#include "StdAfx.h" #include "MA_Voxel_Coding.h" // ---------------------------------------------------------------------------------------- // findMidPtOfIntersection // // Description: There might be a plane of same value BS max points in a single cluster, // this will attempt to center the max point within the plane. // ---------------------------------------------------------------------------------------- void MA_VoxelCoding::findMidPtOfIntersection( Vect3usi &start_coord ) { int dlr, dsn, ddu; // First, find distances in all 6 directions, and find offsets to middle of field. dlr = (findDepthOfCone(RIGHT, start_coord) - findDepthOfCone(LEFT, start_coord)) / 2; dsn = (findDepthOfCone(NORTH, start_coord) - findDepthOfCone(SOUTH, start_coord)) / 2; ddu = (findDepthOfCone(UP, start_coord) - findDepthOfCone(DOWN, start_coord)) / 2; // Make sure none of the offsets results in out of bound conditions if ( ((int)start_coord.x + dlr) >= (int)SS_cube->wX ) { dlr = dlr - (start_coord.x + dlr - SS_cube->wX + 1); } else if ( ((int)start_coord.x + dlr) < 0 ) { dlr = dlr - (start_coord.x + dlr); } if ( ((int)start_coord.y + dsn) >= (int)SS_cube->wY ) { dsn = dsn - (start_coord.y + dsn - SS_cube->wY + 1); } else if ( ((int)start_coord.y + dsn) < 0 ) { dsn = dsn - (start_coord.y + dsn); } if ( ((int)start_coord.z + ddu) >= (int)SS_cube->wZ ) { ddu = ddu - (start_coord.z + ddu - SS_cube->wZ + 1); } else if ( ((int)start_coord.z + ddu) < 0 ) { ddu = ddu - (start_coord.z + ddu); } // Now travel the calculated offset to get middle of intersection. travelDesiredOffsetInIntersection( dlr, dsn, ddu, start_coord, start_coord ); } // ---------------------------------------------------------------------------------------- // travelDesiredOffsetInIntersection // // Description: // ---------------------------------------------------------------------------------------- void MA_VoxelCoding::travelDesiredOffsetInIntersection(int lr_off, int sn_off, int du_off, Vect3usi &cur_coord, Vect3usi &ret_end_coord) { // 8 Cases: // left - south, north, down, up // right - south, north, down, up // If offsets are 0, we have found final spot. if ( (lr_off==0) && (sn_off==0) && (du_off==0) ) { ret_end_coord = cur_coord; return; } char offset; Vect3usi nxt_coord; // If we have a remaining left/right offset. if (lr_off != 0) { offset = (lr_off < 0) ? (-1) : (1); // left-south nxt_coord.from_zyx( cur_coord.z, cur_coord.y-1, cur_coord.x+offset ); if ( (sn_off < 0) && (SS_cube->datac(nxt_coord) == SS_cube->datac(cur_coord)) && (BS_cube->datac(nxt_coord) == BS_cube->datac(cur_coord)) ) { travelDesiredOffsetInIntersection(lr_off-offset, sn_off+1, du_off, nxt_coord, ret_end_coord); return; } // left-north nxt_coord.y = cur_coord.y+1; if ( (sn_off > 0) && (SS_cube->datac(nxt_coord) == SS_cube->datac(cur_coord)) && (BS_cube->datac(nxt_coord) == BS_cube->datac(cur_coord)) ) { travelDesiredOffsetInIntersection(lr_off-offset, sn_off-1, du_off, nxt_coord, ret_end_coord); return; } // left-down nxt_coord.y = cur_coord.y; nxt_coord.z = cur_coord.z-1; if ( (du_off < 0) && (SS_cube->datac(nxt_coord) == SS_cube->datac(cur_coord)) && (BS_cube->datac(nxt_coord) == BS_cube->datac(cur_coord)) ) { travelDesiredOffsetInIntersection(lr_off-offset, sn_off, du_off+1, nxt_coord, ret_end_coord); return; } // left-up nxt_coord.z = cur_coord.z+1; if ( (du_off > 0) && (SS_cube->datac(nxt_coord) == SS_cube->datac(cur_coord)) && (BS_cube->datac(nxt_coord) == BS_cube->datac(cur_coord)) ) { travelDesiredOffsetInIntersection(lr_off-offset, sn_off, du_off-1, nxt_coord, ret_end_coord); return; } // Tie break (both sn and du are 0, or no valid paths), just find first valid spot. // left-south nxt_coord.from_zyx( cur_coord.z, cur_coord.y-1, cur_coord.x+offset ); if ( (cur_coord.y > 0) && (SS_cube->datac(nxt_coord) == SS_cube->datac(cur_coord)) && (BS_cube->datac(nxt_coord) == BS_cube->datac(cur_coord)) ) { travelDesiredOffsetInIntersection(lr_off-offset, sn_off, du_off, nxt_coord, ret_end_coord); return; } // left-north nxt_coord.y = cur_coord.y+1; if ( (cur_coord.y < (SS_cube->wY-1)) && (SS_cube->datac(nxt_coord) == SS_cube->datac(cur_coord)) && (BS_cube->datac(nxt_coord) == BS_cube->datac(cur_coord)) ) { travelDesiredOffsetInIntersection(lr_off-offset, sn_off, du_off, nxt_coord, ret_end_coord); return; } // left-down nxt_coord.y = cur_coord.y; nxt_coord.z = cur_coord.z-1; if ( (cur_coord.z > 0) && (SS_cube->datac(nxt_coord) == SS_cube->datac(cur_coord)) && (BS_cube->datac(nxt_coord) == BS_cube->datac(cur_coord)) ) { travelDesiredOffsetInIntersection(lr_off-offset, sn_off, du_off, nxt_coord, ret_end_coord); return; } // left-up nxt_coord.z = cur_coord.z+1; if ( (cur_coord.z < (SS_cube->wZ-1)) && (SS_cube->datac(nxt_coord) == SS_cube->datac(cur_coord)) && (BS_cube->datac(nxt_coord) == BS_cube->datac(cur_coord)) ) { travelDesiredOffsetInIntersection(lr_off-offset, sn_off, du_off, nxt_coord, ret_end_coord); return; } // If we get this far, we are stuck, but at least update with as far as we got ret_end_coord = cur_coord; return; } // Next try north south offsets if ( sn_off != 0 ) { offset = (sn_off < 0) ? (-1) : (1); // south-down nxt_coord.from_zyx( cur_coord.z-1, cur_coord.y+offset, cur_coord.x ); if ( (du_off < 0) && (SS_cube->datac(nxt_coord) == SS_cube->datac(cur_coord)) && (BS_cube->datac(nxt_coord) == BS_cube->datac(cur_coord)) ) { travelDesiredOffsetInIntersection(lr_off, sn_off-offset, du_off+1, nxt_coord, ret_end_coord); return; } // south-up nxt_coord.z = cur_coord.z+1; if ( (du_off > 0) && (SS_cube->datac(nxt_coord) == SS_cube->datac(cur_coord)) && (BS_cube->datac(nxt_coord) == BS_cube->datac(cur_coord)) ) { travelDesiredOffsetInIntersection(lr_off, sn_off-offset, du_off-1, nxt_coord, ret_end_coord); return; } // Tie breaker (du_off is 0) // south-down nxt_coord.z = cur_coord.z-1; if ( (cur_coord.z > 0) && (SS_cube->datac(nxt_coord) == SS_cube->datac(cur_coord)) && (BS_cube->datac(nxt_coord) == BS_cube->datac(cur_coord)) ) { travelDesiredOffsetInIntersection(lr_off, sn_off-offset, du_off, nxt_coord, ret_end_coord); return; } // south-up nxt_coord.z = cur_coord.z+1; if ( (cur_coord.z < (SS_cube->wZ-1)) && (SS_cube->datac(nxt_coord) == SS_cube->datac(cur_coord)) && (BS_cube->datac(nxt_coord) == BS_cube->datac(cur_coord)) ) { travelDesiredOffsetInIntersection(lr_off, sn_off-offset, du_off, nxt_coord, ret_end_coord); return; } // If we get this far, we are stuck, but at least update with as far as we got ret_end_coord = cur_coord; return; } // Finally, only up down left (4 way tie breaker) if ( (du_off < 0) && (cur_coord.z > 0) ) { offset = -1; } else if ( (du_off > 0) && (cur_coord.z < (SS_cube->wZ-1)) ) { offset = 1; } else { // If we get this far, we are stuck, but at least update with as far as we got ret_end_coord = cur_coord; return; } // down-left nxt_coord.from_zyx( cur_coord.z+offset, cur_coord.y, cur_coord.x ); nxt_coord.x = ( cur_coord.x > 0 ) ? (cur_coord.x-1) : (cur_coord.x); if ( (SS_cube->datac(nxt_coord) == SS_cube->datac(cur_coord)) && (BS_cube->datac(nxt_coord) == BS_cube->datac(cur_coord)) ) { travelDesiredOffsetInIntersection(lr_off, sn_off, du_off-offset, nxt_coord, ret_end_coord); return; } // down-right nxt_coord.x = ( cur_coord.x < (SS_cube->wX-1) ) ? (cur_coord.x+1) : (cur_coord.x); if ( (SS_cube->datac(nxt_coord) == SS_cube->datac(cur_coord)) && (BS_cube->datac(nxt_coord) == BS_cube->datac(cur_coord)) ) { travelDesiredOffsetInIntersection(lr_off, sn_off, du_off-offset, nxt_coord, ret_end_coord); return; } // down-south nxt_coord.x = cur_coord.x; nxt_coord.y = ( cur_coord.y > 0 ) ? (cur_coord.y-1) : (cur_coord.y); if ( (SS_cube->datac(nxt_coord) == SS_cube->datac(cur_coord)) && (BS_cube->datac(nxt_coord) == BS_cube->datac(cur_coord)) ) { travelDesiredOffsetInIntersection(lr_off, sn_off, du_off-offset, nxt_coord, ret_end_coord); return; } // down-north nxt_coord.y = ( nxt_coord.y < (SS_cube->wY-1) ) ? (cur_coord.y+1) : (cur_coord.y); if ( (SS_cube->datac(nxt_coord) == SS_cube->datac(cur_coord)) && (BS_cube->datac(nxt_coord) == BS_cube->datac(cur_coord)) ) { travelDesiredOffsetInIntersection(lr_off, sn_off, du_off-offset, nxt_coord, ret_end_coord); return; } // If we get this far, we are stuck, but at least update with as far as we got ret_end_coord = cur_coord; } // ---------------------------------------------------------------------------------------- // recurseInConeIfValid // // Description: // ---------------------------------------------------------------------------------------- int MA_VoxelCoding::recurseInConeIfValid( ma_direction direction, Vect3usi &cur_coord, Vect3usi &nxt_coord ) { if ( (SS_cube->datac(cur_coord) == SS_cube->datac(nxt_coord)) && (BS_cube->datac(cur_coord) == BS_cube->datac(nxt_coord)) ) { return ( 1 + findDepthOfCone(direction, nxt_coord) ); } else { return -1; } } // ---------------------------------------------------------------------------------------- // findDepthOfCone // // Description: // ---------------------------------------------------------------------------------------- int MA_VoxelCoding::findDepthOfCone( ma_direction direction, Vect3usi &cur_coord ) { Vect3usi nxt_coord; bool recurse = false; int largest = 1, new_value; // Current direction switch( direction ) { case LEFT: case RIGHT: if ( (direction == LEFT) && (cur_coord.x > 0) ) { nxt_coord.from_zyx( cur_coord.z, cur_coord.y-1, cur_coord.x-1); recurse = true; } else if ( (direction == RIGHT) && (cur_coord.x < (SS_cube->wX-1)) ) { nxt_coord.from_zyx( cur_coord.z, cur_coord.y-1, cur_coord.x+1); recurse = true; } if ( recurse == true ) { if ( cur_coord.y > 0 ) { new_value = recurseInConeIfValid( direction, cur_coord, nxt_coord ); if ( largest < new_value ) largest = new_value; } nxt_coord.y = cur_coord.y + 1; if ( cur_coord.y < (SS_cube->wY-1) ) { new_value = recurseInConeIfValid( direction, cur_coord, nxt_coord ); if ( largest < new_value ) largest = new_value; } nxt_coord.z = cur_coord.z - 1; nxt_coord.y = cur_coord.y; if ( cur_coord.z > 0 ) { new_value = recurseInConeIfValid( direction, cur_coord, nxt_coord ); if ( largest < new_value ) largest = new_value; } nxt_coord.z = cur_coord.z + 1; if ( cur_coord.z < (SS_cube->wZ-1) ) { new_value = recurseInConeIfValid( direction, cur_coord, nxt_coord ); if ( largest < new_value ) largest = new_value; } } return largest; case SOUTH: case NORTH: if ( (direction == SOUTH) && (cur_coord.y > 0) ) { nxt_coord.from_zyx( cur_coord.z, cur_coord.y-1, cur_coord.x-1); recurse = true; } else if ( (direction == NORTH) && (cur_coord.y < (SS_cube->wY-1)) ) { nxt_coord.from_zyx( cur_coord.z, cur_coord.y+1, cur_coord.x-1); recurse = true; } if ( recurse == true ) { if ( cur_coord.x > 0 ) { new_value = recurseInConeIfValid( direction, cur_coord, nxt_coord ); if ( largest < new_value ) largest = new_value; } nxt_coord.x = cur_coord.x + 1; if ( cur_coord.x < (SS_cube->wX-1) ) { new_value = recurseInConeIfValid( direction, cur_coord, nxt_coord ); if ( largest < new_value ) largest = new_value; } nxt_coord.z = cur_coord.z - 1; nxt_coord.x = cur_coord.x; if ( cur_coord.z > 0 ) { new_value = recurseInConeIfValid( direction, cur_coord, nxt_coord ); if ( largest < new_value ) largest = new_value; } nxt_coord.z = cur_coord.z + 1; if ( cur_coord.z < (SS_cube->wZ-1) ) { new_value = recurseInConeIfValid( direction, cur_coord, nxt_coord ); if ( largest < new_value ) largest = new_value; } } return largest; case DOWN: case UP: if ( (direction == DOWN) && (cur_coord.z > 0) ) { nxt_coord.from_zyx( cur_coord.z-1, cur_coord.y, cur_coord.x-1); recurse = true; } else if ( (direction == UP) && (cur_coord.z < (SS_cube->wZ-1)) ) { nxt_coord.from_zyx( cur_coord.z+1, cur_coord.y, cur_coord.x-1); recurse = true; } if ( recurse == true ) { if ( cur_coord.x > 0 ) { new_value = recurseInConeIfValid( direction, cur_coord, nxt_coord ); if ( largest < new_value ) largest = new_value; } nxt_coord.x = cur_coord.x + 1; if ( cur_coord.x < (SS_cube->wX-1) ) { new_value = recurseInConeIfValid( direction, cur_coord, nxt_coord ); if ( largest < new_value ) largest = new_value; } nxt_coord.y = cur_coord.y - 1; nxt_coord.x = cur_coord.x; if ( cur_coord.y > 0 ) { new_value = recurseInConeIfValid( direction, cur_coord, nxt_coord ); if ( largest < new_value ) largest = new_value; } nxt_coord.y = cur_coord.y + 1; if ( cur_coord.y < (SS_cube->wY-1) ) { new_value = recurseInConeIfValid( direction, cur_coord, nxt_coord ); if ( largest < new_value ) largest = new_value; } } return largest; default: write_to_log("MA_VoxelCoding::findDepthOfCone - FATAL ERROR - Received invalid direction."); exit( 1 ); } }