cgma
GeometryQueryTool.cpp
Go to the documentation of this file.
00001 
00002 #include <assert.h>
00003 #include <stdlib.h>
00004 #include <math.h>
00005 
00006 #include "CubitDefines.h"
00007 #include "AppUtil.hpp"
00008 #include "ProgressTool.hpp"
00009 #include "GeometryDefines.h"
00010 #include "GeometryEntity.hpp"
00011 #include "GeomMeasureTool.hpp"
00012 #include "GeometryQueryTool.hpp"
00013 #include "GeometryModifyTool.hpp"
00014 #include "AnalyticGeometryTool.hpp"
00015 #include "MergeTool.hpp"
00016 #include "GeometryQueryEngine.hpp"
00017 #include "GeometryModifyEngine.hpp" // for creation of temporary construction entities
00018 #include "DAG.hpp"
00019 #include "TBOwnerSet.hpp"
00020 
00021 #include "RefEntity.hpp"
00022 #include "RefEntityFactory.hpp"
00023 #include "BasicTopologyEntity.hpp"
00024 #include "RefVertex.hpp"
00025 #include "RefEdge.hpp"
00026 #include "RefFace.hpp"
00027 #include "RefVolume.hpp"
00028 #include "RefGroup.hpp"
00029 
00030 #include "CoVertex.hpp"
00031 #include "CoEdge.hpp"
00032 #include "CoFace.hpp"
00033 #include "CoVolume.hpp"
00034 
00035 #include "Chain.hpp"
00036 #include "Loop.hpp"
00037 #include "Shell.hpp"
00038 #include "Body.hpp"
00039 
00040 #include "Lump.hpp"
00041 #include "Surface.hpp"
00042 #include "Curve.hpp"
00043 #include "Point.hpp"
00044 #include "BodySM.hpp"
00045 #include "ShellSM.hpp"
00046 #include "LoopSM.hpp"
00047 #include "CoEdgeSM.hpp"
00048 
00049 #include "CubitUtil.hpp"
00050 #include "CubitAttrib.hpp"
00051 #include "CubitVector.hpp"
00052 #include "CubitPlane.hpp"
00053 
00054 #include "DLIList.hpp"
00055 #include "GSaveOpen.hpp"
00056 
00057 #include "CubitMessage.hpp"
00058 
00059 #include "CastTo.hpp"
00060 #include "CpuTimer.hpp"
00061 
00062 #include "BridgeManager.hpp"
00063 #include "TDUniqueId.hpp"
00064 #include "CAMergePartner.hpp"
00065 #include "CAActuateSet.hpp"
00066 #include "CADeferredAttrib.hpp"
00067 #include "CAUniqueId.hpp"
00068 
00069 #include "SettingHandler.hpp"
00070 #include "ModelQueryEngine.hpp"
00071 
00072 #include "CubitTransformMatrix.hpp"
00073 #include "CubitUndo.hpp"
00074 #include "GMem.hpp"
00075 #include "IntersectionTool.hpp"
00076 
00077 #include "GfxPreview.hpp" //DJQ
00078 #include "GfxDebug.hpp" //DJQ
00079 #include "RefEntityName.hpp"
00080 
00081 double GeometryQueryTool::geometryToleranceFactor = DEFAULT_GEOM_FACTOR;
00082 GeometryQueryTool* GeometryQueryTool::instance_ = 0;
00083 CubitBoolean GeometryQueryTool::useFacetBBox = CUBIT_FALSE;
00084 CubitBoolean GeometryQueryTool::trackMergedAwayEnts = CUBIT_FALSE;
00085 CubitBoolean GeometryQueryTool::importingSolidModel = CUBIT_FALSE;
00086 CubitBoolean GeometryQueryTool::mergeGloballyOnImport = CUBIT_TRUE;
00087 CubitBoolean GeometryQueryTool::clearUidMapBeforeImport = CUBIT_TRUE; 
00088 DLIList<int> GeometryQueryTool::uidsOfImportingEnts;
00089 int GeometryQueryTool::entitiesMergedAway = 0;
00090 
00091 #ifndef CAT
00092   // Keep checking bounding box and use internal surf check for Sandia
00093   CubitBoolean GeometryQueryTool::bboxMergeTest = CUBIT_TRUE;
00094   int GeometryQueryTool::internalSurfaceMergeTest = 2; // 0=off, 1=all, 2=splines only
00095 #else
00096 //test
00097   // Cat prefers to avoid internal checks altogether as they cause problems with splines
00098   CubitBoolean GeometryQueryTool::bboxMergeTest = CUBIT_FALSE;
00099   int GeometryQueryTool::internalSurfaceMergeTest = 0; // 0=off, 1=all, 2=splines only
00100 #endif // ndef CAT
00101 
00102 double GeometryQueryTool::curveSliverCleanUpTolerance = geometryToleranceFactor*GEOMETRY_RESABS ;
00103 double GeometryQueryTool::surfaceSliverCleanUpTolerance = -1.0;
00104 
00105 // static CubitStatus import_actuate(DLIList<RefEntity*> &entity_list);
00106 
00107 // ********** END STATIC DECLARATIONS      **********
00108 
00109 #define PRINT(var) cout << #var << " = " << var << endl;
00110 
00111 #define CUBIT_VERY_SMALL_NUMBER (CUBIT_RESABS * 1.0E-15)
00112 
00113 // ********** BEGIN PUBLIC FUNCTIONS       **********
00114 //-------------------------------------------------------------------------
00115 // Purpose       : Controls access and creation of the sole instance of this
00116 //                 class.
00117 //
00118 // Special Notes :
00119 //
00120 // Creator       : Xuechen Liu
00121 //
00122 // Creation Date : 07/11/96
00123 //-------------------------------------------------------------------------
00124 
00125 GeometryQueryTool* GeometryQueryTool::instance(GeometryQueryEngine *GQEPtr)
00126 {
00127      // Check to see if we have created an instance of the class
00128      // If proceed to create one.
00129 
00130    if (instance_ == 0)
00131    {
00132         // When creating the instance, we should always have a valid
00133         // GQEPtr. If not, complain.
00134 
00135      instance_ = new GeometryQueryTool (GQEPtr) ;
00136 
00137         // check to make sure there's a ref entity factory extant
00138      //RefEntityFactory *factory =
00139      RefEntityFactory::instance();
00140    }
00141 
00142      // If there is an existing instance of the class, check if there
00143      // was a request to set default solid modeling engine. If so, be nice
00144      // to the calling routine :) :) and kindly set the default solid
00145      // modeling engine.
00146 
00147    else if ( GQEPtr != NULL && !instance_->gqeList.move_to(GQEPtr)) {
00148        delete instance_->gqeList.remove();
00149        instance_->gqeList.insert(GQEPtr);
00150    }
00151 
00152      // Return the a pointer to the instance of the class.
00153 
00154    return instance_ ;
00155 }
00156 
00157 //-------------------------------------------------------------------------
00158 // Purpose       : Destructor.
00159 //
00160 // Special Notes :
00161 //
00162 // Creator       : Xuechen Liu
00163 //
00164 // Creation Date : 07/11/96
00165 //-------------------------------------------------------------------------
00166 GeometryQueryTool::~GeometryQueryTool ()
00167 {
00168 
00169   //Kill the geometry query engine(s).
00170    int i;
00171    for (i = gqeList.size(); i > 0; i--)
00172    {
00173      delete gqeList.get_and_step();
00174    }
00175    gqeList.clean_out();
00176 
00177    instance_ = NULL;
00178 }
00179 
00180 //-------------------------------------------------------------------------
00181 // Purpose       : Function to delete instance variable
00182 //
00183 // Special Notes :
00184 //
00185 // Creator       : Corey Ernst
00186 //
00187 // Creation Date : 12/31/07
00188 //-------------------------------------------------------------------------
00189 void GeometryQueryTool::delete_instance()
00190 {
00191   if( NULL != instance_ )
00192   {
00193     delete instance_;
00194     instance_ = NULL;
00195   }
00196 }
00197 
00198 //-------------------------------------------------------------------------
00199 // Purpose       : Creates temporary geometry files for save/restore
00200 //
00201 // Special Notes :
00202 //
00203 // Creator       : Corey Ernst
00204 //
00205 // Creation Date : 01/17/03
00206 //-------------------------------------------------------------------------
00207 
00208 CubitStatus GeometryQueryTool::save_temp_geom_files(DLIList<RefEntity*> &ref_entity_list,
00209                                              const char *base_filename,
00210                                              const CubitString &cubit_version,
00211                                              std::list<CubitString> &files_written,
00212                                              std::list<CubitString> &types_written)
00213 {
00214   int i;
00215 // clear all attributes
00216   if (ref_entity_list.size() == 0) {
00217 
00218       // All bodies are to be exported
00219     RefEntityFactory::instance()->ref_entity_list("Body",
00220                                                   ref_entity_list);
00221 
00222       // add free ref entities
00223     get_free_ref_entities(ref_entity_list);
00224 
00225   }
00226 
00227     // get all child entities
00228   DLIList<RefEntity*> child_list;
00229   RefEntity::get_all_child_ref_entities( ref_entity_list, child_list );
00230 
00231     // merge lists
00232   for(i = ref_entity_list.size(); i--; )
00233     ref_entity_list.get_and_step()->marked(1);
00234   for(i = child_list.size(); i--; )
00235     child_list.get_and_step()->marked(0);
00236   for(i = ref_entity_list.size(); i--; )
00237   {
00238     RefEntity* ent = ref_entity_list.get_and_step();
00239     if( ent->marked() )
00240     {
00241       ent->marked(0);
00242       child_list.append(ent);
00243     }
00244   }
00245 
00246     // now call auto update on this combined list; this will update both visible
00247     // and hidden entities; the combined list should be used here, but only the
00248     // export list should be exported (some of the hidden entities might be directly
00249     // related to other entities on the export list, and we want to avoid exporting
00250     // those entities twice)
00251   CubitAttribUser::auto_update_cubit_attrib(child_list);
00252 
00253     // Get list of TopologyBridges to save
00254   DLIList<TopologyBridge*> geometry_list(ref_entity_list.size()), ref_ent_bridges;
00255   ref_entity_list.reset();
00256   for ( i = ref_entity_list.size(); i--; )
00257   {
00258     RefEntity* ref_ent = ref_entity_list.get_and_step();
00259     TopologyEntity* topo_ent = dynamic_cast<TopologyEntity*>(ref_ent);
00260     if ( !topo_ent )
00261     {
00262       PRINT_ERROR("Attempt to save %s (%s %d) as geometry.\n",
00263         ref_ent->entity_name().c_str(), ref_ent->class_name(), ref_ent->id());
00264       continue;
00265     }
00266 
00267     ref_ent_bridges.clean_out();
00268     topo_ent->bridge_manager()->get_bridge_list(ref_ent_bridges);
00269     geometry_list += ref_ent_bridges;
00270   }
00271 
00272     // Save virtual.
00273   for (IGESet::reverse_iterator itor = igeSet.rbegin(); itor != igeSet.rend(); ++itor)
00274     (*itor)->export_geometry(geometry_list);
00275 
00276   //we need this list around so that we can remove the CSAs off
00277   // the entities under the virtual entities
00278   DLIList<TopologyBridge*> geometry_list2 = geometry_list;
00279 
00280   CubitStatus result = CUBIT_SUCCESS, temp_result;
00281 
00282   GeometryQueryEngine* gqe = NULL;
00283   //we're just going to mess with MBG stuff right now
00284   gqeList.reset();
00285   for( int k=0; k<gqeList.size(); k++)
00286   {
00287     gqe = gqeList.get_and_step();
00288 
00289     CubitString file_written;
00290     CubitString type_written;
00291 
00292     temp_result = gqe->save_temp_geom_file(geometry_list, base_filename,
00293                                            cubit_version, file_written,
00294                                            type_written );
00295     if( file_written.length() )
00296     {
00297       files_written.push_back( file_written );
00298       types_written.push_back( type_written );
00299     }
00300 
00301     if (CUBIT_SUCCESS == temp_result) result = temp_result;
00302 
00303   }
00304 
00305 
00306   //if there is still geometry left over....could not be handled
00307   if( geometry_list.size() )
00308     PRINT_ERROR("Not all geometry could be handled for save.\n");
00309   CubitAttribUser::clear_all_simple_attrib(child_list);
00310 
00311   //remove attributes off underlying entities of virtual geometry
00312   if( geometry_list2.size() )
00313     GeometryQueryTool::instance()->ige_remove_attributes( geometry_list2 );
00314 
00315   gqeList.reset();
00316   return result;
00317 }
00318 
00319 //-------------------------------------------------------------------------
00320 // Purpose       : Export a list of solid model entities to a file.
00321 //
00322 // Special Notes :
00323 //
00324 // Creator       : Steve Storm
00325 //
00326 // Creation Date : 03/17/99
00327 //-------------------------------------------------------------------------
00328 
00329 CubitStatus GeometryQueryTool::export_solid_model(DLIList<RefEntity*>& ref_entity_list,
00330   char const* filename,
00331   Model_File_Type filetype,
00332   int &num_ents_exported,
00333   const CubitString &cubit_version,
00334   ModelExportOptions &export_options )
00335 {
00336   if (0 == gqeList.size())
00337   {
00338     PRINT_WARNING("No active geometry engine.\n");
00339     return CUBIT_FAILURE;
00340   }
00341 
00342   int i;
00343 
00344   if (ref_entity_list.size() == 0) {
00345 
00346       // All bodies are to be exported
00347     RefEntityFactory::instance()->ref_entity_list("Body",
00348                                                   ref_entity_list);
00349 
00350       // add free ref entities
00351     get_free_ref_entities(ref_entity_list);
00352 
00353   }
00354 
00355     // Get TopologyBridges from RefEntities.
00356   DLIList<TopologyBridge*> bridge_list(ref_entity_list.size()),
00357                            parent_bridges, ref_ent_bridges;
00358   ref_entity_list.reset();
00359   for( i = ref_entity_list.size(); i--; )
00360   {
00361     ref_ent_bridges.clean_out();
00362     TopologyEntity* topo_ptr = dynamic_cast<TopologyEntity*>(ref_entity_list.get_and_step());
00363     if( topo_ptr )
00364       topo_ptr->bridge_manager()->get_bridge_list( ref_ent_bridges );
00365     bridge_list += ref_ent_bridges;
00366   }
00367 
00368     // Get all child RefEntities
00369   DLIList<RefEntity*> child_list;
00370   RefEntity::get_all_child_ref_entities( ref_entity_list, child_list );
00371 
00372     // Scan for free-but-merged entities in child list.
00373   child_list.reset();
00374   for (i = child_list.size(); i--; )
00375   {
00376     ref_ent_bridges.clean_out();
00377     TopologyEntity* topo_ptr = dynamic_cast<TopologyEntity*>(child_list.get_and_step());
00378     assert(!!topo_ptr);
00379     topo_ptr->bridge_manager()->get_bridge_list( ref_ent_bridges );
00380     ref_ent_bridges.reset();
00381     for (int j = ref_ent_bridges.size(); j--; )
00382     {
00383       TopologyBridge* bridge = ref_ent_bridges.get_and_step();
00384       parent_bridges.clean_out();
00385       bridge->get_parents(parent_bridges);
00386       if (parent_bridges.size() == 0)
00387         bridge_list.append_unique(bridge);
00388     }
00389   }
00390 
00391     // Merge lists so we have one big list of every
00392     // RefEntity to be saved.
00393   for(i = ref_entity_list.size(); i--; )
00394     ref_entity_list.get_and_step()->marked(1);
00395 
00396   for(i = child_list.size(); i--; )
00397     child_list.get_and_step()->marked(0);
00398   for(i = ref_entity_list.size(); i--; )
00399   {
00400     RefEntity* ent = ref_entity_list.get_and_step();
00401     if( ent->marked() )
00402     {
00403       ent->marked(0);
00404       child_list.append(ent);
00405     }
00406   }
00407 
00408   // Make a copy of the bridge list to be used below in
00409   // removing the virtual geometry attributes.  We can't
00410   // use the original bridge list because it gets emptied.
00411   DLIList<TopologyBridge*> copy_of_bridge_list = bridge_list;
00412 
00413   int num_input_entities = bridge_list.size();
00414 
00415     // now call auto update on this combined list; this will update both visible
00416     // and hidden entities; the combined list should be used here, but only the
00417     // export list should be exported (some of the hidden entities might be directly
00418     // related to other entities on the export list, and we want to avoid exporting
00419     // those entities twice)
00420   CubitAttribUser::auto_update_cubit_attrib(child_list);
00421 
00422     // Save virtual.
00423   IGESet::reverse_iterator itor;
00424   for (itor = igeSet.rbegin(); itor != igeSet.rend(); ++itor)
00425     (*itor)->export_geometry(bridge_list);
00426 
00427   CubitStatus result = CUBIT_SUCCESS, temp_result;
00428 
00429   if( !bridge_list.size() )
00430   {
00431     return CUBIT_SUCCESS;
00432   }
00433 //   GeometryQueryEngine* gqe = NULL;
00434   //we're just going to mess with MBG stuff right now
00435   gqeList.reset();
00436 
00437   int num_ents_before = bridge_list.size();
00438   temp_result = gqeList.get()->export_solid_model(bridge_list, filename, filetype,
00439                                         cubit_version, export_options );
00440   if (temp_result == CUBIT_SUCCESS )
00441     result = temp_result;
00442 
00443   //if all geometry wasn't exported, warn user and print out
00444   //what wasn't
00445   if( bridge_list.size() != 0 )
00446   {
00447     if( bridge_list.size() == num_ents_before )
00448       PRINT_ERROR("No geometry exported.  Must set geometry engine to another type.\n");
00449     else
00450       PRINT_WARNING("Not all geometry could be handled for save.\n");
00451 
00452     PRINT_INFO("Set the geometry engine appropriately to export the following geometry:\n");
00453     int k;
00454     for(k=bridge_list.size(); k--; )
00455     {
00456       TopologyEntity *te = bridge_list.get()->topology_entity();
00457       if( te )
00458       {
00459         RefEntity *ref_ent = CAST_TO( te, RefEntity );
00460         if( ref_ent )
00461         {
00462           GeometryQueryEngine *gqe = bridge_list.get()->get_geometry_query_engine();
00463           PRINT_INFO("%s is of Geometry Engine type %s\n",
00464           ref_ent->entity_name().c_str(), gqe->modeler_type() );
00465         }
00466       }
00467       bridge_list.step();
00468     }
00469   }
00470 
00471     // clean off attributes off of underyling virtual geometry
00472   for (itor = igeSet.rbegin(); itor != igeSet.rend(); ++itor)
00473     (*itor)->remove_attributes(copy_of_bridge_list);
00474 
00475   CubitAttribUser::clear_all_simple_attrib(child_list);
00476 
00477   num_ents_exported = num_input_entities - bridge_list.size();
00478   gqeList.reset();
00479   return result;
00480 }
00481 
00482 // export entities to buffer
00483 CubitStatus GeometryQueryTool::export_solid_model(DLIList<RefEntity*>& ref_entity_list,
00484                                                   char*& p_buffer,
00485                                                   int& n_buffer_size,
00486                                                   bool b_export_buffer)
00487 {
00488   if (0 == gqeList.size())
00489   {
00490     PRINT_WARNING("No active geometry engine.\n");
00491     return CUBIT_FAILURE;
00492   }
00493 
00494   int i;
00495 
00496   if (ref_entity_list.size() == 0) {
00497     // All bodies are to be exported
00498     RefEntityFactory::instance()->ref_entity_list("Body",
00499                                                   ref_entity_list);
00500 
00501     // add free ref entities
00502     get_free_ref_entities(ref_entity_list);
00503   }
00504 
00505   // Get TopologyBridges from RefEntities.
00506   DLIList<TopologyBridge*> bridge_list(ref_entity_list.size()),
00507     parent_bridges, ref_ent_bridges;
00508   ref_entity_list.reset();
00509   for( i = ref_entity_list.size(); i--; ) {
00510     ref_ent_bridges.clean_out();
00511     TopologyEntity* topo_ptr = dynamic_cast<TopologyEntity*>(ref_entity_list.get_and_step());
00512     if( topo_ptr )
00513       topo_ptr->bridge_manager()->get_bridge_list( ref_ent_bridges );
00514     bridge_list += ref_ent_bridges;
00515   }
00516 
00517   // Get all child RefEntities
00518   DLIList<RefEntity*> child_list;
00519   RefEntity::get_all_child_ref_entities( ref_entity_list, child_list );
00520 
00521   // Scan for free-but-merged entities in child list.
00522   child_list.reset();
00523   for (i = child_list.size(); i--; )
00524   {
00525     ref_ent_bridges.clean_out();
00526     TopologyEntity* topo_ptr = dynamic_cast<TopologyEntity*>(child_list.get_and_step());
00527     assert(!!topo_ptr);
00528     topo_ptr->bridge_manager()->get_bridge_list( ref_ent_bridges );
00529     ref_ent_bridges.reset();
00530     for (int j = ref_ent_bridges.size(); j--; )
00531     {
00532       TopologyBridge* bridge = ref_ent_bridges.get_and_step();
00533       parent_bridges.clean_out();
00534       bridge->get_parents(parent_bridges);
00535       if (parent_bridges.size() == 0)
00536         bridge_list.append_unique(bridge);
00537     }
00538   }
00539 
00540   // Merge lists so we have one big list of every
00541   // RefEntity to be saved.
00542   for(i = ref_entity_list.size(); i--; )
00543     ref_entity_list.get_and_step()->marked(1);
00544 
00545   for(i = child_list.size(); i--; )
00546     child_list.get_and_step()->marked(0);
00547   for(i = ref_entity_list.size(); i--; )
00548   {
00549     RefEntity* ent = ref_entity_list.get_and_step();
00550     if( ent->marked() )
00551     {
00552       ent->marked(0);
00553       child_list.append(ent);
00554     }
00555   }
00556 
00557   // Make a copy of the bridge list to be used below in
00558   // removing the virtual geometry attributes.  We can't
00559   // use the original bridge list because it gets emptied.
00560   DLIList<TopologyBridge*> copy_of_bridge_list = bridge_list;
00561 
00562   /*int num_input_entities =*/ bridge_list.size();
00563 
00564     // now call auto update on this combined list; this will update both visible
00565     // and hidden entities; the combined list should be used here, but only the
00566     // export list should be exported (some of the hidden entities might be directly
00567     // related to other entities on the export list, and we want to avoid exporting
00568     // those entities twice)
00569   CubitAttribUser::auto_update_cubit_attrib(child_list);
00570 
00571     // Save virtual.
00572   IGESet::reverse_iterator itor;
00573   for (itor = igeSet.rbegin(); itor != igeSet.rend(); ++itor)
00574     (*itor)->export_geometry(bridge_list);
00575 
00576   CubitStatus result = CUBIT_SUCCESS, temp_result;
00577 
00578   if( !bridge_list.size() )
00579   {
00580     return CUBIT_SUCCESS;
00581   }
00582   //   GeometryQueryEngine* gqe = NULL;
00583   //we're just going to mess with MBG stuff right now
00584   gqeList.reset();
00585 
00586   int num_ents_before = bridge_list.size();
00587   temp_result = gqeList.get()->export_solid_model(bridge_list, p_buffer,
00588                                                   n_buffer_size, b_export_buffer);
00589   if (temp_result == CUBIT_SUCCESS )
00590     result = temp_result;
00591 
00592   //if all geometry wasn't exported, warn user and print out
00593   //what wasn't
00594   if( bridge_list.size() != 0 )
00595   {
00596     if( bridge_list.size() == num_ents_before )
00597       PRINT_ERROR("No geometry exported.  Must set geometry engine to another type.\n");
00598     else
00599       PRINT_WARNING("Not all geometry could be handled for save.\n");
00600 
00601     PRINT_INFO("Set the geometry engine appropriately to export the following geometry:\n");
00602     int k;
00603     for(k=bridge_list.size(); k--; )
00604     {
00605       TopologyEntity *te = bridge_list.get()->topology_entity();
00606       if( te )
00607       {
00608         RefEntity *ref_ent = CAST_TO( te, RefEntity );
00609         if( ref_ent )
00610         {
00611           GeometryQueryEngine *gqe = bridge_list.get()->get_geometry_query_engine();
00612           PRINT_INFO("%s is of Geometry Engine type %s\n",
00613           ref_ent->entity_name().c_str(), gqe->modeler_type() );
00614         }
00615       }
00616       bridge_list.step();
00617     }
00618   }
00619 
00620     // clean off attributes off of underyling virtual geometry
00621   for (itor = igeSet.rbegin(); itor != igeSet.rend(); ++itor)
00622     (*itor)->remove_attributes(copy_of_bridge_list);
00623 
00624   CubitAttribUser::clear_all_simple_attrib(child_list);
00625 
00626   //num_ents_exported = num_input_entities - bridge_list.size();
00627   gqeList.reset();
00628   return result;
00629 }
00630 
00631 //-------------------------------------------------------------------------
00632 // Purpose       : Fire a ray at a list of entities and return the
00633 //                 parameters along the ray (distance from origin of ray)
00634 //                 where it hits the entities; optionally find the
00635 //                 corresponding entities it hit.
00636 //
00637 // Special Notes :
00638 //
00639 // Creator       : Steve Storm
00640 //
00641 // Creation Date : 3/29/2007
00642 //-------------------------------------------------------------------------
00643 CubitStatus GeometryQueryTool::fire_ray( CubitVector &origin,
00644                                          CubitVector &direction,
00645                                          DLIList<RefEntity*> &at_entity_list,
00646                                          DLIList<double> &ray_params,
00647                                          int max_hits,
00648                                          double ray_radius,
00649                                          DLIList<RefEntity*> *hit_entity_list_ptr )
00650 {
00651   int i;
00652 
00653   // Do this in a way to account for the case if they happen to be from
00654   // different geometry engines (could easily occur with virtual geometry)
00655 
00656   DLIList<TopologyEntity*> te_fire_at_list;
00657   DLIList<TopologyEntity*> te_hit_entity_list;
00658   DLIList<TopologyEntity*> *te_hit_entity_list_ptr = 0;
00659   if( hit_entity_list_ptr )
00660     te_hit_entity_list_ptr = &te_hit_entity_list;
00661 
00662   GeometryQueryEngine *gqe = 0;
00663   GeometryQueryEngine *gqe_last = 0;
00664   RefEntity *ref_entity_ptr;
00665   TopologyEntity *topo_ptr;
00666 
00667   int loc_max_hits = max_hits;
00668   CubitBoolean hits_limited = CUBIT_FALSE;
00669   if( max_hits > 0 )
00670     hits_limited = CUBIT_TRUE;
00671 
00672   // Note we care about order
00673   at_entity_list.reset();
00674   for( i=at_entity_list.size(); i--; )
00675   {
00676     ref_entity_ptr = at_entity_list.get_and_step();
00677 
00678     topo_ptr = CAST_TO( ref_entity_ptr, TopologyEntity );
00679     if( !topo_ptr )
00680     {
00681       PRINT_ERROR( "Couldnt get topo_ptr\n" );
00682       continue;
00683     }
00684 
00685     gqe = topo_ptr->get_geometry_query_engine();
00686     if( !gqe )
00687     {
00688       PRINT_ERROR( "Unable to find geometry engine associated with an entity!\n" );
00689       return CUBIT_FAILURE;
00690     }
00691 
00692     if( !gqe_last )
00693     {
00694       gqe_last = gqe;
00695     }
00696     if( gqe != gqe_last )
00697     {
00698       if( hits_limited == CUBIT_TRUE )
00699       {
00700         loc_max_hits = max_hits - ray_params.size();
00701         if( loc_max_hits <= 0 )
00702           break;
00703       }
00704 
00705       if( fire_ray( origin, direction, te_fire_at_list, ray_params,
00706         loc_max_hits, ray_radius, te_hit_entity_list_ptr ) == CUBIT_FAILURE )
00707         return CUBIT_FAILURE;
00708 
00709       // Reset
00710       gqe_last = gqe;
00711       te_fire_at_list.clean_out();
00712     }
00713 
00714     te_fire_at_list.append( topo_ptr );
00715   }
00716 
00717   // Do the last ray fire, if necessary
00718   if( hits_limited == CUBIT_TRUE )
00719     loc_max_hits = max_hits - ray_params.size();
00720   if( hits_limited==CUBIT_FALSE || loc_max_hits>0 )
00721     if( fire_ray( origin, direction, te_fire_at_list, ray_params,
00722       loc_max_hits, ray_radius, te_hit_entity_list_ptr ) == CUBIT_FAILURE )
00723       return CUBIT_FAILURE;
00724 
00725   if( hit_entity_list_ptr )
00726   {
00727     // Find RefEntities from TopologyEntities
00728     te_hit_entity_list.reset();
00729     for( i=te_hit_entity_list.size(); i--; )
00730     {
00731       topo_ptr = te_hit_entity_list.get_and_step();
00732       if( !topo_ptr )
00733       {
00734         hit_entity_list_ptr->append( 0 );
00735         continue;
00736       }
00737 
00738       ref_entity_ptr = CAST_TO( topo_ptr, RefEntity );
00739       hit_entity_list_ptr->append( ref_entity_ptr );
00740     }
00741   }
00742 
00743   // Now, make sure we don't have more hits than asked for
00744   if( hits_limited == CUBIT_TRUE )
00745   {
00746     if( ray_params.size() <= max_hits )
00747       return CUBIT_SUCCESS;
00748 
00749     for( i=ray_params.size()-max_hits; i--; )
00750     {
00751       ray_params.last();
00752       ray_params.remove();
00753       if( hit_entity_list_ptr )
00754       {
00755         hit_entity_list_ptr->last();
00756         hit_entity_list_ptr->remove();
00757       }
00758     }
00759   }
00760 
00761   return CUBIT_SUCCESS;
00762 }
00763 
00764 //-------------------------------------------------------------------------
00765 // Purpose       : Fire a ray at a list of entities and return the
00766 //                 parameters along the ray (distance from origin of ray)
00767 //                 where it hits the entities; optionally find the
00768 //                 corresponding entities it hit.
00769 //
00770 // Special Notes : All entities must be from the same geometry engine.
00771 //
00772 // Creator       : Steve Storm
00773 //
00774 // Creation Date : 5/19/2007
00775 //-------------------------------------------------------------------------
00776 CubitStatus GeometryQueryTool::fire_ray( CubitVector &origin,
00777                                          CubitVector &direction,
00778                                          DLIList<TopologyEntity*> &at_entity_list,
00779                                          DLIList<double> &ray_params,
00780                                          int max_hits,
00781                                          double ray_radius,
00782                                          DLIList<TopologyEntity*> *hit_entity_list_ptr )
00783 {
00784   if( !at_entity_list.size() )
00785     return CUBIT_SUCCESS;
00786 
00787 
00788   TopologyEntity *topo_ptr = at_entity_list.get();
00789 
00790   GeometryQueryEngine *gqe = topo_ptr->get_geometry_query_engine();
00791   if( !gqe )
00792   {
00793     PRINT_ERROR( "Unable to find geometry engine associated with an entity!\n" );
00794     return CUBIT_FAILURE;
00795   }
00796 
00797 
00798   DLIList<TopologyBridge*> tb_list;
00799   int i;
00800   at_entity_list.reset();
00801   for( i=at_entity_list.size(); i--; )
00802   {
00803     topo_ptr = at_entity_list.get_and_step();
00804     DLIList<TopologyBridge*> bridge_list;
00805     topo_ptr->bridge_manager()->get_bridge_list( bridge_list );
00806     bridge_list.reset();
00807     tb_list.append( bridge_list.get() );
00808   }
00809 
00810   // Setup temporary variables to pass
00811   DLIList<double> tmp_ray_params;
00812 
00813   DLIList<TopologyBridge*> tb_hit_list;
00814   DLIList<TopologyBridge*> *tb_hit_list_ptr = NULL;
00815   if( hit_entity_list_ptr )
00816     tb_hit_list_ptr = &tb_hit_list;
00817 
00818   // Do the ray fire.  Note we will sort the hits by distance and append to the output lists.
00819   if( gqe->fire_ray( origin, direction, tb_list, tmp_ray_params,
00820     max_hits, ray_radius, tb_hit_list_ptr ) == CUBIT_FAILURE )
00821     return CUBIT_FAILURE;
00822 
00823   tmp_ray_params.reset();
00824   if( tb_hit_list_ptr) tb_hit_list_ptr->reset();
00825 
00826   // Append to output lists
00827   ray_params += tmp_ray_params;
00828 
00829   // Get the TE's from the TopologyBridges
00830   if( hit_entity_list_ptr )
00831   {
00832       // First need to make sure that the entities hit are visible...entities hit
00833       // may be hidden under virtual entities....we need to get the visible
00834       // entities.
00835       DLIList<TopologyBridge*> vis_tb_hit_list;
00836       DLIList<CubitVector*> cv_list;
00837 
00838       CubitVector *loc_ptr;
00839       double param;
00840       tmp_ray_params.reset();
00841       for( i=tmp_ray_params.size(); i--; )
00842       {
00843           param = tmp_ray_params.get_and_step();
00844 
00845           loc_ptr = new CubitVector;
00846           origin.next_point( direction, param, *loc_ptr );
00847           cv_list.append( loc_ptr );
00848       }
00849 
00850 
00851       TopologyBridge *bridge_ptr;
00852       for( i=0; i<tb_hit_list_ptr->size(); i++ )
00853       {
00854           bridge_ptr = tb_hit_list_ptr->get_and_step();
00855 
00856           TopologyBridge *visible_tb = NULL;
00857           TBOwner* o2 = bridge_ptr->owner();
00858 
00859           bool broke_early = false;
00860           BridgeManager* bridge_manager2;
00861           while (!(bridge_manager2 = dynamic_cast<BridgeManager*>(o2)))
00862           {
00863               if (TopologyBridge* bridge2 = dynamic_cast<TopologyBridge*>(o2))
00864               {
00865                   GeometryQueryEngine* gqe2 = bridge2->get_geometry_query_engine();
00866 
00867                   //Let the VQE handle the work
00868                   visible_tb = gqe2->get_visible_entity_at_point(bridge_ptr, cv_list[i]);
00869                   if (visible_tb)
00870                       o2 = visible_tb->owner();
00871                   else
00872                       o2 = bridge2->owner();
00873               }
00874 
00875               else if(TBOwnerSet* set = dynamic_cast<TBOwnerSet*>(o2))
00876               {
00877                   DLIList<TopologyBridge*> list2;
00878                   set->get_owners(list2);
00879                   list2.reset();
00880 
00881                   // This had better be the Virtual QE.
00882                   GeometryQueryEngine* gqe2 = list2.get()->get_geometry_query_engine();
00883 
00884                   //Let the VQE handle the work
00885                   visible_tb = gqe2->get_visible_entity_at_point(bridge_ptr, cv_list[i]);
00886                   if (visible_tb)
00887                       o2 = visible_tb->owner();
00888                   else
00889                   {
00890                       broke_early = true;
00891                       break;
00892                   }
00893               }
00894               else
00895               {
00896                   broke_early = true;
00897                   break;
00898               }
00899           }
00900 
00901           if (!broke_early)
00902               visible_tb = bridge_manager2->topology_bridge();
00903 
00904 
00905           if( visible_tb )
00906           {
00907               topo_ptr = visible_tb->topology_entity();
00908               hit_entity_list_ptr->append( topo_ptr );
00909           }
00910           else
00911               hit_entity_list_ptr->append( 0 );
00912       }
00913 
00914 
00915       // Free memory
00916       while( cv_list.size() ) delete cv_list.pop();
00917   }
00918 
00919   // Sort ray_params (low to high) and sort hit_entity_list_ptr to match
00920   //  This will ensure entities are in order of who got hit first
00921   //  Do the sort by adding to a map (should auto-sort)
00922   std::map<double, TopologyEntity*> temp_map;
00923   for (i=0; i<ray_params.size(); i++)
00924       temp_map.insert(std::map<double, 
00925     TopologyEntity*>::value_type( ray_params.get_and_step(), 
00926     hit_entity_list_ptr ? hit_entity_list_ptr->get_and_step() : 0 ) );
00927 
00928   // The map should be sorted, so iterate through it and add to the official lists
00929   ray_params.clean_out();
00930   if( hit_entity_list_ptr) hit_entity_list_ptr->clean_out();
00931 
00932   std::map<double, TopologyEntity*>::iterator iter;
00933   for (iter=temp_map.begin(); iter != temp_map.end(); iter++)
00934   {
00935       ray_params.append(iter->first);
00936       if( hit_entity_list_ptr) hit_entity_list_ptr->append(iter->second);
00937   }
00938 
00939     return CUBIT_SUCCESS;
00940 }
00941 
00942 //-------------------------------------------------------------------------
00943 // Purpose       : Reads in geometry and creates the necessary Reference
00944 //                 entities associated with the input geometry. Has ability
00945 //                 to read selectively read in either bodies, free surfaces,
00946 //                 free curves or free vertices from the file.
00947 //
00948 //                 Valid file types are:
00949 //
00950 //                       "IGES"        --  IGES file
00951 //                       "STEP"        --  STEP file
00952 //                       "KCM"         --  KCM file
00953 //
00954 // Special Notes :
00955 //
00956 // Creator       : Steve Storm
00957 //
00958 // Creation Date : 03/17/99
00959 //-------------------------------------------------------------------------
00960 CubitStatus GeometryQueryTool::import_solid_model( const char* file_name,
00961   Model_File_Type file_type,
00962   ModelImportOptions &import_options,
00963   DLIList<RefEntity*> *imported_entities )
00964 {
00965   if (0 == gqeList.size())
00966   {
00967     PRINT_WARNING("No active geometry engine.\n");
00968     return CUBIT_FAILURE;
00969   }
00970 
00971   importingSolidModel = CUBIT_TRUE;
00972   uidsOfImportingEnts.clean_out();
00973   mergeGloballyOnImport = import_options.merge_globally;
00974  
00975  if( clearUidMapBeforeImport )
00976     CAUniqueId::clear_out_old_to_new_map();
00977 
00978   if( GSaveOpen::performingUndo )
00979     mergeGloballyOnImport = CUBIT_TRUE;
00980 
00981   if( CubitUndo::get_undo_enabled() )
00982     CubitUndo::save_state();
00983 
00984     // reset the attribImporteds flags to facilitate attribute reporting
00985 //  CubitAttrib::clear_attrib_importeds();
00986 
00987     // Use the default MQE to import a list of ToplogyBridges from the file.
00988   gqeList.reset();
00989   DLIList<TopologyBridge*> bridge_list;
00990 
00991   import_options.print_results = CUBIT_TRUE;
00992 
00993   // We will turn off the printing of name change warnings during import and just
00994   // keep track of how many happened. 
00995   bool prev_print_warning_flag = RefEntityName::instance()->print_name_change_warnings();
00996   RefEntityName::instance()->print_name_change_warnings(false);
00997   RefEntityName::instance()->num_name_change_warnings(0);
00998   
00999   CubitStatus status = gqeList.get()->import_solid_model( file_name,
01000       file_type, bridge_list, import_options );
01001       
01002   if( bridge_list.size() == 0 )
01003   {
01004     importingSolidModel = CUBIT_FALSE;
01005     mergeGloballyOnImport = CUBIT_FALSE; 
01006     return status;
01007   }
01008 
01009   for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end(); ++itor)
01010     (*itor)->import_geometry(bridge_list);
01011 
01012   bridge_list.reset();
01013   DLIList<RefEntity*> tmp_ent_list;
01014   status = construct_refentities(bridge_list, &tmp_ent_list);
01015 
01016   // Print out a summary warning message if names were changed.
01017   RefEntityName::instance()->print_name_change_warnings(prev_print_warning_flag);
01018   if(RefEntityName::instance()->num_name_change_warnings() > 0)
01019   {
01020     PRINT_WARNING("%d invalid names were found during import.\n\n",
01021             RefEntityName::instance()->num_name_change_warnings());
01022   }
01023     
01024   if( imported_entities )
01025     (*imported_entities) += tmp_ent_list;
01026 
01027   if( CubitUndo::get_undo_enabled() )
01028   {
01029     if( tmp_ent_list.size() && status == CUBIT_SUCCESS )
01030       CubitUndo::note_result_entities( tmp_ent_list );
01031     else
01032       CubitUndo::remove_last_undo();
01033   }
01034 
01035   //clear out all attributes that were set to actuate
01036   DLIList<RefEntity*> all_ents;
01037   RefEntity::get_all_child_ref_entities( tmp_ent_list, all_ents );
01038   all_ents += tmp_ent_list;
01039   CubitAttribUser::clear_all_simple_attrib_set_to_actuate( all_ents );
01040 
01041     // report attribs imported
01042 //  CubitAttrib::report_attrib_importeds();
01043 
01044   importingSolidModel = CUBIT_FALSE;
01045   mergeGloballyOnImport = CUBIT_FALSE; 
01046     // now return
01047   return status;
01048 }
01049 
01050 // import entities to buffer
01051 CubitStatus GeometryQueryTool::import_solid_model(DLIList<RefEntity*> *imported_entities,
01052                                                   const char* pBuffer,
01053                                                   const int n_buffer_size)
01054 {
01055   if (0 == gqeList.size())
01056   {
01057     PRINT_WARNING("No active geometry engine.\n");
01058     return CUBIT_FAILURE;
01059   }
01060 
01061   if( CubitUndo::get_undo_enabled() )
01062     CubitUndo::save_state();
01063 
01064     // reset the attribImporteds flags to facilitate attribute reporting
01065 //  CubitAttrib::clear_attrib_importeds();
01066 
01067     // Use the default MQE to import a list of ToplogyBridges from the file.
01068   gqeList.reset();
01069   DLIList<TopologyBridge*> bridge_list;
01070 
01071   CubitStatus status = CUBIT_SUCCESS;
01072   for(int i = 0; i < gqeList.size(); i++)
01073   {
01074     status = gqeList.get_and_step()->import_solid_model( bridge_list, pBuffer, n_buffer_size );
01075 
01076     if( bridge_list.size() > 0 )
01077       break;
01078   }
01079   if(bridge_list.size() == 0)
01080     return status;
01081 
01082   for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end(); ++itor)
01083     (*itor)->import_geometry(bridge_list);
01084 
01085   bridge_list.reset();
01086   DLIList<RefEntity*> tmp_ent_list;
01087   status = construct_refentities(bridge_list, &tmp_ent_list);
01088 
01089   if( imported_entities )
01090     (*imported_entities) += tmp_ent_list;
01091 
01092   if( CubitUndo::get_undo_enabled() )
01093   {
01094     if( tmp_ent_list.size() && status == CUBIT_SUCCESS )
01095       CubitUndo::note_result_entities( tmp_ent_list );
01096     else
01097       CubitUndo::remove_last_undo();
01098   }
01099 
01100   //clear out all attributes that were set to actuate
01101 //  DLIList<RefEntity*> all_ents;
01102 //  RefEntity::get_all_child_ref_entities( tmp_ent_list, all_ents );
01103 //  all_ents += tmp_ent_list;
01104 //  CubitAttribUser::clear_all_simple_attrib_set_to_actuate( all_ents );
01105 
01106     // report attribs imported
01107 //  CubitAttrib::report_attrib_importeds();
01108 
01109 
01110     // now return
01111   return status;
01112 }
01113 
01114 CubitStatus GeometryQueryTool::construct_refentities(DLIList<TopologyBridge*> &bridge_list,
01115                                                      DLIList<RefEntity*> *imported_entities)
01116 {
01117 
01118     // Construct VGI Topology from the TopologyBridges.
01119   DLIList<Body*> body_list;
01120   DLIList<RefFace*> face_list;
01121   DLIList<RefEdge*> edge_list;
01122   DLIList<RefVertex*> vtx_list;
01123     // We are going to pop entities from bridge_list,
01124     // so reverse the list so that the entities get
01125     // created in the old order and the IDs remain
01126     // the same.
01127   bridge_list.reverse();
01128   bridge_list.reset();
01129   CubitStatus status = CUBIT_SUCCESS;
01130 
01131   bool do_progress = bridge_list.size() > 2 ? true : false;
01132 
01133   if(do_progress)
01134   {
01135     char message[128];
01136     sprintf(message, "Building %d CUBIT Entities", bridge_list.size() );
01137     AppUtil::instance()->progress_tool()->start(0, bridge_list.size(), "Progress",
01138         message, TRUE, TRUE);
01139   }
01140 
01141 
01142   while( bridge_list.size() && !AppUtil::instance()->interrupt() )
01143   {
01144     BodySM* bodysm_ptr;
01145     Surface* surface_ptr;
01146     Curve* curve_ptr;
01147     TBPoint* point_ptr;
01148     TopologyBridge* bridge_ptr = bridge_list.pop();
01149     if( (bodysm_ptr = dynamic_cast<BodySM*>(bridge_ptr) ) != NULL )
01150     {
01151       Body* body_ptr = make_Body( bodysm_ptr );
01152       if( body_ptr )
01153       {
01154         body_list.append( body_ptr );
01155       }
01156       else
01157       {
01158         PRINT_ERROR("\nError constructing VGI Body.\n");
01159         status = CUBIT_FAILURE;
01160       }
01161     }
01162     else if( (surface_ptr = dynamic_cast<Surface*>(bridge_ptr) ) != NULL )
01163     {
01164       bool is_free_face = true;
01165       RefFace* face_ptr = make_free_RefFace( surface_ptr, is_free_face );
01166       if( face_ptr )
01167       {
01168         face_list.append( face_ptr );
01169       }
01170       else
01171       {
01172         PRINT_ERROR("\nError constructing free VGI Surface.\n");
01173         status = CUBIT_FAILURE;
01174       }
01175     }
01176     else if( (curve_ptr = dynamic_cast<Curve*>(bridge_ptr) ) != NULL )
01177     {
01178       RefEdge* edge_ptr = make_free_RefEdge( curve_ptr );
01179       if( edge_ptr )
01180       {
01181         edge_list.append( edge_ptr );
01182       }
01183       else
01184       {
01185         PRINT_ERROR("\nError constructing free VGI Curve.\n");
01186         status = CUBIT_FAILURE;
01187       }
01188     }
01189     else if( (point_ptr = dynamic_cast<TBPoint*>(bridge_ptr) ) != NULL )
01190     {
01191       RefVertex* vtx_ptr = make_free_RefVertex( point_ptr );
01192       if( vtx_ptr )
01193       {
01194         vtx_list.append( vtx_ptr );
01195       }
01196       else
01197       {
01198         PRINT_ERROR("\nError constructing free VGI Vertex.\n");
01199         status = CUBIT_FAILURE;
01200       }
01201     }
01202     else
01203     {
01204       PRINT_ERROR("Unknown entity type imported by solid modeler.  Ignored.\n");
01205       status = CUBIT_FAILURE;
01206     }
01207     if(do_progress)
01208         AppUtil::instance()->progress_tool()->step();
01209   }
01210 
01211   if(do_progress)
01212     AppUtil::instance()->progress_tool()->end();
01213 
01214   PRINT_INFO("\n");
01215 
01216     // If the above loop was interrupted, bridge_list will not be
01217     // empty.  Free any bridges we did not make topology for.
01218   if( AppUtil::instance()->interrupt() )
01219   {
01220     PRINT_WARNING("Aborted construction of %d entities.\n", bridge_list.size());
01221   }
01222   while( bridge_list.size() )
01223   {
01224     TopologyBridge* bridge_ptr = bridge_list.pop();
01225     GeometryQueryEngine* gqe = bridge_ptr->get_geometry_query_engine();
01226     BodySM* body_ptr;
01227     Surface* surface_ptr;
01228     Curve* curve_ptr;
01229     TBPoint* point_ptr;
01230     if( (body_ptr = dynamic_cast<BodySM*>(bridge_ptr) ) != NULL )
01231       gqe->delete_solid_model_entities( body_ptr );
01232     else if( (surface_ptr = dynamic_cast<Surface*>(bridge_ptr) ) != NULL )
01233       gqe->delete_solid_model_entities( surface_ptr );
01234     else if( (curve_ptr = dynamic_cast<Curve*>(bridge_ptr) ) != NULL )
01235       gqe->delete_solid_model_entities( curve_ptr );
01236     else if( (point_ptr = dynamic_cast<TBPoint*>(bridge_ptr) ) != NULL )
01237       gqe->delete_solid_model_entities( point_ptr );
01238   }
01239 
01240 /*
01241     // If any geometry was pre-merged during the
01242     // RefEntity construction, adjust the sense of
01243     // the entities to match what it was originally.
01244   DLIList<BasicTopologyEntity*> bte_list;
01245   DLIList<RefFace*> child_face_list;
01246   DLIList<RefEdge*> child_edge_list;
01247   for( int b = body_list.size(); b--; )
01248   {
01249     body_list.get()->ref_faces( child_face_list );
01250     CAST_LIST_TO_PARENT( child_face_list, bte_list );
01251     adjust_merge_sense( bte_list );
01252     body_list.get()->ref_edges( child_edge_list );
01253     CAST_LIST_TO_PARENT( child_edge_list, bte_list );
01254     adjust_merge_sense( bte_list );
01255     body_list.step();
01256   }
01257   CAST_LIST_TO_PARENT( face_list, bte_list );
01258   adjust_merge_sense( bte_list );
01259   for( int f = face_list.size(); f--; )
01260   {
01261     face_list.get_and_step()->ref_edges( child_edge_list );
01262     CAST_LIST_TO_PARENT( child_edge_list, bte_list );
01263     adjust_merge_sense( bte_list );
01264   }
01265   CAST_LIST_TO_PARENT( edge_list, bte_list );
01266   adjust_merge_sense( bte_list );
01267 */
01268 
01269     // Actuate Attributes
01270   DLIList<RefEntity*> ref_entity_list, temp_ref_list;
01271 
01272   CAST_LIST_TO_PARENT( body_list, temp_ref_list );
01273   ref_entity_list += temp_ref_list;
01274   CAST_LIST_TO_PARENT( face_list, temp_ref_list );
01275   ref_entity_list += temp_ref_list;
01276   CAST_LIST_TO_PARENT( edge_list, temp_ref_list );
01277   ref_entity_list += temp_ref_list;
01278   CAST_LIST_TO_PARENT(  vtx_list, temp_ref_list );
01279   ref_entity_list += temp_ref_list;
01280 
01281   import_actuate( ref_entity_list );
01282 
01283     // Pass back imported entities
01284   if( imported_entities )
01285   {
01286     *imported_entities = ref_entity_list;
01287   }
01288 
01289   char pre[100];
01290   if( body_list.size() )
01291   {
01292     DLIList<RefVolume*> temp_vols;
01293     for( int nv = body_list.size(); nv > 0; nv-- )
01294     {
01295       DLIList<RefVolume*> t2;
01296       body_list.get_and_step()->ref_volumes( t2 );
01297       temp_vols += t2;
01298     }
01299 
01300     DLIList<CubitEntity*> temp_list;
01301     if( DEBUG_FLAG( 153 ) )
01302     {
01303       CAST_LIST_TO_PARENT(body_list, temp_list);
01304       if( temp_list.size() == 1 )
01305          CubitUtil::list_entity_ids( "Constructed 1 Body: ", temp_list);
01306       else
01307       {
01308         sprintf( pre, "Constructed %d Bodies: ", temp_list.size() );
01309         CubitUtil::list_entity_ids( pre, temp_list );
01310       }
01311     }
01312 
01313     temp_list.clean_out();
01314     CAST_LIST_TO_PARENT( temp_vols, temp_list );
01315     if( temp_list.size() == 1 )
01316        CubitUtil::list_entity_ids( "Constructed 1 Volume: ", temp_list);
01317     else
01318     {
01319       sprintf( pre, "Constructed %d Volumes: ", temp_list.size() );
01320       CubitUtil::list_entity_ids( pre, temp_list );
01321     }
01322   }
01323   if( face_list.size() )
01324   {
01325     DLIList<CubitEntity*> temp_list;
01326     CAST_LIST_TO_PARENT(face_list, temp_list);
01327     if( temp_list.size() == 1 )
01328       CubitUtil::list_entity_ids( "Constructed 1 Free Surface: ", temp_list );
01329     else
01330     {
01331       sprintf( pre, "Constructed %d Free Surfaces: ", temp_list.size() );
01332       CubitUtil::list_entity_ids( pre, temp_list );
01333     }
01334   }
01335   if( edge_list.size() )
01336   {
01337     DLIList<CubitEntity*> temp_list;
01338     CAST_LIST_TO_PARENT(edge_list, temp_list);
01339     if( temp_list.size() == 1 )
01340       CubitUtil::list_entity_ids( "Constructed 1 Free Curve: ", temp_list );
01341     else
01342     {
01343       sprintf( pre, "Constructed %d Free Curves: ", temp_list.size() );
01344       CubitUtil::list_entity_ids( pre, temp_list );
01345     }
01346   }
01347   if( vtx_list.size() )
01348   {
01349     DLIList<CubitEntity*> temp_list;
01350     CAST_LIST_TO_PARENT(vtx_list, temp_list);
01351     if( temp_list.size() == 1 )
01352       CubitUtil::list_entity_ids( "Constructed 1 Free Vertex: ", temp_list );
01353     else
01354     {
01355       sprintf( pre, "Constructed %d Free Vertices: ", temp_list.size() );
01356       CubitUtil::list_entity_ids( pre, temp_list );
01357     }
01358   }
01359 
01360   return status;
01361 }
01362 
01363 //-------------------------------------------------------------------------
01364 // Purpose       : Build/update Body topology
01365 //
01366 // Special Notes :
01367 //
01368 // Creator       : Jason Kraftcheck
01369 //
01370 // Creation Date : 08/21/02
01371 //-------------------------------------------------------------------------
01372 Body* GeometryQueryTool::make_Body(BodySM *bodysm_ptr) const
01373 {
01374   int i;
01375   CpuTimer timer;
01376   bool body_created = false;
01377   bool body_modified = false;
01378   bool vol_modified = false, tmp_vol_modified;
01379 
01380   Body* body = CAST_TO( bodysm_ptr->topology_entity(), Body );
01381   if( ! body )
01382   {
01383     body = RefEntityFactory::instance()->construct_Body(bodysm_ptr);
01384     body_created = true;
01385   }
01386   if( ! body )
01387   {
01388     PRINT_ERROR("Body creation failed in GeometryQueryTool::make_Body\n");
01389     assert( !!body );
01390     return 0;
01391   }
01392 
01393   DLIList<Lump*> lumps;
01394   bodysm_ptr->lumps( lumps );
01395 
01396   DLIList<SenseEntity*> dead_covols, new_covols(lumps.size());
01397   lumps.reset();
01398   for( i = lumps.size(); i--; )
01399   {
01400     RefVolume* vol = make_RefVolume( lumps.get_and_step(), tmp_vol_modified );
01401     if( !vol )
01402     {
01403       PRINT_ERROR("RefVolume creation failed in GeometryQueryTool::make_Body\n");
01404       PRINT_ERROR("Aborting construction of Body %d\n", body->id() );
01405       assert( !!vol );
01406     }
01407 
01408     if (tmp_vol_modified)
01409       vol_modified = true;
01410 
01411     SenseEntity* covol = vol->find_sense_entity( body );
01412     if (!covol)
01413     {
01414       covol = new CoVolume( vol );
01415       body_modified = true;
01416     }
01417 
01418     new_covols.append(covol);
01419   }
01420 
01421   body->set_sense_entity_list( new_covols, dead_covols );
01422 
01423   while (dead_covols.size())
01424   {
01425     destroy_dead_entity(dead_covols.pop());
01426     body_modified = true;
01427   }
01428 
01429   PRINT_DEBUG_3("Constructed Body %d from BodySM in %f seconds.\n",
01430     body->id(), timer.cpu_secs() );
01431 
01432   if( body_created )
01433   {
01434     AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::FREE_REF_ENTITY_GENERATED, body));
01435     CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_CREATED, body);
01436     const_cast<CGMHistory&>(mHistory).add_event(evt);
01437   }
01438   else if( body_modified )
01439   {
01440     AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::TOPOLOGY_MODIFIED, body));
01441     CGMHistory::Event evt(CGMHistory::TOPOLOGY_CHANGED, body);
01442     const_cast<CGMHistory&>(mHistory).add_event(evt);
01443   }
01444   else if( vol_modified )
01445   {
01446     AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_MODIFIED, body));
01447     CGMHistory::Event evt(CGMHistory::GEOMETRY_CHANGED, body);
01448     const_cast<CGMHistory&>(mHistory).add_event(evt);
01449   }
01450 
01451   PRINT_DEBUG_3("Updated graphics for Body %d in %f seconds.\n",
01452     body->id(), timer.cpu_secs() );
01453 
01454   return body;
01455 }
01456 
01457 //-------------------------------------------------------------------------
01458 // Purpose       : Build/update RefVolume topology
01459 //
01460 // Special Notes :
01461 //
01462 // Creator       : Jason Kraftcheck
01463 //
01464 // Creation Date : 08/21/02
01465 //-------------------------------------------------------------------------
01466 RefVolume* GeometryQueryTool::make_RefVolume( Lump* lump_ptr,
01467                                               bool& volume_modified ) const
01468 {
01469   int i;
01470 
01471   DLIList<ShellSM*> shellsms;
01472   DLIList<GroupingEntity*> old_shells, new_shells;
01473 
01474   bool volume_created = false;
01475   volume_modified = false;
01476   RefVolume* volume = CAST_TO( lump_ptr->topology_entity(), RefVolume );
01477   if( ! volume )
01478   {
01479     volume = RefEntityFactory::instance()->construct_RefVolume(lump_ptr);
01480     volume_created = true;
01481   }
01482   if( ! volume )
01483   {
01484     PRINT_ERROR("Volume creation failed in GeometryQueryTool::make_RefVolume\n");
01485     assert( !!volume );
01486     return 0;
01487   }
01488 
01489   lump_ptr->shellsms( shellsms );
01490   shellsms.reset();
01491   for( i = shellsms.size(); i--; )
01492   {
01493     bool shell_modified;
01494 
01495       // Don't use a shell if it is in a different RefVolume.
01496       // Can't move shells or other RefVolume may appear  unmodified
01497       // in later call to make_RefVolume.
01498 // This breaks things -- live without it for now
01499 //    ShellSM* shellsm = shellsms.get_and_step();
01500 //    Shell* shell = dynamic_cast<Shell*>(shellsm->topology_entity());
01501 //    if (shell && shell->get_basic_topology_entity_ptr() &&
01502 //                 shell->get_basic_topology_entity_ptr() != volume)
01503 //      shell->bridge_manager()->remove_bridge(shellsm);
01504 
01505       // Build/update Shell
01506     Shell* shell = make_Shell( shellsms.get_and_step(), shell_modified );
01507 
01508     if( !shell )
01509     {
01510       PRINT_ERROR("Shell creation failed in GeometryQueryTool::make_RefVolume\n");
01511       PRINT_ERROR("Aborting construction of Volume %d\n", volume->id() );
01512       assert( !!shell );
01513       return 0;
01514     }
01515     if( shell_modified )
01516       volume_modified = true;
01517 
01518       // If the shell is new (not already part of RefVolume) then
01519       // we will be modifying the RefVolume when we add it later.
01520     BasicTopologyEntity* parent = shell->get_basic_topology_entity_ptr();
01521     if (parent != volume)
01522     {
01523       if (parent)
01524         parent->remove_grouping_entity(shell);
01525       volume_modified = true;
01526     }
01527 
01528     new_shells.append( shell );
01529   }
01530 
01531   volume->set_grouping_entity_list( new_shells, old_shells );
01532   while( old_shells.size() )
01533   {
01534     GroupingEntity* shell = old_shells.pop();
01535     destroy_dead_entity( shell );
01536     volume_modified = true;
01537   }
01538 
01539   if (volume->deactivated())
01540     volume_modified = false;
01541   else if(!volume_created && volume_modified )
01542   {
01543 
01544 #ifndef ALPHA_LAYTRACKS3D
01545     AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::TOPOLOGY_MODIFIED, volume));
01546     CGMHistory::Event evt(CGMHistory::TOPOLOGY_CHANGED, volume);
01547     const_cast<CGMHistory&>(mHistory).add_event(evt);
01548 #endif
01549   }
01550 
01551   return volume;
01552 }
01553 
01554 //-------------------------------------------------------------------------
01555 // Purpose       : Build/update Shell topology
01556 //
01557 // Special Notes :
01558 //
01559 // Creator       : Jason Kraftcheck
01560 //
01561 // Creation Date : 08/21/02
01562 //-------------------------------------------------------------------------
01563 Shell* GeometryQueryTool::make_Shell(ShellSM *shellsm_ptr, bool& shell_modified ) const
01564 {
01565   Shell* shell = CAST_TO( shellsm_ptr->topology_entity(), Shell );
01566   shell_modified = false;
01567   if( !shell )
01568     shell = new Shell(shellsm_ptr);
01569   assert( shell != NULL );
01570 
01571   DLIList<CoFace*> face_cofaces(2);
01572   //shell->co_faces( old_cofaces );
01573   DLIList<SenseEntity*> new_cofaces, old_cofaces;
01574 
01575   DLIList<Surface*> surfaces;
01576   shellsm_ptr->surfaces( surfaces );
01577 
01578   int i;
01579   surfaces.reset();
01580   for( i = surfaces.size(); i--; )
01581   {
01582     Surface* surface = surfaces.get_and_step();
01583     RefFace* face = make_RefFace(surface);
01584     if( !face )
01585     {
01586       PRINT_ERROR("Surface creation failed in GeometryQueryTool::make_Shell\n");
01587       assert( !!face );
01588       return 0;
01589     }
01590 
01591     CubitSense sense = surface->get_shell_sense( shellsm_ptr );
01592     if( surface->bridge_sense() == CUBIT_REVERSED )
01593       sense = CubitUtil::opposite_sense( sense );
01594 
01595       // If sense is CUBIT_UNKNOWN, we have a two-sided
01596       // face and need to make two CoFaces.
01597     int num_cofaces = 1;
01598     if( sense == CUBIT_UNKNOWN )
01599     {
01600       DLIList<ShellSM*> surf_shells(2);
01601       surface->shellsms( surf_shells );
01602       assert( surf_shells.is_in_list(shellsm_ptr) );
01603       num_cofaces = 2;
01604       sense = CUBIT_FORWARD;
01605     }
01606 
01607       // If two CoFaces, loop once for each
01608     face_cofaces.clean_out();
01609     face->co_faces(face_cofaces);
01610     for( int k = 0; k < num_cofaces; k++ )
01611     {
01612 
01613       CoFace* coface = 0;
01614       for( int j = face_cofaces.size(); j--; )
01615       {
01616         CoFace* tmp_coface = face_cofaces.get();
01617         if( tmp_coface->get_sense() == sense &&
01618             tmp_coface->get_shell_ptr() == shell )
01619         {
01620           coface = tmp_coface;
01621           break;
01622         }
01623       }
01624 
01625       if (!coface)
01626       {
01627         coface = new CoFace();
01628         coface->attach_basic_topology_entity( face );
01629         shell_modified = true;
01630         if( coface->get_sense() != sense )
01631           coface->set_sense( sense );
01632       }
01633 
01634       new_cofaces.append(coface);
01635 
01636         // If we loop to create a second CoFace between
01637         // the same Surface-Shell pair, create it with
01638         // the opposite sense.
01639       sense = CubitUtil::opposite_sense(sense);
01640     }
01641   }
01642 
01643   shell->set_sense_entity_list( new_cofaces, old_cofaces );
01644 
01645     // Destroy any unwanted CoFaces (those remaining
01646     // in old_cofaces)
01647   while( old_cofaces.size() )
01648   {
01649     CoFace* dead_coface = dynamic_cast<CoFace*>(old_cofaces.pop());
01650     assert(!dead_coface->get_shell_ptr());
01651     destroy_dead_entity(dead_coface);
01652     shell_modified = true;
01653   }
01654 
01655   return shell;
01656 }
01657 
01658 
01659 //-------------------------------------------------------------------------
01660 // Purpose       : Find the CoEdgeSM in the passed Surface that should
01661 //                 be merged with the passed CoEdgeSM.
01662 //
01663 // Special Notes : Should be O(1) in the average case.  See comments below.
01664 //
01665 // Creator       : Jason Kraftcheck
01666 //
01667 // Creation Date : 08/21/02
01668 //-------------------------------------------------------------------------
01669 CoEdgeSM* GeometryQueryTool::find_merged_coedgesm( Surface* on_this_surf,
01670                                       CoEdgeSM* merged_with_this ) const
01671 {
01672     // Get the relative sense of the merged surfaces
01673   DLIList<Surface*> coedge_surfaces(1);
01674   merged_with_this->surfaces( coedge_surfaces );
01675   if( coedge_surfaces.size() != 1 )
01676     return 0;
01677   bool surfaces_reversed =
01678     (coedge_surfaces.get()->bridge_sense() != on_this_surf->bridge_sense());
01679 
01680     // Get the Curve merge partner from the CoEdgeSM merge partner
01681   DLIList<Curve*> coedge_curves(1);
01682   merged_with_this->curves( coedge_curves );
01683   if( coedge_curves.size() != 1 )
01684   {
01685     assert(coedge_curves.size() == 1);
01686     return 0;
01687   }
01688   Curve* merged_curve = coedge_curves.get();
01689 
01690     // If the curve doesn't have a bridge manager, it is
01691     // not merged.
01692   if (!merged_curve->bridge_manager())
01693     return 0;
01694 
01695     // Get all curves merged with the merged_curve
01696   int num_bridges = merged_curve->bridge_manager()->number_of_bridges();
01697   DLIList<TopologyBridge*> curve_bridges( num_bridges );
01698   merged_curve->bridge_manager()->get_bridge_list( curve_bridges );
01699 
01700     // Loop through Curves, looking for the Curve with the
01701     // parent CoEdgeSM we want.  This loop should be
01702     // roughly O(1) for manifold geometry (and most non-
01703     // manifold geometry), where n is the number of curves
01704     // merged together in the RefEdge.  For manifold
01705     // geometry, there are never more than 2 CoEdgeSMs per
01706     // Curve.  For most models, n is <= 4, so this entire
01707     // function can be considered O(1) for most models.
01708   DLIList<CoEdgeSM*> curve_coedges(2);
01709   curve_bridges.reset();
01710   for( int i = curve_bridges.size(); i--; )
01711   {
01712     TopologyBridge* curve = curve_bridges.get_and_step();
01713 
01714     curve_coedges.clean_out();
01715     curve->coedgesms( curve_coedges );
01716     curve_coedges.reset();
01717     for( int j = curve_coedges.size(); j--; )
01718     {
01719       CoEdgeSM* coedgesm = curve_coedges.get_and_step();
01720 
01721         // Get parent Surface of CoEdgeSM
01722       coedge_surfaces.clean_out();
01723       coedgesm->surfaces( coedge_surfaces );
01724       assert( coedge_surfaces.size() == 1 );
01725 
01726         // Is the parent Surface the one we are looking for?
01727       if( coedge_surfaces.get() == on_this_surf )
01728       {
01729           // Curve may occur in surface twice for non-manifold
01730           // topology.  We need to make sure we have the CoEdgeSM
01731           // with the correct sense.
01732 
01733           // Are the curves reversed wrt to each other?
01734         bool curves_reversed =
01735           (merged_curve->bridge_sense() != curve->bridge_sense());
01736           // Should this coedgesm be reversed wrt to the merge partner?
01737         bool should_be_reversed = (curves_reversed != surfaces_reversed);
01738           // Are the coedgesm actually reversed wrt to each other?
01739         bool are_reversed = (merged_with_this->sense() != coedgesm->sense());
01740 
01741           // Do the coedges have the appropriate senses
01742         if( should_be_reversed == are_reversed )
01743         {
01744           return  coedgesm;
01745         }
01746       }
01747     } // for(j = curve_coedgesms)
01748   } // for(i = curve_coedges)
01749 
01750   return 0;
01751 }
01752 
01753 //-------------------------------------------------------------------------
01754 // Purpose       : Build/update RefFace topology
01755 //
01756 // Special Notes :
01757 //
01758 // Creator       : Jason Kraftcheck
01759 //
01760 // Creation Date : 08/21/02
01761 //-------------------------------------------------------------------------
01762 RefFace* GeometryQueryTool::make_RefFace( Surface* surface_ptr ) const
01763 {
01764   int i;
01765   DLIList<LoopSM*> loopsms;
01766   DLIList<CoEdgeSM*> coedgesms;
01767   DLIList<Curve*> curves(1);
01768 
01769     // Get/construct RefFace for surface.
01770   bool face_created = false;
01771   bool face_modified = false;
01772   bool face_modified2 = false;
01773   RefFace* face = CAST_TO( surface_ptr->topology_entity(), RefFace );
01774   if( !face )
01775   {
01776     face = dynamic_cast<RefFace*>(check_mergeable_refentity(surface_ptr));
01777 
01778     //Including this call in here in case the surface a composite and
01779     //hidden curves need to be removed in the graphics.
01780     if( face )
01781     {
01782       face_modified2 = true;
01783     }
01784   }
01785   if( !face )
01786   {
01787     face = RefEntityFactory::instance()->construct_RefFace(surface_ptr);
01788     face_created = true;
01789   }
01790   assert(!!face);
01791   bool merged = face->bridge_manager()->number_of_bridges() > 1;
01792 
01793     // First construct all the RefEdges.  If the Curves
01794     // were merged, the RefEdges will be constructed merged.
01795     // We need the merged RefEdges to determined which
01796     // CoEdges and Loops need to be merged.  We could do this
01797     // with one loop by getting the curves directly from the
01798     // surface.  However, that might result in different
01799     // RefEdge IDs, so do it with nested loops like the old code.
01800   loopsms.clean_out();
01801   surface_ptr->loopsms( loopsms );
01802   loopsms.reset();
01803   for( i = loopsms.size(); i--; )
01804   {
01805     LoopSM* loopsm = loopsms.get_and_step();
01806     coedgesms.clean_out();
01807     loopsm->coedgesms(coedgesms);
01808     coedgesms.reset();
01809     for( int j = coedgesms.size(); j--; )
01810     {
01811       CoEdgeSM* coedgesm = coedgesms.get_and_step();
01812       curves.clean_out();
01813       coedgesm->curves(curves);
01814       if( curves.size() != 1 )
01815       {
01816         PRINT_ERROR("Invalid SolidModel topology encountered in "
01817                     "GeometryQueryTool::make_RefFace.  CoEdgeSM in "
01818                     "Surface %d has %d curves.\n", face->id(), curves.size());
01819         if( curves.size() == 0 )
01820           continue;
01821       }
01822 
01823       RefEdge* edge = make_RefEdge( curves.get() );
01824       if( !edge )
01825       {
01826         PRINT_ERROR("Failed to construct RefEdge in Surface %d\n",face->id());
01827       }
01828     }
01829   }
01830 
01831     // If the Surface was merged, make sure it can remain merged
01832   if (merged && !make_merged_RefFace(surface_ptr))
01833     merged = false;
01834 
01835     // If !merged, then if necessary unmerge the RefFace
01836   if( !merged && face->bridge_manager()->number_of_bridges() > 1 )
01837   {
01838     PRINT_WARNING("Unmerging Surface %d.\n", face->id() );
01839 
01840       // unmerge
01841     face->bridge_manager()->remove_bridge(surface_ptr);
01842 
01843       // reset bridge sense on unmerged surface
01844     if (surface_ptr->bridge_sense() == CUBIT_REVERSED)
01845       surface_ptr->reverse_bridge_sense();
01846 
01847       // if the first bridge in the old refface is now reversed,
01848       // flip the refface.
01849     if (face->get_surface_ptr()->bridge_sense() == CUBIT_REVERSED)
01850     {
01851       face->bridge_manager()->reverse_bridge_senses();
01852       face->reverse_topology();
01853     }
01854 
01855       // construct new refface for unmerged surface.
01856     face = RefEntityFactory::instance()->construct_RefFace(surface_ptr);
01857     face_created = true;
01858   }
01859 
01860     // If the sense of the Surface with respect to the RefFace is
01861     // reversed, need to construct Loops and CoEdges reversed.
01862   bool need_to_reverse = (surface_ptr->bridge_sense() == CUBIT_REVERSED);
01863 
01864     // Construct LoopSMs and CoEdgeSMs, and attach
01865   loopsms.clean_out();
01866   surface_ptr->loopsms( loopsms );
01867   loopsms.reset();
01868   DLIList<SenseEntity*> coedges, old_coedges;
01869   DLIList<GroupingEntity*> loops(loopsms.size()), dead_loops;
01870   for( i = loopsms.size(); i--; )
01871   {
01872       // Get/construct Loop
01873     LoopSM* loopsm = loopsms.get_and_step();
01874     Loop* loop = dynamic_cast<Loop*>(loopsm->topology_entity());
01875     if( loop && !merged && loop->bridge_manager()->number_of_bridges() > 1 )
01876     {
01877       loop->bridge_manager()->remove_bridge( loopsm );
01878       loop = new Loop( loopsm );
01879       face_modified = true;
01880     }
01881     else if( !loop )
01882     {
01883       loop = new Loop( loopsm );
01884       face_modified = true;
01885     }
01886 
01887       // If loop is already attached to some other RefFace
01888       // we cannot use it.  NOTE:  Removing the Loop from
01889       // the other RefFace is NOT an option, even if the
01890       // loop has only our loopsm.  If we were to remove it
01891       // we could potentially miss the fact that the other
01892       // RefFace was modified when doing make_RefFace for
01893       // RefFace.
01894     RefFace* loop_face = loop->get_ref_face_ptr();
01895     if( loop_face && loop_face != face )
01896     {
01897       loop->bridge_manager()->remove_bridge( loopsm );
01898       loop = new Loop( loopsm );
01899       face_modified = true;
01900     }
01901     loops.append(loop);
01902 
01903       // Get CoEdges in the appropriate order
01904     coedgesms.clean_out();
01905     loopsm->coedgesms( coedgesms );
01906     if( coedgesms.size() == 0 )
01907     {
01908       PRINT_ERROR("Encountered Loop with no CoEdges in Surface %d.\n",
01909         face->id() );
01910       continue;
01911     }
01912     if( need_to_reverse )
01913       coedgesms.reverse();
01914     coedgesms.reset();
01915 
01916       // Consturct/update each CoEdge
01917     int j;
01918     coedges.clean_out();
01919     for( j = coedgesms.size(); j--; )
01920     {
01921       CoEdgeSM* coedgesm = coedgesms.get_and_step();
01922       CoEdge* coedge = dynamic_cast<CoEdge*>(coedgesm->topology_entity());
01923 
01924         // If the CoEdge is merged but the surface isn't, unmerge
01925         // the CoEdge
01926       if( coedge && !merged && coedge->bridge_manager()->number_of_bridges() > 1 )
01927       {
01928         coedge->bridge_manager()->remove_bridge( coedgesm );
01929         coedge = 0;
01930       }
01931 
01932         // If CoEdge belongs to a loop in some other face, don't
01933         // use it.
01934       if( coedge && coedge->get_loop_ptr() && coedge->get_loop_ptr() != loop )
01935       {
01936         coedge->bridge_manager()->remove_bridge( coedgesm );
01937         coedge = 0;
01938       }
01939 
01940         // If the CoEdgeSM doesn't already have an owning CoEdge
01941         // (or we unmerged) create a new CoEdge
01942       if( !coedge )
01943       {
01944         coedge = new CoEdge();
01945         coedge->bridge_manager()->add_bridge( coedgesm );
01946         face_modified = true;
01947       }
01948       coedges.append( coedge );
01949 
01950         // Find the RefEdge to attach to
01951       curves.clean_out();
01952       coedgesm->curves( curves );
01953       if( curves.size() == 0 )
01954         continue; // error message should have been printed already
01955 
01956       Curve* curve = curves.get();
01957       RefEdge* edge = dynamic_cast<RefEdge*>(curve->topology_entity());
01958       assert( edge != NULL );
01959 
01960         // Figure out what the CoEdge sense should be.
01961         // The CoEdge sense should be the product ("product"
01962         // as in multiply) of three
01963         // senses: 1) the sense of the surface wrt its RefFace,
01964         // 2) the sense of the curve wrt its RefEdge, and 3)
01965         // the sense of the CoEdgeSM.
01966       bool curve_reversed = (CUBIT_REVERSED == curve->bridge_sense());
01967       bool reverse = (curve_reversed != need_to_reverse);
01968       CubitSense sense = coedgesm->sense();
01969       if( reverse )
01970         sense = CubitUtil::opposite_sense(sense);
01971       if( coedge->get_sense() != sense )
01972         coedge->set_sense( sense );
01973 
01974         // Attach RefEdge to CoEdge (if it isn't already)
01975       RefEdge* coedge_edge = coedge->get_ref_edge_ptr();
01976       if (coedge_edge != edge)
01977       {
01978         if (coedge_edge)
01979         {
01980           coedge_edge->remove_sense_entity(coedge);
01981           destroy_dead_entity(coedge_edge);
01982           face_modified = true;
01983         }
01984         coedge->attach_basic_topology_entity(edge);
01985       }
01986     }
01987 
01988       // Attach CoEdges to Loop
01989     old_coedges.clean_out();
01990     loop->set_sense_entity_list(coedges, old_coedges);
01991 
01992       // Clean up dead coedges
01993     while (old_coedges.size())
01994     {
01995       CoEdge* dead_coedge = dynamic_cast<CoEdge*>(old_coedges.pop());
01996       assert(!dead_coedge->get_loop_ptr());
01997       destroy_dead_entity(dead_coedge);
01998       face_modified = true;
01999     }
02000   } // end for( i == loopsms )
02001 
02002     // Attach loops
02003   face->set_grouping_entity_list( loops, dead_loops );
02004 
02005     // Remove any dead loops
02006   while (dead_loops.size())
02007   {
02008     GroupingEntity* loop = dead_loops.pop();
02009     destroy_dead_entity(loop);
02010     face_modified = true;
02011   }
02012 
02013   if( !face_created && face_modified && !face->deactivated() )
02014   {
02015     AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_TOPOLOGY_MODIFIED, face));
02016     CGMHistory::Event evt2(CGMHistory::TOPOLOGY_CHANGED, face);
02017     const_cast<CGMHistory&>(mHistory).add_event(evt2);
02018     CGMHistory::Event evt(CGMHistory::GEOMETRY_CHANGED, face);
02019     const_cast<CGMHistory&>(mHistory).add_event(evt);
02020   }
02021   else if(face_modified2)
02022   {
02023     AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::TOPOLOGY_MODIFIED, face));
02024     CGMHistory::Event evt(CGMHistory::TOPOLOGY_CHANGED, face);
02025     const_cast<CGMHistory&>(mHistory).add_event(evt);
02026   }
02027 
02028   return face;
02029 }
02030 
02031 
02032 //-------------------------------------------------------------------------
02033 // Purpose       : Check if Surface can remain merged.
02034 //
02035 // Special Notes :
02036 //
02037 // Creator       : Jason Kraftcheck
02038 //
02039 // Creation Date : 12/12/03
02040 //-------------------------------------------------------------------------
02041 CubitStatus GeometryQueryTool::make_merged_RefFace(Surface* surface_ptr) const
02042 {
02043     // Get the RefFace
02044   RefFace* face = dynamic_cast<RefFace*>(surface_ptr->topology_entity());
02045   if (!face)  // isn't merged
02046     return CUBIT_FAILURE;
02047 
02048     // Get a Surface to compare to.
02049   int num_bridges = face->bridge_manager()->number_of_bridges();
02050   if (num_bridges < 2) // isn't merged
02051     return CUBIT_FAILURE;
02052 
02053   // Get some other Surface in merged RefFace to compare
02054   // topology with.
02055   DLIList<TopologyBridge*> bridge_list(num_bridges);
02056   face->bridge_manager()->get_bridge_list(bridge_list);
02057   bridge_list.reset();
02058   if (bridge_list.get() == surface_ptr)
02059     bridge_list.step();
02060   TopologyBridge* merged_bridge = bridge_list.get();
02061   Surface* merged_surface = dynamic_cast<Surface*>(merged_bridge);
02062   assert(merged_surface && merged_surface != surface_ptr);
02063 
02064     // Get the relative sense of the Surfaces
02065   bool surfaces_reversed =
02066     (surface_ptr->bridge_sense() != merged_surface->bridge_sense());
02067 
02068     // Get LoopSMs for both surfaces
02069   DLIList<LoopSM*> merged_loops, loopsms;
02070   surface_ptr->loopsms(loopsms);
02071   merged_surface->loopsms(merged_loops);
02072   if( merged_loops.size() != loopsms.size() )
02073     return CUBIT_FAILURE;
02074 
02075     // For each LoopSM on the merged Surface, find the
02076     // corresponding LoopSM on this Surface and merge.
02077   DLIList<CoEdgeSM*> merged_coedges, coedgesms;
02078   DLIList<LoopSM*> coedge_loops(1);
02079   DLIList<Curve*> curves(1);
02080   merged_loops.reset();
02081   for( int i = merged_loops.size(); i--; )
02082   {
02083     LoopSM* merged_loop = merged_loops.get_and_step();
02084 
02085       // Find the LoopSM by choosing a CoEdgeSM from the
02086       // merged LoopSM, and finding corresponding CoEdgeSM
02087       // on the Surface we are building.
02088 
02089     merged_coedges.clean_out();
02090     merged_loop->coedgesms( merged_coedges );
02091     merged_coedges.reset();
02092     CoEdgeSM* merged_coedge = merged_coedges.get();
02093 
02094     CoEdgeSM* coedgesm = find_merged_coedgesm( surface_ptr, merged_coedge );
02095     if( !coedgesm )
02096       return CUBIT_FAILURE;
02097 
02098      // Get the LoopSM in surface_ptr from the CoEdgeSM
02099     coedge_loops.clean_out();
02100     coedgesm->loopsms( coedge_loops );
02101     assert( coedge_loops.size() == 1 );
02102     LoopSM* loopsm = coedge_loops.get();
02103 
02104       // Get all the CoEdgeSMs on the LoopSM we are going to merge.
02105     coedgesms.clean_out();
02106     loopsm->coedgesms( coedgesms );
02107     if( coedgesms.size() != merged_coedges.size() )
02108       return CUBIT_FAILURE;
02109 
02110       // Get the CoEdge list in the appropriate order and position
02111     if( surfaces_reversed )
02112       coedgesms.reverse();
02113     coedgesms.move_to(coedgesm);
02114     assert( coedgesms.get() == coedgesm );
02115 
02116       // Now check and merge CoEdgeSM pairs
02117     for( int j = coedgesms.size(); j--; )
02118     {
02119       coedgesm = coedgesms.get_and_step();
02120       merged_coedge = merged_coedges.get_and_step();
02121 
02122         // Get Curve in surface_ptr
02123       curves.clean_out();
02124       coedgesm->curves(curves);
02125       if( curves.size() != 1 )
02126       {
02127         PRINT_ERROR("Invalid SolidModel topology encountered in "
02128                     "GeometryQueryTool::make_RefFace.  CoEdgeSM in "
02129                     "has %d curves.\n", curves.size());
02130         return CUBIT_FAILURE;
02131       }
02132       Curve* curve = curves.get();
02133 
02134         // Get Curve in merged_surface
02135       curves.clean_out();
02136       merged_coedge->curves(curves);
02137       if( curves.size() != 1 )
02138       {
02139         PRINT_ERROR("Invalid SolidModel topology encountered in "
02140                     "GeometryQueryTool::make_RefFace.  CoEdgeSM in "
02141                     "has %d curves.\n", curves.size());
02142         return CUBIT_FAILURE;
02143       }
02144       Curve* merged_curve = curves.get_and_step();
02145 
02146         // Check if curves are merged
02147       if( merged_curve->bridge_manager() != curve->bridge_manager() )
02148         return CUBIT_FAILURE;
02149 
02150         // Check that relative sense of CoEdgeSMs is correct
02151       bool curves_reversed =
02152         (merged_curve->bridge_sense() != curve->bridge_sense());
02153         // Should this coedgesm be reversed wrt to the merge partner?
02154       bool should_be_reversed = (curves_reversed != surfaces_reversed);
02155         // Are the coedgesm actually reversed wrt to each other?
02156       bool are_reversed = (merged_coedge->sense() != coedgesm->sense());
02157       if( should_be_reversed != are_reversed )
02158         return CUBIT_FAILURE;
02159 
02160         // Merge the CoEdgeSMs
02161       CoEdge* coedge = dynamic_cast<CoEdge*>(coedgesm->topology_entity());
02162       CoEdge* merge  = dynamic_cast<CoEdge*>(merged_coedge->topology_entity());
02163 
02164         // If this coedgesm is not the primary coedgesm in the
02165         // CoEdge, check to make sure the primary CoEdgeSM's curve
02166         // is merged with our curve.
02167       if (coedge && coedge->bridge_manager()->number_of_bridges() > 1
02168            && coedge->bridge_manager()->topology_bridge() != coedgesm
02169            && coedge->bridge_manager()->topology_bridge() != merged_coedge )
02170       {
02171         curves.clean_out();
02172         coedge->bridge_manager()->topology_bridge()->curves(curves);
02173         assert(curves.size() == 1);
02174         if (curves.get()->owner() != curve->owner())
02175         {
02176           coedge->bridge_manager()->remove_bridge(coedgesm);
02177           assert(coedge->get_parents());
02178           coedge = 0;
02179         }
02180       }
02181       if (merge && merge->bridge_manager()->number_of_bridges() > 1
02182            && merge->bridge_manager()->topology_bridge() != coedgesm
02183            && merge->bridge_manager()->topology_bridge() != merged_coedge )
02184       {
02185         curves.clean_out();
02186         merge->bridge_manager()->topology_bridge()->curves(curves);
02187         assert(curves.size() == 1);
02188         if (curves.get()->owner() != curve->owner())
02189         {
02190           merge->bridge_manager()->remove_bridge(merged_coedge);
02191           assert(merge->get_parents());
02192           merge = 0;
02193         }
02194       }
02195 
02196         // If the two CoEdgeSM's aren't in the same CoEdge,
02197         // merge them.
02198       if (merge && merge != coedge)
02199       {
02200         if (coedge)
02201         {
02202           coedge->bridge_manager()->remove_bridge(coedgesm);
02203           destroy_dead_entity(coedge);
02204         }
02205         merge->bridge_manager()->add_bridge(coedgesm);
02206       }
02207         // If for some reason (Composite curve creatation does
02208         // this) neither CoEdgeSM has a CoEdge, create one and
02209         // re-merge them.
02210       else if (!coedge && !merge)
02211       {
02212         coedge = new CoEdge(coedgesm);
02213         coedge->bridge_manager()->add_bridge(merged_coedge);
02214       }
02215       else if(!coedge)
02216       {
02217         merge->bridge_manager()->add_bridge(coedgesm);
02218       }
02219       else if(!merge)
02220       {
02221         coedge->bridge_manager()->add_bridge(merged_coedge);
02222       }
02223     } // for( j = coedgesms )
02224 
02225 
02226     Loop* loop = dynamic_cast<Loop*>(loopsm->topology_entity());
02227     Loop* merged = dynamic_cast<Loop*>(merged_loop->topology_entity());
02228       // If the two LoopSMs aren't in the same Loop, merge them
02229     if( merged != 0 && merged != loop )
02230     {
02231       if( loop )
02232         loop->bridge_manager()->remove_bridge(loopsm);
02233       merged->bridge_manager()->add_bridge(loopsm);
02234     }
02235     else if( !loop && !merged )
02236     {
02237       loop = new Loop;
02238       loop->bridge_manager()->add_bridge(merged_loop);
02239     }
02240     else if( !loop )
02241     {
02242       merged->bridge_manager()->add_bridge(loopsm);
02243     }
02244     else if( !merged )
02245     {
02246       loop->bridge_manager()->add_bridge(merged_loop);
02247     }
02248   } // for( i = merged_loops )
02249 
02250   return CUBIT_SUCCESS;
02251 }
02252 
02253 //-------------------------------------------------------------------------
02254 // Purpose       : Get/construct/update a RefEdge from a Curve
02255 //
02256 // Special Notes :
02257 //
02258 // Creator       : Jason Kraftcheck
02259 //
02260 // Creation Date : 08/22/02
02261 //-------------------------------------------------------------------------
02262 RefEdge* GeometryQueryTool::make_RefEdge( Curve* curve_ptr ) const
02263 {
02264   int i;
02265 
02266     // Get/construct RefEdge
02267   bool edge_created = false;
02268   bool edge_modified = false;
02269   RefEdge* edge = dynamic_cast<RefEdge*>(curve_ptr->topology_entity());
02270   if( !edge )
02271     edge = dynamic_cast<RefEdge*>(check_mergeable_refentity(curve_ptr));
02272   if( !edge )
02273   {
02274     edge = RefEntityFactory::instance()->construct_RefEdge(curve_ptr);
02275     edge_created = true;
02276   }
02277   assert(edge != NULL);
02278   bool reversed = (CUBIT_REVERSED == curve_ptr->bridge_sense());
02279   bool merged = edge->bridge_manager()->number_of_bridges() > 1;
02280 
02281     // Construct RefVertices
02282   DLIList<TBPoint*> points(2);
02283   curve_ptr->points( points );
02284   if( reversed )
02285     points.reverse();
02286 
02287   if( points.size() > 2 || points.size() < 1 )
02288   {
02289     PRINT_ERROR("Invalid SolidModel topology encountered in "
02290                 "GeometryQueryTool::make_RefEdge.  Curve %d "
02291                 "has %d vertices.\n", edge->id(), points.size() );
02292     assert( points.size() == 1 || points.size() == 2 );
02293     if( points.size() == 0 )
02294       return edge;
02295   }
02296 
02297   points.reset();
02298   RefVertex* start_vertex = make_RefVertex( points.get() );
02299   points.last();
02300   RefVertex* end_vertex = make_RefVertex( points.get() );
02301 
02302     // If curves are merged, make sure vertices are merged.
02303   if( merged )
02304   {
02305     int num_bridges = edge->bridge_manager()->number_of_bridges();
02306     DLIList<TopologyBridge*> bridge_list( num_bridges );
02307     edge->bridge_manager()->get_bridge_list( bridge_list );
02308 
02309     bridge_list.reset();
02310     for( i = bridge_list.size(); i--; )
02311       if( bridge_list.get() != curve_ptr )
02312         break;
02313       else
02314         bridge_list.step();
02315 
02316       // Get points on some other Curve that this curve is merged with.
02317     Curve* other_curve = dynamic_cast<Curve*>(bridge_list.get());
02318     assert( other_curve != curve_ptr) ;
02319     points.clean_out();
02320     other_curve->points(points);
02321     if( other_curve->bridge_sense() == CUBIT_REVERSED )
02322       points.reverse();
02323 
02324       // Check that points merged.
02325     points.reset();
02326     if( points.get()->topology_entity() != start_vertex )
02327       merged = false;
02328     points.last();
02329     if( points.get()->topology_entity() != end_vertex )
02330       merged = false;
02331 
02332     //perhaps the bridge sense just needs to be swapped 
02333     if( merged == false )
02334     {
02335       points.reverse();
02336       points.reset();
02337       TBPoint *point1 = points.get_and_step();
02338       TBPoint *point2 = points.get_and_step();
02339       if( point1->topology_entity() == start_vertex &&
02340           point2->topology_entity() == end_vertex )
02341       {
02342         merged = true;
02343         curve_ptr->reverse_bridge_sense();
02344       }
02345     }
02346   }
02347     // Unmerge the curve, if necessary.
02348   if( !merged && edge->bridge_manager()->number_of_bridges() > 1 )
02349   {
02350     PRINT_WARNING("Unmerging Curve %d\n", edge->id() );
02351 
02352       // unmerge
02353     edge->bridge_manager()->remove_bridge( curve_ptr );
02354 
02355       // reset bridge sense on un-merged curve
02356     if (curve_ptr->bridge_sense() == CUBIT_REVERSED)
02357     {
02358       curve_ptr->reverse_bridge_sense();
02359     }
02360 
02361       // if first curve in old edge now has reversed sense,
02362       // reverse the old edge also.
02363     //if (edge->get_curve_ptr()->bridge_sense() == CUBIT_REVERSED)
02364     //{
02365     //  edge->bridge_manager()->reverse_bridge_senses();
02366     //  edge->reverse_topology();
02367     //}
02368 
02369       // Create new RefEdge for un-merged curve
02370     edge = RefEntityFactory::instance()->construct_RefEdge( curve_ptr );
02371     PRINT_WARNING("Creating edge %d that was supposed to be merged\n", edge->id() );
02372     edge_created = true;
02373 
02374       // If we had swapped the vertex order because the curve
02375       // was reversed, switch them back because we unmerged so
02376       // we're going to create the new curve with a forward sense.
02377     if( reversed )
02378       std::swap(start_vertex,end_vertex);
02379   }
02380 
02381     // Get/construct Chain
02382   Chain* chain = edge->get_chain_ptr();
02383   if( !chain )
02384   {
02385     chain = new Chain();
02386     edge->add_grouping_entity( chain );
02387   }
02388 
02389     // Get any existing CoVertices
02390   DLIList<CoVertex*> co_vertices(2);
02391   chain->co_vertices( co_vertices );
02392   if( co_vertices.size() > 2 )
02393   {
02394     PRINT_ERROR("In GeometryQueryTool::make_RefEdge, encountered "
02395                 "a Chain with %d CoVertices on Curve %d\n",
02396                 co_vertices.size(), edge->id());
02397     assert( co_vertices.size() <= 2 );
02398   }
02399 
02400     // Now construct CoVertices if necessary, and attach
02401     // RefVertices.
02402   DLIList<RefVertex*> vertices(1);
02403   CoVertex* prev = 0;
02404     // First iteration is for start RefVertex
02405   RefVertex* vertex = start_vertex;
02406   co_vertices.reset();
02407     // Loop twice, once for each CoVertex.
02408   for( i = 0; i < 2; i++ )
02409   {
02410       // Construct CoVertex if one does not already exist
02411     CoVertex* cvtx = 0;
02412     if( co_vertices.size() > i )
02413     {
02414       cvtx = co_vertices.get_and_step();
02415     }
02416     else
02417     {
02418       cvtx = new CoVertex();
02419       chain->add_sense_entity( cvtx , prev );
02420     }
02421     prev = cvtx;
02422 
02423       // Get existing RefVertex from CoVertex, if it has one.
02424     vertices.clean_out();
02425     cvtx->ref_vertices( vertices );
02426     if( vertices.size() > 1 )
02427     {
02428       PRINT_ERROR("In GeometryQueryTool::make_RefEdge, encountered "
02429                   "a CoVertex with %d Vertices on Curve %d\n",
02430                    vertices.size(), edge->id());
02431       assert( vertices.size() <= 1 );
02432       vertices.reset();
02433     }
02434     RefVertex* cvtx_vertex = vertices.size() ? vertices.get() : 0;
02435 
02436       // Attach RefVertex to CoVertex if necessary
02437     if( cvtx_vertex != vertex )
02438     {
02439         // Wrong RefVertex.  Unhook from that one.
02440       if( cvtx_vertex )
02441       {
02442         cvtx_vertex->remove_sense_entity(cvtx);
02443         if (NULL == cvtx_vertex->get_point_ptr())
02444           destroy_dead_entity( cvtx_vertex );
02445       }
02446 
02447       cvtx->attach_basic_topology_entity( vertex );
02448       edge_modified = true;
02449     }
02450 
02451       // Second iteration is for end RefVertex
02452     vertex = end_vertex;
02453   }
02454 
02455   if( !edge_created && edge_modified && !edge->deactivated() )
02456   {
02457     AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_TOPOLOGY_MODIFIED, edge));
02458     CGMHistory::Event evt2(CGMHistory::TOPOLOGY_CHANGED, edge);
02459     const_cast<CGMHistory&>(mHistory).add_event(evt2);
02460     CGMHistory::Event evt(CGMHistory::GEOMETRY_CHANGED, edge);
02461     const_cast<CGMHistory&>(mHistory).add_event(evt);
02462   }
02463 
02464   return edge;
02465 }
02466 
02467 
02468 RefEntity *GeometryQueryTool::check_mergeable_refentity(GeometryEntity *bridge) const
02469 {
02470     // Disable for surfaces until we can correctly handle
02471     // surfaces that have virtual curves.
02472     // J.Kraftcheck  Apr.29,2002
02473 //  if( dynamic_cast<Surface*>(bridge) )
02474 //    return 0;
02475 
02476   if (CUBIT_FALSE == CGMApp::instance()->attrib_manager()->auto_actuate_flag(CA_MERGE_PARTNER))
02477     return NULL;
02478 
02479     // checks the topology bridge for a merge attribute, which might lead to another
02480     // refentity
02481   DLIList<CubitSimpleAttrib> csa_list;
02482   const char* name = CGMApp::instance()->attrib_manager()->att_internal_name(CA_MERGE_PARTNER);
02483   bridge->get_simple_attribute(name, csa_list);
02484 
02485   RefEntity *re_ptr = NULL;
02486 
02487   if(csa_list.size() > 0)
02488   {
02489     const CubitSimpleAttrib &csa_ptr = csa_list.size() ? csa_list.get() : CubitSimpleAttrib();
02490 
02491       // from the csa, call CAMP to get the partner, if one exists
02492       // (and return it)
02493     int merge_id = csa_ptr.int_data_list()[0];
02494 
02495     if( importingSolidModel && CUBIT_FALSE == GSaveOpen::performingUndo && 
02496         !mergeGloballyOnImport )
02497     {
02498       //if the merge id isn't already on some other entity already imported,
02499       //this entity doesn't have anybody to merge with...return NULL
02500       if( !uidsOfImportingEnts.is_in_list( merge_id) )
02501       {
02502         GeometryQueryTool::uidsOfImportingEnts.append( merge_id );
02503         return NULL;
02504       }
02505     }
02506 
02507     bool unique_append = false;
02508     if( GeometryQueryTool::trackMergedAwayEnts )
02509       unique_append = GeometryQueryTool::uidsOfImportingEnts.append_unique( merge_id );
02510 
02511     ToolDataUser *tdu = TDUniqueId::find_td_unique_id(merge_id);
02512     TopologyEntity *te = dynamic_cast<TopologyEntity*>(tdu);
02513 
02514     CubitSense sense = CAMergePartner::get_bridge_sense( csa_ptr );
02515 
02516     //We found the merge partner.....
02517     if (te != NULL)
02518     {
02519       //it's the first time you found this uid and you found an entity
02520       //
02521       if(GeometryQueryTool::trackMergedAwayEnts && unique_append )
02522         GeometryQueryTool::entitiesMergedAway++;
02523 
02524         // assume this merge attrib will be actuated, so remove the csa
02525       bridge->remove_simple_attribute_virt(csa_ptr);
02526 
02527         // now do the actual merge
02528       re_ptr = dynamic_cast<RefEntity*> (te);
02529 
02530       //compare relative sense.....reverse bridges as necessary
02531       Surface *surface = CAST_TO( bridge, Surface );
02532       Curve *curve= CAST_TO( bridge, Curve );
02533       CubitSense rel_sense = CUBIT_FORWARD;
02534 
02535       CubitBoolean is_survivor = CAMergePartner::is_survivor( csa_ptr );
02536       if( surface )
02537       {
02538         TopologyBridge *other_bridge = te->bridge_manager()->topology_bridge();
02539         Surface *other_surface = CAST_TO( other_bridge, Surface );
02540         rel_sense = relative_sense( surface, other_surface );
02541       }
02542       else if( curve )
02543       {
02544         TopologyBridge *other_bridge = te->bridge_manager()->topology_bridge();
02545         Curve *other_curve = CAST_TO( other_bridge, Curve );
02546         rel_sense = curve->relative_sense( other_curve );
02547       }
02548 
02549       //non-surviving merged entity is here....reverse
02550       //its bridge sense so that it will merge
02551       if( !is_survivor && sense != CUBIT_UNKNOWN && rel_sense == CUBIT_REVERSED )
02552         bridge->reverse_bridge_sense();
02553       //surviving merged entity is now being restored....
02554       //reverse the ref entity and make this entity the primary one
02555       if( is_survivor )
02556       {
02557         //If the passed in new bridge is the real survivor of the merge,
02558         //it should be the first bridge in the bridge manager.  The first
02559         //bridge in the bridge manager is always FORWARD wrt the TE.
02560         // If this new bridge is reversed wrt the current first bridge,
02561         // reverse all the other bridges so that they will all merge
02562         //successfully with this new first bridge.  Also add this new bridge
02563         //as the first bridge, since it was the original survivor.
02564         if( rel_sense == CUBIT_REVERSED )
02565         {
02566           te->reverse_topology();
02567 
02568           //reverse the sense of the bridges of this refentity
02569           DLIList<TopologyBridge*> bridge_list;
02570           te->bridge_manager()->get_bridge_list( bridge_list );
02571 
02572           int kk;
02573           for( kk=bridge_list.size(); kk--; )
02574           {
02575             TopologyBridge *tmp_bridge = bridge_list.get_and_step();
02576             tmp_bridge->reverse_bridge_sense();
02577           }
02578         } 
02579 
02580         //add this bridge as the primary bridge
02581         te->bridge_manager()->add_bridge_as_representation(bridge);
02582       }
02583       else
02584         te->bridge_manager()->add_bridge(bridge);
02585     }
02586 
02587       // Set the merge sense of the bridge, if it is saved in the
02588       // attribute.
02589     if( re_ptr && sense == CUBIT_UNKNOWN )
02590     {
02591       TopologyBridge* first = te->bridge_manager()->topology_bridge();
02592       Curve* curve;
02593       Surface* surface;
02594       if( (curve = dynamic_cast<Curve*>(bridge) ) != NULL )
02595       {
02596         Curve* first_curve = dynamic_cast<Curve*>(first);
02597         assert(first_curve != NULL);
02598         sense = first_curve->bridge_sense();
02599         if( first_curve->relative_sense(curve) == CUBIT_REVERSED )
02600           sense = CubitUtil::opposite_sense(sense);
02601       }
02602       else if( (surface = dynamic_cast<Surface*>(bridge) ) != NULL )
02603       {
02604         Surface* first_surf = dynamic_cast<Surface*>(first);
02605         assert(first_surf != NULL);
02606         sense = first_surf->bridge_sense();
02607         if( relative_sense( first_surf, surface ) == CUBIT_REVERSED )
02608           sense = CubitUtil::opposite_sense(sense);
02609       }
02610     }
02611 
02612     int id = CAMergePartner::get_saved_id( csa_ptr );
02613     if (id)
02614       bridge->set_saved_id( id );
02615   }
02616 
02617   return re_ptr;
02618 }
02619 
02620 //-------------------------------------------------------------------------
02621 // Purpose       : Find relative senes of two Surfaces
02622 //
02623 // Special Notes : Used when CAMergePartner attrib is too old to
02624 //                 contain sense information.
02625 //
02626 // Creator       : Jason Kraftcheck
02627 //
02628 // Creation Date : 08/22/02
02629 //-------------------------------------------------------------------------
02630 CubitSense GeometryQueryTool::relative_sense( Surface* surf1, Surface* surf2 )
02631 {
02632   CubitVector point1 = surf1->bounding_box().center();
02633   CubitVector point2 = surf2->bounding_box().center();
02634   CubitVector point = 0.5 * (point1 + point2);
02635 
02636   CubitVector closest1, closest2, normal1, normal2;
02637   surf1->closest_point_trimmed( point, closest1 );
02638   surf2->closest_point( closest1, &closest2, &normal2 );
02639   surf1->closest_point( closest2, &closest1, &normal1 );
02640 
02641   return normal1 % normal2 < 0 ? CUBIT_REVERSED : CUBIT_FORWARD;
02642 }
02643 
02644 RefVertex* GeometryQueryTool::make_RefVertex(TBPoint* point) const
02645 {
02646      // first, handle making the new RefVertex's; check for
02647      // existing chain afterwards
02648    RefVertex* vertex = 0;
02649 
02650      // First check to make sure we haven't already created a RefVertex
02651      // from this point
02652    TopologyEntity* topo = point->topology_entity();
02653    vertex = CAST_TO(topo, RefVertex);
02654   
02655    if ( vertex == NULL)
02656    {
02657      assert( topo == NULL );
02658      RefEntity *re_ptr = check_mergeable_refentity(point);
02659      if (re_ptr != NULL)
02660      {
02661        vertex = dynamic_cast<RefVertex*>(re_ptr);
02662      }
02663    }
02664  
02665    if (vertex == NULL)
02666    {
02667        // Create a RefVertex from this TBPoint.
02668      vertex = RefEntityFactory::instance()->construct_RefVertex(point);
02669    }
02670    assert(vertex != NULL);
02671 
02672    return vertex;
02673 }
02674 
02675 
02676 
02677 //-------------------------------------------------------------------------
02678 // Purpose       : Build a free RefFace given a SurfaceSM.
02679 //
02680 // Special Notes : Purpose is to build a free surface.  Entities are
02681 //                 added to the graphics.
02682 //
02683 // Creator       : Steve Storm
02684 //
02685 // Creation Date : 3/27/99
02686 //-------------------------------------------------------------------------
02687 RefFace* GeometryQueryTool::make_free_RefFace(Surface *surface_ptr,
02688                                               bool is_free_face ) const
02689 {
02690    RefFace* ref_face_ptr = make_RefFace( surface_ptr );
02691    if( !ref_face_ptr )
02692    {
02693      PRINT_ERROR("Failed to construct free RefFace.\n");
02694      assert(!!ref_face_ptr);
02695      return 0;
02696    }
02697 
02698    // Add the new ref_face to the graphics
02699    if( is_free_face )
02700    {
02701      AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::FREE_REF_ENTITY_GENERATED, ref_face_ptr));
02702      
02703      CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_CREATED, ref_face_ptr);
02704      const_cast<CGMHistory&>(mHistory).add_event(evt);
02705    }
02706 
02707    return ref_face_ptr;
02708 }
02709 
02710 //-------------------------------------------------------------------------
02711 // Purpose       : Build a free RefEdge given a CurveSM.
02712 //
02713 // Special Notes : Purpose is to build a free curve.  Entities are
02714 //                 added to the graphics.
02715 //
02716 // Creator       : Steve Storm
02717 //
02718 // Creation Date : 3/27/99
02719 //-------------------------------------------------------------------------
02720 RefEdge* GeometryQueryTool::make_free_RefEdge(Curve *curve_ptr ) const
02721 {
02722    RefEdge* ref_edge_ptr = make_RefEdge(curve_ptr);
02723    if( !ref_edge_ptr )
02724    {
02725      PRINT_ERROR("Failed to construct free RefEdge.\n");
02726      assert(!!ref_edge_ptr);
02727      return 0;
02728    }
02729 
02730    AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::FREE_REF_ENTITY_GENERATED, ref_edge_ptr));
02731    
02732    CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_CREATED, ref_edge_ptr);
02733    const_cast<CGMHistory&>(mHistory).add_event(evt);
02734 
02735    return ref_edge_ptr;
02736 }
02737 
02738 //-------------------------------------------------------------------------
02739 // Purpose       : Build a free RefVertex given a PointSM.
02740 //
02741 // Special Notes : Purpose is to build a free vertex.  Vertex
02742 //                 is added to the graphics.
02743 //
02744 // Creator       : Steve Storm
02745 //
02746 // Creation Date : 3/27/99
02747 //-------------------------------------------------------------------------
02748 RefVertex* GeometryQueryTool::make_free_RefVertex(TBPoint *point_ptr ) const
02749 {
02750    RefVertex* ref_vertex_ptr = make_RefVertex( point_ptr );
02751    if( !ref_vertex_ptr )
02752    {
02753      PRINT_ERROR("Failed to construct free RefVertex.\n");
02754      assert(!!ref_vertex_ptr);
02755      return 0;
02756    }
02757 
02758    // Add the new ref_vertex to the graphics
02759    AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::FREE_REF_ENTITY_GENERATED, ref_vertex_ptr));
02760    
02761    CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_CREATED, ref_vertex_ptr);
02762    const_cast<CGMHistory&>(mHistory).add_event(evt);
02763 
02764    return ref_vertex_ptr;
02765 }
02766 
02767 void GeometryQueryTool::delete_Body(DLIList<Body*>& body_list)
02768 {
02769   body_list.reset();
02770   for (int i = body_list.size(); i--; )
02771     delete_Body(body_list.get_and_step());
02772 }
02773 
02774 //-------------------------------------------------------------------------
02775 // Purpose       : Delete a Body
02776 //
02777 // Special Notes :
02778 //
02779 // Creator       : Jason Kraftcheck
02780 //
02781 // Creation Date : 09/24/03
02782 //-------------------------------------------------------------------------
02783 CubitStatus GeometryQueryTool::delete_Body( Body* body_ptr )
02784 {
02785   BodySM* bodysm = body_ptr->get_body_sm_ptr();
02786   if (!bodysm)
02787   {
02788     PRINT_ERROR("Body %d is invalid -- no attached BodySM.\n",body_ptr->id());
02789   }
02790   else
02791   {
02792       // Ask owning model engine to delete the TopologyBridges
02793     GeometryQueryEngine* gqe = bodysm->get_geometry_query_engine();
02794     gqe->delete_solid_model_entities(bodysm);
02795 
02796       // Clean up any virtual geometry that was on the body
02797     for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end(); ++itor)
02798       (*itor)->clean_out_deactivated_geometry();
02799   }
02800 
02801      // Check if body actually got deleted.
02802   return destroy_dead_entity( body_ptr );
02803 }
02804 
02805 //-------------------------------------------------------------------------
02806 // Purpose       : Delete a Body
02807 //
02808 // Special Notes : Checks if child entities are merged and regenerates
02809 //                 graphics for them.  This is necessary when 2 merged
02810 //                 entities have been "force-merged", usually meaning they
02811 //                 are not spatially equal.
02812 //
02813 // Creator       : Corey Ernst
02814 //
02815 // Creation Date : 08/25/04
02816 //-------------------------------------------------------------------------
02817 CubitStatus GeometryQueryTool::delete_single_Body( Body* body_ptr )
02818 {
02819   BodySM* bodysm = body_ptr->get_body_sm_ptr();
02820   DLIList<RefEntity*> merged_children;
02821   DLIList<RefFace*> faces_to_reverse;
02822   DLIList<RefEdge*> edges_to_reverse;
02823   if (!bodysm)
02824   {
02825     PRINT_ERROR("Body %d is invalid -- no attached BodySM.\n",body_ptr->id());
02826   }
02827   else
02828   {
02829     //get all the child entities that have been merged
02830     DLIList<RefEntity*> tmp_merged_children;
02831     MergeTool::instance()->contains_merged_children( body_ptr, tmp_merged_children );
02832 
02833     //get the owning bodies for each entity
02834     int i;
02835     for(i=tmp_merged_children.size(); i--;)
02836     {
02837       RefEntity *ref_ent = tmp_merged_children.get_and_step();
02838       TopologyEntity *tmp_entity = CAST_TO( ref_ent, TopologyEntity);
02839       DLIList<Body*> body_list;
02840       tmp_entity->bodies( body_list );
02841       //if 2 bodies own it, get body that is not "body_ptr"
02842       //for later graphics regeneration
02843       if( body_list.size() > 1 )
02844       {
02845         if( body_list.get() != body_ptr )
02846           merged_children.append( ref_ent );
02847         else if( body_list.step_and_get() != body_ptr )
02848           merged_children.append( ref_ent );
02849       }
02850     }
02851 
02852 //    if( tmp_merged_children.size() )
02853 //      MergeTool::instance()->unmerge( body_ptr );
02854 
02855     //fix up merged children -- some might need to be reversed
02856     for(i=merged_children.size(); i--; )
02857     {
02858       RefEntity *merged_child = merged_children.get_and_step();
02859       BasicTopologyEntity *bte = static_cast<BasicTopologyEntity*>(merged_child);
02860 
02861       //get the first bridge of the entity
02862       DLIList<TopologyBridge*> child_bridge_list;
02863       bte->bridge_manager()->get_bridge_list( child_bridge_list );
02864       child_bridge_list.reset();
02865       TopologyBridge *first_bridge = child_bridge_list.get_and_step();
02866 
02867       //if it is not the body we're deleting just continue
02868       BodySM *owning_body = first_bridge->bodysm();
02869       if( owning_body != bodysm )
02870         continue;
02871 
02872       RefFace *ref_face = CAST_TO( merged_child, RefFace );
02873       if( ref_face )
02874       {
02875         TopologyBridge *second_bridge = child_bridge_list.get_and_step();
02876 
02877         if( first_bridge->bridge_sense() != second_bridge->bridge_sense() )
02878           faces_to_reverse.append( ref_face );
02879         continue;
02880       }
02881       RefEdge *ref_edge = CAST_TO( merged_child, RefEdge );
02882       if( ref_edge )
02883       {
02884         //get merged_child's first topology bridge
02885         TopologyBridge *second_bridge = child_bridge_list.get_and_step();
02886 
02887         Curve *first_curve = CAST_TO( first_bridge, Curve );
02888         Curve *second_curve = CAST_TO( second_bridge, Curve );
02889 
02890         CubitSense relative_sense = first_curve->relative_sense( second_curve );
02891 
02892         if( relative_sense == CUBIT_REVERSED )
02893           edges_to_reverse.append( ref_edge );
02894         continue;
02895       }
02896     }
02897 
02898       // Ask owning model engine to delete the TopologyBridges
02899     GeometryQueryEngine* gqe = bodysm->get_geometry_query_engine();
02900     gqe->delete_solid_model_entities(bodysm);
02901 
02902 
02903       // Clean up any virtual geometry that was on the body
02904     for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end(); ++itor)
02905       (*itor)->clean_out_deactivated_geometry();
02906   }
02907 
02908   int i;
02909   for( i=faces_to_reverse.size(); i--; )
02910     faces_to_reverse.get_and_step()->reverse_normal();
02911   for( i=edges_to_reverse.size(); i--; )
02912     edges_to_reverse.get_and_step()->reverse_tangent();
02913 
02914     //regenerate graphics of merged entities
02915   for( i=merged_children.size(); i--; )
02916   {
02917     RefEntity* child = merged_children.get_and_step();
02918     AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_TOPOLOGY_MODIFIED, child));
02919     CGMHistory::Event evt2(CGMHistory::TOPOLOGY_CHANGED, child);
02920     const_cast<CGMHistory&>(mHistory).add_event(evt2);
02921     CGMHistory::Event evt(CGMHistory::GEOMETRY_CHANGED, child);
02922     const_cast<CGMHistory&>(mHistory).add_event(evt);
02923   }
02924 
02925   // Check if body actually got deleted.
02926   CubitStatus ret = destroy_dead_entity( body_ptr );
02927 
02928   // Send an unmerge event out for surfaces that were a part
02929   // of the body that was deleted.  Do this after the above
02930   // call to destroy_dead_entity() so that the Body
02931   // pointer associated with the deleted volume will no
02932   // longer be referenced by the merged surface.  This code
02933   // was added so that sidesets which are watching surface
02934   // modifications will know to update their data when 
02935   // the body is deleted. 
02936   for( i=merged_children.size(); i--; )
02937   {
02938     RefFace* child = CAST_TO(merged_children.get_and_step(), RefFace);
02939     if(child)
02940     {
02941       UnMergeEvent unmerge_event( child, child );
02942       AppUtil::instance()->send_event(unmerge_event );
02943     }
02944   }
02945 
02946   return ret;
02947 }
02948 
02949 //-------------------------------------------------------------------------
02950 // Purpose       : Delete a RefEntity
02951 //
02952 // Special Notes :
02953 //
02954 // Creator       : Jason Kraftcheck
02955 //
02956 // Creation Date : 09/24/03
02957 //-------------------------------------------------------------------------
02958 CubitStatus GeometryQueryTool::delete_RefEntity( RefEntity* ref_entity_ptr )
02959 {
02960   if (Body* body = dynamic_cast<Body*>(ref_entity_ptr))
02961     return delete_Body(body);
02962 
02963   if(RefFace* face = dynamic_cast<RefFace*>(ref_entity_ptr))
02964     return delete_RefFace(face);
02965 
02966   if(RefEdge* edge = dynamic_cast<RefEdge*>(ref_entity_ptr))
02967     return delete_RefEdge(edge);
02968 
02969   if(RefVertex* vtx = dynamic_cast<RefVertex*>(ref_entity_ptr))
02970     return delete_RefVertex(vtx);
02971   PRINT_ERROR("Cannot delete entity of type '%s'\n", ref_entity_ptr->class_name());
02972   return CUBIT_FAILURE;
02973 }
02974 
02975 //-------------------------------------------------------------------------
02976 // Purpose       : Delete a RefFace
02977 //
02978 // Special Notes :
02979 //
02980 // Creator       : Jason Kraftcheck
02981 //
02982 // Creation Date : 09/24/03
02983 //-------------------------------------------------------------------------
02984 CubitStatus GeometryQueryTool::delete_RefFace( RefFace* ref_face )
02985 {
02986     // Get the list of Surfaces owned by the RefFace
02987   BridgeManager* manager = ref_face->bridge_manager();
02988   DLIList<TopologyBridge*> bridge_list(manager->number_of_bridges());
02989   manager->get_bridge_list(bridge_list);
02990 
02991     // Ask each Surface's owning engine to destroy the surface.
02992   while( bridge_list.size() )
02993   {
02994     TopologyBridge* bridge = bridge_list.pop();
02995     Surface* surface = dynamic_cast<Surface*>(bridge);
02996     if (!surface)
02997     {
02998       PRINT_ERROR("RefFace %d is invalid -- attached TopologyBridge "
02999                   "is not a Surface.\n", ref_face->id());
03000       continue;
03001     }
03002 
03003     surface->get_geometry_query_engine()->
03004       delete_solid_model_entities( surface );
03005   }
03006 
03007     // Clean up any virtual geometry that was on the surface
03008   for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end(); ++itor)
03009     (*itor)->clean_out_deactivated_geometry();
03010 
03011     // Check if all the Surfaces got deleted.
03012   return destroy_dead_entity( ref_face );
03013 }
03014 
03015 //-------------------------------------------------------------------------
03016 // Purpose       : Delete a RefEdge
03017 //
03018 // Special Notes :
03019 //
03020 // Creator       : Jason Kraftcheck
03021 //
03022 // Creation Date : 09/24/03
03023 //-------------------------------------------------------------------------
03024 CubitStatus GeometryQueryTool::delete_RefEdge( RefEdge* ref_edge )
03025 {
03026     // Get the list of Curves owned by the RefEdge
03027   BridgeManager* manager = ref_edge->bridge_manager();
03028   DLIList<TopologyBridge*> bridge_list(manager->number_of_bridges());
03029   manager->get_bridge_list(bridge_list);
03030 
03031     // Ask each Curve's owning engine to destroy the surface.
03032   while( bridge_list.size() )
03033   {
03034     TopologyBridge* bridge = bridge_list.pop();
03035     Curve* curve = dynamic_cast<Curve*>(bridge);
03036     if (!curve)
03037     {
03038       PRINT_ERROR("RefEdge %d is invalid -- attached TopologyBridge "
03039                   "is not a Curve.\n", ref_edge->id());
03040       continue;
03041     }
03042 
03043     curve->get_geometry_query_engine()->
03044       delete_solid_model_entities( curve );
03045   }
03046 
03047     // Clean up any virtual geometry that was on the curve
03048   for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end(); ++itor)
03049     (*itor)->clean_out_deactivated_geometry();
03050 
03051     // Check if all the curves got deleted.
03052   return destroy_dead_entity( ref_edge );
03053 }
03054 
03055 //-------------------------------------------------------------------------
03056 // Purpose       : Delete a RefVertex
03057 //
03058 // Special Notes :
03059 //
03060 // Creator       : Jason Kraftcheck
03061 //
03062 // Creation Date : 09/24/03
03063 //-------------------------------------------------------------------------
03064 CubitStatus GeometryQueryTool::delete_RefVertex( RefVertex* ref_vertex )
03065 {
03066     // Get the list of Points owned by the RefVertex
03067   BridgeManager* manager = ref_vertex->bridge_manager();
03068   DLIList<TopologyBridge*> bridge_list(manager->number_of_bridges());
03069   manager->get_bridge_list(bridge_list);
03070 
03071     // Ask each Curve's owning engine to destroy the surface.
03072   while( bridge_list.size() )
03073   {
03074     TopologyBridge* bridge = bridge_list.pop();
03075     TBPoint* point = dynamic_cast<TBPoint*>(bridge);
03076     if (!point)
03077     {
03078       PRINT_ERROR("RefVertex %d is invalid -- attached TopologyBridge "
03079                   "is not a Point.\n", ref_vertex->id());
03080       continue;
03081     }
03082 
03083     point->get_geometry_query_engine()->
03084       delete_solid_model_entities( point );
03085   }
03086 
03087     // Clean up any virtual geometry that was on the Point
03088   for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end(); ++itor)
03089     (*itor)->clean_out_deactivated_geometry();
03090 
03091     // Check if all the Points got deleted.
03092   return destroy_dead_entity( ref_vertex );
03093 }
03094 
03095 //Initialize all settings in this class
03096 void GeometryQueryTool::initialize_settings()
03097 {
03098 
03099   SettingHandler::instance()->add_setting("Merge Tolerance",
03100                                           GeometryQueryTool::set_geometry_factor,
03101                       GeometryQueryTool::get_geometry_factor);
03102 
03103   SettingHandler::instance()->add_setting("Merge Test BBox",
03104                                           GeometryQueryTool::set_merge_test_bbox,
03105                       GeometryQueryTool::get_merge_test_bbox);
03106 
03107   SettingHandler::instance()->add_setting("Merge Test InternalSurf",
03108                      GeometryQueryTool::set_merge_test_internal,
03109                      GeometryQueryTool::get_merge_test_internal);
03110 
03111   SettingHandler::instance()->add_setting("Facet BBox",
03112                      GeometryQueryTool::set_facet_bbox,
03113                      GeometryQueryTool::get_facet_bbox);
03114 }
03115 
03116 //-------------------------------------------------------------------------
03117 // Purpose       : Constructor of the GeometryQueryTool class.
03118 //
03119 // Special Notes :
03120 //
03121 // Creator       : Xuechen Liu
03122 //
03123 // Creation Date : 07/11/96
03124 //-------------------------------------------------------------------------
03125 GeometryQueryTool::GeometryQueryTool(GeometryQueryEngine*gqe_ptr)
03126 {
03127   if (gqe_ptr != NULL) add_gqe(gqe_ptr);
03128 }
03129 
03130 // ********** END PROTECTED FUNCTIONS      **********
03131 
03132 // ********** BEGIN PRIVATE FUNCTIONS      **********
03133 
03134 
03135 void GeometryQueryTool::geom_debug( DLIList<TopologyEntity*> topo_list )
03136 {
03137      //This function was created March 1998 to assist in debugging
03138      //the unmerge command.  When sufficient time has passed and
03139      //it is no longer needed, this function can be deleted.
03140      //SR Jankovich
03141    for( int i = topo_list.size(); i > 0; i-- )
03142    {
03143       TopologyEntity *topo_entity = topo_list.get_and_step();
03144       if( !topo_entity )
03145           return;
03146       RefEntity *ref_entity = CAST_TO( topo_entity, RefEntity );
03147       if( !ref_entity )
03148           return;
03149 
03150       PRINT_INFO( "%s\n", ref_entity->entity_name().c_str() );
03151       DLIList<TopologyEntity*> next_topo_list;
03152       next_topo_list.clean_out();
03153 
03154       if( CAST_TO( ref_entity, Body ) )
03155       {
03156 
03157         DLIList<CoVolume*> co_vol_list;
03158         if( !topo_entity->co_volumes( co_vol_list ) )
03159            return;
03160         for( int j = co_vol_list.size(); j > 0; j-- )
03161         {
03162           CoVolume *co_vol = co_vol_list.get_and_step();
03163           PRINT_INFO( "   CoVolume %d (not id)\n",
03164                       co_vol_list.size() - j );
03165           TopologyEntity *temp_topo = CAST_TO( co_vol, TopologyEntity );
03166           if( !temp_topo )
03167              return;
03168           DLIList<RefVolume*> vol_list;
03169           if( !temp_topo->ref_volumes( vol_list ) )
03170              return;
03171           for( int k = vol_list.size(); k > 0; k-- )
03172           {
03173             RefVolume *vol = vol_list.get_and_step();
03174             PRINT_INFO( "      %s\n", vol->entity_name().c_str() );
03175             TopologyEntity *next_topo = CAST_TO( vol, TopologyEntity );
03176             next_topo_list.append( next_topo );
03177           }
03178         }
03179         GeometryQueryTool::geom_debug( next_topo_list );
03180       }
03181       else if( CAST_TO( ref_entity, RefVolume ) )
03182       {
03183         DLIList<Shell*> shell_list;
03184         if( !topo_entity->shells( shell_list ) )
03185            return;
03186         for( int m = shell_list.size(); m > 0; m-- )
03187         {
03188           Shell *shell = shell_list.get_and_step();
03189           PRINT_INFO( "   Shell %d (not id)\n", shell_list.size() - m );
03190           TopologyEntity *group_topo = CAST_TO( shell, TopologyEntity );
03191           if( !group_topo )
03192              return;
03193           DLIList<CoFace*> co_face_list;
03194           if( !group_topo->co_faces( co_face_list ) )
03195              return;
03196           for( int j = co_face_list.size(); j > 0; j-- )
03197           {
03198             CoFace *co_face = co_face_list.get_and_step();
03199             PRINT_INFO( "      CoFace %d (not id)\n",
03200                         co_face_list.size() - j );
03201             TopologyEntity *temp_topo = CAST_TO( co_face, TopologyEntity );
03202             if( !temp_topo )
03203                return;
03204             DLIList<RefFace*> face_list;
03205             if( !temp_topo->ref_faces( face_list ) )
03206                return;
03207             for( int k = face_list.size(); k > 0; k-- )
03208             {
03209               RefFace *face = face_list.get_and_step();
03210               PRINT_INFO( "         %s\n", face->entity_name().c_str() );
03211               TopologyEntity *next_topo = CAST_TO( face, TopologyEntity );
03212               next_topo_list.append( next_topo );
03213             }
03214           }
03215         }
03216         GeometryQueryTool::geom_debug( next_topo_list );
03217       }
03218       else if( CAST_TO( ref_entity, RefFace ) )
03219       {
03220         DLIList<Loop*> loop_list;
03221         if( !topo_entity->loops( loop_list ) )
03222            return;
03223         for( int m = loop_list.size(); m > 0; m-- )
03224         {
03225           Loop *loop = loop_list.get_and_step();
03226           PRINT_INFO( "   Loop %d (not id)\n", loop_list.size() - m );
03227           TopologyEntity *group_topo = CAST_TO( loop, TopologyEntity );
03228           if( !group_topo )
03229              return;
03230           DLIList<CoEdge*> co_edge_list;
03231           if( !group_topo->co_edges( co_edge_list ) )
03232              return;
03233           for( int j = co_edge_list.size(); j > 0; j-- )
03234           {
03235             CoEdge *co_edge = co_edge_list.get_and_step();
03236             PRINT_INFO( "      CoEdge %d (not id)\n",
03237                         co_edge_list.size() - j );
03238             TopologyEntity *temp_topo = CAST_TO( co_edge, TopologyEntity );
03239             if( !temp_topo )
03240                return;
03241             DLIList<RefEdge*> edge_list;
03242             if( !temp_topo->ref_edges( edge_list ) )
03243                return;
03244             for( int k = edge_list.size(); k > 0; k-- )
03245             {
03246               RefEdge *edge = edge_list.get_and_step();
03247               PRINT_INFO( "         %s\n", edge->entity_name().c_str() );
03248               TopologyEntity *next_topo = CAST_TO( edge, TopologyEntity );
03249               next_topo_list.append( next_topo );
03250             }
03251           }
03252         }
03253         GeometryQueryTool::geom_debug( next_topo_list );
03254       }
03255       else if( CAST_TO( ref_entity, RefEdge ) )
03256       {
03257         DLIList<Chain*> chain_list;
03258         if( !topo_entity->chains( chain_list ) )
03259            return;
03260         for( int m = chain_list.size(); m > 0; m-- )
03261         {
03262           Chain *chain = chain_list.get_and_step();
03263           PRINT_INFO( "   Chain %d (not id)\n", chain_list.size() - m );
03264           TopologyEntity *group_topo = CAST_TO( chain, TopologyEntity );
03265           if( !group_topo )
03266              return;
03267           DLIList<CoVertex*> co_vertex_list;
03268           if( !group_topo->co_vertices( co_vertex_list ) )
03269              return;
03270           for( int j = co_vertex_list.size(); j > 0; j-- )
03271           {
03272             CoVertex *co_vertex = co_vertex_list.get_and_step();
03273             PRINT_INFO( "      CoVertex %d (not id)\n",
03274                         co_vertex_list.size() - j );
03275             TopologyEntity *temp_topo = CAST_TO( co_vertex, TopologyEntity );
03276             if( !temp_topo )
03277                return;
03278             DLIList<RefVertex*> vertex_list;
03279             if( !temp_topo->ref_vertices( vertex_list ) )
03280                return;
03281             for( int k = vertex_list.size(); k > 0; k-- )
03282             {
03283               RefVertex *vertex = vertex_list.get_and_step();
03284               PRINT_INFO( "         %s\n",
03285                           vertex->entity_name().c_str() );
03286               TopologyEntity *next_topo = CAST_TO( vertex, TopologyEntity );
03287               next_topo_list.append( next_topo );
03288             }
03289           }
03290         }
03291         GeometryQueryTool::geom_debug( next_topo_list );
03292       }
03293       else if( CAST_TO( ref_entity, RefVertex ) )
03294          ;//Do nothing
03295       else
03296          PRINT_INFO( "UNKNOWN ENTITY TYPE!!!\n" );
03297    }
03298 }
03299 
03300 CubitBoolean GeometryQueryTool::about_spatially_equal (RefVertex* refVertex1,
03301                                                   RefVertex* refVertex2,
03302                                                   double tolerance_factor)
03303 {
03304    return ( refVertex1->about_spatially_equal( refVertex2, tolerance_factor));
03305 }
03306 
03307 CubitBoolean GeometryQueryTool::about_spatially_equal (const CubitVector &vector1,
03308                                                   const CubitVector &vector2,
03309                                                   double tolerance_factor)
03310 {
03311   double tol = GEOMETRY_RESABS * tolerance_factor;
03312   tol *= tol;
03313   double dist_sq = vector1.distance_between_squared(vector2);
03314   return !(dist_sq > tol);
03315   // within_tolerance() just checks coordinate aligned distances, not the actual distance.
03316 //   return (vector1.within_tolerance( vector2, GEOMETRY_RESABS * tolerance_factor ));
03317 }
03318 
03319 double GeometryQueryTool::geometric_angle(RefEdge* ref_edge_1,
03320                                      RefEdge* ref_edge_2,
03321                                      RefFace* ref_face )
03322 {
03323      // calculates internal surface angles given 2 refedges on the surface
03324    CoEdge *co_edge_1, *co_edge_2;
03325      //First get the two coedges that corrispond to the edges sent into
03326      //this function.  The two coedges are found from the ref_face's loop
03327      //where co_edge_1 is followed by co_edge_2 in the loop and co_edge_1 is
03328      //associated with ref_edge_1 while co_edge_2 is associated with
03329      //ref_edge_2.
03330    ref_edge_1->get_two_co_edges( ref_edge_2, ref_face, co_edge_1,
03331                                  co_edge_2 );
03332 
03333    return geometric_angle( co_edge_1, co_edge_2 );
03334 }
03335 
03336 double GeometryQueryTool::geometric_angle(CoEdge* co_edge_1,
03337                                      CoEdge* co_edge_2 )
03338 {
03339 
03340   RefEdge *ref_edge_1 = co_edge_1->get_ref_edge_ptr();
03341   RefEdge *ref_edge_2 = co_edge_2->get_ref_edge_ptr();
03342 
03343     // return 2 pi for the tip of a hard line.
03344   if ( co_edge_1 != co_edge_2 && ref_edge_1 == ref_edge_2 )
03345     return 2.0 * CUBIT_PI;
03346 
03347   RefVertex *ref_vertex =
03348     co_edge_1->get_sense() == CUBIT_FORWARD ?
03349     ref_edge_1->end_vertex() :
03350     ref_edge_1->start_vertex();
03351 
03352   //RefVertex *junk_vertex1 = ref_edge_2->start_vertex();
03353   //RefVertex *junk_vertex2 = ref_edge_2->end_vertex();
03354   //CubitSense junk_sense = co_edge_2->get_sense();
03355 
03356   assert( ref_vertex ==
03357           ( co_edge_2->get_sense() == CUBIT_FORWARD ?
03358             ref_edge_2->start_vertex() :
03359             ref_edge_2->end_vertex() ) );
03360 
03361      // coordinates of common point
03362   CubitVector vertex_point = ref_vertex->coordinates();
03363 
03364     // Find normal to the the face at the common vertex of
03365     // the refedges. Use loop sense to artificially switch inner loops.
03366     // Use intrinsic normal.
03367   RefFace *ref_face = co_edge_1->get_ref_face();
03368   CubitVector normal = ref_face->normal_at(vertex_point, NULL);
03369 
03370     // Find directed tangents to determine interior angle
03371     // Use sense of edge with respect to this face's loop.
03372   CubitVector tangent_1, tangent_2;
03373   ref_edge_1->tangent( vertex_point, tangent_1 );
03374   ref_edge_2->tangent( vertex_point, tangent_2 );
03375 
03376   if ( co_edge_1->get_sense() == CUBIT_REVERSED )
03377     tangent_1 = -tangent_1;
03378   if ( co_edge_2->get_sense() == CUBIT_REVERSED )
03379     tangent_2 = -tangent_2;
03380 
03381     //  At this point we have the tangents going in the correct loop
03382     //  sense.
03383     //  Now get tangent pointing away from the center for the correct
03384     //  angle
03385   tangent_1 = -tangent_1;
03386     // Return angle from given tangents and normal to face
03387   double angle = normal.vector_angle( tangent_2, tangent_1 );
03388   if ( angle*180.0/CUBIT_PI >  360.0 - GEOMETRY_RESABS )
03389   {
03390       //try other points to make sure this is going the right way.
03391     CubitVector new_loc_1, new_loc_2;
03392     if ( ref_edge_1->start_vertex() == ref_vertex )
03393       ref_edge_1->position_from_fraction(0.01,
03394                                     new_loc_1);
03395     else
03396       ref_edge_1->position_from_fraction(0.99,
03397                                     new_loc_1);
03398     if ( ref_edge_2->start_vertex() == ref_vertex )
03399       ref_edge_2->position_from_fraction(0.01,
03400                                     new_loc_2);
03401     else
03402       ref_edge_2->position_from_fraction(0.99,
03403                                     new_loc_2);
03404       //Now just do the exact same thing as above but
03405       //use these new points...
03406     ref_edge_1->tangent( new_loc_1, tangent_1 );
03407     ref_edge_2->tangent( new_loc_2, tangent_2 );
03408 
03409     if ( co_edge_1->get_sense() == CUBIT_REVERSED )
03410       tangent_1 = -tangent_1;
03411     if ( co_edge_2->get_sense() == CUBIT_REVERSED )
03412       tangent_2 = -tangent_2;
03413     tangent_1 = -tangent_1;
03414       // Return angle from given tangents and normal to face
03415     angle = normal.vector_angle( tangent_2, tangent_1 );
03416     if ( angle < CUBIT_PI )
03417       angle = 0.0;
03418     else
03419       angle = 2.0*CUBIT_PI;
03420   }
03421   return angle;
03422 }
03423 
03424 CubitString GeometryQueryTool::get_engine_version_string()
03425 {
03426   if (gqeList.size())
03427   {
03428     gqeList.reset();
03429     return gqeList.get()->get_engine_version_string();
03430   }
03431   else
03432   {
03433     return CubitString("No Active GeometryEngine");
03434   }
03435 }
03436 
03437 CubitBoolean
03438 GeometryQueryTool::does_geom_contain_query_engine(DLIList<TopologyEntity*> &topo_list,
03439                                                   GeometryQueryEngine *engine) const
03440 {
03441   GeometryQueryEngine *ge_ptr;
03442   for( int i=topo_list.size(); i--; )
03443   {
03444     ge_ptr = topo_list.get_and_step()->get_geometry_query_engine();
03445     if( ge_ptr == engine )
03446     {
03447       return CUBIT_TRUE;
03448     }
03449   }
03450 
03451   return CUBIT_FALSE;
03452 }
03453 
03454 CubitBoolean
03455 GeometryQueryTool::does_geom_contain_query_engine(DLIList<RefEntity*> &ref_entity_list,
03456                                                   GeometryQueryEngine *engine,
03457                                                   CubitBoolean children_too) const
03458 {
03459   DLIList<RefEntity*> complete_entity_list;
03460 
03461   // Check the check_children option and check all the children if necessary
03462   if (children_too)
03463   {
03464     //Make a complete list of all the RefEntitys and their children
03465     DLIList<RefEntity*> temp = ref_entity_list;
03466     RefEntity* ref_entity_ptr;
03467     int i;
03468     for( i=ref_entity_list.size(); i--; )
03469     {
03470       ref_entity_ptr = ref_entity_list.get_and_step();
03471       complete_entity_list.clean_out();
03472       ref_entity_ptr->get_all_child_ref_entities(complete_entity_list);
03473       temp += complete_entity_list;
03474     }
03475     complete_entity_list.clean_out();
03476     complete_entity_list.merge_unique(temp);
03477   }
03478 
03479   // Now check the RefEntities for the given geometry engine
03480   DLIList<TopologyEntity*> te_list;
03481   CAST_LIST(complete_entity_list, te_list, TopologyEntity);
03482   return does_geom_contain_query_engine(te_list, engine);
03483 }
03484 
03485 TopologyEntity* GeometryQueryTool::entity_from_bridge( TopologyBridge* bridge_ptr ) const
03486 {
03487   if( !bridge_ptr )
03488     return NULL;
03489   TBOwner* owner = bridge_ptr->owner();
03490   BridgeManager* bridge_manager;
03491   while (!(bridge_manager = dynamic_cast<BridgeManager*>(owner)))
03492   {
03493     if (TopologyBridge* bridge = dynamic_cast<TopologyBridge*>(owner))
03494       owner = bridge->owner();
03495     else if(TBOwnerSet* set = dynamic_cast<TBOwnerSet*>(owner))
03496     {
03497       DLIList<TopologyBridge*> list;
03498       set->get_owners(list);
03499       list.reset();
03500       owner = list.get()->owner();
03501     }
03502     else
03503       break;
03504   }
03505 
03506   return bridge_manager ? bridge_manager->topology_entity() : 0;
03507 }
03508 
03509 
03510 CubitStatus GeometryQueryTool::set_default_gqe(GeometryQueryEngine* gqe)
03511 {
03512   int i;
03513   for (i = 0; i < gqeList.size(); i++)
03514   {
03515     if(gqe == gqeList.get())
03516       break;
03517 
03518     gqeList.step();
03519   }
03520 
03521   if(i == gqeList.size()) return CUBIT_FAILURE;
03522 
03523   GeometryQueryEngine* temp_ptr = gqeList.get();
03524   gqeList.remove();
03525   gqeList.insert_first(temp_ptr);
03526   PRINT_INFO("Geometry engine set to: %s\n", gqe->get_engine_version_string().c_str() );
03527   return CUBIT_SUCCESS;
03528 }
03529 
03530 CubitStatus GeometryQueryTool::set_export_allint_version(int version)
03531 {
03532   if (gqeList.size())
03533   {
03534     gqeList.reset();
03535     return gqeList.get()->set_export_allint_version(version);
03536   }
03537   else
03538   {
03539     PRINT_WARNING("No active geometry engine.");
03540     return CUBIT_FAILURE;
03541   }
03542 }
03543 
03544 int GeometryQueryTool::get_allint_version()
03545 {
03546   if (gqeList.size())
03547   {
03548     gqeList.reset();
03549     return gqeList.get()->get_allint_version();
03550   }
03551   else
03552   {
03553     PRINT_WARNING("No active geometry engine.");
03554     return 0;
03555   }
03556 }
03557 
03558 CubitStatus GeometryQueryTool::list_engine_versions(CubitString &versions)
03559 {
03560   if (gqeList.size())
03561   {
03562     gqeList.reset();
03563     return gqeList.get()->list_engine_versions(versions);
03564   }
03565   else
03566   {
03567     PRINT_WARNING("No active geometry engine.");
03568     return CUBIT_FAILURE;
03569   }
03570 }
03571 
03572 double GeometryQueryTool::get_sme_resabs_tolerance()
03573 {
03574   if (gqeList.size())
03575   {
03576     gqeList.reset();
03577     return gqeList.get()->get_sme_resabs_tolerance();
03578   }
03579   else
03580   {
03581     PRINT_WARNING("No active geometry engine.");
03582     return 0.0;
03583   }
03584 }
03585 
03586 double GeometryQueryTool::set_sme_resabs_tolerance( double new_resabs )
03587 {
03588   if (gqeList.size())
03589   {
03590     gqeList.reset();
03591     return gqeList.get()->set_sme_resabs_tolerance( new_resabs );
03592   }
03593   else
03594   {
03595     PRINT_WARNING("No active geometry engine.");
03596     return 0.0;
03597   }
03598 }
03599 
03600 CubitStatus GeometryQueryTool::set_sme_int_option( const char* opt_name, int val )
03601 {
03602   if (gqeList.size())
03603   {
03604     gqeList.reset();
03605     return gqeList.get()->set_int_option( opt_name, val );
03606   }
03607   else
03608   {
03609     PRINT_WARNING("No active geometry engine.");
03610     return CUBIT_FAILURE;
03611   }
03612 }
03613 
03614 CubitStatus GeometryQueryTool::set_sme_dbl_option( const char* opt_name, double val )
03615 {
03616   if (gqeList.size())
03617   {
03618     gqeList.reset();
03619     return gqeList.get()->set_dbl_option( opt_name, val );
03620   }
03621   else
03622   {
03623     PRINT_WARNING("No active geometry engine.");
03624     return CUBIT_FAILURE;
03625   }
03626 }
03627 
03628 CubitStatus GeometryQueryTool::set_sme_str_option( const char* opt_name, const char* val )
03629 {
03630   if (gqeList.size())
03631   {
03632     gqeList.reset();
03633     return gqeList.get()->set_str_option( opt_name, val );
03634   }
03635   else
03636   {
03637     PRINT_WARNING("No active geometry engine.");
03638     return CUBIT_FAILURE;
03639   }
03640 }
03641 
03642 CubitStatus GeometryQueryTool::get_intersections( RefEdge* ref_edge1,
03643                                                   CubitVector& point1,
03644                                                   CubitVector& point2,
03645                                                   DLIList<CubitVector>& intersection_list,
03646                                                   CubitBoolean bounded,
03647                                                   CubitBoolean closest)
03648 {
03649   Curve* curve_ptr1 = ref_edge1->get_curve_ptr();
03650   if( curve_ptr1 == NULL )
03651   {
03652     if( curve_ptr1 == NULL )
03653       PRINT_ERROR("Unable to retrieve underlying geometric entity of Curve %d\n"      "       This is a bug - please report it\n", ref_edge1->id() );
03654     return CUBIT_FAILURE;
03655   }
03656 
03657   if ( curve_ptr1->geometry_type() == STRAIGHT_CURVE_TYPE )
03658   {
03659     CubitVector dir = point2 - point1;
03660     return straightline_intersections(ref_edge1, point1, dir,
03661                              intersection_list, bounded, closest);
03662   }
03663 
03664   GeometryQueryEngine* GQE_ptr =
03665       curve_ptr1->get_geometry_query_engine();
03666   return GQE_ptr->get_intersections( curve_ptr1, point1, point2,
03667                                      intersection_list, bounded, closest);
03668 }
03669 
03670 CubitStatus GeometryQueryTool::straightline_intersections(RefEdge* ref_edge1,
03671                                  CubitVector & origin2,
03672                                  CubitVector & dir,
03673                                  DLIList<CubitVector> &intersection_list,
03674                                  CubitBoolean bounded ,
03675                                  CubitBoolean closest)
03676 {
03677   Curve* curve_ptr1 = ref_edge1->get_curve_ptr();
03678 
03679   if( curve_ptr1 == NULL )
03680   {
03681     if( curve_ptr1 == NULL )
03682       PRINT_ERROR("Unable to retrieve underlying geometric entity of Curve %d\n"      "       This is a bug - please report it\n", ref_edge1->id() );
03683     return CUBIT_FAILURE;
03684   }
03685 
03686   CubitVector dir2 = dir;
03687   dir2.normalize();
03688   assert( curve_ptr1->geometry_type() == STRAIGHT_CURVE_TYPE );
03689   // Proceed with the intersection calculation
03690   CubitVector origin1, dir1;
03691   double origin_pnt1[3], dir_vec1[3], origin_pnt2[3], dir_vec2[3];
03692 
03693   if( ref_edge1->get_point_direction( origin1, dir1 ) == CUBIT_FAILURE )
03694   {
03695     PRINT_ERROR( "Unable to get straight line information for Curve %d; aborting\n",
03696       ref_edge1->id() );
03697     return CUBIT_FAILURE;
03698   }
03699 
03700   origin1.get_xyz( origin_pnt1 ); origin2.get_xyz( origin_pnt2 );
03701   dir1.get_xyz( dir_vec1 ); dir2.get_xyz( dir_vec2 );
03702 
03703   AnalyticGeometryTool* agt = AnalyticGeometryTool::instance();
03704 
03705   int num_int;
03706   double int_pnt1[3], int_pnt2[3];
03707   num_int = agt->int_ln_ln( origin_pnt1, dir_vec1, origin_pnt2, dir_vec2,
03708     int_pnt1, int_pnt2 );
03709   if( num_int == 0 || (closest == CUBIT_FALSE && num_int == 2) )
03710   {
03711     if( num_int == 0 )
03712       PRINT_ERROR( "Curves %d and the straight line defined by position %g, %g, %g, and direction %g, %g, %g are parallel - no intersection exists\n",
03713  ref_edge1->id(),  origin2.x(), origin2.y(), origin2.z(), dir2.x(), dir2.y(), dir2.z());
03714 
03715     else
03716       PRINT_ERROR( "Curves %d and the straight line defined by position %g, %g, %g, and direction %g, %g, %g do not intersect\n", ref_edge1->id(),
03717       origin2.x(), origin2.y(), origin2.z(), dir2.x(), dir2.y(), dir2.z());
03718     return CUBIT_FAILURE;
03719   }
03720 
03721   if( bounded == CUBIT_TRUE )
03722   {
03723     CubitVector start1 = ref_edge1->start_vertex()->coordinates();
03724     CubitVector end1 = ref_edge1->end_vertex()->coordinates();
03725     CubitVector start2 = origin2;
03726     CubitVector end2 = origin2 + dir;
03727 
03728     double start_pnt1[3], end_pnt1[3], start_pnt2[3], end_pnt2[3];
03729     start1.get_xyz( start_pnt1 ); start2.get_xyz( start_pnt2 );
03730     end1.get_xyz( end_pnt1 ); end2.get_xyz( end_pnt2 );
03731 
03732     if( num_int == 1 )
03733     {
03734       // Vertex must be on both curves
03735       if( agt->is_pnt_on_ln_seg( int_pnt1, start_pnt1, end_pnt1 ) &&
03736         agt->is_pnt_on_ln_seg( int_pnt2, start_pnt2, end_pnt2 ) )
03737       {
03738         intersection_list.append( CubitVector(int_pnt1) );
03739       }
03740       else
03741       {
03742         PRINT_WARNING( "intersection point of Curves was not within bounds of both curves\n");
03743       }
03744     }
03745     else
03746     {
03747       // Only keep the vertices that are on the curve bounds
03748       if( agt->is_pnt_on_ln_seg( int_pnt1, start_pnt1, end_pnt1 ) )
03749       {
03750         intersection_list.append( CubitVector(int_pnt1) );
03751       }
03752       else
03753       {
03754         PRINT_WARNING( "intersection point on Curve %d was not within it's bounds\n",
03755           ref_edge1->id() );
03756       }
03757       if( agt->is_pnt_on_ln_seg( int_pnt2, start_pnt2, end_pnt2 ) )
03758       {
03759         intersection_list.append( CubitVector(int_pnt2) );
03760       }
03761       else
03762       {
03763         PRINT_WARNING( "intersection point on the straight line defined by position %g, %g, %g, and direction %g, %g, %g  was not within it's bounds\n",
03764         origin2.x(), origin2.y(), origin2.z(), dir2.x(), dir2.y(), dir2.z() );
03765       }
03766     }
03767     if( intersection_list.size() == 0 )
03768       return CUBIT_FAILURE;
03769 
03770     return CUBIT_SUCCESS;
03771   }
03772   else // Not bounded
03773   {
03774     intersection_list.append( CubitVector(int_pnt1) );
03775     if( num_int == 2 )
03776     {
03777       intersection_list.append( CubitVector(int_pnt2) );
03778     }
03779     return CUBIT_SUCCESS;
03780   }
03781 }
03782 
03783 CubitStatus GeometryQueryTool::get_intersections( RefEdge* ref_edge1,
03784                                                   RefEdge* ref_edge2,
03785                                                   DLIList<CubitVector>& intersection_list,
03786                                                   CubitBoolean bounded,
03787                                                   CubitBoolean closest)
03788 {
03789   // If both curves are straight, compute their intersection; otherwise
03790   // use the geometry engine to do it.
03791   CubitStatus status = CUBIT_FAILURE;
03792   Curve* curve_ptr1 = ref_edge1->get_curve_ptr();
03793   Curve* curve_ptr2 = ref_edge2->get_curve_ptr();
03794 
03795   if( curve_ptr1 == NULL || curve_ptr2 == NULL )
03796   {
03797     if( curve_ptr1 == NULL )
03798       PRINT_ERROR("Unable to retrieve underlying geometric entity of Curve %d\n"
03799       "       This is a bug - please report it\n", ref_edge1->id() );
03800     if( curve_ptr2 == NULL )
03801       PRINT_ERROR("Unable to retrieve underlying geometry entity of Curve %d\n"
03802       "       This is a bug - please report it\n", ref_edge2->id() );
03803     return CUBIT_FAILURE;
03804   }
03805 
03806   if( curve_ptr1->geometry_type() == STRAIGHT_CURVE_TYPE &&
03807     curve_ptr2->geometry_type() == STRAIGHT_CURVE_TYPE )
03808   {
03809     // Proceed with the intersection calculation
03810     CubitVector origin2, dir2;
03811 
03812     if( ref_edge2->get_point_direction( origin2, dir2 ) == CUBIT_FAILURE )
03813     {
03814       PRINT_ERROR( "Unable to get straight line information for Curve %d; aborting\n",
03815         ref_edge2->id() );
03816       return CUBIT_FAILURE;
03817     }
03818 
03819     if (bounded)
03820     {
03821        origin2 = ref_edge2->start_vertex()->coordinates();
03822        dir2 = ref_edge2->end_vertex()->coordinates() - origin2;
03823     }
03824     return straightline_intersections(ref_edge1, origin2, dir2,
03825                              intersection_list, bounded, closest);
03826   }
03827 
03828   if( closest == CUBIT_TRUE )
03829   {
03830     PRINT_ERROR( "'Near' option only works for straight lines\n" );
03831     return CUBIT_FAILURE;
03832   }
03833 
03834   // Use geometry engine to find intersections
03835   DLIList<TopologyEntity*> entity_list(2);
03836   DLIList<TopologyBridge*> bridge_list(2);
03837   DLIList<TopologyBridge*> curve_list1, curve_list2;
03838   entity_list.append(ref_edge1);
03839   entity_list.append(ref_edge2);
03840 
03841   //if there's virtual edge, find the underlying real curve.
03842   if (ref_edge1->get_geometry_query_engine())
03843     ref_edge1->get_geometry_query_engine()->get_underlying_curves(curve_ptr1, curve_list1);
03844   if (ref_edge2->get_geometry_query_engine())
03845     ref_edge2->get_geometry_query_engine()->get_underlying_curves(curve_ptr2, curve_list2);
03846 
03847   GeometryQueryEngine* gqe = common_query_engine( entity_list, bridge_list );
03848 
03849   //if they are both virtual...set gqe to NULL
03850   if( is_intermediate_geometry(curve_ptr1) && is_intermediate_geometry( curve_ptr2 ) )
03851     gqe = NULL;
03852 
03853   if( gqe == NULL && (curve_list1.size() > 0 || curve_list2.size() > 0) )
03854   {
03855     if (curve_list1.size() == 0)
03856       curve_list1.append (CAST_TO(curve_ptr1, TopologyBridge));
03857     if (curve_list2.size() == 0)
03858       curve_list2.append (CAST_TO(curve_ptr2, TopologyBridge));
03859     int i, j;
03860     for (i = 0; i <curve_list1.size(); i++)
03861     {
03862       TopologyBridge * tb1 = curve_list1.get_and_step();
03863       GeometryQueryEngine *gqe_ptr1 = tb1->get_geometry_query_engine();
03864       curve_ptr1 = CAST_TO(tb1, Curve);
03865 
03866       for(j = 0; j< curve_list2.size(); j++)
03867       {      
03868         TopologyBridge * tb2 = curve_list2.get_and_step();      
03869         GeometryQueryEngine *gqe_ptr2 = tb2->get_geometry_query_engine();
03870         if (gqe_ptr1 && gqe_ptr1 == gqe_ptr2 )
03871         {      
03872           curve_ptr2 = CAST_TO(tb2, Curve);
03873           status = gqe_ptr1->get_intersections(curve_ptr1, curve_ptr2,
03874             intersection_list, bounded, closest );
03875         }
03876       }
03877     }
03878 
03879     //remove duplicate intersections
03880     for( int k=0; k<intersection_list.size(); k++ )
03881     {
03882       intersection_list.reset();
03883       intersection_list.step(k+1);
03884       for( int s=k+1; s<intersection_list.size();)
03885       {
03886         if( intersection_list[k].distance_between( intersection_list[s] ) < GEOMETRY_RESABS )
03887         {
03888           intersection_list.remove();
03889         }
03890         else
03891         {
03892           s++;
03893           intersection_list.step();
03894         }
03895       }
03896     }
03897 
03898     return status;
03899   }
03900 
03901   else if (gqe == NULL)
03902   {
03903     PRINT_ERROR( "Curves %d and %d do not have the same underlying geometry modeling engine\n"
03904       "       For intersection calculations, they must be the same\n",
03905       ref_edge1->id(), ref_edge2->id() );
03906     return CUBIT_FAILURE;
03907   }
03908 
03909   bridge_list.reset();
03910   curve_ptr1 = dynamic_cast<Curve*>(bridge_list.next(0));
03911   curve_ptr2 = dynamic_cast<Curve*>(bridge_list.next(1));
03912   return gqe->get_intersections( curve_ptr1, curve_ptr2,
03913                                  intersection_list, bounded, closest );
03914 }
03915 
03916 CubitStatus
03917 GeometryQueryTool::get_intersections( RefEdge* ref_edge, RefFace* ref_face,
03918                                       DLIList<CubitVector>& intersection_list,
03919                                       CubitBoolean bounded )
03920 {
03921   // Use geometry engine to find intersections
03922   DLIList<TopologyEntity*> entity_list(2);
03923   DLIList<TopologyBridge*> bridge_list(2);
03924   entity_list.append(ref_edge);
03925   entity_list.append(ref_face);
03926   GeometryQueryEngine* gqe = common_query_engine( entity_list, bridge_list );
03927 
03928   if( gqe == NULL )
03929   {
03930     PRINT_ERROR( "Curve %d and Surface %d do not have the same underlying geometry query engine\n"
03931       "       For intersection calculations, they must be the same\n",
03932       ref_edge->id(), ref_face->id() );
03933     return CUBIT_FAILURE;
03934   }
03935 
03936   bridge_list.reset();
03937   Curve* curve = dynamic_cast<Curve*>(bridge_list.next(0));
03938   Surface* surf = dynamic_cast<Surface*>(bridge_list.next(1));
03939   return gqe->get_intersections( curve, surf, intersection_list, bounded );
03940 }
03941 
03942 CubitStatus
03943 GeometryQueryTool::get_intersections(RefEdge* ref_edge, CubitPlane plane,
03944                                       DLIList<CubitVector> &intersection_list,
03945                                       CubitBoolean bounded, double extended_percent )
03946 {
03947   CubitBox box = ref_edge->bounding_box();
03948 
03949   // create a Surface from the plane
03950   CubitVector p1, p2, p3, p4;
03951   AnalyticGeometryTool::instance()->min_pln_box_int_corners(plane, box, 1, extended_percent, p1, p2, p3, p4, true );
03952 
03953   TopologyBridge* bridge = 0;
03954   GeometryModifyEngine* gme = GeometryModifyTool::instance()->get_engine( ref_edge, &bridge );
03955   BodySM* sheet = gme->planar_sheet(p1, p2, p3, p4);
03956   if (!sheet)
03957   {
03958     PRINT_INFO("%s", "Unable to test for planar intersections\n");
03959     return CUBIT_FAILURE;
03960   }
03961 
03962   DLIList<Surface*> surfaces;
03963   sheet->surfaces( surfaces );
03964 
03965   Curve* curve = ref_edge->get_curve_ptr();
03966   GeometryQueryEngine* gqe = ref_edge->get_geometry_query_engine();
03967   CubitStatus status = gqe->get_intersections( curve, surfaces[0], intersection_list, bounded );
03968 
03969   gqe->delete_solid_model_entities(sheet);
03970 
03971   return status;
03972 }
03973 
03974 //===============================================================================
03975 // Function   : entity_extrema
03976 // Member Type: PUBLIC
03977 // Description: Find extrema location on entity
03978 // Author     : Steve Storm
03979 // Date       : 11/02
03980 //===============================================================================
03981 CubitStatus
03982 GeometryQueryTool::entity_extrema( RefEntity *ref_entity_ptr,
03983                                    const CubitVector *dir1,
03984                                    const CubitVector *dir2,
03985                                    const CubitVector *dir3,
03986                                    CubitVector &extrema,
03987                                    RefEntity *&extrema_entity_ptr )
03988 {
03989   DLIList<RefEntity*> ref_entity_list;
03990   ref_entity_list.append( ref_entity_ptr );
03991 
03992   return entity_extrema( ref_entity_list, dir1, dir2, dir3, extrema,
03993                          extrema_entity_ptr );
03994 }
03995 
03996 //===============================================================================
03997 // Function   : entity_extrema
03998 // Member Type: PUBLIC
03999 // Description: Find extrema location on a list of entities
04000 // Author     : Steve Storm
04001 // Date       : 11/02
04002 //===============================================================================
04003 CubitStatus
04004 GeometryQueryTool::entity_extrema( DLIList<RefEntity*> &ref_entity_list,
04005                                    const CubitVector *dir1,
04006                                    const CubitVector *dir2,
04007                                    const CubitVector *dir3,
04008                                    CubitVector &extrema,
04009                                    RefEntity *&extrema_entity_ptr )
04010 {
04011   if( ref_entity_list.size() == 0 )
04012   {
04013     PRINT_ERROR( "No entities found for extrema calculation.\n" );
04014     return CUBIT_FAILURE;
04015   }
04016 
04017   DLIList<TopologyEntity*> entity_list(ref_entity_list.size());
04018   DLIList<TopologyBridge*> bridge_list(ref_entity_list.size());
04019   DLIList<RefVolume*> ref_vols;
04020     // Can only do BasicTopologyEntitys.  Relace Bodys with RefVolumes.
04021   ref_entity_list.reset();
04022   for (int i = ref_entity_list.size(); i--; )
04023   {
04024     RefEntity* entity = ref_entity_list.get_and_step();
04025     if (BasicTopologyEntity* bte = dynamic_cast<BasicTopologyEntity*>(entity))
04026     {
04027       entity_list.append(bte);
04028       continue;
04029     }
04030 
04031     if (Body* body = dynamic_cast<Body*>(entity))
04032     {
04033       ref_vols.clean_out();
04034       body->ref_volumes(ref_vols);
04035       ref_vols.reset();
04036       for (int j = ref_vols.size(); j--;)
04037         entity_list.append(ref_vols.get_and_step());
04038       continue;
04039     }
04040 
04041     PRINT_ERROR("Don't know how to handle entity of type '%s' in "
04042                 "GQT::entity_extrema.\n", entity->class_name());
04043     return CUBIT_FAILURE;
04044   }
04045 
04046 
04047   GeometryQueryEngine* gqe = common_query_engine(entity_list, bridge_list);
04048   if( gqe == NULL )
04049   {
04050     PRINT_ERROR( "Entities specified for extrema do not have the same\n"
04051       "       underlying geometry query engine.\n"
04052       "       For extrema calculations, they must be the same.\n" );
04053     return CUBIT_FAILURE;
04054   }
04055 
04056     // Need GeometryEntities.
04057   DLIList<GeometryEntity*> geom_list(bridge_list.size());
04058   CAST_LIST(bridge_list, geom_list, GeometryEntity);
04059 
04060   // Check direction inputs
04061   if( dir1 == NULL )
04062   {
04063     PRINT_ERROR( "Direction not found for extrema calculation - it is required.\n" );
04064     return CUBIT_FAILURE;
04065   }
04066   if( dir2 == NULL && dir3 )
04067   {
04068     PRINT_ERROR( "Second direction not specified but last direction\n"
04069     "       was - this is not allowed for extrema calculation.\n" );
04070     return CUBIT_FAILURE;
04071   }
04072 
04073   GeometryEntity* extrema_geom = 0;
04074   CubitStatus status = gqe->entity_extrema( geom_list, dir1, dir2, dir3,
04075                                            extrema, extrema_geom );
04076   extrema_entity_ptr = dynamic_cast<RefEntity*>(entity_from_bridge(extrema_geom));
04077   return status;
04078 }
04079 
04080 CubitStatus
04081 GeometryQueryTool::entity_entity_distance( RefEntity *ref_entity_ptr1,
04082                                            RefEntity *ref_entity_ptr2,
04083                                            CubitVector &pos1, CubitVector &pos2,
04084                                            double &distance )
04085 {
04086   DLIList<TopologyEntity*> entity_list(2);
04087   DLIList<TopologyBridge*> bridge_list(2);
04088 
04089   BasicTopologyEntity* bte1 = dynamic_cast<BasicTopologyEntity*>(ref_entity_ptr1);
04090   BasicTopologyEntity* bte2 = dynamic_cast<BasicTopologyEntity*>(ref_entity_ptr2);
04091   if (!bte1 || !bte2)
04092   {
04093     const char* name = bte2 ? ref_entity_ptr1->class_name() : ref_entity_ptr2->class_name();
04094     PRINT_ERROR("Cannot calculate entity distance for entity of type '%s'\n", name);
04095     return CUBIT_FAILURE;
04096   }
04097 
04098   entity_list.append(bte1);
04099   entity_list.append(bte2);
04100   GeometryQueryEngine* gqe = common_query_engine(entity_list, bridge_list);
04101   if( gqe == NULL )
04102   {
04103     PRINT_ERROR( "%s and %s do not have the same underlying geometry query engine.\n"
04104       "       For distance calculations, they must be the same.\n",
04105       ref_entity_ptr1->entity_name().c_str(), ref_entity_ptr2->entity_name().c_str() );
04106     return CUBIT_FAILURE;
04107   }
04108 
04109   bridge_list.reset();
04110   GeometryEntity* geom1 = dynamic_cast<GeometryEntity*>(bridge_list.next(0));
04111   GeometryEntity* geom2 = dynamic_cast<GeometryEntity*>(bridge_list.next(1));
04112   return gqe->entity_entity_distance( geom1, geom2, pos1, pos2, distance );
04113 }
04114 
04115 CubitStatus
04116 GeometryQueryTool::entity_entity_distance( GeometryEntity *ge1,
04117                                            GeometryEntity *ge2,
04118                                            CubitVector &pos1, CubitVector &pos2,
04119                                            double &distance )
04120 {
04121   GeometryQueryEngine *gqe1 = ge1->get_geometry_query_engine();
04122   GeometryQueryEngine *gqe2 = ge2->get_geometry_query_engine();
04123 
04124   if(gqe1 != gqe2)
04125   {
04126     if(gqe1->is_intermediate_engine())
04127       return gqe1->entity_entity_distance(ge1, ge2, pos1, pos2, distance);
04128     else if(gqe2->is_intermediate_engine())
04129       return gqe2->entity_entity_distance(ge1, ge2, pos1, pos2, distance);
04130     else
04131     {
04132       PRINT_ERROR( "Entities do not have the same underlying geometry query engine.\n"
04133         "       For distance calculations, they must be the same.\n" );
04134       return CUBIT_FAILURE;
04135     }
04136   }
04137   else
04138   {
04139     return gqe1->entity_entity_distance(ge1, ge2, pos1, pos2, distance);
04140   }
04141 }
04142 
04143 CubitBox GeometryQueryTool::bounding_box_of_bodies()
04144 {
04145    CubitBox total_bound;
04146    int i;
04147 
04148    if(GeometryQueryTool::instance()->num_bodies() > 0)
04149    {
04150      GeometryQueryTool::instance()->get_last_body();
04151         // Assign the first body's bounding box to total_bound
04152      total_bound = GeometryQueryTool::instance()->get_last_body()->bounding_box();
04153 
04154         // Create union of all remaining bounding boxes
04155       for (i = GeometryQueryTool::instance()->num_bodies(); --i; )
04156           total_bound |= GeometryQueryTool::instance()->get_next_body()->bounding_box();
04157    }
04158    else
04159    {
04160         // Set the box to [(0,0,0)(0,0,0)]
04161       CubitVector temp(0,0,0);
04162       total_bound.reset(temp);
04163    }
04164      // Return the box
04165    return total_bound;
04166 }
04167 
04168 void GeometryQueryTool::cleanout_deactivated_geometry ()
04169 {
04170 
04171 
04172      // This routine removes from the model all RefEntities that have been
04173      // deactivated
04174    PRINT_DEBUG_17("\n\n...Cleaning out deactivated RefEntities "
04175                "and asociated Mesh Entities from the model\n");
04176 
04177      // First delete the meshes associated with the deactivated RefEntities
04178      // delete_meshes_of_deactivated_refEntities();
04179 
04180      // Now delete the deactivated RefEntities and remove all traces
04181      // of them from the DAG
04182    DAG::instance()->cleanout_deactivated_DAG_nodes();
04183 
04184      // Leave gracefully :-)
04185    PRINT_DEBUG_17(
04186                "Successfully cleaned out all deactivated RefEntities "
04187                "and associated Mesh Entities from the model.\n");
04188 
04189    return;
04190 }
04191 
04192 void GeometryQueryTool::delete_geometry ()
04193 {
04194 
04195    CubitStatus status = CUBIT_FAILURE;
04196 
04197      // Delete all RefGroups
04198    RefGroup::delete_all_groups();
04199    Body* bodyPtr = NULL;
04200    //DLIList<Body*> bodyList;
04201    //GeometryQueryTool::instance()->bodies(bodyList);
04202    //bodyList.reset();
04203    //for ( i = bodyList.size(); i > 0; i--)
04204    //{
04205    //   bodyPtr = bodyList.get_and_step();
04206 
04207    while( (bodyPtr = GeometryQueryTool::instance()->get_last_body() ) != NULL )
04208      {
04209         // Now delete this Body and its underlying solid model entities
04210       status = GeometryQueryTool::instance()->delete_Body( bodyPtr );
04211       if (status == CUBIT_FAILURE)
04212       {
04213          PRINT_ERROR("In GeometryQueryTool::delete_geometry\n"
04214                      "       Could not delete Body %d.\n"
04215                      "       The Model database is likely corrupted due"
04216                      " to\n       this unsuccessful deletion.\n",
04217                      bodyPtr->id() );
04218          assert( status != CUBIT_FAILURE) ;
04219          break;
04220       }
04221    }
04222 
04223      // Remove free-floating RefFaces
04224    RefFace* refFacePtr = NULL;
04225    //DLIList<RefFace*> refFaceList;
04226    //GeometryQueryTool::instance()->ref_faces(refFaceList);
04227    //refFaceList.reset();
04228    //for ( i = refFaceList.size(); i > 0; i--)
04229    //{
04230    //   refFacePtr = refFaceList.get_and_step();
04231 
04232    while( (refFacePtr = GeometryQueryTool::instance()->get_last_ref_face() ) != NULL )
04233      {
04234         // NOTE-
04235         //   The following GeometryQueryTool call results in a call to
04236         //   the RefFace destructor which notifies the Model of
04237         //   the destruction event. Model, in turn, removes the RefFace
04238         //   pointer from refFaceList. Hence, the size of this list
04239         //   changes inside this "while" loop.
04240       status = GeometryQueryTool::instance()->delete_RefFace( refFacePtr );
04241       if (status == CUBIT_FAILURE)
04242       {
04243          PRINT_ERROR("In GeometryQueryTool::delete_geometry\n"
04244                      "       Could not delete RefFace %d.\n"
04245                      "       The Model database is likely corrupted "
04246                      "due to\n       this unsuccessful deletion.\n",
04247                      refFacePtr->id());
04248          assert( status != CUBIT_FAILURE) ;
04249          break;
04250       }
04251    }
04252 
04253      // Remove free-floating RefEdges
04254    RefEdge* refEdgePtr = NULL;
04255    //DLIList<RefEdge*> refEdgeList;
04256    //GeometryQueryTool::instance()->ref_edges(refEdgeList);
04257    //refEdgeList.reset();
04258    //for ( i = refEdgeList.size(); i > 0; i--)
04259    //{
04260      //   refEdgePtr = refEdgeList.get_and_step();
04261 
04262    while( (refEdgePtr = GeometryQueryTool::instance()->get_last_ref_edge() ) != NULL )
04263      {
04264         // NOTE-
04265         //   The following GeometryQueryTool call results in a call to
04266         //   the RefEdge destructor which notifies the Model of
04267         //   the destruction event. Model, in turn, removes the RefEdge
04268         //   pointer from refEdgeList. Hence, the size of this list
04269         //   changes inside this "while" loop.
04270       status = GeometryQueryTool::instance()->delete_RefEdge( refEdgePtr );
04271       if (status == CUBIT_FAILURE)
04272       {
04273          PRINT_ERROR("In GeometryQueryTool::delete_geometry\n"
04274                      "       Could not delete RefEdge %d.\n"
04275                      "       The Model database is likely corrupted "
04276                      "due to\n       this unsuccessful deletion.\n",
04277                      refEdgePtr->id());
04278          assert( status != CUBIT_FAILURE) ;
04279          break;
04280       }
04281    }
04282 
04283      // Remove free-floating RefVertex'es
04284    RefVertex* refVertexPtr = NULL;
04285    //DLIList<RefVertex*> refVertexList;
04286    //GeometryQueryTool::instance()->ref_vertices(refVertexList);
04287    //refVertexList.reset();
04288    //for ( i = refVertexList.size(); i > 0; i--)
04289    //{
04290    //   refVertexPtr = refVertexList.get_and_step();
04291 
04292    while( (refVertexPtr = GeometryQueryTool::instance()->get_last_ref_vertex() ) != NULL )
04293      {
04294         // NOTE-
04295         //   The following GeometryQueryTool call results in a call to
04296         //   the RefVertex destructor which notifies the Model of
04297         //   the destruction event. Model, in turn, removes the RefVertex
04298         //   pointer from refVertexList. Hence, the size of this list
04299         //   changes inside this "while" loop.
04300       status = GeometryQueryTool::instance()->delete_RefVertex( refVertexPtr );
04301       if (status == CUBIT_FAILURE)
04302       {
04303          PRINT_ERROR("In GeometryQueryTool::delete_geometry\n"
04304                      "       Could not delete RefVertex %d.\n"
04305                      "       The Model database is likely corrupted "
04306                      "due to\n       this unsuccessful deletion.\n",
04307                      refVertexPtr->id());
04308          assert( status != CUBIT_FAILURE) ;
04309          break;
04310       }
04311    }
04312 
04313 
04314      // reset counters
04315    RefEntityFactory::instance()->reset_ids();
04316 
04317 }
04318 
04319 CubitStatus GeometryQueryTool::ref_entity_list(char const* keyword,
04320                                           DLIList<RefEntity*> &entity_list,
04321                                           const CubitBoolean print_errors)
04322 {
04323   return RefEntityFactory::instance()->ref_entity_list(keyword, entity_list,
04324                                                        print_errors);
04325 }
04326 
04327 CubitBox GeometryQueryTool::model_bounding_box()
04328 {
04329   int i;
04330   CubitBox result;
04331   DLIList<Body*> bodies;
04332   this->bodies(bodies);
04333 
04334   DLIList<RefEntity*> free_entity_list;
04335   this->get_free_ref_entities(free_entity_list);
04336   
04337   if (!(bodies.size() + free_entity_list.size()))
04338     return result;
04339 
04340   bodies.reset();
04341   free_entity_list.reset();
04342   
04343   if( bodies.size() )
04344   {
04345     result = bodies.get_and_step()->bounding_box();
04346     for ( i = bodies.size()-1; i--; )
04347       result |= bodies.get_and_step()->bounding_box();
04348     i = free_entity_list.size();
04349   }
04350   else
04351   {
04352     result = free_entity_list.get_and_step()->bounding_box();
04353     i = free_entity_list.size()-1;
04354   }
04355 
04356   for ( ; i>0 ; i-- )
04357     result |= free_entity_list.get_and_step()->bounding_box();
04358 
04359   return result;
04360 }
04361 
04362 void GeometryQueryTool::bodies(DLIList<Body*> &bodies)
04363 {
04364   RefEntityFactory::instance()->bodies(bodies);
04365 }
04366 
04367 void GeometryQueryTool::ref_volumes(DLIList<RefVolume*> &ref_volumes)
04368 {
04369   RefEntityFactory::instance()->ref_volumes(ref_volumes);
04370 }
04371 
04372 void GeometryQueryTool::ref_groups(DLIList<RefGroup*> &ref_groups)
04373 {
04374   RefEntityFactory::instance()->ref_groups(ref_groups);
04375 }
04376 
04377 void GeometryQueryTool::ref_faces(DLIList<RefFace*> &ref_faces)
04378 {
04379   RefEntityFactory::instance()->ref_faces(ref_faces);
04380 }
04381 
04382 void GeometryQueryTool::ref_edges(DLIList<RefEdge*> &ref_edges)
04383 {
04384   RefEntityFactory::instance()->ref_edges(ref_edges);
04385 }
04386 
04387 void GeometryQueryTool::ref_vertices(DLIList<RefVertex*> &ref_vertices)
04388 {
04389   RefEntityFactory::instance()->ref_vertices(ref_vertices);
04390 }
04391 
04392 void GeometryQueryTool::get_ordered_loops(RefFace* face, DLIList<Loop*> &loop_list)
04393 {
04394   GeometryQueryEngine *gqe = face->get_geometry_query_engine();
04395   gqe->get_ordered_loops(face, loop_list);
04396 }
04397 
04398 #ifdef PROE
04399 void GeometryQueryTool::ref_parts (DLIList<RefPart*> &ref_parts)
04400 {
04401     RefEntityFactory::instance()->ref_parts(ref_parts);
04402 }
04403 
04404 void GeometryQueryTool::ref_assemblies (DLIList<RefAssembly*> &ref_assemblies)
04405 {
04406     RefEntityFactory::instance()->ref_assemblies(ref_assemblies);
04407 }
04408 #endif
04409 
04410 int GeometryQueryTool::num_bodies() const
04411 {
04412   return RefEntityFactory::instance()->num_bodies();
04413 }
04414 
04415 int GeometryQueryTool::num_ref_volumes() const
04416 {
04417   return RefEntityFactory::instance()->num_ref_volumes();
04418 }
04419 
04420 int GeometryQueryTool::num_ref_groups() const
04421 {
04422   return RefEntityFactory::instance()->num_ref_groups();
04423 }
04424 
04425 int GeometryQueryTool::num_ref_faces() const
04426 {
04427   return RefEntityFactory::instance()->num_ref_faces();
04428 }
04429 
04430 int GeometryQueryTool::num_ref_edges() const
04431 {
04432   return RefEntityFactory::instance()->num_ref_edges();
04433 }
04434 
04435 int GeometryQueryTool::num_ref_vertices() const
04436 {
04437   return RefEntityFactory::instance()->num_ref_vertices();
04438 }
04439 
04440 RefEntity *GeometryQueryTool::get_ref_entity(const char *type, int id)
04441 {
04442   return RefEntityFactory::instance()->get_ref_entity(type, id);
04443 }
04444 
04445 RefEntity *GeometryQueryTool::get_ref_entity(const std::type_info& type, int id)
04446 {
04447   return RefEntityFactory::instance()->get_ref_entity(type, id);
04448 }
04449 
04450 Body *GeometryQueryTool::get_body( int id)
04451 {
04452   return RefEntityFactory::instance()->get_body(id);
04453 }
04454 
04455 RefVolume *GeometryQueryTool::get_ref_volume( int id)
04456 {
04457   return RefEntityFactory::instance()->get_ref_volume(id);
04458 }
04459 
04460 RefGroup *GeometryQueryTool::get_ref_group( int id)
04461 {
04462   return RefEntityFactory::instance()->get_ref_group(id);
04463 }
04464 
04465 RefFace *GeometryQueryTool::get_ref_face( int id)
04466 {
04467   return RefEntityFactory::instance()->get_ref_face(id);
04468 }
04469 
04470 RefEdge *GeometryQueryTool::get_ref_edge( int id)
04471 {
04472   return RefEntityFactory::instance()->get_ref_edge(id);
04473 }
04474 
04475 RefVertex *GeometryQueryTool::get_ref_vertex( int id)
04476 {
04477   return RefEntityFactory::instance()->get_ref_vertex(id);
04478 }
04479 
04480 Body *GeometryQueryTool::get_first_body()
04481 {
04482   return RefEntityFactory::instance()->get_first_body();
04483 }
04484 
04485 RefVolume *GeometryQueryTool::get_first_ref_volume()
04486 {
04487   return RefEntityFactory::instance()->get_first_ref_volume();
04488 }
04489 
04490 RefGroup *GeometryQueryTool::get_first_ref_group()
04491 {
04492   return RefEntityFactory::instance()->get_first_ref_group();
04493 }
04494 
04495 RefFace *GeometryQueryTool::get_first_ref_face()
04496 {
04497   return RefEntityFactory::instance()->get_first_ref_face();
04498 }
04499 
04500 RefEdge *GeometryQueryTool::get_first_ref_edge()
04501 {
04502   return RefEntityFactory::instance()->get_first_ref_edge();
04503 }
04504 
04505 RefVertex *GeometryQueryTool::get_first_ref_vertex()
04506 {
04507   return RefEntityFactory::instance()->get_first_ref_vertex();
04508 }
04509 
04510 Body *GeometryQueryTool::get_next_body()
04511 {
04512   return RefEntityFactory::instance()->get_next_body();
04513 }
04514 
04515 RefVolume *GeometryQueryTool::get_next_ref_volume()
04516 {
04517   return RefEntityFactory::instance()->get_next_ref_volume();
04518 }
04519 
04520 RefGroup *GeometryQueryTool::get_next_ref_group()
04521 {
04522   return RefEntityFactory::instance()->get_next_ref_group();
04523 }
04524 
04525 RefFace *GeometryQueryTool::get_next_ref_face()
04526 {
04527   return RefEntityFactory::instance()->get_next_ref_face();
04528 }
04529 
04530 RefEdge *GeometryQueryTool::get_next_ref_edge()
04531 {
04532   return RefEntityFactory::instance()->get_next_ref_edge();
04533 }
04534 
04535 RefVertex *GeometryQueryTool::get_next_ref_vertex()
04536 {
04537   return RefEntityFactory::instance()->get_next_ref_vertex();
04538 }
04539 
04540 
04541 Body *GeometryQueryTool::get_last_body()
04542 {
04543   return RefEntityFactory::instance()->get_last_body();
04544 }
04545 
04546 RefVolume *GeometryQueryTool::get_last_ref_volume()
04547 {
04548   return RefEntityFactory::instance()->get_last_ref_volume();
04549 }
04550 
04551 RefGroup *GeometryQueryTool::get_last_ref_group()
04552 {
04553   return RefEntityFactory::instance()->get_last_ref_group();
04554 }
04555 
04556 RefFace *GeometryQueryTool::get_last_ref_face()
04557 {
04558   return RefEntityFactory::instance()->get_last_ref_face();
04559 }
04560 
04561 RefEdge *GeometryQueryTool::get_last_ref_edge()
04562 {
04563   return RefEntityFactory::instance()->get_last_ref_edge();
04564 }
04565 
04566 RefVertex *GeometryQueryTool::get_last_ref_vertex()
04567 {
04568   return RefEntityFactory::instance()->get_last_ref_vertex();
04569 }
04570 
04571 CubitStatus GeometryQueryTool::get_free_ref_entities(DLIList<RefEntity*> &free_entities)
04572 {
04573     // go through the global entity lists looking for free entities
04574 
04575     // this algorithm works as follows: start by marking all entities in the model;
04576     // - bodies that don't have virtual children are NOT free, along with their children;
04577     //   unmark them all
04578     // - for all remaining entities:
04579     // . entities that are unmarked are not free since they were unmarked during the
04580     //   body check
04581     // . entities that are virtual are not free, but their underlying entities may be;
04582     //     check this, and unmark the underlying non-free entities, but not their children
04583     // . entities that don't have a TopologyBridge connected to a bodysm are free
04584     //
04585     // - Removed virtual stuff - no longer required - J.Kraftcheck 10-8-2003
04586 
04587   int i, j;
04588   RefEntityFactory *REF = RefEntityFactory::instance();
04589 
04590     // define a macro to mark all the children
04591 #define MARK_CHILDREN(entity, index) \
04592    {ref_list.clean_out(); entity->get_all_child_ref_entities(ref_list); \
04593    for (index=ref_list.size(); index>0; index--) ref_list.get_and_step()->marked(0);}
04594 
04595     // mark all entities first
04596   for (i = REF->num_ref_volumes(); i > 0; i--)
04597     REF->get_next_ref_volume()->marked(1);
04598   for (i = REF->num_ref_faces(); i > 0; i--)
04599     REF->get_next_ref_face()->marked(1);
04600   for (i = REF->num_ref_edges(); i > 0; i--)
04601     REF->get_next_ref_edge()->marked(1);
04602   for (i = REF->num_ref_vertices(); i > 0; i--)
04603     REF->get_next_ref_vertex()->marked(1);
04604 
04605   DLIList<RefEntity*> ref_list;
04606 
04607     // first, mark all the children of bodies
04608   Body *body;
04609   for (i = REF->num_bodies(); i > 0; i--) {
04610     body = REF->get_next_body();
04611     MARK_CHILDREN(body, j);
04612   }
04613 
04614     // now go through them, checking for VG and free entities
04615   RefVolume *volume;
04616   for (i = REF->num_ref_volumes(); i > 0; i--) {
04617     volume = REF->get_next_ref_volume();
04618     if (volume->marked()) {
04619         // go through volume's children & unmark
04620       MARK_CHILDREN(volume, j);
04621       free_entities.append(volume);
04622       volume->marked(0);
04623     }
04624   }
04625 
04626   RefFace *face;
04627   for (i = REF->num_ref_faces(); i > 0; i--) {
04628     face = REF->get_next_ref_face();
04629     if (face->marked()) {
04630       MARK_CHILDREN(face, j);
04631       free_entities.append(face);
04632       face->marked(0);
04633     }
04634   }
04635 
04636   RefEdge *edge;
04637   for (i = REF->num_ref_edges(); i > 0; i--) {
04638     edge = REF->get_next_ref_edge();
04639     if (edge->marked()) {
04640       MARK_CHILDREN(edge, j);
04641       free_entities.append(edge);
04642       edge->marked(0);
04643     }
04644   }
04645 
04646   RefVertex *vertex;
04647   for (i = REF->num_ref_vertices(); i > 0; i--) {
04648     vertex = REF->get_next_ref_vertex();
04649     if (vertex->marked()) {
04650       free_entities.append(vertex);
04651       vertex->marked(0);
04652     }
04653   }
04654 
04655   return CUBIT_SUCCESS;
04656 }
04657 
04658 
04659 double GeometryQueryTool::surface_angle(RefFace *ref_face_1, RefFace *ref_face_2,
04660                                         RefEdge *ref_edge,
04661                                         RefVolume *ref_volume,
04662                                         double frac)
04663 {
04664 
04665     // check for and supply missing ref edge if necessary
04666   if (ref_edge == NULL) {
04667     ref_edge = ref_face_1->common_ref_edge(ref_face_2);
04668     assert (ref_edge != NULL);
04669   }
04670 
04671   if (ref_volume == NULL) {
04672     ref_volume = ref_face_1->common_ref_volume(ref_face_2);
04673     assert(ref_volume != NULL);
04674   }
04675 
04676      //Find the dihedral angle for the ref_edge
04677    CubitVector mid_point;
04678    if ( frac != .5 )
04679      ref_edge->position_from_fraction(frac, mid_point);
04680    else
04681      mid_point = ref_edge->center_point();
04682 
04683 
04684      //Now find the normals of the surfaces at this point, wrt volume
04685    CubitVector surf_1_norm = ref_face_1->normal_at( mid_point, ref_volume );
04686    CubitVector surf_2_norm = ref_face_2->normal_at( mid_point, ref_volume );
04687 
04688      //Now we need to get the correct normal
04689    CubitVector tangent_vector;
04690 
04691      //This gets the correct tangent with respect for to the
04692      //ref_face_ptr.  Do the following check for non-manifold volumes.
04693      //This function will assert if the ref_edge has more than
04694      //one co_edge for the two_faces.  But this should be okay
04695      //since up above this function, that should be traped for...
04696 
04697     //Weed-out case where one edge is shared between more
04698     //than 2 surfaces of the same volume
04699     DLIList<RefFace*> tmp_faces;
04700     ref_edge->ref_faces( tmp_faces );
04701 
04702     if( tmp_faces.size() > 2 )
04703     {
04704       int kk;
04705       for(kk=tmp_faces.size(); kk--;)
04706       {
04707         if( !tmp_faces.get()->is_child( ref_volume ) )
04708           tmp_faces.change_to(NULL);
04709         tmp_faces.step();
04710       }
04711       tmp_faces.remove_all_with_value( NULL );
04712       if( tmp_faces.size() > 2 )
04713         //this isn't the type of surface we are looking for...
04714         return 0.0;
04715     }
04716 
04717 
04718    ref_edge->tangent( mid_point, tangent_vector, ref_face_1 );
04719    CubitSense face_1_sense = ref_face_1->sense( ref_volume );
04720 
04721    if( CUBIT_REVERSED != face_1_sense && CUBIT_FORWARD != face_1_sense )
04722       if(!(ref_volume->is_sheet()))
04723          return 0.0;
04724 
04725    if ( face_1_sense == CUBIT_REVERSED )
04726      tangent_vector = -tangent_vector;
04727 
04728    double angle = CUBIT_PI +
04729      tangent_vector.vector_angle(surf_2_norm, surf_1_norm );
04730      // note 1 and 2 switched.
04731      // tangent is cw, opposite of rhr
04732 
04733      // Range of above is pi/2 to 5pi/2, shift to 0 to 2pi.
04734    if ( angle >= 2.0* CUBIT_PI )
04735      angle -= 2.0 * CUBIT_PI;
04736 
04737      // if the angle is close to 0 or 2pi, use a center point check
04738      // to figure out if the interior angle is zero or 2pi
04739    const double min_tol = 0.1; // CUBIT_RESABS*100. too small
04740      // We could have a real overlap in some models, so keep
04741      // min_tol fairly big.
04742    const double max_tol = 2.0*CUBIT_PI - min_tol;
04743 
04744      // angle near zero - 2pi, make some checks at nearby locations
04745    if (angle <= min_tol || angle >= max_tol )
04746    {
04747        // try to get the inside-outness where the surfaces have a gap
04748        // between them
04749 
04750        // get a non-shared edge with a shared vertex between the surfaces
04751 
04752      int i;
04753 
04754        // get the next edge in the loop
04755      DLIList<DLIList<RefEdge*> > loops_1;
04756      DLIList<RefEdge*> *loop_1 = NULL;
04757      ref_face_1->ref_edge_loops( loops_1 );
04758      for ( i = loops_1.size(); i--; )
04759      {
04760        loop_1 = &loops_1.get_and_step();
04761        if ( loop_1->move_to( ref_edge ) )
04762          break;
04763      }
04764      assert( loop_1->get() == ref_edge );
04765 
04766      DLIList<DLIList<RefEdge*> > loops_2;
04767      DLIList<RefEdge*> *loop_2 = NULL;
04768      ref_face_2->ref_edge_loops( loops_2 );
04769      for ( i = loops_2.size(); i--; )
04770      {
04771        loop_2 = &loops_2.get_and_step();
04772        if ( loop_2->move_to( ref_edge ) )
04773          break;
04774      }
04775      assert( loop_2->get() == ref_edge );
04776 
04777      RefEdge *common_edge = ref_edge, *next_edge,
04778        *uncommon_edge_1 = NULL, *uncommon_edge_2 = NULL;
04779      RefVertex *common_vertex = NULL;
04780 
04781      for ( i = loop_1->size(); !common_vertex && i--; )
04782      {
04783        next_edge = loop_1->step_and_get();
04784        if ( loop_2->prev() == next_edge )
04785        {
04786          loop_2->back();
04787          common_edge = next_edge;
04788        }
04789        else if ( loop_2->next() == next_edge )
04790        {
04791          loop_2->step();
04792          common_edge = next_edge;
04793        }
04794        else
04795        {
04796          uncommon_edge_1 = next_edge;
04797 
04798            // if both vertices are shared, it doesn't matter which we chose.
04799          common_vertex = common_edge->common_ref_vertex( uncommon_edge_1 );
04800 
04801          if ( loop_2->next()->is_parent( common_vertex ) )
04802            uncommon_edge_2 = loop_2->next();
04803          else
04804          {
04805            assert( loop_2->prev()->is_parent( common_vertex ) );
04806            uncommon_edge_2 = loop_2->prev();
04807          }
04808        }
04809      }
04810 
04811      int too_far;
04812 
04813      CubitVector center_1, center_2, center_norm_1, center_norm_2;
04814 
04815        // we've found non-common edges with a common vertex
04816      int bad_angle = CUBIT_TRUE;
04817      if ( common_vertex )
04818      {
04819 
04820          // These two curves are only good geometrically if they
04821          // have a small angle between them: If the angle is too big,
04822          // then the closest pt will be the vertex, and we'll have to
04823          // start over with the surfaces or something.
04824 
04825          // reset midpoint and normals to common vertex...
04826        CubitVector vertex_coord = common_vertex->coordinates();
04827 
04828          // get a pair of close points on each surface
04829        center_1 = uncommon_edge_1->center_point();
04830        center_2 = uncommon_edge_2->center_point();
04831 
04832        double d_1 = (center_1 - vertex_coord).length_squared();
04833        double d_2 = (center_2 - vertex_coord).length_squared();
04834        int give_up = 0;
04835        i = 0;
04836        if ( d_1 <= d_2 )
04837        {
04838          do
04839          {
04840            center_2 = center_1;
04841            uncommon_edge_2->move_to_curve( center_2 );
04842            d_2 = (center_2 - vertex_coord).length_squared();
04843            bad_angle =  d_2 < d_1 * 0.2;
04844            give_up = ( d_1 < GEOMETRY_RESABS*10 || i++ > 10 );
04845            if ( give_up )
04846              break;
04847            if ( bad_angle )
04848            {
04849              center_1 += vertex_coord;
04850              center_1 /= 2.0;
04851              uncommon_edge_1->move_to_curve( center_1 );
04852              d_1 = (center_1 - vertex_coord).length_squared();
04853            }
04854          } while ( bad_angle );
04855        }
04856        else
04857        {
04858          do
04859          {
04860            center_1 = center_2;
04861            uncommon_edge_1->move_to_curve( center_1 );
04862            d_1 = (center_1 - vertex_coord).length_squared();
04863            bad_angle =  d_1 < d_2 * 0.2;
04864            give_up = ( d_2 < GEOMETRY_RESABS*10 || i++ > 10 );
04865            if ( give_up )
04866              break;
04867            if ( bad_angle )
04868            {
04869              center_2 += vertex_coord;
04870              center_2 /= 2.0;
04871              uncommon_edge_2->move_to_curve( center_2 );
04872              d_2 = (center_2 - vertex_coord).length_squared();
04873            }
04874          } while ( bad_angle );
04875        }
04876        if ( !bad_angle )
04877        {
04878          mid_point = vertex_coord;
04879          surf_1_norm = ref_face_1->normal_at( mid_point, ref_volume );
04880          surf_2_norm = ref_face_2->normal_at( mid_point, ref_volume );
04881 
04882 
04883          double best_d_1 = CUBIT_DBL_MAX;
04884 
04885          CubitVector test_center_1 = center_1;
04886          CubitVector test_center_norm_1;
04887 
04888          // may be too far away - make sure normal is roughly the same
04889          //  as at the midpoint
04890 
04891          too_far = CUBIT_TRUE;
04892          for ( i = 12; i-- && too_far; )
04893          {
04894            test_center_norm_1 =
04895              ref_face_1->normal_at( test_center_1, ref_volume );
04896            d_1 = test_center_norm_1 % surf_1_norm;
04897            if ( d_1 < best_d_1 )
04898            {
04899              center_1 = test_center_1;
04900              center_norm_1 = test_center_norm_1;
04901            }
04902            too_far =  d_1 < 0.2;
04903            if ( too_far && i )  // skip last time
04904            {
04905              test_center_1 += mid_point;
04906              test_center_1 /= 2.0;
04907              uncommon_edge_1->move_to_curve( test_center_1 );
04908            }
04909          }
04910 
04911          double best_d_2 = CUBIT_DBL_MAX;
04912 
04913          CubitVector test_center_2 = center_2;
04914          CubitVector test_center_norm_2;
04915 
04916            // may be too far away - make sure normal is roughly the same
04917            //  as at the surface midpoint
04918          too_far = CUBIT_TRUE;
04919          for ( i = 12; i-- && too_far; )
04920          {
04921            test_center_norm_2 =
04922              ref_face_2->normal_at( test_center_2, ref_volume );
04923            d_2 = test_center_norm_2 % surf_2_norm;
04924            if ( d_2 < best_d_2 )
04925            {
04926              center_2 = test_center_2;
04927              center_norm_2 = test_center_norm_2;
04928            }
04929            too_far =  d_2 < 0.2;
04930            if ( too_far && i )  // skip last time
04931            {
04932              test_center_2 += mid_point;
04933              test_center_2 /= 2.0;
04934              uncommon_edge_2->move_to_curve( test_center_2 );
04935            }
04936          }
04937        }
04938      }
04939        // surfaces share all edges! try the face center point
04940      if ( !common_vertex || bad_angle )
04941      {
04942 
04943          // get a pair of close points on each surface
04944        center_1 = ref_face_1->center_point();
04945        center_2 = ref_face_2->center_point();
04946        double d_1 = (center_1 - mid_point).length_squared();
04947        double d_2 = (center_2 - mid_point).length_squared();
04948        if ( d_1 <= d_2 )
04949        {
04950          center_2 = center_1;
04951          ref_face_2->move_to_surface( center_2 );
04952        }
04953        else
04954        {
04955          center_1 = center_2;
04956          ref_face_1->move_to_surface( center_1 );
04957        }
04958 
04959        double best_d_1 = CUBIT_DBL_MAX;
04960 
04961        CubitVector test_center_1 = center_1;
04962        CubitVector test_center_norm_1;
04963 
04964          // may be too far away - make sure normal is roughly the same
04965          //  as at the curve midpoint
04966        too_far = CUBIT_TRUE;
04967        for ( i = 12; i-- && too_far; )
04968        {
04969          test_center_norm_1 =
04970            ref_face_1->normal_at( test_center_1, ref_volume );
04971          d_1 = test_center_norm_1 % surf_1_norm;
04972          if ( d_1 < best_d_1 )
04973          {
04974            center_1 = test_center_1;
04975            center_norm_1 = test_center_norm_1;
04976          }
04977          too_far =  d_1 < 0.2;
04978          if ( too_far && i )  // skip last time
04979          {
04980            test_center_1 += mid_point;
04981            test_center_1 /= 2.0;
04982            ref_face_1->move_to_surface( test_center_1 );
04983          }
04984        }
04985 
04986          // surfaces share all edge! try the center point
04987        double best_d_2 = CUBIT_DBL_MAX;
04988 
04989        CubitVector test_center_2 = center_2;
04990        CubitVector test_center_norm_2;
04991 
04992          // may be too far away - make sure normal is roughly the same
04993          //  as at the curve midpoint
04994        too_far = CUBIT_TRUE;
04995        for ( i = 12; i-- && too_far; )
04996        {
04997          test_center_norm_2 =
04998            ref_face_2->normal_at( test_center_2, ref_volume );
04999          d_2 = test_center_norm_2 % surf_2_norm;
05000          if ( d_2 < best_d_2 )
05001          {
05002            center_2 = test_center_2;
05003            center_norm_2 = test_center_norm_2;
05004          }
05005          too_far =  d_2 < 0.2;
05006          if ( too_far && i )  // skip last time
05007          {
05008            test_center_2 += mid_point;
05009            test_center_2 /= 2.0;
05010            ref_face_2->move_to_surface( test_center_2 );
05011          }
05012        }
05013      }
05014 
05015        // gap vector from center_1 to center_2
05016      CubitVector gap_vector = center_2;
05017      gap_vector -= center_1;
05018 
05019      double gap_d = gap_vector % center_norm_1;
05020      gap_d += -gap_vector % center_norm_2;
05021 
05022      if ( gap_d >= 0 )
05023      {
05024        if ( angle < max_tol )
05025          angle = 2*CUBIT_PI;
05026          // else leave at its current nearly-2pi value
05027      }
05028      else
05029        if ( angle > min_tol )
05030          angle = 0.;
05031        // else leave at its current nearly-zero value
05032 
05033    } // if angle near zero - 2pi
05034 
05035    return angle;
05036 }
05037 
05038 //-------------------------------------------------------------------------
05039 // Purpose       : Find a common geometry query engine
05040 //
05041 // Special Notes :
05042 //
05043 // Creator       : Jason Kraftcheck
05044 //
05045 // Creation Date : 02/28/00
05046 //-------------------------------------------------------------------------
05047 GeometryQueryEngine* GeometryQueryTool::common_query_engine(
05048   DLIList<TopologyEntity*>& topology_list,
05049   DLIList<TopologyBridge*>& engine_bridges,
05050   CubitBoolean allow_default_engine ) const
05051 {
05052   topology_list.reset();
05053 
05054   TopologyEntity* topo_ptr = topology_list.get_and_step();
05055   DLIList<TopologyBridge*> first_bridge_list;
05056   topo_ptr->bridge_manager()->get_bridge_list( first_bridge_list );
05057 
05058   first_bridge_list.reset();
05059   GeometryQueryEngine* gqe_ptr = 0;
05060   for( int i = first_bridge_list.size(); i > 0; i-- )
05061   {
05062     TopologyBridge* bridge_ptr = first_bridge_list.get_and_step();
05063     engine_bridges.clean_out();
05064     engine_bridges.append( bridge_ptr );
05065     gqe_ptr = bridge_ptr->get_geometry_query_engine();
05066 
05067     topology_list.reset();
05068     topology_list.step(); //skip first entry
05069     for( int j = topology_list.size(); j > 1; j-- )
05070     {
05071       topo_ptr = topology_list.get_and_step();
05072       bridge_ptr = topo_ptr->bridge_manager()->topology_bridge(gqe_ptr);
05073       if( bridge_ptr ) engine_bridges.append( bridge_ptr );
05074       else break;
05075     }
05076 
05077     if( engine_bridges.size() == topology_list.size() )
05078       break;
05079 
05080     gqe_ptr = 0;
05081   }
05082 
05083   if( !gqe_ptr )
05084   {
05085     engine_bridges.clean_out();
05086 
05087     if( allow_default_engine )
05088     {
05089       PRINT_WARNING("Entities do not belong to the same geometry "
05090         "engine.  Using the default  geometry engine.\n");
05091       gqe_ptr = default_gqe;
05092       topology_list.reset();
05093       for( int j = topology_list.size(); j > 0; j-- )
05094       {
05095         topo_ptr = topology_list.get_and_step();
05096         TopologyBridge* bridge_ptr =
05097           topo_ptr->bridge_manager()->topology_bridge( gqe_ptr );
05098         if( ! bridge_ptr )
05099           bridge_ptr = topo_ptr->bridge_manager()->topology_bridge();
05100         engine_bridges.append( bridge_ptr );
05101       }
05102     }
05103   }
05104 
05105   return gqe_ptr;
05106 }
05107 
05108 
05109 void GeometryQueryTool::get_connected_free_ref_entities(
05110   RefEntity *entity,
05111   const int merge_option,
05112   DLIList<Body*> &body_list,
05113   DLIList<RefFace*> &ref_face_list,
05114   DLIList<RefEdge*> &ref_edge_list,
05115   DLIList<RefVertex*> &ref_vertex_list )
05116 {
05117 
05118   body_list.clean_out();
05119   ref_face_list.clean_out();
05120   ref_edge_list.clean_out();
05121   ref_vertex_list.clean_out();
05122 
05123   if ( !entity )
05124     return;
05125 
05126    // cases are different enough, just do something totally different
05127   if ( !merge_option  )
05128   {
05129       // get top level entities
05130     TopologyEntity *source_entity = CAST_TO(entity, TopologyEntity);
05131 
05132     Body *body = CAST_TO( source_entity, Body );
05133     if( body )
05134       body_list.append( body );
05135     else
05136         //  get attached bodies, if any
05137       source_entity->bodies( body_list );
05138 
05139     if(body_list.size() == 0)
05140     {
05141       RefEdge* ref_edge = CAST_TO(source_entity, RefEdge);
05142       if ( ref_edge )
05143         ref_edge_list.append( ref_edge );
05144       else
05145       {
05146         source_entity->ref_edges( ref_edge_list );
05147       }
05148       if ( ref_edge_list.size() == 0 )
05149       {
05150         RefVertex *vert = CAST_TO( source_entity, RefVertex );
05151         if ( vert )
05152           ref_vertex_list.append( vert );
05153       }
05154     }
05155     // this is the easy case, we're all done
05156     return;
05157   }
05158 
05159 
05160     // merge_option == 1
05161   DLIList <TopologyEntity*> source_list;
05162   DLIList <RefEntity*> source_entity_list;
05163 
05164   int i;
05165 
05166   DLIList <RefEntity*> free_list;
05167 
05168   DLIList<TopologyBridge*> bridge_list;
05169 
05170   TopologyEntity *topo_entity = CAST_TO( entity, TopologyEntity );
05171   source_list.append( topo_entity );
05172   DLIList<RefEntity*> entity_list;
05173   do
05174   {
05175       // get vertices (bottom level ref entities)
05176     source_entity_list.clean_out();    
05177 
05178     for (i = source_list.size(); i--; )
05179     { 
05180       TopologyEntity *source_entity = source_list.get_and_step();
05181       DLIList<RefVertex*> local_vert_list;
05182       DLIList<RefEntity*> tmp_source_entity_list;
05183       source_entity->ref_vertices( local_vert_list );
05184       if(local_vert_list.size() == 0)
05185       {
05186         DLIList<RefEdge*> local_edge_list;
05187         source_entity->ref_edges(local_edge_list);
05188         if(local_edge_list.size() == 0)
05189         {
05190           DLIList<RefFace*> local_face_list;
05191           source_entity->ref_faces(local_face_list);
05192           if(local_face_list.size() > 0)
05193           {
05194             CAST_LIST( local_face_list, tmp_source_entity_list, RefEntity);
05195             source_entity_list += tmp_source_entity_list;
05196           }
05197         }
05198         else
05199         {
05200           CAST_LIST( local_edge_list, tmp_source_entity_list, RefEntity);
05201           source_entity_list += tmp_source_entity_list;
05202         }
05203       }
05204       else
05205       {
05206         CAST_LIST( local_vert_list, tmp_source_entity_list, RefEntity);
05207         source_entity_list += tmp_source_entity_list;
05208       }
05209     }
05210     source_list.clean_out();
05211 
05212       // get top level entities
05213     for ( i = source_entity_list.size(); i--; )
05214     {
05215       RefEntity *source_entity = source_entity_list.get_and_step();
05216         // get all upwards related ref entities
05217       entity_list.clean_out();
05218         // get the bodies, too!
05219       source_entity->get_all_parent_ref_entities( entity_list, CUBIT_TRUE );
05220       entity_list.append( source_entity );
05221 
05222         // check each one to see if it is a new top level in the solid
05223         // modeller
05224       int j;
05225       for ( j = entity_list.size(); j--; )
05226       {
05227         // entity is top level if it has a topology bridge that has a bodysm
05228         RefEntity *ref_entity = entity_list.get_and_step(); 
05229 
05230         if ( !ref_entity->marked() )
05231         {
05232           bridge_list.clean_out();
05233           topo_entity = CAST_TO( ref_entity, TopologyEntity );
05234           topo_entity->bridge_manager()->get_bridge_list(bridge_list);
05235           int k;
05236           bool no_parents = true;
05237           for ( k = bridge_list.size(); k--; )
05238           {
05239             TopologyBridge* bridge = bridge_list.get_and_step();
05240             DLIList<TopologyBridge*> parents;
05241             bridge->get_parents( parents );            
05242             if( parents.size() )
05243             {
05244               no_parents = false;
05245               break;
05246             }
05247           }
05248           if( no_parents )
05249           {             
05250             ref_entity->marked( 1 );
05251             topo_entity = CAST_TO( ref_entity, TopologyEntity );
05252             source_list.append( topo_entity );
05253             free_list.append( ref_entity );
05254             continue;
05255           }
05256         }
05257       }
05258     }
05259 
05260   } while( source_list.size() );
05261 
05262     // xfer data, clean up marks
05263   for ( i = free_list.size(); i--; )
05264   {
05265     RefEntity *ref_entity = free_list.get_and_step();
05266     ref_entity->marked(0);
05267   }
05268   CAST_LIST( free_list, body_list, Body );
05269   CAST_LIST( free_list, ref_face_list, RefFace);
05270   CAST_LIST( free_list, ref_edge_list, RefEdge);
05271   CAST_LIST( free_list, ref_vertex_list, RefVertex);
05272 }
05273 
05274 
05275 CubitStatus GeometryQueryTool::register_intermediate_engine(
05276   IntermediateGeomEngine* engine_ptr )
05277 {
05278   return (CubitStatus)igeSet.insert(engine_ptr).second;
05279 }
05280 
05281 void GeometryQueryTool::unregister_intermediate_engine(
05282   IntermediateGeomEngine* engine_ptr )
05283 {
05284   igeSet.erase(engine_ptr);
05285 }
05286 
05287 void GeometryQueryTool::ige_export_geom( DLIList<TopologyBridge*> &geom_list )
05288 {
05289   for (IGESet::reverse_iterator itor = igeSet.rbegin(); itor != igeSet.rend(); ++itor)
05290     (*itor)->export_geometry(geom_list);
05291 }
05292 
05293 void GeometryQueryTool::ige_push_imprint_attributes_before_modify
05294                                 ( DLIList<BodySM*> &geom_list )
05295 {
05296   for (IGESet::reverse_iterator itor = igeSet.rbegin(); itor != igeSet.rend(); ++itor)
05297     (*itor)->push_imprint_attributes_before_modify(geom_list);
05298 }
05299 
05300 void GeometryQueryTool::ige_push_named_attributes_to_curves_and_points
05301                                 ( DLIList<TopologyBridge*> &tb_list, const char *name_in )
05302 {
05303   for (IGESet::reverse_iterator itor = igeSet.rbegin(); itor != igeSet.rend(); ++itor)
05304     (*itor)->push_named_attributes_to_curves_and_points(tb_list, name_in);
05305 }
05306 
05307 void GeometryQueryTool::ige_remove_imprint_attributes_after_modify
05308                                 ( DLIList<BodySM*> &old_sms,
05309                                   DLIList<BodySM*> &new_sms )
05310 {
05311   for (IGESet::reverse_iterator itor = igeSet.rbegin(); itor != igeSet.rend(); ++itor)
05312     (*itor)->remove_imprint_attributes_after_modify(old_sms, new_sms);
05313 }
05314 
05315 bool GeometryQueryTool::ige_is_composite(TBOwner *bridge_owner)
05316 {
05317   bool ret = false;
05318   for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end() && ret != true; ++itor)
05319   {
05320     if((*itor)->is_composite(bridge_owner))
05321     {
05322       ret = true;
05323     }
05324   }
05325   return ret;
05326 }
05327 
05328 bool GeometryQueryTool::ige_is_composite(TopologyBridge *bridge)
05329 {
05330   bool ret = false;
05331   for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end() && ret != true; ++itor)
05332   {
05333     if((*itor)->is_composite(bridge))
05334     {
05335       ret = true;
05336     }
05337   }
05338   return ret;
05339 }
05340 
05341 
05342 bool GeometryQueryTool::ige_is_partition(TBOwner *bridge_owner)
05343 {
05344   bool ret = false;
05345   for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end() && ret != true; ++itor)
05346   {
05347     if((*itor)->is_partition(bridge_owner))
05348     {
05349       ret = true;
05350     }
05351   }
05352   return ret;
05353 }
05354 
05355 void GeometryQueryTool::ige_import_geom( DLIList<TopologyBridge*> &geom_list )
05356 {
05357   for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end(); ++itor)
05358     (*itor)->import_geometry(geom_list);
05359 }
05360 
05361 void GeometryQueryTool::get_tbs_with_bridge_manager_as_owner( TopologyBridge *source_bridge, 
05362                                                             DLIList<TopologyBridge*> &tbs )
05363 {
05364   for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end(); ++itor)
05365     (*itor)->get_tbs_with_bridge_manager_as_owner( source_bridge, tbs );
05366 }
05367 
05368 void GeometryQueryTool::ige_attribute_after_imprinting(DLIList<TopologyBridge*> &tb_list,
05369                                                        DLIList<Body*> &old_bodies)
05370 {
05371   for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end(); ++itor)
05372     (*itor)->attribute_after_imprinting(tb_list, old_bodies);
05373 }
05374 
05375 void GeometryQueryTool::ige_remove_attributes( DLIList<TopologyBridge*> &geom_list )
05376 {
05377   for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end(); ++itor)
05378     (*itor)->remove_attributes(geom_list);
05379 }
05380 
05381 void GeometryQueryTool::ige_remove_attributes_from_unmodifed_virtual(DLIList<TopologyBridge*> &bridges)
05382 {
05383   for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end(); ++itor)
05384     (*itor)->remove_attributes_from_unmodifed_virtual(bridges);
05385 }
05386 
05387 bool GeometryQueryTool::contains_intermediate_geometry(DLIList<RefEntity*>& ref_entity_list) const
05388 {
05389   // Unfortunately, the current implementation of partition creates virtual
05390   // bodies as well as virtual subentities.  Thus, we have to go up the tree
05391   // as well as down it.
05392   // TODO: Partitioning HAS got to change.  KGM 2/9/06
05393   //get the owning bodies
05394   DLIList<Body*> body_list;
05395   int j;
05396   for(j=ref_entity_list.size(); j--;)
05397   {
05398     TopologyEntity* te = dynamic_cast<TopologyEntity*>( ref_entity_list.get_and_step());
05399     te->bodies( body_list );
05400   }
05401   int i;
05402   for ( i = 0; i < body_list.size(); i++)
05403     if (GeometryQueryTool::instance()->
05404         is_intermediate_geometry(body_list.next(i)))
05405       return true;
05406 
05407   for ( i = 0; i < ref_entity_list.size(); i++)
05408     if (GeometryQueryTool::instance()->
05409         contains_intermediate_geometry(ref_entity_list.next(i)))
05410       return true;
05411 
05412   return false;
05413 }
05414 
05415 bool GeometryQueryTool::contains_intermediate_geometry(RefEntity* entity_ptr) const
05416 {
05417   if (igeSet.empty())
05418     return false;
05419 
05420   DLIList<RefEntity*> children;
05421   entity_ptr->get_all_child_ref_entities(children);
05422   children.append(entity_ptr);
05423 
05424   while(children.size())
05425     if (is_intermediate_geometry(children.pop()))
05426       return true;
05427 
05428   return false;
05429 }
05430 
05431 bool GeometryQueryTool::is_intermediate_geometry(RefEntity* entity_ptr) const
05432 {
05433   TopologyEntity* topo_ptr = CAST_TO(entity_ptr, TopologyEntity);
05434   if (!topo_ptr)
05435     return false;
05436 
05437   DLIList<TopologyBridge*> bridge_list;
05438   topo_ptr->bridge_manager()->get_bridge_list(bridge_list);
05439   while(bridge_list.size())
05440     if (is_intermediate_geometry(bridge_list.pop()))
05441       return true;
05442 
05443   return false;
05444 }
05445 
05446 bool GeometryQueryTool::is_intermediate_geometry( TopologyBridge* bridge ) const
05447 {
05448   if (bridge->get_geometry_query_engine() == NULL )
05449     return true;
05450   else
05451     return bridge->get_geometry_query_engine()->is_intermediate_engine();
05452 }
05453 
05454 
05455 //-------------------------------------------------------------------------
05456 // Purpose       : Destroy dead entity and dead children
05457 //
05458 // Special Notes :
05459 //
05460 // Creator       : Jason Kraftcheck
05461 //
05462 // Creation Date : 12/08/03
05463 //-------------------------------------------------------------------------
05464 CubitStatus GeometryQueryTool::destroy_dead_entity(
05465                                             TopologyEntity* topo_ent,
05466                                             bool top ) const
05467 {
05468   if (topo_ent->get_parents() || topo_ent->bridge_manager()->topology_bridge())
05469     return CUBIT_FAILURE;
05470 
05471   topo_ent->deactivated(CUBIT_TRUE);
05472 
05473   CubitObservable* ob = dynamic_cast<CubitObservable*>(topo_ent);
05474   if (ob)
05475   {
05476     if (dynamic_cast<RefEntity*>(topo_ent))
05477     {
05478         // "top" indicates if this call is the topmost call to this
05479         // recursive function.  It should be the case that if it is
05480         // the topmost call and the passed entity is a RefEntity, then
05481         // the entity was top-level (had no parent entities in the
05482         // topology graph.)  For cases where dead topology is cleaned
05483         // out and a dead RefEntity is not-top-most, it will have some
05484         // parent sense entity which this function will be called on and
05485         // that call will be the top-most one.
05486       if (top)
05487       {
05488         AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::TOP_LEVEL_ENTITY_DESTRUCTED, static_cast<RefEntity*>(ob)));
05489         CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_DELETED, static_cast<RefEntity*>(ob));
05490         const_cast<CGMHistory&>(mHistory).add_event(evt);
05491       }
05492       AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::TOPOLOGY_ENTITY_DESTRUCTED, static_cast<RefEntity*>(ob)));
05493     }
05494     else
05495       AppUtil::instance()->send_event(TopologyEvent(TopologyEvent::TOPOLOGY_ENTITY_DESTRUCTED, topo_ent));
05496   }
05497 
05498   DLIList<TopologyEntity*> child_list;
05499   topo_ent->disconnect_all_children(&child_list);
05500   child_list.reset();
05501   for (int i = child_list.size(); i--; )
05502   {
05503     TopologyEntity* child = child_list.get_and_step();
05504     TopologyEntity* child_topo_ent = dynamic_cast<TopologyEntity*>(child);
05505     if (child_topo_ent)
05506     {
05507       destroy_dead_entity(child_topo_ent, false);
05508       if (!child_topo_ent->deactivated() &&
05509            child_topo_ent->bridge_manager()->number_of_bridges() > 0 &&
05510            child_topo_ent->get_parents() == 0 &&
05511            NULL != (ob = dynamic_cast<CubitObservable*>(child_topo_ent)))
05512       {
05513         DLIList<TopologyBridge*> list1, list2;
05514         bool has_parents = false;
05515         child_topo_ent->bridge_manager()->get_bridge_list(list1);
05516         while (list1.size())
05517         {
05518           list2.clean_out();
05519           list1.pop()->get_parents(list2);
05520           if (list2.size())
05521             has_parents = true;
05522         }
05523         if (!has_parents)
05524         {
05525           AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::FREE_REF_ENTITY_GENERATED, static_cast<RefEntity*>(ob)));
05526           CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_CREATED, static_cast<RefEntity*>(ob));
05527           const_cast<CGMHistory&>(mHistory).add_event(evt);
05528         }
05529       }
05530     }
05531   }
05532 
05533   if (top)
05534     GeometryQueryTool::instance()->cleanout_deactivated_geometry();
05535 
05536   return CUBIT_SUCCESS;
05537 }
05538 
05539 // TODO - find out where this functionality belongs
05540 CubitStatus GeometryQueryTool::import_actuate(DLIList<RefEntity*> &entity_list)
05541 {
05542   int i;
05543 
05544     // given a Body list, actuates first the merge partner attribute
05545     // on all entities in the list, then actuates all other types of
05546     // attributes
05547 
05548   DLIList<TopologyEntity*> temp_list;
05549   DLIList<RefEntity*> refent_list;
05550 
05551   CubitBoolean auto_actuate_merge;
05552   auto_actuate_merge = CGMApp::instance()->attrib_manager()->auto_actuate_flag(CA_MERGE_PARTNER);
05553 
05554 
05555   if (auto_actuate_merge) {
05556 
05557       // Prevent MergeTool from destroying dead entities
05558       // after merging.  Otherwise we get stale pointers
05559       // in our lists.
05560       // Don't forget to turn this back on later!
05561     MergeTool::destroy_dead_geometry( false );
05562 
05563     DLIList<TopologyEntity*> me_list;
05564     CAST_LIST(entity_list, me_list, TopologyEntity);
05565 
05566     ModelQueryEngine *const mqe = ModelQueryEngine::instance();
05567 
05568     // vertices
05569     mqe->query_model(me_list, DagType::ref_vertex_type(), temp_list);
05570     CAST_LIST(temp_list, refent_list, RefEntity);
05571       // actuate merge attribute for vertices
05572     if (refent_list.size() > 0)
05573       refent_list.get()->actuate_cubit_attrib(refent_list, CA_MERGE_PARTNER);
05574 
05575     // edges
05576     temp_list.clean_out();
05577     refent_list.clean_out();
05578     mqe->query_model(me_list, DagType::ref_edge_type(), temp_list);
05579     CAST_LIST(temp_list, refent_list, RefEntity);
05580       // actuate merge attribute for edges
05581     if (refent_list.size() > 0)
05582       refent_list.get()->actuate_cubit_attrib(refent_list, CA_MERGE_PARTNER);
05583 
05584     // faces
05585     temp_list.clean_out();
05586     refent_list.clean_out();
05587     mqe->query_model(me_list, DagType::ref_face_type(), temp_list);
05588     CAST_LIST(temp_list, refent_list, RefEntity);
05589       // actuate merge attribute for faces
05590     if (refent_list.size() > 0)
05591       refent_list.get()->actuate_cubit_attrib(refent_list, CA_MERGE_PARTNER);
05592 
05593       // clean out entities destroyed during merge
05594     entity_list.reset();
05595     for( i = entity_list.size(); i--; )
05596     {
05597       TopologyEntity* me_ptr = dynamic_cast<TopologyEntity*>(entity_list.get());
05598       if( me_ptr && me_ptr->deactivated() )
05599         entity_list.extract();
05600       else
05601         entity_list.step();
05602     }
05603 
05604       // Restore merge tool setting, and clean up dead geometry
05605     MergeTool::destroy_dead_geometry( true );
05606     GeometryQueryTool::instance()->cleanout_deactivated_geometry();
05607   }
05608 
05609     // now actuate other attributes
05610   RefEntity* entity_ptr;
05611   CAActuateSet actuate_set( entity_list );
05612 
05613     // actuate in increasing dimension
05614     // (vtx = 0, ..., volume = 3, body = 4)
05615   for( i = 0; i < 5; i++ )
05616   {
05617     actuate_set.set_current_dimension( i );
05618     while( (entity_ptr = actuate_set.remove_next() ) != NULL )
05619       entity_ptr->auto_actuate_cubit_attrib(CUBIT_FALSE);
05620   }
05621 
05622     // actuate deferred attribs
05623   CADeferredAttrib::cleanup_cadas(CUBIT_TRUE, CUBIT_TRUE);
05624 
05625     // finally, actuate the attributes that go after all other geometry changes
05626   for( i = 0; i < 4; i++ )
05627   {
05628     actuate_set.set_current_dimension( i );
05629     while( (entity_ptr = actuate_set.remove_next() ) != NULL )
05630       entity_ptr->auto_actuate_cubit_attrib(CUBIT_FALSE, CUBIT_TRUE);
05631   }
05632 
05633   return CUBIT_SUCCESS;
05634 }
05635 
05636 CubitBoolean GeometryQueryTool::okay_to_transform( Body* body ) const
05637 {
05638   MergeTool* mt = MergeTool::instance();
05639   int i;
05640 
05641     // Check for merged vertices
05642   DLIList<RefVertex*> vertices;
05643   body->ref_vertices( vertices );
05644   for (i = vertices.size(); i--; )
05645     if ( mt->entity_merged( vertices.get_and_step() ) )
05646     {
05647       PRINT_ERROR("Cannot transform %s (Body %d) with merged geomtery.\n",
05648           body->entity_name().c_str(), body->id() );
05649       return CUBIT_FALSE;
05650     }
05651 
05652     // Need to check for merged surfaces because can have surfaces
05653     // w/out vertices.
05654   DLIList<RefFace*> surfaces;
05655   body->ref_faces( surfaces );
05656   for (i = surfaces.size(); i--; )
05657     if ( mt->entity_merged( surfaces.get_and_step() ) )
05658     {
05659       PRINT_ERROR("Cannot transform %s (Body %d) with merged geomtery.\n",
05660           body->entity_name().c_str(), body->id() );
05661       return CUBIT_FALSE;
05662     }
05663 
05664   return CUBIT_TRUE;
05665 }
05666 
05667 void GeometryQueryTool::translate( DLIList<RefEntity*> &entities_to_transform,
05668         double x, double y, double z, bool check_before_transforming,
05669         DLIList<RefEntity*> &entities_transformed,
05670         bool preview /*= false*/)
05671 {
05672   CubitVector delta(x,y,z);
05673 
05674   //translate free, merged-away entities first
05675   DLIList<TopologyBridge*> free_ents; 
05676   get_merged_away_free_entities( entities_to_transform, free_ents );
05677 
05678   int i;
05679   if (!preview)
05680   {
05681     for( i=free_ents.size(); i--; )
05682     {
05683       TopologyBridge *bridge = free_ents.get_and_step();
05684       Curve *curve= CAST_TO( bridge, Curve );
05685       TBPoint *point = CAST_TO( bridge, TBPoint );
05686 
05687       if( curve || point )
05688       {
05689         GeometryEntity *geom = CAST_TO( bridge, GeometryEntity );
05690         GeometryQueryEngine* engine = geom->get_geometry_query_engine();
05691         CubitStatus result = engine->translate( geom, delta );
05692         if (CUBIT_SUCCESS != result) {
05693           PRINT_ERROR("GeometryQueryEngine::translate failed.\n");
05694           return;
05695         }
05696       }
05697     }
05698   }
05699 
05700   RefFace *tmp_face;
05701   RefEdge *tmp_curve;
05702   RefVertex *tmp_vertex;
05703   CubitStatus result = CUBIT_SUCCESS;
05704 
05705   DLIList<Body*> bodies_to_translate;
05706   DLIList<BasicTopologyEntity*> ents_to_translate;
05707   CAST_LIST( entities_to_transform, bodies_to_translate, Body);
05708 
05709   if( bodies_to_translate.size() != entities_to_transform.size() )
05710   {
05711     for( int k=0; k<entities_to_transform.size(); k++ )
05712     {
05713       RefEntity *ent = entities_to_transform[k];
05714 
05715       if( ( tmp_face = CAST_TO( ent, RefFace ) ) != NULL )
05716         ents_to_translate.append( tmp_face );
05717       else if( (tmp_curve = CAST_TO( ent, RefEdge ) ) != NULL )
05718         ents_to_translate.append( tmp_curve );
05719       else if( (tmp_vertex = CAST_TO( ent, RefVertex ) ) != NULL )
05720         ents_to_translate.append( tmp_vertex );
05721     }
05722   }
05723 
05724 
05725   if( bodies_to_translate.size() )
05726   {
05727     DLIList<Body*> bodies_translated;
05728     result = translate( bodies_to_translate, 
05729       CubitVector(x,y,z), 
05730       &bodies_translated,
05731       check_before_transforming,
05732       preview );  
05733 
05734     if( result )
05735     {
05736       for( int k=0; k<bodies_translated.size(); k++ )
05737         entities_transformed.append( bodies_translated[k] );
05738     }
05739   }
05740 
05741   if( ents_to_translate.size() )
05742   {
05743     DLIList<BasicTopologyEntity*> btes_translated;
05744      result = translate( ents_to_translate, 
05745       CubitVector(x,y,z), 
05746       &btes_translated,
05747       check_before_transforming,
05748       preview );  
05749 
05750     if( result )
05751     {
05752       for( int k=0; k<btes_translated.size(); k++ )
05753         entities_transformed.append( btes_translated[k] );
05754     }
05755   }
05756 }
05757 
05758 
05759 CubitStatus GeometryQueryTool::translate( DLIList<Body*> &bodies,
05760                                           const CubitVector& delta,
05761                                           DLIList<Body*> *bodies_translated,
05762                                           bool check_to_transform,
05763                                           bool preview )
05764 {
05765   CubitTransformMatrix xform;
05766   xform.translate( delta );    
05767 
05768   DLIList<RefEntity*> ents_transformed;
05769 
05770   for( int k=0; k<bodies.size(); k++ )
05771   {
05772     Body *body = bodies[k];
05773 
05774     if( check_to_transform )
05775       if (!okay_to_transform( body ))
05776         continue;
05777 
05778     if (preview)
05779     {
05780       DLIList<RefEdge*> edges;
05781       body->ref_edges(edges);
05782       if( edges.size() )
05783       {
05784         for (int i = 0; i < edges.size(); i++)
05785         {
05786           GMem poly;
05787           if( CUBIT_SUCCESS == edges[i]->get_graphics(poly) )
05788           {
05789             poly.transform(xform);
05790             GfxPreview::draw_polyline(poly.point_list(), poly.point_list_size(), CUBIT_BLUE_INDEX);
05791           }
05792           else if( edges[i]->start_vertex() == edges[i]->end_vertex() )
05793           {
05794             CubitVector tmp_pt = edges[i]->start_vertex()->coordinates();
05795             tmp_pt = xform*tmp_pt;
05796             GfxPreview::draw_point( tmp_pt, CUBIT_BLUE_INDEX);
05797           }
05798         }
05799       }
05800       else
05801       {
05802         //just draw the surfaces
05803         DLIList<RefFace*> faces;
05804         body->ref_faces( faces );
05805         for( int i=0; i<faces.size(); i-- )
05806         {
05807           GMem poly;
05808           faces.get_and_step()->get_graphics( poly );
05809           poly.transform(xform);
05810 
05811           int* facet_list = poly.facet_list();
05812           GPoint* plist = poly.point_list();
05813 
05814           GPoint p[3];
05815           for (i = 0; i < poly.fListCount; )
05816           {
05817             int sides = facet_list[i++];
05818             if (sides != 3)
05819             {
05820               i += sides;
05821               continue;
05822             }
05823             else
05824             {
05825               p[0] = plist[facet_list[i++]];
05826               p[1] = plist[facet_list[i++]];
05827               p[2] = plist[facet_list[i++]];
05828               GfxPreview::draw_polygon(p, 3, CUBIT_BLUE_INDEX, CUBIT_BLUE_INDEX, false);
05829             }
05830           }
05831         }
05832       }
05833       GfxPreview::flush();
05834       continue;
05835     }
05836 
05837     BodySM* bodysm = body->get_body_sm_ptr();
05838     GeometryQueryEngine* engine = bodysm->get_geometry_query_engine();
05839     CubitStatus result = engine->translate( bodysm, delta );
05840     if (result)
05841     {
05842       notify_intermediate_of_transform( body, xform );
05843       
05844       if( bodies_translated )
05845         bodies_translated->append( body );
05846       ents_transformed.append( body );
05847     }
05848     else
05849       PRINT_ERROR("Translate of %s (%s %d) failed.\n",
05850       body->entity_name().c_str(), body->class_name(), body->id() );
05851   }
05852 
05853   if( ents_transformed.size() )
05854   {
05855     notify_observers_of_transform( ents_transformed, &xform );
05856     return CUBIT_SUCCESS;
05857   }
05858   else if( preview )
05859     return CUBIT_SUCCESS;
05860   else
05861     return CUBIT_FAILURE;  
05862 }
05863 
05864 CubitStatus GeometryQueryTool::rotate( DLIList<RefEntity*> &entities_to_transform,  
05865                       const CubitVector& point,
05866                       const CubitVector& direction,
05867                       double angle,
05868                       bool check_before_transforming,
05869                       DLIList<RefEntity*> &entities_transformed,
05870                       bool preview /*= false*/)
05871 {
05872   //rotate free, merged-away entities first
05873   DLIList<TopologyBridge*> free_ents; 
05874   get_merged_away_free_entities( entities_to_transform, free_ents );
05875   
05876   int i;
05877   if (!preview)
05878   {
05879     for( i=free_ents.size(); i--; )
05880     {
05881       TopologyBridge *bridge = free_ents.get_and_step();
05882       Curve *curve= CAST_TO( bridge, Curve );
05883       TBPoint *tmp_point = CAST_TO( bridge, TBPoint );
05884 
05885       if( curve || tmp_point )
05886       {
05887         GeometryEntity *geom = CAST_TO( bridge, GeometryEntity );
05888         GeometryQueryEngine* engine = geom->get_geometry_query_engine();
05889         CubitStatus result = engine->translate( geom, -point ); 
05890         if (CUBIT_SUCCESS != result) {
05891           PRINT_ERROR("GeometryQueryEngine::translate failed.\n");
05892           return result;
05893         }
05894         result = engine->rotate( geom, direction, angle ); 
05895         if (CUBIT_SUCCESS != result) {
05896           PRINT_ERROR("GeometryQueryEngine::rotate failed.\n");
05897           return result;
05898         }
05899         result = engine->translate( geom, point ); 
05900         if (CUBIT_SUCCESS != result) {
05901           PRINT_ERROR("GeometryQueryEngine::translate failed.\n");
05902           return result;
05903         }
05904       }
05905     }
05906   }
05907   
05908   RefFace *tmp_face;
05909   RefEdge *tmp_curve;
05910   RefVertex *tmp_vertex;
05911   CubitStatus result = CUBIT_SUCCESS;
05912 
05913   DLIList<Body*> bodies_to_rotate;
05914   DLIList<BasicTopologyEntity*> ents_to_rotate;
05915   CAST_LIST( entities_to_transform, bodies_to_rotate, Body);
05916 
05917   if( bodies_to_rotate.size() != entities_to_transform.size() )
05918   {
05919     for( int k=0; k<entities_to_transform.size(); k++ )
05920     {
05921       RefEntity *ent = entities_to_transform[k];
05922 
05923       if( ( tmp_face = CAST_TO( ent, RefFace ) ) != NULL )
05924         ents_to_rotate.append( tmp_face );
05925       else if( (tmp_curve = CAST_TO( ent, RefEdge ) ) != NULL )
05926         ents_to_rotate.append( tmp_curve );
05927       else if( (tmp_vertex = CAST_TO( ent, RefVertex ) ) != NULL )
05928         ents_to_rotate.append( tmp_vertex );
05929     }
05930   }
05931 
05932 
05933   if( bodies_to_rotate.size() )
05934   {
05935     DLIList<Body*> bodies_rotated;
05936     
05937     result = rotate( bodies_to_rotate, 
05938       point, direction, angle,
05939       &bodies_rotated,
05940       check_before_transforming, preview); 
05941 
05942     if( result )
05943     {
05944       for( int k=0; k<bodies_rotated.size(); k++ )
05945         entities_transformed.append( bodies_rotated[k] );
05946     }
05947   }
05948 
05949   if( ents_to_rotate.size() )
05950   {
05951     DLIList<BasicTopologyEntity*> btes_rotated;
05952     
05953      result = rotate( ents_to_rotate, 
05954       point,
05955       direction,
05956       angle,
05957       &btes_rotated,
05958       check_before_transforming,
05959       preview );  
05960 
05961     if( result )
05962     {
05963       for( int k=0; k<btes_rotated.size(); k++ )
05964         entities_transformed.append( btes_rotated[k] );
05965     }
05966   }
05967 
05968   if( entities_transformed.size() )
05969     return CUBIT_SUCCESS;
05970   else
05971     return CUBIT_FAILURE;
05972 }
05973 
05974 CubitStatus GeometryQueryTool::rotate( DLIList<Body*> &bodies,
05975                                        const CubitVector& axis,
05976                                        double angle,
05977                                        DLIList<Body*> *bodies_rotated,
05978                                        bool check_to_transform,
05979                                        bool preview )
05980 {
05981   CubitTransformMatrix xform;
05982   xform.rotate( angle, axis );
05983 
05984   DLIList<RefEntity*> ents_transformed;
05985 
05986   for( int k=0; k<bodies.size(); k++ )
05987   {
05988     Body *body = bodies[k];
05989 
05990     if( check_to_transform )
05991       if (!okay_to_transform( body ))
05992         continue;
05993 
05994     if (preview)
05995     {
05996       DLIList<RefEdge*> edges;
05997       body->ref_edges(edges);
05998       if( edges.size() )
05999       {
06000         for (int i = 0; i < edges.size(); i++)
06001         {
06002           GMem poly;
06003           if( CUBIT_SUCCESS == edges[i]->get_graphics(poly) )
06004           {
06005             poly.transform(xform);
06006             GfxPreview::draw_polyline(poly.point_list(), poly.point_list_size(), CUBIT_BLUE_INDEX);
06007           }
06008           else if( edges[i]->start_vertex() == edges[i]->end_vertex() )
06009           {
06010             CubitVector tmp_pt = edges[i]->start_vertex()->coordinates();
06011             tmp_pt = xform*tmp_pt;
06012             GfxPreview::draw_point( tmp_pt, CUBIT_BLUE_INDEX);
06013           }
06014         }
06015       }
06016       else
06017       {
06018         //just draw the surfaces
06019         DLIList<RefFace*> faces;
06020         body->ref_faces( faces );
06021         for( int i=0; i<faces.size(); i-- )
06022         {
06023           GMem poly;
06024           faces.get_and_step()->get_graphics( poly );
06025           poly.transform(xform);
06026 
06027           int* facet_list = poly.facet_list();
06028           GPoint* plist = poly.point_list();
06029 
06030           GPoint p[3];
06031           for (i = 0; i < poly.fListCount; )
06032           {
06033             int sides = facet_list[i++];
06034             if (sides != 3)
06035             {
06036               i += sides;
06037               continue;
06038             }
06039             else
06040             {
06041               p[0] = plist[facet_list[i++]];
06042               p[1] = plist[facet_list[i++]];
06043               p[2] = plist[facet_list[i++]];
06044               GfxPreview::draw_polygon(p, 3, CUBIT_BLUE_INDEX, CUBIT_BLUE_INDEX, false);
06045             }
06046           }
06047         }
06048       }
06049       GfxPreview::flush();
06050       continue;
06051     }
06052 
06053     BodySM* bodysm = body->get_body_sm_ptr();
06054     GeometryQueryEngine* engine = bodysm->get_geometry_query_engine();
06055     CubitStatus result = engine->rotate( bodysm, axis, angle );
06056 
06057     if (result)
06058     {
06059       notify_intermediate_of_transform( body, xform );
06060       
06061       if( bodies_rotated )
06062         bodies_rotated->append( body );
06063       ents_transformed.append( body );     
06064     }
06065     else
06066       PRINT_ERROR("Rotate of %s (%s %d) failed.\n",
06067       body->entity_name().c_str(), body->class_name(), body->id() );
06068   }
06069 
06070   if( ents_transformed.size() )
06071   {
06072     notify_observers_of_transform( ents_transformed, &xform );
06073     return CUBIT_SUCCESS;
06074   }
06075   else if( preview )
06076     return CUBIT_SUCCESS;
06077   else
06078     return CUBIT_FAILURE;
06079 }
06080 
06081 CubitStatus GeometryQueryTool::rotate( DLIList<Body*> &bodies,
06082                                        const CubitVector& point,
06083                                        const CubitVector& direction,
06084                                        double degrees,
06085                                        DLIList<Body*> *bodies_rotated,
06086                                        bool check_to_transform,
06087                                        bool preview /*=false*/)
06088 { 
06089   CubitTransformMatrix prev_xform;
06090   prev_xform.translate(-point);
06091 
06092   CubitTransformMatrix rot_mat;
06093   rot_mat.rotate( degrees, direction );
06094 
06095   CubitTransformMatrix mov_mat;
06096   mov_mat.translate( point );
06097   
06098   CubitTransformMatrix total_transform;
06099   total_transform = mov_mat*rot_mat*prev_xform;    
06100 
06101   DLIList<RefEntity*> ents_transformed;
06102 
06103   for( int k=0; k<bodies.size(); k++ )
06104   {
06105     Body *body = bodies[k];
06106 
06107     if( check_to_transform )
06108       if (!okay_to_transform( body ))
06109         continue;
06110 
06111     if (preview)
06112     {
06113       DLIList<RefEdge*> edges;
06114       body->ref_edges(edges);
06115       if( edges.size() )
06116       {
06117         for (int i = 0; i < edges.size(); i++)
06118         {
06119           GMem poly;
06120           if( CUBIT_SUCCESS == edges[i]->get_graphics(poly) )
06121           {
06122             poly.transform( total_transform );
06123             GfxPreview::draw_polyline(poly.point_list(), poly.point_list_size(), CUBIT_BLUE_INDEX);
06124           }
06125           else if( edges[i]->start_vertex() == edges[i]->end_vertex() )
06126           {
06127             CubitVector tmp_pt = edges[i]->start_vertex()->coordinates();          
06128             tmp_pt = total_transform*tmp_pt;
06129             GfxPreview::draw_point( tmp_pt, CUBIT_BLUE_INDEX);
06130           }
06131         }
06132       }
06133       else
06134       {
06135         //just draw the surfaces
06136         DLIList<RefFace*> faces;
06137         body->ref_faces( faces );
06138         for( int i=0; i<faces.size(); i-- )
06139         {
06140           GMem poly;
06141           faces.get_and_step()->get_graphics( poly );        
06142           poly.transform( total_transform );
06143 
06144           int* facet_list = poly.facet_list();
06145           GPoint* plist = poly.point_list();
06146 
06147           GPoint p[3];
06148           for (i = 0; i < poly.fListCount; )
06149           {
06150             int sides = facet_list[i++];
06151             if (sides != 3)
06152             {
06153               i += sides;
06154               continue;
06155             }
06156             else
06157             {
06158               p[0] = plist[facet_list[i++]];
06159               p[1] = plist[facet_list[i++]];
06160               p[2] = plist[facet_list[i++]];
06161               GfxPreview::draw_polygon(p, 3, CUBIT_BLUE_INDEX, CUBIT_BLUE_INDEX, false);
06162             }
06163           }
06164         }
06165       }
06166       GfxPreview::flush();
06167       continue;
06168     }
06169 
06170     BodySM* bodysm = body->get_body_sm_ptr();
06171     GeometryQueryEngine* engine = bodysm->get_geometry_query_engine();
06172     CubitStatus result = CUBIT_FAILURE;
06173 
06174     // Move to origin
06175     result = engine->translate( bodysm, -point );
06176 
06177     if (result)
06178     {
06179       CubitTransformMatrix xform;
06180       xform.translate( -point );
06181       notify_intermediate_of_transform( body, xform );
06182     }
06183     else
06184     {
06185       continue;
06186     }
06187 
06188     // Rotate about direction vector
06189     result = engine->rotate( bodysm, direction, degrees );
06190     if (result)
06191     {
06192       CubitTransformMatrix rot_mat;
06193       rot_mat.rotate( degrees, direction );
06194       notify_intermediate_of_transform( body, rot_mat );
06195     }
06196     else
06197     {
06198       continue;
06199     }
06200 
06201     result= engine->translate( bodysm, point );
06202     if (result)
06203     {
06204       CubitTransformMatrix xform;
06205       xform.translate( point );
06206       notify_intermediate_of_transform( body, xform );
06207 
06208       if( bodies_rotated )
06209         bodies_rotated->append( body );
06210       ents_transformed.append( body );  
06211     }
06212     else
06213     {
06214       continue;
06215     }
06216   }
06217 
06218   if( ents_transformed.size() )
06219   {
06220     notify_observers_of_transform( ents_transformed, &total_transform );
06221     return CUBIT_SUCCESS;
06222   }
06223   else if( preview )
06224     return CUBIT_SUCCESS;
06225   else
06226     return CUBIT_FAILURE;
06227 }
06228 
06229 void GeometryQueryTool::scale( DLIList<RefEntity*> &entities_to_transform, 
06230                               const CubitVector& point,
06231                               double scale_x, double scale_y, double scale_z, 
06232                               bool check_before_transforming, 
06233                               DLIList<RefEntity*> &entities_scaled,
06234                               bool preview /*= false*/)
06235 {
06236   CubitVector factors(scale_x, scale_y, scale_z);
06237 
06238   //scale free, merged-away entities first
06239   DLIList<TopologyBridge*> free_ents; 
06240   get_merged_away_free_entities( entities_to_transform, free_ents );
06241   int i;
06242   if (!preview)
06243   {
06244       for( i=free_ents.size(); i--; )
06245       {
06246           TopologyBridge *bridge = free_ents.get_and_step();
06247           Curve *curve= CAST_TO( bridge, Curve );
06248           TBPoint *tbpoint = CAST_TO( bridge, TBPoint );
06249 
06250           if( curve || tbpoint )
06251           {
06252               GeometryEntity *geom = CAST_TO( bridge, GeometryEntity );
06253               GeometryQueryEngine* engine = geom->get_geometry_query_engine();
06254               CubitStatus result = engine->translate( geom, -point );
06255               if (CUBIT_SUCCESS != result) {
06256                 PRINT_ERROR("GeometryQueryEngine::translate failed.\n");
06257                 return;
06258               }
06259               result = engine->scale( geom, factors );
06260               if (CUBIT_SUCCESS != result) {
06261                 PRINT_ERROR("GeometryQueryEngine::scale failed.\n");
06262                 return;
06263               }
06264               result = engine->translate( geom, point );
06265               if (CUBIT_SUCCESS != result) {
06266                 PRINT_ERROR("GeometryQueryEngine::translate failed.\n");
06267                 return;
06268               }
06269           }
06270       }
06271   }
06272   
06273 
06274   CubitStatus result = CUBIT_SUCCESS;
06275   for(i=entities_to_transform.size(); i--; )
06276   {
06277     RefEntity *tmp_ent = entities_to_transform.get_and_step();
06278     Body *tmp_body;
06279     RefFace* tmp_face;
06280     RefEdge *tmp_curve;
06281     RefVertex *tmp_vertex;
06282     if( ( tmp_body = CAST_TO( tmp_ent, Body ) ) != NULL )
06283     {
06284       //non-uniform scaling
06285       if( scale_x != scale_y ||
06286           scale_x != scale_z ||
06287           scale_y != scale_z )
06288       {
06289         // use GMT version for non-uniform scaling b/c it updates topology if it changes
06290  
06291         result = GeometryModifyTool::instance()->scale(tmp_body,point, factors, 
06292                                                   check_before_transforming, preview,false);
06293         tmp_ent = tmp_body;
06294       }
06295       else
06296         result = scale( tmp_body,point, CubitVector(scale_x, scale_y, scale_z),
06297                  check_before_transforming, preview);
06298     }
06299     else if( ( tmp_face = CAST_TO( tmp_ent, RefFace ) ) != NULL )
06300     {
06301      // only allow scaling of RefFaces if preview is on
06302      if (!preview)
06303          continue;
06304      result = scale( tmp_face,point, CubitVector(scale_x, scale_y, scale_z),
06305                 check_before_transforming, preview);
06306     }
06307     else if( ( tmp_curve = CAST_TO( tmp_ent, RefEdge ) ) != NULL )
06308     {
06309      result = scale( tmp_curve,point, CubitVector(scale_x, scale_y, scale_z),
06310                 check_before_transforming, preview);
06311     }
06312     else if( ( tmp_vertex = CAST_TO( tmp_ent, RefVertex ) ) != NULL )
06313     {
06314      result = scale( tmp_vertex,point, CubitVector(scale_x, scale_y, scale_z),
06315                 check_before_transforming, preview);
06316     }
06317     if(result)
06318       entities_scaled.append( tmp_ent );
06319   } 
06320   
06321 }
06322 
06323 
06324 CubitStatus GeometryQueryTool::scale( Body* body,const CubitVector& point, double factor, bool check_to_transform, bool preview )
06325 {
06326   if( check_to_transform )
06327     if (!okay_to_transform( body ))
06328       return CUBIT_FAILURE;
06329 
06330   CubitTransformMatrix pre_form;
06331   pre_form.translate( -point );
06332 
06333   CubitTransformMatrix xform;
06334   xform.scale_about_origin( factor );
06335 
06336   CubitTransformMatrix post_form;
06337   post_form.translate( point );
06338 
06339  if (preview)
06340   {
06341     DLIList<RefEdge*> edges;
06342     body->ref_edges(edges);
06343     if( edges.size() )
06344     {
06345       for (int i = 0; i < edges.size(); i++)
06346       {
06347         GMem poly;
06348         if( CUBIT_SUCCESS == edges[i]->get_graphics(poly) )
06349         {
06350           poly.transform(pre_form);
06351           poly.transform(xform);
06352           poly.transform(post_form);
06353           GfxPreview::draw_polyline(poly.point_list(), poly.point_list_size(), CUBIT_BLUE_INDEX);
06354         }
06355         else if( edges[i]->start_vertex() == edges[i]->end_vertex() )
06356         {
06357           CubitVector tmp_pt = edges[i]->start_vertex()->coordinates();
06358           tmp_pt = pre_form*tmp_pt;
06359           tmp_pt = xform*tmp_pt;
06360           tmp_pt = post_form*tmp_pt;          
06361           GfxPreview::draw_point( tmp_pt, CUBIT_BLUE_INDEX);
06362         }
06363       }
06364     }
06365     else
06366     {
06367       //just draw the surfaces
06368       DLIList<RefFace*> faces;
06369       body->ref_faces( faces );
06370       for( int i=0; i<faces.size(); i-- )
06371       {
06372         GMem poly;
06373         faces.get_and_step()->get_graphics( poly );
06374         poly.transform(pre_form);
06375         poly.transform(xform);
06376         poly.transform(post_form);
06377 
06378         int* facet_list = poly.facet_list();
06379         GPoint* plist = poly.point_list();
06380         
06381         GPoint p[3];
06382         for (i = 0; i < poly.fListCount; )
06383         {
06384           int sides = facet_list[i++];
06385           if (sides != 3)
06386           {
06387             i += sides;
06388             continue;
06389           }
06390           else
06391           {
06392             p[0] = plist[facet_list[i++]];
06393             p[1] = plist[facet_list[i++]];
06394             p[2] = plist[facet_list[i++]];
06395             GfxPreview::draw_polygon(p, 3, CUBIT_BLUE_INDEX, CUBIT_BLUE_INDEX, false);
06396           }
06397         }
06398       }
06399     }
06400     GfxPreview::flush();
06401     return CUBIT_SUCCESS;
06402   }
06403 
06404 
06405 
06406   //if (preview)
06407   //{
06408   //  DLIList<RefEdge*> edges;
06409   //  body->ref_edges(edges);
06410   //  for (int i = 0; i < edges.size(); i++)
06411   //  {
06412   //    GMem poly;
06413   //    edges[i]->get_graphics(poly);
06414   //    poly.transform(pre_form);
06415   //    poly.transform(xform);
06416   //    poly.transform(post_form);
06417   //    GfxPreview::draw_polyline(poly.point_list(), poly.point_list_size(), CUBIT_BLUE_INDEX);
06418   //  }
06419   //  GfxPreview::flush();
06420   //  return CUBIT_SUCCESS;
06421   //}
06422 
06423   BodySM* bodysm = body->get_body_sm_ptr();
06424   GeometryQueryEngine* engine = bodysm->get_geometry_query_engine();
06425   CubitStatus result = engine->translate( bodysm, -point );
06426   if (result)
06427   {
06428     notify_intermediate_of_transform( body, pre_form );
06429   }
06430   else
06431     PRINT_ERROR("Scale of %s (%s %d) failed.\n",
06432       body->entity_name().c_str(), body->class_name(), body->id() );
06433 
06434 
06435   result = engine->scale( bodysm, factor );
06436   if (result)
06437   {
06438     notify_intermediate_of_transform( body, xform );
06439   }
06440   else
06441     PRINT_ERROR("Scale of %s (%s %d) failed.\n",
06442       body->entity_name().c_str(), body->class_name(), body->id() );
06443 
06444   result = engine->translate( bodysm, point );
06445   if (result)
06446   {
06447     notify_intermediate_of_transform( body, post_form );
06448   }
06449   else
06450     PRINT_ERROR("Scale of %s (%s %d) failed.\n",
06451       body->entity_name().c_str(), body->class_name(), body->id() );
06452   
06453   notify_observers_of_transform( body );
06454 
06455   return result;
06456 }
06457 
06458 CubitStatus GeometryQueryTool::scale( Body *body,
06459                                      const CubitVector& point,
06460                                       const CubitVector& factors,
06461                                       bool check_to_transform,
06462                                       bool preview )
06463 {
06464   if( check_to_transform )
06465     if (!okay_to_transform( body ))
06466       return CUBIT_FAILURE;
06467 
06468   CubitTransformMatrix pre_form;
06469   pre_form.translate( -point );
06470 
06471   CubitTransformMatrix xform;
06472   xform.scale_about_origin( factors );
06473 
06474   CubitTransformMatrix post_form;
06475   post_form.translate( point );
06476 
06477   if (preview)
06478   {
06479     DLIList<RefEdge*> edges;
06480     body->ref_edges(edges);
06481     if( edges.size() )
06482     {
06483       for (int i = 0; i < edges.size(); i++)
06484       {
06485         GMem poly;
06486         if( CUBIT_SUCCESS == edges[i]->get_graphics(poly) )
06487         {
06488           poly.transform(pre_form);
06489           poly.transform(xform);
06490           poly.transform(post_form);
06491           GfxPreview::draw_polyline(poly.point_list(), poly.point_list_size(), CUBIT_BLUE_INDEX);
06492         }
06493         else if( edges[i]->start_vertex() == edges[i]->end_vertex() )
06494         {
06495           CubitVector tmp_pt = edges[i]->start_vertex()->coordinates();
06496           tmp_pt = pre_form*tmp_pt;
06497           tmp_pt = xform*tmp_pt;
06498           tmp_pt = post_form*tmp_pt;          
06499           GfxPreview::draw_point( tmp_pt, CUBIT_BLUE_INDEX);
06500         }
06501       }
06502     }
06503     else
06504     {
06505       //just draw the surfaces
06506       DLIList<RefFace*> faces;
06507       body->ref_faces( faces );
06508       for( int i=0; i<faces.size(); i-- )
06509       {
06510         GMem poly;
06511         faces.get_and_step()->get_graphics( poly );
06512         poly.transform(pre_form);
06513         poly.transform(xform);
06514         poly.transform(post_form);
06515 
06516         int* facet_list = poly.facet_list();
06517         GPoint* plist = poly.point_list();
06518 
06519         GPoint p[3];
06520         for (i = 0; i < poly.fListCount; )
06521         {
06522           int sides = facet_list[i++];
06523           if (sides != 3)
06524           {
06525             i += sides;
06526             continue;
06527           }
06528           else
06529           {
06530             p[0] = plist[facet_list[i++]];
06531             p[1] = plist[facet_list[i++]];
06532             p[2] = plist[facet_list[i++]];
06533             GfxPreview::draw_polygon(p, 3, CUBIT_BLUE_INDEX, CUBIT_BLUE_INDEX, false);
06534           }
06535         }
06536       }
06537     }
06538 
06539     GfxPreview::flush();
06540     return CUBIT_SUCCESS;
06541   }
06542 
06543   BodySM* bodysm = body->get_body_sm_ptr();
06544   GeometryQueryEngine* engine = bodysm->get_geometry_query_engine();
06545 
06546   CubitStatus result = engine->translate( bodysm, -point );
06547   if (result)
06548   {
06549     notify_intermediate_of_transform( body, pre_form );
06550   }
06551   else
06552     PRINT_ERROR("Scale of %s (%s %d) failed.\n",
06553       body->entity_name().c_str(), body->class_name(), body->id() );
06554 
06555 
06556   result = engine->scale( bodysm, factors );
06557   if (result)
06558   {
06559     notify_intermediate_of_transform( body, xform );
06560   }
06561   else
06562     PRINT_ERROR("Scale of %s (%s %d) failed.\n",
06563       body->entity_name().c_str(), body->class_name(), body->id() );
06564 
06565   result = engine->translate( bodysm, point );
06566   if (result)
06567   {
06568     notify_intermediate_of_transform( body, post_form );
06569   }
06570   else
06571     PRINT_ERROR("Scale of %s (%s %d) failed.\n",
06572       body->entity_name().c_str(), body->class_name(), body->id() );
06573   
06574   notify_observers_of_transform( body );
06575 
06576   return result;
06577 }
06578 
06579 void GeometryQueryTool::reflect( DLIList<RefEntity*> &entities_to_reflect,
06580                                 const CubitVector& point,
06581                                 const CubitVector& normal,
06582                             bool check_before_transforming,
06583                             DLIList<RefEntity*> &entities_transformed,
06584                             bool preview /*= false*/)
06585 {
06586   //reflect free, merged-away entities
06587   DLIList<TopologyBridge*> free_ents; 
06588   get_merged_away_free_entities( entities_to_reflect, free_ents );
06589   
06590   int i;
06591   if (!preview)
06592   {
06593     for( i=free_ents.size(); i--; )
06594     {
06595       TopologyBridge *bridge = free_ents.get_and_step();
06596       Curve *curve= CAST_TO( bridge, Curve );
06597       TBPoint *tmp_point = CAST_TO( bridge, TBPoint );
06598 
06599       if( curve || tmp_point )
06600       {
06601         GeometryEntity *geom = CAST_TO( bridge, GeometryEntity );
06602         GeometryQueryEngine* engine = geom->get_geometry_query_engine();
06603         CubitStatus result = engine->translate( geom, -point ); 
06604         if (CUBIT_SUCCESS != result) {
06605           PRINT_ERROR("GeometryQueryEngine::translate failed.\n");
06606           return;
06607         }
06608         result = engine->reflect( geom, normal ); 
06609         if (CUBIT_SUCCESS != result) {
06610           PRINT_ERROR("GeometryQueryEngine::reflect failed.\n");
06611           return;
06612         }
06613         result = engine->translate( geom, point ); 
06614         if (CUBIT_SUCCESS != result) {
06615           PRINT_ERROR("GeometryQueryEngine::translate failed.\n");
06616           return;
06617         }
06618       }
06619     }
06620   }
06621 
06622   RefFace *tmp_face;
06623   RefEdge *tmp_curve;
06624   RefVertex *tmp_vertex;
06625   CubitStatus result;
06626 
06627   DLIList<Body*> bodies_to_reflect;
06628   DLIList<BasicTopologyEntity*> ents_to_reflect;
06629   CAST_LIST( entities_to_reflect, bodies_to_reflect, Body);
06630 
06631   if( bodies_to_reflect.size() != entities_to_reflect.size() )
06632   {
06633     for( int k=0; k<entities_to_reflect.size(); k++ )
06634     {
06635       RefEntity *ent = entities_to_reflect[k];
06636 
06637       if( ( tmp_face = CAST_TO( ent, RefFace ) ) != NULL )
06638         ents_to_reflect.append( tmp_face );
06639       else if( (tmp_curve = CAST_TO( ent, RefEdge ) ) != NULL )
06640         ents_to_reflect.append( tmp_curve );
06641       else if( (tmp_vertex = CAST_TO( ent, RefVertex ) ) != NULL )
06642         ents_to_reflect.append( tmp_vertex );
06643     }
06644   }
06645 
06646   if( bodies_to_reflect.size() )
06647   {
06648     DLIList<Body*> bodies_reflected;
06649     result = reflect( bodies_to_reflect,
06650       point, normal, 
06651       &bodies_reflected,      
06652       preview );  
06653 
06654     if( result )
06655     {
06656       for( int k=0; k<bodies_reflected.size(); k++ )
06657         entities_transformed.append( bodies_reflected[k] );
06658     }
06659   }
06660 
06661   if( ents_to_reflect.size() )
06662   {
06663     DLIList<BasicTopologyEntity*> btes_reflected;
06664      result = reflect( ents_to_reflect, 
06665       point,
06666       normal,
06667       &btes_reflected,
06668       check_before_transforming,
06669       preview );  
06670 
06671     if( result )
06672     {
06673       for( int k=0; k<btes_reflected.size(); k++ )
06674         entities_transformed.append( btes_reflected[k] );
06675     }
06676   }
06677 }
06678 
06679 CubitStatus GeometryQueryTool::reflect( DLIList<Body*> &bodies,
06680                                         const CubitVector& point,
06681                                         const CubitVector& normal,
06682                                         DLIList<Body*> *bodies_reflected,
06683                                         bool preview)
06684 {
06685   Body *tmp_body;
06686   CubitStatus result = CUBIT_FAILURE;
06687 
06688   CubitTransformMatrix prev_xform;
06689   prev_xform.translate(-point);
06690 
06691   CubitTransformMatrix ref_mat;
06692   ref_mat.reflect(normal );
06693 
06694   CubitTransformMatrix mov_mat;
06695   mov_mat.translate( point );
06696 
06697   CubitTransformMatrix total_transform;
06698   total_transform = mov_mat*ref_mat*prev_xform;
06699   
06700   DLIList<RefEntity*> ents_transformed;
06701 
06702   if (preview)
06703   {
06704     for (int i = 0; i < bodies.size(); i++)
06705     {
06706       DLIList<RefEdge*> edges;
06707       bodies[i]->ref_edges(edges);
06708       if( edges.size() )
06709       {
06710         for (int i = 0; i < edges.size(); i++)
06711         {
06712           GMem poly;
06713           if( CUBIT_SUCCESS == edges[i]->get_graphics(poly) )
06714           {
06715             poly.transform( total_transform );
06716             GfxPreview::draw_polyline(poly.point_list(), poly.point_list_size(), CUBIT_BLUE_INDEX);
06717           }
06718           else if( edges[i]->start_vertex() == edges[i]->end_vertex() )
06719           {
06720             CubitVector tmp_pt = edges[i]->start_vertex()->coordinates();            
06721             tmp_pt = total_transform*tmp_pt;
06722             GfxPreview::draw_point( tmp_pt, CUBIT_BLUE_INDEX);
06723           }
06724         }
06725       }
06726       else
06727       {
06728         //just draw the surfaces
06729         DLIList<RefFace*> faces;
06730         bodies[i]->ref_faces( faces );
06731         for( int i=0; i<faces.size(); i-- )
06732         {
06733           GMem poly;
06734           faces.get_and_step()->get_graphics( poly );
06735           poly.transform( total_transform );
06736 
06737           int* facet_list = poly.facet_list();
06738           GPoint* plist = poly.point_list();
06739 
06740           GPoint p[3];
06741           for (i = 0; i < poly.fListCount; )
06742           {
06743             int sides = facet_list[i++];
06744             if (sides != 3)
06745             {
06746               i += sides;
06747               continue;
06748             }
06749             else
06750             {
06751               p[0] = plist[facet_list[i++]];
06752               p[1] = plist[facet_list[i++]];
06753               p[2] = plist[facet_list[i++]];
06754               GfxPreview::draw_polygon(p, 3, CUBIT_BLUE_INDEX, CUBIT_BLUE_INDEX, false);
06755             }
06756           }
06757         }
06758       }
06759       GfxPreview::flush();
06760     }
06761     return CUBIT_SUCCESS;
06762   }
06763   //first, reflect the underlying geometry
06764   int i;
06765   for( i=bodies.size(); i--;)
06766   {
06767     tmp_body = bodies.get_and_step();
06768     BodySM* bodysm = tmp_body->get_body_sm_ptr();
06769     GeometryQueryEngine* engine = bodysm->get_geometry_query_engine();
06770 
06771     // Move to origin
06772     result = engine->translate( bodysm, -point );
06773     if (result)
06774     {
06775       CubitTransformMatrix xform;
06776       xform.translate( -point );
06777       notify_intermediate_of_transform( tmp_body, xform );
06778     }
06779     else
06780     {
06781       PRINT_ERROR("Reflect of %s (%s %d) failed.\n",
06782         tmp_body->entity_name().c_str(), tmp_body->class_name(), tmp_body->id() );
06783       return result;
06784     }
06785 
06786     result = engine->reflect( bodysm, normal );
06787     if (result)
06788     {
06789       CubitTransformMatrix xform;
06790       xform.reflect( normal);
06791       notify_intermediate_of_transform( tmp_body, xform );
06792     }
06793     else
06794     {
06795       PRINT_ERROR("Reflect of %s (%s %d) failed.\n",
06796         tmp_body->entity_name().c_str(), tmp_body->class_name(), tmp_body->id() );
06797       return result;
06798     }
06799     
06800     result = engine->translate( bodysm, point );
06801     if (result)
06802     {
06803       CubitTransformMatrix xform;
06804       xform.translate( point );
06805       notify_intermediate_of_transform( tmp_body, xform );
06806 
06807       if( bodies_reflected )
06808         bodies_reflected->append( tmp_body );
06809       ents_transformed.append( tmp_body );
06810     }
06811     else
06812     {
06813       PRINT_ERROR("Reflect of %s (%s %d) failed.\n",
06814         tmp_body->entity_name().c_str(), tmp_body->class_name(), tmp_body->id() );
06815       return result;
06816     }
06817   }
06818     
06819   for( i=0; i<ents_transformed.size(); i++)
06820   {
06821     tmp_body = (Body*)ents_transformed[i];
06822     tmp_body = make_Body( tmp_body->get_body_sm_ptr() );
06823     if( tmp_body != ents_transformed[i] )
06824       ents_transformed[i] = tmp_body;
06825   }
06826 
06827   if( ents_transformed.size() )
06828   {
06829     notify_observers_of_transform( ents_transformed, &total_transform );
06830     return CUBIT_SUCCESS;
06831   }
06832   else if( preview )
06833     return CUBIT_SUCCESS;
06834   else
06835     return CUBIT_FAILURE;    
06836 }
06837 
06838 CubitStatus GeometryQueryTool::notify_intermediate_of_transform(
06839                                         TopologyEntity* entity,
06840                                         const CubitTransformMatrix& xform ) const
06841 {
06842   for (IGESet::const_iterator iter = igeSet.begin(); iter != igeSet.end(); ++iter)
06843     (*iter)->notify_transform( entity->bridge_manager()->topology_bridge(), xform );
06844   return CUBIT_SUCCESS;
06845 }
06846 
06847 void GeometryQueryTool::notify_observers_of_transform(
06848                                         DLIList<RefEntity*> &ref_ents,
06849                                         const CubitTransformMatrix *xform ) const
06850 {
06851   if( xform )
06852   {
06853     //gather all the children
06854     DLIList<RefEntity*> all_ref_ents;
06855     RefEntity::get_all_child_ref_entities( ref_ents, all_ref_ents );   
06856     all_ref_ents.uniquify_ordered();
06857 
06858     all_ref_ents += ref_ents;
06859 
06860     for(int i=0; i<all_ref_ents.size(); i++)
06861     {
06862       GeometryEvent evt(GeometryEvent::GEOMETRY_TRANSFORMED, all_ref_ents[i]);
06863       all_ref_ents[i]->notify_observers(&evt);
06864     }
06865 
06866     AppUtil::instance()->send_event(TransformEvent(*xform, all_ref_ents.as_vector() ));    
06867   }
06868   else
06869   {
06870     for( int i=0; i<ref_ents.size(); i++ )
06871     {
06872       RefEntity *ent = ref_ents[i];
06873       ent->notify_sub_all_observers( GeometryEvent::GEOMETRY_MODIFIED );    
06874     }
06875   }
06876 }
06877 
06878 void GeometryQueryTool::notify_observers_of_transform(
06879                                         RefEntity* ref_entity,
06880                                         const CubitTransformMatrix *xform ) const
06881 {
06882   ref_entity->notify_sub_all_observers( GeometryEvent::GEOMETRY_MODIFIED );
06883   
06884   //CGMHistory::Event evt(CGMHistory::GEOMETRY_TRANSFORMED, ref_entity);
06885   //const_cast<CGMHistory&>(mHistory).add_event(evt);
06886 }
06887 
06888 CubitBoolean GeometryQueryTool::okay_to_transform( BasicTopologyEntity* bte ) const
06889 {
06890   if (bte->get_parents() > 0)
06891   {
06892     PRINT_ERROR("Cannot transform %s (%s %d) : not a free %s\n",
06893       bte->entity_name().c_str(), bte->class_name(), bte->id(), bte->class_name() );
06894     return CUBIT_FALSE;
06895   }
06896 
06897   DLIList<RefEntity*> list(1);
06898   list.append( bte );
06899   if (MergeTool::instance()->contains_merged_entities( list ))
06900   {
06901     PRINT_ERROR("Cannot tranmform %s (%s %d) : "
06902                 "%s is merged or contains merged geomtry.\n",
06903       bte->entity_name().c_str(), bte->class_name(), bte->id(), bte->class_name() );
06904     return CUBIT_FALSE;
06905   }
06906 
06907   return CUBIT_TRUE;
06908 }
06909 
06910 CubitStatus GeometryQueryTool::translate( DLIList<BasicTopologyEntity*> &btes,
06911                                           const CubitVector& delta,
06912                                           DLIList<BasicTopologyEntity*> *btes_translated,
06913                                           bool check_to_transform,
06914                                           bool preview )
06915 {
06916   CubitTransformMatrix xform;
06917   xform.translate(delta);
06918 
06919   DLIList<RefEntity*> transformed_ents;
06920 
06921   for( int k=0; k<btes.size(); k++ )
06922   {
06923     BasicTopologyEntity *bte = btes[k];
06924 
06925     if( check_to_transform )
06926       if (!okay_to_transform( bte ))
06927         continue;
06928 
06929     if (preview)
06930     {
06931       if(bte->dimension()==0)
06932       {
06933         DLIList<RefVertex*> points;
06934         bte->ref_vertices(points);
06935         for (int i = 0; i < points.size(); i++)
06936         {
06937           CubitVector temp(points[i]->center_point());
06938           temp = xform*temp;
06939           GfxPreview::draw_point(temp, CUBIT_BLUE_INDEX);
06940         }
06941       }
06942       else
06943       {
06944         DLIList<RefEdge*> edges;
06945         bte->ref_edges(edges);
06946         for (int i = 0; i < edges.size(); i++)
06947         {
06948           GMem poly;
06949           if( CUBIT_SUCCESS == edges[i]->get_graphics(poly) )
06950           {
06951             poly.transform(xform);
06952             GfxPreview::draw_polyline(poly.point_list(), poly.point_list_size(), CUBIT_BLUE_INDEX);
06953           }
06954           else if( edges[i]->start_vertex() == edges[i]->end_vertex() )
06955           {
06956             CubitVector tmp_pt = edges[i]->start_vertex()->coordinates();
06957             tmp_pt = xform*tmp_pt;
06958             GfxPreview::draw_point( tmp_pt, CUBIT_BLUE_INDEX);
06959           }
06960         }
06961         if (edges.size() == 0)
06962         {
06963           DLIList<RefVertex*> points;
06964           bte->ref_vertices(points);
06965           for (int i = 0; i < points.size(); i++)
06966           {
06967             CubitVector temp(points[i]->center_point());
06968             temp=xform*temp;
06969             GfxPreview::draw_point(temp, CUBIT_BLUE_INDEX);
06970           }
06971         }
06972       }
06973       GfxPreview::flush();
06974       continue;
06975     }
06976 
06977     GeometryEntity* geom = bte->get_geometry_entity_ptr();
06978     GeometryQueryEngine* engine = geom->get_geometry_query_engine();
06979     CubitStatus result = engine->translate( geom, delta );
06980     if (result)
06981     {
06982       notify_intermediate_of_transform( bte, xform );
06983       
06984       if( btes_translated )
06985         btes_translated->append( bte );
06986       transformed_ents.append( bte );
06987     }
06988     else
06989       PRINT_ERROR("Translate of %s (%s %d) failed.\n",
06990       bte->entity_name().c_str(), bte->class_name(), bte->id() );
06991   }
06992 
06993   if( transformed_ents.size() )
06994   {
06995     notify_observers_of_transform( transformed_ents, &xform );
06996     return CUBIT_SUCCESS;
06997   }
06998   else if( preview )
06999     return CUBIT_SUCCESS;
07000   else
07001     return CUBIT_FAILURE;
07002 }
07003 
07004 CubitStatus GeometryQueryTool::rotate( DLIList<BasicTopologyEntity*> &btes,
07005                                        const CubitVector& point,
07006                                        const CubitVector& direction,
07007                                        double angle,
07008                                        DLIList<BasicTopologyEntity*> *btes_rotated,
07009                                        bool check_to_transform,
07010                                        bool preview )
07011 {
07012   CubitTransformMatrix prev_xform;
07013   prev_xform.translate(-point);
07014 
07015   CubitTransformMatrix rot_mat;
07016   rot_mat.rotate( angle, direction );
07017 
07018   CubitTransformMatrix mov_mat;
07019   mov_mat.translate( point );
07020   
07021   CubitTransformMatrix total_transform;
07022   total_transform = mov_mat*rot_mat*prev_xform;  
07023 
07024   DLIList<RefEntity*> ents_transformed;
07025 
07026   for( int k=0; k<btes.size(); k++ )
07027   {
07028     BasicTopologyEntity *bte = btes[k];
07029 
07030     if( check_to_transform )
07031       if (!okay_to_transform( bte ))
07032         continue;
07033 
07034     if (preview)
07035     {
07036       if(bte->dimension()==0)
07037       {
07038         DLIList<RefVertex*> points;
07039         bte->ref_vertices(points);
07040         for (int i = 0; i < points.size(); i++)
07041         {
07042           CubitVector temp(points[i]->center_point());        
07043           temp = total_transform*temp;
07044           GfxPreview::draw_point(temp, CUBIT_BLUE_INDEX);
07045         }
07046       }
07047       else
07048       {
07049 
07050         DLIList<RefEdge*> edges;
07051         bte->ref_edges(edges);
07052 
07053         for (int j = 0; j < edges.size(); j++)
07054         {
07055           GMem poly;
07056           if( CUBIT_SUCCESS == edges[j]->get_graphics(poly) )
07057           {          
07058             poly.transform(total_transform);
07059             GfxPreview::draw_polyline(poly.point_list(), poly.point_list_size(), CUBIT_BLUE_INDEX);
07060           }
07061           else if( edges[j]->start_vertex() == edges[j]->end_vertex() )
07062           {
07063             CubitVector tmp_pt = edges[j]->start_vertex()->coordinates(); 
07064             tmp_pt = total_transform*tmp_pt;          
07065             GfxPreview::draw_point( tmp_pt, CUBIT_BLUE_INDEX);
07066           }
07067         }
07068         if (edges.size() == 0)
07069         {
07070           DLIList<RefVertex*> points;
07071           bte->ref_vertices(points);
07072           for (int i = 0; i < points.size(); i++)
07073           {
07074             CubitVector p(points[i]->center_point());          
07075             p = total_transform*p;
07076             GfxPreview::draw_point(p, CUBIT_BLUE_INDEX);
07077           }
07078         }
07079       }
07080 
07081       GfxPreview::flush();
07082       continue;
07083     }
07084 
07085     GeometryEntity* geom = bte->get_geometry_entity_ptr();
07086     GeometryQueryEngine* engine = geom->get_geometry_query_engine();
07087     CubitStatus result;
07088     // Move to origin
07089     result = engine->translate( geom, -point );
07090     if (result)
07091     {
07092       CubitTransformMatrix xform;
07093       xform.translate( -point );
07094       notify_intermediate_of_transform( bte, xform );
07095     }
07096     else
07097     {
07098       PRINT_ERROR("Rotate of %s (%s %d) failed.\n",
07099         bte->entity_name().c_str(), bte->class_name(), bte->id() );
07100       continue;
07101     }
07102 
07103     result = engine->rotate( geom, direction, angle );
07104     if (result)
07105     {
07106       CubitTransformMatrix rot_mat;
07107       rot_mat.rotate( angle, direction );
07108       notify_intermediate_of_transform( bte, rot_mat );
07109     }
07110     else
07111     {
07112       PRINT_ERROR("Rotate of %s (%s %d) failed.\n",
07113         bte->entity_name().c_str(), bte->class_name(), bte->id() );
07114       continue;
07115     }
07116     result=engine->translate( geom, point );
07117 
07118     if (result)
07119     {
07120       CubitTransformMatrix mov_mat;
07121       mov_mat.translate( point );
07122       notify_intermediate_of_transform( bte, mov_mat );
07123 
07124       if( btes_rotated )
07125         btes_rotated->append( bte );
07126       ents_transformed.append( bte );
07127     }
07128     else
07129     {
07130       PRINT_ERROR("Rotate of %s (%s %d) failed.\n",
07131         bte->entity_name().c_str(), bte->class_name(), bte->id() );
07132       continue;
07133     }
07134   }
07135 
07136   if( ents_transformed.size() )
07137   {
07138     notify_observers_of_transform( ents_transformed, &total_transform );
07139     return CUBIT_SUCCESS;
07140   }
07141    else if( preview )
07142     return CUBIT_SUCCESS;
07143   else
07144     return CUBIT_FAILURE;
07145 }
07146 
07147 CubitStatus GeometryQueryTool::rotate( DLIList<BasicTopologyEntity*> &btes,
07148                                        const CubitVector& axis,
07149                                        double angle,
07150                                        DLIList<BasicTopologyEntity*> *btes_rotated,
07151                                        bool check_to_transform,
07152                                        bool preview )
07153 { 
07154   CubitTransformMatrix xform;
07155   xform.rotate( angle, axis );
07156 
07157   DLIList<RefEntity*> ents_transformed;
07158 
07159   for( int k=0; k<btes.size(); k++ )
07160   {
07161     BasicTopologyEntity *bte = btes[k];
07162 
07163     if( check_to_transform )
07164       if (!okay_to_transform( bte ))
07165         continue;
07166 
07167     if (preview)
07168     {
07169       if(bte->dimension()==0)
07170       {
07171         DLIList<RefVertex*> points;
07172         bte->ref_vertices(points);
07173         for (int i = 0; i < points.size(); i++)
07174         {
07175           CubitVector temp(points[i]->center_point());
07176           temp = xform*temp;
07177           GfxPreview::draw_point(temp, CUBIT_BLUE_INDEX);
07178         }
07179       }
07180       else
07181       {
07182         DLIList<RefEdge*> edges;
07183         bte->ref_edges(edges);
07184 
07185         for (int j = 0; j < edges.size(); j++)
07186         {
07187           GMem poly;
07188           if( CUBIT_SUCCESS == edges[j]->get_graphics(poly) )
07189           {
07190             poly.transform(xform);
07191             GfxPreview::draw_polyline(poly.point_list(), poly.point_list_size(), CUBIT_BLUE_INDEX);
07192           }
07193           else if( edges[j]->start_vertex() == edges[j]->end_vertex() )
07194           {
07195             CubitVector tmp_pt = edges[j]->start_vertex()->coordinates();
07196             tmp_pt = xform*tmp_pt;
07197             GfxPreview::draw_point( tmp_pt, CUBIT_BLUE_INDEX);
07198           }
07199         }
07200         if (edges.size() == 0)
07201         {
07202           DLIList<RefVertex*> points;
07203           bte->ref_vertices(points);
07204           for (int i = 0; i < points.size(); i++)
07205           {
07206             CubitVector p(points[i]->center_point());
07207             CubitVector q =xform*p;
07208             GfxPreview::draw_point(q, CUBIT_BLUE_INDEX);
07209           }
07210         }
07211       }
07212 
07213       GfxPreview::flush();
07214       continue;
07215     }
07216 
07217     GeometryEntity* geom = bte->get_geometry_entity_ptr();
07218     GeometryQueryEngine* engine = geom->get_geometry_query_engine();
07219     CubitStatus result = engine->rotate( geom, axis, angle );
07220     if (result)
07221     {
07222       notify_intermediate_of_transform( bte, xform );
07223 
07224       if( btes_rotated )
07225         btes_rotated->append( bte );
07226       ents_transformed.append( bte );    
07227     }
07228     else
07229       PRINT_ERROR("Rotate of %s (%s %d) failed.\n",
07230       bte->entity_name().c_str(), bte->class_name(), bte->id() );
07231   }
07232   
07233   if( ents_transformed.size() )
07234   {
07235     notify_observers_of_transform( ents_transformed, &xform );
07236     return CUBIT_SUCCESS;
07237   }
07238    else if( preview )
07239     return CUBIT_SUCCESS;
07240   else
07241     return CUBIT_FAILURE;
07242 }
07243 
07244 CubitStatus GeometryQueryTool::scale( BasicTopologyEntity* bte,const CubitVector& point, double factor,
07245                                       bool check_to_transform, bool preview )
07246 {
07247   if( check_to_transform )
07248     if (!okay_to_transform( bte ))
07249       return CUBIT_FAILURE;
07250 
07251   CubitTransformMatrix prev_xform;
07252   prev_xform.translate(-point);
07253 
07254   CubitTransformMatrix xform;
07255   xform.scale_about_origin( factor );
07256 
07257   CubitTransformMatrix mov_mat;
07258   mov_mat.translate( point );
07259 
07260 
07261   if (preview)
07262   {
07263 
07264     if(bte->dimension()==0)
07265     {
07266       DLIList<RefVertex*> points;
07267       bte->ref_vertices(points);
07268       for (int i = 0; i < points.size(); i++)
07269       {
07270         CubitVector temp(points[i]->center_point());
07271         temp = prev_xform*temp;
07272         temp = xform*temp;
07273         temp = mov_mat*temp;
07274         GfxPreview::draw_point(temp, CUBIT_BLUE_INDEX);
07275       }
07276     }
07277     else
07278     {
07279 
07280       DLIList<RefEdge*> edges;
07281       bte->ref_edges(edges);
07282       for (int i = 0; i < edges.size(); i++)
07283       {
07284         GMem poly;
07285         if( CUBIT_SUCCESS == edges[i]->get_graphics(poly) )
07286         {
07287           poly.transform(prev_xform);
07288           poly.transform(xform);
07289           poly.transform(mov_mat);
07290           GfxPreview::draw_polyline(poly.point_list(), poly.point_list_size(), CUBIT_BLUE_INDEX);
07291         }
07292         else if( edges[i]->start_vertex() == edges[i]->end_vertex() )
07293         {
07294           CubitVector tmp_pt = edges[i]->start_vertex()->coordinates();
07295           tmp_pt = prev_xform*tmp_pt;
07296           tmp_pt = xform*tmp_pt;
07297           tmp_pt = mov_mat*tmp_pt;          
07298           GfxPreview::draw_point( tmp_pt, CUBIT_BLUE_INDEX);
07299         }
07300       }
07301     }
07302     GfxPreview::flush();
07303     return CUBIT_SUCCESS;
07304   }
07305 
07306   GeometryEntity* geom = bte->get_geometry_entity_ptr();
07307   GeometryQueryEngine* engine = geom->get_geometry_query_engine();
07308   CubitStatus result = engine->translate( geom, -point );
07309   if (result)
07310   {
07311     CubitTransformMatrix prev_xform;
07312     prev_xform.translate(-point);
07313     notify_intermediate_of_transform( bte, prev_xform );
07314   }
07315   else
07316   {
07317     PRINT_ERROR("Scale of %s (%s %d) failed.\n",
07318       bte->entity_name().c_str(), bte->class_name(), bte->id() );
07319     return result;
07320   }
07321 
07322   result = engine->scale( geom, factor );
07323   if (result)
07324   {
07325     CubitTransformMatrix xform;
07326     xform.scale_about_origin( factor );
07327     notify_intermediate_of_transform( bte, xform );
07328   }
07329   else
07330   {
07331     PRINT_ERROR("Scvale of %s (%s %d) failed.\n",
07332       bte->entity_name().c_str(), bte->class_name(), bte->id() );
07333     return result;
07334   }
07335   result = engine->translate( geom, point );
07336   if (result)
07337   {
07338     CubitTransformMatrix mov_mat;
07339     mov_mat.translate( point );
07340 
07341     notify_intermediate_of_transform( bte, prev_xform );
07342     notify_observers_of_transform( bte );
07343   }
07344   else
07345     PRINT_ERROR("Scale of %s (%s %d) failed.\n",
07346     bte->entity_name().c_str(), bte->class_name(), bte->id() );
07347   return result;
07348 }
07349 
07350 
07351 CubitStatus GeometryQueryTool::scale( BasicTopologyEntity* bte,
07352                                      const CubitVector& point,
07353                                       const CubitVector& factors,
07354                                       bool check_to_transform,
07355                                       bool preview )
07356 {
07357   if( check_to_transform )
07358     if (!okay_to_transform( bte ))
07359       return CUBIT_FAILURE;
07360 
07361   CubitTransformMatrix prev_xform;
07362   prev_xform.translate(-point);
07363 
07364   CubitTransformMatrix xform;
07365   xform.scale_about_origin( factors );
07366 
07367   CubitTransformMatrix mov_mat;
07368   mov_mat.translate( point );
07369 
07370 
07371   if (preview)
07372   {
07373     if(bte->dimension()==0)
07374     {
07375       DLIList<RefVertex*> points;
07376       bte->ref_vertices(points);
07377       for (int i = 0; i < points.size(); i++)
07378       {
07379         CubitVector temp(points[i]->center_point());
07380         temp = prev_xform*temp;
07381         temp = xform*temp;
07382         temp = mov_mat*temp;
07383         GfxPreview::draw_point(temp, CUBIT_BLUE_INDEX);
07384       }
07385     }
07386     else
07387     {
07388 
07389       DLIList<RefEdge*> edges;
07390       bte->ref_edges(edges);
07391       for (int i = 0; i < edges.size(); i++)
07392       {
07393         GMem poly;  
07394         if( CUBIT_SUCCESS == edges[i]->get_graphics(poly) )
07395         {
07396           poly.transform(prev_xform);
07397           poly.transform(xform);
07398           poly.transform(mov_mat);
07399           GfxPreview::draw_polyline(poly.point_list(), poly.point_list_size(), CUBIT_BLUE_INDEX);
07400         }
07401         else if( edges[i]->start_vertex() == edges[i]->end_vertex() )
07402         {
07403           CubitVector tmp_pt = edges[i]->start_vertex()->coordinates();
07404           tmp_pt = prev_xform*tmp_pt;
07405           tmp_pt = xform*tmp_pt;
07406           tmp_pt = mov_mat*tmp_pt;          
07407           GfxPreview::draw_point( tmp_pt, CUBIT_BLUE_INDEX);
07408         }
07409       }
07410     }
07411     GfxPreview::flush();
07412     return CUBIT_SUCCESS;
07413   }
07414 
07415   GeometryEntity* geom = bte->get_geometry_entity_ptr();
07416   GeometryQueryEngine* engine = geom->get_geometry_query_engine();
07417   CubitStatus result = engine->translate( geom, -point );
07418   if (result)
07419   {
07420     notify_intermediate_of_transform( bte, prev_xform );
07421   }
07422   else
07423     PRINT_ERROR("Scale of %s (%s %d) failed.\n",
07424       bte->entity_name().c_str(), bte->class_name(), bte->id() );
07425 
07426   result = engine->scale( geom, factors );
07427   if (result)
07428   {
07429     notify_intermediate_of_transform( bte, xform );
07430   }
07431   else
07432     PRINT_ERROR("Scale of %s (%s %d) failed.\n",
07433       bte->entity_name().c_str(), bte->class_name(), bte->id() );
07434 
07435 
07436   result = engine->translate( geom, point );
07437   if (result)
07438   {
07439     notify_intermediate_of_transform( bte, mov_mat );
07440     notify_observers_of_transform( bte );
07441   }
07442   else
07443     PRINT_ERROR("Scale of %s (%s %d) failed.\n",
07444       bte->entity_name().c_str(), bte->class_name(), bte->id() );
07445 
07446 
07447 
07448   return result;
07449 }
07450 
07451 CubitStatus GeometryQueryTool::reflect( DLIList<BasicTopologyEntity*> &btes,
07452                                         const CubitVector& point,
07453                                         const CubitVector& normal,
07454                                         DLIList<BasicTopologyEntity*> *btes_reflected,
07455                                         bool check_to_transform,
07456                                         bool preview )
07457 {
07458   CubitTransformMatrix prev_xform;
07459   prev_xform.translate(-point);
07460 
07461   CubitTransformMatrix ref_mat;
07462   ref_mat.reflect(normal );
07463 
07464   CubitTransformMatrix mov_mat;
07465   mov_mat.translate( point );
07466   
07467   CubitTransformMatrix total_transform;
07468   total_transform = mov_mat*ref_mat*prev_xform;
07469   
07470   DLIList<RefEntity*> transformed_ents;
07471 
07472   for( int k=0; k<btes.size(); k++ )  
07473   {
07474     BasicTopologyEntity *bte = btes[k];
07475 
07476     if( check_to_transform )
07477       if (!okay_to_transform( bte ))
07478         return CUBIT_FAILURE;
07479 
07480     if (preview)
07481     {
07482       if(bte->dimension()==0)
07483       {
07484         DLIList<RefVertex*> points;
07485         bte->ref_vertices(points);
07486         for (int i = 0; i < points.size(); i++)
07487         {
07488           CubitVector temp(points[i]->center_point());        
07489           temp = total_transform*temp;
07490           GfxPreview::draw_point(temp, CUBIT_BLUE_INDEX);
07491         }
07492       }
07493       else
07494       {
07495 
07496         DLIList<RefEdge*> edges;
07497         bte->ref_edges(edges);
07498         for (int j = 0; j < edges.size(); j++)
07499         {
07500           GMem poly;        
07501           if( CUBIT_SUCCESS == edges[j]->get_graphics(poly) )
07502           {
07503             poly.transform( total_transform );
07504             GfxPreview::draw_polyline(poly.point_list(), poly.point_list_size(), CUBIT_BLUE_INDEX);
07505           }
07506           else if( edges[j]->start_vertex() == edges[j]->end_vertex() )
07507           {
07508             CubitVector tmp_pt = edges[j]->start_vertex()->coordinates();          
07509             tmp_pt = total_transform*tmp_pt;
07510             GfxPreview::draw_point( tmp_pt, CUBIT_BLUE_INDEX);
07511           }
07512         }
07513       }
07514       GfxPreview::flush();
07515       continue;
07516     }
07517 
07518     GeometryEntity* geom = bte->get_geometry_entity_ptr();
07519     GeometryQueryEngine* engine = geom->get_geometry_query_engine();
07520     CubitStatus result;
07521 
07522     // Move to origin
07523     result = engine->translate( geom, -point );
07524     if (result)
07525     {
07526       CubitTransformMatrix xform;
07527       xform.translate( -point );
07528       notify_intermediate_of_transform( bte, xform );
07529     }
07530     else
07531     {
07532       PRINT_ERROR("Reflect of %s (%s %d) failed.\n",
07533         bte->entity_name().c_str(), bte->class_name(), bte->id() );
07534       return result;
07535     }
07536 
07537     result = engine->reflect( geom, normal );
07538     if (result)
07539     {
07540       CubitTransformMatrix xform;
07541       xform.reflect( normal);
07542       notify_intermediate_of_transform( bte, xform );
07543     }
07544     else
07545     {
07546       PRINT_ERROR("Reflect of %s (%s %d) failed.\n",
07547         bte->entity_name().c_str(), bte->class_name(), bte->id() );
07548       return result;
07549     }
07550 
07551     result = engine->translate( geom, point );
07552     if (result)
07553     {
07554       CubitTransformMatrix xform;
07555       xform.translate( point );
07556       notify_intermediate_of_transform( bte, xform );
07557 
07558       if( btes_reflected )
07559         btes_reflected->append( bte );
07560       transformed_ents.append( bte );      
07561     }
07562     else
07563     {
07564       PRINT_ERROR("Reflect of %s (%s %d) failed.\n",
07565         bte->entity_name().c_str(), bte->class_name(), bte->id() );
07566       return result;
07567     }
07568   }
07569 
07570   if( transformed_ents.size() )
07571   {
07572     notify_observers_of_transform( transformed_ents, &total_transform );
07573     return CUBIT_SUCCESS;
07574   }
07575   else if( preview )
07576     return CUBIT_SUCCESS;
07577   else
07578     return CUBIT_FAILURE;
07579 }
07580 
07581 void GeometryQueryTool::ige_remove_modified(DLIList<Surface*> &all_surfs,
07582                                             DLIList<Curve*> &all_curves,
07583                                             DLIList<TBPoint*> &all_points)
07584 {
07585   IGESet::iterator itor;
07586 
07587   for (itor = igeSet.begin(); itor != igeSet.end(); ++itor)
07588     (*itor)->remove_modified(all_surfs, all_curves, all_points);
07589 
07590   for (itor = igeSet.begin(); itor != igeSet.end(); ++itor)
07591     (*itor)->clean_out_deactivated_geometry();
07592 }
07593 
07594 CubitBoolean GeometryQueryTool::bodies_overlap( Body *body_ptr_1,
07595                                                 Body *body_ptr_2 )
07596 {
07597   BodySM *body1 = body_ptr_1->get_body_sm_ptr();
07598   BodySM *body2 = body_ptr_2->get_body_sm_ptr();
07599 
07600   if( is_intermediate_geometry( body_ptr_1 ) )
07601     return body_ptr_1->get_geometry_query_engine()->bodies_overlap( body1, body2 );
07602   else if( is_intermediate_geometry( body_ptr_2 ) )
07603     return body_ptr_2->get_geometry_query_engine()->bodies_overlap( body2, body1 );
07604   else if( body_ptr_1->get_geometry_query_engine() !=
07605            body_ptr_2->get_geometry_query_engine() )
07606   {
07607     PRINT_ERROR("Volumes must be of the same type ( SolidWorks, etc) to\n"
07608                 "find if they overlap.\n");
07609     return CUBIT_FALSE;
07610   }
07611   else
07612     return body_ptr_1->get_geometry_query_engine()->bodies_overlap( body1, body2 );
07613 }
07614 
07615 CubitBoolean GeometryQueryTool::volumes_overlap( RefVolume *volume_1,
07616                                                  RefVolume *volume_2 )
07617 {
07618   Lump *lump1 = volume_1->get_lump_ptr();
07619   Lump *lump2 = volume_2->get_lump_ptr();
07620 
07621   if( is_intermediate_geometry( volume_1 ) )
07622     return volume_1->get_geometry_query_engine()->volumes_overlap( lump1, lump2 );
07623   else if( is_intermediate_geometry( volume_2 ) )
07624     return volume_2->get_geometry_query_engine()->volumes_overlap( lump2, lump1 );
07625   else if( volume_1->get_geometry_query_engine() !=
07626            volume_2->get_geometry_query_engine() )
07627   {
07628     PRINT_ERROR("Volumes must be of the same type (SolidWorks, etc) to\n"
07629                 "find if they overlap.\n");
07630     return CUBIT_FALSE;
07631   }
07632   else
07633     return volume_1->get_geometry_query_engine()->volumes_overlap( lump1, lump2 );
07634 }
07635 
07636 void GeometryQueryTool::find_nonmanifold_curves(DLIList<RefVolume*> &vol_list,
07637                                                 DLIList<RefEdge*> &curve_list)
07638 {
07639   int i;
07640   for(i=vol_list.size(); i>0; i--)
07641   {
07642     RefVolume *vol = vol_list.get_and_step();
07643     DLIList<RefEdge*> vol_curves;
07644     vol->ref_edges(vol_curves);
07645     int j;
07646     for(j=vol_curves.size(); j>0; j--)
07647     {
07648       RefEdge *cur_curve = vol_curves.get_and_step();
07649       if(cur_curve->is_merged())
07650       {
07651         DLIList<RefFace*> curve_faces;
07652         cur_curve->ref_faces(curve_faces);
07653         bool merged_face_exists = false;
07654         while(curve_faces.size() && !merged_face_exists)
07655         {
07656           RefFace *cur_face = curve_faces.pop();
07657           if(cur_face->is_merged())
07658             merged_face_exists = true;
07659         }
07660         if(!merged_face_exists)
07661           curve_list.append(cur_curve);
07662       }
07663     }
07664   }
07665   curve_list.uniquify_ordered();
07666 }
07667 
07668 double GeometryQueryTool::estimate_merge_tolerance(DLIList<RefVolume*> &vol_list,
07669                                                     bool accurate_in,
07670                                                     bool report_in,
07671                                                     double lo_val_in, 
07672                                                     double hi_val_in,
07673                                                     int num_calculations_in,
07674                                                     bool return_calculations_in,
07675                                                     DLIList<double> *merge_tols,
07676                                                     DLIList<int> *num_proximities)
07677 {
07678   double return_merge_tol = -1.0;  // return value of < 0.0 will mean failure
07679                                    // to find a merge tolerance
07680 
07681   DLIList<double> local_merge_tols;
07682   DLIList<int> local_num_proximities;
07683   bool report = report_in;
07684   double lo_val = 0.0;
07685   double hi_val = get_geometry_factor()*GEOMETRY_RESABS*10.0;  // 10 * merge tol -- arbitrary
07686   int num_calculations = num_calculations_in;
07687 
07688   if(lo_val_in != -1.0)
07689     lo_val = lo_val_in;
07690   if(hi_val_in != -1.0)
07691     hi_val = hi_val_in;
07692 
07693   if(hi_val > lo_val)
07694   {
07695     double cur_val = lo_val;
07696     double step = (hi_val - lo_val)/(double)num_calculations;
07697     int i;
07698     if(report)
07699     {
07700       PRINT_INFO("\n\nLooking for merge toleance...\n\n");
07701       PRINT_INFO("  Possible range: %f, %f\n", lo_val, hi_val);
07702       PRINT_INFO("  Number of steps: %d\n\n", num_calculations+1);
07703     }
07704 
07705     std::map <RefVertex*, DLIList<dist_vert_struct*>*> vert_dist_map;
07706     GeomMeasureTool::find_near_coincident_vertices_unique(vol_list, hi_val, vert_dist_map);
07707 
07708     int total_num_proximities = 0;
07709     for(i=0; i<=num_calculations; i++)
07710     {
07711       int cur_num_proximities = 0;
07712       local_merge_tols.append(cur_val);
07713 
07714       std::map <RefVertex*, DLIList<dist_vert_struct*>*>::iterator iter;
07715       for(iter=vert_dist_map.begin(); iter != vert_dist_map.end(); iter++ )
07716       {
07717         //RefVertex *vert = iter->first;
07718         DLIList<dist_vert_struct*> *struct_list = iter->second;
07719         int m;
07720         for(m=struct_list->size(); m>0; m--)
07721         {
07722           dist_vert_struct *dvs = struct_list->get();
07723           if(dvs->dist <= cur_val)
07724           {
07725   //          PRINT_INFO("Vertices %d and %d, distance: %.10lf\n", vert->id(), dvs->v2->id(), dvs->dist);
07726             struct_list->change_to(NULL);
07727             delete dvs;
07728             cur_num_proximities++;
07729           }
07730           struct_list->step();
07731         }
07732         struct_list->remove_all_with_value(NULL);
07733       }
07734 
07735       total_num_proximities += cur_num_proximities;
07736       local_num_proximities.append(total_num_proximities);
07737 
07738       if(report)
07739       {
07740         PRINT_INFO("  At merge tolerance = %f number of proximities = %d.\n", cur_val, total_num_proximities);
07741       }
07742 
07743       cur_val += step;
07744     }
07745 
07746     std::map <RefVertex*, DLIList<dist_vert_struct*>*>::iterator iter;
07747     for(iter=vert_dist_map.begin(); iter != vert_dist_map.end(); iter++ )
07748     {
07749       DLIList<dist_vert_struct*> *struct_list = iter->second;
07750       // I think all of the items in the lists should be gone
07751       // by now but just in case...
07752       while(struct_list->size())
07753         delete struct_list->pop();
07754       delete struct_list;
07755     }
07756 
07757     local_num_proximities.reset();
07758     local_merge_tols.reset();
07759     int num_total = local_merge_tols.size();
07760     if(num_total > 2)
07761     {
07762       int num_triplets = num_total - 2;
07763       int h, min_index, min_diff;
07764       DLIList<int> diffs;
07765       for(h=0; h<num_triplets; h++)
07766       {
07767         int num_begin = local_num_proximities.get();
07768         local_num_proximities.step(2);
07769         int num_end = local_num_proximities.get();
07770         local_num_proximities.back();
07771         int cur_diff = num_end - num_begin;
07772         if(h==0)
07773         {
07774           min_index = h;
07775           min_diff = cur_diff;
07776         }
07777         else
07778         {
07779           if(cur_diff < min_diff)
07780           {
07781             min_diff = cur_diff;
07782             min_index = h;
07783           }
07784         }
07785       }
07786       local_merge_tols.step(min_index+1);
07787       return_merge_tol = local_merge_tols.get();
07788     }
07789     else
07790       PRINT_ERROR("Unable to estimate merge tolerance.\n");
07791 
07792 /*
07793     // Pick off a merge tolerance.
07794     local_num_proximities.reset();
07795     local_merge_tols.reset();
07796     DLIList<int> unique_num_proximities;
07797     DLIList<int> unique_counts;
07798     DLIList<double> tmp_merge_tol_list;
07799     int tmp_num_proximities;
07800     double tmp_merge_tol;
07801 
07802     double cur_merge_tol = local_merge_tols.get_and_step();
07803     int cur_num_prox = local_num_proximities.get_and_step();
07804     int cur_unique_counts = 1;
07805     // Loop over the whole size even though we have processed the 
07806     // first entry because we need to record the results after the
07807     // last entry.
07808     for(i=local_num_proximities.size(); i>0; i--)
07809     {
07810       if(i>1)
07811       {
07812         tmp_num_proximities = local_num_proximities.get_and_step();
07813         tmp_merge_tol = local_merge_tols.get_and_step();
07814       }
07815       else 
07816       {
07817         // On the last time in just give it a dummy value so we
07818         // can record the results from the last real entry.
07819         tmp_num_proximities = -1;
07820       }
07821       if(cur_num_prox == tmp_num_proximities)
07822       {
07823         cur_unique_counts++;
07824       }
07825       else
07826       {
07827         tmp_merge_tol_list.append(cur_merge_tol);
07828         unique_counts.append(cur_unique_counts);
07829         unique_num_proximities.append(cur_num_prox);
07830         cur_unique_counts = 1;
07831         cur_num_prox = tmp_num_proximities;
07832         cur_merge_tol = tmp_merge_tol;
07833       }
07834     }
07835 
07836     int max_index = -1;
07837     int cur_max_num_counts = 0;
07838     unique_counts.reset();
07839     unique_num_proximities.reset();
07840     tmp_merge_tol_list.reset();
07841     for(i=unique_counts.size(); i>0; i--)
07842     {
07843       int cur_num_counts = unique_counts.get();
07844       if(cur_num_counts > cur_max_num_counts)
07845       {
07846         cur_max_num_counts = cur_num_counts;
07847         max_index = unique_counts.get_index();
07848       }
07849       unique_counts.step();
07850     }
07851 
07852     if(max_index > -1)
07853     {
07854       tmp_merge_tol_list.step(max_index);
07855       return_merge_tol = tmp_merge_tol_list.get();
07856     }
07857     else
07858     {
07859       PRINT_ERROR("Unable to estimate merge tolerance.\n");
07860     }
07861     */
07862 
07863     if(report)
07864       PRINT_INFO("\nEstimated merge tolerance: %f\n", return_merge_tol);
07865   }
07866   else
07867     PRINT_ERROR("Range low value is larger than range high value.\n");
07868 
07869   return return_merge_tol;
07870 }
07871 
07872 void GeometryQueryTool::find_floating_volumes(DLIList<RefVolume*> &vol_list,
07873                                               DLIList<RefVolume*> &floating_list)
07874 {
07875   int i;
07876   for(i=vol_list.size(); i>0; i--)
07877   {
07878     bool floating = true;
07879     RefVolume *vol = vol_list.get_and_step();
07880     DLIList<RefEdge*> vol_curves;
07881     DLIList<RefVertex*> vol_verts;
07882     DLIList<RefFace*> vol_surfs;
07883     vol->ref_edges(vol_curves);
07884     vol->ref_faces(vol_surfs);
07885     vol->ref_vertices(vol_verts);
07886     int j;
07887     for(j=vol_surfs.size(); j>0 && floating; j--)
07888     {
07889       RefFace *cur_surf = vol_surfs.get_and_step();
07890       if(cur_surf->is_merged())
07891         floating = false;
07892     }
07893     for(j=vol_curves.size(); j>0 && floating; j--)
07894     {
07895       RefEdge *cur_curve = vol_curves.get_and_step();
07896       if(cur_curve->is_merged())
07897         floating = false;
07898     }
07899     for(j=vol_verts.size(); j>0 && floating; j--)
07900     {
07901       RefVertex *cur_vert = vol_verts.get_and_step();
07902       if(cur_vert->is_merged())
07903         floating = false;
07904     }
07905     if(floating)
07906       floating_list.append(vol);
07907   }
07908   floating_list.uniquify_ordered();
07909 }
07910 
07911 void GeometryQueryTool::find_nonmanifold_vertices(DLIList<RefVolume*> &vol_list,
07912                                                 DLIList<RefVertex*> &vertex_list)
07913 {
07914   int i;
07915   for(i=vol_list.size(); i>0; i--)
07916   {
07917     RefVolume *vol = vol_list.get_and_step();
07918     DLIList<RefVertex*> vol_verts;
07919     vol->ref_vertices(vol_verts);
07920     int j;
07921     for(j=vol_verts.size(); j>0; j--)
07922     {
07923       RefVertex *cur_vert = vol_verts.get_and_step();
07924       if(cur_vert->is_merged())
07925       {
07926         DLIList<RefEdge*> vert_edges;
07927         cur_vert->ref_edges(vert_edges);
07928         bool merged_edge_exists = false;
07929         while(vert_edges.size() && !merged_edge_exists)
07930         {
07931           RefEdge *cur_edge = vert_edges.pop();
07932           if(cur_edge->is_merged())
07933             merged_edge_exists = true;
07934         }
07935         if(!merged_edge_exists)
07936           vertex_list.append(cur_vert);
07937       }
07938     }
07939   }
07940   vertex_list.uniquify_ordered();
07941 }
07942 
07943 CGMHistory& GeometryQueryTool::history()
07944 {
07945   return mHistory;
07946 }
07947 
07948 void GeometryQueryTool::get_merged_away_free_entities( DLIList<RefEntity*> &ref_ents,
07949                                                        DLIList<TopologyBridge*> &free_ents )
07950 {
07951   //determine if you have any free entities that were merged away 
07952   DLIList<RefEntity*> merged_ref_ents;
07953   MergeTool::instance()->contains_merged_entities( ref_ents, &merged_ref_ents );
07954   int i;
07955   for( i=merged_ref_ents.size(); i--; )
07956   {
07957     RefEntity *tmp_ent = merged_ref_ents.get_and_step();
07958     DLIList<TopologyBridge*> bridge_list;
07959     TopologyEntity *te = CAST_TO(tmp_ent, TopologyEntity );
07960     te->bridge_manager()->get_bridge_list( bridge_list );
07961     //bridge_list.reset();
07962     //bridge_list.step(); //don't want to first bridge...that's the real thing
07963     
07964     //check for free entities...
07965     int j;
07966     for( j=0; j<bridge_list.size(); j++ )
07967     {
07968       TopologyBridge *tmp_bridge = bridge_list.get_and_step();
07969 
07970       //ignore the representation bridge if it's a free vertex
07971       if( j==0 )
07972         if( tmp_ent->num_parent_ref_entities() == 0 )
07973           continue;
07974 
07975       DLIList<TopologyBridge*> parents;
07976       tmp_bridge->get_parents( parents );
07977       if( parents.size() == 0 ) 
07978         free_ents.append( tmp_bridge );
07979     }
07980   }
07981 }
07982 
07983 
07984 CubitStatus GeometryQueryTool::get_graphics( RefFace *ref_face,
07985                                              GMem *gmem,
07986                                              std::vector<RefEntity*> &facet_point_ownership_vector,
07987                                              std::vector<std::pair< RefEntity*, std::pair<int,int> > > &facetedges_on_refedges,
07988                                              unsigned short normal_tolerance, 
07989                                              double distance_tolerance, 
07990                                              double max_edge_length )
07991 {
07992   Surface* surf_ptr = ref_face->get_surface_ptr();
07993   if (!surf_ptr)
07994   {
07995     PRINT_ERROR("RefFace %d is invalid -- no attached Surface.\n",ref_face->id());
07996     return CUBIT_FAILURE;
07997   }
07998    
07999   std::vector<TopologyBridge*> vertex_edge_to_point_vector;
08000   std::vector<std::pair<TopologyBridge*, std::pair<int,int> > > facetedges_on_curve;
08001 
08002   CubitStatus rv = surf_ptr->get_geometry_query_engine()->
08003     get_graphics(surf_ptr, gmem, vertex_edge_to_point_vector, facetedges_on_curve,
08004     normal_tolerance, distance_tolerance, max_edge_length );
08005   if (CUBIT_SUCCESS != rv) {
08006     PRINT_ERROR("GeometryQueryEngine::get_graphics failed.\n");
08007     return rv;
08008   }
08009 
08010   facet_point_ownership_vector.resize( vertex_edge_to_point_vector.size(), NULL );
08011   RefEntity *ref_ent = NULL;
08012   for( unsigned int i = 0; i < vertex_edge_to_point_vector.size(); i++ )
08013   {    
08014     TopologyBridge *tb = vertex_edge_to_point_vector[i];     
08015     if( NULL == tb )
08016       continue;
08017     
08018     if( tb->topology_entity() )
08019     {
08020       ref_ent = CAST_TO( tb->topology_entity(), RefEntity ); 
08021       facet_point_ownership_vector[i] = ref_ent;
08022     }
08023     else
08024       assert(0);
08025   }
08026 
08027   for( unsigned int i = 0; i < facetedges_on_curve.size(); i++ )
08028   {    
08029     std::pair<TopologyBridge*, std::pair<int,int> > tmp_pair = facetedges_on_curve[i];
08030     TopologyBridge *tb = tmp_pair.first;
08031     
08032     if( tb->topology_entity() )
08033     {
08034       ref_ent = CAST_TO( tb->topology_entity(), RefEntity ); 
08035       facetedges_on_refedges.push_back( std::make_pair( ref_ent, tmp_pair.second ) ); 
08036     }
08037     else
08038     {
08039       assert(0);
08040     }
08041   }
08042 
08043   
08044   bool debug = false;
08045 
08046   if( debug )
08047   {    
08048     //GfxDebug::clear();
08049     //GPoint *pt_list = gmem->point_list();
08050     for( unsigned int i = 0; i < facet_point_ownership_vector.size(); i++ )
08051     {
08052       //RefEntity *ref_ent = facet_point_ownership_vector[i];
08053 
08054       //int color = 3;
08055       //if( ref_ent->dimension() == 1 )
08056         //color = 4;
08057       //else if( ref_ent->dimension() == 2 )
08058         //color = 5;
08059     }   
08060 
08061     GfxDebug::flush();
08062     GfxDebug::mouse_xforms();    
08063     
08064 
08065     GfxDebug::clear();
08066     //draw the curves
08067     for( unsigned int i=0; i<facetedges_on_refedges.size(); i++ )
08068     {
08069       std::pair<RefEntity*, std::pair<int,int> > tmp_pair;
08070       tmp_pair = facetedges_on_refedges[i];
08071 
08072       RefEntity* ref_ent = tmp_pair.first;
08073       std::pair<int,int> int_pair = tmp_pair.second;
08074 
08075       CubitVector pt0( gmem->point_list()[int_pair.first].x,
08076         gmem->point_list()[int_pair.first].y,
08077         gmem->point_list()[int_pair.first].z );
08078 
08079       CubitVector pt1( gmem->point_list()[int_pair.second].x,
08080         gmem->point_list()[int_pair.second].y,
08081         gmem->point_list()[int_pair.second].z );
08082 
08083       GfxDebug::draw_point(pt0, (ref_ent->id()%10) + 3  );
08084       GfxDebug::draw_point(pt1, (ref_ent->id()%10) + 3  );
08085       GfxDebug::draw_line( pt0, pt1, (ref_ent->id()%10) + 3 );      
08086     }
08087     GfxDebug::flush();      
08088     GfxDebug::mouse_xforms();
08089 
08090     int index = 0;
08091     GfxDebug::clear();
08092     for( int i=0; i<gmem->fListCount; i++ )
08093     {
08094       int step = gmem->facet_list()[index++];      
08095       //create pts      
08096       CubitVector pt0( gmem->point_list()[ gmem->facet_list()[index] ].x,
08097         gmem->point_list()[ gmem->facet_list()[index] ].y,
08098         gmem->point_list()[ gmem->facet_list()[index] ].z );       
08099       index++;
08100 
08101       CubitVector pt1( gmem->point_list()[ gmem->facet_list()[index] ].x,
08102         gmem->point_list()[ gmem->facet_list()[index] ].y,
08103         gmem->point_list()[ gmem->facet_list()[index] ].z );
08104       index++;
08105 
08106       CubitVector pt2( gmem->point_list()[ gmem->facet_list()[index] ].x,
08107         gmem->point_list()[ gmem->facet_list()[index] ].y,
08108         gmem->point_list()[ gmem->facet_list()[index] ].z );       
08109       index++;
08110 
08111        //draw lines
08112        GPoint three_pts[3];
08113        three_pts[0].x = pt0.x();
08114        three_pts[0].y = pt0.y();
08115        three_pts[0].z = pt0.z();    
08116 
08117        three_pts[1].x = pt1.x();
08118        three_pts[1].y = pt1.y();
08119        three_pts[1].z = pt1.z();    
08120 
08121        three_pts[2].x = pt2.x();
08122        three_pts[2].y = pt2.y();
08123        three_pts[2].z = pt2.z();                  
08124 
08125        GfxDebug::draw_polygon( three_pts, 3, i%20, i%20, true );
08126        GfxDebug::draw_line( pt0, pt1, i%20 );
08127        GfxDebug::draw_line( pt1, pt2, i%20 );
08128        GfxDebug::draw_line( pt0, pt2, i%20 );       
08129        i+=step;              
08130     }          
08131     GfxDebug::flush();
08132     GfxDebug::mouse_xforms();
08133   }
08134 
08135 
08136 
08137 
08138   return CUBIT_SUCCESS;  
08139 }
08140 
08141 
08142 CubitStatus GeometryQueryTool::get_graphics( Body *body, 
08143                                              GMem *g_mem,
08144                                              std::vector<RefFace*> &ref_face_to_facet_vector,
08145                                              std::vector<RefEntity*> &facet_point_ownership_vector,
08146                                              std::vector<std::pair< RefEntity*, std::pair<int,int> > > &facetedges_on_refedges,
08147                                              unsigned short normal_tolerance, 
08148                                              double distance_tolerance, 
08149                                              double max_edge_length )
08150 {
08151   //get all the RefFaces from 
08152   DLIList<RefFace*> all_ref_faces; 
08153   body->ref_faces( all_ref_faces );    
08154 
08155   BodySM *body_sm = NULL;
08156 
08157   //get the underlying body in partition bodies
08158   if( GeometryQueryTool::instance()->is_intermediate_geometry( body ) )
08159   {      
08160     DLIList<TopologyBridge*> partition_body(1);
08161     body->get_body_sm_ptr()->get_geometry_query_engine()->get_underlying_bridges( body->get_body_sm_ptr(), partition_body );
08162     if( partition_body.size() == 1 )
08163       body_sm = static_cast<BodySM*>(partition_body.get());
08164   }
08165   else  
08166     body_sm = body->get_body_sm_ptr();        
08167 
08168   //make sure everything belongs to the same GQE  
08169   GeometryQueryEngine* gqe = body_sm->get_geometry_query_engine();  
08170   
08171   //get the graphics
08172   std::vector<Surface*> surfaces_to_facet_vector;
08173   std::vector<TopologyBridge*> tmp_facet_point_ownership_vector;
08174   std::vector<std::pair<TopologyBridge*, std::pair<int,int> > > facetedges_on_curve;
08175   CubitStatus stat = gqe->get_graphics( body_sm, g_mem, surfaces_to_facet_vector, tmp_facet_point_ownership_vector,
08176     facetedges_on_curve, normal_tolerance, distance_tolerance, max_edge_length );
08177 
08178   if( CUBIT_FAILURE == stat )
08179     return CUBIT_FAILURE;
08180 
08181   //map Surfaces to MRefFaces
08182   Surface *current_surf = NULL;
08183   RefFace *current_ref_face = NULL;
08184   bool ignore_facets = false;
08185 
08186   unsigned int i;
08187   for( i=0; i<surfaces_to_facet_vector.size(); i++ )
08188   {    
08189     Surface *tmp_surf = surfaces_to_facet_vector[i];     
08190     
08191     if( tmp_surf != current_surf )
08192     {
08193       ignore_facets = false;
08194       current_surf = tmp_surf;
08195 
08196       if( tmp_surf->topology_entity() )
08197       {
08198         current_ref_face = CAST_TO( tmp_surf->topology_entity(), RefFace ); 
08199         if( current_ref_face )        
08200           ref_face_to_facet_vector.push_back( current_ref_face );
08201       }
08202       else
08203       {
08204         int times_through = 0;
08205         for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end(); ++itor)
08206         {          
08207           times_through++;
08208           DLIList<TopologyBridge*> bridge_list;
08209           (*itor)->get_tbs_with_bridge_manager_as_owner(tmp_surf, bridge_list);
08210           if( bridge_list.size() == 0 )
08211           {
08212             if( times_through == 2 )
08213               assert(0);
08214             continue;
08215           }
08216 
08217           if( bridge_list.size() == 1 )
08218           {
08219             current_ref_face = CAST_TO( bridge_list.get()->topology_entity(), RefFace );
08220             if( current_ref_face )
08221               ref_face_to_facet_vector.push_back( current_ref_face );              
08222             else 
08223             {
08224               PRINT_INFO("Having trouble finding the top-level RefFace\n");
08225               assert(0);
08226             }  
08227             break;
08228           }
08229           else if( bridge_list.size() > 1 ) // it is a partition...we'll ignore the facets
08230           {             
08231             ref_face_to_facet_vector.push_back( NULL );
08232             ignore_facets = true;
08233             break;
08234           }
08235         }     
08236       }
08237     }
08238     else
08239     {   
08240       if( ignore_facets )
08241         ref_face_to_facet_vector.push_back( NULL );
08242       else
08243         ref_face_to_facet_vector.push_back( current_ref_face );
08244     }
08245   }
08246   
08247   facet_point_ownership_vector.resize( tmp_facet_point_ownership_vector.size(), NULL );
08248   RefEntity *ref_ent = NULL;
08249   for( i=0; i<tmp_facet_point_ownership_vector.size(); i++ )
08250   {    
08251     TopologyBridge *tb = tmp_facet_point_ownership_vector[i];     
08252     if( NULL == tb )
08253       continue;
08254     
08255     if( tb->topology_entity() )
08256     {
08257       ref_ent = CAST_TO( tb->topology_entity(), RefEntity ); 
08258       facet_point_ownership_vector[i] = ref_ent;
08259     }
08260     else
08261     {
08262       int times_through = 0;
08263       for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end(); ++itor)
08264       {          
08265         times_through++;
08266         DLIList<TopologyBridge*> bridge_list;
08267         (*itor)->get_tbs_with_bridge_manager_as_owner(tb, bridge_list);
08268         if( bridge_list.size() == 0 )
08269         {
08270           if( times_through == 2 )
08271             assert(0);
08272           continue;
08273         }
08274 
08275         //composites
08276         if( bridge_list.size() == 1 )
08277         {
08278           ref_ent = CAST_TO( bridge_list.get()->topology_entity(), RefEntity );
08279           if( ref_ent )
08280             facet_point_ownership_vector[i] = ref_ent;
08281           else 
08282           {
08283             PRINT_INFO("Having trouble finding the top-level RefEdge or RefVertex\n");
08284             assert(0);
08285           }  
08286           break;
08287         }
08288         else if( bridge_list.size() > 1 ) // it is a partition...we'll ignore the facets
08289         {             
08290           facet_point_ownership_vector[i] = NULL;
08291           ignore_facets = true;
08292           break;
08293         }
08294       }     
08295     }
08296   }
08297 
08298   for( i=0; i<facetedges_on_curve.size(); i++ )
08299   {    
08300     std::pair<TopologyBridge*, std::pair<int,int> > tmp_pair = facetedges_on_curve[i];
08301     TopologyBridge *tb = tmp_pair.first;
08302     
08303     if( tb->topology_entity() )
08304     {
08305       ref_ent = CAST_TO( tb->topology_entity(), RefEntity ); 
08306       facetedges_on_refedges.push_back( std::make_pair( ref_ent, tmp_pair.second ) ); 
08307     }
08308     else
08309     {
08310       int times_through = 0;
08311       for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end(); ++itor)
08312       {          
08313         times_through++;
08314         DLIList<TopologyBridge*> bridge_list;
08315         (*itor)->get_tbs_with_bridge_manager_as_owner(tb, bridge_list);
08316         if( bridge_list.size() == 0 )
08317         {
08318           //if( times_through == 2 )
08319           //  assert(0);
08320           continue;
08321         }
08322 
08323         //composites
08324         if( bridge_list.size() == 1 )
08325         {
08326           ref_ent = CAST_TO( bridge_list.get()->topology_entity(), RefEntity );
08327           if( ref_ent )
08328             facetedges_on_refedges.push_back( std::make_pair( ref_ent, tmp_pair.second ) ); 
08329           else 
08330           {
08331             PRINT_INFO("Having trouble finding the top-level RefEdge or RefVertex\n"