cgma
CompositeTool.cpp
Go to the documentation of this file.
00001 #include <assert.h>
00002 #include <vector>
00003 
00004 #include "CompositeTool.hpp"
00005 
00006 #include "DLIList.hpp"
00007 #include "CastTo.hpp"
00008 #include "CubitUtil.hpp"
00009 
00010 #include "RefEntityFactory.hpp"
00011 #include "RefEdge.hpp"
00012 #include "RefFace.hpp"
00013 #include "RefVertex.hpp"
00014 #include "RefVolume.hpp"
00015 #include "Loop.hpp"
00016 #include "Shell.hpp"
00017 #include "Chain.hpp"
00018 #include "CoEdge.hpp"
00019 #include "CoFace.hpp"
00020 #include "CoVertex.hpp"
00021 #include "Body.hpp"
00022 
00023 #include "CompositeCurve.hpp"
00024 #include "CompositeSurface.hpp"
00025 #include "CompositeLump.hpp"
00026 #include "CompositeBody.hpp"
00027 
00028 //#include "VirtualQueryEngine.hpp"
00029 #include "PartitionTool.hpp"
00030 #include "BasicTopologyEntity.hpp"
00031 #include "ModelQueryEngine.hpp"
00032 #include "RefEntityName.hpp"
00033 
00034 #include "CompositeEngine.hpp"
00035 #include "Point.hpp"
00036 #include "GeometryQueryTool.hpp"
00037 #include "DAG.hpp"
00038 //#include "CAMergePartner.hpp"
00039 //#include "TDUniqueId.hpp"
00040 #include "CubitAttrib.hpp"
00041 #include "CADefines.hpp"
00042 
00043 #include "PartitionEngine.hpp"
00044 #include "PartitionSurface.hpp"
00045 #include "SegmentedCurve.hpp"
00046 #include "PartPTCurve.hpp"
00047 #include "PartitionPoint.hpp"
00048 #include "GMem.hpp"
00049 #include "GfxDebug.hpp"
00050 
00051 CompositeTool* CompositeTool::instance_ = NULL;
00052 
00053 
00054 //-------------------------------------------------------------------------
00055 // Purpose       : Constructor 
00056 //
00057 // Special Notes : 
00058 //
00059 // Creator       : Jason Kraftcheck
00060 //
00061 // Creation Date : 10/17/03
00062 //-------------------------------------------------------------------------
00063 CompositeTool::CompositeTool()
00064 {
00065 }
00066 
00067 
00068 //-------------------------------------------------------------------------
00069 // Purpose       : Destructor
00070 //
00071 // Special Notes : 
00072 //
00073 // Creator       : Jason Kraftcheck
00074 //
00075 // Creation Date : 
00076 //-------------------------------------------------------------------------
00077 CompositeTool::~CompositeTool()
00078 {
00079   assert( instance_ == this );
00080   instance_ = NULL;
00081 }
00082 
00083 //-------------------------------------------------------------------------
00084 // Purpose       : Create a composite curve
00085 //
00086 // Special Notes : 
00087 //
00088 // Creator       : Jason Kraftcheck
00089 //
00090 // Creation Date : 
00091 //-------------------------------------------------------------------------
00092 RefEdge* CompositeTool::composite( DLIList<RefEdge*>& edge_list,
00093                                    RefVertex* keep,
00094                                    RefEdge* survivor  )
00095 {
00096   int i;
00097   DLIList<RefVertex*> vertex_list;
00098   DLIList<RefEdge*> modified_edges;
00099   
00100   for( i = edge_list.size(); i--; )
00101   {
00102     RefEdge* edge = edge_list.get_and_step();
00103     RefVertex* start_vtx = edge->start_vertex();
00104     RefVertex* end_vtx = edge->end_vertex();
00105     start_vtx->marked(0);
00106     end_vtx->marked(0);
00107     vertex_list.append( start_vtx );
00108     vertex_list.append( end_vtx );
00109   }
00110   for( i = vertex_list.size(); i--; )
00111   {
00112     RefVertex* vtx = vertex_list.get_and_step();
00113     vtx->marked( vtx->marked() + 1 );
00114   }
00115   // Check for edges that will have both vertices removed.
00116   // If any exist then we want to set the flag to have the
00117   // DAG updated after each vertex is removed.  Otherwise
00118   // things get left in a bad state.
00119   bool update_dag = false;
00120   for(i=edge_list.size(); i>0; i--)
00121   {
00122     RefEdge* edge = edge_list.get_and_step();
00123     if(edge->start_vertex()->marked() == 2 &&
00124        edge->end_vertex()->marked() == 2)
00125     {
00126       update_dag = true;
00127       i=0;
00128     }
00129   }
00130   for( i = vertex_list.size(); i--; )
00131     if( vertex_list.step_and_get()->marked() == 2 )
00132       vertex_list.get()->marked(0);
00133     else
00134       vertex_list.change_to( 0 );
00135   vertex_list.remove_all_with_value(0);
00136   
00137   if ( keep && vertex_list.move_to(keep) )
00138     vertex_list.remove();
00139   
00140   if( vertex_list.size() == 0 )
00141   {
00142     PRINT_ERROR("Cannot create any composites from passed curves.\n");
00143     return 0;
00144   }
00145   vertex_list.reset();
00146   RefEdge* result = 0;
00147   DLIList<RefEdge*> vtx_edges;
00148   for( i = vertex_list.size(); i--; )
00149   {
00150     RefVertex* vtx = vertex_list.get_and_step();
00151     vtx_edges.clean_out();
00152     vtx->ref_edges(vtx_edges);
00153     //check to make sure that the two edges resides on the same surface(s)
00154     if ( vtx_edges.size() == 2 )
00155     {
00156       RefEdge* first_edge = vtx_edges.get();
00157       RefEdge* second_edge = vtx_edges.step_and_get();
00158       DLIList <RefFace*> common_faces;
00159       int size = first_edge->common_ref_faces(second_edge, common_faces);
00160       if (first_edge->num_ref_faces() != second_edge->num_ref_faces() ||
00161           size != first_edge->num_ref_faces())
00162       {
00163          PRINT_INFO("Curve %d and curve %d don't reside on the same surfaces.\n", first_edge->id(), second_edge->id());
00164          continue;
00165       }
00166     
00167       result = remove_vertex( vtx, false, update_dag, survivor );
00168       if (result)
00169       {
00170         // First remove any edges from the list that got destroyed in the
00171         // last remove_vertex operation.
00172         if(result == first_edge && modified_edges.move_to(second_edge))
00173         {
00174           modified_edges.remove();
00175         }
00176         else if(result == second_edge && modified_edges.move_to(first_edge))
00177         {
00178           modified_edges.remove();
00179         }
00180         modified_edges.append_unique(result);
00181       }
00182     }  
00183   }
00184   
00185   for ( i = modified_edges.size(); i--; )
00186     if ( ! modified_edges.step_and_get()->get_curve_ptr() )
00187       modified_edges.change_to(0);
00188   modified_edges.remove_all_with_value(0);
00189   
00190   result = modified_edges.size() ? modified_edges.get() : 0;
00191 
00192   DLIList<Surface*> update_surfaces, curve_surfaces;
00193   DLIList<TopologyBridge*> curve_bridges;
00194   for ( i = modified_edges.size(); i--; )
00195   {
00196     RefEdge* edge = modified_edges.get_and_step();
00197     edge->set_id( RefEntityFactory::instance()->next_ref_edge_id() );
00198     edge->bridge_manager()->get_bridge_list(curve_bridges);
00199     curve_bridges.reset();
00200     for (int j = curve_bridges.size(); j--; )
00201     {
00202       curve_surfaces.clean_out();
00203       curve_bridges.get_and_step()->surfaces(curve_surfaces);
00204       update_surfaces.merge_unique(curve_surfaces);
00205     }
00206   }
00207 
00208   update_surfaces.reset();
00209   for ( i = update_surfaces.size(); i--; )
00210   {
00211     GeometryQueryTool::instance()->make_RefFace(update_surfaces.get_and_step());
00212   }
00213   assert( !(survivor && survivor->deactivated()) );
00214   DAG::instance()->cleanout_deactivated_DAG_nodes();
00215 
00216   return result;
00217 }
00218 
00219 
00220 //-------------------------------------------------------------------------
00221 // Purpose       : Composite over a vertex
00222 //
00223 // Special Notes : 
00224 //
00225 // Creator       : Jason Kraftcheck
00226 //
00227 // Creation Date : 03/12/03
00228 //-------------------------------------------------------------------------
00229 RefEdge* CompositeTool::remove_vertex( RefVertex* vertex,
00230                                        bool remove_partitions, /* = false */
00231                                        bool update_dag ,       /* = true  */
00232                                        RefEdge* keep_edge      /* = NULL */ )
00233 {
00234   DLIList<RefEdge*> vertex_edges;
00235   int i;
00236   
00237     // Get two ref-edges
00238   vertex->ref_edges( vertex_edges );
00239   if ( vertex_edges.size() != 2 )
00240   {
00241     PRINT_ERROR("Cannot composite over valence-%d vertex.\n", vertex_edges.size());
00242     return 0;
00243   }
00244   
00245   DLIList<TopologyBridge*> point_bridges;
00246   DLIList<CoEdgeSM*> coedgesms;
00247     
00248   RefEdge *edge = 0, *refedge1 = 0, *refedge2 = 0;
00249   point_bridges.clean_out();
00250   vertex->bridge_manager()->get_bridge_list( point_bridges );
00251     
00252 
00253   int result_interval=-1;
00254   double result_size=-1;
00255   SizeIntervalType  result_size_type=NOT_SET; 
00256   FirmnessType  result_count_type=LIMP; 
00257 
00258   std::vector<CubitString> names_to_add;
00259   Curve* end_result = 0;
00260   point_bridges.reset();
00261   while( point_bridges.size() )
00262   {
00263     Curve* result_curve = 0;
00264     TBPoint* point = dynamic_cast<TBPoint*>(point_bridges.pop());
00265 
00266       // get the RefEdges that will be joined when the vertex is removed
00267     DLIList<Curve*> curves;
00268     point->curves(curves);
00269     curves.reset();
00270     
00271     if (curves.size() == 0)  // merged free vertex -- ignore it
00272       continue;
00273 
00274       // If only one curve, need to stitch point with some other
00275       // point in same vertex.
00276     if (curves.size() == 1) {
00277     
00278       /* Stitching code not complete.  Fail for now. */
00279       return 0;
00280       
00281       /*
00282       Curve* first_curve = curves.pop();
00283     
00284       TBPoint* other = 0;
00285       for ( i = point_bridges.size(); i--; ) {
00286         TBPoint* temp = dynamic_cast<TBPoint*>(point_bridges.step_and_get());
00287         curves.clean_out();
00288         temp->curves(curves);
00289         if ( curves.size() == 1 && curves.get()->owner() != first_curve->owner() ) 
00290         {
00291           point_bridges.extract();
00292           other = temp;
00293           break;
00294         }
00295       }
00296     
00297       if (!other)
00298         return 0;
00299       
00300       point = CompositeEngine::instance().stitch_points(point, other);
00301       if (!point)
00302         return 0;
00303         
00304       curves.append(first_curve);
00305       
00306       */
00307     } // end if (curves.size() == 1)
00308     
00309 
00310    // assert(curves.size() == 2);
00311     if(curves.size() != 2)
00312     {
00313       break;
00314     }
00315 
00316 
00317     TopologyEntity* topo = curves.get()->topology_entity();
00318     refedge1 = CAST_TO(topo, RefEdge);
00319     assert(refedge1 != NULL);
00320     curves.get()->set_saved_id(refedge1->id());
00321     DLIList<CubitString> tmp_names;
00322     std::vector<CubitString> edge1_names;
00323     refedge1->entity_names( tmp_names );
00324     curves.get()->set_saved_names( tmp_names.as_vector() );
00325     for( int i=tmp_names.size(); i--; )
00326       edge1_names.push_back( tmp_names.get_and_step() );
00327     tmp_names.clean_out();
00328     refedge1->remove_entity_names();
00329 
00330     topo = curves.next()->topology_entity();
00331     refedge2 = CAST_TO(topo, RefEdge);
00332     assert(refedge2 != NULL);   
00333     curves.next()->set_saved_id(refedge2->id());
00334     std::vector<CubitString> edge2_names;
00335     refedge2->entity_names( tmp_names );
00336     curves.next()->set_saved_names( tmp_names.as_vector() );
00337     for( int i=tmp_names.size(); i--; )
00338       edge2_names.push_back( tmp_names.get_and_step() );
00339     refedge2->remove_entity_names();
00340 
00341 
00342 
00343     determine_combined_edges_interval_or_size( refedge1,refedge2,result_interval,result_size,result_count_type,result_size_type); 
00344 
00345 
00346     Curve* keep = 0;
00347     if (keep_edge) 
00348     {
00349       if (keep_edge->bridge_manager() == curves.get()->owner())
00350         keep = curves.get();
00351       else if (keep_edge->bridge_manager() == curves.next()->owner())
00352         keep = curves.next();
00353     }
00354 
00355       // remove the point to make the composite curve
00356     PartitionPoint* part = dynamic_cast<PartitionPoint*>(point);
00357     if( remove_partitions && part )
00358       result_curve = PartitionEngine::instance().remove_point( part );
00359     if ( !result_curve )
00360       result_curve = CompositeEngine::instance().remove_point( point, remove_partitions, keep );
00361 
00362     if( !result_curve )
00363     {
00364       //reapply names
00365       for( int i=edge1_names.size(); i--; )
00366         refedge1->entity_name( edge1_names[i] );
00367       for( int i=edge2_names.size(); i--; )
00368         refedge2->entity_name( edge2_names[i] );
00369 
00370       PRINT_ERROR("Failed to remove vertex %d\n", vertex->id() );
00371       break;
00372     }
00373     else if( !edge )
00374     {
00375       edge = dynamic_cast<RefEdge*>(result_curve->topology_entity());     
00376     }
00377     else
00378     {
00379       if( result_curve->owner() )
00380         result_curve->owner()->remove_bridge( result_curve );
00381       edge->bridge_manager()->add_bridge( result_curve );
00382         
00383       Curve* curve = edge->get_curve_ptr();
00384       bool geom_sense = curve->relative_sense( result_curve ) == CUBIT_FORWARD;
00385       bool bridge_sense = curve->bridge_sense() == result_curve->bridge_sense();
00386       if( geom_sense != bridge_sense )
00387         result_curve->reverse_bridge_sense();
00388 
00389       coedgesms.clean_out();
00390       result_curve->coedgesms( coedgesms );
00391       while( coedgesms.size() )
00392       { 
00393         CoEdgeSM* coe = coedgesms.pop();
00394         if( coe->owner() )
00395           coe->owner()->remove_bridge( coe );
00396       }
00397     }
00398 
00399     names_to_add.insert(names_to_add.end(), edge1_names.begin(), edge1_names.end() );
00400     names_to_add.insert(names_to_add.end(), edge2_names.begin(), edge2_names.end() );
00401     
00402     if ( result_curve )
00403       end_result = result_curve;
00404   }
00405   
00406   RefEdge* result = NULL;
00407   if(end_result)
00408     result = dynamic_cast<RefEdge*>(end_result->topology_entity());
00409     
00410   RefEdge* dead = NULL;
00411   if(result)
00412   {
00413     // notify observers that one edge is being composited into another
00414     // TODO - make a simple function for this notification since it is  times????
00415     dead = result != refedge1 ? refedge1 : result != refedge2 ? refedge2 : 0;
00416     update_combined_edges( result, dead ,result_interval,result_size,result_count_type,result_size_type);
00417 
00418     //append all names to this ref entity
00419     for (size_t k = 0; k < names_to_add.size(); k++)
00420       result->entity_name( names_to_add[k] );
00421     
00422   }
00423 
00424   if ( result && update_dag )
00425   {
00426     CubitBoolean flag = CGMApp::instance()->attrib_manager()->auto_actuate_flag(CA_MERGE_PARTNER);
00427     CGMApp::instance()->attrib_manager()->set_auto_actuate_flag(CA_MERGE_PARTNER, CUBIT_TRUE);
00428     
00429     DLIList<RefFace*> parent_faces;
00430     result->ref_faces( parent_faces );
00431     
00432     for( i = parent_faces.size(); i--; )
00433     {
00434       Surface* surf = parent_faces.get_and_step()->get_surface_ptr();
00435       GeometryQueryTool::instance()->make_RefFace( surf );
00436     }
00437     if ( !parent_faces.size() && end_result) // free curves
00438     {
00439       RefEdge* edge = GeometryQueryTool::instance()->make_RefEdge(end_result);
00440       RefEdge* dead = edge == refedge1 ? refedge2 : edge == refedge2 ? refedge1 : 0;
00441       assert( dead && !dead->get_curve_ptr() );
00442       dead->remove_from_DAG();
00443     }
00444     assert( !(keep_edge && keep_edge->deactivated()) );
00445     DAG::instance()->cleanout_deactivated_DAG_nodes();
00446     CGMApp::instance()->attrib_manager()->set_auto_actuate_flag(CA_MERGE_PARTNER, flag);
00447   }
00448 
00449   
00450   return result;
00451 }
00452 
00453 
00454 /*
00455 CubitStatus CompositeTool::make_mergeable( GeometryEntity* bridge1,
00456                                            GeometryEntity* bridge2 )
00457 {
00458   BasicTopologyEntity *bte1, *bte2;
00459   bte1 = dynamic_cast<BasicTopologyEntity*>(bridge1->topology_entity());
00460   bte2 = dynamic_cast<BasicTopologyEntity*>(bridge2->topology_entity());
00461   if( (!bte1) == (!bte2) ) // 1 must be null and one non-null
00462     return CUBIT_FAILURE;
00463   
00464   if( bte2 )
00465   {
00466     bte1 = bte2;
00467     GeometryEntity* tmp = bridge1;
00468     bridge1 = bridge2;
00469     bridge2 = tmp;
00470   }
00471   
00472   DLIList<CubitSimpleAttrib> csa_list;
00473   bridge1->get_simple_attribute( csa_list );
00474   CubitSimpleAttrib* csa = 0;
00475   for( int i = csa_list.size(); !csa && i--; )
00476     if( CubitAttrib::attrib_type(csa_list.step_and_get()) == CA_MERGE_PARTNER )
00477       csa = csa_list.get();
00478   
00479   if( !csa )
00480   {
00481     int merge_id = TDUniqueId::get_unique_id(bte1);
00482     csa = CAMergePartner::cubit_simple_attrib(merge_id);
00483     bridge1->append_simple_attribute( csa );
00484   }
00485  
00486   assert(csa);
00487   bridge2->append_simple_attribute( csa );
00488   delete csa;
00489   return CUBIT_SUCCESS;
00490 }
00491 */
00492   
00493 
00494 //-------------------------------------------------------------------------
00495 // Purpose       : Create a composite surface
00496 //
00497 // Special Notes : 
00498 //
00499 // Creator       : Jason Kraftcheck
00500 //
00501 // Creation Date : 
00502 //-------------------------------------------------------------------------
00503 RefFace* CompositeTool::composite( DLIList<RefFace*>& face_list,
00504                                    RefFace* keep_face /* = 0 */ )
00505 {
00506   int i;
00507   DLIList<RefFace*> modified_faces;
00508 
00509     // Get all edges in the faces in face_list
00510   DLIList<TopologyEntity*> query_input(face_list.size()), query_output;
00511   CAST_LIST_TO_PARENT(face_list, query_input);
00512   ModelQueryEngine::instance()
00513     ->query_model( query_input, DagType::ref_edge_type(), query_output );
00514   DLIList<RefEdge*> edge_list(query_output.size());
00515   CAST_LIST(query_output, edge_list, RefEdge);
00516   
00517     // Remove all edges that don't occur in exactly two faces in list
00518   edge_list.last();
00519   DLIList<CoEdge*> coedges;
00520   for (i = edge_list.size(); i--; )
00521   {
00522     RefEdge* edge = edge_list.step_and_get();
00523     coedges.clean_out();
00524     edge->co_edges(coedges);
00525     if (coedges.size() == 2)
00526     {
00527       RefFace* face1 = coedges.get()->get_ref_face();
00528       RefFace* face2 = coedges.next()->get_ref_face();
00529       // Check to make sure both faces are in the faces we are compositing
00530       // and also make sure the faces are not the same otherwise we
00531       // will composite out hardlines in one of the faces.
00532       if (face1 != face2 &&
00533         face_list.is_in_list(face1) && face_list.is_in_list(face2))
00534         continue;
00535     }
00536     
00537     edge_list.change_to(0);
00538   }
00539   edge_list.remove_all_with_value(0);
00540   
00541   if( edge_list.size() == 0 )
00542   {
00543     PRINT_ERROR("Cannot create composites from the specified surfaces.\n");
00544     return 0;
00545   } 
00546 
00547   edge_list.reset();
00548   for( i = edge_list.size(); i--; )
00549   {
00550     RefEdge* edge = edge_list.get_and_step();
00551     RefFace* face = remove_edge( edge, false, false, keep_face );      
00552     if (face)
00553       modified_faces.append_unique(face);
00554   }
00555   
00556   for ( i = modified_faces.size(); i--; )
00557     if( ! modified_faces.step_and_get()->get_surface_ptr() )
00558       modified_faces.change_to(0);
00559   modified_faces.remove_all_with_value(0);  
00560   
00561   RefFace* result = modified_faces.size() ? modified_faces.get() : 0;
00562 
00563 #ifdef ALPHA_TREADSWEEP
00564   // Make sure names from all of the faces get added to the
00565   // list of names in the result.
00566   if(result)
00567   {
00568     for(i=face_list.size(); i--;)
00569     {
00570       RefFace *cur_face = face_list.get_and_step();
00571       if(cur_face != result)
00572       {
00573         result->merge_entity_names(cur_face);
00574       }
00575     }
00576   }
00577 #endif
00578 
00579   DLIList<RefVolume*> vol_list, surf_vols;
00580   for ( i = modified_faces.size(); i--; )
00581   {
00582     RefFace* face = modified_faces.get_and_step();
00583     face->set_id( RefEntityFactory::instance()->next_ref_face_id() );
00584     surf_vols.clean_out();
00585     face->ref_volumes(surf_vols);
00586     vol_list.merge_unique(surf_vols);
00587   }
00588   
00589   vol_list.reset();
00590   for ( i = vol_list.size(); i--; )
00591   {
00592     RefVolume* vol = vol_list.get_and_step();
00593     Lump* lump = vol->get_lump_ptr();
00594     GeometryQueryTool::instance()->make_Body(lump->bodysm());
00595   }
00596   assert( !(keep_face && keep_face->deactivated()) );
00597   DAG::instance()->cleanout_deactivated_DAG_nodes();
00598 
00599   return result;
00600 }
00601 
00602 //-------------------------------------------------------------------------
00603 // Purpose       : Composite over a curve
00604 //
00605 // Special Notes : 
00606 //
00607 // Creator       : Jason Kraftcheck
00608 //
00609 // Creation Date : 03/12/03
00610 //-------------------------------------------------------------------------
00611 RefFace* CompositeTool::remove_edge( RefEdge* edge,
00612                                      bool remove_partitions, /* = false */
00613                                      bool update_dag,        /* = true  */
00614                                      RefFace* keep_face      /* = NULL  */ )
00615 {
00616   int i;
00617 
00618   DLIList<CoEdge*> edge_coedges;
00619   edge->co_edges(edge_coedges);
00620   if (edge_coedges.size() != 2 && 
00621      (edge->get_curve_ptr()->geometry_type() != POINT_CURVE_TYPE ||
00622       edge_coedges.size() != 1))
00623   {
00624     PRINT_ERROR("Cannot composite over %d-valent curve %d (%s)\n",
00625       edge_coedges.size(), edge->id(), edge->entity_name().c_str());
00626     return NULL;
00627   }
00628 
00629   DLIList<TopologyBridge*> curves(edge->bridge_manager()->number_of_bridges());
00630   edge->bridge_manager()->get_bridge_list( curves );
00631 
00632   DLIList<Surface*> surfaces;
00633   assert(curves.size());
00634   curves.get()->surfaces( surfaces );
00635   if ( surfaces.size() > 2  || surfaces.size() < 1 )
00636   {
00637     PRINT_ERROR("Cannot composite over %d-valence curve %d\n",
00638       surfaces.size(), edge->id() );
00639     return 0;
00640   }
00641     
00642   RefFace* face = 0;
00643 
00644   // These will be the two RefFaces associated with the two 
00645   // surfaces being composited.  We need to store them before we
00646   // get to the call to remove_curve because after that we won't
00647   // have access to both of them and we need to pass both of them
00648   // down to update_combined_faces.
00649   RefFace *face1 = NULL;
00650   RefFace *face2 = NULL;
00651     
00652   std::vector<CubitString> names_to_add;
00653   curves.reset();
00654   Surface* surface = 0;
00655   for( i = curves.size(); i--; )
00656   {
00657     Curve* curve = dynamic_cast<Curve*>(curves.get_and_step());
00658 
00659       // get the two Surfaces that will be involved in the composite operation
00660       // when the curve is removed
00661     DLIList<Surface*> surfs;
00662     curve->surfaces(surfs);
00663     assert(surfs.size() > 0  && surfs.size() <= 2);  // should be one or two surfs
00664     face1 = dynamic_cast<RefFace*>(surfs.get()->topology_entity());
00665     face2 = dynamic_cast<RefFace*>(surfs.next()->topology_entity());
00666 
00667     //Save the names and ids
00668     surfs.get()->set_saved_id(face1->id());
00669     DLIList<CubitString> tmp_names;
00670     face1->entity_names( tmp_names );        
00671     surfs.get()->set_saved_names( tmp_names.as_vector() );
00672     std::vector<CubitString> face1_names = tmp_names.as_vector();
00673     tmp_names.clean_out();       
00674     face1->remove_entity_names();
00675     
00676     surfs.next()->set_saved_id(face2->id());
00677     face2->entity_names( tmp_names );        
00678     surfs.next()->set_saved_names( tmp_names.as_vector() );
00679     std::vector<CubitString> face2_names = tmp_names.as_vector();
00680     tmp_names.clean_out();       
00681     face2->remove_entity_names();
00682 
00683       // if only one surface, the edge should be internal to a composite surface
00684     surfs.reset();
00685 
00686       // Composite the surfaces
00687     Surface* result = 0;
00688     PartitionCurve* partcurve = 0;
00689     if ( !(partcurve = dynamic_cast<SegmentedCurve*>(curve)) )
00690       partcurve = dynamic_cast<PartPTCurve*>(curve);
00691     
00692     Surface* keep = 0;
00693     if (keep_face) {
00694       if (surfs.get()->owner() == keep_face->bridge_manager())
00695         keep = surfs.get();
00696       else if (surfs.next()->owner() == keep_face->bridge_manager())
00697         keep = surfs.next();
00698     }
00699     if( remove_partitions && partcurve )
00700       result = PartitionEngine::instance().remove_curve( partcurve );
00701     if( !result )
00702       result = CompositeEngine::instance().remove_curve( curve, remove_partitions, keep );
00703 
00704     if( !result )
00705     {
00706       //reapply names
00707       for( int i=face1_names.size(); i--; )
00708         face1->entity_name( face1_names[i] );
00709       for( int i=face2_names.size(); i--; )
00710         face2->entity_name( face2_names[i] );
00711 
00712       PRINT_ERROR("Failed to remove curve %d\n",edge->id());
00713       break;
00714     }
00715     else if( !face )  // get surviving refface
00716     {
00717       face = dynamic_cast<RefFace*>(result->topology_entity());
00718     }
00719     
00720     else  // merge resulting composites into surviving refface
00721     {
00722       RefFace* old_face = dynamic_cast<RefFace*>(result->topology_entity());
00723       if( old_face != face )
00724       {
00725         if( old_face )
00726           old_face->bridge_manager()->remove_bridge( result );
00727         face->bridge_manager()->add_bridge( result );                
00728       }
00729     }
00730     
00731     names_to_add.insert(names_to_add.end(), face1_names.begin(), face1_names.end() );
00732     names_to_add.insert(names_to_add.end(), face2_names.begin(), face2_names.end() );
00733       
00734     if( result )
00735       surface = result;
00736   }
00737   
00738   if( !surface )
00739   {
00740     PRINT_ERROR("Failed to remove curve %d\n", edge->id() );
00741     return 0;
00742   }
00743   
00744   RefFace* result = dynamic_cast<RefFace*>(surface->topology_entity());
00745   assert( result == face );
00746 
00747   //append all names to this ref entity
00748   for (size_t k = 0; k < names_to_add.size(); k++)
00749     result->entity_name( names_to_add[k] );
00750 
00751     // notify observers that one face is being composited into another
00752 
00753   // We need to pass the result face and also the one that wasn't chosen
00754   // as the result face.
00755   RefFace *delete_face = face1;
00756   if(result == delete_face)
00757     delete_face = face2;
00758   update_combined_faces( result, edge, delete_face );
00759   
00760   if ( update_dag )
00761   {
00762     DLIList<RefVolume*> modified_volumes;
00763     result->ref_volumes(modified_volumes);
00764     for( i = modified_volumes.size(); i--; )
00765     {
00766       RefVolume* volume = modified_volumes.get_and_step();
00767       Lump* lump = volume->get_lump_ptr();
00768       GeometryQueryTool::instance()->make_Body(lump->bodysm());
00769     }
00770 
00771     assert( !(keep_face && keep_face->deactivated()) );
00772     DAG::instance()->cleanout_deactivated_DAG_nodes();
00773   }
00774   
00775   return result;
00776 }
00777 
00778 //-------------------------------------------------------------------------
00779 // Purpose       : Create a composite volume
00780 //
00781 // Special Notes : 
00782 //
00783 // Creator       : Jason Kraftcheck
00784 //
00785 // Creation Date : 09/25/01
00786 //-------------------------------------------------------------------------
00787 RefVolume* CompositeTool::composite( DLIList<RefVolume*>& volumes,
00788                                      Body** body_ptr /* = 0 */ )
00789 {
00790   int i;
00791   DLIList<RefVolume*> modified_vols;
00792   DLIList<Body*> input_bodies;
00793   for (i = volumes.size(); i--; )
00794     input_bodies.append_unique( volumes.get_and_step()->get_body_ptr() );
00795 
00796     // Get all faces in the volumes
00797   DLIList<TopologyEntity*> query_input(volumes.size()), query_output;
00798   CAST_LIST_TO_PARENT(volumes, query_input);
00799   ModelQueryEngine::instance()
00800     ->query_model( query_input, DagType::ref_face_type(), query_output );
00801   DLIList<RefFace*> faces(query_output.size());
00802   CAST_LIST(query_output, faces, RefFace);
00803   
00804     // Remove all faces that don't occur in exactly two volumes in list
00805   faces.last();
00806   DLIList<CoFace*> cofaces;
00807   for (i = faces.size(); i--; )
00808   {
00809     RefFace* face = faces.step_and_get();
00810     cofaces.clean_out();
00811     face->co_faces(cofaces);
00812     if (cofaces.size() == 2)
00813     {
00814       RefVolume* vol1 = cofaces.get()->get_ref_volume();
00815       RefVolume* vol2 = cofaces.next()->get_ref_volume();
00816       if (volumes.is_in_list(vol1) && volumes.is_in_list(vol2))
00817         continue;
00818     }
00819     
00820     faces.change_to(0);
00821   }
00822   faces.remove_all_with_value(0);
00823   
00824   if( faces.size() == 0 )
00825   {
00826     PRINT_ERROR("Cannot create composites from the specified volumes.\n");
00827     return 0;
00828   }
00829   
00830   faces.reset();
00831   for( i = faces.size(); i--; )
00832   {
00833     RefFace* face = faces.get_and_step();
00834     RefVolume* vol = remove_face( face, false, false );
00835     if (vol)
00836       modified_vols.append_unique(vol);
00837   }
00838   
00839   for ( i = modified_vols.size(); i--; )
00840     if( ! modified_vols.step_and_get()->get_lump_ptr() )
00841       modified_vols.change_to(0);
00842   modified_vols.remove_all_with_value(0);  
00843   
00844   RefVolume* result = modified_vols.size() ? modified_vols.get() : 0;
00845   for ( i = modified_vols.size(); i--; )
00846   {
00847     RefVolume* vol = modified_vols.get_and_step();
00848     vol->set_id( RefEntityFactory::instance()->next_ref_volume_id() );
00849   }
00850   
00851   input_bodies.reset();
00852   for ( i = input_bodies.size(); i--; )
00853   {
00854     Body* body = input_bodies.get_and_step();
00855     BodySM* sm = body->get_body_sm_ptr();
00856     if (sm)
00857       GeometryQueryTool::instance()->make_Body(sm);
00858     else
00859       GeometryQueryTool::instance()->destroy_dead_entity( body );
00860   }
00861   DAG::instance()->cleanout_deactivated_DAG_nodes();
00862    
00863   if (body_ptr)
00864     *body_ptr = result->get_body_ptr();
00865   return result;
00866 }
00867 
00868 //-------------------------------------------------------------------------
00869 // Purpose       : Composite over a surface
00870 //
00871 // Special Notes : 
00872 //
00873 // Creator       : Jason Kraftcheck
00874 //
00875 // Creation Date : 03/12/03
00876 //-------------------------------------------------------------------------
00877 RefVolume* CompositeTool::remove_face( RefFace* face,
00878                                   bool remove_partitions, /* = false */
00879                                   bool update_dag         /* = true  */)
00880 {
00881   int i;
00882 
00883   DLIList<RefVolume*> vol_list(2);
00884   face->ref_volumes( vol_list );
00885 
00886   DLIList<CoFace*> face_cofaces;
00887   face->co_faces(face_cofaces);
00888   if (face_cofaces.size() != 2)
00889   {
00890     PRINT_ERROR("Cannot composite over %d-valent surface %d (%s)\n",
00891       face_cofaces.size(), face->id(), face->entity_name().c_str());
00892     return NULL;
00893   }
00894 
00895   DLIList<TopologyBridge*> surfs(face->bridge_manager()->number_of_bridges());
00896   face->bridge_manager()->get_bridge_list( surfs );
00897   
00898     // Seam topology
00899   Surface *surf1 = 0, *surf2 = 0;
00900   if (surfs.size()  == 2)
00901   {
00902     surfs.reset();
00903     surf1 = dynamic_cast<Surface*>(surfs.get());
00904     surf2 = dynamic_cast<Surface*>(surfs.next());
00905     
00906     DLIList<RefEdge*> edge_list;
00907     DLIList<TopologyBridge*> bridges, ptcurves;
00908     DLIList<Surface*> surfaces;
00909     face->ref_edges( edge_list );
00910     while( edge_list.size() )
00911     {
00912       RefEdge* edge = edge_list.pop();
00913       edge->bridge_manager()->get_bridge_list( bridges );
00914       TopologyBridge *curve1 = 0, *curve2 = 0;
00915       while (bridges.size())
00916       {
00917         TopologyBridge* curve = bridges.pop();
00918         surfaces.clean_out();
00919         curve->surfaces( surfaces );
00920         if (surfaces.is_in_list(surf1))
00921           curve1 = curve;
00922         if (surfaces.is_in_list(surf2))
00923           curve2 = curve;
00924       }
00925       
00926       assert(curve1 && curve2);
00927       if (curve1 == curve2)
00928         continue;
00929       
00930       for (int i = 0; i < 2; i++)
00931       {
00932         RefVertex* vtx = i ? edge->end_vertex() : edge->start_vertex();
00933         vtx->bridge_manager()->get_bridge_list( bridges );
00934         TopologyBridge *point1 = 0, *point2 = 0;
00935         while (bridges.size())
00936         {
00937           TopologyBridge* point = bridges.pop();
00938           ptcurves.clean_out();
00939           point->get_parents(ptcurves);
00940           if (ptcurves.is_in_list( curve1 ))
00941             point1 = point;
00942           if (ptcurves.is_in_list( curve2 ))
00943             point2 = point;
00944         }
00945         
00946         if (point1 != point2)
00947           CompositeEngine::instance().stitch_points( 
00948             dynamic_cast<TBPoint*>(point1), 
00949             dynamic_cast<TBPoint*>(point2) );
00950       }
00951       
00952       CompositeEngine::instance().stitch_curves( 
00953             dynamic_cast<Curve*>(curve1), 
00954             dynamic_cast<Curve*>(curve2) );
00955     }
00956   }
00957   else if (surfs.size() == 1)
00958   {
00959      surf1 = dynamic_cast<Surface*>(surfs.get());
00960      surf2 = 0;
00961   }
00962   else
00963   {
00964     return 0;
00965   }
00966 
00967   DLIList<Lump*> lumps, tmp;
00968   surf1->lumps( lumps );
00969   if (surf2)
00970   {
00971     surf2->lumps(tmp);
00972     lumps.merge_unique(tmp);
00973   }
00974   if ( lumps.size() > 2  || lumps.size() < 1 )
00975   {
00976     PRINT_ERROR("Cannot composite over %d-valence surface %d\n",
00977       lumps.size(), face->id() );
00978     return 0;
00979   }
00980     
00981     // get the two Lumps that will be involved in the composite operation
00982     // when the surface is removed
00983   Lump* lump = 0;
00984   RefVolume *tmp_vol = dynamic_cast<RefVolume*>(lumps.get()->topology_entity());
00985   lumps.get()->set_saved_id( tmp_vol->id() );
00986   DLIList<CubitString> names;
00987   tmp_vol->entity_names( names );
00988   lumps.get()->set_saved_names( names.as_vector() );
00989   names.clean_out();  
00990 
00991   tmp_vol = dynamic_cast<RefVolume*>(lumps.get()->topology_entity());
00992   lumps.next()->set_saved_id( tmp_vol->id() );
00993   tmp_vol->entity_names( names );
00994   lumps.next()->set_saved_names( names.as_vector() );
00995 
00996     // if only one lump, the surface should be internal to a composite lump
00997   lumps.reset();
00998 
00999     // Composite the lumps
01000   PartitionSurface* partsurf = dynamic_cast<PartitionSurface*>(surf1);
01001   if( surf1 == surf2 && remove_partitions && partsurf )
01002     lump = PartitionEngine::instance().remove_surface( partsurf );
01003   if( !lump )
01004     lump = CompositeEngine::instance().remove_surface( surf1, surf2, remove_partitions );
01005 
01006   if( !lump )
01007   {
01008     PRINT_ERROR("Failed to remove surface %d\n",face->id());
01009     return 0;
01010   }
01011   
01012   RefVolume* result = dynamic_cast<RefVolume*>(lump->topology_entity());
01013   
01014     // notify observers that one face is being composited into another
01015   RefVolume* dead_vol =0;
01016   if (vol_list.size() > 1)
01017   {
01018     vol_list.move_to( result );
01019     dead_vol = vol_list.next();
01020   }
01021   update_combined_vols( result, dead_vol );
01022   
01023   if ( update_dag )
01024   {
01025     DLIList<Body*> modified_bodies;
01026     result->bodies(modified_bodies);
01027     for( i = modified_bodies.size(); i--; )
01028     {
01029       Body* body = modified_bodies.get_and_step();
01030       BodySM* sm = body->get_body_sm_ptr();
01031       if (sm)
01032         GeometryQueryTool::instance()->make_Body(sm);
01033       else
01034         GeometryQueryTool::instance()->destroy_dead_entity( body );
01035     }
01036 
01037     DAG::instance()->cleanout_deactivated_DAG_nodes();
01038   }
01039   
01040   return result;
01041 }
01042 
01043 
01044 //-------------------------------------------------------------------------
01045 // Purpose       : Create a composite body
01046 //
01047 // Special Notes : 
01048 //
01049 // Creator       : Jason Kraftcheck
01050 //
01051 // Creation Date : 10/02/01
01052 //-------------------------------------------------------------------------
01053 Body* CompositeTool::composite( DLIList<Body*>& )
01054 {
01055   return 0;
01056 }
01057 
01058 
01059 //-------------------------------------------------------------------------
01060 // Purpose       : Check for the topological validity of a possible composite
01061 //
01062 // Special Notes : 
01063 //
01064 // Creator       : Jason Kraftcheck
01065 //
01066 // Creation Date : 
01067 //-------------------------------------------------------------------------
01068 CubitBoolean CompositeTool::okayToComposite( 
01069                         DLIList<BasicTopologyEntity*>& bte_list,
01070                         DLIList<BasicTopologyEntity*>* boundary,
01071                         DLIList<BasicTopologyEntity*>* internal,
01072                         bool print_errors,
01073                         bool force_same_parents ) const
01074 {
01075   //check that all entities are of the same type
01076   bte_list.reset();
01077   DagType type = bte_list.get_and_step()->dag_type();
01078   if( (type != DagType::ref_face_type()) && 
01079       (type != DagType::ref_edge_type()) && 
01080       (type != DagType::ref_volume_type()) )
01081   {
01082     if (print_errors) 
01083       PRINT_ERROR("Invalid entities passed to CompositeTool::okayToComposite().\n");
01084     return CUBIT_FALSE;
01085   }
01086   int i;
01087   for( i = bte_list.size(); i > 1; i-- )
01088   {
01089     if( bte_list.get_and_step()->dag_type() != type )
01090     {
01091       if (print_errors) PRINT_ERROR("Cannot combine entities of different dimensionality.\n");
01092       return CUBIT_FALSE;
01093     }
01094   }
01095   
01096   //check that all entities are C0-continous
01097   DLIList<RefEntity*> unchecked_entities, current_entities,
01098                   next_entities, child_entities, temp_list ;
01099   CAST_LIST_TO_PARENT( bte_list, unchecked_entities);
01100   current_entities.append( unchecked_entities.pop() );
01101 
01102   while( current_entities.size() > 0 )
01103   {
01104     next_entities.clean_out();
01105     child_entities.clean_out();
01106 
01107     
01108     // Get all adjacent entities
01109     for( i = current_entities.size(); i > 0; i-- )
01110     {
01111       temp_list.clean_out();
01112       current_entities.get_and_step()->get_child_ref_entities( temp_list );
01113       child_entities.merge_unique( temp_list );
01114     }
01115 
01116     for( i = child_entities.size(); i > 0; i-- )
01117     {
01118       temp_list.clean_out();
01119       child_entities.get_and_step()->get_parent_ref_entities( temp_list );
01120       next_entities.merge_unique( temp_list );
01121     }
01122     
01123     temp_list.clean_out();
01124     for( i = next_entities.size(); i > 0; i-- )
01125     {
01126       RefEntity* entity_ptr = next_entities.get_and_step();
01127 
01128       if( unchecked_entities.move_to( entity_ptr ) )
01129       {
01130         temp_list.append( entity_ptr );
01131         unchecked_entities.extract();
01132       }
01133     }
01134     current_entities = temp_list;
01135   }
01136   if( unchecked_entities.size() == 1 )
01137   {
01138     if (print_errors) 
01139     {
01140       PRINT_ERROR("%s is not connected to any others.\n",
01141         unchecked_entities.get()->entity_name().c_str() );
01142       if( unchecked_entities.get()->dag_type() == DagType::ref_volume_type() )
01143         PRINT_ERROR("\tTry merging first.\n");
01144     }
01145     return CUBIT_FALSE;
01146   }
01147   else if( unchecked_entities.size() > 1 )
01148   {
01149     if (print_errors) {
01150       PRINT_ERROR("Entities \n");
01151       for( i = unchecked_entities.size(); i > 0; i-- )
01152         PRINT_INFO("%d, ",unchecked_entities.get_and_step()->id());
01153       PRINT_INFO("do not appear to be connected to the others.\n");
01154     }
01155     
01156     return CUBIT_FALSE;
01157   }
01158   
01159   //Check that all common children have at most two
01160   //parents (and those parents are in the list of entities to
01161   //composite).
01162   unchecked_entities.clean_out();
01163   child_entities.clean_out();
01164   CAST_LIST_TO_PARENT( bte_list, unchecked_entities);
01165   for( i = unchecked_entities.size(); i > 0; i-- )
01166   {
01167     temp_list.clean_out();
01168     unchecked_entities.get_and_step()->get_child_ref_entities( temp_list );
01169     child_entities.merge_unique( temp_list );
01170   }
01171   
01172   DLIList<SenseEntity*> sense_entity_list;
01173   for( i = child_entities.size(); i > 0; i-- )
01174   {
01175     int parent_count = 0;
01176     current_entities.clean_out();
01177     RefEntity* child_ptr = child_entities.step_and_get();
01178     sense_entity_list.clean_out();
01179     CAST_TO(child_ptr,BasicTopologyEntity)->get_sense_entity_list( sense_entity_list );
01180     for( int k = sense_entity_list.size(); k > 0; k-- )
01181       current_entities.append( sense_entity_list.get_and_step()->
01182         get_grouping_entity_ptr()->get_basic_topology_entity_ptr() );
01183     for( int j = current_entities.size(); j> 0; j-- )
01184       if( unchecked_entities.move_to( current_entities.get_and_step() ) )
01185         parent_count++;
01186     switch( parent_count )
01187     {
01188       case 0:
01189 //        assert( parent_count != 0 ); break;
01190         return CUBIT_FALSE;
01191       case 1:
01192         if( boundary != NULL ) boundary->
01193           append( CAST_TO( child_entities.get(), BasicTopologyEntity) );
01194         break;
01195       case 2:
01196         if( current_entities.size() != 2 )
01197         {
01198           if (print_errors) PRINT_ERROR("Child entity %d cannot be removed.\n",
01199                                         child_entities.get()->id() );
01200           return CUBIT_FALSE;
01201         }
01202         if( internal != NULL ) internal->
01203           append( CAST_TO( child_entities.get(), BasicTopologyEntity) );
01204         break;
01205       default:
01206         if (print_errors) PRINT_ERROR("Entities are not simply connected.\n");
01207         return CUBIT_FALSE;
01208     }
01209   }
01210   
01211     //Check that all entities to merge are common to all parent grouping entities.
01212   if( force_same_parents )
01213   {
01214     assert( type.functional_type() == DagType::BasicTopologyEntity_TYPE );
01215     const DagType type_2 = DagType( type.dimension(), DagType::GroupingEntity_TYPE );
01216     DLIList<TopologyEntity*> first_entity_parents, current_entity_parents;
01217     bte_list.reset();
01218     ModelQueryEngine::instance()->query_model( 
01219       *(bte_list.get_and_step()), type_2, first_entity_parents ); 
01220 
01221     for( i = bte_list.size(); i > 1; i-- )
01222     {
01223       current_entity_parents.clean_out();
01224       ModelQueryEngine::instance()->query_model(
01225         *(bte_list.get_and_step()), type_2, current_entity_parents );
01226 
01227       if( current_entity_parents != first_entity_parents )  
01228       {
01229         if (print_errors) PRINT_ERROR("All entities to be combined must have common "
01230                                       "topological parents.\n");
01231         return CUBIT_FALSE;
01232       }
01233     }
01234   }
01235     
01236   return CUBIT_TRUE;
01237 }
01238 
01239 //-------------------------------------------------------------------------
01240 // Purpose       : Classify child topology
01241 //
01242 // Special Notes : 
01243 //
01244 // Creator       : Jason Kraftcheck
01245 //
01246 // Creation Date : 
01247 //-------------------------------------------------------------------------
01248 CubitStatus CompositeTool::classify_children( 
01249                                  DLIList<BasicTopologyEntity*>& bte_list,
01250                                  DLIList<BasicTopologyEntity*>& boundary_children,
01251                                  DLIList<BasicTopologyEntity*>& interior_children,
01252                                  DLIList<BasicTopologyEntity*>& unknown_children )
01253 {
01254   DLIList<RefEntity*> ref_entity_list, all_children;
01255   RefEntity *child_ptr, *parent_ptr;
01256   BasicTopologyEntity* bte_ptr;
01257   int i, j;
01258   for( i = bte_list.size(); i > 0; i-- )
01259   {
01260     ref_entity_list.clean_out();
01261     bte_list.get_and_step()->get_child_ref_entities( ref_entity_list );
01262     all_children.merge_unique( ref_entity_list );
01263   }
01264   for( i = all_children.size(); i > 0; i-- )
01265   {
01266     ref_entity_list.clean_out();
01267     child_ptr = all_children.get_and_step();
01268     child_ptr->get_parent_ref_entities( ref_entity_list );
01269     
01270     int parent_count = 0;
01271     for( j = ref_entity_list.size(); j > 0; j-- )
01272     {
01273       parent_ptr = ref_entity_list.get_and_step();
01274       bte_ptr = CAST_TO( parent_ptr, BasicTopologyEntity );
01275       if( bte_list.move_to( bte_ptr ) ) parent_count++;
01276     }
01277     
01278     bte_ptr = CAST_TO( child_ptr, BasicTopologyEntity );
01279     if( parent_count == 1 )
01280       boundary_children.append( bte_ptr );
01281     else if( parent_count == ref_entity_list.size() )
01282       interior_children.append( bte_ptr );
01283     else
01284       unknown_children.append( bte_ptr );
01285   }
01286   return CUBIT_SUCCESS;
01287 }
01288   
01289   
01290   
01291 
01292 //-------------------------------------------------------------------------
01293 // Purpose       : remove a composite edge, restoring the orignial edges.
01294 //
01295 // Special Notes : 
01296 //
01297 // Creator       : Jason Kraftcheck
01298 //
01299 // Creation Date : 
01300 //-------------------------------------------------------------------------
01301 CubitStatus CompositeTool::uncomposite( RefEdge* composite_edge, 
01302                                         DLIList<RefEdge*>* restored_edges)
01303 {
01304   int i;
01305   DLIList<TBPoint*> hidden_points;
01306   DLIList<RefFace*> face_list;
01307   DLIList<Curve*> curve_list;
01308   
01309   composite_edge->ref_faces( face_list );
01310   
01311   if( composite_edge->bridge_manager()->number_of_bridges() != 1 )
01312   {
01313     PRINT_ERROR("Curve %d is a merged curve.  Unmerge before removing composite.\n",
01314       composite_edge->id() );
01315     return CUBIT_FAILURE;
01316   }
01317   
01318   CompositeCurve* curve_ptr = dynamic_cast<CompositeCurve*>(composite_edge->get_curve_ptr());
01319   if( !curve_ptr )
01320     return CUBIT_FAILURE;
01321   
01322   for( i = 0; i < curve_ptr->num_curves(); i++ )  
01323     curve_list.append( curve_ptr->get_curve(i) );
01324 
01325   //remove all names off this ref entity
01326   composite_edge->remove_entity_names();
01327   
01328   curve_ptr->get_hidden_points( hidden_points );
01329   CubitStatus result = CUBIT_SUCCESS;
01330   hidden_points.reset();
01331   for( i = hidden_points.size(); i--; )
01332   {
01333     //remove attributes off the hidden points
01334     CompositeEngine::strip_attributes( hidden_points.get() );
01335 
01336     if( ! CompositeEngine::instance().
01337       restore_point( hidden_points.get_and_step() ) )
01338       result = CUBIT_FAILURE;
01339   }
01340   
01341   DLIList<TopologyBridge*> bridge_list;
01342   composite_edge->bridge_manager()->get_bridge_list(bridge_list);
01343   int smallest_id = 0;
01344   for ( i = bridge_list.size(); i--; )
01345   {
01346     GeometryEntity* geom_ptr = dynamic_cast<GeometryEntity*>(bridge_list.get_and_step());
01347     int saved_id = geom_ptr->get_saved_id();
01348     if ( saved_id && (!smallest_id || saved_id < smallest_id) &&
01349          !RefEntityFactory::instance()->get_ref_edge(saved_id) )
01350       smallest_id = saved_id;
01351   }
01352   if ( smallest_id && composite_edge->id() != smallest_id )
01353     composite_edge->set_id( smallest_id );
01354 
01355   
01356   for( i = face_list.size(); i--; ) 
01357   {
01358     Surface* surf = face_list.get_and_step()->get_surface_ptr();
01359     GeometryQueryTool::instance()->make_RefFace( surf );
01360   }
01361   for( i = face_list.size(); i--; )
01362     GeometryQueryTool::instance()->destroy_dead_entity( face_list.get_and_step() );
01363   
01364   for( i = curve_list.size(); i--; )
01365   {
01366     //remove attributes off the underlying curves
01367     Curve *tmp_curve = curve_list.get_and_step();
01368     CompositeEngine::strip_attributes( tmp_curve );
01369 
01370     BridgeManager* bm = dynamic_cast<BridgeManager*>(tmp_curve->owner());
01371     RefEdge* edge = bm ? dynamic_cast<RefEdge*>(bm->topology_entity()) : 0;
01372     if( restored_edges )
01373       restored_edges->append( edge );
01374     std::vector<CubitString> underlying_names;
01375     tmp_curve->get_saved_names( underlying_names );
01376     for (size_t k = 0; k < underlying_names.size(); k++)
01377       edge->entity_name( underlying_names[k] );
01378   }
01379     
01380   return result;
01381 }
01382 
01383 //-------------------------------------------------------------------------
01384 // Purpose       : Restore a hidden point, remerging points and
01385 //                 parent curves if possible.
01386 //
01387 // Special Notes : Helper function for uncomposite(RefFace*,...)
01388 //
01389 // Creator       : Jason Kraftcheck
01390 //
01391 // Creation Date : 08/06/03
01392 //-------------------------------------------------------------------------
01393 CubitStatus CompositeTool::restore_merged_point( TBPoint* hidden_pt,
01394                                       DLIList<RefFace*>& modified,
01395                                       bool force )
01396 {
01397   int i;
01398   
01399   HiddenEntitySet* hs = dynamic_cast<HiddenEntitySet*>(hidden_pt->owner());
01400   if (!hs)
01401     return CUBIT_FAILURE;
01402   CompositeCurve* owner = dynamic_cast<CompositeCurve*>(hs->owner());
01403   if (!owner)
01404     return CUBIT_FAILURE;
01405   
01406   RefEdge* old_edge = dynamic_cast<RefEdge*>(owner->topology_entity());
01407   int num_curves;
01408   DLIList<TopologyBridge*> curve_bridges;
01409   if (old_edge)
01410   {
01411     num_curves = old_edge->bridge_manager()->number_of_bridges();
01412     old_edge->bridge_manager()->get_bridge_list(curve_bridges);
01413   }
01414   else
01415   {
01416     num_curves = 1;
01417     curve_bridges.append(owner);
01418   }
01419      
01420   DLIList<CompositeCurve*> curves(num_curves);
01421   CAST_LIST(curve_bridges, curves, CompositeCurve);
01422   DLIList<TBPoint*> points(curves.size());
01423   
01424   assert(curves.is_in_list(owner));
01425   CubitVector position = hidden_pt->coordinates();
01426   
01427   DLIList<TBPoint*> curve_pts;
01428   curves.reset();
01429   GeometryQueryTool* gqt = GeometryQueryTool::instance();
01430   double factor = gqt->get_geometry_factor();
01431   for ( i = curves.size(); i--; )
01432   {
01433     curve_pts.clean_out();
01434     curves.get_and_step()->get_hidden_points(curve_pts);
01435     for (int j = curve_pts.size(); j--; )
01436     {
01437       TBPoint* curve_pt = curve_pts.get_and_step();
01438       if (gqt->about_spatially_equal(position, curve_pt->coordinates(), factor))
01439       {
01440         points.append(curve_pt);
01441         break;
01442       }
01443     }
01444   }
01445   
01446   if (!force && points.size() != curve_bridges.size())
01447   {
01448     RefEdge* edge = dynamic_cast<RefEdge*>(owner->topology_entity());
01449     PRINT_ERROR("Cannot restore vertex hidden by curve %d without unmerging "
01450                 "curve and possibly adjacent surfaces.  Use the 'force' "
01451                 "option to force unmerging of geometry.\n", edge ? edge->id() : 0);
01452     return CUBIT_FAILURE;
01453   }
01454   
01455   points.last();
01456   for ( i = points.size(); i--; )
01457   {
01458     TBPoint* pt = points.step_and_get();
01459     if (CompositePoint* cp = dynamic_cast<CompositePoint*>(pt))
01460       pt = cp->get_point();
01461     
01462     if (!CompositeEngine::instance().restore_point(pt))
01463       points.change_to(0);
01464     else if (CompositePoint* cp = dynamic_cast<CompositePoint*>(pt->owner()))
01465       points.change_to(cp);
01466     else
01467       points.change_to(pt);
01468   }
01469   points.remove_all_with_value(0);
01470   
01471   if (!points.size())
01472     return CUBIT_FAILURE;
01473   
01474   points.reset();
01475   RefVertex* new_vtx = gqt->make_RefVertex(points.get());
01476   for ( i = points.size(); i--; )
01477   {
01478     TBPoint* pt = points.get_and_step();
01479     if (pt->owner())
01480       assert(pt->topology_entity() == new_vtx);
01481     else
01482       new_vtx->bridge_manager()->add_bridge(pt);
01483   }
01484           
01485   CubitVector center_1, center_2;
01486   DLIList<TopologyBridge*> pt_curves(2);
01487   points.reset();
01488   points.get()->get_parents(pt_curves);
01489   
01490     // Ignore composite point-curves.  They are transient and will be
01491     // deleted later.  Don't try to create RefEdges for them now.
01492   if (pt_curves.size() != 2)
01493   {
01494 #ifndef NDEBUG
01495     assert(pt_curves.size() == 1);
01496     CompositeCurve* ccurve = dynamic_cast<CompositeCurve*>(pt_curves.get());
01497     assert(ccurve->num_curves() == 0 && ccurve->geometry_type() == POINT_CURVE_TYPE );
01498 #endif
01499     return CUBIT_SUCCESS;
01500   }
01501   
01502   dynamic_cast<Curve*>(pt_curves.get())->position_from_fraction(0.5, center_1);
01503   dynamic_cast<Curve*>(pt_curves.next())->position_from_fraction(0.5, center_2);
01504   
01505   DLIList<Curve*> new_edge_1_curves(points.size()), 
01506                   new_edge_2_curves(points.size());
01507   
01508   points.reset();
01509   for ( i = points.size(); i--; )
01510   {
01511     pt_curves.clean_out();
01512     points.get_and_step()->get_parents(pt_curves);
01513     assert(pt_curves.size() == 2);
01514     Curve* curve_1 = dynamic_cast<Curve*>(pt_curves.get());
01515     Curve* curve_2 = dynamic_cast<Curve*>(pt_curves.next());
01516     CubitVector ptc1, ptc2;
01517     curve_1->position_from_fraction( 0.5, ptc1 );
01518     curve_2->position_from_fraction( 0.5, ptc2 );
01519     bool close1 = (center_1 - ptc1).length_squared() < (center_2 - ptc1).length_squared();
01520     bool close2 = (center_1 - ptc2).length_squared() < (center_2 - ptc2).length_squared();
01521     if (close1 && !close2)
01522     {
01523       new_edge_1_curves.append(curve_1);
01524       new_edge_2_curves.append(curve_2);
01525     }
01526     else if (!close1 && close2)
01527     {
01528       new_edge_2_curves.append(curve_1);
01529       new_edge_1_curves.append(curve_2);
01530     }
01531     else
01532     {
01533       assert(close1 != close2);
01534     }
01535   }
01536 
01537   for ( i = 0; i < 2; i++ )
01538   {
01539     int j;
01540     DLIList<Curve*>& new_edge_curves = i ? new_edge_2_curves : new_edge_1_curves;
01541     DLIList<Curve*>& otr_edge_curves = i ? new_edge_1_curves : new_edge_2_curves;
01542     RefEdge* new_edge = 0;
01543     new_edge_curves.reset();
01544     for (j = new_edge_curves.size(); j--; )
01545     {
01546       Curve* curve = new_edge_curves.get_and_step();
01547       if (curve->owner())
01548       {
01549         RefEdge* edge = dynamic_cast<RefEdge*>(curve->topology_entity());
01550         assert(!!edge);
01551         if (!otr_edge_curves.is_in_list(edge->get_curve_ptr()))
01552           new_edge = edge;
01553       }
01554     }
01555     if (!new_edge)
01556     {
01557       Curve* curve = new_edge_curves.get();
01558       if (curve->owner())
01559         curve->owner()->remove_bridge(curve);
01560       new_edge = gqt->make_RefEdge(curve);
01561     }
01562   
01563     Curve* first = new_edge->get_curve_ptr();
01564     for (j = new_edge_curves.size(); j--; )
01565     {
01566       Curve* curve = new_edge_curves.get_and_step();
01567       if (curve->owner())
01568       {
01569         if (curve->topology_entity() == new_edge)
01570           continue;
01571         else
01572           curve->owner()->remove_bridge(curve);
01573       }
01574       
01575       bool reversed = first->relative_sense(curve) == CUBIT_REVERSED;
01576       bool saved = first->bridge_sense() == curve->bridge_sense();
01577       if (reversed == saved)
01578         curve->reverse_bridge_sense();
01579       new_edge->bridge_manager()->add_bridge(curve);
01580     }
01581   }
01582   
01583   if (old_edge)
01584   {
01585     DLIList<RefFace*> face_list;
01586     old_edge->ref_faces(face_list);
01587     modified += face_list;
01588   }
01589   return CUBIT_SUCCESS;
01590 }
01591   
01592   
01593   
01594   
01595 
01596   
01597 
01598 
01599 //-------------------------------------------------------------------------
01600 // Purpose       : remove a composite face, restoring the orignial faces.
01601 //
01602 // Special Notes : 
01603 //
01604 // Creator       : Jason Kraftcheck
01605 //
01606 // Creation Date : 
01607 //-------------------------------------------------------------------------
01608 CubitStatus CompositeTool::uncomposite( RefFace* composite_face,
01609                                         DLIList<RefFace*>* restored_faces,
01610                                         bool force_unmerge )
01611 {
01612   int i;
01613   DLIList<Curve*> hidden_curves;
01614   DLIList<RefVolume*> vol_list;
01615   DLIList<Surface*> surface_list;
01616   
01617   composite_face->ref_volumes( vol_list );
01618   
01619   if( composite_face->bridge_manager()->number_of_bridges() != 1 )
01620   {
01621     PRINT_ERROR("Surface %d is a merged curve.  Unmerge before removing composite.\n",
01622       composite_face->id() );
01623     return CUBIT_FAILURE;
01624   }
01625   
01626   CompositeSurface* surf_ptr = dynamic_cast<CompositeSurface*>(composite_face->get_surface_ptr());
01627   if( !surf_ptr )
01628     return CUBIT_FAILURE;
01629 
01630   //remove all names off this ref entity
01631   composite_face->remove_entity_names();
01632   
01633   for( i = 0; i < surf_ptr->num_surfs(); i++ )
01634     surface_list.append( surf_ptr->get_surface(i) );
01635   
01636   surf_ptr->get_hidden_curves( hidden_curves );
01637   CubitStatus result = CUBIT_SUCCESS;
01638   hidden_curves.reset();
01639   DLIList<TopologyBridge*> points(2);
01640   DLIList<RefFace*> modified_faces;
01641   for( i = hidden_curves.size(); i--; )
01642   {
01643     //remove attributes off the hidden curves 
01644     CompositeEngine::strip_attributes( hidden_curves.get() );
01645 
01646     Curve* curve = hidden_curves.get_and_step();
01647 
01648     if(DEBUG_FLAG(87))
01649     {
01650       GMem gmem;
01651       curve->get_geometry_query_engine()->get_graphics(curve,&gmem);
01652       GfxDebug::draw_polyline(gmem.point_list(),gmem.pointListCount,CUBIT_RED_INDEX);
01653       GfxDebug::flush();
01654     }
01655 
01656     curve->get_children(points, true);
01657     while (points.size())
01658     {
01659       TBPoint* pt = dynamic_cast<TBPoint*>(points.pop());
01660 
01661       //remove attributes off the underlying points 
01662       CompositeEngine::strip_attributes( pt ); 
01663 
01664       HiddenEntitySet* hs = dynamic_cast<HiddenEntitySet*>(pt->owner());
01665       if (hs && dynamic_cast<CompositeCurve*>(hs->owner()))
01666       {
01667         if (!restore_merged_point(pt, modified_faces, force_unmerge))
01668         {
01669           PRINT_ERROR("Failed to restore hidden vertex.\n");
01670           result = CUBIT_FAILURE;
01671           break;
01672         }
01673       }
01674     }
01675     
01676     if (!result)
01677       break;
01678     
01679     if( ! CompositeEngine::instance().restore_curve( curve ) )
01680       result = CUBIT_FAILURE;
01681   }
01682   
01683   if (modified_faces.size())
01684   {
01685     DLIList<TopologyEntity*> query_input(modified_faces.size());
01686     CAST_LIST_TO_PARENT(modified_faces, query_input);
01687     DLIList<TopologyEntity*> query_output;
01688     ModelQueryEngine::instance()->
01689       query_model(query_input,DagType::ref_volume_type(),query_output);
01690     while(query_output.size())
01691       vol_list.append_unique(dynamic_cast<RefVolume*>(query_output.pop()));
01692   }
01693                                  
01694   
01695   DLIList<TopologyBridge*> bridge_list;
01696   composite_face->bridge_manager()->get_bridge_list(bridge_list);
01697   int smallest_id = 0;
01698   for ( i = bridge_list.size(); i--; )
01699   {
01700     GeometryEntity* geom_ptr = dynamic_cast<GeometryEntity*>(bridge_list.get_and_step());
01701     int saved_id = geom_ptr->get_saved_id();
01702     if ( saved_id && (!smallest_id || saved_id < smallest_id) &&
01703          !RefEntityFactory::instance()->get_ref_face(saved_id) )
01704       smallest_id = saved_id;
01705   }
01706   if ( smallest_id && composite_face->id() != smallest_id )
01707     composite_face->set_id( smallest_id );
01708   
01709   for( i = vol_list.size(); i--; )
01710   {
01711     Lump* lump= dynamic_cast<Lump*>(
01712       vol_list.get_and_step()->bridge_manager()->topology_bridge() );
01713     GeometryQueryTool::instance()->make_Body( lump->bodysm() );
01714   }
01715   for( i = vol_list.size(); i--; )
01716     GeometryQueryTool::instance()->destroy_dead_entity( vol_list.get_and_step() );
01717   
01718   for( i = surface_list.size(); i--; )
01719   {
01720     Surface *tmp_surf = surface_list.get_and_step();
01721     //remove attributes off the surfaces 
01722     CompositeEngine::strip_attributes( tmp_surf ); 
01723 
01724     BridgeManager* bm = dynamic_cast<BridgeManager*>(tmp_surf->owner());
01725     RefFace* face = bm ? dynamic_cast<RefFace*>(bm->topology_entity()) : 0;
01726     if( restored_faces )
01727       restored_faces->append( face );
01728     std::vector<CubitString> underlying_names;
01729     tmp_surf->get_saved_names( underlying_names );
01730     for (size_t k = 0; k < underlying_names.size(); k++)
01731       face->entity_name( underlying_names[k] );
01732   }
01733   
01734   return result;
01735 }
01736 
01737 
01738 //-------------------------------------------------------------------------
01739 // Purpose       : Remove a composite volume
01740 //
01741 // Special Notes : 
01742 //
01743 // Creator       : Jason Kraftcheck
01744 //
01745 // Creation Date : 09/25/01
01746 //-------------------------------------------------------------------------
01747 CubitStatus CompositeTool::uncomposite( RefVolume* composite_vol,
01748                                         DLIList<RefVolume*>* restored_vols )
01749 {
01750   int i;
01751   DLIList<Surface*> hidden_surfs;
01752   DLIList<Body*> body_list;
01753   DLIList<Lump*> lump_list;
01754   
01755   composite_vol->bodies( body_list );
01756   
01757   CompositeLump* lump_ptr = dynamic_cast<CompositeLump*>(composite_vol->get_lump_ptr());
01758   if( !lump_ptr )
01759     return CUBIT_FAILURE;
01760   
01761   for( i = 0; i < lump_ptr->num_lumps(); i++ )
01762     lump_list.append( lump_ptr->get_lump(i) );
01763   
01764   lump_ptr->get_hidden_surfaces( hidden_surfs );
01765   CubitStatus result = CUBIT_SUCCESS;
01766   hidden_surfs.reverse();
01767   while( hidden_surfs.size() )
01768   {
01769     Surface* surf = hidden_surfs.pop();
01770     Surface* stitch = 0;
01771     if( ! CompositeEngine::instance().restore_surface( surf, stitch ) )
01772       result = CUBIT_FAILURE;
01773     if (stitch)
01774       hidden_surfs.remove( stitch );
01775   }
01776   
01777   int saved_id = composite_vol->get_lump_ptr()->get_saved_id();
01778   if (saved_id && saved_id < composite_vol->id() &&
01779       !RefEntityFactory::instance()->get_ref_volume(saved_id))
01780     composite_vol->set_id( saved_id );
01781   
01782   for( i = body_list.size(); i--; )
01783     GeometryQueryTool::instance()->make_Body( body_list.get_and_step()->get_body_sm_ptr() );
01784   for( i = body_list.size(); i--; )
01785     GeometryQueryTool::instance()->destroy_dead_entity( body_list.get_and_step() );
01786   
01787   if( restored_vols )
01788   {
01789     for( i = lump_list.size(); i--; )
01790     {
01791       TBOwner* owner = lump_list.get_and_step()->owner();
01792       if (BridgeManager* bm = dynamic_cast<BridgeManager*>(owner))
01793         restored_vols->append( dynamic_cast<RefVolume*>(bm->topology_entity()) );
01794       else if (CompositeLump* lump = dynamic_cast<CompositeLump*>(owner))
01795         restored_vols->append_unique( dynamic_cast<RefVolume*>(lump->topology_entity() ) );
01796     }
01797   }
01798   
01799   return result;
01800 }
01801 
01802 //-------------------------------------------------------------------------
01803 // Purpose       : Remove composite body
01804 //
01805 // Special Notes : 
01806 //
01807 // Creator       : Jason Kraftcheck
01808 //
01809 // Creation Date : 10/02/01
01810 //-------------------------------------------------------------------------
01811 CubitStatus CompositeTool::uncomposite( Body* , 
01812                                         DLIList<Body*>* )
01813 {
01814   return CUBIT_FAILURE;
01815 }
01816 
01817 
01818 
01819 
01820 //-------------------------------------------------------------------------
01821 // Purpose       : Create multiple composite curves
01822 //
01823 // Special Notes : 
01824 //
01825 // Creator       : Jason Kraftcheck
01826 //
01827 // Creation Date : 12/03/99
01828 //-------------------------------------------------------------------------
01829 CubitStatus CompositeTool::composite( DLIList<RefEdge*>& edges, 
01830                                       DLIList<RefEdge*>& new_edge_list,
01831                                       DLIList<RefVertex*>* vertices_to_keep, 
01832                                       double max_curve_angle /*radians*/ )
01833 {
01834   new_edge_list.clean_out();
01835   double min_cos_angle = cos( max_curve_angle );
01836   int i;
01837   
01838   //check for duplicates
01839   DLIList<RefEdge*> edges_to_composite;
01840   for( i = edges.size(); i > 0; i-- )
01841   {
01842     RefEdge* edge_ptr = edges.get_and_step();
01843     if( ! edges_to_composite.append_unique( edge_ptr ) )
01844     {
01845       PRINT_WARNING("Duplicate curve %d in list of curves to composite.\n",
01846         edge_ptr->id());
01847     }
01848   }
01849   
01850   
01851   if( edges_to_composite.size() < 2 ) return CUBIT_SUCCESS;
01852   
01853   fast_edge_sort( edges_to_composite, true );
01854   
01855   //look for a place to start (a point that we cannot 
01856   //composite across.)
01857 
01858   RefVertex *vtx_ptr;
01859   RefEdge* first_edge;
01860   DLIList<RefEdge*> vertex_edges;
01861 
01862   edges_to_composite.last();
01863   RefEdge* prev_edge = edges_to_composite.get();
01864   edges_to_composite.reset();
01865   
01866   for( i = edges_to_composite.size(); i >= 0; i-- )
01867   {
01868     first_edge = edges_to_composite.get_and_step();
01869     vtx_ptr = first_edge->common_ref_vertex( prev_edge );
01870     if( ! vtx_ptr ) break;
01871     
01872     vertex_edges.clean_out();
01873     vtx_ptr->ref_edges( vertex_edges );
01874     vertex_edges.remove( first_edge );
01875     vertex_edges.remove( prev_edge );
01876     if( vertex_edges.size() > 0 ) break;
01877     
01878     prev_edge = first_edge;
01879   }
01880   
01881   if( i < 0 ) //if all the edges get composited into one
01882   {
01883     edges_to_composite.reset();
01884     first_edge = edges_to_composite.get();
01885   }
01886     
01887   //composite chains of consecutive edges
01888   
01889   edges_to_composite.move_to( first_edge );
01890   DLIList<RefEdge*> edge_list, sublist;
01891   int edge_count = edges_to_composite.size();
01892   while( edge_count > 0 )
01893   {
01894     edge_list.clean_out();
01895     RefEdge* edge_ptr = edges_to_composite.get_and_step();
01896     edge_list.append( edge_ptr );
01897     edge_count--;
01898     
01899     //Find a chain of connected edges that can form a 
01900     //topologically valid composite.
01901     
01902     while( edge_count > 0 )
01903     {
01904       RefEdge* next_edge = edges_to_composite.get();
01905       vtx_ptr = edge_ptr->common_ref_vertex( next_edge );
01906       if( ! vtx_ptr ) break;
01907       
01908       vertex_edges.clean_out();
01909       vtx_ptr->ref_edges( vertex_edges );
01910       vertex_edges.remove( edge_ptr );
01911       vertex_edges.remove( next_edge );
01912       if( vertex_edges.size() > 0 ) break;
01913       
01914       edge_ptr = next_edge;
01915       edges_to_composite.step();
01916       edge_list.append( edge_ptr );
01917       edge_count--;
01918     }
01919       
01920     if( edge_list.size() == 1 ) continue;
01921     assert( edge_list.size() );
01922     
01923     //Now split that chain of edges further based on
01924     //user-specified constraints (vertices and/or angle.)
01925     //This is done seperatly from the above loop to handle
01926     //cases where the edge_list forms a closed loop, and the
01927     //user specified one position on that loop to keep.
01928     
01929     //Find a start point in the chain.
01930     edge_list.last();
01931     edge_ptr = edge_list.get();
01932     edge_list.reset();
01933     RefVertex* keep_vertex = 0;
01934     if( edge_ptr->common_ref_vertex( edge_list.get() ) )
01935     //if we have a closed loop
01936     {
01937       edge_ptr = edge_list.get_and_step();
01938       for( i = edge_list.size(); i > 0; i-- )
01939       {
01940         RefEdge* next_edge = edge_list.get();
01941         vtx_ptr = edge_ptr->common_ref_vertex( next_edge );
01942         assert( vtx_ptr != 0 );
01943         
01944         if( vertices_to_keep && vertices_to_keep->is_in_list( vtx_ptr ) )
01945         {
01946           keep_vertex = vtx_ptr;
01947           break;
01948         }
01949         CubitVector cur_tan = tangent( edge_ptr, vtx_ptr ) * -1.0;
01950         CubitVector next_tan = tangent( next_edge, vtx_ptr );
01951         double cos_angle = (cur_tan % next_tan) / 
01952                        (cur_tan.length() * next_tan.length());
01953         if( cos_angle < min_cos_angle )
01954         {
01955           keep_vertex = vtx_ptr;
01956           break;
01957         }
01958         
01959         edge_ptr = next_edge;
01960         edge_list.step();
01961       }
01962     }
01963     
01964     //If we didn't find any split locations, that's okay.
01965     //We'll let the compositing code choose which vertex to keep.
01966     
01967     int subcount = edge_list.size();
01968     while( subcount > 0 )
01969     {
01970       sublist.clean_out();
01971       edge_ptr = edge_list.get_and_step();
01972       subcount--;
01973       sublist.append( edge_ptr );
01974       
01975       while( subcount > 0 )
01976       {
01977         RefEdge* next_edge = edge_list.get();
01978         vtx_ptr = edge_ptr->common_ref_vertex( next_edge );
01979         assert( vtx_ptr != 0 );
01980         
01981         if( vertices_to_keep && vertices_to_keep->is_in_list( vtx_ptr ) )
01982         {
01983           keep_vertex = vtx_ptr;
01984           break;
01985         }
01986         CubitVector cur_tan = tangent( edge_ptr, vtx_ptr ) * -1.0;
01987         CubitVector next_tan = tangent( next_edge, vtx_ptr );
01988         double cos_angle = (cur_tan % next_tan) / 
01989                         (cur_tan.length() * next_tan.length());
01990         if( cos_angle < min_cos_angle )
01991         {
01992           keep_vertex = vtx_ptr;
01993           break;
01994         }
01995         
01996         edge_ptr = next_edge;
01997         edge_list.step();
01998         subcount--;
01999         sublist.append( edge_ptr );
02000       }
02001       
02002     
02003       if( sublist.size() > 1 )
02004       {
02005         edge_ptr = composite( sublist, keep_vertex );
02006         if( ! edge_ptr ) return CUBIT_FAILURE;
02007         new_edge_list.append( edge_ptr );
02008       }
02009     }
02010   }
02011   
02012   return CUBIT_SUCCESS;
02013 }
02014 
02015 //-------------------------------------------------------------------------
02016 // Purpose       : Get the tangent along an edge away from a vertex.
02017 //
02018 // Special Notes : 
02019 //
02020 // Creator       : Jason Kraftcheck
02021 //
02022 // Creation Date : 12/03/99
02023 //-------------------------------------------------------------------------
02024 CubitVector CompositeTool::tangent( RefEdge* edge_ptr, RefVertex* vtx_ptr ) const
02025 {
02026   CubitVector result;
02027   edge_ptr->tangent( vtx_ptr->coordinates(), result );
02028   if( vtx_ptr == edge_ptr->end_vertex() )
02029     result *= -1;
02030   return result;
02031 } 
02032 
02033 //-------------------------------------------------------------------------
02034 // Purpose       : Sort edges topologically.  
02035 //
02036 // Special Notes : Not safe with secondary links
02037 //
02038 // Creator       : Jason Kraftcheck
02039 //
02040 // Creation Date : 12/03/99
02041 //-------------------------------------------------------------------------
02042 CubitStatus CompositeTool::fast_edge_sort( DLIList<RefEdge*>& edge_list,
02043                                            bool valence2_vertices ) const
02044 {
02045   int i;
02046   if( edge_list.size() < 2 ) return CUBIT_SUCCESS;
02047   
02048   //make sure all RefEdges are initially marked as zero.
02049   DLIList<RefVertex*> vtx_list(2), all_vertices(edge_list.size() * 2);
02050   DLIList<RefEdge*> vertex_edges;
02051   RefEdge* edge_ptr;
02052   RefVertex* vtx_ptr;
02053   for( i = edge_list.size(); i > 0; i-- )
02054   {
02055     edge_ptr = edge_list.get_and_step();
02056     vtx_list.clean_out();
02057     edge_ptr->ref_vertices( vtx_list );
02058     for( int j = vtx_list.size(); j > 0; j-- )
02059     {
02060       vtx_ptr = vtx_list.get_and_step();
02061       vtx_ptr->marked( 0 );
02062     }
02063   }
02064   for( i = edge_list.size(); i > 0; i-- )
02065   {
02066     edge_ptr = edge_list.get_and_step();
02067     vtx_list.clean_out();
02068     edge_ptr->ref_vertices( vtx_list );
02069     for( int j = vtx_list.size(); j > 0; j-- )
02070     {
02071       vtx_ptr = vtx_list.get_and_step();
02072       if( vtx_ptr->marked() ) continue;
02073     
02074       all_vertices.append( vtx_ptr );
02075       vtx_ptr->marked( 1 );
02076 
02077       vertex_edges.clean_out();
02078       vtx_ptr->ref_edges( vertex_edges );
02079       for( int k = vertex_edges.size(); k > 0; k-- )
02080         vertex_edges.get_and_step()->marked( 0 );
02081     }
02082   }
02083   
02084   //now mark all of the edges in the edge list with a 1
02085   for( i = edge_list.size(); i > 0; i-- )
02086     edge_list.get_and_step()->marked( 1 );
02087     
02088   DLIList<RefEdge*> sorted_edge_list( edge_list.size() );
02089   
02090   int passes = 0;
02091   while( sorted_edge_list.size() < edge_list.size() ) 
02092   {
02093     passes++;
02094     RefVertex* start_vtx = 0;
02095     RefEdge* start_edge = 0;
02096     
02097     //choose a start_vtx and start_edge
02098     for( i = all_vertices.size(); i > 0; i-- )
02099     {
02100       vtx_ptr = all_vertices.get_and_step();
02101       //if( ! vtx_ptr->marked() ) continue;
02102       
02103       int edge_count = 0;
02104       vertex_edges.clean_out();
02105       vtx_ptr->ref_edges( vertex_edges );
02106       for( int j = vertex_edges.size(); j > 0; j-- )
02107       {
02108         edge_ptr = vertex_edges.get_and_step();
02109         if( edge_ptr->marked() )
02110         {
02111           start_edge = edge_ptr;
02112           edge_count++;
02113           if( (edge_count > 1) || (valence2_vertices && vertex_edges.size() > 2) ) 
02114             break;
02115           // If the vertex has more than two edges, consider it a 
02116           // valid starting point for the search because it will not
02117           // be possible to create a composite across that vertex
02118           // anyway.
02119         }
02120       }
02121       if( edge_count == 1 )
02122       {
02123         start_vtx = vtx_ptr;
02124         break;
02125       }
02126     }
02127     
02128     //If we have a circular loop, choose any vertex as the start vertex
02129     if( ! start_vtx )
02130     {
02131       start_edge = 0;
02132       all_vertices.reset();
02133       for( i = all_vertices.size(); ! start_edge && (i > 0); i-- )
02134       {
02135         start_vtx = all_vertices.get_and_step();
02136         vertex_edges.clean_out();
02137         start_vtx->ref_edges( vertex_edges );
02138         for( int j = vertex_edges.size(); j > 0; j-- )
02139         {
02140           edge_ptr = vertex_edges.get_and_step();
02141           if( edge_ptr->marked() )
02142           {
02143             start_edge = edge_ptr;
02144             break;
02145           }
02146         }
02147         if( start_vtx->marked() ) break;
02148       }
02149     }
02150 
02151     assert( start_edge != 0 );
02152     assert( start_vtx != 0 );
02153 
02154 
02155     start_vtx->marked( 0 );
02156     edge_ptr = start_edge;
02157     vtx_ptr = start_vtx;
02158     
02159     do
02160     {
02161       sorted_edge_list.append( edge_ptr );
02162       edge_ptr->marked( 0 );
02163       
02164       RefVertex* next_vtx = edge_ptr->other_vertex( vtx_ptr );
02165       next_vtx->marked( 0 );
02166       
02167       vertex_edges.clean_out();
02168       next_vtx->ref_edges( vertex_edges );
02169       RefEdge* next_edge = 0;
02170       
02171       if( !valence2_vertices || vertex_edges.size() < 3 )
02172       {
02173         for( i = vertex_edges.size(); i > 0; i-- )
02174         {
02175           RefEdge* edge2_ptr = vertex_edges.get_and_step();
02176           if( edge2_ptr->marked() )
02177           {
02178             next_edge = edge2_ptr;
02179             break;
02180           }
02181         }
02182       }
02183       
02184       edge_ptr = next_edge;
02185       vtx_ptr = next_vtx;
02186     } while( edge_ptr );
02187   }
02188   
02189   assert( sorted_edge_list.size() == edge_list.size() );
02190   
02191   edge_list.clean_out();
02192   edge_list = sorted_edge_list;
02193   return (passes == 1) ? CUBIT_SUCCESS : CUBIT_FAILURE;
02194 }
02195 
02196 
02197 CubitStatus CompositeTool::composite( DLIList<RefFace*>& faces_to_composite,
02198                                       DLIList<RefFace*>& new_composites,
02199                                       double max_angle )
02200 {
02201   int i;
02202   DLIList<CoEdge*> coedges(2);
02203   double cos_max_angle = cos( max_angle );
02204   CubitStatus result = CUBIT_SUCCESS;
02205   
02206   DLIList<BasicTopologyEntity*> input, boundary, internal, other;
02207   CAST_LIST_TO_PARENT( faces_to_composite, input );
02208   classify_children( input, boundary, internal, other );
02209   DLIList<RefEdge*> internal_edges(internal.size());
02210   CAST_LIST( internal, internal_edges, RefEdge );
02211   if ( !internal_edges.size() )
02212     return CUBIT_FAILURE;
02213     
02214     // Group faces into sets to be composited
02215   
02216   std::vector< DLIList<RefFace*> > face_sets;
02217   for ( i = faces_to_composite.size(); i--; )
02218     faces_to_composite.get_and_step()->marked(0);
02219   
02220   while ( internal_edges.size() )
02221   {
02222     RefEdge* edge = internal_edges.pop();
02223     coedges.clean_out();
02224     edge->co_edges(coedges);
02225     if ( coedges.size() != 2 )
02226       continue;
02227     
02228     CoEdge* coedge1 = coedges.get_and_step();
02229     CoEdge* coedge2 = coedges.get_and_step();
02230     RefFace* face1 = coedge1->get_ref_face();
02231     RefFace* face2 = coedge2->get_ref_face();
02232     
02233     if ( max_angle < 4.0 )
02234     {
02235       CubitVector point, norm1, norm2;
02236       bool reversed = coedge1->get_sense() == coedge2->get_sense();
02237 
02238       edge->position_from_fraction( 0.33, point );
02239       norm1 = face1->normal_at( point );
02240       norm2 = face2->normal_at( point );
02241       if ( reversed ) norm2 *= -1.0;
02242       double cos_angle = (norm1 % norm2)/(norm1.length()*norm2.length());
02243       if ( cos_angle < cos_max_angle )
02244         continue;
02245 
02246       edge->position_from_fraction( 0.67, point );
02247       norm1 = face1->normal_at( point );
02248       norm2 = face2->normal_at( point );
02249       if ( reversed ) norm2 *= -1.0;
02250       cos_angle = (norm1 % norm2)/(norm1.length()*norm2.length());
02251       if ( cos_angle < cos_max_angle )
02252         continue;
02253     }
02254     
02255     if ( face1->marked() && face2->marked() )
02256     {
02257       if ( face1->marked() != face2->marked() )
02258       {
02259         DLIList<RefFace*>& merge_set = face_sets[face2->marked()-1];
02260         face_sets[face1->marked()-1] += merge_set;
02261         while( merge_set.size() )
02262           merge_set.pop()->marked( face1->marked() );
02263       }
02264     }
02265     else if ( face2->marked() )
02266     {
02267       face1->marked(face2->marked());
02268       face_sets[face2->marked()-1].append(face1);
02269     }
02270     else
02271     {
02272       if ( !face1->marked() )
02273       {
02274         face_sets.push_back(DLIList<RefFace*>());
02275         face1->marked(face_sets.size());
02276         face_sets[face1->marked()-1].append(face1);
02277       }
02278       face2->marked(face1->marked());
02279       face_sets[face1->marked()-1].append(face2);
02280     }
02281   }
02282   
02283     // clear all marks
02284   std::vector< DLIList<RefFace*> >::iterator s_itor;
02285   for ( s_itor = face_sets.begin(); s_itor != face_sets.end(); ++s_itor )
02286   {
02287     for ( i = s_itor->size(); i--; )
02288       s_itor->get_and_step()->marked(0);
02289   }
02290 
02291     // composite faces
02292   for ( s_itor = face_sets.begin(); s_itor != face_sets.end(); ++s_itor )
02293   {
02294     if ( s_itor->size() < 2 )
02295       continue;
02296     
02297     RefFace* comp = composite(*s_itor);
02298     if ( comp )
02299       new_composites.append(comp);
02300     else
02301       result = CUBIT_FAILURE;
02302   }
02303 
02304   return result;
02305 }
02306 
02307 //-------------------------------------------------------------------------
02308 // Purpose       : Composite surfaces and curves.
02309 //
02310 // Special Notes : 
02311 //
02312 // Creator       : Jason Kraftcheck
02313 //
02314 // Creation Date : 04/13/00
02315 //-------------------------------------------------------------------------
02316 RefFace* CompositeTool::composite( DLIList<RefFace*>& faces_to_composite,
02317                                    DLIList<RefEdge*>& result_edges,
02318                                    DLIList<RefVertex*>* vertices_to_keep,
02319                                    double max_vertex_angle )
02320 {
02321   result_edges.clean_out();
02322   RefFace* result = composite( faces_to_composite );
02323   if( ! result ) return 0;
02324   
02325   DLIList<RefEdge*> face_edges;
02326   result->ref_edges( face_edges );
02327   composite( face_edges, result_edges, vertices_to_keep, max_vertex_angle );
02328   
02329   return result;
02330 }
02331 
02332 //-------------------------------------------------------------------------
02333 // Purpose       : Composite surfaces and curves.
02334 //
02335 // Special Notes : 
02336 //
02337 // Creator       : Jason Kraftcheck
02338 //
02339 // Creation Date : 04/13/00
02340 //-------------------------------------------------------------------------
02341 CubitStatus CompositeTool::composite( DLIList<RefFace*>& faces_to_composite,
02342                                       DLIList<RefFace*>& result_faces,
02343                                       DLIList<RefEdge*>& result_edges,
02344                                       double max_curve_angle,
02345                                       DLIList<RefVertex*>* vertices_to_keep,
02346                                       double max_vtx_angle  )
02347 {
02348   result_faces.clean_out();
02349   result_edges.clean_out();
02350   
02351   CubitStatus status = 
02352     composite( faces_to_composite, result_faces, max_curve_angle );
02353   if( ! status ) return status;
02354   
02355   DLIList<TopologyEntity*> query_input, query_output;
02356   CAST_LIST_TO_PARENT( result_faces, query_input );
02357   ModelQueryEngine::instance()->
02358     query_model( query_input, DagType::ref_edge_type(), query_output );
02359   
02360   DLIList<RefEdge*> edge_list;
02361   CAST_LIST( query_output, edge_list, RefEdge );
02362   
02363   return composite( edge_list, result_edges, vertices_to_keep, max_vtx_angle );
02364 }
02365 
02366   
02367 
02368   
02369 CubitStatus CompositeTool::stitch_points( TBPoint* pt1, TBPoint* pt2 )
02370 {
02371   if ( pt1->owner() && pt2->owner() && pt1->owner() != pt2->owner() )
02372     return CUBIT_FAILURE;
02373   
02374   CompositePoint* result = CompositeEngine::instance().stitch_points( pt1, pt2 );
02375   return result ? CUBIT_SUCCESS : CUBIT_FAILURE;
02376 }
02377 
02378 CubitStatus CompositeTool::stitch_curves( Curve* cv1, Curve* cv2 )
02379 {
02380   if ( cv1->owner() && cv2->owner() && cv1->owner() != cv2->owner() )
02381     return CUBIT_FAILURE;
02382   
02383   DLIList<TopologyBridge*> points;
02384   TBPoint *start1, *end1, *start2, *end2;
02385 
02386   points.clean_out();
02387   cv1->get_children( points );
02388   points.reset();
02389   start1 = dynamic_cast<TBPoint*>(points.get_and_step());
02390   end1 = dynamic_cast<TBPoint*>(points.get_and_step());
02391 
02392   points.clean_out();
02393   cv2->get_children( points );
02394   points.reset();
02395   start2 = dynamic_cast<TBPoint*>(points.get_and_step());
02396   end2 = dynamic_cast<TBPoint*>(points.get_and_step());
02397   
02398   assert( start1 && start2 && end1 && end2 );
02399   
02400   if ( (start1 == end1) != (start2 == end2) )
02401     return CUBIT_FAILURE;
02402   
02403   if ( start1 == end2 || start1->owner() == end2->owner() )
02404     std::swap(start2, end2);
02405   
02406   if ( (start1->owner() != start2->owner()) || (end1->owner() != end2->owner()) )
02407     return CUBIT_FAILURE;
02408   
02409   if ( start1 != start2 && !stitch_points( start1, start2 ) )
02410     return CUBIT_FAILURE;
02411   
02412   if ( start1 != end1 && end1 != end2 && !stitch_points( end1, end2 ) )
02413     return CUBIT_FAILURE;
02414   
02415   CompositeCurve* result = CompositeEngine::instance().stitch_curves( cv1, cv2 );
02416   return result ? CUBIT_SUCCESS : CUBIT_FAILURE;
02417 }
02418 
02419 
02420 
02421         
02422 //-------------------------------------------------------------------------
02423 // Purpose       : Functions overloaded by CompositeToolMesh
02424 //
02425 // Special Notes : 
02426 //
02427 // Creator       : Jason Kraftcheck
02428 //
02429 // Creation Date : 05/10/04
02430 //-------------------------------------------------------------------------
02431 CubitStatus CompositeTool::update_combined_vols( RefVolume*, RefVolume* ) 
02432   {return CUBIT_SUCCESS;}
02433 CubitStatus CompositeTool::update_combined_faces( RefFace*, RefEdge*, RefFace* ) 
02434   {return CUBIT_SUCCESS;}
02435 CubitStatus CompositeTool::update_combined_edges( RefEdge*, RefEdge* ,int keep_interval,double keep_size,FirmnessType interval_keep_type,SizeIntervalType size_keep_type) 
02436   {return CUBIT_SUCCESS;}
02437 CubitStatus CompositeTool::determine_combined_edges_interval_or_size( RefEdge* edge_1, RefEdge* edge_2,int& result_interval,double& result_size,FirmnessType& interval_keep_type,SizeIntervalType& size_keep_type)
02438 {return CUBIT_SUCCESS;}
02439 
02440 
02441 
02442 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines