cgma
|
00001 //- Class: MergeTool 00002 //- Description: Location of all Merge and Unmerge functionality 00003 //- Owner: Steven Jankovich 00004 //- Created: 27 April 1998 00005 //- Checked by: 00006 00007 #include <assert.h> 00008 00009 #include "GeometryEntity.hpp" 00010 #include "MergeTool.hpp" 00011 #include "MergeToolAssistant.hpp" 00012 #include "RefEntityFactory.hpp" 00013 #include "GeometryQueryTool.hpp" 00014 #include "GeometryQueryEngine.hpp" 00015 #include "ModelQueryEngine.hpp" 00016 #include "GeometryModifyTool.hpp" 00017 #include "SurfaceOverlapTool.hpp" 00018 #include "GeometryModifyEngine.hpp" 00019 #include "CGMHistory.hpp" 00020 00021 #include "CubitObserver.hpp" 00022 #include "CubitUtil.hpp" 00023 #include "RefEntity.hpp" 00024 #include "BasicTopologyEntity.hpp" 00025 #include "GroupingEntity.hpp" 00026 #include "SenseEntity.hpp" 00027 #include "GeometryEvent.hpp" 00028 00029 #include "RefVertex.hpp" 00030 #include "RefEdge.hpp" 00031 #include "RefFace.hpp" 00032 #include "RefVolume.hpp" 00033 #include "RefGroup.hpp" 00034 00035 #include "CoVertex.hpp" 00036 #include "CoEdge.hpp" 00037 #include "CoFace.hpp" 00038 00039 #include "Chain.hpp" 00040 #include "Loop.hpp" 00041 #include "Shell.hpp" 00042 #include "Body.hpp" 00043 #include "BodySM.hpp" 00044 00045 #include "ToolData.hpp" 00046 #include "TDCompare.hpp" 00047 00048 #include "DLIList.hpp" 00049 00050 #include "Surface.hpp" 00051 #include "Curve.hpp" 00052 #include "Point.hpp" 00053 #include "LoopSM.hpp" 00054 #include "CoEdgeSM.hpp" 00055 #include "ShellSM.hpp" 00056 00057 #include "CpuTimer.hpp" 00058 #include "ProgressTool.hpp" 00059 #include "AppUtil.hpp" 00060 #include "CastTo.hpp" 00061 #include "RTree.hpp" 00062 #include "AbstractTree.hpp" 00063 #include "SettingHandler.hpp" 00064 00065 MergeTool* MergeTool::instance_ = NULL; 00066 CubitBoolean MergeTool::groupResults = CUBIT_FALSE; 00067 CubitBoolean MergeTool::destroyDeadGeometry = CUBIT_TRUE; 00068 00069 // Constructor 00070 MergeTool* MergeTool::instance() 00071 { 00072 if( instance_ == NULL ) 00073 instance_ = new MergeTool; 00074 return instance_; 00075 } 00076 00077 void MergeTool::initialize_settings( ) 00078 { 00079 } 00080 00081 MergeTool::MergeTool() 00082 { 00083 //This is private. It can only be accessed through 00084 //the instance() function above. 00085 00086 unmerged_list_in_use = CUBIT_FALSE; 00087 displayProgress = false; 00088 destroyDeadGeometry = true; 00089 //These shouldn't get deleted, they 00090 //get deleted when other groups get deleted (reset). 00091 lastSurfsMerged = NULL; 00092 lastCurvsMerged = NULL; 00093 lastVertsMerged = NULL; 00094 } 00095 00096 // Destructor 00097 MergeTool::~MergeTool() 00098 { 00099 while( assistant_list_.size() ) 00100 delete assistant_list_.pop(); 00101 instance_ = 0; 00102 } 00103 00104 void MergeTool::merge_with_auto_imprint(RefFace *surf1, RefFace *surf2) 00105 { 00106 DLIList<CubitString> ds, cs, ps; 00107 RefFace *local_surf1 = surf1; 00108 RefFace *local_surf2 = surf2; 00109 bool time_to_stop = false; 00110 int cntr = 0; 00111 bool first_time = true; 00112 while(!time_to_stop && local_surf1 && 00113 local_surf2 && !local_surf1->is_merged() && 00114 !local_surf2->is_merged() ) 00115 { 00116 int surf1_id = local_surf1->id(); 00117 int surf2_id = local_surf2->id(); 00118 if(first_time) 00119 { 00120 Body *b1 = local_surf1->body(); 00121 Body *b2 = local_surf2->body(); 00122 if(b1 && b2) 00123 { 00124 DLIList<Body*> body_list, new_bodies; 00125 body_list.append(b1); 00126 body_list.append(b2); 00127 DLIList<RefFace*> faces_to_imprint; 00128 faces_to_imprint.append( local_surf1 ); 00129 faces_to_imprint.append( local_surf2 ); 00130 DLIList<RefEdge*> dummy_list; 00131 CubitStatus imprint_status; 00132 imprint_status = GeometryModifyTool::instance()->tolerant_imprint( faces_to_imprint, dummy_list, new_bodies, true ); 00133 if( CUBIT_FAILURE == imprint_status ) 00134 return; 00135 first_time = false; 00136 } 00137 } 00138 else 00139 { 00140 this->imprint_merge_solutions_for_overlapping_surfaces(local_surf1, 00141 local_surf2, true, ds, cs, ps); 00142 } 00143 RefFace *new_surf1 = RefEntityFactory::instance()->get_ref_face(surf1_id); 00144 RefFace *new_surf2 = RefEntityFactory::instance()->get_ref_face(surf2_id); 00145 if(new_surf1 && new_surf1->is_merged()) 00146 time_to_stop = true; 00147 else if(new_surf2 && new_surf2->is_merged()) 00148 time_to_stop = true; 00149 else 00150 { 00151 if(new_surf1 && new_surf2) 00152 { 00153 DLIList<RefFace*> current_face_list, out1, out2; 00154 DLIList<RefEntity*> faces_to_draw; 00155 current_face_list.append(new_surf1); 00156 current_face_list.append(new_surf2); 00157 SurfaceOverlapTool::instance()->find_overlapping_surfaces(current_face_list, 00158 out1, 00159 out2, 00160 faces_to_draw, 00161 CUBIT_FALSE, 00162 CUBIT_TRUE); 00163 if(out1.size() == 1 && out2.size() == 1 && 00164 ((out1.get() == new_surf1 && out2.get() == new_surf2) || 00165 (out1.get() == new_surf2 && out2.get() == new_surf1))) 00166 { 00167 local_surf1 = new_surf1; 00168 local_surf2 = new_surf2; 00169 } 00170 else 00171 { 00172 time_to_stop = true; 00173 } 00174 } 00175 else 00176 { 00177 time_to_stop = true; 00178 } 00179 } 00180 cntr++; 00181 if(cntr > 5) 00182 time_to_stop = true; 00183 } 00184 } 00185 00186 //Public Functions: 00187 CubitBoolean MergeTool::contains_merged_entities( DLIList<RefEntity*> &ref_entities, 00188 DLIList<RefEntity*> *merged_ref_ents ) 00189 { 00190 //Loop through the entities and their children to find 00191 //merged entities. For now, just do it quickly, so 00192 //if we find a merged entity, return true. 00193 00194 DLIList<RefEntity*> all_entities, temp_entities; 00195 00196 if ( ref_entities.size() == 0 ) 00197 return CUBIT_FALSE; 00198 00199 ref_entities.reset(); 00200 ref_entities.get()->get_all_child_ref_entities(ref_entities, temp_entities); 00201 temp_entities += ref_entities; 00202 00203 all_entities.merge_unique(temp_entities); 00204 00205 for (int i = all_entities.size(); i > 0; i--) { 00206 RefEntity *temp_entity = all_entities.get_and_step(); 00207 if (entity_merged(CAST_TO(temp_entity, TopologyEntity))) 00208 { 00209 if( NULL == merged_ref_ents ) 00210 return CUBIT_TRUE; 00211 else 00212 merged_ref_ents->append( temp_entity ); 00213 } 00214 } 00215 00216 if( merged_ref_ents ) 00217 if( merged_ref_ents->size() ) 00218 return CUBIT_TRUE; 00219 00220 return CUBIT_FALSE; 00221 } 00222 00223 CubitBoolean MergeTool::contains_merged_children( Body *body, 00224 DLIList<RefEntity*> &merged_children) 00225 { 00226 00227 RefEntity *ref_ent = NULL; 00228 DLIList<RefEntity*> ref_ent_list; 00229 body->get_all_child_ref_entities( ref_ent_list ); 00230 int i; 00231 for( i=ref_ent_list.size(); i--;) 00232 { 00233 ref_ent = ref_ent_list.get_and_step(); 00234 if(entity_merged(CAST_TO(ref_ent, TopologyEntity))) 00235 merged_children.append( ref_ent ); 00236 } 00237 00238 if( merged_children.size() ) 00239 return CUBIT_TRUE; 00240 else 00241 return CUBIT_FALSE; 00242 } 00243 00244 00245 CubitBoolean MergeTool::contains_merged_entities( DLIList<Body*> &bodies ) 00246 { 00247 //Loop through the bodies and their entities to find 00248 //merged entities. For now, just do it quickly, so 00249 //if we find a merged entity, return true. 00250 DLIList<RefEntity*> ref_entities; 00251 CAST_LIST_TO_PARENT(bodies, ref_entities); 00252 return contains_merged_entities(ref_entities); 00253 } 00254 00255 CubitBoolean MergeTool::entity_merged( TopologyEntity *entity ) 00256 { 00257 if (entity->bridge_manager()->number_of_bridges() > 1) 00258 return CUBIT_TRUE; 00259 else 00260 return CUBIT_FALSE; 00261 } 00262 00263 CubitStatus MergeTool::merge_all_bodies() 00264 { 00265 int number_volumes = GeometryQueryTool::instance()->num_ref_volumes(); 00266 00267 DLIList<RefEntity*> free_ref_ents; 00268 GeometryQueryTool::instance()->get_free_ref_entities( free_ref_ents ); 00269 00270 if( number_volumes == 1 && free_ref_ents.size() == 0 ) 00271 { 00272 PRINT_WARNING("Need more than 1 volume to merge anything\n"); 00273 return CUBIT_FAILURE; 00274 } 00275 00276 PRINT_INFO( "\n...Merging all features in the model\n" ); 00277 00278 if( merge_all_reffaces() == CUBIT_FAILURE ) 00279 { 00280 return CUBIT_FAILURE; 00281 } 00282 00283 if( merge_all_refedges() == CUBIT_FAILURE ) 00284 { 00285 return CUBIT_FAILURE; 00286 } 00287 00288 if( merge_all_refvertices() == CUBIT_FAILURE ) 00289 { 00290 return CUBIT_FAILURE; 00291 } 00292 00293 return CUBIT_SUCCESS; 00294 } 00295 00296 CubitStatus MergeTool::merge_bodies( DLIList<Body*>& body_list ) 00297 { 00298 DLIList<TopologyEntity*> query_input(body_list.size()), query_output; 00299 CAST_LIST_TO_PARENT(body_list, query_input); 00300 ModelQueryEngine *const mqe = ModelQueryEngine::instance(); 00301 00302 // Get the RefFaces 00303 query_output.clean_out(); 00304 mqe->query_model( query_input, DagType::ref_face_type(), query_output ); 00305 DLIList<RefFace*> refface_list(query_output.size()); 00306 CAST_LIST(query_output, refface_list, RefFace); 00307 00308 // Merge the RefFaces 00309 if( merge_reffaces( refface_list ) == CUBIT_FAILURE ) 00310 { 00311 PRINT_ERROR( "Surface merging failed\n" ); 00312 return CUBIT_FAILURE; 00313 } 00314 00315 // Get the RefEdges 00316 query_output.clean_out(); 00317 mqe->query_model( query_input, DagType::ref_edge_type(), query_output ); 00318 DLIList<RefEdge*> refedge_list(query_output.size()); 00319 CAST_LIST(query_output, refedge_list, RefEdge); 00320 00321 // Merge the RefEdges 00322 if( merge_refedges( refedge_list ) == CUBIT_FAILURE ) 00323 { 00324 PRINT_ERROR( "Curve merging failed\n" ); 00325 return CUBIT_FAILURE; 00326 } 00327 00328 // Get the RefVertices 00329 query_output.clean_out(); 00330 mqe->query_model( query_input, DagType::ref_vertex_type(), query_output ); 00331 DLIList<RefVertex*> refvertex_list(query_output.size()); 00332 CAST_LIST(query_output, refvertex_list, RefVertex); 00333 00334 // Merge the RefVertices 00335 if( merge_refvertices( refvertex_list ) == CUBIT_FAILURE ) 00336 { 00337 PRINT_ERROR( "Vertex merging failed\n" ); 00338 return CUBIT_FAILURE; 00339 } 00340 00341 return CUBIT_SUCCESS; 00342 } 00343 00344 CubitStatus MergeTool::merge_volumes( DLIList<RefVolume*>& vol_list, 00345 CubitBoolean print_info ) 00346 { 00347 int i; 00348 vol_list.reset(); 00349 00350 // Get the RefFaces 00351 DLIList<RefFace*> refface_list; 00352 for( i = vol_list.size(); i > 0; i-- ) 00353 vol_list.get_and_step()->ref_faces( refface_list ); 00354 00355 // Merge the RefFaces 00356 if( merge_reffaces( refface_list, print_info ) == CUBIT_FAILURE ) 00357 { 00358 PRINT_ERROR( "Surface merging failed\n" ); 00359 return CUBIT_FAILURE; 00360 } 00361 00362 // Get the RefEdges 00363 DLIList<RefEdge*> refedge_list; 00364 for( i = vol_list.size(); i > 0; i-- ) 00365 vol_list.get_and_step()->ref_edges( refedge_list ); 00366 00367 // Merge the RefEdges 00368 if( merge_refedges( refedge_list, CUBIT_TRUE, print_info ) == CUBIT_FAILURE ) 00369 { 00370 PRINT_ERROR( "Curve merging failed\n" ); 00371 return CUBIT_FAILURE; 00372 } 00373 00374 // Get the RefVertices 00375 DLIList<RefVertex*> refvertex_list; 00376 for( i = vol_list.size(); i > 0; i-- ) 00377 vol_list.get_and_step()->ref_vertices( refvertex_list ); 00378 00379 // Merge the RefVertices 00380 if( merge_refvertices( refvertex_list, print_info ) == CUBIT_FAILURE ) 00381 { 00382 PRINT_ERROR( "Vertex merging failed\n" ); 00383 return CUBIT_FAILURE; 00384 } 00385 00386 return CUBIT_SUCCESS; 00387 } 00388 00389 CubitStatus MergeTool::merge_all_reffaces() 00390 { 00391 // if( !displayProgress ) 00392 PRINT_INFO( "\n...Merging all Surfaces in the model\n" ); 00393 00394 // Get the list of all the RefFaces in the model 00395 DLIList<RefFace*> refface_list; 00396 GeometryQueryTool::instance()->ref_faces(refface_list); 00397 00398 // Merge the RefFaces in this list 00399 if ( DEBUG_FLAG(139) ) 00400 { 00401 test_r_tree(refface_list); 00402 // test_r_star_tree(refface_list); 00403 test_no_tree(refface_list); 00404 } 00405 if( merge_reffaces( refface_list ) == CUBIT_FAILURE ) 00406 { 00407 PRINT_ERROR( "Surface merging failed\n" ); 00408 return CUBIT_FAILURE; 00409 } 00410 00411 return CUBIT_SUCCESS; 00412 } 00413 00414 CubitStatus MergeTool::merge_reffaces_old( DLIList<RefFace*>& refface_list, 00415 CubitBoolean print_info) 00416 { 00417 // The basic algorithm is to step through the input list, 00418 // compare every entity with every other entity, and 00419 // merge the entities that are spatially equivalent. 00420 // In the merge, the entity with the lowest ID is retained. 00421 // This is complicated by the fact that once an entity has 00422 // been merged out, we can no longer access that pointer 00423 // since it is invalid. So...we need to remove it from the 00424 // list, but still keep track of where we are in the list. 00425 // If the entity that is deleted is before the retained item 00426 // in the list, then we do not want to step or we will.... 00427 00428 CpuTimer timer; 00429 int merge_count = 0; 00430 00431 DLIList<RefFace*> refface_array( refface_list.size() ); 00432 refface_list.reset(); 00433 00434 // Remove entities that should not be automatically merged 00435 int i = 0; 00436 for( i = refface_list.size(); i > 0; i-- ) 00437 { 00438 RefFace *curr_face = refface_list.get_and_step(); 00439 if( curr_face->is_mergeable() ) 00440 refface_array.append( curr_face ); 00441 } 00442 00443 ProgressTool* progress = 0; 00444 if( displayProgress ) 00445 { 00446 char info[64]; 00447 sprintf(info, "Comparing %d Surfaces for Merge", refface_array.size() ); 00448 progress = AppUtil::instance()->progress_tool(); 00449 if (progress) 00450 { 00451 progress->start( 0, refface_array.size(), "Comparing Surfaces:", 00452 info, CUBIT_TRUE, CUBIT_TRUE ); 00453 } 00454 } 00455 00456 // Now find overlapping RefFaces and merge them. 00457 // Make sure that the operation is not performed on 00458 // RefFaces that are deactivated. 00459 int j = 0; 00460 RefFace* refface_ptr = NULL; 00461 RefFace* compare_refface_ptr = NULL; 00462 int array_size = refface_array.size(); 00463 DLIList<RefFace*> faces_merged; 00464 00465 for( i = 0; (i < array_size) && !AppUtil::instance()->interrupt(); i++ ) 00466 { 00467 if( progress ) 00468 progress->step(); 00469 00470 refface_ptr = refface_array[i]; 00471 if( refface_ptr == NULL ) 00472 continue; 00473 00474 // There is no need to compare if the first RefFace is 00475 // deactivated. 00476 if( refface_ptr->deactivated() == CUBIT_TRUE ) 00477 continue ; 00478 00479 j = i+1; 00480 for( j = i+1; (j < array_size) && !AppUtil::instance()->interrupt(); j++ ) 00481 { 00482 compare_refface_ptr = refface_array[j]; 00483 if( compare_refface_ptr == NULL ) 00484 continue; 00485 00486 // Make sure we are not comparing the same entity 00487 // and that they are not deactivated. 00488 if( ( refface_ptr == compare_refface_ptr ) || 00489 ( compare_refface_ptr->deactivated() == CUBIT_TRUE ) ) 00490 continue; 00491 00492 // IMPORTANT: this compare is for merging, so we set the 00493 // last parameter to CUBIT_TRUE so that the 00494 // compare sets the TDCompare data which will 00495 // be used in the RefEntity compare and merge. 00496 // By Jihong 00497 00498 double geom_factor = GeometryQueryTool::get_geometry_factor(); 00499 CubitBoolean status = 00500 refface_ptr->about_spatially_equal( compare_refface_ptr, 00501 geom_factor, 00502 CUBIT_TRUE, 00503 GeometryQueryTool::instance()->get_merge_test_bbox(), 00504 GeometryQueryTool::instance()->get_merge_test_internal() ); 00505 if( status == CUBIT_FALSE ) 00506 continue; 00507 00508 //don't merge 2 surfaces of solid volumes if they have 00509 //opposite sense..indicative that they overlap 00510 #if 0 00511 if( refface_ptr->compare_alignment(compare_refface_ptr) == CUBIT_FORWARD ) 00512 { 00513 //if they are both on solid volumes...bail 00514 if( refface_ptr->body()->is_sheet_body() == CUBIT_FALSE && 00515 compare_refface_ptr->body()->is_sheet_body() == CUBIT_FALSE ) 00516 continue; 00517 } 00518 #endif 00519 // If we are in this block, we want to merge the 00520 // two entities. If they do not merge, there was 00521 // an error somewhere. 00522 00523 //First test to see if all the children of these 00524 // reffaces are mergeable 00525 if( !compare_refface_ptr->children_mergeable() ) 00526 { 00527 PRINT_WARNING( "Cannot merge surfaces %d and %d\n" 00528 " Make sure all merge flags are on.\n", 00529 refface_ptr->id(), compare_refface_ptr->id() ); 00530 continue; 00531 } 00532 00533 //Now let us test to see if we are merging two faces that 00534 //belong to the same volume. 00535 DLIList<RefVolume*> ref_vols_1, ref_vols_2; 00536 refface_ptr->ref_volumes( ref_vols_1 ); 00537 compare_refface_ptr->ref_volumes( ref_vols_2 ); 00538 ref_vols_2.intersect( ref_vols_1 ); 00539 if( ref_vols_2.size() > 0 ) 00540 { 00541 PRINT_DEBUG_19( "Tolerance problems, trying to merge " 00542 "surfaces\non the same volume.\n" 00543 " %s (surface %d) and %s (surface %d) on\n" 00544 " %s (volume %d)\n", 00545 refface_ptr->entity_name().c_str(), 00546 refface_ptr->id(), 00547 compare_refface_ptr->entity_name().c_str(), 00548 compare_refface_ptr->id(), 00549 ref_vols_2.get()->entity_name().c_str(), 00550 ref_vols_2.get()->id() ); 00551 if (print_info) { PRINT_DEBUG_19( "Try changing the merge tolerance.\n" ); } 00552 continue; 00553 } 00554 00555 /* 00556 //don't merge 2 surfaces of solid volumes if they have 00557 //opposite sense..indicative that they overlap 00558 if( refface_ptr->compare_alignment(compare_refface_ptr) == CUBIT_FORWARD ) 00559 { 00560 continue; 00561 } */ 00562 00563 // Always retain the entity with the lowest id. 00564 int nullify = j; 00565 if( refface_ptr->id() > compare_refface_ptr->id() ) 00566 { 00567 std::swap(refface_ptr, compare_refface_ptr); 00568 nullify = i; 00569 } 00570 if (groupResults ) 00571 { 00572 faces_merged.append(refface_ptr); 00573 } 00574 00575 // Now check if merge is okay with all assistants. 00576 CubitBoolean assistant_says_no = CUBIT_FALSE; 00577 for( int k = assistant_list_.size(); k > 0; k-- ) 00578 { 00579 if( ! assistant_list_.get_and_step() 00580 ->can_merge( refface_ptr, compare_refface_ptr ) ) 00581 { 00582 assistant_says_no = CUBIT_TRUE; 00583 break; 00584 } 00585 } 00586 if( assistant_says_no ) 00587 continue; 00588 00589 // Need to retain these so that the pointers are not 00590 // accessed after a merge operation when the 'deleted' 00591 // pointer may be invalid. 00592 int retained_id = refface_ptr->id(); 00593 int deleted_id = compare_refface_ptr->id(); 00594 00595 PRINT_DEBUG_19( "Consolidating RefFace %d and " 00596 "%d...\n", retained_id, deleted_id ); 00597 if( merge_BTE( refface_ptr, compare_refface_ptr ) ) 00598 { 00599 merge_count++; 00600 if (print_info && !progress) 00601 PRINT_INFO( "Surface %d and %d consolidated\n", 00602 retained_id, deleted_id ); 00603 00604 // The 'deleted' RefFace is now gone. It is an 00605 // error to access that pointer, so we need to 00606 // get it out of the list. 00607 refface_array[nullify] = NULL; 00608 } 00609 else 00610 { 00611 PRINT_ERROR( "Failed to merge Surface %d and %d\n", 00612 retained_id, deleted_id); 00613 PRINT_INFO("Could be sliver geometry in the vecinity\n"); 00614 } 00615 00616 if (nullify == i) 00617 break; 00618 } 00619 } 00620 00621 // Remove the crud that accumulated during the merge 00622 // operations, from the geometry database. 00623 00624 complete_merge(); 00625 if (progress) 00626 progress->end(); 00627 PRINT_DEBUG_3( "Merge Reffaces time: %f secs\n", 00628 timer.cpu_secs() ); 00629 00630 PRINT_DEBUG_19("Cleaning out TDCompare data from RefFaces...\n"); 00631 00632 if ( groupResults && faces_merged.size() ) 00633 { 00634 DLIList<RefEntity*> refentity_list; 00635 RefFace *tmp_face; 00636 for (int iii = faces_merged.size(); iii > 0; iii-- ) 00637 { 00638 tmp_face = faces_merged.get_and_step(); 00639 if ( !tmp_face->deactivated() ) 00640 refentity_list.append(tmp_face); 00641 } 00642 RefGroup *new_group = RefEntityFactory::instance()->construct_RefGroup("gr_surfs_merged"); 00643 new_group->add_ref_entity( refentity_list ); 00644 if (print_info) PRINT_INFO("Created new group %s (Group %d)\n" 00645 " Group contains surfaces that were merged during\n" 00646 " current merge operation\n", 00647 new_group->entity_name().c_str(), 00648 new_group->id()); 00649 lastSurfsMerged = new_group; 00650 } 00651 //since surface mergeing has occured and we either don't want the 00652 //group or didn't store it, set the lastsurfs to null. 00653 else 00654 lastSurfsMerged = NULL; 00655 00656 if( destroyDeadGeometry ) 00657 GeometryQueryTool::instance()->cleanout_deactivated_geometry(); 00658 00659 PRINT_DEBUG_3( "cleanout time: %f secs\n", timer.cpu_secs() ); 00660 if (print_info) 00661 { 00662 PRINT_INFO( "Consolidated %d pair", merge_count); 00663 if(merge_count > 1) 00664 PRINT_INFO("s"); 00665 PRINT_INFO( " of surfaces\n"); 00666 } 00667 00668 if( AppUtil::instance()->interrupt() ) 00669 { 00670 PRINT_WARNING("Surface merging aborted.\n"); 00671 return CUBIT_FAILURE; 00672 } 00673 00674 return CUBIT_SUCCESS; 00675 } 00676 00677 CubitStatus MergeTool::merge_reffaces( DLIList<RefFace*>& refface_list, 00678 CubitBoolean print_info) 00679 { 00680 if (refface_list.size() < 20) 00681 { 00682 if ( merge_reffaces_old(refface_list, print_info) == CUBIT_FAILURE ) 00683 return CUBIT_FAILURE; 00684 else 00685 return CUBIT_SUCCESS; 00686 } 00687 00688 // The basic algorithm is to step through the input list, 00689 // compare every entity with every entity within range of 00690 // its bounding box and merge the spatially equivellant entities. 00691 // An R-Tree is used to efficiently find the entities within range. 00692 // In the merge, the entity with the lowest ID is retained. 00693 // This is complicated by the fact that once an entity has 00694 // been merged out, we can no longer access that pointer 00695 // since it is invalid. So...we need to remove it from the 00696 // tree, but still keep track of where we are in the list. 00697 double geom_factor = GeometryQueryTool::get_geometry_factor(); 00698 RTree<RefFace*> a_tree(GEOMETRY_RESABS*geom_factor); 00699 // AbstractTree <RefFace*> *a_tree = new RTree<RefFace*> (GEOMETRY_RESABS*geom_factor); 00700 CpuTimer timer; 00701 int merge_count = 0; 00702 00703 DLIList<RefFace*> refface_array( refface_list.size() ); 00704 refface_list.reset(); 00705 00706 // Remove entities that should not be automatically merged 00707 int i = 0; 00708 int loop_size = refface_list.size(); 00709 CpuTimer time_to_build; 00710 for( i = 0; i < loop_size; i++ ) 00711 { 00712 RefFace *curr_face = refface_list.get_and_step(); 00713 if( curr_face->is_mergeable() ) 00714 { 00715 refface_array.append( curr_face ); 00716 a_tree.add(curr_face); 00717 } 00718 } 00719 PRINT_DEBUG_3( "Time to build r_tree %f secs, with %d entries\n", 00720 time_to_build.cpu_secs(), refface_array.size() ); 00721 00722 //initialize the marked flag for fast nulification... 00723 int array_size = refface_array.size(); 00724 for ( i = 0; i < array_size; i++) 00725 refface_array[i]->marked(i); 00726 00727 ProgressTool* progress = 0; 00728 if( displayProgress ) 00729 { 00730 char info[64]; 00731 sprintf(info, "Comparing %d Surfaces for Merge", refface_array.size() ); 00732 progress = AppUtil::instance()->progress_tool(); 00733 if (progress) 00734 { 00735 progress->start( 0, refface_array.size(), "Comparing Surfaces:", 00736 info, CUBIT_TRUE, CUBIT_TRUE ); 00737 } 00738 } 00739 00740 // Now find overlapping RefFaces and merge them. 00741 // Make sure that the operation is not performed on 00742 // RefFaces that are deactivated. 00743 int j = 0; 00744 RefFace* refface_ptr = NULL; 00745 RefFace* compare_refface_ptr = NULL; 00746 DLIList<RefFace*> faces_merged, faces_in_range; 00747 CubitBox temp_box; 00748 std::map<RefFace*, RefFace*> failed_merges; 00749 std::map<RefFace*, RefFace*>::iterator map_iter; 00750 00751 for( i = 0; (i < array_size) && !AppUtil::instance()->interrupt(); i++ ) 00752 { 00753 if( progress ) progress->step(); 00754 00755 refface_ptr = refface_array[i]; 00756 if( refface_ptr == NULL ) 00757 continue; 00758 00759 // There is no need to compare if the first RefFace is 00760 // deactivated. 00761 if( refface_ptr->deactivated() == CUBIT_TRUE ) 00762 continue ; 00763 00764 //Now from the atree, get the surfaces that are close. 00765 temp_box = refface_ptr->bounding_box(); 00766 faces_in_range.clean_out(); 00767 a_tree.find(temp_box, faces_in_range); 00768 00769 for( j = 0; (j < faces_in_range.size()) && !AppUtil::instance()->interrupt(); j++ ) 00770 { 00771 compare_refface_ptr = faces_in_range.get_and_step(); 00772 if( compare_refface_ptr == NULL ) 00773 continue; 00774 00775 // Make sure we are not comparing the same entity 00776 // and that they are not deactivated. 00777 if( ( refface_ptr == compare_refface_ptr ) || 00778 ( compare_refface_ptr->deactivated() == CUBIT_TRUE ) ) 00779 continue; 00780 00781 map_iter = failed_merges.find( refface_ptr ); 00782 if( map_iter != failed_merges.end() ) 00783 if( map_iter->second == compare_refface_ptr ) 00784 continue; 00785 00786 // IMPORTANT: this compare is for merging, so we set the 00787 // last parameter to CUBIT_TRUE so that the 00788 // compare sets the TDCompare data which will 00789 // be used in the RefEntity compare and merge. 00790 // By Jihong 00791 00792 geom_factor = GeometryQueryTool::get_geometry_factor(); 00793 CubitBoolean status = 00794 refface_ptr->about_spatially_equal( compare_refface_ptr, 00795 geom_factor, 00796 CUBIT_TRUE, 00797 GeometryQueryTool::instance()->get_merge_test_bbox(), 00798 GeometryQueryTool::instance()->get_merge_test_internal() ); 00799 if( status == CUBIT_FALSE ) 00800 continue; 00801 00802 //don't merge 2 surfaces of solid volumes if they have 00803 //opposite sense..indicative that they overlap 00804 #if 0 00805 if( refface_ptr->compare_alignment(compare_refface_ptr) == CUBIT_FORWARD ) 00806 { 00807 //if they are both on solid volumes...bail 00808 if( refface_ptr->body()->is_sheet_body() == CUBIT_FALSE && 00809 compare_refface_ptr->body()->is_sheet_body() == CUBIT_FALSE ) 00810 continue; 00811 } 00812 #endif 00813 // If we are in this block, we want to merge the 00814 // two entities. If they do not merge, there was 00815 // an error somewhere. 00816 00817 //First test to see if all the children of these 00818 // reffaces are mergeable 00819 if( !compare_refface_ptr->children_mergeable() ) 00820 { 00821 PRINT_WARNING( "Cannot merge surfaces %d and %d\n" 00822 " Make sure all merge flags are on.\n", 00823 refface_ptr->id(), compare_refface_ptr->id() ); 00824 continue; 00825 } 00826 00827 //Now let us test to see if we are merging two faces that 00828 //belong to the same volume. 00829 DLIList<RefVolume*> ref_vols_1, ref_vols_2; 00830 refface_ptr->ref_volumes( ref_vols_1 ); 00831 compare_refface_ptr->ref_volumes( ref_vols_2 ); 00832 ref_vols_2.intersect( ref_vols_1 ); 00833 if( ref_vols_2.size() > 0 ) 00834 { 00835 PRINT_DEBUG_19( "Tolerance problems, trying to merge " 00836 "surfaces\non the same volume.\n" 00837 " %s (surface %d) and %s (surface %d) on\n" 00838 " %s (volume %d)\n", 00839 refface_ptr->entity_name().c_str(), 00840 refface_ptr->id(), 00841 compare_refface_ptr->entity_name().c_str(), 00842 compare_refface_ptr->id(), 00843 ref_vols_2.get()->entity_name().c_str(), 00844 ref_vols_2.get()->id() ); 00845 if (print_info) { PRINT_DEBUG_19( "Try changing the merge tolerance.\n" ); } 00846 continue; 00847 } 00848 00849 // Always retain the entity with the lowest id. 00850 int nullify = compare_refface_ptr->marked(); 00851 if( refface_ptr->id() > compare_refface_ptr->id() ) 00852 { 00853 std::swap(refface_ptr, compare_refface_ptr); 00854 nullify = i; 00855 } 00856 if (groupResults ) 00857 { 00858 faces_merged.append(refface_ptr); 00859 } 00860 00861 // Now check if merge is okay with all assistants. 00862 CubitBoolean assistant_says_no = CUBIT_FALSE; 00863 for( int k = assistant_list_.size(); k > 0; k-- ) 00864 { 00865 if( ! assistant_list_.get_and_step() 00866 ->can_merge( refface_ptr, compare_refface_ptr ) ) 00867 { 00868 assistant_says_no = CUBIT_TRUE; 00869 break; 00870 } 00871 } 00872 if( assistant_says_no ) 00873 continue; 00874 00875 // Need to retain these so that the pointers are not 00876 // accessed after a merge operation when the 'deleted' 00877 // pointer may be invalid. 00878 int retained_id = refface_ptr->id(); 00879 int deleted_id = compare_refface_ptr->id(); 00880 00881 PRINT_DEBUG_19( "Consolidating RefFace %d and " 00882 "%d...\n", retained_id, deleted_id ); 00883 00884 a_tree.remove(compare_refface_ptr); 00885 00886 if( merge_BTE( refface_ptr, compare_refface_ptr ) ) 00887 { 00888 merge_count++; 00889 if (print_info && !progress) 00890 PRINT_INFO( "Surface %d and %d consolidated\n", 00891 retained_id, deleted_id ); 00892 00893 // The 'deleted' RefFace is now gone. It is an 00894 // error to access that pointer, so we need to 00895 // get it out of the list. 00896 refface_array[nullify] = NULL; 00897 } 00898 else 00899 { 00900 failed_merges.insert( std::make_pair(compare_refface_ptr, refface_ptr) ); 00901 00902 PRINT_ERROR( "Failed to merge Surface %d and %d\n", 00903 retained_id, deleted_id); 00904 PRINT_INFO("Could be sliver geometry in the vicinity\n"); 00905 a_tree.add(compare_refface_ptr); 00906 } 00907 00908 if (nullify == i) 00909 break; 00910 00911 } 00912 } 00913 //clean the marks. 00914 for( i = 0; i < array_size; i++ ) 00915 { 00916 if ( refface_array[i] != NULL ) 00917 refface_array[i]->marked(0); 00918 } 00919 complete_merge(); 00920 if (progress) 00921 progress->end(); 00922 CpuTimer time_to_destroy; 00923 00924 PRINT_DEBUG_3( "Time to destroy r_tree %f secs.\n", 00925 time_to_destroy.cpu_secs()); 00926 00927 // Remove the crud that accumulated during the merge 00928 // operations, from the geometry database. 00929 PRINT_DEBUG_3( "Merge Reffaces time: %f secs\n", 00930 timer.cpu_secs() ); 00931 00932 PRINT_DEBUG_19("Cleaning out TDCompare data from RefFaces...\n"); 00933 if ( groupResults && faces_merged.size() ) 00934 { 00935 DLIList<RefEntity*> refentity_list; 00936 RefFace *tmp_face; 00937 for (int iii = faces_merged.size(); iii > 0; iii-- ) 00938 { 00939 tmp_face = faces_merged.get_and_step(); 00940 if ( !tmp_face->deactivated() ) 00941 refentity_list.append(tmp_face); 00942 } 00943 RefGroup *new_group = RefEntityFactory::instance()->construct_RefGroup("gr_surfs_merged"); 00944 new_group->add_ref_entity( refentity_list ); 00945 if (print_info) PRINT_INFO("Created new group %s (Group %d)\n" 00946 " Group contains surfaces that were merged during\n" 00947 " current merge operation\n", 00948 new_group->entity_name().c_str(), 00949 new_group->id()); 00950 lastSurfsMerged = new_group; 00951 } 00952 //since surface mergeing has occured and we either don't want the 00953 //group or didn't store it, set the lastsurfs to null. 00954 else 00955 lastSurfsMerged = NULL; 00956 00957 if( destroyDeadGeometry ) 00958 GeometryQueryTool::instance()->cleanout_deactivated_geometry(); 00959 00960 PRINT_DEBUG_3( "cleanout time: %f secs\n", timer.cpu_secs() ); 00961 if (print_info) 00962 { 00963 PRINT_INFO( "Consolidated %d pair", merge_count); 00964 if(merge_count > 1) 00965 PRINT_INFO("s"); 00966 PRINT_INFO( " of surfaces\n"); 00967 } 00968 if( AppUtil::instance()->interrupt() ) 00969 { 00970 PRINT_WARNING("Surface merging aborted.\n"); 00971 return CUBIT_FAILURE; 00972 } 00973 00974 if( failed_merges.size() ) 00975 return CUBIT_FAILURE; 00976 00977 return CUBIT_SUCCESS; 00978 } 00979 00980 CubitStatus MergeTool::merge_all_refedges() 00981 { 00982 // if( !displayProgress ) 00983 PRINT_INFO( "\n...Merging all Curves in the model\n" ); 00984 00985 // Get the list of all the RefEdges in the model 00986 DLIList<RefEdge*> refedge_list_model; 00987 GeometryQueryTool::instance()->ref_edges(refedge_list_model); 00988 00989 // Merge the RefEdges in this list 00990 if( merge_refedges( refedge_list_model ) == CUBIT_FAILURE ) 00991 { 00992 PRINT_ERROR( "Curve merging failed\n" ); 00993 return CUBIT_FAILURE; 00994 } 00995 00996 return CUBIT_SUCCESS; 00997 } 00998 00999 CubitStatus MergeTool::find_mergeable_refentities( DLIList<RefEntity*> &entities, 01000 DLIList< DLIList<RefFace*>*> &lists_of_mergeable_ref_faces, 01001 DLIList< DLIList<RefEdge*>*> &lists_of_mergeable_ref_edges, 01002 DLIList< DLIList<RefVertex*>*> &lists_of_mergeable_ref_vertices) 01003 { 01004 DLIList<RefEntity*> tmp_ents; 01005 01006 int i; 01007 01008 //only want surfaces and above 01009 for( i=entities.size(); i--; ) 01010 { 01011 RefEntity *ref_ent = entities.get_and_step(); 01012 if( ref_ent->dimension() > 1 || ref_ent->dimension() == -1 ) 01013 tmp_ents.append( ref_ent ); 01014 } 01015 find_mergeable_reffaces( tmp_ents, lists_of_mergeable_ref_faces, false ); 01016 01017 //only want curves and above 01018 tmp_ents.clean_out(); 01019 for( i=entities.size(); i--; ) 01020 { 01021 RefEntity *ref_ent = entities.get_and_step(); 01022 if( ref_ent->dimension() > 0 || ref_ent->dimension() == -1 ) 01023 tmp_ents.append( ref_ent ); 01024 } 01025 find_mergeable_refedges( tmp_ents, lists_of_mergeable_ref_edges, false ); 01026 01027 find_mergeable_refvertices( entities, lists_of_mergeable_ref_vertices, false); 01028 01029 /* 01030 //remove the compare partners off everything 01031 DLIList<RefEntity*> all_ents; 01032 RefEntity::get_all_child_ref_entities( entities, all_ents ); 01033 PRINT_INFO("Got %d children\n", all_ents.size() ); 01034 all_ents += entities; 01035 01036 int i; 01037 for( i=all_ents.size(); i--; ) 01038 all_ents.get_and_step()->remove_compare_data(); 01039 */ 01040 remove_compare_data(); 01041 01042 return CUBIT_SUCCESS; 01043 } 01044 01045 CubitStatus MergeTool::find_mergeable_reffaces( DLIList<RefEntity*> &entities, 01046 DLIList< DLIList<RefFace*>*> &lists_of_mergeable_ref_faces, 01047 bool clean_up_compare_data ) 01048 { 01049 DLIList<TopologyEntity*> t_ents; 01050 CAST_LIST(entities, t_ents, TopologyEntity); 01051 01052 DLIList<RefFace*> refface_list; 01053 int i; 01054 for( i=t_ents.size(); i--; ) 01055 { 01056 DLIList<RefFace*> tmp_faces; 01057 t_ents.get_and_step()->ref_faces( tmp_faces ); 01058 refface_list += tmp_faces; 01059 } 01060 01061 double geom_factor = GeometryQueryTool::get_geometry_factor(); 01062 RTree<RefFace*> a_tree(GEOMETRY_RESABS*geom_factor); 01063 // AbstractTree <RefFace*> *a_tree = new RTree<RefFace*> (GEOMETRY_RESABS*geom_factor); 01064 01065 DLIList<RefFace*> refface_array( refface_list.size() ); 01066 refface_list.reset(); 01067 01068 // Remove entities that should not be automatically merged 01069 int loop_size = refface_list.size(); 01070 CpuTimer time_to_build; 01071 for( i = 0; i < loop_size; i++ ) 01072 { 01073 RefFace *curr_face = refface_list.get_and_step(); 01074 if( curr_face->is_mergeable() ) 01075 { 01076 refface_array.append( curr_face ); 01077 a_tree.add(curr_face); 01078 } 01079 } 01080 PRINT_DEBUG_3( "Time to build r_tree %f secs, with %d entries\n", 01081 time_to_build.cpu_secs(), refface_array.size() ); 01082 01083 //initialize the marked flag for fast nulification... 01084 int array_size = refface_array.size(); 01085 for ( i = 0; i < array_size; i++) 01086 refface_array[i]->marked(i); 01087 01088 ProgressTool* progress = 0; 01089 if( displayProgress ) 01090 { 01091 char info[64]; 01092 sprintf(info, "Comparing %d Surfaces for Merge", refface_array.size() ); 01093 progress = AppUtil::instance()->progress_tool(); 01094 if (progress) 01095 { 01096 progress->start( 0, refface_array.size(), "Comparing Surfaces:", 01097 info, CUBIT_TRUE, CUBIT_TRUE ); 01098 } 01099 } 01100 01101 // Now find overlapping RefFaces and merge them. 01102 // Make sure that the operation is not performed on 01103 // RefFaces that are deactivated. 01104 int j = 0; 01105 RefFace* refface_ptr = NULL; 01106 RefFace* compare_refface_ptr = NULL; 01107 DLIList<RefFace*> faces_in_range; 01108 01109 CubitBox temp_box; 01110 for( i = 0; (i < array_size) && !AppUtil::instance()->interrupt(); i++ ) 01111 { 01112 if( progress ) progress->step(); 01113 01114 refface_ptr = refface_array[i]; 01115 if( refface_ptr == NULL ) 01116 continue; 01117 01118 // There is no need to compare if the first RefFace is 01119 // deactivated. 01120 if( refface_ptr->deactivated() == CUBIT_TRUE ) 01121 continue ; 01122 01123 //Now from the atree, get the surfaces that are close. 01124 temp_box = refface_ptr->bounding_box(); 01125 faces_in_range.clean_out(); 01126 a_tree.find(temp_box, faces_in_range); 01127 01128 DLIList<RefVolume*> tmp_vols; 01129 refface_ptr->ref_volumes( tmp_vols); 01130 RefVolume* tmp_vol= tmp_vols.get(); 01131 01132 DLIList<RefFace*> *new_list = NULL; 01133 for( j = 0; (j < faces_in_range.size()) && !AppUtil::instance()->interrupt(); j++ ) 01134 { 01135 compare_refface_ptr = faces_in_range.get_and_step(); 01136 if( compare_refface_ptr == NULL ) 01137 continue; 01138 01139 if( compare_refface_ptr == refface_ptr ) 01140 continue; 01141 01142 //surfaces in the same bodies won't merge 01143 tmp_vols.clean_out(); 01144 compare_refface_ptr->ref_volumes( tmp_vols ); 01145 RefVolume* compare_vol= tmp_vols.get(); 01146 if( tmp_vol == compare_vol ) 01147 continue; 01148 01149 // Make sure we are not comparing the same entity 01150 // and that they are not deactivated. 01151 if( ( refface_ptr == compare_refface_ptr ) || 01152 ( compare_refface_ptr->deactivated() == CUBIT_TRUE ) ) 01153 continue; 01154 01155 geom_factor = GeometryQueryTool::get_geometry_factor(); 01156 CubitBoolean status = 01157 refface_ptr->about_spatially_equal( compare_refface_ptr, 01158 geom_factor, 01159 CUBIT_TRUE, 01160 GeometryQueryTool::instance()->get_merge_test_bbox(), 01161 GeometryQueryTool::instance()->get_merge_test_internal() ); 01162 if( status == CUBIT_FALSE ) 01163 continue; 01164 01165 //First test to see if all the children of these 01166 // reffaces are mergeable 01167 if( !compare_refface_ptr->children_mergeable() ) 01168 continue; 01169 01170 //Now let us test to see if we are merging two faces that 01171 //belong to the same volume. 01172 DLIList<RefVolume*> ref_vols_1, ref_vols_2; 01173 refface_ptr->ref_volumes( ref_vols_1 ); 01174 compare_refface_ptr->ref_volumes( ref_vols_2 ); 01175 ref_vols_2.intersect( ref_vols_1 ); 01176 if( ref_vols_2.size() > 0 ) 01177 { 01178 PRINT_ERROR( "Tolerance problems, trying to find mergeable " 01179 "surfaces\non the same volume.\n" 01180 " %s (surface %d) and %s (surface %d) on\n" 01181 " %s (volume %d)\n", 01182 refface_ptr->entity_name().c_str(), 01183 refface_ptr->id(), 01184 compare_refface_ptr->entity_name().c_str(), 01185 compare_refface_ptr->id(), 01186 ref_vols_2.get()->entity_name().c_str(), 01187 ref_vols_2.get()->id() ); 01188 continue; 01189 } 01190 01191 // Always retain the entity with the lowest id. 01192 int nullify = compare_refface_ptr->marked(); 01193 01194 // Now check if merge is okay with all assistants. 01195 CubitBoolean assistant_says_no = CUBIT_FALSE; 01196 for( int k = assistant_list_.size(); k > 0; k-- ) 01197 { 01198 if( ! assistant_list_.get_and_step() 01199 ->can_merge( refface_ptr, compare_refface_ptr ) ) 01200 { 01201 assistant_says_no = CUBIT_TRUE; 01202 break; 01203 } 01204 } 01205 if( assistant_says_no ) 01206 continue; 01207 01208 a_tree.remove(compare_refface_ptr); 01209 01210 refface_array[nullify] = NULL; 01211 01212 if( new_list == NULL ) 01213 { 01214 new_list = new DLIList<RefFace*>; 01215 new_list->append( refface_ptr ); 01216 new_list->append( compare_refface_ptr ); 01217 } 01218 else 01219 new_list->append( compare_refface_ptr ); 01220 } 01221 01222 if( new_list ) 01223 lists_of_mergeable_ref_faces.append( new_list ); 01224 } 01225 //clean the marks. 01226 for( i = 0; i < array_size; i++ ) 01227 { 01228 if ( refface_array[i] != NULL ) 01229 refface_array[i]->marked(0); 01230 } 01231 01232 if( clean_up_compare_data ) 01233 remove_compare_data(); 01234 01235 if (progress) 01236 progress->end(); 01237 01238 01239 if( AppUtil::instance()->interrupt() ) 01240 { 01241 PRINT_WARNING("Finding mergeable surfaces aborted.\n"); 01242 return CUBIT_FAILURE; 01243 } 01244 01245 return CUBIT_SUCCESS; 01246 } 01247 01248 CubitStatus MergeTool::find_mergeable_refedges( DLIList<RefEntity*> &entities, 01249 DLIList< DLIList<RefEdge*>*> &lists_of_mergeable_ref_edges, 01250 bool clean_up_compare_data ) 01251 { 01252 01253 DLIList<TopologyEntity*> t_ents; 01254 CAST_LIST(entities, t_ents, TopologyEntity); 01255 01256 DLIList<RefEdge*> refedge_list; 01257 int i; 01258 for( i=t_ents.size(); i--; ) 01259 { 01260 DLIList<RefEdge*> tmp_edges; 01261 t_ents.get_and_step()->ref_edges( tmp_edges ); 01262 refedge_list += tmp_edges; 01263 } 01264 01265 if( refedge_list.size() == 0 ) 01266 return CUBIT_SUCCESS; 01267 01268 DLIList<RefEdge*> refedge_array( refedge_list.size() ); 01269 refedge_list.reset(); 01270 01271 DLIList<RefEdge*> edges_on_two_surfs; 01272 01273 for( i = refedge_list.size(); i > 0; i-- ) 01274 { 01275 // Remove entities that should not be automatically merged 01276 RefEdge *curr_edge = refedge_list.get_and_step(); 01277 if( curr_edge->is_mergeable() ) 01278 { 01279 //put all edges in the list first that are attached 01280 //to only one or zero surface. This prevents curves on sheet 01281 //bodies from being excluded. 01282 DLIList<RefFace*> tmp_faces; 01283 curr_edge->ref_faces( tmp_faces ); 01284 if( tmp_faces.size() < 2 ) 01285 refedge_array.append( curr_edge ); 01286 else 01287 edges_on_two_surfs.append( curr_edge ); 01288 } 01289 } 01290 01291 for( i = edges_on_two_surfs.size(); i--; ) 01292 refedge_array.append( edges_on_two_surfs.get_and_step() ); 01293 01294 ProgressTool* progress = 0; 01295 01296 int j = 0; 01297 RefEdge* refedge_ptr = NULL; 01298 RefEdge* compare_refedge_ptr = NULL; 01299 int array_size = refedge_array.size(); 01300 for( i = 0; (i < array_size) && !AppUtil::instance()->interrupt(); i++ ) 01301 { 01302 if( progress ) progress->step(); 01303 01304 refedge_ptr = refedge_array[i]; 01305 if( refedge_ptr == NULL ) 01306 continue; 01307 01308 // There is not need to compare if the first RefEdge is 01309 // dactivated. 01310 if ( refedge_ptr->deactivated() == CUBIT_TRUE ) 01311 continue ; 01312 01313 if( refedge_ptr->get_compare_partner() ) 01314 { 01315 //see if owning reface has compare partner...if so 01316 //edge is merged already. 01317 DLIList<RefFace*> tmp_faces; 01318 refedge_ptr->ref_faces( tmp_faces ); 01319 01320 int kk; 01321 bool owning_surface_has_compare_partner = false; 01322 for( kk=tmp_faces.size(); kk--; ) 01323 if( tmp_faces.get_and_step()->get_compare_partner() ) 01324 owning_surface_has_compare_partner = true; 01325 01326 if( owning_surface_has_compare_partner ) 01327 continue; 01328 } 01329 01330 DLIList<RefEdge*> *new_list = NULL; 01331 01332 for( j = i+1; (j < array_size) && !AppUtil::instance()->interrupt(); j++ ) 01333 { 01334 compare_refedge_ptr = refedge_array[j]; 01335 if( compare_refedge_ptr == NULL ) 01336 continue; 01337 01338 // Make sure we are not comparing the same entity 01339 // and that they are not deactivated. 01340 if( ( refedge_ptr == compare_refedge_ptr ) || 01341 ( compare_refedge_ptr->deactivated() == CUBIT_TRUE ) ) 01342 continue; 01343 01344 double geom_factor = GeometryQueryTool::get_geometry_factor(); 01345 CubitBoolean status = 01346 refedge_ptr->about_spatially_equal(compare_refedge_ptr, 01347 geom_factor, 01348 (CubitSense*)NULL, 01349 CUBIT_TRUE); 01350 if( status == CUBIT_FALSE ) 01351 continue; 01352 01353 01354 //Make sure the children of the refedges are mergeable 01355 if( !refedge_ptr->children_mergeable() ) 01356 continue; 01357 01358 //Now let us test to see if we are merging two edges that 01359 //belong to the same face 01360 DLIList<RefFace*> ref_faces_1, ref_faces_2; 01361 refedge_ptr->ref_faces( ref_faces_1 ); 01362 compare_refedge_ptr->ref_faces( ref_faces_2 ); 01363 ref_faces_2.intersect( ref_faces_1 ); 01364 if( ref_faces_2.size() > 0 ) 01365 { 01366 PRINT_DEBUG_19( "Tolerance problems, trying to find mergeable" 01367 " curves\non the same surface.\n" 01368 "%s (curve %d) and %s (curve %d) on\n" 01369 "%s (surface %d)\n", 01370 refedge_ptr->entity_name().c_str(), 01371 refedge_ptr->id(), 01372 compare_refedge_ptr->entity_name().c_str(), 01373 compare_refedge_ptr->id(), 01374 ref_faces_2.get()->entity_name().c_str(), 01375 ref_faces_2.get()->id() ); 01376 PRINT_DEBUG_19( "Try changing the merge tolerance.\n" ); 01377 continue; 01378 } 01379 // If we are in this block, we want to merge the 01380 // two entities. If they do not merge, there was 01381 // an error somewhere. 01382 01383 // Always retain the entity with the lowest id. 01384 int nullify = j; 01385 if( refedge_ptr->id() > compare_refedge_ptr->id() ) 01386 { 01387 std::swap(refedge_ptr, compare_refedge_ptr); 01388 nullify = i; 01389 } 01390 01391 // Now check if merge is okay with all assistants. 01392 CubitBoolean assistant_says_no = CUBIT_FALSE; 01393 for( int k = assistant_list_.size(); k > 0; k-- ) 01394 { 01395 if( ! assistant_list_.get_and_step() 01396 ->can_merge( refedge_ptr, compare_refedge_ptr ) ) 01397 { 01398 assistant_says_no = CUBIT_TRUE; 01399 break; 01400 } 01401 } 01402 if( assistant_says_no ) 01403 continue; 01404 01405 // Need to retain these so that the pointers are not 01406 // accessed after a merge operation when the 'deleted' 01407 // pointer may be invalid. 01408 //int retained_id = refedge_ptr->id(); 01409 //int deleted_id = compare_refedge_ptr->id(); 01410 01411 if( new_list == NULL ) 01412 { 01413 new_list = new DLIList<RefEdge*>; 01414 new_list->append( refedge_ptr ); 01415 new_list->append( compare_refedge_ptr ); 01416 } 01417 else 01418 new_list->append( compare_refedge_ptr ); 01419 01420 refedge_array[nullify] = NULL; 01421 01422 if (nullify == i) 01423 break; 01424 } 01425 01426 if( new_list ) 01427 lists_of_mergeable_ref_edges.append( new_list ); 01428 } 01429 01430 if( clean_up_compare_data ) 01431 remove_compare_data(); 01432 01433 if(progress) 01434 progress->end(); 01435 01436 return CUBIT_SUCCESS; 01437 } 01438 01439 CubitStatus MergeTool::find_only_mergeable_surfaces ( DLIList<BodySM*> &body_list, 01440 DLIList< DLIList<Surface*>*> &lists_of_mergeable_surfaces ) 01441 { 01442 double geom_factor = GeometryQueryTool::get_geometry_factor(); 01443 double merge_tolerance = geom_factor*GEOMETRY_RESABS; 01444 int i,j,k,l; 01445 01446 std::map< Surface*, DLIList<Surface*>*> surf_to_list_map; 01447 std::map< Surface*, DLIList<Surface*>*>::iterator list_iter; 01448 01449 DLIList<BodySM*> tmp_body_list = body_list; 01450 tmp_body_list.reset(); 01451 for(i=tmp_body_list.size(); i--; ) 01452 { 01453 BodySM *tmp_body1 = tmp_body_list.pop(); 01454 CubitBox body1_box = tmp_body1->bounding_box(); 01455 for(j=tmp_body_list.size(); j--; ) 01456 { 01457 BodySM *tmp_body2 = tmp_body_list.get_and_step(); 01458 CubitBox body2_box = tmp_body2->bounding_box(); 01459 01460 01461 if( body1_box.overlap( merge_tolerance, body2_box ) ) 01462 { 01463 DLIList<Surface*> body1_surfs; 01464 DLIList<Surface*> body2_surfs; 01465 01466 tmp_body1->surfaces( body1_surfs ); 01467 tmp_body2->surfaces( body2_surfs ); 01468 01469 for( k=body1_surfs.size(); k--; ) 01470 { 01471 Surface *body1_surf = body1_surfs.pop(); 01472 CubitBox surf1_box = body1_surf->bounding_box(); 01473 01474 for(l=body2_surfs.size(); l--; ) 01475 { 01476 Surface *body2_surf = body2_surfs.get(); 01477 01478 if( body2_surf == NULL ) 01479 { 01480 body2_surfs.step(); 01481 continue; 01482 } 01483 01484 CubitBox surf2_box = body2_surf->bounding_box(); 01485 01486 if( surf1_box.overlap( merge_tolerance, surf2_box ) ) 01487 { 01488 01489 if( about_spatially_equal( body1_surf, body2_surf, geom_factor) ) 01490 { 01491 //check to see if surfs have already been inserted into lists 01492 DLIList<Surface*> *surf1_list = NULL; 01493 DLIList<Surface*> *surf2_list = NULL; 01494 01495 list_iter = surf_to_list_map.find( body1_surf); 01496 if( list_iter != surf_to_list_map.end() ) 01497 surf1_list = list_iter->second; 01498 01499 list_iter = surf_to_list_map.find( body2_surf); 01500 if( list_iter != surf_to_list_map.end() ) 01501 surf2_list = list_iter->second; 01502 01503 if( surf1_list == NULL && surf2_list == NULL ) 01504 { 01505 surf1_list = new DLIList<Surface*>; 01506 surf1_list->append( body1_surf ); 01507 surf1_list->append( body2_surf ); 01508 surf_to_list_map.insert( std::map<Surface*, 01509 DLIList<Surface*>*>::value_type( body1_surf, surf1_list )); 01510 surf_to_list_map.insert( std::map<Surface*, 01511 DLIList<Surface*>*>::value_type( body2_surf, surf1_list )); 01512 lists_of_mergeable_surfaces.append( surf1_list ); 01513 break; 01514 } 01515 else if( surf1_list == NULL ) 01516 { 01517 PRINT_ERROR("A surface cannot be merged with more than 1 other surface\n"); 01518 } 01519 else if( surf2_list == NULL ) 01520 { 01521 PRINT_ERROR("A surface cannot be merged with more than 1 other surface\n"); 01522 } 01523 01524 body2_surfs.change_to( NULL ); 01525 } 01526 } 01527 body2_surfs.step(); 01528 } 01529 } 01530 } 01531 } 01532 } 01533 return CUBIT_SUCCESS; 01534 } 01535 01536 01537 CubitStatus MergeTool::find_only_mergeable_surfaces ( DLIList<BodySM*> &body_list, 01538 DLIList< DLIList<Surface*>*> &lists_of_mergeable_surfaces, const double tol ) 01539 { 01540 double geom_factor = GeometryQueryTool::get_geometry_factor(); 01541 double merge_tolerance = tol; 01542 int i,j,k,l; 01543 01544 std::map< Surface*, DLIList<Surface*>*> surf_to_list_map; 01545 std::map< Surface*, DLIList<Surface*>*>::iterator list_iter; 01546 01547 DLIList<BodySM*> tmp_body_list = body_list; 01548 tmp_body_list.reset(); 01549 for(i=tmp_body_list.size(); i--; ) 01550 { 01551 BodySM *tmp_body1 = tmp_body_list.pop(); 01552 CubitBox body1_box = tmp_body1->bounding_box(); 01553 for(j=tmp_body_list.size(); j--; ) 01554 { 01555 BodySM *tmp_body2 = tmp_body_list.get_and_step(); 01556 CubitBox body2_box = tmp_body2->bounding_box(); 01557 01558 01559 if( body1_box.overlap( merge_tolerance, body2_box ) ) 01560 { 01561 DLIList<Surface*> body1_surfs; 01562 DLIList<Surface*> body2_surfs; 01563 01564 tmp_body1->surfaces( body1_surfs ); 01565 tmp_body2->surfaces( body2_surfs ); 01566 01567 for( k=body1_surfs.size(); k--; ) 01568 { 01569 Surface *body1_surf = body1_surfs.pop(); 01570 CubitBox surf1_box = body1_surf->bounding_box(); 01571 01572 for(l=body2_surfs.size(); l--; ) 01573 { 01574 Surface *body2_surf = body2_surfs.get(); 01575 01576 if( body2_surf == NULL ) 01577 { 01578 body2_surfs.step(); 01579 continue; 01580 } 01581 01582 CubitBox surf2_box = body2_surf->bounding_box(); 01583 01584 if( surf1_box.overlap( merge_tolerance, surf2_box ) ) 01585 { 01586 01587 if( about_spatially_equal( body1_surf, body2_surf, geom_factor) ) 01588 { 01589 //check to see if surfs have already been inserted into lists 01590 DLIList<Surface*> *surf1_list = NULL; 01591 DLIList<Surface*> *surf2_list = NULL; 01592 01593 list_iter = surf_to_list_map.find( body1_surf); 01594 if( list_iter != surf_to_list_map.end() ) 01595 surf1_list = list_iter->second; 01596 01597 list_iter = surf_to_list_map.find( body2_surf); 01598 if( list_iter != surf_to_list_map.end() ) 01599 surf2_list = list_iter->second; 01600 01601 if( surf1_list == NULL && surf2_list == NULL ) 01602 { 01603 surf1_list = new DLIList<Surface*>; 01604 surf1_list->append( body1_surf ); 01605 surf1_list->append( body2_surf ); 01606 surf_to_list_map.insert( std::map<Surface*, 01607 DLIList<Surface*>*>::value_type( body1_surf, surf1_list )); 01608 surf_to_list_map.insert( std::map<Surface*, 01609 DLIList<Surface*>*>::value_type( body2_surf, surf1_list )); 01610 lists_of_mergeable_surfaces.append( surf1_list ); 01611 break; 01612 } 01613 else if( surf1_list == NULL ) 01614 { 01615 PRINT_ERROR("A surface cannot be merged with more than 1 other surface\n"); 01616 } 01617 else if( surf2_list == NULL ) 01618 { 01619 PRINT_ERROR("A surface cannot be merged with more than 1 other surface\n"); 01620 } 01621 01622 body2_surfs.change_to( NULL ); 01623 } 01624 } 01625 body2_surfs.step(); 01626 } 01627 } 01628 } 01629 } 01630 } 01631 return CUBIT_SUCCESS; 01632 } 01633 01634 CubitStatus MergeTool::find_only_mergeable_curves( DLIList<Curve*> &all_curves, 01635 DLIList< DLIList<Curve*>*> &lists_of_mergeable_curves, double input_tol ) 01636 { 01637 int i; 01638 double geom_factor = GeometryQueryTool::get_geometry_factor(); 01639 if(input_tol > 0.0) 01640 geom_factor = input_tol/GEOMETRY_RESABS; 01641 01642 //build up a tree for speed purposes 01643 RTree<Curve*> a_tree(GEOMETRY_RESABS*geom_factor); 01644 //AbstractTree <Curve*> *a_tree = new RTree<Curve*> (GEOMETRY_RESABS*geom_factor); 01645 for( i=all_curves.size(); i--; ) 01646 a_tree.add( all_curves.get_and_step() ); 01647 01648 std::map< Curve*, DLIList<Curve*>*> curve_to_list_map; 01649 std::map< Curve*, DLIList<Curve*>*>::iterator list_iter; 01650 01651 for( i=all_curves.size(); i--; ) 01652 { 01653 Curve *curr_curve = all_curves.get_and_step(); 01654 if( curr_curve == NULL ) 01655 continue; 01656 01657 BodySM *cur_sm = curr_curve->bodysm(); 01658 01659 //get close curves 01660 DLIList<Curve*> close_curves; 01661 a_tree.find(curr_curve->bounding_box(), close_curves); 01662 01663 int j; 01664 for( j=close_curves.size(); j--; ) 01665 { 01666 Curve *other_curve = close_curves.get_and_step(); 01667 if( curr_curve == other_curve ) 01668 continue; 01669 01670 BodySM *other_sm = other_curve->bodysm(); 01671 01672 if(cur_sm != other_sm) 01673 { 01674 bool mergeable = false; 01675 01676 // If these curves are already merged add them to the list. 01677 if(curr_curve->bridge_manager() && 01678 curr_curve->bridge_manager() == other_curve->bridge_manager()) 01679 { 01680 mergeable = true; 01681 } 01682 01683 if(!mergeable) 01684 { 01685 CubitSense rel_sense; 01686 CubitBoolean abs = about_spatially_equal( curr_curve, other_curve, rel_sense, 01687 geom_factor ); 01688 if(abs) 01689 mergeable = true; 01690 } 01691 01692 if( mergeable ) 01693 { 01694 //check to see if curves have already been inserted into lists 01695 DLIList<Curve*> *curve1_list = NULL; 01696 01697 list_iter = curve_to_list_map.find( curr_curve ); 01698 if( list_iter != curve_to_list_map.end() ) 01699 curve1_list = list_iter->second; 01700 01701 if( curve1_list == NULL ) 01702 { 01703 curve1_list = new DLIList<Curve*>; 01704 curve1_list->append( curr_curve ); 01705 curve1_list->append( other_curve ); 01706 curve_to_list_map.insert( std::map<Curve*, 01707 DLIList<Curve*>*>::value_type( curr_curve , curve1_list )); 01708 curve_to_list_map.insert( std::map<Curve*, 01709 DLIList<Curve*>*>::value_type( other_curve, curve1_list )); 01710 lists_of_mergeable_curves.append( curve1_list ); 01711 } 01712 else 01713 { 01714 curve1_list->append( other_curve ); 01715 curve_to_list_map.insert( std::map<Curve*, 01716 DLIList<Curve*>*>::value_type( other_curve, curve1_list )); 01717 } 01718 01719 //remove mergeable curves from list and reset list 01720 int item_index = all_curves.where_is_item( other_curve ); 01721 if( item_index > 0 ) 01722 { 01723 int curr_index = all_curves.get_index(); 01724 all_curves.reset(); 01725 all_curves.step( item_index ); 01726 all_curves.change_to( NULL ); 01727 all_curves.reset(); 01728 all_curves.step( curr_index ); 01729 } 01730 } 01731 } 01732 } 01733 } 01734 return CUBIT_SUCCESS; 01735 } 01736 01737 CubitStatus MergeTool::find_only_mergeable_curves( DLIList<Surface*> &surf_list, 01738 DLIList< DLIList<Curve*>*> &lists_of_mergeable_curves, double input_tol ) 01739 { 01740 //collect all the curves from off the bodies 01741 DLIList<Curve*> all_curves; 01742 surf_list.reset(); 01743 int i; 01744 for(i=surf_list.size(); i--; ) 01745 { 01746 Surface* tmp_surf = surf_list.get_and_step(); 01747 DLIList<Curve*> tmp_curves; 01748 tmp_surf->curves(tmp_curves); 01749 all_curves += tmp_curves; 01750 } 01751 01752 return find_only_mergeable_curves(all_curves, lists_of_mergeable_curves, input_tol); 01753 } 01754 01755 CubitStatus MergeTool::find_only_mergeable_curves( DLIList<BodySM*> &body_list, 01756 DLIList< DLIList<Curve*>*> &lists_of_mergeable_curves, double input_tol ) 01757 { 01758 //collect all the curves from off the bodies 01759 DLIList<Curve*> all_curves; 01760 body_list.reset(); 01761 int i; 01762 for(i=body_list.size(); i--; ) 01763 { 01764 BodySM* tmp_body = body_list.get_and_step(); 01765 DLIList<Curve*> tmp_curves; 01766 tmp_body->curves( tmp_curves); 01767 all_curves += tmp_curves; 01768 } 01769 01770 return find_only_mergeable_curves(all_curves, lists_of_mergeable_curves, input_tol); 01771 01772 } 01773 01774 CubitStatus MergeTool::find_mergeable_refvertices( DLIList<RefEntity*> &entities, 01775 DLIList< DLIList<RefVertex*>*> &lists_of_mergeable_ref_vertices, 01776 bool clean_up_compare_data ) 01777 { 01778 01779 DLIList<TopologyEntity*> t_ents; 01780 CAST_LIST(entities, t_ents, TopologyEntity); 01781 01782 DLIList<RefVertex*> refvertex_list; 01783 int i; 01784 for( i=t_ents.size(); i--; ) 01785 { 01786 DLIList<RefVertex*> tmp_verts; 01787 t_ents.get_and_step()->ref_vertices( tmp_verts); 01788 refvertex_list += tmp_verts; 01789 } 01790 01791 if( refvertex_list.size() == 0 ) 01792 return CUBIT_SUCCESS; 01793 01794 DLIList<RefVertex*> refvertex_array( refvertex_list.size() ); 01795 refvertex_list.reset(); 01796 01797 // Remove entities that should not be automatically merged 01798 for( i = refvertex_list.size(); i > 0; i-- ) 01799 { 01800 RefVertex *curr_vert = refvertex_list.get_and_step(); 01801 if( curr_vert->is_mergeable() ) 01802 refvertex_array.append( curr_vert ); 01803 } 01804 01805 ProgressTool* progress = 0; 01806 01807 // Now find overlapping RefVertices and merge them. 01808 // Make sure that the operation is not performed on 01809 // RefVertices that are deactivated. 01810 int j = 0; 01811 RefVertex* refvertex_ptr = NULL; 01812 RefVertex* compare_refvertex_ptr = NULL; 01813 int array_size = refvertex_array.size(); 01814 for( i = 0; (i < array_size) && !AppUtil::instance()->interrupt(); i++ ) 01815 { 01816 if( progress ) progress->step(); 01817 01818 refvertex_ptr = refvertex_array[i]; 01819 if( refvertex_ptr == NULL ) 01820 continue; 01821 01822 if( refvertex_ptr->get_compare_partner() ) 01823 continue; 01824 01825 // There is not need to compare if the first RefVertex is 01826 // dactivated. 01827 if( refvertex_ptr->deactivated() == CUBIT_TRUE ) 01828 continue ; 01829 01830 DLIList<RefVertex*> *new_list = NULL; 01831 01832 for( j = i+1; (j < array_size) && !AppUtil::instance()->interrupt(); j++ ) 01833 { 01834 compare_refvertex_ptr = refvertex_array[j]; 01835 if( compare_refvertex_ptr == NULL ) 01836 continue; 01837 01838 // Make sure we are not comparing the same entity 01839 // and that they are not deactivated. 01840 if( ( refvertex_ptr == compare_refvertex_ptr ) || 01841 ( compare_refvertex_ptr->deactivated() == CUBIT_TRUE ) ) 01842 continue; 01843 01844 double geom_factor = GeometryQueryTool::get_geometry_factor(); 01845 CubitBoolean status = 01846 refvertex_ptr->about_spatially_equal( compare_refvertex_ptr, 01847 geom_factor ); 01848 if( status == CUBIT_FALSE ) 01849 continue; 01850 01851 //Make sure we arn't merging two vertices on a 01852 //curve. 01853 DLIList<RefEdge*> edges_1, edges_2; 01854 refvertex_ptr->ref_edges( edges_1 ); 01855 compare_refvertex_ptr->ref_edges( edges_2 ); 01856 edges_2.intersect( edges_1 ); 01857 if( edges_2.size() > 0 ) 01858 { 01859 PRINT_DEBUG_19( "Tolerance problems, trying to merge" 01860 " vertices\non the same curve.\n" 01861 "%s (vertex %d) and %s (vertex %d) on\n" 01862 "%s (curve %d)\n", 01863 refvertex_ptr->entity_name().c_str(), 01864 refvertex_ptr->id(), 01865 compare_refvertex_ptr->entity_name().c_str(), 01866 compare_refvertex_ptr->id(), 01867 edges_2.get()->entity_name().c_str(), 01868 edges_2.get()->id() ); 01869 PRINT_DEBUG_19( "Try changing the merge tolerance.\n" ); 01870 continue; 01871 } 01872 01873 // Always retain the entity with the lowest id. 01874 int nullify = j; 01875 if( refvertex_ptr->id() > compare_refvertex_ptr->id() ) 01876 { 01877 std::swap(refvertex_ptr, compare_refvertex_ptr); 01878 nullify = i; 01879 } 01880 01881 // Now check if merge is okay with all assistants. 01882 CubitBoolean assistant_says_no = CUBIT_FALSE; 01883 for( int k = assistant_list_.size(); k > 0; k-- ) 01884 { 01885 if( ! assistant_list_.get_and_step() 01886 ->can_merge( refvertex_ptr, compare_refvertex_ptr ) ) 01887 { 01888 assistant_says_no = CUBIT_TRUE; 01889 break; 01890 } 01891 } 01892 if( assistant_says_no ) 01893 continue; 01894 01895 // Need to retain these so that the pointers are not 01896 // accessed after a merge operation when the 'deleted' 01897 // pointer may be invalid. 01898 //int retained_id = refvertex_ptr->id(); 01899 //int deleted_id = compare_refvertex_ptr->id(); 01900 01901 refvertex_array[nullify] = NULL; 01902 01903 if( new_list == NULL ) 01904 { 01905 new_list = new DLIList<RefVertex*>; 01906 new_list->append( refvertex_ptr ); 01907 new_list->append( compare_refvertex_ptr ); 01908 } 01909 else 01910 new_list->append( compare_refvertex_ptr ); 01911 01912 if( nullify == i ) 01913 break; 01914 } 01915 01916 if( new_list ) 01917 lists_of_mergeable_ref_vertices.append( new_list ); 01918 } 01919 01920 if(progress) 01921 progress->end(); 01922 01923 if( clean_up_compare_data ) 01924 remove_compare_data(); 01925 01926 if( AppUtil::instance()->interrupt() ) 01927 { 01928 PRINT_WARNING("Vertex merging aborted.\n"); 01929 return CUBIT_FAILURE; 01930 } 01931 return CUBIT_SUCCESS; 01932 } 01933 01934 01935 CubitStatus MergeTool::merge_refedges( DLIList<RefEdge*>& refedge_list, 01936 CubitBoolean should_clean_out, 01937 CubitBoolean print_info) 01938 { 01939 if( refedge_list.size() < 20 ) 01940 return old_merge_refedges( refedge_list, should_clean_out, print_info ); 01941 01942 int merge_count = 0; 01943 CpuTimer timer; 01944 01945 double geom_factor = GeometryQueryTool::get_geometry_factor(); 01946 RTree<RefEdge*> a_tree(GEOMETRY_RESABS*geom_factor); 01947 //AbstractTree <RefEdge*> *a_tree = new RTree<RefEdge*> (GEOMETRY_RESABS*geom_factor); 01948 01949 DLIList<RefEdge*> refedge_array( refedge_list.size() ); 01950 refedge_list.reset(); 01951 01952 // Remove entities that should not be automatically merged 01953 int i = 0; 01954 int loop_size = refedge_list.size(); 01955 CpuTimer time_to_build; 01956 for( i = 0; i < loop_size; i++ ) 01957 { 01958 RefEdge *curr_edge = refedge_list.get_and_step(); 01959 if( curr_edge->is_mergeable() ) 01960 { 01961 refedge_array.append( curr_edge ); 01962 a_tree.add(curr_edge); 01963 } 01964 } 01965 01966 //initialize the marked flag for fast nulification... 01967 int array_size = refedge_array.size(); 01968 for ( i = 0; i < array_size; i++) 01969 refedge_array[i]->marked(i); 01970 01971 ProgressTool* progress = 0; 01972 if( displayProgress ) 01973 { 01974 char info[64]; 01975 sprintf(info, "Comparing %d Curves for Merge", refedge_array.size() ); 01976 progress = AppUtil::instance()->progress_tool(); 01977 if (progress) 01978 { 01979 progress->start( 0, refedge_array.size(), "Comparing Curves:", 01980 info, CUBIT_TRUE, CUBIT_TRUE ); 01981 } 01982 } 01983 01984 // Now find overlapping RefEdges and merge them. 01985 // Make sure that the operation is not performed on 01986 // RefEdges that are deactivated. 01987 int j = 0; 01988 RefEdge* refedge_ptr = NULL; 01989 RefEdge* compare_refedge_ptr = NULL; 01990 DLIList<RefEdge*> edges_merged, edges_in_range; 01991 CubitBox temp_box; 01992 std::map<RefEdge*, RefEdge*> failed_merges; 01993 std::map<RefEdge*, RefEdge*>::iterator map_iter; 01994 01995 for( i = 0; (i < array_size) && !AppUtil::instance()->interrupt(); i++ ) 01996 { 01997 if( progress ) progress->step(); 01998 01999 refedge_ptr = refedge_array[i]; 02000 if( refedge_ptr == NULL ) 02001 continue; 02002 02003 // There is no need to compare if the first RefEdge is 02004 // deactivated. 02005 if( refedge_ptr->deactivated() == CUBIT_TRUE ) 02006 continue ; 02007 02008 //Now from the atree, get the edges that are close. 02009 temp_box = refedge_ptr->bounding_box(); 02010 edges_in_range.clean_out(); 02011 a_tree.find(temp_box, edges_in_range); 02012 02013 for( j = 0; (j < edges_in_range.size()) && !AppUtil::instance()->interrupt(); j++ ) 02014 { 02015 compare_refedge_ptr = edges_in_range.get_and_step(); 02016 if( compare_refedge_ptr == NULL ) 02017 continue; 02018 02019 // Make sure we are not comparing the same entity 02020 // and that they are not deactivated. 02021 if( ( refedge_ptr == compare_refedge_ptr ) || 02022 ( compare_refedge_ptr->deactivated() == CUBIT_TRUE ) ) 02023 continue; 02024 02025 map_iter = failed_merges.find( refedge_ptr ); 02026 if( map_iter != failed_merges.end() ) 02027 if( map_iter->second == compare_refedge_ptr ) 02028 continue; 02029 02030 // IMPORTANT: this compare is for merging, so we set the 02031 // last parameter to CUBIT_TRUE so that the 02032 // compare sets the TDCompare data which will 02033 // be used in the RefEntity compare and merge. 02034 // By Jihong 02035 02036 geom_factor = GeometryQueryTool::get_geometry_factor(); 02037 CubitBoolean status = 02038 refedge_ptr->about_spatially_equal( compare_refedge_ptr, 02039 geom_factor, 02040 (CubitSense*)NULL, 02041 CUBIT_TRUE ); 02042 if( status == CUBIT_FALSE ) 02043 continue; 02044 02045 // If we are in this block, we want to merge the 02046 // two entities. If they do not merge, there was 02047 // an error somewhere. 02048 02049 //First test to see if all the children of these 02050 // refedges are mergeable 02051 if( !compare_refedge_ptr->children_mergeable() ) 02052 { 02053 PRINT_WARNING( "Cannot merge curve %d and %d\n" 02054 " Make sure all merge flags are on.\n", 02055 refedge_ptr->id(), compare_refedge_ptr->id() ); 02056 continue; 02057 } 02058 02059 /* 02060 //refuse to merge free edges 02061 if( refedge_ptr->ref_volume() == NULL ) 02062 { 02063 PRINT_WARNING("Merging of free curves prohibited: Curve %d\n", refedge_ptr->id() ); 02064 continue; 02065 } 02066 02067 if( compare_refedge_ptr->ref_volume() == NULL ) 02068 { 02069 PRINT_WARNING("Merging of free curves prohibited: Curve %d\n", compare_refedge_ptr->id() ); 02070 continue; 02071 } */ 02072 02073 // Always retain the entity with the lowest id. 02074 int nullify = compare_refedge_ptr->marked(); 02075 if( refedge_ptr->id() > compare_refedge_ptr->id() ) 02076 { 02077 std::swap(refedge_ptr, compare_refedge_ptr); 02078 nullify = i; 02079 } 02080 if (groupResults ) 02081 { 02082 edges_merged.append(refedge_ptr); 02083 } 02084 02085 // Now check if merge is okay with all assistants. 02086 CubitBoolean assistant_says_no = CUBIT_FALSE; 02087 for( int k = assistant_list_.size(); k > 0; k-- ) 02088 { 02089 if( ! assistant_list_.get_and_step() 02090 ->can_merge( refedge_ptr, compare_refedge_ptr ) ) 02091 { 02092 assistant_says_no = CUBIT_TRUE; 02093 break; 02094 } 02095 } 02096 if( assistant_says_no ) 02097 continue; 02098 02099 // Need to retain these so that the pointers are not 02100 // accessed after a merge operation when the 'deleted' 02101 // pointer may be invalid. 02102 int retained_id = refedge_ptr->id(); 02103 int deleted_id = compare_refedge_ptr->id(); 02104 02105 PRINT_DEBUG_19( "Consolidating RefEdge %d and " 02106 "%d...\n", retained_id, deleted_id ); 02107 02108 a_tree.remove(compare_refedge_ptr); 02109 if( merge_BTE( refedge_ptr, compare_refedge_ptr ) ) 02110 { 02111 merge_count++; 02112 if (print_info && !progress) 02113 PRINT_INFO( "Curve %d and %d consolidated\n", 02114 retained_id, deleted_id ); 02115 02116 // The 'deleted' RefEdge is now gone. It is an 02117 // error to access that pointer, so we need to 02118 // get it out of the list. 02119 refedge_array[nullify] = NULL; 02120 } 02121 else 02122 { 02123 failed_merges.insert( std::make_pair(compare_refedge_ptr, refedge_ptr) ); 02124 PRINT_DEBUG_19("Failed to merge Curve %d and %d\n", 02125 retained_id, deleted_id); 02126 a_tree.add(compare_refedge_ptr); 02127 } 02128 02129 if (nullify == i) 02130 break; 02131 02132 } 02133 } 02134 02135 //clean the marks. 02136 for( i = 0; i < array_size; i++ ) 02137 { 02138 if ( refedge_array[i] != NULL ) 02139 refedge_array[i]->marked(0); 02140 } 02141 complete_merge(); 02142 if (progress) 02143 progress->end(); 02144 CpuTimer time_to_destroy; 02145 02146 PRINT_DEBUG_3( "Time to destroy r_tree %f secs.\n", 02147 time_to_destroy.cpu_secs()); 02148 02149 // Remove the crud that accumulated during the merge 02150 // operations, from the geometry database. 02151 PRINT_DEBUG_3( "Merge RefEdge time: %f secs\n", 02152 timer.cpu_secs() ); 02153 02154 PRINT_DEBUG_19("Cleaning out TDCompare data from RefEdges...\n"); 02155 if ( groupResults && edges_merged.size() ) 02156 { 02157 DLIList<RefEntity*> refentity_list; 02158 RefEdge *tmp_edge; 02159 for (int iii = edges_merged.size(); iii > 0; iii-- ) 02160 { 02161 tmp_edge = edges_merged.get_and_step(); 02162 if ( !tmp_edge->deactivated() ) 02163 refentity_list.append(tmp_edge); 02164 } 02165 RefGroup *new_group = RefEntityFactory::instance()->construct_RefGroup("gr_curvs_merged"); 02166 new_group->add_ref_entity( refentity_list ); 02167 if (print_info) PRINT_INFO("Created new group %s (Group %d)\n" 02168 " Group contains curves that were merged during\n" 02169 " current merge operation\n", 02170 new_group->entity_name().c_str(), 02171 new_group->id()); 02172 lastCurvsMerged = new_group; 02173 } 02174 else 02175 lastCurvsMerged = NULL; 02176 02177 if( destroyDeadGeometry ) 02178 GeometryQueryTool::instance()->cleanout_deactivated_geometry(); 02179 02180 PRINT_DEBUG_3( "cleanout time: %f secs\n", timer.cpu_secs() ); 02181 if (print_info) 02182 { 02183 PRINT_INFO( "Consolidated %d pair", merge_count); 02184 if(merge_count > 1) 02185 PRINT_INFO("s"); 02186 PRINT_INFO( " of curves \n"); 02187 } 02188 if( AppUtil::instance()->interrupt() ) 02189 { 02190 PRINT_WARNING("Curve merging aborted.\n"); 02191 return CUBIT_FAILURE; 02192 } 02193 02194 return CUBIT_SUCCESS; 02195 } 02196 02197 02198 CubitStatus MergeTool::old_merge_refedges( DLIList<RefEdge*>& refedge_list, 02199 CubitBoolean should_clean_out, 02200 CubitBoolean print_info) 02201 { 02202 // The basic algorithm is to step through the input list, 02203 // compare every entity with every other entity, and 02204 // merge the entities that are spatially equivalent. 02205 // In the merge, the entity with the lowest ID is retained. 02206 // NOTE: RefEdges can participate in multiple merges. 02207 int merge_count = 0; 02208 CpuTimer timer; 02209 DLIList<RefEdge*> refedge_array( refedge_list.size() ); 02210 refedge_list.reset(); 02211 02212 // Remove entities that should not be automatically merged 02213 int i = 0; 02214 for( i = refedge_list.size(); i > 0; i-- ) 02215 { 02216 RefEdge *curr_edge = refedge_list.get_and_step(); 02217 if( curr_edge->is_mergeable() ) 02218 refedge_array.append( curr_edge ); 02219 } 02220 DLIList<RefEdge*> edges_merged; 02221 02222 02223 ProgressTool* progress = 0; 02224 //if( displayProgress ) 02225 //{ 02226 // progress = AppUtil::instance()->progress_tool(); 02227 // if (progress) 02228 // { 02229 // progress->start( 0, refedge_array.size(), "Comparing Curves:", 02230 // 0, CUBIT_TRUE, CUBIT_TRUE ); 02231 // } 02232 //} 02233 02234 // Now find overlapping Refedges and merge them. 02235 // Make sure that the operation is not performed 02236 // on Refedges that are deactivated. 02237 int j = 0; 02238 RefEdge* refedge_ptr = NULL; 02239 RefEdge* compare_refedge_ptr = NULL; 02240 int array_size = refedge_array.size(); 02241 for( i = 0; (i < array_size) && !AppUtil::instance()->interrupt(); i++ ) 02242 { 02243 if( progress ) progress->step(); 02244 02245 refedge_ptr = refedge_array[i]; 02246 if( refedge_ptr == NULL ) 02247 continue; 02248 02249 // There is not need to compare if the first RefEdge is 02250 // dactivated. 02251 if ( refedge_ptr->deactivated() == CUBIT_TRUE ) 02252 continue ; 02253 02254 // // Get the GeometryQueryEngine of the Refedges 02255 // // Try to merge this RefEdge only if it is associated 02256 // // with a SolidModelingEngine. 02257 // GeometryQueryEngine* firstGMEPtr = 02258 // refedge_ptr->get_geometry_query_engine(); 02259 // SolidModelingEngine* SMEPtr = CAST_TO( firstGMEPtr, SolidModelingEngine ); 02260 02261 // // If the RefEdge is not associated with a 02262 // // SolidModelingEngine, go on to the next RefEdge. 02263 // if ( SMEPtr == NULL ) 02264 // continue ; 02265 02266 for( j = i+1; (j < array_size) && !AppUtil::instance()->interrupt(); j++ ) 02267 { 02268 compare_refedge_ptr = refedge_array[j]; 02269 if( compare_refedge_ptr == NULL ) 02270 continue; 02271 02272 // Make sure we are not comparing the same entity 02273 // and that they are not deactivated. 02274 if( ( refedge_ptr == compare_refedge_ptr ) || 02275 ( compare_refedge_ptr->deactivated() == CUBIT_TRUE ) ) 02276 continue; 02277 02278 // // Get the GeometryQueryEngine of the second RefEdge. 02279 // // Make sure that both engines are same before proceeding 02280 // // with the merge. 02281 // GeometryQueryEngine* secondGMEPtr = 02282 // compare_refedge_ptr->get_geometry_query_engine() ; 02283 02284 // // If the two engines are different, move on to the 02285 // // next RefEdge. 02286 // if( firstGMEPtr != secondGMEPtr ) 02287 // continue; 02288 02289 // IMPORTANT: this compare is for merging, so we set the 02290 // last parameter to CUBIT_TRUE so that the 02291 // compare sets the TDCompare data which will 02292 // be used in the RefEntity compare and merge. 02293 // By Jihong 02294 02295 double geom_factor = GeometryQueryTool::get_geometry_factor(); 02296 CubitBoolean status = 02297 refedge_ptr->about_spatially_equal(compare_refedge_ptr, 02298 geom_factor, 02299 (CubitSense*)NULL, 02300 CUBIT_TRUE ); 02301 if( status == CUBIT_FALSE ) 02302 continue; 02303 02304 //Make sure the children of the refedges are mergeable 02305 if( !refedge_ptr->children_mergeable() ) 02306 { 02307 PRINT_WARNING( "Cannot merge curves %d and %d\n" 02308 " Make sure merge flags are on\n", 02309 refedge_ptr->id(), compare_refedge_ptr->id() ); 02310 continue; 02311 } 02312 02313 //Now let us test to see if we are merging two edges that 02314 //belong to the same face 02315 DLIList<RefFace*> ref_faces_1, ref_faces_2; 02316 refedge_ptr->ref_faces( ref_faces_1 ); 02317 compare_refedge_ptr->ref_faces( ref_faces_2 ); 02318 ref_faces_2.intersect( ref_faces_1 ); 02319 if( ref_faces_2.size() > 0 ) 02320 { 02321 PRINT_DEBUG_19( "Tolerance problems, trying to merge" 02322 " curves\non the same surface.\n" 02323 "%s (curve %d) and %s (curve %d) on\n" 02324 "%s (surface %d)\n", 02325 refedge_ptr->entity_name().c_str(), 02326 refedge_ptr->id(), 02327 compare_refedge_ptr->entity_name().c_str(), 02328 compare_refedge_ptr->id(), 02329 ref_faces_2.get()->entity_name().c_str(), 02330 ref_faces_2.get()->id() ); 02331 PRINT_DEBUG_19( "Try changing the merge tolerance.\n" ); 02332 continue; 02333 } 02334 // If we are in this block, we want to merge the 02335 // two entities. If they do not merge, there was 02336 // an error somewhere. 02337 02338 // Always retain the entity with the lowest id. 02339 int nullify = j; 02340 if( refedge_ptr->id() > compare_refedge_ptr->id() ) 02341 { 02342 std::swap(refedge_ptr, compare_refedge_ptr); 02343 nullify = i; 02344 } 02345 /* 02346 //refuse to merge free edges 02347 if( refedge_ptr->ref_volume() == NULL ) 02348 { 02349 PRINT_WARNING("Merging of free curves prohibited: Curve %d\n", refedge_ptr->id() ); 02350 continue; 02351 } 02352 02353 if( compare_refedge_ptr->ref_volume() == NULL ) 02354 { 02355 PRINT_WARNING("Merging of free curves prohibited: Curve %d\n", compare_refedge_ptr->id() ); 02356 continue; 02357 } */ 02358 02359 // Now check if merge is okay with all assistants. 02360 CubitBoolean assistant_says_no = CUBIT_FALSE; 02361 for( int k = assistant_list_.size(); k > 0; k-- ) 02362 { 02363 if( ! assistant_list_.get_and_step() 02364 ->can_merge( refedge_ptr, compare_refedge_ptr ) ) 02365 { 02366 assistant_says_no = CUBIT_TRUE; 02367 break; 02368 } 02369 } 02370 if( assistant_says_no ) 02371 continue; 02372 02373 // Need to retain these so that the pointers are not 02374 // accessed after a merge operation when the 'deleted' 02375 // pointer may be invalid. 02376 int retained_id = refedge_ptr->id(); 02377 int deleted_id = compare_refedge_ptr->id(); 02378 if ( groupResults ) 02379 { 02380 edges_merged.append(refedge_ptr); 02381 } 02382 if( merge_BTE( refedge_ptr, compare_refedge_ptr ) ) 02383 { 02384 merge_count++; 02385 if (print_info && !progress) 02386 PRINT_INFO( "Curve %d and %d consolidated\n", 02387 retained_id, deleted_id); 02388 02389 // The 'deleted' RefEdge is now gone. It is an 02390 // error to access that pointer, so we need to 02391 // get it out of the list. 02392 refedge_array[nullify] = NULL; 02393 } 02394 else 02395 { 02396 PRINT_ERROR( "Failed to merge Curve %d and %d\n", 02397 retained_id, deleted_id); 02398 PRINT_INFO("Check for sliver geometry in the vicinity\n"); 02399 } 02400 02401 if (nullify == i) 02402 break; 02403 } 02404 } 02405 02406 // Remove the crud that accumulated during the 02407 // merge operations, from the geometry database. 02408 PRINT_DEBUG_3( "Merge RefEdges time: %f secs\n", 02409 timer.cpu_secs() ); 02410 02411 PRINT_DEBUG_19( 02412 "Cleaning out TDCompare data from RefEdges...\n" ); 02413 complete_merge(); 02414 if (progress) 02415 progress->end(); 02416 02417 if ( groupResults && edges_merged.size() ) 02418 { 02419 DLIList<RefEntity*> refentity_list; 02420 RefEdge *tmp_edge; 02421 for (int iii = edges_merged.size(); iii > 0; iii-- ) 02422 { 02423 tmp_edge = edges_merged.get_and_step(); 02424 if ( !tmp_edge->deactivated() ) 02425 refentity_list.append(tmp_edge); 02426 } 02427 RefGroup *new_group = RefEntityFactory::instance()->construct_RefGroup("gr_curvs_merged"); 02428 new_group->add_ref_entity( refentity_list ); 02429 if (print_info) PRINT_INFO("Created new group %s (Group %d)\n" 02430 " Group contains curves that were seperatly merged during\n" 02431 " current merge operation (ie, not during surface merge)\n", 02432 new_group->entity_name().c_str(), 02433 new_group->id()); 02434 lastCurvsMerged = new_group; 02435 } 02436 //set this to null otherwise. 02437 else 02438 lastCurvsMerged = NULL; 02439 02440 if( should_clean_out == CUBIT_TRUE && destroyDeadGeometry ) 02441 { 02442 GeometryQueryTool::instance()->cleanout_deactivated_geometry(); 02443 PRINT_DEBUG_3( "cleanout time: %f secs\n", 02444 timer.cpu_secs() ); 02445 } 02446 02447 if(print_info) 02448 PRINT_INFO( "Consolidated %d curves\n", merge_count ); 02449 02450 if( AppUtil::instance()->interrupt() ) 02451 { 02452 PRINT_WARNING("Curve merging aborted.\n"); 02453 return CUBIT_FAILURE; 02454 } 02455 02456 return CUBIT_SUCCESS; 02457 } 02458 02459 CubitStatus MergeTool::merge_all_refvertices() 02460 { 02461 // if( !displayProgress ) 02462 PRINT_INFO( "\n...Merging all Vertices in the model\n" ); 02463 02464 // Get the list of all the RefVertices in the model 02465 DLIList<RefVertex*> refvertex_list_model; 02466 GeometryQueryTool::instance()->ref_vertices(refvertex_list_model); 02467 02468 // Merge the RefVerties in this list 02469 if( merge_refvertices( refvertex_list_model ) == CUBIT_FAILURE ) 02470 { 02471 PRINT_ERROR( "Vertex merging failed\n" ); 02472 return CUBIT_FAILURE; 02473 } 02474 02475 return CUBIT_SUCCESS; 02476 } 02477 02478 02479 CubitStatus MergeTool::merge_refvertices( DLIList<RefVertex*>& refvertex_list, 02480 CubitBoolean print_info) 02481 { 02482 if( refvertex_list.size() < 20 ) 02483 return old_merge_refvertices( refvertex_list, print_info ); 02484 02485 CpuTimer timer; 02486 int merge_count = 0; 02487 02488 double geom_factor = GeometryQueryTool::get_geometry_factor(); 02489 RTree<RefVertex*> a_tree(GEOMETRY_RESABS*geom_factor); 02490 DLIList<RefVertex*> refvertex_array( refvertex_list.size() ); 02491 refvertex_list.reset(); 02492 02493 // Remove entities that should not be automatically merged 02494 int i = 0; 02495 for( i = refvertex_list.size(); i > 0; i-- ) 02496 { 02497 RefVertex *curr_vert = refvertex_list.get_and_step(); 02498 if( curr_vert->is_mergeable() ) 02499 { 02500 refvertex_array.append( curr_vert ); 02501 a_tree.add( curr_vert ); 02502 } 02503 } 02504 02505 //initialize the marked flag for fast nulification... 02506 int array_size = refvertex_array.size(); 02507 for ( i = 0; i < array_size; i++) 02508 refvertex_array[i]->marked(i); 02509 02510 DLIList<RefVertex*> vertices_merged; 02511 02512 ProgressTool* progress = 0; 02513 02514 // Now find overlapping RefVertices and merge them. 02515 // Make sure that the operation is not performed on 02516 // RefVertices that are deactivated. 02517 int j = 0; 02518 RefVertex* refvertex_ptr = NULL; 02519 RefVertex* compare_refvertex_ptr = NULL; 02520 for( i = 0; (i < array_size) && !AppUtil::instance()->interrupt(); i++ ) 02521 { 02522 if( progress ) progress->step(); 02523 02524 refvertex_ptr = refvertex_array[i]; 02525 if( refvertex_ptr == NULL ) 02526 continue; 02527 02528 // There is not need to compare if the first RefVertex is 02529 // dactivated. 02530 if( refvertex_ptr->deactivated() == CUBIT_TRUE ) 02531 continue ; 02532 02533 DLIList<RefVertex*> close_verts; 02534 a_tree.find(refvertex_ptr->bounding_box(), close_verts); 02535 02536 for( j = 0; (j < close_verts.size()) && !AppUtil::instance()->interrupt(); j++ ) 02537 { 02538 compare_refvertex_ptr = close_verts.get_and_step(); 02539 02540 //skip vertices already handled 02541 if( refvertex_array[ compare_refvertex_ptr->marked() ] == NULL ) 02542 continue; 02543 02544 if( compare_refvertex_ptr == NULL ) 02545 continue; 02546 02547 // Make sure we are not comparing the same entity 02548 // and that they are not deactivated. 02549 if( ( refvertex_ptr == compare_refvertex_ptr ) || 02550 ( compare_refvertex_ptr->deactivated() == CUBIT_TRUE ) ) 02551 continue; 02552 02553 // IMPORTANT: this compare is for merging, so we set the 02554 // last parameter to CUBIT_TRUE so that the 02555 // compare sets the TDCompare data which will 02556 // be used in the RefEntity compare and merge. 02557 // By Jihong 02558 double geom_factor = GeometryQueryTool::get_geometry_factor(); 02559 CubitBoolean status = 02560 refvertex_ptr->about_spatially_equal( compare_refvertex_ptr, 02561 geom_factor, 02562 CUBIT_TRUE ); 02563 if( status == CUBIT_FALSE ) 02564 continue; 02565 02566 /* //refuse to merge free edges 02567 if( refvertex_ptr->ref_edge() == NULL ) 02568 { 02569 PRINT_WARNING("Merging of free vertices prohibited: Vertex %d\n", refvertex_ptr->id() ); 02570 continue; 02571 } 02572 02573 if( compare_refvertex_ptr->ref_edge() == NULL ) 02574 { 02575 PRINT_WARNING("Merging of free vertices prohibited: Vertex %d\n", compare_refvertex_ptr->id() ); 02576 continue; 02577 } */ 02578 02579 //Make sure we arn't merging two vertices in the same volume. 02580 DLIList<RefVolume*> vols_1, vols_2; 02581 refvertex_ptr->ref_volumes(vols_1); 02582 compare_refvertex_ptr->ref_volumes(vols_2); 02583 vols_2.intersect( vols_1 ); 02584 if( vols_2.size() > 0 ) 02585 { 02586 PRINT_DEBUG_19( "Tolerance problems, trying to merge" 02587 " vertices\non the same volume.\n" 02588 "%s (vertex %d) and %s (vertex %d) on\n" 02589 "%s (volume %d)\n", 02590 refvertex_ptr->entity_name().c_str(), 02591 refvertex_ptr->id(), 02592 compare_refvertex_ptr->entity_name().c_str(), 02593 compare_refvertex_ptr->id(), 02594 vols_2.get()->entity_name().c_str(), 02595 vols_2.get()->id() ); 02596 PRINT_DEBUG_19( "Try changing the merge tolerance.\n" ); 02597 continue; 02598 } 02599 02600 // Always retain the entity with the lowest id. 02601 int nullify = compare_refvertex_ptr->marked(); 02602 if( refvertex_ptr->id() > compare_refvertex_ptr->id() ) 02603 { 02604 std::swap(refvertex_ptr, compare_refvertex_ptr); 02605 nullify = i; 02606 } 02607 02608 // Now check if merge is okay with all assistants. 02609 CubitBoolean assistant_says_no = CUBIT_FALSE; 02610 for( int k = assistant_list_.size(); k > 0; k-- ) 02611 { 02612 if( ! assistant_list_.get_and_step() 02613 ->can_merge( refvertex_ptr, compare_refvertex_ptr ) ) 02614 { 02615 assistant_says_no = CUBIT_TRUE; 02616 break; 02617 } 02618 } 02619 if( assistant_says_no ) 02620 continue; 02621 02622 // Need to retain these so that the pointers are not 02623 // accessed after a merge operation when the 'deleted' 02624 // pointer may be invalid. 02625 int retained_id = refvertex_ptr->id(); 02626 int deleted_id = compare_refvertex_ptr->id(); 02627 if (groupResults) 02628 { 02629 vertices_merged.append(refvertex_ptr); 02630 } 02631 02632 a_tree.remove( compare_refvertex_ptr ); 02633 if( merge_BTE( refvertex_ptr, compare_refvertex_ptr ) ) 02634 { 02635 merge_count++; 02636 if(print_info && !progress) 02637 PRINT_INFO( "Vertex %d and %d consolidated\n", 02638 retained_id, deleted_id); 02639 02640 // The 'deleted' RefVertex is now gone. It is an 02641 // error to access that pointer, so we need to 02642 // get it out of the list. 02643 refvertex_array[nullify] = NULL; 02644 } 02645 else 02646 { 02647 PRINT_ERROR("Failed to merge Vertex %d and %d\n", 02648 retained_id, deleted_id ); 02649 PRINT_INFO("Check for sliver geometry in the vicinity\n"); 02650 a_tree.add( compare_refvertex_ptr ); 02651 } 02652 if( nullify == i ) 02653 break; 02654 } 02655 } 02656 02657 //clean the marks. 02658 for( i = 0; i < array_size; i++ ) 02659 { 02660 if ( refvertex_array[i] != NULL ) 02661 refvertex_array[i]->marked(0); 02662 } 02663 02664 // Remove the crud that accumulated during the merge 02665 // operations, from the geometry database. 02666 PRINT_DEBUG_3( "Merge RefVertexs time: %f secs\n", 02667 timer.cpu_secs() ); 02668 02669 PRINT_DEBUG_19( "Cleaning out TDCompare data from RefVertices...\n"); 02670 complete_merge(); 02671 if(progress) 02672 progress->end(); 02673 02674 if ( groupResults && vertices_merged.size() ) 02675 { 02676 DLIList<RefEntity*> refentity_list; 02677 RefVertex *tmp_vertex; 02678 for (int iii = vertices_merged.size(); iii > 0; iii-- ) 02679 { 02680 tmp_vertex = vertices_merged.get_and_step(); 02681 if ( !tmp_vertex->deactivated() ) 02682 refentity_list.append(tmp_vertex); 02683 } 02684 RefGroup *new_group = RefEntityFactory::instance()->construct_RefGroup("gr_verts_merged"); 02685 new_group->add_ref_entity( refentity_list ); 02686 if (print_info) PRINT_INFO("Created new group %s (Group %d)\n" 02687 " Group contains curves that were seperatly merged during\n" 02688 " current merge operation (ie, not during surface merge)\n", 02689 new_group->entity_name().c_str(), 02690 new_group->id()); 02691 lastVertsMerged = new_group; 02692 } 02693 //set this to null otherwise. 02694 else 02695 lastVertsMerged = NULL; 02696 02697 if( destroyDeadGeometry ) 02698 GeometryQueryTool::instance()->cleanout_deactivated_geometry(); 02699 PRINT_DEBUG_3( "cleanout time: %f secs\n", 02700 timer.cpu_secs() ); 02701 02702 if (print_info) PRINT_INFO( "Consolidated %d pairs of vertices\n", merge_count ); 02703 if( AppUtil::instance()->interrupt() ) 02704 { 02705 PRINT_WARNING("Vertex merging aborted.\n"); 02706 return CUBIT_FAILURE; 02707 } 02708 return CUBIT_SUCCESS; 02709 } 02710 02711 //---------------------------------------------------------------- 02712 // Purpose : merge all items in the RefVertex list if 02713 // they can be merged. 02714 // 02715 // Special Notes : 02716 // 02717 // Creator : Jihong Ma 02718 // 02719 // Creation Date : 11/27/96 02720 //---------------------------------------------------------------- 02721 CubitStatus MergeTool::old_merge_refvertices( DLIList<RefVertex*>& refvertex_list, 02722 CubitBoolean print_info) 02723 { 02724 // The basic algorithm is to step through the input list, 02725 // compare every entity with every other entity, and 02726 // merge the entities that are spatially equivalent. 02727 // In the merge, the entity with the lowest ID is retained. 02728 // NOTE: RefVertices can participate in multiple merges. 02729 02730 CpuTimer timer; 02731 int merge_count = 0; 02732 02733 DLIList<RefVertex*> refvertex_array( refvertex_list.size() ); 02734 refvertex_list.reset(); 02735 02736 // Remove entities that should not be automatically merged 02737 int i = 0; 02738 for( i = refvertex_list.size(); i > 0; i-- ) 02739 { 02740 RefVertex *curr_vert = refvertex_list.get_and_step(); 02741 if( curr_vert->is_mergeable() ) 02742 refvertex_array.append( curr_vert ); 02743 } 02744 DLIList<RefVertex*> vertices_merged; 02745 02746 ProgressTool* progress = 0; 02747 // if( displayProgress ) 02748 // { 02749 // progress = AppUtil::instance()->progress_tool(); 02750 // if (progress) 02751 // { 02752 // progress->start( 0, refvertex_array.size(), 02753 // "Comparing Vertices:", 0, CUBIT_TRUE, CUBIT_TRUE ); 02754 // } 02755 // } 02756 02757 // Now find overlapping RefVertices and merge them. 02758 // Make sure that the operation is not performed on 02759 // RefVertices that are deactivated. 02760 int j = 0; 02761 RefVertex* refvertex_ptr = NULL; 02762 RefVertex* compare_refvertex_ptr = NULL; 02763 int array_size = refvertex_array.size(); 02764 for( i = 0; (i < array_size) && !AppUtil::instance()->interrupt(); i++ ) 02765 { 02766 if( progress ) progress->step(); 02767 02768 refvertex_ptr = refvertex_array[i]; 02769 if( refvertex_ptr == NULL ) 02770 continue; 02771 02772 // There is not need to compare if the first RefVertex is 02773 // dactivated. 02774 if( refvertex_ptr->deactivated() == CUBIT_TRUE ) 02775 continue ; 02776 02777 // // Get the GeometryQueryEngine of the Refedges 02778 // // Try to merge this RefVertex only if it is associated 02779 // // with a SolidModelingEngine. 02780 // GeometryQueryEngine* firstGMEPtr = 02781 // refvertex_ptr->get_geometry_query_engine(); 02782 // SolidModelingEngine* SMEPtr = CAST_TO( firstGMEPtr, SolidModelingEngine ); 02783 02784 // // If the RefVertex is not associated with a 02785 // // SolidModelingEngine, go on to the next RefVertex. 02786 // if( SMEPtr == NULL ) 02787 // continue ; 02788 02789 for( j = i+1; (j < array_size) && !AppUtil::instance()->interrupt(); j++ ) 02790 { 02791 compare_refvertex_ptr = refvertex_array[j]; 02792 if( compare_refvertex_ptr == NULL ) 02793 continue; 02794 02795 // Make sure we are not comparing the same entity 02796 // and that they are not deactivated. 02797 if( ( refvertex_ptr == compare_refvertex_ptr ) || 02798 ( compare_refvertex_ptr->deactivated() == CUBIT_TRUE ) ) 02799 continue; 02800 02801 // // Get the GeometryQueryEngine of the second 02802 // // RefVertex. Make sure that both engines are same 02803 // // before proceeding with the merge. 02804 // GeometryQueryEngine* secondGMEPtr = 02805 // compare_refvertex_ptr->get_geometry_query_engine() ; 02806 02807 // // If the two engines are different, move on to the 02808 // // next RefVertex. 02809 // if( firstGMEPtr != secondGMEPtr ) 02810 // continue ; 02811 02812 // IMPORTANT: this compare is for merging, so we set the 02813 // last parameter to CUBIT_TRUE so that the 02814 // compare sets the TDCompare data which will 02815 // be used in the RefEntity compare and merge. 02816 // By Jihong 02817 double geom_factor = GeometryQueryTool::get_geometry_factor(); 02818 CubitBoolean status = 02819 refvertex_ptr->about_spatially_equal( compare_refvertex_ptr, 02820 geom_factor, 02821 CUBIT_TRUE ); 02822 if( status == CUBIT_FALSE ) 02823 continue; 02824 /* 02825 //refuse to merge free edges 02826 if( refvertex_ptr->ref_edge() == NULL ) 02827 { 02828 PRINT_WARNING("Merging of free vertices prohibited: Vertex %d\n", refvertex_ptr->id() ); 02829 continue; 02830 } 02831 02832 if( compare_refvertex_ptr->ref_edge() == NULL ) 02833 { 02834 PRINT_WARNING("Merging of free vertices prohibited: Vertex %d\n", compare_refvertex_ptr->id() ); 02835 continue; 02836 } 02837 */ 02838 //Make sure we arn't merging two vertices on a that are in the same volume. 02839 DLIList<RefVolume*> vols_1, vols_2; 02840 refvertex_ptr->ref_volumes(vols_1); 02841 compare_refvertex_ptr->ref_volumes(vols_2); 02842 vols_2.intersect( vols_1 ); 02843 if( vols_2.size() > 0 ) 02844 { 02845 PRINT_DEBUG_19( "Tolerance problems, trying to merge" 02846 " vertices\non the same volume.\n" 02847 "%s (vertex %d) and %s (vertex %d) on\n" 02848 "%s (volume %d)\n", 02849 refvertex_ptr->entity_name().c_str(), 02850 refvertex_ptr->id(), 02851 compare_refvertex_ptr->entity_name().c_str(), 02852 compare_refvertex_ptr->id(), 02853 vols_2.get()->entity_name().c_str(), 02854 vols_2.get()->id() ); 02855 PRINT_DEBUG_19( "Try changing the merge tolerance.\n" ); 02856 continue; 02857 } 02858 02859 // Always retain the entity with the lowest id. 02860 int nullify = j; 02861 if( refvertex_ptr->id() > compare_refvertex_ptr->id() ) 02862 { 02863 std::swap(refvertex_ptr, compare_refvertex_ptr); 02864 nullify = i; 02865 } 02866 02867 // Now check if merge is okay with all assistants. 02868 CubitBoolean assistant_says_no = CUBIT_FALSE; 02869 for( int k = assistant_list_.size(); k > 0; k-- ) 02870 { 02871 if( ! assistant_list_.get_and_step() 02872 ->can_merge( refvertex_ptr, compare_refvertex_ptr ) ) 02873 { 02874 assistant_says_no = CUBIT_TRUE; 02875 break; 02876 } 02877 } 02878 if( assistant_says_no ) 02879 continue; 02880 02881 // Need to retain these so that the pointers are not 02882 // accessed after a merge operation when the 'deleted' 02883 // pointer may be invalid. 02884 int retained_id = refvertex_ptr->id(); 02885 int deleted_id = compare_refvertex_ptr->id(); 02886 if (groupResults) 02887 { 02888 vertices_merged.append(refvertex_ptr); 02889 } 02890 if( merge_BTE( refvertex_ptr, compare_refvertex_ptr ) ) 02891 { 02892 merge_count++; 02893 if (print_info && !progress) 02894 { 02895 PRINT_INFO("Failed to merge Vertex %d and %d\n", 02896 retained_id, deleted_id); 02897 PRINT_INFO("Check for sliver geometry in the vicinity\n"); 02898 } 02899 02900 // The 'deleted' RefVertex is now gone. It is an 02901 // error to access that pointer, so we need to 02902 // get it out of the list. 02903 refvertex_array[nullify] = NULL; 02904 } 02905 else 02906 { 02907 PRINT_ERROR("Failed to merge Vertex %d and %d\n", 02908 retained_id, deleted_id ); 02909 } 02910 02911 if( nullify == i ) 02912 break; 02913 } 02914 } 02915 02916 // Remove the crud that accumulated during the merge 02917 // operations, from the geometry database. 02918 PRINT_DEBUG_3( "Merge RefVertexs time: %f secs\n", 02919 timer.cpu_secs() ); 02920 02921 PRINT_DEBUG_19( 02922 "Cleaning out TDCompare data from RefVertices...\n"); 02923 complete_merge(); 02924 if (progress) 02925 progress->end(); 02926 if ( groupResults && vertices_merged.size() ) 02927 { 02928 DLIList<RefEntity*> refentity_list; 02929 RefVertex *tmp_vertex; 02930 for (int iii = vertices_merged.size(); iii > 0; iii-- ) 02931 { 02932 tmp_vertex = vertices_merged.get_and_step(); 02933 if ( !tmp_vertex->deactivated() ) 02934 refentity_list.append(tmp_vertex); 02935 } 02936 RefGroup *new_group = RefEntityFactory::instance()->construct_RefGroup("gr_verts_merged"); 02937 new_group->add_ref_entity( refentity_list ); 02938 if (print_info) PRINT_INFO("Created new group %s (Group %d)\n" 02939 " Group contains curves that were seperatly merged during\n" 02940 " current merge operation (ie, not during surface merge)\n", 02941 new_group->entity_name().c_str(), 02942 new_group->id()); 02943 lastVertsMerged = new_group; 02944 } 02945 //set this to null otherwise. 02946 else 02947 lastVertsMerged = NULL; 02948 02949 if( destroyDeadGeometry ) 02950 GeometryQueryTool::instance()->cleanout_deactivated_geometry(); 02951 PRINT_DEBUG_3( "cleanout time: %f secs\n", 02952 timer.cpu_secs() ); 02953 02954 if(print_info) 02955 PRINT_INFO( "Consolidated %d pairs of vertices\n", merge_count ); 02956 02957 if( AppUtil::instance()->interrupt() ) 02958 { 02959 PRINT_WARNING("Vertex merging aborted.\n"); 02960 return CUBIT_FAILURE; 02961 } 02962 return CUBIT_SUCCESS; 02963 } 02964 02965 02966 //------------------------------------------------------------------------- 02967 // Purpose : Unmerge everything 02968 // 02969 // Special Notes : 02970 // 02971 // Creator : Jason Kraftcheck 02972 // 02973 // Creation Date : 03/27/01 02974 //------------------------------------------------------------------------- 02975 CubitStatus MergeTool::unmerge_all() 02976 { 02977 int i; 02978 CubitStatus result = CUBIT_SUCCESS; 02979 CubitBoolean top = start_unmerge(); 02980 02981 02982 DLIList<RefFace*> face_list; 02983 DLIList<RefEdge*> edge_list; 02984 DLIList<RefVertex*> vtx_list; 02985 02986 GeometryQueryTool::instance()->ref_faces( face_list ); 02987 GeometryQueryTool::instance()->ref_edges( edge_list ); 02988 GeometryQueryTool::instance()->ref_vertices( vtx_list ); 02989 02990 for( i = face_list.size(); (i > 0) && !AppUtil::instance()->interrupt(); i-- ) 02991 if( ! unmerge(face_list.get_and_step(),CUBIT_FALSE) ) 02992 result = CUBIT_FAILURE; 02993 02994 for( i = edge_list.size(); (i > 0) && !AppUtil::instance()->interrupt(); i-- ) 02995 if( ! unmerge(edge_list.get_and_step(),CUBIT_FALSE) ) 02996 result = CUBIT_FAILURE; 02997 02998 for( i = vtx_list.size(); (i > 0) && !AppUtil::instance()->interrupt(); i-- ) 02999 if( ! unmerge(vtx_list.get_and_step()) ) 03000 result = CUBIT_FAILURE; 03001 03002 end_unmerge(top); 03003 03004 return result; 03005 } 03006 03007 03008 //------------------------------------------------------------------------- 03009 // Purpose : Unmerge RefEntities 03010 // 03011 // Special Notes : 03012 // 03013 // Creator : Jason Kraftcheck 03014 // 03015 // Creation Date : 01/18/01 03016 //------------------------------------------------------------------------- 03017 CubitStatus MergeTool::unmerge( DLIList<RefEntity*> &entity_list, 03018 CubitBoolean descend ) 03019 { 03020 CubitBoolean top = start_unmerge(); 03021 03022 for( int i = entity_list.size(); (i > 0) && !AppUtil::instance()->interrupt(); i-- ) 03023 unmerge( entity_list.get_and_step(), descend ); 03024 03025 end_unmerge(top); 03026 return CUBIT_SUCCESS; 03027 } 03028 03029 //------------------------------------------------------------------------- 03030 // Purpose : Unmerge a RefEntity 03031 // 03032 // Special Notes : All parents must be unmerged. 03033 // 03034 // Creator : Jason Kraftcheck 03035 // 03036 // Creation Date : 01/18/01 03037 //------------------------------------------------------------------------- 03038 CubitStatus MergeTool::unmerge( RefEntity* entity_ptr, CubitBoolean descend ) 03039 { 03040 if( CAST_TO( entity_ptr, Body ) ) 03041 return descend ? unmerge(CAST_TO(entity_ptr,Body)) : CUBIT_FAILURE; 03042 else if( CAST_TO( entity_ptr, RefVolume ) ) 03043 return descend ? unmerge(CAST_TO(entity_ptr,RefVolume)) : CUBIT_FAILURE; 03044 else if( CAST_TO( entity_ptr, RefFace ) ) 03045 return unmerge( CAST_TO(entity_ptr,RefFace), descend ); 03046 else if( CAST_TO( entity_ptr, RefEdge ) ) 03047 return unmerge( CAST_TO(entity_ptr,RefEdge), descend ); 03048 else if( CAST_TO( entity_ptr, RefVertex ) ) 03049 return unmerge( CAST_TO(entity_ptr,RefVertex) ); 03050 else 03051 { 03052 PRINT_ERROR("Bad Entity \"%s\" in " 03053 "MergeTool::unmerge(RefEntity*,CubitBoolean)\n", 03054 entity_ptr->class_name()); 03055 return CUBIT_FAILURE; 03056 } 03057 } 03058 03059 //------------------------------------------------------------------------- 03060 // Purpose : Unmerge 03061 // 03062 // Special Notes : 03063 // 03064 // Creator : Jason Kraftcheck 03065 // 03066 // Creation Date : 06/01/04 03067 //------------------------------------------------------------------------- 03068 CubitStatus MergeTool::unmerge( Body* body_ptr ) 03069 { 03070 DLIList<Body*> list(1); 03071 list.append( body_ptr ); 03072 return separate_bodies( list ); 03073 } 03074 03075 //------------------------------------------------------------------------- 03076 // Purpose : Unmerge 03077 // 03078 // Special Notes : 03079 // 03080 // Creator : Jason Kraftcheck 03081 // 03082 // Creation Date : 06/01/04 03083 //------------------------------------------------------------------------- 03084 CubitStatus MergeTool::unmerge( RefVolume* vol_ptr ) 03085 { 03086 DLIList<RefVolume*> list(1); 03087 list.append( vol_ptr ); 03088 return separate_volumes( list ); 03089 } 03090 03091 //------------------------------------------------------------------------- 03092 // Purpose : Unmerge 03093 // 03094 // Special Notes : 03095 // 03096 // Creator : Jason Kraftcheck 03097 // 03098 // Creation Date : 06/01/04 03099 //------------------------------------------------------------------------- 03100 CubitStatus MergeTool::unmerge( RefFace* face_ptr, CubitBoolean descend, 03101 DLIList<RefFace*> *new_faces) 03102 { 03103 CubitBoolean top = start_unmerge(); 03104 CubitStatus result = CUBIT_SUCCESS; 03105 int i; 03106 03107 DLIList<TopologyBridge*> bridge_list; 03108 face_ptr->bridge_manager()->get_bridge_list(bridge_list); 03109 if (bridge_list.size() < 2) 03110 return CUBIT_SUCCESS; 03111 03112 DLIList<Surface*> surf_list; 03113 bridge_list.reset(); 03114 for (i = bridge_list.size(); i > 1; i--) 03115 { 03116 Surface* surf = dynamic_cast<Surface*>(bridge_list.step_and_get()); 03117 surf_list.clean_out(); 03118 surf_list.append( surf ); 03119 RefFace *new_face = separate_face( surf_list, descend ); 03120 03121 if (0 == new_face) 03122 { 03123 result = CUBIT_FAILURE; 03124 break; 03125 } 03126 else 03127 { 03128 if(new_faces) 03129 new_faces->append(new_face); 03130 } 03131 } 03132 03133 end_unmerge(top); 03134 return result; 03135 } 03136 03137 03138 //------------------------------------------------------------------------- 03139 // Purpose : Unmerge 03140 // 03141 // Special Notes : 03142 // 03143 // Creator : Jason Kraftcheck 03144 // 03145 // Creation Date : 06/01/04 03146 //------------------------------------------------------------------------- 03147 CubitStatus MergeTool::unmerge( RefEdge* edge_ptr, CubitBoolean descend, 03148 DLIList<RefEdge*> *new_curves) 03149 { 03150 CubitBoolean top = start_unmerge(); 03151 CubitStatus result = CUBIT_SUCCESS; 03152 int i; 03153 03154 DLIList<TopologyBridge*> bridge_list; 03155 edge_ptr->bridge_manager()->get_bridge_list(bridge_list); 03156 if (bridge_list.size() < 2) 03157 return CUBIT_SUCCESS; 03158 03159 DLIList<Curve*> curve_list; 03160 bridge_list.reset(); 03161 for (i = bridge_list.size(); i > 1; i--) 03162 { 03163 Curve* curve = dynamic_cast<Curve*>(bridge_list.step_and_get()); 03164 curve_list.clean_out(); 03165 curve_list.append( curve ); 03166 RefEdge *new_curve = separate_edge( curve_list, descend ); 03167 if (0 == new_curve) 03168 { 03169 result = CUBIT_FAILURE; 03170 break; 03171 } 03172 else 03173 { 03174 if(new_curves) 03175 new_curves->append(new_curve); 03176 } 03177 } 03178 03179 end_unmerge(top); 03180 return result; 03181 } 03182 03183 03184 //------------------------------------------------------------------------- 03185 // Purpose : Unmerge 03186 // 03187 // Special Notes : 03188 // 03189 // Creator : Jason Kraftcheck 03190 // 03191 // Creation Date : 06/01/04 03192 //------------------------------------------------------------------------- 03193 CubitStatus MergeTool::unmerge( RefVertex* vtx_ptr, DLIList<RefVertex*> *new_verts ) 03194 { 03195 CubitBoolean top = start_unmerge(); 03196 CubitStatus result = CUBIT_SUCCESS; 03197 int i; 03198 03199 DLIList<TopologyBridge*> bridge_list; 03200 vtx_ptr->bridge_manager()->get_bridge_list(bridge_list); 03201 if (bridge_list.size() < 2) 03202 return CUBIT_SUCCESS; 03203 03204 DLIList<TBPoint*> point_list; 03205 bridge_list.reset(); 03206 for (i = bridge_list.size(); i > 1; i--) 03207 { 03208 TBPoint* point = dynamic_cast<TBPoint*>(bridge_list.step_and_get()); 03209 point_list.clean_out(); 03210 point_list.append( point ); 03211 RefVertex *new_vert = separate_vertex( point_list ); 03212 if(0 == new_vert) 03213 { 03214 result = CUBIT_FAILURE; 03215 break; 03216 } 03217 else 03218 { 03219 if(new_verts) 03220 new_verts->append(new_vert); 03221 } 03222 } 03223 03224 end_unmerge(top); 03225 return result; 03226 } 03227 03228 03229 03230 03231 03232 //------------------------------------------------------------------------- 03233 // Purpose : Handle sending various events as a result of unmerging. 03234 // 03235 // Special Notes : 03236 // 03237 // Creator : Jason Kraftcheck 03238 // 03239 // Creation Date : 01/18/01 03240 //------------------------------------------------------------------------- 03241 void MergeTool::cleanup_unmerge() 03242 { 03243 std::set<CubitObservable*> modified_list, new_list; 03244 int i; 03245 // CpuTimer timer; 03246 int vtx_count = 0, curve_count = 0, surf_count = 0; 03247 03248 DLIList<RefEntity*> parents; 03249 assert( new_unmerged.size() == old_unmerged.size() ); 03250 new_unmerged.reset(); 03251 old_unmerged.reset(); 03252 for (i = new_unmerged.size(); i--; ) 03253 { 03254 RefEntity* new_ptr = new_unmerged.get_and_step(); 03255 RefEntity* old_ptr = old_unmerged.get_and_step(); 03256 if (dynamic_cast<RefVertex*>(new_ptr)) 03257 vtx_count++; 03258 else if(dynamic_cast<RefEdge*>(new_ptr)) 03259 curve_count++; 03260 if (dynamic_cast<RefFace*>(new_ptr)) 03261 surf_count++; 03262 03263 03264 new_ptr->get_parent_ref_entities( parents ); 03265 03266 if (parents.size() == 0) 03267 { 03268 if (new_list.insert(new_ptr).second) 03269 { 03270 AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::FREE_REF_ENTITY_GENERATED, new_ptr)); 03271 CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_CREATED, new_ptr); 03272 GeometryQueryTool::instance()->history().add_event(evt); 03273 } 03274 } 03275 03276 while (parents.size()) 03277 modified_list.insert( parents.pop() ); 03278 03279 old_ptr->get_parent_ref_entities( parents ); 03280 while (parents.size()) 03281 modified_list.insert( parents.pop() ); 03282 modified_list.insert( old_ptr ); 03283 03284 UnMergeEvent event( old_ptr, new_ptr ); 03285 AppUtil::instance()->send_event( event ); 03286 } 03287 03288 std::set<CubitObservable*>::iterator iter; 03289 for (iter = modified_list.begin(); iter != modified_list.end(); ++iter) 03290 { 03291 AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::TOPOLOGY_MODIFIED, static_cast<RefEntity*>(*iter))); 03292 CGMHistory::Event evt(CGMHistory::TOPOLOGY_CHANGED, static_cast<RefEntity*>(*iter)); 03293 GeometryQueryTool::instance()->history().add_event(evt); 03294 } 03295 03296 for( int a = assistant_list_.size(); a--; ) 03297 assistant_list_.get_and_step()->finish_unmerge(); 03298 03299 if (vtx_count) 03300 PRINT_INFO("Unmerged %d vertices.\n", vtx_count); 03301 if (curve_count) 03302 PRINT_INFO("Unmerged %d curves.\n", curve_count); 03303 if (surf_count) 03304 PRINT_INFO("Unmerged %d surfaces.\n", surf_count); 03305 if (vtx_count + curve_count + surf_count == 0) 03306 PRINT_INFO("No entities unmerged.\n"); 03307 } 03308 03309 03310 03311 void MergeTool::compare_notify(RefEntity *entity) 03312 { 03313 //- notifies MergeTool about comparisons found and put on ref entities 03314 compareEntityList.append_unique(entity); 03315 } 03316 03317 CubitStatus MergeTool::merge_BTE( BasicTopologyEntity* keeper_entity, 03318 BasicTopologyEntity* dead_entity ) 03319 { 03320 CubitStatus result = CUBIT_FAILURE; 03321 DLIList<TopologyEntity*> query_results, query_results_2; 03322 03323 // save to notify at end 03324 DLIList<RefEntity*> dead_parents; 03325 dead_entity->get_parent_ref_entities(dead_parents); 03326 03327 // Make sure that the 2 BTE's are of the same type 03328 if( keeper_entity->dag_type() != dead_entity->dag_type() ) 03329 { 03330 PRINT_DEBUG_19( "In MergeTool::merge_BTE(), \n" 03331 " two different types of entities " 03332 "are merged. \n" 03333 " THIS IS A BUG - PLEASE REPORT IT!\n"); 03334 return CUBIT_FAILURE; 03335 } 03336 03337 // Debug info 03338 CubitString keeper_entity_name(""), dead_entity_name(""); 03339 if (DEBUG_FLAG(19)) 03340 { 03341 keeper_entity_name = keeper_entity->entity_name(); 03342 dead_entity_name = dead_entity->entity_name(); 03343 03344 PRINT_DEBUG_19("...In MergeTool::merge_BTE - " 03345 "Merging %s and %s\n", 03346 keeper_entity_name.c_str(), 03347 dead_entity_name.c_str() ); 03348 } 03349 03350 // Sanity Check: don't merge the entities if either of them 03351 // is already deactivated 03352 if( keeper_entity->deactivated() ) 03353 { 03354 PRINT_ERROR( "%s has already been merged\n", 03355 keeper_entity->entity_name().c_str() ); 03356 return CUBIT_FAILURE; 03357 } 03358 if( dead_entity->deactivated() ) 03359 { 03360 PRINT_ERROR( "%s has already been merged\n", 03361 dead_entity->entity_name().c_str() ); 03362 return CUBIT_FAILURE; 03363 } 03364 03365 // sanity check - don't merge entity with itself 03366 if( keeper_entity == dead_entity ) 03367 { 03368 // Debug info 03369 PRINT_DEBUG_19( " Did not merge %s and %s. " 03370 "Cannot merge entity with itself.\n", 03371 keeper_entity_name.c_str(), 03372 dead_entity_name.c_str() ); 03373 return CUBIT_SUCCESS; 03374 } 03375 03376 // sanity check - don't merge entities w/ same parent 03377 ModelQueryEngine *const mqe = ModelQueryEngine::instance(); 03378 DagType parent_type = keeper_entity->get_parent_ref_entity_type(); 03379 mqe->query_model( *keeper_entity, parent_type, query_results ); 03380 mqe->query_model( *dead_entity, parent_type, query_results_2 ); 03381 query_results.intersect( query_results_2 ); 03382 if (query_results.size()) 03383 { 03384 PRINT_DEBUG_19( "In MergeTool::merge_BTE()\n" ); 03385 PRINT_INFO("\n"); 03386 PRINT_WARNING("Attempting to merge two entities with same parent.\n" 03387 " %s (%s %d) and %s (%s %d)\n", 03388 keeper_entity->entity_name().c_str(), 03389 keeper_entity->class_name(), keeper_entity->id(), 03390 dead_entity->entity_name().c_str(), 03391 dead_entity->class_name(), dead_entity->id()); 03392 PRINT_INFO("Check for sliver geometry in the vicinity\n"); 03393 return CUBIT_FAILURE; 03394 } 03395 03396 // Merge the GroupingEntitys of the BasicTopologyEntity 03397 DLIList<GroupingEntity*> keeper_GE_list; 03398 DLIList<GroupingEntity*> dead_GE_list; 03399 03400 // First get the GroupingEntities of the BTE's 03401 keeper_entity->get_grouping_entity_list( keeper_GE_list ); 03402 dead_entity->get_grouping_entity_list( dead_GE_list ); 03403 03404 // Make sure they have the same number of GroupingEntities 03405 if( keeper_GE_list.size() != dead_GE_list.size() ) 03406 { 03407 PRINT_DEBUG_19( "In MergeTool::merge_BTE()\n" 03408 " the two entities have different " 03409 "numbers of GroupingEntities.\n" 03410 " THIS IS A BUG - PLEASE REPORT IT!\n" ); 03411 return CUBIT_FAILURE; 03412 } 03413 03414 // Merge all child BTEs 03415 BasicTopologyEntity *bte_ptr_1, *bte_ptr_2; 03416 DagType child_type = keeper_entity->get_child_ref_entity_type(); 03417 if (child_type.is_valid()) 03418 { 03419 query_results.clean_out(); 03420 mqe->query_model( *keeper_entity, child_type, query_results ); 03421 while (query_results.size()) 03422 { 03423 bte_ptr_1 = dynamic_cast<BasicTopologyEntity*>(query_results.pop()); 03424 bte_ptr_2 = dynamic_cast<BasicTopologyEntity*>(bte_ptr_1->get_compare_partner()); 03425 if (!bte_ptr_2 || bte_ptr_2->deactivated()) 03426 continue; 03427 03428 if (bte_ptr_2->get_compare_partner() != bte_ptr_1) 03429 { 03430 PRINT_DEBUG_19("Bad compare partner TDs encountered at %s:%d.\n" 03431 "This is a bug. Please report it.\n", 03432 __FILE__, __LINE__ ); 03433 return CUBIT_FAILURE; 03434 } 03435 03436 CubitStatus merge_status; 03437 if (bte_ptr_1->id() < bte_ptr_2->id()) 03438 merge_status = merge_BTE(bte_ptr_1, bte_ptr_2); 03439 else 03440 merge_status = merge_BTE(bte_ptr_2, bte_ptr_1); 03441 03442 if (!merge_status) 03443 return CUBIT_FAILURE; 03444 } 03445 } 03446 03447 // If RefFace or RefEdge, adjust sense of parent sense entities, 03448 // if necessary. This was previously handled by the 03449 // switch_child_notify() callback in DAGNode/TopologyEntity. 03450 // However, with virtual geometry, there may be CoEdges/CoFaces 03451 // that do not get merged with anything and still need to be 03452 // updated. Also, by taking this out of switch_child_notify, 03453 // compare_alignment() does not need to be called for every 03454 // SenseEntitiy merge. We only need to call it once. 03455 CubitBoolean switch_sense = CUBIT_FALSE; 03456 03457 if(CAST_TO( keeper_entity, RefFace ) ) 03458 { 03459 RefFace* keep_face = CAST_TO(keeper_entity,RefFace); 03460 RefFace* dead_face = CAST_TO( dead_entity,RefFace); 03461 if( keep_face->compare_alignment(dead_face) == CUBIT_REVERSED ) 03462 { 03463 switch_sense = CUBIT_TRUE; 03464 } 03465 //warn_about_refface_sense( keep_face, dead_face, switch_sense ); 03466 } 03467 else if( CAST_TO( keeper_entity, RefEdge ) ) 03468 { 03469 RefEdge* keep_edge = CAST_TO(keeper_entity,RefEdge); 03470 RefEdge* dead_edge = CAST_TO( dead_entity,RefEdge); 03471 CubitSense sense; 03472 CubitBoolean junk; 03473 keep_edge->relative_sense( dead_edge, 03474 GeometryQueryTool::get_geometry_factor(), 03475 &sense, junk, CUBIT_TRUE ); 03476 if( sense == CUBIT_REVERSED ) 03477 switch_sense = CUBIT_TRUE; 03478 } 03479 03480 03481 // Let any assistants know that we are about to merge 03482 // these two entities. 03483 for( int a = assistant_list_.size(); a > 0; a-- ) 03484 assistant_list_.get_and_step() 03485 ->merging( keeper_entity, dead_entity, switch_sense ); 03486 03487 03488 // Now find the matching pairs of GroupingEntities to merge 03489 GroupingEntity *keeper_GE = NULL; 03490 GroupingEntity *dead_GE = NULL; 03491 03492 CubitStatus found_flag; 03493 keeper_GE_list.reset(); 03494 for( int i = 0; i< keeper_GE_list.size(); i++ ) 03495 { 03496 found_flag = CUBIT_FAILURE; 03497 keeper_GE = keeper_GE_list.get_and_step(); 03498 03499 // if keeper_GE is deactivated, 03500 // then skip this one and come to the next one 03501 if( keeper_GE->deactivated() == CUBIT_TRUE ) 03502 continue; 03503 03504 dead_GE_list.reset(); 03505 for( int j = 0; j < dead_GE_list.size(); j++ ) 03506 { 03507 dead_GE = dead_GE_list.get_and_step(); 03508 03509 // Before doing any compares, check to see if this 03510 // GroupingEntity has already been deactivated 03511 if( dead_GE->deactivated() == CUBIT_TRUE ) 03512 continue; 03513 03514 // if find any item in dead_GE_list matches the item in 03515 // keeper_GE_list, then merge these two items, remove 03516 // dead_GE from the dead_GE_list, continue to the next 03517 // item in keeper_GE_list. 03518 if( compare_GE( keeper_GE, dead_GE ) ) 03519 { 03520 if( merge_GE( keeper_GE, dead_GE ) == CUBIT_FAILURE ) 03521 { 03522 PRINT_DEBUG_19("In MergeTool::merge_BTE()\n" 03523 " Cannot merge the GroupingEntities\n" 03524 " THIS IS A BUG - PLEASE REPORT IT!\n" ); 03525 return CUBIT_FAILURE; 03526 } 03527 else 03528 { 03529 // A match was found and merged. Deactivation of 03530 // dead_GE is done in TopologyEntity::merge_links(). 03531 found_flag = CUBIT_SUCCESS; 03532 dead_GE_list.reset(); 03533 break; 03534 } 03535 } 03536 } 03537 03538 if( found_flag == CUBIT_FAILURE ) 03539 { 03540 PRINT_DEBUG_19( "In MergeTool::merge_BTE()\n" 03541 " cannot find the matching GroupingEntities.\n" 03542 " This may be due to curves smaller than the\n" 03543 " merge tolerance. You will probably want to\n" 03544 " modify the geometry.\n"); 03545 return CUBIT_FAILURE; 03546 } 03547 } 03548 03549 // Merge the name(s) of dead_entity to those of keeper_entity 03550 keeper_entity->merge_entity_names( dead_entity ); 03551 03552 bool is_dead_entity_free_entity = false; 03553 if( dead_entity->num_parent_ref_entities() == 0 ) 03554 is_dead_entity_free_entity = true; 03555 03556 bool is_keeper_entity_free_entity = false; 03557 if( keeper_entity->num_parent_ref_entities() == 0 ) 03558 is_keeper_entity_free_entity = true; 03559 03560 // Next, merge the links of these two BTEs 03561 SenseEntity* co_edge_ptr; 03562 result = CUBIT_SUCCESS; 03563 while( (co_edge_ptr = dead_entity->get_first_sense_entity_ptr()) ) 03564 { 03565 if (switch_sense) 03566 co_edge_ptr->reverse_sense(); 03567 if (!dead_entity->remove_sense_entity(co_edge_ptr)) 03568 result = CUBIT_FAILURE; 03569 if (!keeper_entity->add_sense_entity(co_edge_ptr)) 03570 result = CUBIT_FAILURE; 03571 } 03572 03573 if( result == CUBIT_FAILURE ) 03574 { 03575 PRINT_DEBUG_19( "In MergeTool::merge_BTE()\n" 03576 " Could not merge the links of %s and %s.\n" 03577 " THIS IS A BUG - PLEASE REPORT IT!\n", 03578 keeper_entity->entity_name().c_str(), 03579 dead_entity->entity_name().c_str() ); 03580 return CUBIT_FAILURE; 03581 } 03582 03583 // Save IDs for geometry from dead entity. 03584 // Only do this for the first geometry if the dead 03585 // entity is already a merge of several. Others should 03586 // already have IDs saved from whatever they where 03587 // before they were merged. 03588 GeometryEntity* geom = dead_entity->get_geometry_entity_ptr(); 03589 geom->set_saved_id( dead_entity->id() ); 03590 03591 03592 // TODO -- Suggestion to make this merge code more friendly for observers: 03593 // 1. emit only one merge event after the merge actually happened 03594 // 2. delete entities after the merge event was emitted 03595 03596 // Destroy the old entity 03597 03598 AppUtil::instance()->send_event( MergeEvent(dead_entity, keeper_entity) ); 03599 03600 AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::TOPOLOGY_ENTITY_DESTRUCTED, dead_entity)); 03601 if( is_dead_entity_free_entity ) //is free entity...top level 03602 { 03603 AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::TOP_LEVEL_ENTITY_DESTRUCTED, dead_entity)); 03604 CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_DELETED, dead_entity); 03605 GeometryQueryTool::instance()->history().add_event(evt); 03606 } 03607 03608 dead_entity->deactivated(CUBIT_TRUE); 03609 03610 BridgeManager* keeper_GEs = keeper_entity->bridge_manager(); 03611 BridgeManager* dead_GEs = dead_entity->bridge_manager(); 03612 result = keeper_GEs->merge( dead_GEs, 03613 switch_sense ? CUBIT_REVERSED : CUBIT_FORWARD ); 03614 if( result == CUBIT_FAILURE ) 03615 { 03616 PRINT_DEBUG_19( "In MergeTool::merge_BTE()\n" 03617 " Could not merge the GeometryEntities " 03618 "of %s and %s.\n" 03619 " THIS IS A BUG - PLEASE REPORT IT!\n", 03620 keeper_entity->entity_name().c_str(), 03621 dead_entity->entity_name().c_str() ); 03622 return CUBIT_FAILURE; 03623 } 03624 03625 // Debug info 03626 PRINT_DEBUG_19( 03627 "\n...Merging of %s (retained) and %s (deleted) " 03628 "successful.\n\n\n", keeper_entity_name.c_str(), 03629 dead_entity_name.c_str() ); 03630 03631 if( is_keeper_entity_free_entity && !is_dead_entity_free_entity ) //is free entity...top level 03632 { 03633 AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::TOP_LEVEL_ENTITY_DESTRUCTED, keeper_entity)); 03634 CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_DELETED, keeper_entity); 03635 GeometryQueryTool::instance()->history().add_event(evt); 03636 } 03637 03638 03639 for(int i=0; i<dead_parents.size(); i++) 03640 { 03641 AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::TOPOLOGY_MODIFIED, dead_parents[i])); 03642 CGMHistory::Event evt(CGMHistory::TOPOLOGY_CHANGED, dead_parents[i]); 03643 GeometryQueryTool::instance()->history().add_event(evt); 03644 } 03645 03646 return CUBIT_SUCCESS; 03647 } 03648 03649 //------------------------------------------------------------------------- 03650 // Purpose : When merging RefFaces with the same sense, check 03651 // CoFace senses to see if the adjacent RefVolumes overlap. 03652 // 03653 // Special Notes : 03654 // 03655 // Creator : Jason Kraftcheck 03656 // 03657 // Creation Date : 03/04/04 03658 //------------------------------------------------------------------------- 03659 void MergeTool::warn_about_refface_sense( RefFace* face1, RefFace* face2, 03660 bool faces_reversed ) 03661 { 03662 DLIList<CoFace*> coface_list_1, coface_list_2; 03663 face1->co_faces(coface_list_1); 03664 face2->co_faces(coface_list_2); 03665 bool non_manifold_1 = false, non_manifold_2 = false; 03666 while (coface_list_1.size()) 03667 { 03668 CoFace* coface1 = coface_list_1.pop(); 03669 if (face1->is_nonmanifold(coface1->get_shell_ptr())) 03670 { 03671 non_manifold_1 = true; 03672 continue; 03673 } 03674 03675 for (int i = coface_list_2.size(); i--; ) 03676 { 03677 CoFace* coface2 = coface_list_2.pop(); 03678 if (face2->is_nonmanifold(coface2->get_shell_ptr())) 03679 { 03680 non_manifold_2 = true; 03681 continue; 03682 } 03683 03684 bool cofaces_reversed = (coface1->get_sense() == coface2->get_sense()); 03685 if (faces_reversed != cofaces_reversed) 03686 { 03687 RefVolume* vol1 = coface1->get_shell_ptr()->get_ref_volume_ptr(); 03688 RefVolume* vol2 = coface2->get_shell_ptr()->get_ref_volume_ptr(); 03689 PRINT_WARNING("Merging %s (surface %d) and %s (surface %d): " 03690 "%s (volume %d) and %s (volume %d) appear to be " 03691 "on the same side of the surfaces. This may " 03692 "indicate bad geometry.\n", 03693 face1->entity_name().c_str(), face1->id(), 03694 face2->entity_name().c_str(), face2->id(), 03695 vol1->entity_name().c_str(), vol1->id(), 03696 vol2->entity_name().c_str(), vol2->id()); 03697 } 03698 } 03699 } 03700 03701 if (non_manifold_1) 03702 PRINT_WARNING("Merging non-manifold surface %d (%s). Sheet body?\n", 03703 face1->id(), face1->entity_name().c_str()); 03704 if (non_manifold_2) 03705 PRINT_WARNING("Merging non-manifold surface %d (%s). Sheet body?\n", 03706 face2->id(), face2->entity_name().c_str()); 03707 } 03708 03709 03710 //---------------------------------------------------------------- 03711 // Purpose : Merge "this" GroupingEntity with the input 03712 // GroupingEntity 03713 // 03714 // Special Notes : 03715 // 03716 // Creator : jihong Ma 03717 // 03718 // Creation Date : 11/26/96 03719 //---------------------------------------------------------------- 03720 CubitStatus MergeTool::merge_GE( GroupingEntity *keeper_entity, 03721 GroupingEntity *dead_entity ) 03722 { 03723 // first check if merging keeper_entity with itself 03724 if( keeper_entity == dead_entity ) 03725 return CUBIT_SUCCESS; 03726 03727 CubitStatus result = CUBIT_FAILURE; 03728 03729 // Merge is done whenever we find matching SenseEntities from 03730 // keeper_entity and dead_entity in compare_and_merge() with a 03731 // CUBIT_TRUE input parameter. 03732 result = compare_and_merge( CUBIT_TRUE, keeper_entity, dead_entity ); 03733 03734 // When merging SenseEntities fails, print error and return 03735 if( result == CUBIT_FAILURE ) 03736 { 03737 PRINT_DEBUG_19( "In MergeTool::merge_GE()\n" 03738 " Could not merge the SenseEntities\n" 03739 " THIS IS A BUG - PLEASE REPORT IT!\n" ); 03740 return CUBIT_FAILURE; 03741 } 03742 03743 // After succussfully merging SenseEntities, merge the links 03744 // of the GeometryEntities. 03745 assert(dead_entity->get_children() == 0); 03746 dead_entity->deactivated(CUBIT_TRUE); 03747 BasicTopologyEntity* parent = dead_entity->get_basic_topology_entity_ptr(); 03748 result = parent->remove_grouping_entity(dead_entity); 03749 03750 if( result == CUBIT_FAILURE ) 03751 { 03752 PRINT_DEBUG_19( "In MergeTool::merge_GE()\n" 03753 " Could not merge the GroupingEntity links.\n" 03754 " THIS IS A BUG - PLEASE REPORT IT!\n" ); 03755 return CUBIT_FAILURE; 03756 } 03757 03758 // merge the OSME's. 03759 BridgeManager* keeper_OSMEs = keeper_entity->bridge_manager(); 03760 BridgeManager* dead_OSMEs = dead_entity->bridge_manager(); 03761 03762 result = keeper_OSMEs->merge(dead_OSMEs,CUBIT_UNKNOWN); 03763 if( result == CUBIT_FAILURE ) 03764 { 03765 PRINT_DEBUG_19( "In MergeTool::merge_GE()\n" 03766 " Could not merge the OSME's.\n" 03767 " THIS IS A BUG - PLEASE REPORT IT!\n" ); 03768 return CUBIT_FAILURE; 03769 } 03770 03771 return CUBIT_SUCCESS; 03772 } 03773 03774 03775 //---------------------------------------------------------------- 03776 // Purpose : Compare this GroupingEntity to the input 03777 // GroupingEntity to compare for spatial equality. 03778 // 03779 // Special Notes : 03780 // 03781 // Creator : jihong Ma 03782 // 03783 // Creation Date : 11/26/96 03784 //---------------------------------------------------------------- 03785 CubitBoolean MergeTool::compare_GE( GroupingEntity* keeper_entity, 03786 GroupingEntity* dead_entity ) 03787 { 03788 // Comparison is done by comparing the SenseEntity list of 03789 // keeper_entity with the SenseEntity list of dead_entity. 03790 // If we find that all the SenseEntities of keeper_entity 03791 // match with all the SenseEntities of dead_entity 03792 // then the GroupingEntities are spatially equal. 03793 03794 if( compare_and_merge( CUBIT_FALSE, keeper_entity, dead_entity ) ) 03795 return CUBIT_TRUE; 03796 else 03797 return CUBIT_FALSE; 03798 } 03799 03800 //--------------------------------------------------------------- 03801 // Purpose : spatially compare this GroupingEntity with the 03802 // input GroupingEntity. But if the merge_flag is 03803 // CUBIT_TRUE, merge the matching SenseEntity 03804 // pairs whenever found. 03805 // 03806 // Special Notes : Merging the OSME's and merging links are done 03807 // in merge_GE() function. In this function, ONLY 03808 // the matching SenseEntities can be merged when 03809 // asked to merge them ( i.e., merge_flag is 03810 // set to CUBIT_TRUE ). 03811 // 03812 // Grouping entities compare successfully if their 03813 // associated lists of SenseEntities compare 03814 // successfully. For example, 2 Loops compare if 03815 // their lists of CoEdges contain matching (ones 03816 // that compare) pairs. 03817 // 03818 // The first trial check that is done is to make 03819 // sure that the GroupingEntities have the same 03820 // number of SenseEntities. If they do not, then 03821 // we ASSUME that the GroupingEntities are not 03822 // spatially equal. This is not strictly a good 03823 // assumption, but we don't have a more exact 03824 // algorithm that takes care of the case where, 03825 // for example, the number of RefEdges associated 03826 // with two Loops are different, but the Loops 03827 // themselves are spatialy equal. Consider the 03828 // case of 2 Loops representing the exact same 03829 // square -- one can have 4 RefEdges and the other 03830 // could have 5 (just bisect one of the previous 03831 // ones...) 03832 // 03833 // Creator : jihong Ma 03834 // 03835 // Creation Date : 12/05/96 03836 //--------------------------------------------------------------- 03837 CubitStatus MergeTool::compare_and_merge( CubitBoolean merge_flag, 03838 GroupingEntity* keeper_entity, 03839 GroupingEntity* dead_entity ) 03840 { 03841 // check if they are equal 03842 if( keeper_entity == dead_entity ) 03843 return CUBIT_SUCCESS; 03844 03845 // Make sure that the 2 GroupingEntities are of the same type 03846 if( keeper_entity->dag_type() != dead_entity->dag_type() ) 03847 { 03848 PRINT_ERROR( "In MergeTool::compare_and_merge()\n" 03849 " Entities of different type are being compared.\n" 03850 " THIS IS A BUG - PLEASE REPORT IT!\n" ); 03851 return CUBIT_FAILURE; 03852 } 03853 03854 // Now compare, and merge if asked, the SenseEntities 03855 // Get the SenseEntity lists 03856 DLIList<SenseEntity*> keeper_SE_list; 03857 DLIList<SenseEntity*> dead_SE_list; 03858 03859 keeper_entity->get_sense_entity_list( keeper_SE_list ); 03860 dead_entity->get_sense_entity_list( dead_SE_list ); 03861 03862 // Make sure the lists are of the same size. If not, then 03863 // there is a bug here as the 2 GroupingEntities should not 03864 // have passed the "compare" test. 03865 if( keeper_SE_list.size() != dead_SE_list.size() ) 03866 { 03867 if( merge_flag == CUBIT_TRUE ) 03868 { 03869 PRINT_ERROR(" THIS IS A BUG - PLEASE REPORT IT!\n"); 03870 assert(0); 03871 } 03872 return CUBIT_FAILURE; 03873 } 03874 03875 SenseEntity* keeper_SE = NULL; 03876 SenseEntity* dead_SE = NULL; 03877 CubitStatus found_flag; 03878 03879 // Now find the matching pairs of SenseEntities 03880 keeper_SE_list.reset(); 03881 for( int i = 0; i < keeper_SE_list.size(); i++ ) 03882 { 03883 found_flag = CUBIT_FAILURE; 03884 keeper_SE = keeper_SE_list.get_and_step(); 03885 03886 // If this SenseEntity has already been deactivated, 03887 // then skip to the next one 03888 if( keeper_SE->deactivated() == CUBIT_TRUE ) 03889 continue; 03890 03891 dead_SE_list.reset(); 03892 for( int j = 0; j < dead_SE_list.size(); j++ ) 03893 { 03894 dead_SE = dead_SE_list.get_and_step(); 03895 03896 // if dead_SE is deactivated, then skip to next one 03897 if( dead_SE->deactivated() == CUBIT_TRUE ) 03898 continue; 03899 03900 // look for an item in dead_SE_list that matches an 03901 // item in keeper_SE_list 03902 if( compare_SE( keeper_SE, dead_SE ) ) 03903 { 03904 // if asked to merge, then merge the matching 03905 // SenseEntities remove the dead_SE from the 03906 // dead_SE_list. Continue to the next item in 03907 // keeper_SE_list 03908 if( merge_flag == CUBIT_TRUE ) 03909 { 03910 if( merge_SE( keeper_SE, dead_SE ) == CUBIT_FAILURE ) 03911 { 03912 PRINT_ERROR( "In MergeTool::compare_and_merge()\n" 03913 " Cannot merge the matched SenseEntity\n" 03914 " THIS IS A BUG - PLEASE REPORT IT!\n" ); 03915 return CUBIT_FAILURE; 03916 } 03917 } 03918 03919 // if not asked to merge, just break to outer loop to 03920 // compare the next SenseEntity. 03921 found_flag = CUBIT_SUCCESS; 03922 dead_SE_list.reset(); 03923 break; 03924 } 03925 } 03926 03927 // If we were unable to find a match for one of the SEs, 03928 // return failure. 03929 if (found_flag == CUBIT_FAILURE) 03930 return CUBIT_FAILURE; 03931 } 03932 return CUBIT_SUCCESS; 03933 } 03934 03935 //---------------------------------------------------------------- 03936 // Purpose : merge two SenseEntities 03937 // 03938 // Special Notes : 03939 // 03940 // Creator : jihong Ma 03941 // 03942 // Creation Date : 11/20/96 03943 //---------------------------------------------------------------- 03944 CubitStatus MergeTool::merge_SE( SenseEntity* keeper_entity, 03945 SenseEntity* dead_entity ) 03946 { 03947 // first check if merging the SenseEntity with itself 03948 if( keeper_entity == dead_entity ) 03949 return CUBIT_SUCCESS; 03950 03951 CubitStatus result = CUBIT_FAILURE; 03952 03953 // Make sure that the 2 SenseEntities are of the same type 03954 if( keeper_entity->dag_type() != dead_entity->dag_type() ) 03955 { 03956 PRINT_ERROR( "In MergeTool::merge_SE()\n" 03957 " Merging SenseEntities of different types\n" 03958 " THIS IS A BUG - PLEASE REPORT IT!\n" ); 03959 return CUBIT_FAILURE; 03960 } 03961 03962 BasicTopologyEntity* keeper_BTE; 03963 BasicTopologyEntity* dead_BTE; 03964 03965 // Get the BTE's of the SenseEntities being merged 03966 keeper_BTE = keeper_entity->get_basic_topology_entity_ptr(); 03967 dead_BTE = dead_entity->get_basic_topology_entity_ptr(); 03968 03969 // Compare them to make sure that these SenseEntities can 03970 // really be merged. 03971 if( keeper_BTE != dead_BTE) 03972 { 03973 PRINT_ERROR( "In MergeTool::merge_SE()\n" 03974 " Two SenseEntities have incompatible BTEs\n" 03975 " THIS IS A BUG - PLEASE REPORT IT!\n" ); 03976 assert(0); 03977 return CUBIT_FAILURE; 03978 } 03979 03980 03981 AppUtil::instance()->send_event(TopologyEvent(TopologyEvent::TOPOLOGY_ENTITY_DESTRUCTED, dead_entity)); 03982 03983 // Now that the BTE's have been successfully merged, merge the 03984 // the links of the SenseEntities. 03985 dead_entity->deactivated(CUBIT_TRUE); 03986 GroupingEntity* parent = dead_entity->get_grouping_entity_ptr(); 03987 BasicTopologyEntity* child = dead_entity->get_basic_topology_entity_ptr(); 03988 result = (CubitStatus)(parent->remove_sense_entity(dead_entity) && 03989 child->remove_sense_entity(dead_entity)); 03990 if( result == CUBIT_FAILURE ) 03991 { 03992 PRINT_ERROR( "In MergeTool::merge_SE()\n" 03993 " Couldn't merge the links of the SenseEntities.\n" 03994 " THIS IS A BUG - PLEASE REPORT IT!\n" ); 03995 assert(0); 03996 return CUBIT_FAILURE; 03997 } 03998 03999 // Now that the BTE's have been successfully merged, merge the 04000 // OSME's of the SenseEntities being merged 04001 BridgeManager* keeper_OSMEs = keeper_entity->bridge_manager(); 04002 BridgeManager* dead_OSMEs = dead_entity->bridge_manager(); 04003 04004 result = keeper_OSMEs->merge(dead_OSMEs,CUBIT_UNKNOWN); 04005 if (result == CUBIT_FAILURE) 04006 { 04007 PRINT_ERROR( "In MergeTool::merge_SE()\n" 04008 " Could not merge the OSME's.\n" 04009 " THIS IS A BUG - PLEASE REPORT IT!\n" ); 04010 assert(0) ; 04011 return CUBIT_FAILURE; 04012 } 04013 04014 return CUBIT_SUCCESS; 04015 } 04016 04017 //---------------------------------------------------------------- 04018 // Purpose : Compare two SenseEntities 04019 // 04020 // Special Notes : Sense entities compare successfully if their 04021 // associated BasicTopologyEntities compare 04022 // successfully. For example, 2 CoEdges compare 04023 // if their RefEdges compare. 04024 // 04025 // Creator : jihong Ma 04026 // 04027 // Creation Date : 11/20/96 04028 //---------------------------------------------------------------- 04029 CubitBoolean MergeTool::compare_SE( SenseEntity* keeper_entity, 04030 SenseEntity* dead_entity ) 04031 { 04032 // check if they are the same entity 04033 if( keeper_entity == dead_entity ) 04034 return CUBIT_TRUE; 04035 04036 // first check if they are the same type 04037 if( keeper_entity->dag_type() != dead_entity->dag_type() ) 04038 { 04039 PRINT_ERROR( "In MergeTool::compare_SE()\n" 04040 " SenseEntities of different type are compared\n" 04041 " THIS IS A BUG - PLEASE REPORT IT!\n" ); 04042 return CUBIT_TRUE; 04043 } 04044 04045 // Get their BTE's and compare them 04046 BasicTopologyEntity *keeper_BTE = NULL; 04047 BasicTopologyEntity *dead_BTE = NULL; 04048 04049 keeper_BTE = keeper_entity->get_basic_topology_entity_ptr(); 04050 dead_BTE = dead_entity->get_basic_topology_entity_ptr(); 04051 04052 // Return the status of comparing the BTE's 04053 return keeper_BTE == dead_BTE; 04054 } 04055 04056 void MergeTool::complete_merge() 04057 { 04058 // Merge operation was completed successfully or was aborted midway. 04059 // Clean up the temporary compare data that was added to the RefEntities 04060 // being compared (during the merge) and cleanout the local (Model) lists 04061 // that store pointers to such entities. 04062 04063 remove_compare_data(); 04064 04065 // Now clear the lists 04066 compareEntityList.clean_out() ; 04067 mergeSurvivorEntityList.clean_out(); 04068 04069 // Notify assistants 04070 for( int j = assistant_list_.size(); j--; ) 04071 assistant_list_.get_and_step()->finish_merge(); 04072 } 04073 04074 void MergeTool::remove_compare_data() 04075 { 04076 compareEntityList.reset(); 04077 for(int i = compareEntityList.size(); i > 0 ; i-- ) 04078 { 04079 RefEntity* ref_ent = compareEntityList.get(); 04080 if ( CAST_TO( ref_ent, RefVertex ) || 04081 CAST_TO( ref_ent, RefEdge ) || 04082 CAST_TO( ref_ent, RefFace ) ) 04083 { 04084 // Remove the TDCompare data attached to the entity 04085 PRINT_DEBUG_19( 04086 "Model::notify Removing compare_TD from %s %d\n", 04087 ref_ent->class_name(), 04088 ref_ent->id()); 04089 ref_ent->remove_compare_data(); 04090 } 04091 else 04092 { 04093 PRINT_WARNING("WARNING:Something went wrong with the merging data.\n"); 04094 compareEntityList.remove(); 04095 } 04096 compareEntityList.step(); 04097 } 04098 compareEntityList.clean_out(); 04099 } 04100 04101 04102 void MergeTool::remove_merge_tool_assistant( MergeToolAssistant* mta_ptr ) 04103 { 04104 if( assistant_list_.move_to( mta_ptr ) ) 04105 assistant_list_.remove(); 04106 } 04107 04108 void MergeTool::add_merge_tool_assistant( MergeToolAssistant* mta_ptr ) 04109 { 04110 if( !assistant_list_.is_in_list( mta_ptr ) ) 04111 assistant_list_.append( mta_ptr ); 04112 } 04113 MergeToolAssistant* MergeTool::find_merge_tool_assistant( const std::type_info& type ) 04114 { 04115 for( int i = assistant_list_.size(); i > 0; i-- ) 04116 { 04117 if( typeid( *(assistant_list_.step_and_get()) ) == type ) 04118 return assistant_list_.get(); 04119 } 04120 return 0; 04121 } 04122 void MergeTool::test_r_tree(DLIList <RefFace*> &refface_list) 04123 { 04124 CpuTimer timer; 04125 timer.cpu_secs(); 04126 double geom_factor = GeometryQueryTool::get_geometry_factor(); 04127 double tol = GEOMETRY_RESABS*geom_factor; 04128 RTree<RefFace*> a_tree(GEOMETRY_RESABS*geom_factor); 04129 // AbstractTree <RefFace*> *a_tree = new RTree<RefFace*> (tol); 04130 04131 DLIList<RefFace*> refface_array( refface_list.size() ); 04132 refface_list.reset(); 04133 04134 // Remove entities that should not be automatically merged 04135 int i = 0; 04136 int j; 04137 int loop_size = refface_list.size(); 04138 for( i = 0; i < loop_size; i++ ) 04139 { 04140 RefFace *curr_face = refface_list.get_and_step(); 04141 if( curr_face->is_mergeable() ) 04142 { 04143 refface_array.append( curr_face ); 04144 a_tree.add(curr_face); 04145 } 04146 } 04147 double time_to_build = timer.cpu_secs(); 04148 04149 //initialize the marked flag for fast nulification... 04150 int array_size = refface_array.size(); 04151 RefFace *ref_face, *ref_face1; 04152 CubitBox temp_box, temp_box2; 04153 DLIList<RefFace*> faces_in_range; 04154 int hit = 0; 04155 for ( i = 0; i < array_size; i++ ) 04156 { 04157 ref_face = refface_array[i]; 04158 temp_box = ref_face->bounding_box(); 04159 faces_in_range.clean_out(); 04160 a_tree.find(temp_box, faces_in_range); 04161 for ( j = 0; j<faces_in_range.size(); j++) 04162 { 04163 ref_face1 = faces_in_range.get_and_step(); 04164 temp_box2 = ref_face1->bounding_box(); 04165 if ( temp_box.overlap(tol, temp_box2) ) 04166 hit++; 04167 } 04168 } 04169 PRINT_INFO( "TREE: Total Merge Reffaces time: %f secs\n" 04170 "\tTime to build: %f secs\n", 04171 timer.cpu_secs()+time_to_build, time_to_build ); 04172 } 04173 04174 // void MergeTool::test_r_star_tree(DLIList <RefFace*> &refface_list) 04175 // { 04176 // CpuTimer timer; 04177 // timer.cpu_secs(); 04178 // double geom_factor = GeometryQueryTool::get_geometry_factor(); 04179 // double tol = GEOMETRY_RESABS*geom_factor; 04180 // RStarTree <RefFace*> *r_tree = new RStarTree<RefFace*> (tol); 04181 04182 // DLIList<RefFace*> refface_array( refface_list.size() ); 04183 // refface_list.reset(); 04184 04185 // // Remove entities that should not be automatically merged 04186 // int i = 0; 04187 // int j; 04188 // int loop_size = refface_list.size(); 04189 // for( i = 0; i < loop_size; i++ ) 04190 // { 04191 // RefFace *curr_face = refface_list.get_and_step(); 04192 // if( curr_face->is_mergeable() ) 04193 // { 04194 // refface_array.append( curr_face ); 04195 // r_tree->add(curr_face); 04196 // } 04197 // } 04198 // double time_to_build = timer.cpu_secs(); 04199 // //initialize the marked flag for fast nulification... 04200 // int array_size = refface_array.size(); 04201 // RefFace *ref_face, *ref_face1; 04202 // CubitBox temp_box, temp_box2; 04203 // DLIList<RefFace*> faces_in_range; 04204 // int hit = 0; 04205 // for ( i = 0; i < array_size; i++ ) 04206 // { 04207 // ref_face = refface_array[i]; 04208 // temp_box = ref_face->bounding_box(); 04209 // faces_in_range.clean_out(); 04210 // r_tree->find(temp_box, faces_in_range); 04211 // for ( j = 0; j<faces_in_range.size(); j++) 04212 // { 04213 // ref_face1 = faces_in_range.get_and_step(); 04214 // temp_box2 = ref_face1->bounding_box(); 04215 // if ( temp_box.overlap(tol, temp_box2) ) 04216 // hit++; 04217 // } 04218 // } 04219 // PRINT_INFO( "RSTARTREE: Total Merge Reffaces time: %f secs\n" 04220 // "\tTime to build: %f secs\n", 04221 // timer.cpu_secs()+time_to_build, time_to_build ); 04222 // } 04223 void MergeTool::test_no_tree(DLIList <RefFace*> &refface_list) 04224 { 04225 CpuTimer timer; 04226 double geom_factor = GeometryQueryTool::get_geometry_factor(); 04227 double tol = GEOMETRY_RESABS*geom_factor; 04228 DLIList<RefFace*> refface_array( refface_list.size() ); 04229 refface_list.reset(); 04230 04231 // Remove entities that should not be automatically merged 04232 int i = 0; 04233 int j; 04234 int loop_size = refface_list.size(); 04235 for( i = 0; i < loop_size; i++ ) 04236 { 04237 RefFace *curr_face = refface_list.get_and_step(); 04238 if( curr_face->is_mergeable() ) 04239 refface_array.append( curr_face ); 04240 } 04241 //initialize the marked flag for fast nulification... 04242 int array_size = refface_array.size(); 04243 RefFace *ref_face, *ref_face1; 04244 CubitBox temp_box, temp_box2; 04245 int hit = 0; 04246 for ( i = 0; i < array_size; i++ ) 04247 { 04248 ref_face = refface_array[i]; 04249 temp_box = ref_face->bounding_box(); 04250 for ( j = i+1; j<array_size; j++) 04251 { 04252 ref_face1 = refface_array[j]; 04253 temp_box2 = ref_face1->bounding_box(); 04254 if ( temp_box.overlap(tol, temp_box2) ) 04255 hit++; 04256 } 04257 } 04258 PRINT_INFO( "NO TREE: Merge Reffaces time: %f secs\n", 04259 timer.cpu_secs() ); 04260 } 04261 04262 04263 //------------------------------------------------------------------------- 04264 // Purpose : Force-merge vertices 04265 // 04266 // Special Notes : 04267 // 04268 // Creator : Jason Kraftcheck 04269 // 04270 // Creation Date : 05/10/04 04271 //------------------------------------------------------------------------- 04272 RefVertex* MergeTool::force_merge( RefVertex* vtx1, RefVertex* vtx2 ) 04273 { 04274 if (vtx1 == vtx2) 04275 return vtx1; 04276 04277 if (vtx1->id() > vtx2->id()) 04278 std::swap(vtx1, vtx2); 04279 04280 DLIList<RefFace*> faces1, faces2; 04281 DLIList<RefEdge*> edges1, edges2; 04282 04283 vtx1->ref_faces( faces1 ); 04284 vtx2->ref_faces( faces2 ); 04285 faces1.intersect( faces2 ); 04286 if (faces1.size()) 04287 { 04288 PRINT_ERROR("Vertices %d and %d are both in Surface %d. " 04289 "Cannot merge vertices in the same surface.\n", 04290 vtx1->id(), vtx2->id(), faces1.get()->id()); 04291 return NULL; 04292 } 04293 04294 vtx1->ref_edges( edges1 ); 04295 vtx2->ref_edges( edges2 ); 04296 edges1.intersect( edges2 ); 04297 if (edges1.size()) 04298 { 04299 PRINT_ERROR("Vertices %d and %d are both in Curve %d. " 04300 "Cannot merge vertices in the same curve.\n", 04301 vtx1->id(), vtx2->id(), edges1.get()->id()); 04302 return NULL; 04303 } 04304 04305 int k; 04306 for( k = assistant_list_.size(); k > 0; k-- ) 04307 if( ! assistant_list_.get_and_step()->can_merge( vtx1, vtx2 ) ) 04308 break; 04309 04310 if (k) 04311 return NULL; 04312 04313 if (!merge_BTE( vtx1, vtx2 )) 04314 return NULL; 04315 04316 if (destroyDeadGeometry) 04317 GeometryQueryTool::instance()->cleanout_deactivated_geometry(); 04318 04319 return vtx1; 04320 } 04321 04322 04323 //------------------------------------------------------------------------- 04324 // Purpose : Force-merge curves 04325 // 04326 // Special Notes : 04327 // 04328 // Creator : Jason Kraftcheck 04329 // 04330 // Creation Date : 05/10/04 04331 //------------------------------------------------------------------------- 04332 RefEdge* MergeTool::force_merge( RefEdge* edge1, RefEdge* edge2 ) 04333 { 04334 if (edge1 == edge2) 04335 return edge1; 04336 04337 if (edge1->id() > edge2->id()) 04338 std::swap(edge1, edge2); 04339 04340 DLIList<RefFace*> faces1, faces2; 04341 04342 edge1->ref_faces( faces1 ); 04343 edge2->ref_faces( faces2 ); 04344 faces1.intersect( faces2 ); 04345 if (faces1.size()) 04346 { 04347 PRINT_ERROR("Curves %d and %d are both in Surface %d. " 04348 "Cannot merge curves in the same surface.\n", 04349 edge1->id(), edge2->id(), faces1.get()->id()); 04350 return NULL; 04351 } 04352 04353 bool closed1 = edge1->start_vertex() == edge1->end_vertex(); 04354 bool closed2 = edge2->start_vertex() == edge2->end_vertex(); 04355 if (closed1 != closed2) 04356 { 04357 PRINT_ERROR("Curves %d and %d do not have the same number of vertices.\n", 04358 edge1->id(), edge2->id()); 04359 return NULL; 04360 } 04361 04362 int k; 04363 for( k = assistant_list_.size(); k > 0; k-- ) 04364 if( ! assistant_list_.get_and_step()->can_merge( edge1, edge2 ) ) 04365 break; 04366 04367 if (k) 04368 return NULL; 04369 04370 04371 CubitSense sense; 04372 CubitBoolean equal; 04373 if (!edge1->relative_sense( edge2, 1.0, &sense, equal, true)) 04374 return NULL; 04375 04376 if (closed1) 04377 { 04378 if (edge1->start_vertex() != edge2->start_vertex()) 04379 edge1->start_vertex()->comparison_found( edge2->start_vertex()); 04380 } 04381 else 04382 { 04383 RefVertex *start2 = edge2->start_vertex(); 04384 RefVertex *end2 = edge2->end_vertex(); 04385 if (sense == CUBIT_REVERSED) 04386 std::swap(start2, end2); 04387 04388 if (edge1->start_vertex() == end2 || edge1->end_vertex() == start2) 04389 { 04390 PRINT_ERROR("Error merging curves: invalid relative sense calculation.\n"); 04391 return NULL; 04392 } 04393 04394 if (edge1->start_vertex() != start2) 04395 edge1->start_vertex()->comparison_found( start2 ); 04396 if (edge1->end_vertex() != end2) 04397 edge1->end_vertex()->comparison_found( end2 ); 04398 } 04399 04400 if (!merge_BTE( edge1, edge2 )) 04401 { 04402 PRINT_ERROR("Merge failed.\n"); 04403 remove_compare_data(); 04404 return NULL; 04405 } 04406 04407 remove_compare_data(); 04408 if (destroyDeadGeometry) 04409 GeometryQueryTool::instance()->cleanout_deactivated_geometry(); 04410 04411 return edge1; 04412 } 04413 04414 //------------------------------------------------------------------------- 04415 // Purpose : Force-merge RefFaces 04416 // 04417 // Special Notes : 04418 // 04419 // Creator : Jason Kraftcheck 04420 // 04421 // Creation Date : 05/10/04 04422 //------------------------------------------------------------------------- 04423 RefFace* MergeTool::force_merge( RefFace* face1, RefFace* face2 ) 04424 { 04425 if (face1 == face2) 04426 return face1; 04427 04428 int i, j; 04429 if (face1->id() > face2->id()) 04430 std::swap(face1, face2); 04431 04432 DLIList<RefVolume*> vols1, vols2; 04433 04434 face1->ref_volumes( vols1 ); 04435 face2->ref_volumes( vols2 ); 04436 vols1.intersect( vols2 ); 04437 if (vols1.size()) 04438 { 04439 PRINT_ERROR("Surfaces %d and %d are both in Volume %d. " 04440 "Cannot merge surfaces in the same volume.\n", 04441 face1->id(), face2->id(), vols1.get()->id()); 04442 return NULL; 04443 } 04444 04445 DLIList<RefVertex*> vertices1, vertices2; 04446 DLIList<Loop*> loops1, loops2, tmp_loops; 04447 04448 face1->loops( loops1 ); 04449 face2->loops( loops2 ); 04450 face1->ref_vertices( vertices1 ); 04451 face2->ref_vertices( vertices2 ); 04452 04453 if (loops1.size() != loops2.size() || vertices1.size() != vertices2.size()) 04454 { 04455 PRINT_ERROR("Surfaces %d and %d do not have equivalent topology.\n", 04456 face1->id(), face2->id() ); 04457 return 0; 04458 } 04459 04460 // Need relative sense so we know in which order to compare 04461 // coedges of a loop and the expected sense of the coedges. 04462 CubitSense rel_sense = face1->compare_alignment( face2 ); 04463 if (rel_sense == CUBIT_UNKNOWN) 04464 { 04465 PRINT_ERROR("Cound not calculate relative sense of surfaces.\n"); 04466 return 0; 04467 } 04468 04469 // Remove from consideration any vertices that are already merged. 04470 DLIList<RefVertex*> common( vertices1 ); 04471 common.intersect( vertices2 ); 04472 vertices1 -= common; 04473 vertices2 -= common; 04474 04475 // Match vertex pairs 04476 vertices1.reset(); 04477 for (i = vertices1.size(); i--; ) 04478 { 04479 RefVertex* vtx1 = vertices1.get_and_step(); 04480 04481 RefVertex* closest = 0; 04482 double shortest = CUBIT_DBL_MAX; 04483 vertices2.reset(); 04484 for (j = vertices2.size(); j--; ) 04485 { 04486 RefVertex* vtx2 = vertices2.get_and_step(); 04487 double d = (vtx1->coordinates() - vtx2->coordinates()).length_squared(); 04488 if (d < shortest) 04489 { 04490 shortest = d; 04491 closest = vtx2; 04492 } 04493 } 04494 04495 vertices2.move_to( closest ); 04496 vertices2.extract(); 04497 if (vtx1 != closest) 04498 vtx1->comparison_found( closest ); 04499 } 04500 04501 // Compare all loops, find RefEdge merge pairs 04502 DLIList<CoEdge*> coedges1, coedges2; 04503 loops1.reset(); 04504 for (i = loops1.size(); i--; ) 04505 { 04506 Loop* loop1 = loops1.get_and_step(); 04507 04508 // Given a vertex in a loop in the first surface, 04509 // find the loop connected to that vertex and in 04510 // the second surface. 04511 vertices1.clean_out(); 04512 loop1->ref_vertices( vertices1 ); 04513 RefVertex* vtx = vertices1.get(); 04514 if (vtx->get_compare_partner()) 04515 vtx = dynamic_cast<RefVertex*>(vtx->get_compare_partner()); 04516 tmp_loops.clean_out(); 04517 vtx->loops( tmp_loops ); 04518 Loop* loop2 = 0; 04519 for (j = tmp_loops.size(); j--; ) 04520 { 04521 if (tmp_loops.step_and_get()->get_ref_face_ptr() == face2) 04522 { 04523 loop2 = tmp_loops.get(); 04524 break; 04525 } 04526 } 04527 04528 if (!loop2 || !loops2.move_to(loop2)) 04529 { 04530 PRINT_ERROR("RefFace topology does not match. Cannot merge surfaces %d and %d.\n", face1->id(), face2->id()); 04531 remove_compare_data(); 04532 return 0; 04533 } 04534 loops2.extract(); 04535 04536 // Compare loop coedges 04537 coedges1.clean_out(); 04538 coedges2.clean_out(); 04539 loop1->co_edges( coedges1 ); 04540 loop2->co_edges( coedges2 ); 04541 if (coedges1.size() != coedges2.size()) 04542 { 04543 PRINT_ERROR("RefFace topology does not match. Cannot merge surfaces %d and %d.\n", face1->id(), face2->id()); 04544 remove_compare_data(); 04545 return 0; 04546 } 04547 if (CUBIT_REVERSED == rel_sense) 04548 coedges2.reverse(); 04549 04550 // Given a coedge in the first loop, find the 04551 // matching coedge in the second loop 04552 coedges1.reset(); 04553 coedges2.reset(); 04554 RefVertex* start1 = coedges1.get()->start_vertex(); 04555 RefVertex* end1 = coedges1.get()->end_vertex(); 04556 if (CUBIT_REVERSED == rel_sense) 04557 std::swap(start1, end1); 04558 if (start1->get_compare_partner()) 04559 start1 = dynamic_cast<RefVertex*>(start1->get_compare_partner()); 04560 if (end1->get_compare_partner()) 04561 end1 = dynamic_cast<RefVertex*>(end1->get_compare_partner()); 04562 04563 for (j = coedges2.size(); j > 0; j-- ) 04564 { 04565 if (coedges2.get()->start_vertex() == start1 && 04566 coedges2.get()->end_vertex() == end1) 04567 break; 04568 04569 coedges2.step(); 04570 } 04571 04572 // No matching coedge 04573 if (!j) 04574 { 04575 PRINT_ERROR("RefFace topology does not match. Cannot merge surfaces %d and %d.\n", face1->id(), face2->id()); 04576 remove_compare_data(); 04577 return 0; 04578 } 04579 04580 // Check that remaining coedges match, and mark RefEdges accordingly 04581 for (j = coedges1.size(); j--; ) 04582 { 04583 CoEdge* coedge1 = coedges1.get_and_step(); 04584 CoEdge* coedge2 = coedges2.get_and_step(); 04585 if (coedge1->get_ref_edge_ptr() == coedge2->get_ref_edge_ptr()) 04586 continue; 04587 04588 RefVertex* start1 = coedge1->start_vertex(); 04589 RefVertex* end1 = coedge1->end_vertex(); 04590 if (CUBIT_REVERSED == rel_sense) 04591 std::swap(start1, end1); 04592 if (start1->get_compare_partner()) 04593 start1 = dynamic_cast<RefVertex*>(start1->get_compare_partner()); 04594 if (end1->get_compare_partner()) 04595 end1 = dynamic_cast<RefVertex*>(end1->get_compare_partner()); 04596 04597 if (coedge2->start_vertex() != start1 || 04598 coedge2->end_vertex() != end1) 04599 { 04600 PRINT_ERROR("RefFace topology does not match. Merge aborted.\n"); 04601 remove_compare_data(); 04602 return 0; 04603 } 04604 04605 coedge1->get_ref_edge_ptr()->comparison_found( coedge2->get_ref_edge_ptr()); 04606 } 04607 } // for(loops1) 04608 04609 // check if mesh can be merged, etc. 04610 for( i = assistant_list_.size(); i > 0; i-- ) 04611 if( ! assistant_list_.get_and_step()->can_merge( face1, face2 ) ) 04612 { remove_compare_data(); return 0; } 04613 04614 // merge 04615 if (!merge_BTE( face1, face2 )) 04616 { 04617 PRINT_ERROR("Merge Failed.\n"); 04618 remove_compare_data(); 04619 return 0; 04620 } 04621 04622 remove_compare_data(); 04623 if (destroyDeadGeometry) 04624 GeometryQueryTool::instance()->cleanout_deactivated_geometry(); 04625 04626 return face1; 04627 } 04628 04629 //------------------------------------------------------------------------- 04630 // Purpose : Force-merge RefEntities 04631 // 04632 // Special Notes : 04633 // 04634 // Creator : Jason Kraftcheck 04635 // 04636 // Creation Date : 05/10/04 04637 //------------------------------------------------------------------------- 04638 RefEntity* MergeTool::force_merge( RefEntity* ent1, RefEntity* ent2 ) 04639 { 04640 if (RefFace* face1 = dynamic_cast<RefFace*>(ent1)) 04641 { 04642 if (RefFace* face2 = dynamic_cast<RefFace*>(ent2)) 04643 return force_merge( face1, face2 ); 04644 } 04645 else if (RefEdge* edge1 = dynamic_cast<RefEdge*>(ent1)) 04646 { 04647 if (RefEdge* edge2 = dynamic_cast<RefEdge*>(ent2)) 04648 return force_merge( edge1, edge2 ); 04649 } 04650 else if (RefVertex* vtx1 = dynamic_cast<RefVertex*>(ent1)) 04651 { 04652 if (RefVertex* vtx2 = dynamic_cast<RefVertex*>(ent2)) 04653 return force_merge( vtx1, vtx2 ); 04654 } 04655 04656 PRINT_ERROR("Invalid entities passed to MergeTool::force_merge\n"); 04657 return NULL; 04658 } 04659 04660 //------------------------------------------------------------------------- 04661 // Purpose : Force-merge RefEntities 04662 // 04663 // Special Notes : Provied for use by CAMergeAttribute only 04664 // 04665 // Creator : Jason Kraftcheck 04666 // 04667 // Creation Date : 05/10/04 04668 //------------------------------------------------------------------------- 04669 RefEntity* MergeTool::force_merge( const DLIList<RefEntity*>& list ) 04670 { 04671 RefEntity* result = list.get(); 04672 for (int i = 1; result && i < list.size(); i++ ) 04673 result = force_merge( list.next(i), result ); 04674 return result; 04675 } 04676 04677 //------------------------------------------------------------------------- 04678 // Purpose : Un-merge 04679 // 04680 // Special Notes : 04681 // 04682 // Creator : Jason Kraftcheck 04683 // 04684 // Creation Date : 06/01/04 04685 //------------------------------------------------------------------------- 04686 CubitStatus MergeTool::separate_bodies( DLIList<Body*>& separate_list, 04687 DLIList<Body*>* from_list ) 04688 { 04689 CubitBoolean top = start_unmerge(); 04690 DLIList<RefVolume*> volume_list, tmp_list; 04691 separate_list.reset(); 04692 for (int i = separate_list.size(); i--; ) 04693 { 04694 Body* body = separate_list.get_and_step(); 04695 tmp_list.clean_out(); 04696 body->ref_volumes( tmp_list ); 04697 volume_list += tmp_list; 04698 } 04699 04700 CubitStatus result; 04701 if (from_list == NULL) 04702 { 04703 result = separate_volumes( volume_list, NULL ); 04704 } 04705 else 04706 { 04707 DLIList<RefVolume*> from_vols; 04708 from_list->reset(); 04709 for (int i = from_list->size(); i--; ) 04710 { 04711 Body* body = from_list->get_and_step(); 04712 tmp_list.clean_out(); 04713 body->ref_volumes( tmp_list ); 04714 from_vols += tmp_list; 04715 } 04716 04717 result = separate_volumes( volume_list, &from_vols ); 04718 } 04719 04720 end_unmerge(top); 04721 return result; 04722 } 04723 04724 //------------------------------------------------------------------------- 04725 // Purpose : Unmerge 04726 // 04727 // Special Notes : 04728 // 04729 // Creator : Jason Kraftcheck 04730 // 04731 // Creation Date : 06/01/04 04732 //------------------------------------------------------------------------- 04733 CubitStatus MergeTool::separate_volumes( DLIList<RefVolume*>& split_list, 04734 DLIList<RefVolume*>* from_list ) 04735 { 04736 DLIList<TopologyEntity*> entity_list( split_list.size() ); 04737 CAST_LIST_TO_PARENT( split_list, entity_list ); 04738 if (from_list) 04739 { 04740 DLIList<TopologyEntity*> from_list2( from_list->size() ); 04741 CAST_LIST_TO_PARENT( *from_list, from_list2 ); 04742 return separate_entities( entity_list, &from_list2 ); 04743 } 04744 else 04745 { 04746 return separate_entities( entity_list ); 04747 } 04748 } 04749 CubitStatus MergeTool::separate_faces( DLIList<RefFace*>& split_list, 04750 DLIList<RefFace*>* from_list ) 04751 { 04752 DLIList<TopologyEntity*> entity_list( split_list.size() ); 04753 CAST_LIST_TO_PARENT( split_list, entity_list ); 04754 if (from_list) 04755 { 04756 DLIList<TopologyEntity*> from_list2( from_list->size() ); 04757 CAST_LIST_TO_PARENT( *from_list, from_list2 ); 04758 return separate_entities( entity_list, &from_list2 ); 04759 } 04760 else 04761 { 04762 return separate_entities( entity_list ); 04763 } 04764 } 04765 CubitStatus MergeTool::separate_edges( DLIList<RefEdge*>& split_list, 04766 DLIList<RefEdge*>* from_list ) 04767 { 04768 DLIList<TopologyEntity*> entity_list( split_list.size() ); 04769 CAST_LIST_TO_PARENT( split_list, entity_list ); 04770 if (from_list) 04771 { 04772 DLIList<TopologyEntity*> from_list2( from_list->size() ); 04773 CAST_LIST_TO_PARENT( *from_list, from_list2 ); 04774 return separate_entities( entity_list, &from_list2 ); 04775 } 04776 else 04777 { 04778 return separate_entities( entity_list ); 04779 } 04780 } 04781 04782 04783 //------------------------------------------------------------------------- 04784 // Purpose : Unmerge 04785 // 04786 // Special Notes : 04787 // 04788 // Creator : Jason Kraftcheck 04789 // 04790 // Creation Date : 06/02/04 04791 //------------------------------------------------------------------------- 04792 CubitStatus MergeTool::separate_entities( DLIList<TopologyEntity*>& volume_list, 04793 DLIList<TopologyEntity*>* from_list ) 04794 { 04795 int i, j, k, l; 04796 CubitBoolean top = start_unmerge(); 04797 CubitStatus result = CUBIT_SUCCESS; 04798 04799 if (!volume_list.size()) 04800 return CUBIT_FAILURE; 04801 04802 DagType parent_type = volume_list.get()->dag_type(); 04803 for (i = volume_list.size(); i--;) 04804 if (volume_list.get_and_step()->dag_type() != parent_type) 04805 return CUBIT_FAILURE; 04806 if (from_list) 04807 for (i = from_list->size(); i--; ) 04808 if (from_list->get_and_step()->dag_type() != parent_type) 04809 return CUBIT_FAILURE; 04810 04811 04812 DLIList<TopologyEntity*> query_input( volume_list.size() ), query_output; 04813 CAST_LIST_TO_PARENT( volume_list, query_input ); 04814 DLIList<TopologyBridge*> bridge_list, split_list, parent_bridges; 04815 DLIList<TopologyEntity*> entity_vol_list; 04816 DLIList<BasicTopologyEntity*> entity_list; 04817 DLIList<Lump*> lump_list; 04818 DLIList<Surface*> surface_list; 04819 DLIList<Curve*> curve_list; 04820 DLIList<TBPoint*> point_list; 04821 04822 04823 // Loop once for each type, 04824 DagType types[] = { DagType::ref_face_type(), 04825 DagType::ref_edge_type(), 04826 DagType::ref_vertex_type() }; 04827 for (j = 0; j < 3; j++) 04828 { 04829 if (types[j] >= parent_type) 04830 continue; 04831 04832 // Get RefFaces/RefEdges/RefVertices from RefVolumes 04833 query_output.clean_out(); 04834 entity_list.clean_out(); 04835 ModelQueryEngine::instance()->query_model( query_input, types[j], query_output ); 04836 CAST_LIST( query_output, entity_list, BasicTopologyEntity ); 04837 04838 entity_list.reset(); 04839 for (i = entity_list.size(); i--; ) 04840 { 04841 BasicTopologyEntity* entity = entity_list.get_and_step(); 04842 split_list.clean_out(); 04843 04844 // Get parent volumes to unmerge from 04845 entity_vol_list.clean_out(); 04846 query_output.clean_out(); 04847 ModelQueryEngine::instance()->query_model( *entity, parent_type, query_output ); 04848 CAST_LIST( query_output, entity_vol_list, TopologyEntity ); 04849 entity_vol_list -= volume_list; 04850 if (from_list) 04851 entity_vol_list.intersect( *from_list ); 04852 if (!entity_vol_list.size()) 04853 continue; 04854 04855 // For each merged bridge in the entity 04856 bridge_list.clean_out(); 04857 entity->bridge_manager()->get_bridge_list( bridge_list ); 04858 bridge_list.reset(); 04859 for (k = bridge_list.size(); k--; ) 04860 { 04861 TopologyBridge* bridge = bridge_list.get_and_step(); 04862 04863 parent_bridges.clean_out(); 04864 if (parent_type == DagType::ref_volume_type()) 04865 { 04866 lump_list.clean_out(); 04867 bridge->lumps( lump_list ); 04868 CAST_LIST_TO_PARENT( lump_list, parent_bridges ); 04869 } 04870 else if(parent_type == DagType::ref_face_type()) 04871 { 04872 surface_list.clean_out(); 04873 bridge->surfaces( surface_list ); 04874 CAST_LIST_TO_PARENT( surface_list, parent_bridges ); 04875 } 04876 else if(parent_type == DagType::ref_edge_type()) 04877 { 04878 curve_list.clean_out(); 04879 bridge->curves( curve_list ); 04880 CAST_LIST_TO_PARENT( curve_list, parent_bridges ); 04881 } 04882 else 04883 { 04884 assert(0); 04885 return CUBIT_FAILURE; 04886 } 04887 04888 // Check if bridge is in RefVolumes to unmerge from 04889 04890 for (l = parent_bridges.size(); l--; ) 04891 { 04892 TopologyBridge* lump = parent_bridges.get_and_step(); 04893 if (entity_vol_list.is_in_list(lump->topology_entity())) 04894 split_list.append( bridge ); 04895 } 04896 } 04897 04898 // If there are bridges to unmerge... 04899 if (split_list.size() != 0 && split_list.size() != bridge_list.size()) 04900 { 04901 if (types[j] == DagType::ref_face_type()) 04902 { 04903 surface_list.clean_out(); 04904 CAST_LIST( split_list, surface_list, Surface ); 04905 RefFace* face = separate_face( surface_list, false ); 04906 if (0 == face) 04907 result = CUBIT_FAILURE; 04908 } 04909 else if(types[j] == DagType::ref_edge_type()) 04910 { 04911 curve_list.clean_out(); 04912 CAST_LIST( split_list, curve_list, Curve ); 04913 RefEdge* edge = separate_edge( curve_list, false ); 04914 if (0 == edge) 04915 result = CUBIT_FAILURE; 04916 } 04917 else 04918 { 04919 point_list.clean_out(); 04920 CAST_LIST( split_list, point_list, TBPoint ); 04921 assert( split_list.size() == point_list.size() ); 04922 RefVertex* vtx = separate_vertex( point_list ); 04923 if (0 == vtx) 04924 result = CUBIT_FAILURE; 04925 } 04926 } 04927 } // for(i in entity_list) 04928 } // for(j in type) 04929 04930 end_unmerge(top); 04931 return result; 04932 } 04933 04934 04935 04936 //------------------------------------------------------------------------- 04937 // Purpose : Common code for separate functions. 04938 // Check if bridges have same owner (are merged together), 04939 // and if check_parents == true, check if unmerging the 04940 // bridges will invalidate the parent topology. 04941 // 04942 // Special Notes : 04943 // 04944 // Creator : Jason Kraftcheck 04945 // 04946 // Creation Date : 06/01/04 04947 //------------------------------------------------------------------------- 04948 BasicTopologyEntity* MergeTool::can_separate( DLIList<TopologyBridge*>& bridges, 04949 bool check_parents ) 04950 { 04951 int i; 04952 BasicTopologyEntity* bte = 0; 04953 04954 TBOwner* owner = bridges.get_and_step()->owner(); 04955 for (i = bridges.size(); i > 1; i--) 04956 if (bridges.get_and_step()->owner() != owner) 04957 return 0; 04958 04959 BridgeManager* bmanager = dynamic_cast<BridgeManager*>(owner); 04960 if (!bmanager) 04961 { assert(0); return 0; } 04962 04963 bte = dynamic_cast<BasicTopologyEntity*>(bmanager->topology_entity()); 04964 if (!bte) 04965 { assert(0); return 0; } 04966 04967 if (bmanager->number_of_bridges() == bridges.size()) 04968 return 0; 04969 04970 if (!check_parents) 04971 return bte; 04972 04973 DLIList<TopologyBridge*> parent_bridges, bte_bridges; 04974 DLIList<TBOwner*> parent_owners; 04975 bte->bridge_manager()->get_bridge_list( bte_bridges ); 04976 bte_bridges -= bridges; 04977 04978 for (i = bte_bridges.size(); i--;) 04979 { 04980 bte_bridges.step_and_get()->get_parents( parent_bridges ); 04981 while (parent_bridges.size()) 04982 parent_owners.append( parent_bridges.pop()->owner() ); 04983 } 04984 for (i = bridges.size(); i--; ) 04985 { 04986 bridges.step_and_get()->get_parents( parent_bridges ); 04987 while (parent_bridges.size()) 04988 if (parent_owners.is_in_list( parent_bridges.pop()->owner() )) 04989 return 0; 04990 } 04991 04992 return bte; 04993 } 04994 04995 04996 //------------------------------------------------------------------------- 04997 // Purpose : Split a RefFace 04998 // 04999 // Special Notes : 05000 // 05001 // Creator : Jason Kraftcheck 05002 // 05003 // Creation Date : 06/01/04 05004 //------------------------------------------------------------------------- 05005 RefFace* MergeTool::separate_face( DLIList<Surface*>& surfaces, 05006 bool unmerge_curves ) 05007 { 05008 int i, j, k; 05009 05010 DLIList<TopologyBridge*> bridge_list( surfaces.size() ); 05011 CAST_LIST_TO_PARENT( surfaces, bridge_list ); 05012 RefFace* old_face = dynamic_cast<RefFace*>( can_separate( bridge_list, false ) ); 05013 if (!old_face) 05014 return 0; 05015 05016 CubitBoolean top = start_unmerge(); 05017 05018 // Split the RefFace 05019 05020 // Remove surfaces from old entity 05021 for (i = surfaces.size(); i--; ) 05022 old_face->bridge_manager()->remove_bridge( surfaces.get_and_step() ); 05023 check_saved_id( old_face ); 05024 surfaces.reset(); 05025 // Use surface with smallest saved ID as primary 05026 for (j = 0, i = 1; i < surfaces.size(); i++) 05027 if (surfaces.next(i)->get_saved_id() < surfaces.next(j)->get_saved_id()) 05028 j = i; 05029 surfaces.step( j ); 05030 // Create new face 05031 RefFace* new_face = RefEntityFactory::instance()->construct_RefFace( surfaces.get() ); 05032 05033 for (i = surfaces.size(); i > 1; i-- ) 05034 new_face->bridge_manager()->add_bridge( surfaces.step_and_get() ); 05035 05036 // Move CoFaces 05037 bridge_list.clean_out(); 05038 DLIList<TopologyBridge*> bridge_parents; 05039 DLIList<TopologyEntity*> shells; 05040 DLIList<CoFace*> co_faces; 05041 old_face->co_faces( co_faces ); 05042 for (i = surfaces.size(); i > 0; i--) 05043 { 05044 surfaces.get_and_step()->get_parents( bridge_list ); 05045 while (bridge_list.size()) 05046 shells.append( bridge_list.pop()->topology_entity() ); 05047 } 05048 co_faces.reset(); 05049 for (i = co_faces.size(); i--; ) 05050 { 05051 CoFace* co_face = co_faces.get_and_step(); 05052 if (shells.is_in_list( co_face->get_grouping_entity_ptr() )) 05053 { 05054 co_face->switch_basic_topology_entity( new_face ); 05055 } 05056 } 05057 05058 // Split loops and coedges 05059 DLIList<Loop*> loops; 05060 DLIList<CoEdge*> coedges; 05061 DLIList<SenseEntity*> new_coedges, junk_list; 05062 DLIList<TopologyBridge*> loop_bridges; 05063 old_face->loops( loops ); 05064 loops.reset(); 05065 for (i = loops.size(); i--; ) 05066 { 05067 Loop* old_loop = loops.get_and_step(); 05068 Loop* new_loop = new Loop; 05069 new_face->add_grouping_entity( new_loop ); 05070 05071 loop_bridges.clean_out(); 05072 bridge_list.clean_out(); 05073 old_loop->bridge_manager()->get_bridge_list( bridge_list ); 05074 bridge_list.reset(); 05075 for (j = bridge_list.size(); j--; ) 05076 { 05077 TopologyBridge* loopsm = bridge_list.get_and_step(); 05078 loopsm->get_parents( bridge_parents ); 05079 Surface* loop_surf = dynamic_cast<Surface*>(bridge_parents.pop()); 05080 assert (loop_surf && !bridge_parents.size()); 05081 if (surfaces.is_in_list(loop_surf)) 05082 { 05083 old_loop->bridge_manager()->remove_bridge( loopsm ); 05084 new_loop->bridge_manager()->add_bridge( loopsm ); 05085 loop_bridges.append( loopsm ); 05086 } 05087 } 05088 05089 new_coedges.clean_out(); 05090 coedges.clean_out(); 05091 old_loop->co_edges( coedges ); 05092 coedges.reset(); 05093 for (j = coedges.size(); j--; ) 05094 { 05095 CoEdge* old_coedge = coedges.get_and_step(); 05096 CoEdge* new_coedge = new CoEdge( old_coedge->get_ref_edge_ptr(), 05097 old_coedge->get_sense() ); 05098 new_coedges.append( new_coedge ); 05099 05100 bridge_list.clean_out(); 05101 old_coedge->bridge_manager()->get_bridge_list( bridge_list ); 05102 bridge_list.reset(); 05103 for (k = bridge_list.size(); k--; ) 05104 { 05105 TopologyBridge* coedgesm = bridge_list.get_and_step(); 05106 coedgesm->get_parents( bridge_parents ); 05107 LoopSM* coedgesm_loop = dynamic_cast<LoopSM*>(bridge_parents.pop()); 05108 assert (coedgesm_loop && !bridge_parents.size()); 05109 if (loop_bridges.is_in_list(coedgesm_loop)) 05110 { 05111 old_coedge->bridge_manager()->remove_bridge( coedgesm ); 05112 new_coedge->bridge_manager()->add_bridge( coedgesm ); 05113 } 05114 } 05115 } 05116 05117 new_loop->set_sense_entity_list( new_coedges, junk_list ); 05118 } 05119 05120 // Check if should reverse new face 05121 bool reverse_new = true; 05122 for (i = surfaces.size(); i--; ) 05123 if (surfaces.get_and_step()->bridge_sense() != CUBIT_REVERSED) 05124 reverse_new = false; 05125 if (reverse_new) 05126 { 05127 new_face->bridge_manager()->reverse_bridge_senses(); 05128 new_face->reverse_topology(); 05129 } 05130 05131 // Check if should reverse old face 05132 bool reverse_old = true; 05133 bridge_list.clean_out(); 05134 old_face->bridge_manager()->get_bridge_list( bridge_list ); 05135 for (i = bridge_list.size(); i--; ) 05136 if (bridge_list.get_and_step()->bridge_sense() != CUBIT_REVERSED) 05137 reverse_old = false; 05138 if (reverse_old) 05139 { 05140 old_face->bridge_manager()->reverse_bridge_senses(); 05141 old_face->reverse_topology(); 05142 } 05143 05144 // Misc stuff for updating other code for changed topology 05145 bool reversed = reverse_old != reverse_new; 05146 new_unmerged.append( new_face ); 05147 old_unmerged.append( old_face ); 05148 for (i = assistant_list_.size(); i--; ) 05149 assistant_list_.get_and_step()->unmerged( old_face, new_face, reversed ); 05150 05151 if (unmerge_curves) 05152 { 05153 DLIList<RefEdge*> edge_list; 05154 DLIList<Curve*> curve_list; 05155 DLIList<TopologyBridge*> bridge_children; 05156 new_face->ref_edges( edge_list ); 05157 edge_list.reset(); 05158 05159 for (i = edge_list.size(); i--;) 05160 { 05161 curve_list.clean_out(); 05162 05163 RefEdge* edge = edge_list.get_and_step(); 05164 bridge_list.clean_out(); 05165 edge->bridge_manager()->get_bridge_list( bridge_list ); 05166 if (bridge_list.size() < 2) 05167 continue; 05168 05169 // Find the curve(s) in the just-unmerged refface 05170 bridge_list.reset(); 05171 DLIList<Curve*> other_curves_to_unmerge; 05172 for (j = bridge_list.size(); j--; ) 05173 { 05174 TopologyBridge* bridge = bridge_list.get_and_step(); 05175 bridge_parents.clean_out(); 05176 bridge->get_parents( bridge_parents ); 05177 bridge_parents.reset(); 05178 bool in_old = false, in_new = false; 05179 05180 while (bridge_parents.size()) 05181 { 05182 CoEdge* coedge = dynamic_cast<CoEdge*>(bridge_parents.pop()->topology_entity()); 05183 BasicTopologyEntity* bte = coedge->get_parent_basic_topology_entity_ptr(); 05184 if (bte == new_face) 05185 in_new = true; 05186 else if(bte == old_face) 05187 in_old = true; 05188 } 05189 05190 if (in_old && in_new) 05191 { 05192 curve_list.clean_out(); 05193 break; 05194 } 05195 else if(in_new) 05196 { 05197 curve_list.append( dynamic_cast<Curve*>(bridge) ); 05198 continue; 05199 } 05200 05201 //Some other curves might be merge candidates now.. 05202 //If both surfaces on either side of the curve have been unmerged, 05203 //then this curve can be unmerged too. 05204 bool unmerge_curve = true; 05205 bridge_parents.clean_out(); 05206 bridge->get_parents( bridge_parents ); 05207 while (bridge_parents.size()) 05208 { 05209 CoEdge* coedge = dynamic_cast<CoEdge*>(bridge_parents.pop()->topology_entity()); 05210 if( coedge->bridge_manager()->number_of_bridges() != 1 ) 05211 { 05212 unmerge_curve = false; 05213 break; 05214 } 05215 } 05216 05217 if( unmerge_curve == true ) 05218 other_curves_to_unmerge.append_unique( dynamic_cast<Curve*>(bridge) ); 05219 05220 } // for( j in bridge_list ) 05221 05222 // Find curve(s) that must remain merged. 05223 curve_list.reset(); 05224 for (j = 0; j < curve_list.size(); j++) 05225 { 05226 bridge_parents.clean_out(); 05227 curve_list.get_and_step()->get_parents( bridge_parents ); 05228 bridge_parents.reset(); 05229 for (k = 0; k< bridge_parents.size(); k++) 05230 { 05231 bridge_list.clean_out(); 05232 BridgeManager* bm = bridge_parents.get_and_step()->bridge_manager(); 05233 bm->get_bridge_list( bridge_list ); 05234 05235 bridge_list.reset(); 05236 for (int l = bridge_list.size(); l--; ) 05237 { 05238 bridge_children.clean_out(); 05239 bridge_list.get_and_step()->get_children( bridge_children ); 05240 assert (bridge_children.size() == 1); // bridges are coedges, must have 1 curve 05241 Curve* curve = dynamic_cast<Curve*>(bridge_children.get()); 05242 assert (curve->owner() == edge->bridge_manager()); 05243 curve_list.append_unique( curve ); 05244 } 05245 } 05246 } // for( j in curve_list ) 05247 05248 if (curve_list.size() != 0 && 05249 curve_list.size() != edge->bridge_manager()->number_of_bridges()) 05250 { 05251 separate_edge( curve_list, true ); 05252 } 05253 05254 if( other_curves_to_unmerge.size() ) 05255 separate_edge( other_curves_to_unmerge, true ); 05256 05257 } // for (i in edge_list) 05258 } // if (unmerge_curves) 05259 05260 end_unmerge(top); 05261 return new_face; 05262 } 05263 05264 05265 //------------------------------------------------------------------------- 05266 // Purpose : Split a RefEdge 05267 // 05268 // Special Notes : 05269 // 05270 // Creator : Jason Kraftcheck 05271 // 05272 // Creation Date : 06/01/04 05273 //------------------------------------------------------------------------- 05274 RefEdge* MergeTool::separate_edge( DLIList<Curve*>& curves, 05275 bool unmerge_vertices ) 05276 { 05277 int i, j, k; 05278 05279 DLIList<TopologyBridge*> bridge_list( curves.size() ); 05280 CAST_LIST_TO_PARENT( curves, bridge_list ); 05281 RefEdge* old_edge = dynamic_cast<RefEdge*>( can_separate( bridge_list, true ) ); 05282 if (!old_edge) 05283 return 0; 05284 05285 bool old_edge_free_before = true; 05286 if( old_edge->num_parent_ref_entities() ) 05287 old_edge_free_before = false; 05288 05289 CubitBoolean top = start_unmerge(); 05290 05291 // Split the RefEdge 05292 05293 // Remove curves from old edge 05294 for (i = curves.size(); i--; ) 05295 old_edge->bridge_manager()->remove_bridge( curves.get_and_step() ); 05296 check_saved_id( old_edge ); 05297 curves.reset(); 05298 // Use curve with smallest saved ID as primary 05299 for (j = 0, i = 1; i < curves.size(); i++) 05300 if (curves.next(i)->get_saved_id() < curves.next(j)->get_saved_id()) 05301 j = i; 05302 curves.step( j ); 05303 // Create new edge 05304 RefEdge* new_edge = RefEntityFactory::instance()->construct_RefEdge( curves.get() ); 05305 05306 for (i = curves.size(); i > 1; i-- ) 05307 new_edge->bridge_manager()->add_bridge( curves.step_and_get() ); 05308 05309 // Move CoEdges 05310 bridge_list.clean_out(); 05311 DLIList<TopologyEntity*> new_coedges; 05312 DLIList<CoEdge*> old_coedges; 05313 old_edge->co_edges( old_coedges ); 05314 for (i = curves.size(); i > 0; i--) 05315 { 05316 curves.get_and_step()->get_parents( bridge_list ); 05317 while (bridge_list.size()) 05318 new_coedges.append( bridge_list.pop()->topology_entity() ); 05319 } 05320 old_coedges.reset(); 05321 for (i = old_coedges.size(); i--; ) 05322 { 05323 CoEdge* co_edge = old_coedges.get_and_step(); 05324 if (new_coedges.is_in_list( co_edge )) 05325 { 05326 co_edge->switch_basic_topology_entity( new_edge ); 05327 } 05328 } 05329 05330 // Construct chain and co-vertices 05331 Chain* new_chain = new Chain; 05332 new_edge->add_grouping_entity( new_chain ); 05333 CoVertex* start = new CoVertex( old_edge->start_vertex() ); 05334 new_chain->add_sense_entity( start ); 05335 CoVertex* end = new CoVertex( old_edge->end_vertex() ); 05336 new_chain->add_sense_entity( end, start ); 05337 05338 // Check if should reverse new edge 05339 bool reverse_new = true; 05340 for (i = curves.size(); i--; ) 05341 if (curves.get_and_step()->bridge_sense() != CUBIT_REVERSED) 05342 reverse_new = false; 05343 if (reverse_new) 05344 { 05345 new_edge->bridge_manager()->reverse_bridge_senses(); 05346 new_edge->reverse_topology(); 05347 } 05348 05349 // Check if should reverse old edge 05350 bool reverse_old = true; 05351 bridge_list.clean_out(); 05352 old_edge->bridge_manager()->get_bridge_list( bridge_list ); 05353 for (i = bridge_list.size(); i--; ) 05354 if (bridge_list.get_and_step()->bridge_sense() != CUBIT_REVERSED) 05355 reverse_old = false; 05356 if (reverse_old) 05357 { 05358 old_edge->bridge_manager()->reverse_bridge_senses(); 05359 old_edge->reverse_topology(); 05360 } 05361 05362 // Misc stuff for updating other code for changed topology 05363 bool reversed = reverse_old != reverse_new; 05364 new_unmerged.append( new_edge ); 05365 old_unmerged.append( old_edge ); 05366 for (i = assistant_list_.size(); i--; ) 05367 assistant_list_.get_and_step()->unmerged( old_edge, new_edge, reversed ); 05368 05369 if (unmerge_vertices) 05370 { 05371 // Split vertices 05372 DLIList<TBPoint*> point_list; 05373 DLIList<TopologyBridge*> parent_curves, curve_points; 05374 05375 int n_vert = old_edge->num_ref_vertices(); 05376 assert(n_vert < 3); 05377 05378 for (i = 0; i < n_vert; i++) 05379 { 05380 point_list.clean_out(); 05381 #ifndef NDEBUG 05382 RefVertex* vtx = i ? old_edge->end_vertex() : old_edge->start_vertex(); 05383 #endif 05384 CubitSense sense = i ? CUBIT_REVERSED : CUBIT_FORWARD; 05385 05386 curves.reset(); 05387 for (j = curves.size(); j--; ) 05388 { 05389 Curve* curve = curves.get_and_step(); 05390 bridge_list.clean_out(); 05391 curve->get_children( bridge_list ); 05392 bridge_list.reset(); 05393 if (reversed != (curve->bridge_sense() != sense)) 05394 bridge_list.step(); 05395 TBPoint* point = dynamic_cast<TBPoint*>(bridge_list.get()); 05396 assert (point->owner() == vtx->bridge_manager()); 05397 point_list.append( point ); 05398 } 05399 05400 for (j = 0; j < point_list.size(); j++) 05401 { 05402 point_list.reset(); 05403 point_list.step(j); 05404 TBPoint* point = point_list.get(); 05405 parent_curves.clean_out(); 05406 point->get_parents( parent_curves ); 05407 05408 parent_curves.reset(); 05409 for (k = parent_curves.size(); k--; ) 05410 { 05411 TopologyBridge* curve = parent_curves.get_and_step(); 05412 BridgeManager* bm = curve->bridge_manager(); 05413 bridge_list.clean_out(); 05414 bm->get_bridge_list( bridge_list ); 05415 05416 bridge_list.reset(); 05417 for (int l = bridge_list.size(); l--; ) 05418 { 05419 curve_points.clean_out(); 05420 bridge_list.get_and_step()->get_children( curve_points ); 05421 assert(curve_points.size() < 3); 05422 if (curve_points.get()->owner() == point->owner()) 05423 point_list.append_unique( dynamic_cast<TBPoint*>(curve_points.get()) ); 05424 else if (curve_points.next()->owner() == point->owner()) 05425 point_list.append_unique( dynamic_cast<TBPoint*>(curve_points.next()) ); 05426 } 05427 } 05428 } 05429 separate_vertex( point_list ); 05430 } 05431 } 05432 05433 if( !old_edge_free_before && old_edge->num_parent_ref_entities() == 0 ) 05434 { 05435 AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::FREE_REF_ENTITY_GENERATED, old_edge)); 05436 CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_CREATED, old_edge ); 05437 GeometryQueryTool::instance()->history().add_event(evt); 05438 } 05439 05440 05441 end_unmerge(top); 05442 return new_edge; 05443 } 05444 05445 05446 05447 //------------------------------------------------------------------------- 05448 // Purpose : Split a RefVertex 05449 // 05450 // Special Notes : 05451 // 05452 // Creator : Jason Kraftcheck 05453 // 05454 // Creation Date : 06/01/04 05455 //------------------------------------------------------------------------- 05456 RefVertex* MergeTool::separate_vertex( DLIList<TBPoint*>& points ) 05457 { 05458 int i, j; 05459 DLIList<TopologyBridge*> bridge_list( points.size() ); 05460 CAST_LIST_TO_PARENT( points, bridge_list ); 05461 RefVertex* old_vtx = dynamic_cast<RefVertex*>( can_separate( bridge_list, true ) ); 05462 if (!old_vtx) 05463 return 0; 05464 05465 bool old_vtx_free_before = true; 05466 if( old_vtx->num_parent_ref_entities() ) 05467 old_vtx_free_before = false; 05468 05469 CubitBoolean top = start_unmerge(); 05470 05471 // Split the RefVertex 05472 05473 // Remove points from old vertex 05474 for (i = points.size(); i--; ) 05475 old_vtx->bridge_manager()->remove_bridge( points.get_and_step() ); 05476 check_saved_id( old_vtx ); 05477 points.reset(); 05478 // Use point with smallest saved ID as primary 05479 for (j = 0, i = 1; i < points.size(); i++) 05480 if (points.next(i)->get_saved_id() < points.next(j)->get_saved_id()) 05481 j = i; 05482 points.step( j ); 05483 // Create new vertex 05484 RefVertex* new_vtx = RefEntityFactory::instance()->construct_RefVertex( points.get() ); 05485 for (i = points.size(); i > 1; i-- ) 05486 new_vtx->bridge_manager()->add_bridge( points.step_and_get() ); 05487 05488 // Move CoVertices 05489 bridge_list.clean_out(); 05490 DLIList<TopologyEntity*> edges; 05491 DLIList<CoVertex*> co_vertices; 05492 old_vtx->co_vertices( co_vertices ); 05493 for (i = points.size(); i > 0; i--) 05494 { 05495 points.get_and_step()->get_parents( bridge_list ); 05496 while (bridge_list.size()) 05497 edges.append( bridge_list.pop()->topology_entity() ); 05498 } 05499 co_vertices.reset(); 05500 for (i = co_vertices.size(); i--; ) 05501 { 05502 CoVertex* covtx = co_vertices.get_and_step(); 05503 if (edges.is_in_list( covtx->get_parent_basic_topology_entity_ptr() )) 05504 { 05505 covtx->switch_basic_topology_entity( new_vtx ); 05506 } 05507 } 05508 05509 // Misc stuff for updating other code for changed topology 05510 new_unmerged.append( new_vtx ); 05511 old_unmerged.append( old_vtx ); 05512 for (i = assistant_list_.size(); i--; ) 05513 assistant_list_.get_and_step()->unmerged( old_vtx, new_vtx, false ); 05514 05515 if( !old_vtx_free_before && old_vtx->num_parent_ref_entities() == 0 ) 05516 { 05517 AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::FREE_REF_ENTITY_GENERATED, old_vtx)); 05518 CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_CREATED, old_vtx ); 05519 GeometryQueryTool::instance()->history().add_event(evt); 05520 } 05521 05522 05523 end_unmerge(top); 05524 return new_vtx; 05525 } 05526 05527 05528 //------------------------------------------------------------------------- 05529 // Purpose : Set entity ID to smallest saved bridge ID 05530 // 05531 // Special Notes : 05532 // 05533 // Creator : Jason Kraftcheck 05534 // 05535 // Creation Date : 06/03/04 05536 //------------------------------------------------------------------------- 05537 CubitStatus MergeTool::check_saved_id( BasicTopologyEntity* bte ) 05538 { 05539 DLIList<TopologyBridge*> bridge_list; 05540 bte->bridge_manager()->get_bridge_list( bridge_list ); 05541 05542 bridge_list.reset(); 05543 int smallest = dynamic_cast<GeometryEntity*>(bridge_list.get())->get_saved_id(); 05544 if (smallest == bte->id()) 05545 return CUBIT_SUCCESS; 05546 05547 for (int i = 1; i < bridge_list.size(); i++) 05548 { 05549 int id = dynamic_cast<GeometryEntity*>(bridge_list.next(i))->get_saved_id(); 05550 // if (!id) 05551 // ; 05552 if (id == bte->id()) 05553 return CUBIT_SUCCESS; 05554 else if(id < smallest) 05555 smallest = id; 05556 } 05557 05558 if (smallest) 05559 { 05560 //make sure this id isn't in use already 05561 RefEntity *tmp_ent = 05562 RefEntityFactory::instance()->get_ref_entity( bte->entity_type_info(), smallest ); 05563 05564 if( tmp_ent == NULL ) 05565 bte->set_id(smallest); 05566 } 05567 05568 return CUBIT_SUCCESS; 05569 } 05570 05571 05572 CubitBoolean MergeTool::about_spatially_equal( Surface *surf_1, Surface *surf_2, 05573 double tolerance_factor ) 05574 { 05575 if( surf_1 == surf_2 ) 05576 return CUBIT_TRUE; 05577 05578 //make sure number of edges between surfaces is identical 05579 DLIList<Curve*> surf_1_edges; 05580 DLIList<Curve*> surf_2_edges; 05581 surf_1->curves( surf_1_edges ); 05582 surf_2->curves( surf_2_edges ); 05583 if( surf_1_edges.size() != surf_2_edges.size() ) 05584 return CUBIT_FALSE; 05585 05586 int test_internal = GeometryQueryTool::get_merge_test_internal(); 05587 if( test_internal == 2 ) 05588 { 05589 const GeometryType surf_1_type = surf_1->geometry_type(); 05590 const GeometryType surf_2_type = surf_2->geometry_type(); 05591 05592 if (surf_1_type != SPLINE_SURFACE_TYPE && 05593 surf_1_type != BEST_FIT_SURFACE_TYPE && 05594 surf_1_type != UNDEFINED_SURFACE_TYPE && 05595 surf_2_type != SPLINE_SURFACE_TYPE && 05596 surf_2_type != BEST_FIT_SURFACE_TYPE && 05597 surf_2_type != UNDEFINED_SURFACE_TYPE ) 05598 test_internal = 0; 05599 } 05600 05601 //make sure number of loops between surfaces is identical 05602 DLIList<LoopSM*> surf_1_loops; 05603 DLIList<LoopSM*> surf_2_loops; 05604 surf_1->loopsms( surf_1_loops ); 05605 surf_2->loopsms( surf_2_loops ); 05606 if( surf_1_loops.size() != surf_2_loops.size() ) 05607 return CUBIT_FALSE; 05608 05609 //compare algnment (sense) 05610 CubitSense relative_sense = CUBIT_FORWARD; 05611 CubitVector bbox_center = surf_1->bounding_box().center(); 05612 CubitVector center_point_1; 05613 surf_1->closest_point( bbox_center, ¢er_point_1 ); 05614 05615 bbox_center = surf_2->bounding_box().center(); 05616 CubitVector center_point_2; 05617 surf_2->closest_point( bbox_center, ¢er_point_2 ); 05618 05619 CubitVector normal_1, normal_2; 05620 surf_1->closest_point( center_point_1, NULL, &normal_1 ); 05621 surf_2->closest_point( center_point_2, NULL, &normal_2 ); 05622 double dot = normal_1 % normal_2; 05623 if ( dot < 0 ) 05624 relative_sense = CUBIT_REVERSED; 05625 05626 //compare loops 05627 int i,j; 05628 for( i=surf_1_loops.size(); i--; ) 05629 { 05630 LoopSM *surf_1_loop = surf_1_loops.get_and_step(); 05631 bool loop_match = false; 05632 05633 //check every loop in surf_2_loops to see if it matches 05634 //the current loop from surf_1_loops 05635 for( j=surf_2_loops.size(); j-- && !loop_match; ) 05636 { 05637 LoopSM *surf_2_loop = surf_2_loops.get_and_step(); 05638 loop_match = about_spatially_equal( surf_1_loop, surf_2_loop, relative_sense, 05639 tolerance_factor ); 05640 05641 if( ! loop_match ) 05642 return CUBIT_FALSE; 05643 05644 } 05645 } 05646 05647 return CUBIT_TRUE; 05648 05649 } 05650 05651 CubitBoolean MergeTool::about_spatially_equal( LoopSM *loop_1, LoopSM *loop_2, 05652 CubitSense relative_sense, double tolerance_factor ) 05653 { 05654 05655 //get the coedges from the loops 05656 DLIList<CoEdgeSM*> loop_1_coedges; 05657 DLIList<CoEdgeSM*> loop_2_coedges; 05658 loop_1->coedgesms( loop_1_coedges ); 05659 loop_2->coedgesms( loop_2_coedges ); 05660 05661 if( loop_1_coedges.size() != loop_2_coedges.size() ) 05662 return CUBIT_FALSE; 05663 05664 // Want to compare coedges in order, so make sure we have 05665 // them in the correct order. 05666 if (relative_sense == CUBIT_REVERSED) 05667 loop_1_coedges.reverse(); 05668 05669 // Try to match all coedges. Begin with the first coedge 05670 // in this loop. For each coedge in the other loop that 05671 // it matches, check if all the other coedges match in the 05672 // correct order. 05673 int other_loop_index = 0; 05674 loop_1_coedges.reset(); 05675 loop_2_coedges.reset(); 05676 CoEdgeSM* coedge_1 = loop_1_coedges.get_and_step(); 05677 int i; 05678 for (i = loop_2_coedges.size(); i--; ) 05679 { 05680 // Loop until we find a matching CoEdge 05681 CoEdgeSM* coedge_2 = loop_2_coedges.get_and_step(); 05682 05683 if (!about_spatially_equal( coedge_1, coedge_2, relative_sense,tolerance_factor )) 05684 continue; 05685 05686 // Found a matching coedge. Now try to match all the 05687 // others in the correct order. 05688 bool match = true; 05689 other_loop_index = loop_2_coedges.get_index(); 05690 for (int j = loop_2_coedges.size() - 1; j-- && match; ) 05691 { 05692 coedge_1 = loop_1_coedges.get_and_step(); 05693 coedge_2 = loop_2_coedges.get_and_step(); 05694 match = about_spatially_equal( coedge_1, coedge_2, relative_sense, tolerance_factor ); 05695 } 05696 05697 // Matched all coedges, in order. Done. 05698 if (match) 05699 return CUBIT_TRUE; 05700 05701 // Try again, as perhaps the first coedge of this loop 05702 // also matches some other one in the second loop and 05703 // if we start with that one, the remaining coedges will 05704 // also match. 05705 loop_1_coedges.reset(); 05706 coedge_1 = loop_1_coedges.get_and_step(); 05707 loop_2_coedges.reset(); 05708 loop_2_coedges.step( other_loop_index ); 05709 } 05710 05711 // If here, loops didn't match. 05712 return CUBIT_FALSE; 05713 05714 } 05715 05716 CubitBoolean MergeTool::about_spatially_equal( CoEdgeSM *coedge_1, CoEdgeSM *coedge_2, 05717 CubitSense relative_sense, 05718 double tolerance_factor ) 05719 { 05720 DLIList<Curve*> curves_1; 05721 DLIList<Curve*> curves_2; 05722 coedge_1->curves( curves_1 ); 05723 coedge_2->curves( curves_2 ); 05724 05725 Curve* curve_1 = curves_1.get(); 05726 Curve* curve_2 = curves_2.get(); 05727 05728 CubitSense edge_sense; 05729 05730 if( !about_spatially_equal( curve_1, curve_2, edge_sense, tolerance_factor ) ) 05731 return CUBIT_FALSE; 05732 05733 if( curve_1->geometry_type() == POINT_CURVE_TYPE || 05734 curve_2->geometry_type() == POINT_CURVE_TYPE ) 05735 return CUBIT_TRUE; 05736 05737 if (edge_sense == CUBIT_UNKNOWN) 05738 { 05739 PRINT_WARNING("Failed to determine relative sense of curves.\n"); 05740 return CUBIT_TRUE; 05741 } 05742 05743 bool coedges_reversed = coedge_1->sense() != coedge_2->sense(); 05744 bool want_reversed = edge_sense != relative_sense; 05745 if (coedges_reversed == want_reversed) 05746 return CUBIT_TRUE; 05747 05748 return CUBIT_FALSE; 05749 } 05750 05751 CubitBoolean MergeTool::about_spatially_equal( Curve *curve_1, Curve *curve_2, 05752 CubitSense &relative_sense, 05753 double tolerance_factor ) 05754 { 05755 if( curve_1 == curve_2 ) 05756 return CUBIT_TRUE; 05757 05758 relative_sense = CUBIT_FORWARD; 05759 const double ONE_THIRD = 1.0/3.0; 05760 05761 // Find the point 1/3 along curve_1 05762 CubitVector test_point_1, test_point_2; 05763 if( curve_1->position_from_fraction( ONE_THIRD, test_point_1 ) != CUBIT_SUCCESS ) 05764 return CUBIT_FALSE; 05765 05766 // See if the 1/3 point on curve_1 lies on curve_2 05767 if ( curve_2->closest_point_trimmed(test_point_1, test_point_2) 05768 != CUBIT_SUCCESS ) 05769 { 05770 return CUBIT_FALSE; 05771 } 05772 05773 if ( GeometryQueryTool::instance()-> 05774 about_spatially_equal(test_point_1, test_point_2, tolerance_factor ) 05775 != CUBIT_SUCCESS ) 05776 { 05777 return CUBIT_FALSE; 05778 } 05779 05780 CubitVector tangent_1, tangent_2; 05781 if( curve_1->closest_point(test_point_2, test_point_1, &tangent_1) != CUBIT_SUCCESS ) 05782 return CUBIT_FALSE; 05783 if( curve_2->closest_point(test_point_1, test_point_2, &tangent_2) != CUBIT_SUCCESS ) 05784 return CUBIT_FALSE; 05785 05786 //If one of the curves is zero-length, it will have a zero 05787 //tangent vector. 05788 double len_product = tangent_1.length() * tangent_2.length(); 05789 if( len_product > CUBIT_DBL_MIN ) 05790 { 05791 double dot_product = (tangent_1 % tangent_2); 05792 if (dot_product < 0) 05793 relative_sense = CUBIT_REVERSED; 05794 } 05795 else 05796 { 05797 //If one of the tangents is zero-length, one of the curves had 05798 //better be as well. 05799 assert( (curve_1->measure() * curve_2->measure()) < CUBIT_RESABS ); 05800 } 05801 05802 //compare the start and end vertices to be spatially equal. 05803 DLIList<TBPoint*> curve_1_points(2), curve_2_points(2); 05804 curve_1->points( curve_1_points ); 05805 curve_2->points( curve_2_points ); 05806 05807 if( curve_1->bridge_sense() == CUBIT_REVERSED ) 05808 curve_1_points.reverse(); 05809 if( curve_2->bridge_sense() == CUBIT_REVERSED ) 05810 curve_2_points.reverse(); 05811 05812 TBPoint* curve_1_start = curve_1_points.get(); 05813 curve_1_points.last(); 05814 TBPoint* curve_1_end = curve_1_points.get(); 05815 05816 TBPoint* curve_2_start = curve_2_points.get(); 05817 curve_2_points.last(); 05818 TBPoint* curve_2_end = curve_2_points.get(); 05819 05820 if (relative_sense == CUBIT_REVERSED) 05821 std::swap(curve_2_start, curve_2_end); 05822 05823 if (curve_1_start == curve_1_end ||curve_2_start == curve_2_end) 05824 { 05825 if ((curve_1_start != curve_1_end) || 05826 (curve_2_start != curve_2_end) || 05827 !about_spatially_equal(curve_1_start, curve_2_start, tolerance_factor)) 05828 return CUBIT_FALSE; 05829 } 05830 else 05831 { 05832 if ((curve_1_start == curve_2_end) || 05833 (curve_1_end == curve_2_start) || 05834 !about_spatially_equal(curve_1_start, curve_2_start, tolerance_factor ) || 05835 !about_spatially_equal(curve_1_end, curve_2_end, tolerance_factor )) 05836 return CUBIT_FALSE; 05837 } 05838 05839 return CUBIT_TRUE; 05840 05841 } 05842 05843 CubitBoolean MergeTool::about_spatially_equal( TBPoint *point_1, TBPoint *point_2, 05844 double tolerance_factor ) 05845 { 05846 if( point_1 == point_2 ) 05847 return CUBIT_TRUE; 05848 05849 CubitVector point_1_pos = point_1->coordinates(); 05850 CubitVector point_2_pos = point_2->coordinates(); 05851 05852 if (!GeometryQueryTool::instance()-> about_spatially_equal( 05853 point_1_pos, point_2_pos, tolerance_factor)) 05854 return CUBIT_FALSE; 05855 05856 return CUBIT_TRUE; 05857 } 05858 05859 void MergeTool::imprint_merge_solutions_for_overlapping_surfaces( 05860 RefFace *face1, 05861 RefFace *face2, 05862 bool execute, 05863 DLIList<CubitString> &display_strings, 05864 DLIList<CubitString> &command_strings, 05865 DLIList<CubitString> &preview_strings ) 05866 { 05867 //collect all the unmerged curves between the 2 surfaces 05868 DLIList<RefEdge*> edges1, edges2, tmp_list; 05869 face1->ref_edges( edges1 ); 05870 face2->ref_edges( edges2 ); 05871 tmp_list += edges1; 05872 tmp_list.intersect_unordered( edges2 ); 05873 05874 //remove all the common edges from both lists 05875 edges1 -= tmp_list; 05876 edges2 -= tmp_list; 05877 05878 double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS; 05879 05880 CubitString preview_string; 05881 05882 if(!execute) 05883 { 05884 preview_string = CubitString("draw surface "); 05885 preview_string += CubitString::number(face1->id()); 05886 preview_string += " "; 05887 preview_string += CubitString::number(face2->id()); 05888 preview_string += " overlap"; 05889 } 05890 05891 //if all curves of both surfaces are merged, suggest 'force merge' 05892 if( edges1.size() == 0 && edges2.size() == 0 ) 05893 { 05894 //quick check to make sure that centerpoints are nearly coincident 05895 CubitVector center1 = face1->center_point(); 05896 CubitVector center2 = face2->center_point(); 05897 05898 if( center1.distance_between( center2 ) <= (tolerance*5) ) 05899 { 05900 if(execute) 05901 { 05902 MergeTool::instance()->force_merge(face1, face2); 05903 } 05904 else 05905 { 05906 //display strings 05907 CubitString display_string("Force merge Surface "); 05908 display_string += CubitString::number(face1->id()); 05909 display_string += " "; 05910 display_string += CubitString::number(face2->id()); 05911 display_strings.append( display_string ); 05912 05913 CubitString command_string("merge surface "); 05914 command_string += CubitString::number(face1->id()); 05915 command_string += " "; 05916 command_string += CubitString::number(face2->id()); 05917 command_string += " force"; 05918 command_strings.append( command_string ); 05919 05920 preview_strings.append( preview_string ); 05921 } 05922 05923 return; 05924 } 05925 } 05926 05927 //get all the vertices 05928 DLIList<RefVertex*> verts1, verts2, merged_vertices; 05929 face1->ref_vertices( verts1 ); 05930 face2->ref_vertices( verts2 ); 05931 merged_vertices += verts1; 05932 merged_vertices.intersect_unordered( verts2 ); 05933 05934 //remove all the merged vertices from both lists 05935 verts1 -= merged_vertices; 05936 verts2 -= merged_vertices; 05937 05938 int i,j,k; 05939 //another force merge case...all vertices are merged, but some 05940 //coincident curves remain unmerged still. 05941 if( verts1.size() == 0 && verts2.size() == 0 ) 05942 { 05943 DLIList<RefEdge*> tmp_edges1( edges1 ); 05944 DLIList<RefEdge*> tmp_edges2( edges2 ); 05945 05946 //find edges that are close to one another 05947 for( i=tmp_edges1.size(); i--; ) 05948 { 05949 RefEdge *edge1 = tmp_edges1.get_and_step(); 05950 05951 //get some random point on curve edge1 05952 CubitVector position_on_edge1; 05953 edge1->position_from_fraction( 0.634, position_on_edge1 ); 05954 05955 bool found_pair = false; 05956 for( j=tmp_edges2.size(); j--; ) 05957 { 05958 RefEdge *edge2 = tmp_edges2.get_and_step(); 05959 05960 if( edge2 == NULL ) 05961 continue; 05962 05963 //make sure that they have the same vertices 05964 if( (edge1->start_vertex() == edge2->start_vertex() || 05965 edge1->start_vertex() == edge2->end_vertex() ) && 05966 (edge1->end_vertex() == edge2->end_vertex() || 05967 edge1->end_vertex() == edge2->start_vertex() ) ) 05968 { 05969 //find the closest point 05970 CubitVector close_pt; 05971 edge2->closest_point_trimmed( position_on_edge1, close_pt ); 05972 05973 //adjust tolerance to be larger possibly, a thousandanth of the curve's length 05974 double tmp_tolerance = edge2->measure()*0.01; 05975 if( tolerance > tmp_tolerance ) 05976 tmp_tolerance = tolerance; 05977 05978 if( close_pt.distance_between( position_on_edge1 ) < tmp_tolerance ) 05979 { 05980 //remove both from the list 05981 tmp_edges2.back(); 05982 tmp_edges2.change_to( NULL ); 05983 found_pair = true; 05984 break; 05985 } 05986 } 05987 } 05988 if( found_pair == true ) 05989 { 05990 tmp_edges1.back(); 05991 tmp_edges1.change_to( NULL ); 05992 tmp_edges1.step(); 05993 } 05994 } 05995 05996 tmp_edges1.remove_all_with_value( NULL ); 05997 tmp_edges2.remove_all_with_value( NULL ); 05998 05999 if( tmp_edges1.size() == 0 && tmp_edges2.size() == 0 ) 06000 { 06001 if(execute) 06002 { 06003 MergeTool::instance()->force_merge(face1, face2); 06004 } 06005 else 06006 { 06007 //display strings 06008 CubitString display_string("Force merge Surface "); 06009 display_string += CubitString::number(face1->id()); 06010 display_string += " "; 06011 display_string += CubitString::number(face2->id()); 06012 display_strings.append( display_string ); 06013 06014 CubitString command_string("merge surface "); 06015 command_string += CubitString::number(face1->id()); 06016 command_string += " "; 06017 command_string += CubitString::number(face2->id()); 06018 command_string += " force"; 06019 command_strings.append( command_string ); 06020 06021 preview_strings.append( preview_string ); 06022 } 06023 return; 06024 } 06025 } 06026 06027 //Look for near-coincident vertices between surfaces. 06028 //If any vertices are less than merge_tolerance*5 apart, 06029 //merge all the vertices 06030 verts1.clean_out(); 06031 verts2.clean_out(); 06032 face1->ref_vertices( verts1 ); 06033 face2->ref_vertices( verts2 ); 06034 double tmp_tol = tolerance * 5; 06035 double recommended_tol = -1; 06036 06037 for( i=verts1.size(); i--; ) 06038 { 06039 RefVertex *vert1 = verts1.get_and_step(); 06040 CubitVector pos1 = vert1->coordinates(); 06041 06042 for( j=verts2.size(); j--; ) 06043 { 06044 RefVertex *vert2 = verts2.get_and_step(); 06045 if( vert2 == vert1 )//already merged case 06046 continue; 06047 CubitVector pos2 = vert2->coordinates(); 06048 06049 double tmp_dist = pos1.distance_between( pos2 ); 06050 if( tmp_dist < tmp_tol ) 06051 { 06052 if( tmp_dist > recommended_tol ) 06053 { 06054 recommended_tol = tmp_dist; 06055 } 06056 } 06057 } 06058 } 06059 06060 if( recommended_tol > 0 ) 06061 { 06062 double merge_tol = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS; 06063 06064 if(execute) 06065 { 06066 double old_merge_tol = -1; 06067 if( recommended_tol > merge_tol ) 06068 { 06069 old_merge_tol = GeometryQueryTool::get_geometry_factor(); 06070 GeometryQueryTool::set_geometry_factor(recommended_tol); 06071 } 06072 DLIList<RefVertex*> merge_vert_list; 06073 face1->ref_vertices(merge_vert_list); 06074 face2->ref_vertices(merge_vert_list); 06075 MergeTool::instance()->merge_refvertices( merge_vert_list ); 06076 if( old_merge_tol != -1 ) 06077 GeometryQueryTool::set_geometry_factor( old_merge_tol ); 06078 } 06079 else 06080 { 06081 CubitString display_string("Merge vertices of surface "); 06082 display_string += CubitString::number(face1->id()); 06083 display_string += " "; 06084 display_string += CubitString::number(face2->id()); 06085 if( recommended_tol > merge_tol ) 06086 { 06087 recommended_tol *= 1.1; 06088 display_string += " tolerance "; 06089 display_string += CubitString::number( recommended_tol, 0, 7 ); 06090 } 06091 display_strings.append( display_string ); 06092 06093 CubitString command_string("merge vertex in surface "); 06094 command_string += CubitString::number(face1->id()); 06095 command_string += " "; 06096 command_string += CubitString::number(face2->id()); 06097 if( recommended_tol > merge_tol ) 06098 { 06099 command_string += " tolerance "; 06100 command_string += CubitString::number( recommended_tol, 0, 7 ); 06101 } 06102 command_strings.append( command_string ); 06103 06104 preview_strings.append( preview_string ); 06105 } 06106 return; 06107 } 06108 06109 DLIList<CubitVector> positions_to_imprint_onto_face1; 06110 DLIList<CubitVector> positions_to_imprint_onto_face2; 06111 06112 double possible_slivers_on_face1 = 0; 06113 double possible_slivers_on_face2 = 0; 06114 06115 double dist1, dist2, dist3; 06116 06117 //if you have overlapping curves, suggest imprinting owning volume with vertex 06118 std::map<RefEdge*, DLIList<CurveOverlapFacet*>* > facet_map; 06119 06120 DLIList<RefEdge*> overlapping_edges2; 06121 06122 for( i=edges1.size(); i--; ) 06123 { 06124 RefEdge *edge1 = edges1.get_and_step(); 06125 06126 DLIList<RefVertex*> verts1; 06127 edge1->ref_vertices( verts1 ); 06128 RefVertex *s_vert1 = verts1.get_and_step(); 06129 RefVertex *e_vert1 = verts1.get(); 06130 06131 bool overlaps_with_another_curve = false; 06132 double edge1_length = edge1->measure(); 06133 double curve_overlap_tolerance = 0.005; 06134 06135 for( j=edges2.size(); j--; ) 06136 { 06137 RefEdge *edge2 = edges2.get_and_step(); 06138 06139 if( edge2 == NULL ) 06140 continue; 06141 06142 if( SurfaceOverlapTool::instance()->check_overlap( edge1, edge2, 06143 &facet_map, 06144 &curve_overlap_tolerance )) 06145 { 06146 overlapping_edges2.append_unique( edge2 ); 06147 overlaps_with_another_curve = true; 06148 06149 DLIList<RefVertex*> verts2; 06150 edge2->ref_vertices( verts2 ); 06151 RefVertex *s_vert2 = verts2.get_and_step(); 06152 RefVertex *e_vert2 = verts2.get(); 06153 06154 CubitVector close_pt; 06155 edge1->closest_point_trimmed( s_vert2->coordinates(), close_pt ); 06156 06157 double edge2_length = edge2->measure(); 06158 06159 double tmp_tolerance = edge2_length; 06160 if( edge1_length < edge2_length ) 06161 tmp_tolerance = edge1_length; 06162 06163 //For a vertex of curve A to be imprinted on curve B, that vertex of A 06164 //must be a distance greater than 1/2 a percent of the lenght of 06165 //whichever curve is smaller (A or B) 06166 tmp_tolerance *= 0.005; 06167 double sliver_tolerance = tmp_tolerance * 2; 06168 06169 if( tolerance < tmp_tolerance ) 06170 tolerance = tmp_tolerance; 06171 06172 dist1 = close_pt.distance_between( s_vert2->coordinates() ); 06173 dist2 = close_pt.distance_between( s_vert1->coordinates() ); 06174 dist3 = close_pt.distance_between( e_vert1->coordinates() ); 06175 06176 //decide what vertex needs to be imprinted where 06177 if( dist1 < tolerance && 06178 dist2 > tolerance && 06179 dist3 > tolerance ) 06180 { 06181 06182 //make sure this position doesn't already exist 06183 bool add_position = true; 06184 for( k=positions_to_imprint_onto_face1.size(); k--; ) 06185 { 06186 CubitVector tmp_vec = positions_to_imprint_onto_face1.get_and_step(); 06187 06188 if( close_pt.distance_between( tmp_vec ) < tolerance ) 06189 { 06190 add_position = false; 06191 break; 06192 } 06193 } 06194 06195 if( add_position ) 06196 { 06197 //imprint body of edge1 with vertex at this location 06198 CubitVector tmp_vec = CubitVector( close_pt ); 06199 positions_to_imprint_onto_face1.append( tmp_vec ); 06200 06201 //watch for possible sliver creation 06202 if( dist2 < sliver_tolerance || dist3 < sliver_tolerance ) 06203 possible_slivers_on_face1++; 06204 } 06205 } 06206 06207 edge1->closest_point_trimmed( e_vert2->coordinates(), close_pt ); 06208 06209 dist1 = close_pt.distance_between( e_vert2->coordinates() ); 06210 dist2 = close_pt.distance_between( s_vert1->coordinates() ); 06211 dist3 = close_pt.distance_between( e_vert1->coordinates() ); 06212 06213 if( dist1 < tolerance && 06214 dist2 > tolerance && 06215 dist3 > tolerance ) 06216 { 06217 //make sure this position doesn't already exist 06218 bool add_position = true; 06219 for( k=positions_to_imprint_onto_face1.size(); k--; ) 06220 { 06221 CubitVector tmp_vec = positions_to_imprint_onto_face1.get_and_step(); 06222 06223 if( close_pt.distance_between( tmp_vec ) < tolerance ) 06224 { 06225 add_position = false; 06226 break; 06227 } 06228 } 06229 06230 if( add_position ) 06231 { 06232 //imprint body of edge1 with vertex at this location 06233 CubitVector tmp_vec = CubitVector( close_pt ); 06234 positions_to_imprint_onto_face1.append( tmp_vec ); 06235 06236 //watch for possible sliver creation 06237 if( dist2 < sliver_tolerance || dist3 < sliver_tolerance ) 06238 possible_slivers_on_face1++; 06239 } 06240 } 06241 06242 edge2->closest_point_trimmed( s_vert1->coordinates(), close_pt ); 06243 06244 dist1 = close_pt.distance_between( s_vert1->coordinates() ); 06245 dist2 = close_pt.distance_between( s_vert2->coordinates() ); 06246 dist3 = close_pt.distance_between( e_vert2->coordinates() ); 06247 06248 if( dist1 < tolerance && 06249 dist2 > tolerance && 06250 dist3 > tolerance ) 06251 { 06252 //make sure this position doesn't already exist 06253 bool add_position = true; 06254 for( k=positions_to_imprint_onto_face2.size(); k--; ) 06255 { 06256 CubitVector tmp_vec = positions_to_imprint_onto_face2.get_and_step(); 06257 06258 if( close_pt.distance_between( tmp_vec ) < tolerance ) 06259 { 06260 add_position = false; 06261 break; 06262 } 06263 } 06264 06265 if( add_position ) 06266 { 06267 //imprint body of edge1 with vertex at this location 06268 CubitVector tmp_vec = CubitVector( close_pt ); 06269 positions_to_imprint_onto_face2.append( tmp_vec ); 06270 06271 //watch for possible sliver creation 06272 if( dist2 < sliver_tolerance || dist3 < sliver_tolerance ) 06273 possible_slivers_on_face2++; 06274 } 06275 } 06276 06277 edge2->closest_point_trimmed( e_vert1->coordinates(), close_pt ); 06278 06279 dist1 = close_pt.distance_between( e_vert1->coordinates() ); 06280 dist2 = close_pt.distance_between( s_vert2->coordinates() ); 06281 dist3 = close_pt.distance_between( e_vert2->coordinates() ); 06282 06283 if( dist1 < tolerance && 06284 dist2 > tolerance && 06285 dist3 > tolerance ) 06286 { 06287 //make sure this position doesn't already exist 06288 bool add_position = true; 06289 for( k=positions_to_imprint_onto_face2.size(); k--; ) 06290 { 06291 CubitVector tmp_vec = positions_to_imprint_onto_face2.get_and_step(); 06292 06293 if( close_pt.distance_between( tmp_vec ) < tolerance ) 06294 { 06295 add_position = false; 06296 break; 06297 } 06298 } 06299 06300 if( add_position ) 06301 { 06302 //imprint body of edge1 with vertex at this location 06303 CubitVector tmp_vec = CubitVector( close_pt ); 06304 positions_to_imprint_onto_face2.append( tmp_vec ); 06305 06306 //watch for possible sliver creation 06307 if( dist2 < sliver_tolerance || dist3 < sliver_tolerance ) 06308 possible_slivers_on_face2++; 06309 } 06310 } 06311 } 06312 } 06313 06314 //remove this curve if it really overlaps 06315 if( overlaps_with_another_curve == true ) 06316 { 06317 edges1.back(); 06318 edges1.change_to( NULL ); 06319 edges1.step(); 06320 } 06321 } 06322 06323 //clean up facets 06324 std::map<RefEdge*, DLIList<CurveOverlapFacet*>* >::iterator facet_iter; 06325 facet_iter=facet_map.begin(); 06326 for(; facet_iter != facet_map.end(); facet_iter++ ) 06327 { 06328 DLIList<CurveOverlapFacet*> *co_facet_list = facet_iter->second; 06329 06330 //delete all the facets in the list 06331 for( i=co_facet_list->size(); i--; ) 06332 delete co_facet_list->get_and_step(); 06333 delete co_facet_list; 06334 } 06335 06336 //reset tolerance 06337 tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS; 06338 06339 //after this you should only be left with unmerged, non-overlapping edges 06340 edges1.remove_all_with_value( NULL ); 06341 edges2 -= overlapping_edges2; 06342 06343 //if all the curves are either merged or overlapping and 06344 //no vertices of any curve will imprint onto any other curve... 06345 //suggest force merging the 2 surfaces 06346 if( edges1.size() == 0 && edges2.size() == 0 && 06347 positions_to_imprint_onto_face1.size() == 0 && 06348 positions_to_imprint_onto_face2.size() == 0 ) 06349 { 06350 06351 //make sure the 2 surfaces have same number of curves and vertices 06352 if( face1->num_ref_vertices() == face2->num_ref_vertices() && 06353 face1->num_ref_edges() == face2->num_ref_edges() ) 06354 { 06355 if(execute) 06356 { 06357 MergeTool::instance()->force_merge(face1, face2); 06358 } 06359 else 06360 { 06361 CubitString display_string("Force merge Surface "); 06362 display_string += CubitString::number(face1->id()); 06363 display_string += " "; 06364 display_string += CubitString::number(face2->id()); 06365 display_strings.append( display_string ); 06366 06367 CubitString command_string("merge surface "); 06368 command_string += CubitString::number(face1->id()); 06369 command_string += " "; 06370 command_string += CubitString::number(face2->id()); 06371 command_string += " force"; 06372 command_strings.append( command_string ); 06373 06374 preview_strings.append( preview_string ); 06375 } 06376 return; 06377 } 06378 } 06379 06380 //try to suggest some curves you can imprint onto a surface 06381 if( edges1.size() || edges2.size() ) 06382 { 06383 DLIList<RefFace*> face_list(1); 06384 face_list.append( face2 ); 06385 06386 //see what edges in edges1 will imprint onto face2 06387 DLIList<RefEdge*> edges_to_imprint_onto_face2; 06388 for( i=edges1.size(); i--; ) 06389 { 06390 RefEdge *edge1 = edges1.get_and_step(); 06391 06392 //project 06393 DLIList<RefEdge*> edge_list(1); 06394 DLIList<RefEdge*> new_edges; 06395 edge_list.append( edge1); 06396 06397 DLIList<Surface*> surface_list(1); 06398 DLIList<Curve*> curves_to_project(1), projected_curves; 06399 GeometryModifyEngine* gme = GeometryModifyTool::instance()->common_modify_engine( 06400 face_list, 06401 edge_list, 06402 surface_list, 06403 curves_to_project); 06404 CubitStatus status = gme-> 06405 project_edges( surface_list, curves_to_project, projected_curves); 06406 06407 if( projected_curves.size() == 0 ) 06408 continue; 06409 06410 Curve *projected_curve = projected_curves.get(); 06411 06412 //if midpoint of projected curve is far from original curve, continue 06413 CubitVector original_curve_mid_point = edge1->center_point(); 06414 if( original_curve_mid_point.distance_between( projected_curve->center_point() ) > tolerance ) 06415 { 06416 gme->get_gqe()->delete_solid_model_entities( projected_curve ); 06417 continue; 06418 } 06419 06420 bool is_curve_on_surface = false; 06421 //do a surface-curve intersection to see if the curve lies on the surface 06422 DLIList<Curve*> intersection_curves; 06423 status = gme->curve_surface_intersection( surface_list.get(), 06424 projected_curve, 06425 intersection_curves); 06426 06427 if( status == CUBIT_SUCCESS && intersection_curves.size() ) 06428 { 06429 //remove any sliver curves 06430 for( j=intersection_curves.size(); j--; ) 06431 { 06432 Curve *tmp_curve = intersection_curves.get_and_step(); 06433 if( tmp_curve->measure() < tolerance ) 06434 { 06435 gme->get_gqe()->delete_solid_model_entities( tmp_curve ); 06436 intersection_curves.back(); 06437 intersection_curves.change_to( NULL ); 06438 intersection_curves.step(); 06439 } 06440 } 06441 06442 intersection_curves.remove_all_with_value( NULL ); 06443 06444 if( intersection_curves.size() ) 06445 is_curve_on_surface = true; 06446 06447 //delete the intersection curves 06448 for( j=intersection_curves.size(); j--; ) 06449 gme->get_gqe()->delete_solid_model_entities( intersection_curves.get_and_step() ); 06450 } 06451 06452 //maybe the surface-curve intersection method above didn't work...do 06453 //this more primitive method instead 06454 if( is_curve_on_surface == false ) 06455 { 06456 double distances_on_curves[3]; 06457 distances_on_curves[0] = .235; 06458 distances_on_curves[1] = .468; 06459 distances_on_curves[2] = .894; 06460 06461 for( j=0; j<3; j++ ) 06462 { 06463 CubitVector position_on_curve; 06464 projected_curve->position_from_fraction( distances_on_curves[j], 06465 position_on_curve ); 06466 06467 CubitVector closest_point_on_surface; 06468 face2->find_closest_point_trimmed( position_on_curve, 06469 closest_point_on_surface ); 06470 06471 if( position_on_curve.distance_between( closest_point_on_surface ) < tolerance ) 06472 { 06473 is_curve_on_surface = true; 06474 break; 06475 } 06476 } 06477 } 06478 06479 //delete the projected curve 06480 gme->get_gqe()->delete_solid_model_entities( projected_curve ); 06481 06482 if( is_curve_on_surface == false ) 06483 continue; 06484 06485 edges_to_imprint_onto_face2.append( edge1 ); 06486 } 06487 06488 //a possible force merge situation??? 06489 if( edges_to_imprint_onto_face2.size() ) 06490 { 06491 //are the number of vertices on both faces the same? 06492 if( face1->num_ref_vertices() == face2->num_ref_vertices() && 06493 face1->num_ref_edges() == face2->num_ref_edges() ) 06494 { 06495 double overlapping_area = 0; 06496 SurfaceOverlapTool::instance()->check_overlap( 06497 face1, face2, CUBIT_FALSE, CUBIT_FALSE, &overlapping_area ); 06498 double face1_area = face1->area(); 06499 double face2_area = face2->area(); 06500 06501 //make sure overlapping area is more than 99% of both surface areas 06502 double area_diff1 = fabs( overlapping_area - face1_area ); 06503 double area_diff2 = fabs( overlapping_area - face2_area ); 06504 06505 if( area_diff1 < (face1_area*0.01) && 06506 area_diff2 < (face2_area*0.01) ) 06507 { 06508 if(execute) 06509 { 06510 MergeTool::instance()->force_merge(face1, face2); 06511 } 06512 else 06513 { 06514 CubitString display_string("Force merge Surface "); 06515 display_string += CubitString::number(face1->id()); 06516 display_string += " "; 06517 display_string += CubitString::number(face2->id()); 06518 display_strings.append( display_string ); 06519 06520 CubitString command_string("merge surface "); 06521 command_string += CubitString::number(face1->id()); 06522 command_string += " "; 06523 command_string += CubitString::number(face2->id()); 06524 command_string += " force"; 06525 command_strings.append( command_string ); 06526 06527 preview_strings.append( preview_string ); 06528 } 06529 return; 06530 } 06531 } 06532 } 06533 06534 face_list.clean_out(); 06535 face_list.append( face1 ); 06536 06537 DLIList<RefEdge*> edges_to_imprint_onto_face1; 06538 //see what edges in edges2 will imprint onto face1 06539 for( i=edges2.size(); i--; ) 06540 { 06541 RefEdge *edge2 = edges2.get_and_step(); 06542 06543 //project 06544 DLIList<RefEdge*> edge_list(1); 06545 DLIList<RefEdge*> new_edges; 06546 edge_list.append( edge2); 06547 06548 DLIList<Surface*> surface_list(1); 06549 DLIList<Curve*> curves_to_project(1), projected_curves; 06550 GeometryModifyEngine* gme = GeometryModifyTool::instance()->common_modify_engine( 06551 face_list, 06552 edge_list, 06553 surface_list, 06554 curves_to_project); 06555 CubitStatus status = gme-> 06556 project_edges( surface_list, curves_to_project, projected_curves); 06557 06558 if( projected_curves.size() == 0 ) 06559 continue; 06560 06561 Curve *projected_curve = projected_curves.get(); 06562 06563 //if midpoint of projected curve is far from original curve, continue 06564 CubitVector original_curve_mid_point = edge2->center_point(); 06565 if( original_curve_mid_point.distance_between( projected_curve->center_point() ) > tolerance ) 06566 { 06567 gme->get_gqe()->delete_solid_model_entities( projected_curve ); 06568 continue; 06569 } 06570 06571 bool is_curve_on_surface = false; 06572 //do a surface-curve intersection to see if the curve lies on the surface 06573 DLIList<Curve*> intersection_curves; 06574 status = gme->curve_surface_intersection( surface_list.get(), 06575 projected_curve, 06576 intersection_curves); 06577 06578 if( status == CUBIT_SUCCESS && intersection_curves.size() ) 06579 { 06580 //remove any sliver curves 06581 for( j=intersection_curves.size(); j--; ) 06582 { 06583 Curve *tmp_curve = intersection_curves.get_and_step(); 06584 if( tmp_curve->measure() < tolerance ) 06585 { 06586 gme->get_gqe()->delete_solid_model_entities( tmp_curve ); 06587 intersection_curves.back(); 06588 intersection_curves.change_to( NULL ); 06589 intersection_curves.step(); 06590 } 06591 } 06592 06593 intersection_curves.remove_all_with_value( NULL ); 06594 06595 if( intersection_curves.size() ) 06596 is_curve_on_surface = true; 06597 06598 //delete the intersection curves 06599 for( j=intersection_curves.size(); j--; ) 06600 gme->get_gqe()->delete_solid_model_entities( intersection_curves.get_and_step() ); 06601 } 06602 06603 //maybe the surface-curve intersection method above didn't work...do 06604 //this more primitive method instead 06605 if( is_curve_on_surface == false ) 06606 { 06607 double distances_on_curves[3]; 06608 distances_on_curves[0] = .235; 06609 distances_on_curves[1] = .468; 06610 distances_on_curves[2] = .894; 06611 06612 for( j=0; j<3; j++ ) 06613 { 06614 CubitVector position_on_curve; 06615 projected_curve->position_from_fraction( distances_on_curves[j], 06616 position_on_curve ); 06617 06618 CubitVector closest_point_on_surface; 06619 face1->find_closest_point_trimmed( position_on_curve, 06620 closest_point_on_surface ); 06621 06622 if( position_on_curve.distance_between( closest_point_on_surface ) < tolerance ) 06623 { 06624 is_curve_on_surface = true; 06625 break; 06626 } 06627 } 06628 } 06629 06630 //delete the projected curve 06631 gme->get_gqe()->delete_solid_model_entities( projected_curve ); 06632 06633 if( is_curve_on_surface == false ) 06634 continue; 06635 06636 edges_to_imprint_onto_face1.append( edge2 ); 06637 } 06638 06639 //a possible force merge situation??? 06640 if( edges_to_imprint_onto_face1.size() ) 06641 { 06642 //are the number of vertices on both faces the same? 06643 if( face1->num_ref_vertices() == face2->num_ref_vertices() && 06644 face1->num_ref_edges() == face2->num_ref_edges() ) 06645 { 06646 double overlapping_area = 0; 06647 SurfaceOverlapTool::instance()->check_overlap( 06648 face1, face2, CUBIT_FALSE, CUBIT_FALSE, &overlapping_area ); 06649 double face1_area = face1->area(); 06650 double face2_area = face2->area(); 06651 06652 //make sure overlapping area is less than 1% of both surface areas 06653 double area_diff1 = fabs( overlapping_area - face1_area ); 06654 double area_diff2 = fabs( overlapping_area - face2_area ); 06655 06656 if( area_diff1 < (face1_area*0.01) && 06657 area_diff2 < (face2_area*0.01) ) 06658 { 06659 if(execute) 06660 { 06661 MergeTool::instance()->force_merge(face1, face2); 06662 } 06663 else 06664 { 06665 CubitString display_string("Force merge Surface "); 06666 display_string += CubitString::number(face1->id()); 06667 display_string += " "; 06668 display_string += CubitString::number(face2->id()); 06669 display_strings.append( display_string ); 06670 06671 CubitString command_string("merge surface "); 06672 command_string += CubitString::number(face1->id()); 06673 command_string += " "; 06674 command_string += CubitString::number(face2->id()); 06675 command_string += " force"; 06676 command_strings.append( command_string ); 06677 06678 preview_strings.append( preview_string ); 06679 } 06680 return; 06681 } 06682 } 06683 } 06684 06685 //imprint all the edges onto both surfaces in a single command 06686 if( edges_to_imprint_onto_face1.size() && 06687 edges_to_imprint_onto_face2.size() ) 06688 { 06689 if(execute) 06690 { 06691 DLIList<RefFace*> ref_face_list; 06692 ref_face_list.append(face1); 06693 ref_face_list.append(face2); 06694 DLIList<RefEdge*> ref_edge_list; 06695 for( i=edges_to_imprint_onto_face2.size(); i--; ) 06696 ref_edge_list.append(edges_to_imprint_onto_face2.get_and_step()); 06697 for( i=edges_to_imprint_onto_face1.size(); i--; ) 06698 ref_edge_list.append(edges_to_imprint_onto_face1.get_and_step()); 06699 DLIList<Body*> tmp_new_bodies; 06700 GeometryModifyTool::instance()->tolerant_imprint( ref_face_list, 06701 ref_edge_list, 06702 tmp_new_bodies, true ); 06703 return; 06704 } 06705 else 06706 { 06707 CubitString command_string("Imprint tolerant surface "); 06708 command_string += CubitString::number(face1->id()); 06709 command_string += " "; 06710 command_string += CubitString::number(face2->id()); 06711 command_string += " with curve "; 06712 06713 CubitString display_string("Imprint with curves "); 06714 06715 CubitString curve_ids; 06716 for( i=edges_to_imprint_onto_face2.size(); i--; ) 06717 { 06718 RefEdge *tmp_edge = edges_to_imprint_onto_face2.get_and_step(); 06719 curve_ids += CubitString::number(tmp_edge->id()); 06720 curve_ids += " "; 06721 } 06722 for( i=edges_to_imprint_onto_face1.size(); i--; ) 06723 { 06724 RefEdge *tmp_edge = edges_to_imprint_onto_face1.get_and_step(); 06725 curve_ids += CubitString::number(tmp_edge->id()); 06726 curve_ids += " "; 06727 } 06728 06729 display_string += curve_ids; 06730 command_string += curve_ids; 06731 command_string += "merge"; 06732 06733 preview_string += " &&& highlight curve "; 06734 preview_string += curve_ids; 06735 06736 display_strings.append( display_string ); 06737 command_strings.append( command_string ); 06738 preview_strings.append( preview_string ); 06739 } 06740 } 06741 //imprint edges onto a single surface 06742 else if( edges_to_imprint_onto_face2.size() ) 06743 { 06744 if(execute) 06745 { 06746 DLIList<RefFace*> ref_face_list; 06747 ref_face_list.append(face2); 06748 DLIList<Body*> tmp_new_bodies; 06749 GeometryModifyTool::instance()->tolerant_imprint( ref_face_list, 06750 edges_to_imprint_onto_face2, 06751 tmp_new_bodies, true ); 06752 return; 06753 } 06754 else 06755 { 06756 CubitString command_string("Imprint tolerant surface "); 06757 command_string += CubitString::number(face2->id()); 06758 command_string += " with curve "; 06759 06760 CubitString display_string("Imprint with curves "); 06761 preview_string += " &&& highlight curve "; 06762 06763 CubitString curve_ids; 06764 for( i=edges_to_imprint_onto_face2.size(); i--; ) 06765 { 06766 RefEdge *tmp_edge = edges_to_imprint_onto_face2.get_and_step(); 06767 curve_ids += CubitString::number(tmp_edge->id()); 06768 curve_ids += " "; 06769 } 06770 06771 command_string += curve_ids; 06772 display_string += curve_ids; 06773 preview_string += curve_ids; 06774 06775 command_string += " merge"; 06776 06777 display_strings.append( display_string ); 06778 command_strings.append( command_string ); 06779 preview_strings.append( preview_string ); 06780 } 06781 } 06782 //imprint edges onto a single surface 06783 else if( edges_to_imprint_onto_face1.size() ) 06784 { 06785 if(execute) 06786 { 06787 DLIList<RefFace*> ref_face_list; 06788 ref_face_list.append(face1); 06789 DLIList<Body*> tmp_new_bodies; 06790 GeometryModifyTool::instance()->tolerant_imprint( ref_face_list, 06791 edges_to_imprint_onto_face1, 06792 tmp_new_bodies, true ); 06793 return; 06794 } 06795 else 06796 { 06797 CubitString command_string("Imprint tolerant surface "); 06798 command_string += CubitString::number(face1->id()); 06799 command_string += " with curve "; 06800 06801 CubitString display_string("Imprint with curves "); 06802 preview_string += " &&& highlight curve "; 06803 06804 CubitString curve_ids; 06805 for( i=edges_to_imprint_onto_face1.size(); i--; ) 06806 { 06807 RefEdge *tmp_edge = edges_to_imprint_onto_face1.get_and_step(); 06808 curve_ids += CubitString::number(tmp_edge->id()); 06809 curve_ids += " "; 06810 } 06811 06812 command_string += curve_ids; 06813 display_string += curve_ids; 06814 preview_string += curve_ids; 06815 06816 command_string += " merge"; 06817 06818 display_strings.append( display_string ); 06819 command_strings.append( command_string ); 06820 preview_strings.append( preview_string ); 06821 } 06822 } 06823 06824 //if we came up with some solutions, get out 06825 if( display_strings.size() ) 06826 return; 06827 } 06828 06829 //just suggest some vertex imprints 06830 if( positions_to_imprint_onto_face1.size() || 06831 positions_to_imprint_onto_face2.size() ) 06832 { 06833 //Are you possibly generating sliver curves? 06834 //Offer a merge force merge instead if topology is identical 06835 if( face1->num_ref_vertices() == face2->num_ref_vertices() && 06836 face1->num_ref_edges() == face2->num_ref_edges() ) 06837 { 06838 if((positions_to_imprint_onto_face1.size() && 06839 positions_to_imprint_onto_face1.size() == possible_slivers_on_face1 ) || 06840 (positions_to_imprint_onto_face2.size() && 06841 positions_to_imprint_onto_face2.size() == possible_slivers_on_face2 )) 06842 { 06843 if(execute) 06844 { 06845 MergeTool::instance()->force_merge(face1, face2); 06846 } 06847 else 06848 { 06849 CubitString display_string("Force merge Surface "); 06850 display_string += CubitString::number(face1->id()); 06851 display_string += " "; 06852 display_string += CubitString::number(face2->id()); 06853 display_strings.append( display_string ); 06854 06855 CubitString command_string("merge surface "); 06856 command_string += CubitString::number(face1->id()); 06857 command_string += " "; 06858 command_string += CubitString::number(face2->id()); 06859 command_string += " force"; 06860 command_strings.append( command_string ); 06861 } 06862 06863 return; 06864 } 06865 } 06866 06867 CubitString command_string; 06868 // CubitString *preview_string = NULL; 06869 if( positions_to_imprint_onto_face1.size() ) 06870 { 06871 if(execute) 06872 { 06873 Body *b = face1->body(); 06874 if(b) 06875 { 06876 DLIList<Body*> body_list; 06877 body_list.append(b); 06878 DLIList<Body*> new_bodies; 06879 GeometryModifyTool::instance()->imprint( body_list, positions_to_imprint_onto_face1, 06880 new_bodies, false, true ); 06881 } 06882 } 06883 else 06884 { 06885 command_string = CubitString("Imprint volume "); 06886 RefVolume *volume1 = face1->ref_volume(); 06887 command_string += CubitString::number(volume1->id()); 06888 command_string += " with"; 06889 preview_string += " &&& highlight"; 06890 for( i=positions_to_imprint_onto_face1.size(); i--; ) 06891 { 06892 //construct the command string 06893 command_string += " position {"; 06894 CubitVector tmp_pos = positions_to_imprint_onto_face1.get_and_step(); 06895 command_string += CubitString::number( tmp_pos.x(), 0, 7 ); 06896 command_string += "} {"; 06897 command_string += CubitString::number( tmp_pos.y(), 0, 7 ); 06898 command_string += "} {"; 06899 command_string += CubitString::number( tmp_pos.z(), 0, 7 ); 06900 command_string += "}"; 06901 06902 //construct the preview string 06903 preview_string += " location "; 06904 preview_string += CubitString::number( tmp_pos.x(), 0, 7 ); 06905 preview_string += " "; 06906 preview_string += CubitString::number( tmp_pos.y(), 0, 7 ); 06907 preview_string += " "; 06908 preview_string += CubitString::number( tmp_pos.z(), 0, 7 ); 06909 preview_string += " "; 06910 } 06911 command_string += " merge"; 06912 } 06913 } 06914 06915 if( positions_to_imprint_onto_face2.size() ) 06916 { 06917 if(execute) 06918 { 06919 Body *b = face2->body(); 06920 if(b) 06921 { 06922 DLIList<Body*> body_list; 06923 body_list.append(b); 06924 DLIList<Body*> new_bodies; 06925 GeometryModifyTool::instance()->imprint( body_list, positions_to_imprint_onto_face2, 06926 new_bodies, false, true ); 06927 } 06928 } 06929 else 06930 { 06931 if( command_string.is_empty() ) 06932 command_string = CubitString("Imprint volume "); 06933 else 06934 command_string += " &&& Imprint volume "; 06935 06936 if( positions_to_imprint_onto_face1.size() == 0 ) 06937 preview_string += " &&& highlight"; 06938 06939 RefVolume *volume2 = face2->ref_volume(); 06940 command_string += CubitString::number(volume2->id()); 06941 command_string += " with"; 06942 for( i=positions_to_imprint_onto_face2.size(); i--; ) 06943 { 06944 command_string += " position {"; 06945 CubitVector tmp_pos = positions_to_imprint_onto_face2.get_and_step(); 06946 06947 command_string += CubitString::number( tmp_pos.x(), 0, 7 ); 06948 command_string += "} {"; 06949 command_string += CubitString::number( tmp_pos.y(), 0, 7 ); 06950 command_string += "} {"; 06951 command_string += CubitString::number( tmp_pos.z(), 0, 7 ); 06952 command_string += "}"; 06953 06954 //construct the preview string 06955 preview_string += " location "; 06956 preview_string += CubitString::number( tmp_pos.x(), 0, 7 ); 06957 preview_string += " "; 06958 preview_string += CubitString::number( tmp_pos.y(), 0, 7 ); 06959 preview_string += " "; 06960 preview_string += CubitString::number( tmp_pos.z(), 0, 7 ); 06961 preview_string += " "; 06962 } 06963 command_string += " merge"; 06964 } 06965 } 06966 06967 if(!execute) 06968 { 06969 command_strings.append( command_string ); 06970 preview_strings.append( preview_string ); 06971 06972 //create the display string 06973 CubitString display_string("Imprint with positions" ); 06974 display_strings.append( display_string ); 06975 } 06976 } 06977 06978 return; 06979 } 06980 06981