cgma
MergeTool.cpp
Go to the documentation of this file.
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, &center_point_1 ); 
05614   
05615   bbox_center = surf_2->bounding_box().center();
05616   CubitVector center_point_2;
05617   surf_2->closest_point( bbox_center, &center_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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines