#include "StdAfx.h" #include "MA_Voxel_Coding.h" #include "MA_vc_Flags.h" // ---------------------------------------------------------------------------------------- // convertPathTo26Linked // // Description: Converts a face connected path to a 26-connected path (reducing size). // // Starting State: -> MARK_cubes[SMOOTHING] needs to be clear // -> SS_cube needs to be in initial state // ---------------------------------------------------------------------------------------- void MA_VoxelCoding::convertPathTo26Linked( LinkedList<PathNode> *path_ptr ) { char dx, dy, dz, xl, xg, yl, yg, zl, zg; ss_t smallest_ss; LinkedListNode<PathNode> *cur_node_ptr = path_ptr->getHeadPtr(); LinkedListNode<PathNode> *new_node_ptr; LinkedListNode<Vect3usi> *cur_coord_ptr; Vect3usi end_coord = path_ptr->getTailPtr()->item.coordinate; Vect3usi cur_coord = path_ptr->getHeadPtr()->item.coordinate; Vect3usi tmp_coord, nxt_coord; // If start coord is same as end, this is a loop path, get rid of it if ( end_coord == cur_coord ) { write_to_log("MA_VoxelCoding::convertPathTo26Linked - Warning, path %d (volume %d) loops onto self at %v, path is removed.", current_medial_path_num, current_volume_num, end_coord); path_ptr->removeAllNodes(); return; } // Mark current path in MARK_cubes[SMOOTHING] coordinate_queue->insertAtStart( queue_mark_coord ); while ( cur_node_ptr ) { // Backup any medial paths encountered if ( SS_cube->datac(cur_node_ptr->item.coordinate) == ss_medial_path ) { SS_cube->datac( cur_node_ptr->item.coordinate, SS_Xfrm_Smooth->getInfinityValue() ); coordinate_queue->insertAtStart( cur_node_ptr->item.coordinate ); } MARK_cubes[SMOOTHING]->set_spot_1( cur_node_ptr->item.coordinate ); cur_node_ptr = cur_node_ptr->next; } // Generate SS field SS_cube->datac( cur_coord, SS_Xfrm_Smooth->getEndValueForSS() ); if ( SS_Xfrm_Smooth->runSS( SS_cube, end_coord, DT_FACE_ONLY | DT_STOP_AT_HIT ) != DT_STOPPED_AT_HIT ) { write_to_log("MA_VoxelCoding::convertPathTo26Linked - FATAL ERROR - could not convert path %d (volume %d), %v to %v to 26-connected, failed at %v.", current_medial_path_num, current_volume_num, &path_ptr->getHeadPtr()->item.coordinate, &path_ptr->getTailPtr()->item.coordinate, &end_coord); doFullDump( MA_CRASH_ON_FATAL_ERROR ); } end_coord = path_ptr->getTailPtr()->item.coordinate; // Delete current list except for head cur_node_ptr = path_ptr->getHeadPtr(); path_ptr->removeAllNodesAfter( cur_node_ptr ); // Do 26-connected shortest path until end coordinate is reached while ( cur_coord != end_coord ) { // Set boundary limits xl=-1; xg=1; yl=-1; yg=1; zl=-1; zg=1; if (cur_coord.x < 1) xl = 0; if (cur_coord.y < 1) yl = 0; if (cur_coord.z < 1) zl = 0; if (cur_coord.x > boundary_cube->wX-2) xg = 0; if (cur_coord.y > boundary_cube->wY-2) yg = 0; if (cur_coord.z > boundary_cube->wZ-2) zg = 0; // Find neighbor closest to end point (smallest SS value) smallest_ss = SS_Xfrm_Smooth->getInfinityValue(); for (dz = zl; dz <= zg; dz++) { for (dy = yl; dy <= yg; dy++) for (dx = xl; dx <= xg; dx++) { tmp_coord = cur_coord; tmp_coord.add_char( dz, dy, dx ); if ( (!boundary_cube->get_spot(tmp_coord)) && (SS_cube->datac(tmp_coord) < smallest_ss) && (SS_cube->datac(tmp_coord) > 0) ) { // This is nearest spot nxt_coord = tmp_coord; smallest_ss = SS_cube->datac(tmp_coord); } } } // Next coordinate should not be same as current one if ( nxt_coord == cur_coord ) { write_to_log( "MA_VoxelCoding::convertPathTo26Linked - FATAL ERROR - path %d (of volume %d), stuck at %v.", current_medial_path_num, current_volume_num, &cur_coord ); doFullDump( MA_CRASH_ON_FATAL_ERROR ); } // Add new node new_node_ptr = path_ptr->getNewNode(); new_node_ptr->item.coordinate = nxt_coord; path_ptr->insertAtEnd( new_node_ptr ); // Go on to the new spot cur_coord = nxt_coord; cur_node_ptr = cur_node_ptr->next; } // Reset SS cube (uses MARK cube), then clear MARK cube, and restore any MAs SS_Xfrm_Smooth->eraseSS( SS_cube, end_coord, ss_medial_path-1, DT_FACE_ONLY ); recurseOnAllNeighbors( end_coord, &MA_VoxelCoding::clearSmoothCube ); cur_coord_ptr = coordinate_queue->getHeadPtr(); while ( cur_coord_ptr ) { if ( cur_coord_ptr->item == queue_mark_coord ) { coordinate_queue->removeHeadNode( ); break; } SS_cube->datac( cur_coord_ptr->item, ss_medial_path ); coordinate_queue->removeHeadNode( ); cur_coord_ptr = coordinate_queue->getHeadPtr(); } // This path should no longer change size, release any preallocated memory path_ptr->purgeFreeList(); } // ---------------------------------------------------------------------------------------- // // Description - // ---------------------------------------------------------------------------------------- bool MA_VoxelCoding::clearSmoothCube( Vect3usi &, Vect3usi &nxt_coord ) { // If spot is a PORE and is not yet initialized, see if it is bigger than current max if ( MARK_cubes[SMOOTHING]->get_spot(nxt_coord) ) { MARK_cubes[SMOOTHING]->set_spot_0(nxt_coord); return true; } else { // Return false, indicating invalid spot return false; } }