cgma
PartitionEngine.cpp
Go to the documentation of this file.
00001 //-------------------------------------------------------------------------
00002 // Filename      : PartitionEngine.cpp
00003 //
00004 // Purpose       : 
00005 //
00006 // Special Notes : 
00007 //
00008 // Creator       : Jason Kraftcheck
00009 //
00010 // Creation Date : 04/23/02
00011 //-------------------------------------------------------------------------
00012 
00013 #include "PartitionEngine.hpp"
00014 #include "CompositeEngine.hpp"
00015 
00016 #include "SubCurve.hpp"
00017 #include "SubSurface.hpp"
00018 #include "SegmentedCurve.hpp"
00019 #include "PartitionPoint.hpp"
00020 #include "PartitionCoEdge.hpp"
00021 #include "PartitionLoop.hpp"
00022 #include "PartitionSurface.hpp"
00023 #include "PartitionLump.hpp"
00024 #include "PartitionBody.hpp"
00025 #include "PartPTCurve.hpp"
00026 #include "PartitionShell.hpp"
00027 #include "BodySM.hpp"
00028 
00029 
00030 #include "GMem.hpp"
00031 #include "GeometryQueryEngine.hpp"
00032 #include "GeometryModifyEngine.hpp"
00033 #include "GeometryModifyTool.hpp"
00034 
00035 #include "VGLoopTool.hpp"
00036 
00037 #include "FacetProjectTool.hpp"
00038 #include "CubitFacetData.hpp"
00039 #include "CubitFacetEdgeData.hpp"
00040 #include "CubitPointData.hpp"
00041 #include "TDVGFacetOwner.hpp"
00042 #include "TDVGFacetSplit.hpp"
00043 #include "FacetEvalTool.hpp"
00044 #include "FacetDataUtil.hpp"
00045 #include "PartSurfFacetTool.hpp"
00046 #include "PartitionTool.hpp"
00047 
00048 #include "CompositeSurface.hpp"
00049 #include "CompositePoint.hpp"
00050 #include "CompositeCurve.hpp"
00051 #include "PartitionLumpImprint.hpp"
00052 #include "GfxDebug.hpp"
00053 #include "BridgeManager.hpp"
00054 
00055 #include "CADefines.hpp"
00056 
00057 #include <set>
00058 #include "GeometryQueryTool.hpp"
00059 
00060 #include "CubitTransformMatrix.hpp"
00061 #include "CubitObservable.hpp"
00062 #include "AppUtil.hpp"
00063 #include "GeometryEvent.hpp"
00064 
00065 const char* const PARTITION_GEOM_ATTRIB_NAME = "PARTITION_GEOM";
00066 
00067 static CubitStatus get_edge_replacements(
00068                          std::vector<CubitFacetData*> &facet_list,
00069                          std::vector<CubitFacetEdgeData*> replacement_edges[3]);
00070 
00071 
00072 PartitionEngine* PartitionEngine::instance_ = NULL; 
00073 
00074 
00075 PartitionEngine::~PartitionEngine()
00076 {
00077   GeometryQueryTool::instance()->unregister_intermediate_engine(this);
00078 }
00079 
00080 void PartitionEngine::delete_instance()
00081 {
00082   if( NULL != instance_ )
00083   {
00084     delete instance_;
00085     instance_ = NULL;
00086   }
00087 }    
00088 
00089 
00090 //-------------------------------------------------------------------------
00091 // Purpose       : Constructor
00092 //
00093 // Special Notes : 
00094 //
00095 // Creator       : Jason Kraftcheck
00096 //
00097 // Creation Date : 08/25/03
00098 //-------------------------------------------------------------------------
00099 PartitionEngine::PartitionEngine()
00100 {
00101   CubitStatus r = GeometryQueryTool::instance()->register_intermediate_engine(this);
00102   assert(r == CUBIT_SUCCESS);
00103   if (CUBIT_SUCCESS != r) {
00104     PRINT_ERROR("Failed to register intermediate engine.\n");
00105   }
00106 }
00107 
00108 //-------------------------------------------------------------------------
00109 // Purpose       : Get instance
00110 //
00111 // Special Notes : 
00112 //
00113 // Creator       : Jason Kraftcheck
00114 //
00115 // Creation Date : 02/23/03
00116 //-------------------------------------------------------------------------
00117 PartitionEngine& PartitionEngine::instance()
00118 {
00119   if( instance_ == NULL )
00120   {
00121     instance_ = new PartitionEngine();
00122     assert( instance_ != NULL );
00123   }
00124   
00125   return *instance_;
00126 }
00127 
00128 //-------------------------------------------------------------------------
00129 // Purpose       : Used by SubEntitySet to update ID map.
00130 //
00131 // Special Notes : 
00132 //
00133 // Creator       : Jason Kraftcheck
00134 //
00135 // Creation Date : 02/23/03
00136 //-------------------------------------------------------------------------
00137 CubitStatus PartitionEngine::add_to_id_map( SubEntitySet* set, int unique_id )
00138 {
00139   if( uniqueIdMap.find(unique_id) != uniqueIdMap.end() )
00140     { assert(0); return CUBIT_FAILURE; }
00141   uniqueIdMap[unique_id] = set;
00142   return CUBIT_SUCCESS;
00143 }
00144 
00145 //-------------------------------------------------------------------------
00146 // Purpose       : Used by SubEntitySet to update ID map.
00147 //
00148 // Special Notes : 
00149 //
00150 // Creator       : Jason Kraftcheck
00151 //
00152 // Creation Date : 02/23/03
00153 //-------------------------------------------------------------------------
00154 CubitStatus PartitionEngine::remove_from_id_map( SubEntitySet* set, int id )
00155 {
00156   std::map<int,SubEntitySet*>::iterator itor = uniqueIdMap.find(id);
00157   if( itor == uniqueIdMap.end() || itor->second != set )
00158     { assert(0); return CUBIT_FAILURE; }
00159   uniqueIdMap.erase(itor);
00160   return CUBIT_SUCCESS;
00161 }
00162 
00163 //-------------------------------------------------------------------------
00164 // Purpose       : Retreive an entity from the ID map
00165 //
00166 // Special Notes : 
00167 //
00168 // Creator       : Jason Kraftcheck
00169 //
00170 // Creation Date : 02/23/03
00171 //-------------------------------------------------------------------------
00172 SubEntitySet* PartitionEngine::get_from_id_map( int id )
00173 {
00174   std::map<int,SubEntitySet*>::iterator itor = uniqueIdMap.find(id);
00175   return itor == uniqueIdMap.end() ? 0 : itor->second;
00176 }
00177 
00178 //-------------------------------------------------------------------------
00179 // Purpose       : Replicate solid model topology in partition layer
00180 //
00181 // Special Notes : 
00182 //
00183 // Creator       : Jason Kraftcheck
00184 //
00185 // Creation Date : 02/23/03
00186 //-------------------------------------------------------------------------
00187 SubCurve* PartitionEngine::replace_curve( Curve* curve )
00188 {
00189   SubCurve* result = dynamic_cast<SubCurve*>(curve);
00190   if( result )
00191     return result;
00192  
00193   if( dynamic_cast<SegmentedCurve*>(curve) )
00194     return 0;
00195   
00196   DLIList<TopologyBridge*> list;
00197   //curve->get_children_virt( list );
00198   //fix_up_query_results( list );
00199   curve->get_children(list, false, layer());
00200   PartitionPoint *start_pt = 0, *end_pt = 0;
00201   bool new_start = false, new_end = false;
00202   list.reset();
00203   TopologyBridge* bridge = list.get_and_step();
00204   start_pt = dynamic_cast<PartitionPoint*>(bridge);
00205   if( ! start_pt ) 
00206   {
00207     start_pt = replace_point( dynamic_cast<TBPoint*>(bridge) );
00208     if( ! start_pt )
00209       return 0;
00210     new_start = true;
00211   }
00212   if( list.size() == 1 )
00213   {
00214     end_pt = start_pt;
00215   }
00216   else if( list.size() == 2 )
00217   {
00218     bridge = list.get();
00219     end_pt = dynamic_cast<PartitionPoint*>(bridge);
00220     if( !end_pt )
00221     {
00222       end_pt = replace_point( dynamic_cast<TBPoint*>(bridge) );
00223       new_end = true;
00224       if( !end_pt )
00225       {
00226         if( new_start )
00227           restore_point( start_pt );
00228         return 0;
00229       }
00230     }
00231   }
00232   
00233   assert( start_pt && end_pt );
00234   
00235   result = new SubCurve( curve );
00236   if( ! result->start_point( start_pt ) ||
00237       ! result->end_point( end_pt ) )
00238   {
00239     result->start_point(0);
00240     result->end_point(0);
00241     delete result;
00242     if( new_start )
00243       restore_point( start_pt );
00244     if( new_end )
00245       restore_point( end_pt );
00246     return 0;
00247   }
00248   if( curve->owner() )
00249   {
00250     curve->owner()->swap_bridge(curve, result, false);
00251   }
00252   curve->owner(&(result->sub_entity_set()));
00253   
00254   list.clean_out();
00255   curve->get_parents_virt( list );
00256   //fix_up_query_results( list );
00257   
00258   for( int i = list.size(); i--; )
00259   {
00260     bridge = list.get_and_step();
00261     CoEdgeSM* coedge = dynamic_cast<CoEdgeSM*>(bridge);
00262     assert( coedge != NULL );
00263     PartitionCoEdge* pcoedge = new PartitionCoEdge( coedge );
00264     CubitStatus s = result->add( pcoedge );
00265     assert( s );
00266     if (CUBIT_SUCCESS != s) {
00267       PRINT_ERROR("Failed to add coedge to SubCurve.\n");
00268       return NULL;
00269     }
00270     if( coedge->owner() )
00271       coedge->owner()->swap_bridge(coedge, pcoedge, false);
00272     coedge->owner(&(pcoedge->sub_entity_set()));
00273   }
00274   
00275   
00276   PartitionBody* body = 0;
00277   if( result->start_point()->sub_entity_set().body() )
00278     body = result->start_point()->sub_entity_set().body();
00279   else if( result->end_point()->sub_entity_set().body() )
00280     body = result->end_point()->sub_entity_set().body();
00281   else
00282     body = make_body(result);
00283     
00284   if( body )
00285   {
00286     if( !result->start_point()->sub_entity_set().body() )
00287       body->add(result->start_point()->sub_entity_set());
00288     if( !result->end_point()->sub_entity_set().body() )
00289       body->add(result->end_point()->sub_entity_set());
00290     body->add(result->sub_entity_set());
00291     PartitionCoEdge* coedge = 0;
00292     while ( (coedge = result->next_coedge(coedge)) )
00293       if ( !coedge->sub_entity_set().body() )
00294         body->add(coedge->sub_entity_set());
00295   }
00296 
00297   // we must notify the graphics of the modify from "real" to virtual -- KGM
00298   // I realize that this is not where the other notifies are completed but there
00299   // is no knowledge of the change later on. 
00300   CubitObservable* observable = dynamic_cast<CubitObservable*>(result->topology_entity());
00301   if (observable)
00302   {
00303      AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_MODIFIED, dynamic_cast<RefEntity*>(result->topology_entity())));
00304   }
00305 
00306   return result;
00307 }
00308 
00309 //-------------------------------------------------------------------------
00310 // Purpose       : Replicate solid model topology in partition layer
00311 //
00312 // Special Notes : 
00313 //
00314 // Creator       : Jason Kraftcheck
00315 //
00316 // Creation Date : 02/23/03
00317 //-------------------------------------------------------------------------
00318 SubSurface* PartitionEngine::replace_surface( Surface* surface )
00319 {
00320   int i, j;
00321 
00322   // check if the input surface is already a SubSurface
00323   SubSurface* result = dynamic_cast<SubSurface*>(surface);
00324   if( result )
00325     return result;
00326  
00327   // check if the input surface is already a PartitionSurface
00328   if( dynamic_cast<PartitionSurface*>(surface) )
00329     return 0;
00330   
00331   // create a new SubSurface, swap out the TBOwner if it
00332   // exists and reset the input surface TBOwner.
00333   DLIList<TopologyBridge*> loop_list, coe_list, curve_list;
00334   surface->get_children( loop_list, false, layer() );
00335   result = new SubSurface( surface );
00336   if( surface->owner() )
00337     surface->owner()->swap_bridge(surface, result, false);
00338   surface->owner(&(result->sub_entity_set()));
00339   
00340   // Add the loop onto the new surface
00341   loop_list.reset();
00342   for( i = loop_list.size(); i--; )
00343   {
00344     LoopSM* loop = dynamic_cast<LoopSM*>(loop_list.get_and_step());
00345     PartitionLoop* partloop = new PartitionLoop();
00346     result->add( partloop );
00347     if( loop->owner() )
00348       loop->owner()->swap_bridge( loop, partloop, false );
00349     loop->owner(0);
00350     
00351     // Take care of the curves in the loop
00352     coe_list.clean_out();
00353     loop->get_children( coe_list, false, layer() );
00354     
00355     coe_list.reset();
00356     for( j = coe_list.size(); j--; )
00357     {
00358       CoEdgeSM* coedge = dynamic_cast<CoEdgeSM*>(coe_list.get_and_step());
00359       if(!dynamic_cast<PartitionCoEdge*>(coedge) &&
00360          !dynamic_cast<SubEntitySet*>(coedge->owner()) )
00361       {
00362         curve_list.clean_out();
00363         coedge->get_children_virt( curve_list );
00364         assert( curve_list.size() == 1 );
00365       
00366         Curve* curve = dynamic_cast<Curve*>(curve_list.get());
00367         assert(! dynamic_cast<PartitionCurve*>(curve) );
00368         SubCurve* pcurve = replace_curve( curve );
00369         assert(pcurve != NULL);
00370         if (NULL == pcurve) {
00371           PRINT_ERROR("Failed to replace curve.\n");
00372           return NULL;
00373         }
00374       }
00375     }
00376     
00377     coe_list.clean_out();
00378     loop->get_children( coe_list, false, layer() );
00379     
00380     coe_list.reset();
00381     PartitionCoEdge *curr, *prev = 0;
00382     coe_list.reset();
00383     for( j = coe_list.size(); j--; )
00384     {
00385       curr = dynamic_cast<PartitionCoEdge*>(coe_list.get_and_step());
00386       assert( curr != NULL );
00387       partloop->insert_after( curr, prev );
00388       prev = curr;
00389     }
00390     
00391   }
00392   
00393   // If the facet data is incorrect put everything back
00394   if (!result->init_facet_data()) {
00395     restore_surface( result );
00396     return 0;
00397   }
00398   
00399   // finalize by making the body
00400   PartitionBody* body = make_body(result);
00401   if( body )
00402     body->add(result->sub_entity_set());
00403   
00404   return result;
00405 }
00406 
00407 //-------------------------------------------------------------------------
00408 // Purpose       : Replicate solid model topology in partition layer
00409 //
00410 // Special Notes : 
00411 //
00412 // Creator       : Jason Kraftcheck
00413 //
00414 // Creation Date : 02/23/03
00415 //-------------------------------------------------------------------------
00416 PartitionLump* PartitionEngine::replace_lump( Lump* lump )
00417 {
00418   int i, j;
00419   PartitionLump* result = dynamic_cast<PartitionLump*>(lump);
00420   if( result )
00421     return result;
00422  
00423   DLIList<TopologyBridge*> shell_list, surface_list;
00424   lump->get_children( shell_list, false, layer() );
00425   
00426   DLIList<PartitionShell*> new_shells;
00427   shell_list.reset();
00428   for( i = shell_list.size(); i--; )
00429   {
00430     ShellSM* shell = dynamic_cast<ShellSM*>(shell_list.get_and_step());
00431     PartitionShell* pshell = new PartitionShell();
00432     new_shells.append(pshell);
00433     if( shell->owner() )
00434       shell->owner()->swap_bridge( shell, pshell, false );
00435     shell->owner(0);
00436     
00437     surface_list.clean_out();
00438     shell->get_children( surface_list, false, layer() );
00439     
00440     surface_list.reset();
00441     for( j = surface_list.size(); j--; )
00442     {
00443       Surface* surface = dynamic_cast<Surface*>(surface_list.get_and_step());
00444       PartitionSurface* psurf = dynamic_cast<PartitionSurface*>(surface);
00445       if( !psurf )
00446       {
00447         psurf = replace_surface( surface );
00448         if (!psurf) 
00449         {
00450           while (new_shells.size())
00451             destroy_shell(new_shells.pop());
00452           return 0;
00453         }
00454       }
00455       
00456       Surface* real_surf = dynamic_cast<Surface*>(psurf->partitioned_entity());
00457       assert(!!real_surf);
00458       CubitSense sense = real_surf->get_shell_sense(shell);
00459       assert(sense == CUBIT_FORWARD || sense == CUBIT_REVERSED);
00460       pshell->add( psurf, sense );
00461     }
00462   }
00463 
00464   result = new PartitionLump( lump );
00465   if( lump->owner() )
00466     lump->owner()->swap_bridge(lump, result, false);
00467   lump->owner(&(result->sub_entity_set()));
00468   new_shells.reverse();
00469   while( new_shells.size() )
00470     result->add(new_shells.pop());
00471   
00472   PartitionBody* body = make_body(result);
00473   if( body )
00474     body->add( result->sub_entity_set() );
00475   
00476   return result;
00477 }
00478 
00479 //-------------------------------------------------------------------------
00480 // Purpose       : Replicate solid model topology in partition layer
00481 //
00482 // Special Notes : 
00483 //
00484 // Creator       : Jason Kraftcheck
00485 //
00486 // Creation Date : 02/23/03
00487 //-------------------------------------------------------------------------
00488 PartitionPoint* PartitionEngine::replace_point( TBPoint* point )
00489 {
00490   PartitionPoint* result = dynamic_cast<PartitionPoint*>(point);
00491   if( !result )
00492   {
00493     result = new PartitionPoint( point );
00494   }  
00495   
00496   if( result )
00497   {
00498     if( point->owner() )
00499       point->owner()->swap_bridge( point, result, false );
00500     point->owner( &(result->sub_entity_set()) );
00501   }
00502   
00503   return result;
00504 }
00505 
00506 //-------------------------------------------------------------------------
00507 // Purpose       : Restore original solid model topology.  (Inverse of
00508 //                 replace_point.)
00509 //
00510 // Special Notes : 
00511 //
00512 // Creator       : Jason Kraftcheck
00513 //
00514 // Creation Date : 02/23/03
00515 //-------------------------------------------------------------------------
00516 TBPoint* PartitionEngine::restore_point( PartitionPoint* point )
00517 {
00518   if( point->num_curves() )
00519     return 0;
00520   
00521   TBPoint* result = point->real_point();
00522   if( result )
00523   {
00524     point->sub_entity_set().unwrap_attributes();
00525     point->sub_entity_set().remove_bridge(result);
00526     if( point->owner() )
00527       point->owner()->swap_bridge( point, result, false );
00528     delete point;
00529   }
00530   
00531   return result;
00532 }
00533 
00534 //-------------------------------------------------------------------------
00535 // Purpose       : Restore original solid model topology.  (Inverse of
00536 //                 replace_curve.)
00537 //
00538 // Special Notes : 
00539 //
00540 // Creator       : Jason Kraftcheck
00541 //
00542 // Creation Date : 02/23/03
00543 //-------------------------------------------------------------------------
00544 Curve* PartitionEngine::restore_curve( SubCurve* curve )
00545 {
00546   if( curve->num_partitions() > 1 )
00547     return 0;
00548   
00549   PartitionCoEdge* coedge = 0;
00550   while( (coedge = curve->next_coedge( coedge )) )
00551     if( coedge->get_loop() )
00552       return 0;
00553   
00554   while( (coedge = curve->next_coedge(0)) )
00555   {
00556     curve->remove( coedge );
00557     CoEdgeSM* real_coedge = coedge->real_coedge();
00558     if( real_coedge )
00559     {
00560       coedge->sub_entity_set().remove_bridge( real_coedge );
00561       if( coedge->owner() )
00562         coedge->owner()->swap_bridge( coedge, real_coedge, false );
00563     }
00564     delete coedge;
00565   }
00566   
00567   PartitionPoint* start = curve->start_point();
00568   curve->start_point( 0 );
00569   if( start->num_curves() == 0 )
00570   {
00571     if( start->real_point() )
00572       restore_point( start );
00573     else
00574       delete start;
00575   }
00576   
00577   PartitionPoint* end = curve->end_point();
00578   curve->end_point(0);
00579   if( end->num_curves() == 0 )
00580   {
00581     if( end->real_point() )
00582       restore_point( end );
00583     else
00584       delete end;
00585   }
00586   
00587   Curve* result = curve->real_curve();
00588   curve->sub_entity_set().unwrap_attributes();
00589   curve->sub_entity_set().remove_bridge( result );
00590   if( curve->owner() )
00591     curve->owner()->swap_bridge( curve, result, false );
00592   delete curve;
00593 
00594   // we must notify the graphics of the modify from "real" to virtual -- KGM
00595   // I realize that this is not where the other notifies are completed but there
00596   // is no knowledge of the change later on. 
00597   CubitObservable* observable = dynamic_cast<CubitObservable*>(result->topology_entity());
00598   if (observable)
00599   {
00600     AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_MODIFIED, dynamic_cast<RefEntity*>(result->topology_entity())));
00601   }
00602 
00603   return result;
00604 }
00605 
00606 
00607 //-------------------------------------------------------------------------
00608 // Purpose       : Restore original solid model topology.  (Inverse of
00609 //                 replace_surface.)
00610 //
00611 // Special Notes : 
00612 //
00613 // Creator       : Jason Kraftcheck
00614 //
00615 // Creation Date : 02/23/03
00616 //-------------------------------------------------------------------------
00617 Surface* PartitionEngine::restore_surface( SubSurface* surface )
00618 {
00619   if( surface->sub_entity_set().has_lower_order() || surface->next_co_surface() )
00620     return 0;
00621   
00622   while( PartitionLoop* loop = surface->next_loop() )
00623     // while surface has loops...
00624   {
00625     surface->remove( loop );
00626     
00627     while( loop->first_coedge() )
00628     {
00629       PartitionCoEdge* coedge = loop->first_coedge();
00630       loop->remove( coedge );
00631       
00632       SubCurve* curve = dynamic_cast<SubCurve*>(coedge->get_curve());
00633       if( !curve || curve->sub_entity_set().has_lower_order() )
00634         continue;
00635       
00636       bool remove = true;
00637       coedge = 0;
00638       while( (coedge = curve->next_coedge( coedge )) )
00639       {
00640         if( coedge->get_loop() )
00641         {
00642           remove = false;
00643           break;
00644         }
00645       }
00646       
00647       if( remove )
00648       {
00649         restore_curve( curve );
00650       }
00651       
00652     }
00653     
00654     delete loop;
00655   }
00656   
00657   
00658   Surface* result = surface->partitioned_surface();
00659   surface->sub_entity_set().unwrap_attributes();
00660   surface->sub_entity_set().remove_bridge( result );
00661   if( surface->owner() )
00662     surface->owner()->swap_bridge( surface, result, false );
00663   delete surface;
00664   return result;
00665 }
00666 
00667 //-------------------------------------------------------------------------
00668 // Purpose       : Destroy a single partition of a volume.
00669 //
00670 // Special Notes : Will restore original volume if this is the last/only
00671 //                  partition.
00672 //
00673 // Creator       : Jason Kraftcheck
00674 //
00675 // Creation Date : 02/11/03
00676 //-------------------------------------------------------------------------
00677 CubitStatus PartitionEngine::destroy_lump( PartitionLump* lump )
00678 {
00679     /* only partition lump? */
00680   if ( ! lump->sub_entity_set().has_multiple_sub_entities() )
00681   {
00682     DLIList<PartitionEntity*> child_entities;
00683     lump->sub_entity_set().get_lower_order( child_entities );
00684     DLIList<PartitionSurface*> surf_list;
00685     CAST_LIST( child_entities, surf_list, PartitionSurface );
00686     
00687     while( surf_list.size() )
00688       if( ! remove_surface( surf_list.pop() ) )
00689         return CUBIT_FAILURE;
00690     
00691     return restore_lump(lump) ? CUBIT_SUCCESS : CUBIT_FAILURE;
00692   }
00693   
00694   PartitionShell* shell;
00695   while ( (shell = lump->next_shell(0)) )
00696   {
00697     lump->remove(shell);
00698     destroy_shell(shell);
00699   }
00700   delete lump;
00701   
00702   return CUBIT_SUCCESS;
00703 }
00704       
00705     
00706 
00707 //-------------------------------------------------------------------------
00708 // Purpose       : Restore original solid model topology.  (Inverse of
00709 //                 replace_lump.)
00710 //
00711 // Special Notes : 
00712 //
00713 // Creator       : Jason Kraftcheck
00714 //
00715 // Creation Date : 02/23/03
00716 //-------------------------------------------------------------------------
00717 Lump* PartitionEngine::restore_lump( PartitionLump* lump )
00718 {
00719   if( lump->sub_entity_set().has_lower_order() )
00720     return 0;
00721   
00722   while( PartitionShell* shell = lump->next_shell() )
00723     // while surface has loops...
00724   {
00725     lump->remove( shell );
00726     destroy_shell( shell );
00727   }
00728   
00729   
00730   Lump* result = lump->real_lump();
00731   lump->sub_entity_set().unwrap_attributes();
00732   lump->sub_entity_set().remove_bridge( result );
00733   if( lump->owner() )
00734     lump->owner()->swap_bridge( lump, result, false );
00735   delete lump;
00736   return result;
00737 }
00738 
00739 bool PartitionEngine::is_partition(TBOwner *bridge_owner)
00740 {
00741   bool ret = false;
00742   if(bridge_owner)
00743   {
00744     if(dynamic_cast<SubEntitySet*>(bridge_owner))
00745     {
00746       ret = true;
00747     }
00748   }
00749   return ret;
00750 }
00751 
00752 bool PartitionEngine::is_composite(TBOwner *bridge_owner)
00753 {
00754   return false;
00755 }
00756 
00757 bool PartitionEngine::is_composite(TopologyBridge *bridge)
00758 {
00759   return false;
00760 }
00761 
00762 //-------------------------------------------------------------------------
00763 // Purpose       : Destroy a shell
00764 //
00765 // Special Notes : 
00766 //
00767 // Creator       : Jason Kraftcheck
00768 //
00769 // Creation Date : 03/11/04
00770 //-------------------------------------------------------------------------
00771 CubitStatus PartitionEngine::destroy_shell( PartitionShell* shell )
00772 {
00773   if (shell->get_lump())
00774   {
00775     assert(0);
00776     return CUBIT_FAILURE;
00777   }
00778   
00779   while( PartitionCoSurf* cosurf = shell->next_co_surface() )
00780   {
00781     shell->remove( cosurf );
00782 
00783     SubSurface* psurf = dynamic_cast<SubSurface*>(cosurf->get_surface());
00784     if (psurf)
00785     {
00786       psurf->remove(cosurf);
00787 
00788         // If PartitionSurface is the same as the underlying surface
00789         // and is not part of any other PartitionLumps, remove it.
00790       if( !psurf->sub_entity_set().has_lower_order() &&
00791            psurf->next_co_surface() == 0 )
00792         restore_surface( psurf );
00793     }
00794     
00795     delete cosurf;
00796   }
00797     
00798   delete shell;
00799   return CUBIT_SUCCESS;
00800 }
00801 
00802 
00803 
00804 //-------------------------------------------------------------------------
00805 // Purpose       : Partition a curve
00806 //
00807 // Special Notes : public interface to curve partitioning
00808 //
00809 // Creator       : Jason Kraftcheck
00810 //
00811 // Creation Date : 02/23/03
00812 //-------------------------------------------------------------------------
00813 TBPoint* PartitionEngine::insert_point( Curve* curve, double u )
00814 {
00815   PartitionCurve* pcurve = dynamic_cast<PartitionCurve*>(curve);
00816   bool replaced_curve = false;
00817   
00818   if( !pcurve )
00819   {
00820     if( CompositeCurve* comp = dynamic_cast<CompositeCurve*>(curve) )
00821     {
00822       return CompositeEngine::instance().insert_point( comp, u );
00823     }
00824   
00825     pcurve = replace_curve( curve );
00826     if( !pcurve )
00827       return 0;
00828     replaced_curve = true;
00829   }
00830   
00831   CubitVector coords;
00832   if( ! pcurve->position_from_u( u, coords ) )
00833   {
00834     if( replaced_curve )
00835       restore_curve( dynamic_cast<SubCurve*>(pcurve) );
00836     return 0;
00837   }
00838   
00839   PartitionPoint* npoint = new PartitionPoint( coords, pcurve );
00840   PartitionCurve* ncurve = insert_point(pcurve, npoint);
00841   
00842   if( !ncurve )
00843   {
00844     if( replaced_curve )
00845       restore_curve( dynamic_cast<SubCurve*>(pcurve) );
00846     delete npoint;
00847     return 0;
00848   }
00849   
00850   return npoint;
00851 }
00852 
00853 
00854 //-------------------------------------------------------------------------
00855 // Purpose       : Partition a curve
00856 //
00857 // Special Notes : not public
00858 //
00859 // Creator       : Jason Kraftcheck
00860 //
00861 // Creation Date : 02/23/03
00862 //-------------------------------------------------------------------------
00863 PartitionCurve* PartitionEngine::insert_point( PartitionCurve* pcurve, 
00864                                                PartitionPoint* npoint )
00865 {
00866   const double TOLSQR = GEOMETRY_RESABS * GEOMETRY_RESABS;
00867   CubitVector coords = npoint->coordinates();
00868   double u = pcurve->u_from_position(coords);
00869   double u_min, u_max;
00870   pcurve->get_param_range( u_min, u_max );
00871 
00872   if(u_min > u_max)
00873   {
00874     double dtemp = u_min;
00875     u_min = u_max;
00876     u_max = dtemp;
00877   }
00878 
00879   if( u - u_min < CUBIT_RESABS || u_max - u < CUBIT_RESABS )
00880     return 0;
00881   
00882   if( (pcurve->start_point()->coordinates() - coords).length_squared() < TOLSQR 
00883    || (pcurve->end_point()->coordinates() - coords).length_squared() < TOLSQR )
00884     return 0;
00885   
00886   PartitionCurve* ncurve = pcurve->split( u );
00887   if( !ncurve ) 
00888     return 0;
00889   
00890   ncurve->end_point( pcurve->end_point() );
00891   pcurve->end_point( npoint );
00892   ncurve->start_point( npoint );
00893   pcurve->fix_facet_data( ncurve );
00894   
00895   PartitionCoEdge *pcoedge = 0, *ncoedge = 0;
00896   while( (pcoedge = pcurve->next_coedge( pcoedge )) )
00897   {
00898     ncoedge = new PartitionCoEdge( pcoedge );
00899     ncurve->add( ncoedge );
00900     if( pcoedge->get_loop() )
00901     {
00902       if( pcoedge->sense() == CUBIT_FORWARD )
00903         pcoedge->get_loop()->insert_after( ncoedge, pcoedge );
00904       else
00905         pcoedge->get_loop()->insert_before( ncoedge, pcoedge );
00906     }
00907   }
00908   
00909   if( pcurve->owner() )
00910     pcurve->owner()->notify_split( ncurve, pcurve );
00911   
00912   return ncurve;
00913 }
00914 
00915 //-------------------------------------------------------------------------
00916 // Purpose       : un-partition a curve
00917 //
00918 // Special Notes : 
00919 //
00920 // Creator       : Jason Kraftcheck
00921 //
00922 // Creation Date : 02/23/03
00923 //-------------------------------------------------------------------------
00924 Curve* PartitionEngine::remove_point( PartitionPoint* point, 
00925                                       PartitionCurve* dead_curves[2] )
00926 {
00927   if( dead_curves )
00928     dead_curves[0] = dead_curves[1] = 0;
00929   
00930   if( point->num_curves() > 2 )
00931     return 0;
00932       
00933   DLIList<TopologyBridge*> curve_bridges;
00934   point->get_parents_virt( curve_bridges );
00935   if( curve_bridges.size() > 2 )
00936     return 0;
00937   
00938   if( curve_bridges.size() == 1 )
00939   {
00940     PartPTCurve* point_curve = dynamic_cast<PartPTCurve*>(curve_bridges.get());
00941     if( ! point_curve )
00942       return 0;
00943     
00944     if( dead_curves )
00945       dead_curves[0] = point_curve;
00946     remove_point_curve( point );
00947     return 0;
00948   }
00949 
00950 /*  
00951   TopologyBridge* real = point->partitioned_entity();
00952   if( dynamic_cast<TBPoint*>(real) )
00953   {
00954     Curve* curve1 = dynamic_cast<Curve*>(curve_bridges.get());
00955     Curve* curve2 = dynamic_cast<Curve*>(curve_bridges.next());
00956     PartitionCurve* pc1 = dynamic_cast<PartitionCurve*>(curve1);
00957     PartitionCurve* pc2 = dynamic_cast<PartitionCurve*>(curve2);
00958     assert( pc1 || pc2 );
00959     if( !pc1 )
00960       pc1 = replace_curve( curve1 );
00961     if( !pc2 )
00962       pc2 = replace_curve( curve2 );
00963     
00964     CompositeEngine::instance()->remove_point( dynamic_cast<TBPoint*>(real) );
00965     bool reverse = ( pc1->start_point() == pc2->start_point() ||
00966                      pc2->end_point() == pc2->end_point() );
00967     if( pc1->partitioned_entity() == 0 )
00968     {
00969       bool prepend = false;
00970       if( pc1->other_point( pc2->start_point() ) )
00971         prepend = true;
00972       pc2->sub_entity_set().merge( pc1->sub_entity_set(), reverse, prepend );
00973     }
00974     else if( pc2->partitioned_entity() == 0 )
00975     {
00976       bool prepend = false;
00977       if( pc2->other_point( pc1->start_point() ) )
00978         prepend = true;
00979       pc1->sub_entity_set().merge( pc2->sub_entity_set(), reverse, prepend );
00980     }
00981     else
00982       return 0;
00983   }
00984 */  
00985   if( point->num_curves() != 2 )
00986     return 0;
00987   
00988   PartitionCurve* survivor = point->next_curve(0);
00989   PartitionCurve* casualty = point->next_curve(survivor);
00990   if( survivor->start_point() == point &&
00991       casualty->end_point() == point )
00992   {
00993       // swap
00994     survivor = casualty;
00995     casualty = point->next_curve(0);
00996   }
00997   
00998   if( ! survivor->combine( casualty ) )
00999     return 0;
01000     
01001   PartitionPoint* other_pt = 
01002     casualty->start_point() == point ? 
01003     casualty->end_point() : casualty->start_point();
01004   casualty->start_point(0);
01005   casualty->end_point(0);
01006   
01007   if( survivor->start_point() == point )
01008     survivor->start_point( other_pt );
01009   else
01010     survivor->end_point( other_pt );
01011   
01012   delete point;
01013   
01014   while( PartitionCoEdge* coedge = casualty->next_coedge(0) )
01015   {
01016     if( coedge->get_loop() )
01017       coedge->get_loop()->remove( coedge );
01018     casualty->remove( coedge );
01019     delete coedge;
01020   }
01021   delete casualty;
01022   if( dead_curves )
01023     dead_curves[0] = casualty;
01024   
01025   Curve* result = survivor;
01026   SubCurve* subcurve = dynamic_cast<SubCurve*>(survivor);
01027   if( subcurve && !survivor->sub_entity_set().has_multiple_sub_entities() )
01028   {
01029     Curve* real_curve = restore_curve( subcurve );
01030     if (real_curve)
01031     { 
01032       result = real_curve;
01033       if (dead_curves)
01034         dead_curves[1] = survivor;
01035     } 
01036   }
01037 
01038   return result;
01039 }
01040 
01041 //-------------------------------------------------------------------------
01042 // Purpose       : Remove a point-curve (point imprinted on a surface)
01043 //
01044 // Special Notes : 
01045 //
01046 // Creator       : Jason Kraftcheck
01047 //
01048 // Creation Date : 02/23/03
01049 //-------------------------------------------------------------------------
01050 CubitStatus PartitionEngine::remove_point_curve( PartitionPoint* point )
01051 {
01052   if( point->num_curves() != 1 )
01053     return CUBIT_FAILURE;
01054   
01055   PartPTCurve* curve = dynamic_cast<PartPTCurve*>(point->next_curve(0));
01056   if( !curve )
01057     return CUBIT_FAILURE;
01058   
01059   PartitionSurface* surf = 0;  
01060   if( curve->num_coedges() )
01061   {
01062     assert( curve->num_coedges() == 1 );
01063     PartitionCoEdge* coedge = curve->next_coedge(0);
01064     PartitionLoop* loop = coedge->get_loop();
01065     if( loop )
01066     {
01067       surf = loop->get_surface();
01068       surf->remove( loop );
01069       loop->remove( coedge );
01070       assert( loop->num_coedges() == 0 );
01071       delete loop;
01072     }
01073     curve->remove( coedge );
01074     delete coedge;
01075   }
01076   
01077   curve->start_point(0);
01078   curve->end_point(0);
01079   delete curve;
01080   delete point;
01081   
01082   if( surf && surf->owner() )
01083     surf->owner()->notify_topology_modified( surf );
01084   
01085   return CUBIT_SUCCESS;
01086 }
01087 
01088 //-------------------------------------------------------------------------
01089 // Purpose       : Topological modifications for surface partitioning
01090 //
01091 // Special Notes : non-public, assumes surface facets have already been
01092 //                 imprinted and the polyline of the imprint is already
01093 //                 associated with the passed curve.
01094 //
01095 // Creator       : Jason Kraftcheck
01096 //
01097 // Creation Date : 02/23/03
01098 //-------------------------------------------------------------------------
01099 PartitionSurface* PartitionEngine::insert_curve( PartitionSurface* surface, 
01100                                                  SegmentedCurve* curve )
01101 {
01102   PartitionSurface* new_surface = 0;
01103   assert( &(curve->sub_entity_set()) == &(surface->sub_entity_set()) );
01104   
01105   PartitionPoint *start_point = curve->start_point();
01106   PartitionPoint *end_point   = curve->end_point();
01107   PartitionLoop  *start_loop = 0, *end_loop = 0;
01108   PartitionCoEdge *start_prev_coedge = 0, *start_next_coedge = 0;
01109   PartitionCoEdge *end_prev_coedge = 0, *end_next_coedge = 0;
01110   
01111     // find where to insert new curve in loop
01112   if ( !find_coedges( surface, curve, start_point, start_prev_coedge, start_next_coedge ) )
01113     return 0;
01114   if ( !find_coedges( surface, curve, end_point, end_prev_coedge, end_next_coedge )) 
01115     return 0;
01116     
01117   assert((!start_prev_coedge && !start_next_coedge) ||
01118          (start_prev_coedge && start_next_coedge && 
01119           start_prev_coedge->get_loop() == start_next_coedge->get_loop()));
01120   assert((!end_prev_coedge && !end_next_coedge) ||
01121          (end_prev_coedge && end_next_coedge && 
01122           end_prev_coedge->get_loop() == end_next_coedge->get_loop()));
01123   if ( start_prev_coedge )
01124     start_loop = start_prev_coedge->get_loop();
01125   if ( end_prev_coedge )
01126     end_loop = end_prev_coedge->get_loop();
01127   
01128   
01129     // remove any point-curves
01130   PartitionCurve* pt_curve;
01131   PartPTCurve* point_curve;
01132   for ( int i = 0; i < 2; i++ ) // do once for each end point
01133   {
01134     PartitionPoint* pt = i ? end_point : start_point;
01135     pt_curve = pt->next_curve(0);
01136     while ( pt_curve  )
01137     {
01138       point_curve = dynamic_cast<PartPTCurve*>(pt_curve);
01139       pt_curve = pt->next_curve(pt_curve);
01140       if (point_curve && point_curve->next_coedge(0)->get_loop()->get_surface() == surface)
01141       {
01142         point_curve->start_point(0);
01143         point_curve->end_point(0);
01144 
01145         PartitionCoEdge* coedge = point_curve->next_coedge(0);
01146         point_curve->remove(coedge);
01147         assert( !point_curve->next_coedge(0) );
01148         PartitionLoop* loop = coedge->get_loop();
01149         loop->remove(coedge);
01150         assert( !loop->first_coedge() );
01151         surface->remove(loop);
01152         delete loop;
01153         delete coedge;
01154         delete point_curve;
01155       }
01156     }
01157   }
01158   
01159   
01160   PartitionCoEdge* forward = new PartitionCoEdge( surface, CUBIT_FORWARD );
01161   PartitionCoEdge* reverse = new PartitionCoEdge( surface, CUBIT_REVERSED );
01162   curve->add(forward);
01163   curve->add(reverse);
01164 
01165     // new one-curve loop?
01166   if( !start_loop && !end_loop )
01167   {
01168     PartitionLoop* new_loop = new PartitionLoop();
01169     surface->add( new_loop );
01170     new_loop->insert_after( forward, 0 );
01171     
01172     if( curve->start_point() == curve->end_point() )
01173     {
01174       PartitionLoop* loop2 = new PartitionLoop();
01175       loop2->insert_after( reverse, 0 );
01176       
01177       if( VGLoopTool
01178           <PartitionSurface,PartitionLoop,PartitionCoEdge,PartitionCurve,PartitionPoint>
01179           ::loop_angle_metric( forward ) > 0 )
01180       {
01181         new_loop = loop2;
01182       }
01183       else
01184       {
01185         surface->remove(new_loop);
01186         surface->add( loop2 );
01187       }
01188       
01189       new_surface = split_surface( surface, new_loop->first_coedge() );
01190       new_surface->add( new_loop );
01191     }
01192     else
01193     {
01194       new_loop->insert_after( reverse, forward );
01195     }
01196   }
01197       
01198     // sipe
01199   else if( !start_loop || !end_loop )
01200   {
01201     PartitionCoEdge* prev;
01202     PartitionLoop* loop;
01203     if( start_loop )
01204     {
01205       loop = start_loop;
01206       prev = start_prev_coedge;
01207     }
01208     else
01209     {
01210       loop = end_loop;
01211       prev = end_prev_coedge;
01212     }
01213     
01214     if( forward->start_point() == prev->end_point() )
01215     {
01216       loop->insert_after( forward, prev );
01217       loop->insert_after( reverse, forward );
01218     }
01219     else
01220     {
01221       assert( reverse->start_point() == prev->end_point() );
01222       loop->insert_after( reverse, prev );
01223       loop->insert_after( forward, reverse );
01224     }
01225   }
01226   
01227     // join loops
01228   else if( start_loop != end_loop )
01229   {
01230     PartitionCoEdge* prev = start_prev_coedge;
01231     PartitionCoEdge* coedge = end_next_coedge;
01232     PartitionCoEdge* next = 0, *other_coedge;
01233     
01234     if( forward->start_point() == prev->end_point() )
01235     {
01236       start_loop->insert_after( forward, prev );
01237       prev = forward;
01238       other_coedge = reverse;
01239     }
01240     else 
01241     {
01242       assert( reverse->start_point() == prev->end_point() );
01243       start_loop->insert_after( reverse, prev );
01244       prev = reverse;
01245       other_coedge = forward;
01246     }
01247     
01248     while ( end_loop->first_coedge() )
01249     {
01250       next = end_loop->next_coedge( coedge );
01251       end_loop->remove( coedge );
01252       start_loop->insert_after( coedge, prev );
01253       prev = coedge;
01254       coedge = next;
01255     }
01256     
01257       // The other coedge for the curve we are restoring...
01258     start_loop->insert_after( other_coedge, prev );
01259     
01260     assert( end_loop->num_coedges() == 0 );
01261     surface->remove( end_loop );
01262     delete end_loop;
01263   }
01264   
01265     // split a loop (and create a new surface)
01266   else
01267   {
01268     assert( start_loop == end_loop );
01269     
01270       // If the curve we are adding results in a hole that
01271       // intersects the loop we are splitting at a single
01272       // vertex, we need to figure out which of the coedges
01273       // goes in the hole and which is added to the loop
01274       // we are splitting.
01275     if( forward->start_point() == forward->end_point() )
01276     {
01277       assert( start_next_coedge == end_next_coedge );
01278       assert( start_prev_coedge == end_prev_coedge );
01279       
01280       CubitVector prev_tan, forward_tan, reverse_tan, normal, junk;
01281       CubitVector point = forward->start_point()->coordinates();
01282       start_prev_coedge->get_curve()->closest_point( point, junk, &prev_tan );
01283       if( start_prev_coedge->sense() == CUBIT_FORWARD ) // yes, forward!!!
01284         prev_tan *= -1.0;
01285       forward->get_curve()->closest_point( point, junk, &forward_tan );
01286       reverse_tan = forward_tan * -1.0;
01287       surface->closest_point( point, 0, &normal );
01288       
01289       double angle1 = normal.vector_angle( prev_tan, forward_tan );
01290       double angle2 = normal.vector_angle( prev_tan, reverse_tan );
01291       
01292       if( angle2 < angle1 )
01293       {
01294         PartitionCoEdge* temp = reverse;
01295         reverse = forward;
01296         forward = temp;
01297       }
01298     }
01299     
01300     else
01301     {
01302       if( forward->end_point() == end_next_coedge->start_point() )
01303       {
01304         PartitionCoEdge* temp = reverse;
01305         reverse = forward;
01306         forward = temp;
01307       }
01308     }
01309     
01310     end_loop = new PartitionLoop();
01311     start_loop->insert_after( forward, end_prev_coedge );
01312     end_loop->insert_after( reverse, 0 );
01313     
01314     PartitionCoEdge* coedge = end_next_coedge;
01315     PartitionCoEdge* prev = reverse;
01316     while( coedge != start_next_coedge )
01317     {
01318       PartitionCoEdge* next = start_loop->next_coedge( coedge );
01319       start_loop->remove( coedge );
01320       end_loop->insert_after( coedge, prev );
01321       prev = coedge;
01322       coedge = next;
01323     }
01324     
01325     new_surface = split_surface( surface, reverse );
01326     new_surface->add( end_loop );
01327   }
01328   
01329   if( new_surface )
01330   {
01331     PartitionCoSurf* cos = 0;
01332     while( (cos = surface->next_co_surface( cos )) )
01333       cos->get_shell()->add( new_surface, cos->sense() );
01334     if( surface->owner() )
01335       surface->owner()->notify_split( new_surface, surface );
01336     return new_surface;
01337   }
01338   else
01339   {
01340     if( surface->owner() )
01341       surface->owner()->notify_topology_modified( surface );
01342     return surface;
01343   }
01344 }
01345 
01346 
01347 //-------------------------------------------------------------------------
01348 // Purpose       : Find where to insert a curve in a loop
01349 //
01350 // Special Notes : 
01351 //
01352 // Creator       : Jason Kraftcheck
01353 //
01354 // Creation Date : 03/24/03
01355 //-------------------------------------------------------------------------
01356 CubitStatus PartitionEngine::find_coedges( PartitionSurface* surface,
01357                                            PartitionCurve* curve,
01358                                            PartitionPoint* point,
01359                                            PartitionCoEdge*& previous,
01360                                            PartitionCoEdge*& next )
01361 {
01362   const char* const bad_loop_message = "Internal error: Invalid loop. (%s:%d)\n";
01363   
01364     // Find list of all coedges around passed point
01365     // and in passed surface.
01366   DLIList<PartitionCoEdge*> point_coedges;
01367   PartitionCoEdge* coedge;
01368   PartitionCurve* pt_curve = 0;
01369   while ( (pt_curve = point->next_curve(pt_curve)) )
01370   {
01371     coedge = 0;
01372     while ( (coedge = pt_curve->next_coedge(coedge)) )
01373     {
01374       if (coedge->get_loop() &&
01375           coedge->get_loop()->get_surface() == surface &&
01376           !dynamic_cast<PartPTCurve*>(coedge->get_curve()))
01377         point_coedges.append(coedge);
01378     }
01379   }
01380   
01381     // TBPoint is at end of a sipe/hardline
01382   if ( point_coedges.size() == 0 )
01383   {
01384     previous = next = 0;
01385     return CUBIT_SUCCESS;
01386   }
01387   
01388     // One coedge - closed curve
01389   if ( point_coedges.size() == 1 &&
01390        point_coedges.get()->start_point() ==
01391        point_coedges.get()->end_point() )
01392   {
01393     previous = next = point_coedges.get();
01394     return CUBIT_SUCCESS;
01395   }
01396   
01397     // Broken loop?
01398   if ( point_coedges.size() % 2 != 0 )
01399   {
01400     PRINT_ERROR(bad_loop_message,__FILE__,__LINE__);
01401     assert(0);
01402     return CUBIT_FAILURE;
01403   }
01404   
01405     // If only two coedges, then we're done
01406     // If closed curve, the answer may be the same coedge for both 
01407     // prev and next.  E.g. A torus cracked along the outside major
01408     // radius and a sipe that intersects that crack curve.  Need
01409     // to fall though to the more complex check below in that case.
01410   if ( point_coedges.size() == 2 &&
01411        point_coedges.get()->get_curve()->start_point() != 
01412          point_coedges.get()->get_curve()->end_point() &&
01413        point_coedges.next()->get_curve()->start_point() !=
01414          point_coedges.next()->get_curve()->end_point() )
01415   {
01416     previous = point_coedges.get();
01417     next = point_coedges.next();
01418     
01419     if ( previous->start_point() == point )
01420       std::swap(previous, next);
01421     
01422     return CUBIT_SUCCESS;
01423   }
01424   
01425     // Find previous/next coedges by using order of
01426     // facet edges about point in surface facetting.
01427   CubitPointData* facet_point = point->facet_point();
01428   DLIList<CubitFacetEdgeData*> curve_edges;
01429   curve->get_facet_data(curve_edges);
01430   
01431   CubitFacetEdgeData* edge;
01432   //bool edge_reversed;
01433   if ( point == curve->start_point() )
01434   {
01435     curve_edges.reset();
01436     edge = curve_edges.get();
01437   }
01438   else
01439   {
01440     assert(curve->end_point() == point);
01441     curve_edges.last();
01442     edge = curve_edges.get();
01443   }
01444     
01445   PartitionCurve *prev_curve, *next_curve;
01446   prev_curve = next_curve_around_point( surface, edge, facet_point, true );
01447   next_curve = next_curve_around_point( surface, edge, facet_point, false );
01448   
01449   if ( !prev_curve || !next_curve )
01450   {
01451     PRINT_ERROR(bad_loop_message,__FILE__,__LINE__);
01452     assert(0);
01453     return CUBIT_FAILURE;
01454   }
01455   
01456   coedge = 0;
01457   while ( (coedge = prev_curve->next_coedge(coedge)) )
01458   {
01459     if ( coedge->get_loop() &&  // parent not a partition surface?
01460          coedge->get_loop()->get_surface() == surface &&
01461          coedge->end_point() == point )
01462     {
01463       previous = coedge;
01464       break;
01465     }
01466   }
01467   coedge = 0;
01468   while ( (coedge = next_curve->next_coedge(coedge)) )
01469   {
01470     if ( coedge->get_loop() &&
01471          coedge->get_loop()->get_surface() == surface &&
01472          coedge->start_point() == point )
01473     {
01474       next = coedge;
01475       break;
01476     }
01477   }
01478 
01479   return CUBIT_SUCCESS;
01480 }
01481     
01482 PartitionCurve* PartitionEngine::next_curve_around_point(
01483                                PartitionSurface *const surface, 
01484                                CubitFacetEdgeData *const start_edge,
01485                                CubitPointData *const point, 
01486                                const bool backwards )
01487 {
01488   //PartitionCoEdge* result = 0;
01489   CubitFacetEdge* edge = start_edge;
01490   
01491   while ( edge->num_adj_facets() == 2 )
01492   {
01493     CubitFacet* facet1 = edge->adj_facet(0);
01494     CubitFacet* facet2 = edge->adj_facet(1);
01495     assert (TDVGFacetOwner::get(facet1) == surface);
01496     assert (TDVGFacetOwner::get(facet2) == surface);
01497     
01498     bool edge_reversed = edge->point(1) == point;
01499     int facet_sense = edge_reversed == backwards ? -1 : 1;
01500     int facet1_index = facet1->edge_index(edge);
01501 #ifndef NDEBUG
01502     int facet2_index = facet2->edge_index(edge);
01503     assert(facet1->edge_use(facet1_index) == -facet2->edge_use(facet2_index));
01504 #endif
01505 
01506     if ( facet_sense == facet1->edge_use(facet1_index) )
01507       edge = facet1->next_edge_at_point( edge, point );
01508     else
01509       edge = facet2->next_edge_at_point( edge, point );
01510       
01511     assert(edge != start_edge);
01512     
01513     PartitionEntity* edge_owner = TDVGFacetOwner::get(edge);
01514     PartitionCurve* curve = dynamic_cast<PartitionCurve*>(edge_owner);
01515     if ( curve )
01516       return curve;
01517   }
01518   
01519   return 0;
01520 }
01521 
01522 
01523 
01524 //-------------------------------------------------------------------------
01525 // Purpose       : Un-partition a surface
01526 //
01527 // Special Notes : 
01528 //
01529 // Creator       : Jason Kraftcheck
01530 //
01531 // Creation Date : 02/23/03
01532 //-------------------------------------------------------------------------
01533 Surface* PartitionEngine::remove_curve( PartitionCurve* passed_curve,
01534                                         PartitionSurface* dead_surfs[2] )
01535 {
01536   if( dead_surfs )
01537     dead_surfs[0] = dead_surfs[1] = 0;
01538   
01539   PartPTCurve* point_curve = dynamic_cast<PartPTCurve*>(passed_curve);
01540   if( point_curve )
01541   {
01542     PartitionSurface* surf = 
01543       point_curve->next_coedge(0)->get_loop()->get_surface();
01544     if( !remove_point_curve( point_curve->start_point() ) )
01545       return 0;
01546     
01547     SubSurface* subsurf = dynamic_cast<SubSurface*>(surf);
01548     if( subsurf && !subsurf->next_co_surface() &&
01549         !subsurf->sub_entity_set().has_lower_order() )
01550     {
01551       Surface* result = restore_surface( subsurf );
01552       if( result && dead_surfs )
01553         dead_surfs[0] = subsurf;
01554       return result;
01555     }
01556     else
01557       return surf;
01558   }
01559   
01560   SegmentedCurve* curve = dynamic_cast<SegmentedCurve*>(passed_curve);
01561 
01562   if( !curve )
01563   {
01564     assert(0);
01565   }
01566 /*
01567     assert( dynamic_cast<SubCurve*>(passed_curve) );
01568     
01569     PartitionCoEdge* coedge1 = passed_curve->next_coedge(0);
01570     PartitionCoEdge* coedge2 = passed_curve->next_coedge(coedge1);
01571     if( !coedge2 || passed_curve->next_coedge(coedge2) )
01572       return 0;
01573       
01574     DLIList<TopologyBridge*> surfaces;
01575     coedge1->find_parent_loop()->get_parents_virt( surfaces );
01576     fix_up_query_results( surfaces );
01577     assert( surfaces.size() == 1 );
01578     Surface* surface1 = dynamic_cast<Surface*>(surfaces.get());
01579     surfaces.clean_out();
01580     coedge2->find_parent_loop()->get_parents_virt( surfaces );
01581     fix_up_query_results( surfaces );
01582     assert( surfaces.size() == 1 );
01583     Surface* surface2 = dynamic_cast<Surface*>(surfaces.get());
01584     
01585     SubSurface* surf1 = dynamic_cast<SubSurface*>(surface1);
01586     SubSurface* surf2 = dynamic_cast<SubSurface*>(surface2);
01587     if( surface1 == surface2 )
01588     {
01589       if( !surf1 )
01590         surf1 = surf2 = replace_surface( surface1 );
01591     }
01592     else
01593     {
01594       if( !surf1 )
01595         surf1 = replace_surface( surface1 );
01596       if( !surf2 )
01597         surf2 = replace_surface( surface2 );
01598     }
01599     
01600       // create SegmentedCurves from SubCurves
01601     
01602     
01603     CompositeEngine::instance()->
01604       remove_curve( dynamic_cast<Curve*>(passed_curve->partitioned_entity()) );
01605   }
01606 */  
01607   DLIList<TopologyBridge*> tb_list;
01608   
01609     // get two coedges to remove
01610   curve->get_parents_virt( tb_list );
01611   if( tb_list.size() != 2 )
01612     return 0;
01613   PartitionCoEdge* coedge1 = dynamic_cast<PartitionCoEdge*>(tb_list.get_and_step());
01614   PartitionCoEdge* coedge2 = dynamic_cast<PartitionCoEdge*>(tb_list.get_and_step());
01615   assert( coedge1 && coedge2 );
01616   
01617     // get two loops and surfaces
01618   PartitionLoop* loop1 = coedge1->get_loop();
01619   PartitionLoop* loop2 = coedge2->get_loop();
01620   PartitionSurface* surf1 = loop1->get_surface();
01621   PartitionSurface* surf2 = loop2->get_surface();
01622   assert( surf1 && surf2 );
01623   
01624     // surfaces must be partitions of the same real surface
01625   if( surf1->partitioned_entity() != surf2->partitioned_entity() )
01626     return 0;
01627   
01628     // surfaces must have same parent shells
01629   PartitionCoSurf* cos = 0;
01630   while( (cos = surf1->next_co_surface( cos )) )
01631     if( ! surf2->find_first( cos->get_shell(), cos->sense() ) )
01632       return 0;
01633     
01634     // same loop : remove a sipe or split a loop
01635   if( loop1 == loop2 )
01636   {
01637     if( loop1->next_coedge( coedge1 ) != coedge2 &&
01638         loop1->prev_coedge( coedge1 ) != coedge2 )
01639     {
01640       loop2 = new PartitionLoop();
01641       PartitionCoEdge* coedge = loop1->next_coedge( coedge1 );
01642       PartitionCoEdge* prev = 0;
01643       while( coedge != coedge2 )
01644       {
01645         loop1->remove( coedge );
01646         loop2->insert_after( coedge, prev );
01647         prev = coedge;
01648         coedge = loop1->next_coedge( coedge1 );
01649       }
01650       
01651       surf1->add( loop2 );
01652     }
01653     
01654     loop1->remove( coedge1 );
01655     loop1->remove( coedge2 );
01656     if( loop1->first_coedge() == 0 )
01657     {
01658       surf1->remove( loop1 );
01659       delete loop1;
01660     }
01661   }
01662     // stitch loops
01663   else
01664   {
01665       // insert coedges
01666     while( loop2->next_coedge(coedge2) != coedge2 ) // all but the dead one
01667     {
01668       PartitionCoEdge* coedge = loop2->next_coedge( coedge2 );
01669       loop2->remove( coedge );
01670       loop1->insert_before( coedge, coedge1 );
01671     }
01672     loop1->remove( coedge1 );
01673     loop2->remove( coedge2 );
01674     assert( loop2->first_coedge() == 0 );
01675     surf2->remove( loop2 );
01676     if( loop1->num_coedges() == 0 )
01677     {
01678       surf1->remove( loop1 );
01679       delete loop1;
01680     }
01681 
01682     delete loop2;
01683   }
01684   
01685   curve->remove( coedge1 );
01686   curve->remove( coedge2 );
01687   delete coedge1;
01688   delete coedge2;
01689   PartitionPoint* start_pt = curve->start_point();
01690   PartitionPoint* end_pt = curve->end_point();
01691   curve->start_point(0);
01692   curve->end_point(0);
01693   delete curve;
01694   if ( !start_pt->next_curve() )
01695   {
01696     if ( start_pt->real_point() )
01697       restore_point(start_pt);
01698     else
01699       delete start_pt;
01700   }
01701   if ( end_pt != start_pt && !end_pt->next_curve() )
01702   {
01703     if ( end_pt->real_point() )
01704       restore_point(end_pt);
01705     else
01706       delete end_pt;
01707   }
01708   
01709     // need to combine surfaces?
01710   if( surf1 != surf2 )
01711   {
01712     surf1->combine( surf2 );
01713     while( PartitionLoop* loop = surf2->next_loop() )
01714     { 
01715       surf2->remove( loop );
01716       surf1->add( loop );
01717     }
01718   
01719     while( PartitionCoSurf* cos = surf2->next_co_surface() )
01720     {
01721       if( cos->get_shell() )
01722         cos->get_shell()->remove( cos );
01723       surf2->remove( cos );
01724       delete cos;
01725     }
01726     
01727     if( dead_surfs )
01728       dead_surfs[0] = surf2;
01729     delete surf2;
01730   }
01731   
01732     // can remove partition surface?
01733   SubSurface* subsurf = dynamic_cast<SubSurface*>(surf1);
01734   if( subsurf && !subsurf->next_co_surface() && 
01735       !subsurf->sub_entity_set().has_lower_order() )
01736   {
01737     if( dead_surfs )
01738     {
01739       if( dead_surfs[0] )
01740         dead_surfs[1] = surf1;
01741       else
01742         dead_surfs[0] = surf1;
01743     }
01744     return restore_surface( subsurf );
01745   }
01746   else
01747     return surf1;
01748 }
01749 
01750 //-------------------------------------------------------------------------
01751 // Purpose       : Find the facet that:
01752 //                   - contains the passed edge 
01753 //                   - uses the passed edge in the specified orientation
01754 //                   - is owned by the passed entity 
01755 //
01756 // Special Notes : 
01757 //
01758 // Creator       : Jason Kraftcheck
01759 //
01760 // Creation Date : 02/23/03
01761 //-------------------------------------------------------------------------
01762 static CubitFacetData* find_facet( CubitFacetEdge* edge, 
01763                                    bool sense,
01764                                    PartitionEntity* owner )
01765 {
01766   DLIList<CubitFacet*> facets(2);
01767   edge->facets(facets);
01768   facets.reset();
01769   for ( int i = facets.size(); i--; ) {
01770     CubitFacet* facet = facets.get();
01771     int edge_index = facet->edge_index(edge);
01772     assert(edge_index >= 0);
01773     bool forward = edge->point(0) == facet->point((edge_index+1)%3);
01774     if ( forward != sense || TDVGFacetOwner::get(facet) != owner )
01775       facets.extract();
01776     else
01777       facets.step();
01778   }
01779   
01780   return facets.size() == 1 ? dynamic_cast<CubitFacetData*>(facets.get()) : 0;
01781 }
01782 
01783 //-------------------------------------------------------------------------
01784 // Purpose       : Find a facet adjacent to the passed point and owned by
01785 //                 the passed PartitionEntity
01786 //
01787 // Special Notes : 
01788 //
01789 // Creator       : Jason Kraftcheck
01790 //
01791 // Creation Date : 02/23/03
01792 //-------------------------------------------------------------------------
01793 static CubitFacetData* find_facet( CubitPoint* pt, PartitionEntity* owner )
01794 {
01795   DLIList<CubitFacet*> facets;
01796   pt->facets(facets);
01797   facets.reset();
01798   for ( int i = facets.size(); i--; )
01799   {
01800     if ( TDVGFacetOwner::get(facets.get()) == owner )
01801       facets.step();
01802     else
01803       facets.extract();
01804   }
01805   
01806   return facets.size() == 1 ? dynamic_cast<CubitFacetData*>(facets.get()) : 0;
01807 }
01808 
01809 //-------------------------------------------------------------------------
01810 // Purpose       : Find the facet adjacent to the passed facet on the
01811 //                 specified edge, and owned by the passed PartitionEntity
01812 //
01813 // Special Notes : 
01814 //
01815 // Creator       : Jason Kraftcheck
01816 //
01817 // Creation Date : 02/23/03
01818 //-------------------------------------------------------------------------
01819 static CubitFacetData* other_facet( CubitFacetData* facet,
01820                                     int edge,
01821                                     PartitionEntity* owner )
01822 {
01823   DLIList<CubitFacet*> facets;
01824   facet->shared_facets( facet->point((edge+1)%3), 
01825                         facet->point((edge+2)%3),
01826                         facets );
01827   for ( int i = facets.size(); i--; )
01828   {
01829     CubitFacet* facet = facets.get();
01830     if( TDVGFacetOwner::get(facet) != owner )
01831       facets.extract();
01832     else
01833       facets.step();
01834   }
01835   
01836   return facets.size() == 1 ? dynamic_cast<CubitFacetData*>(facets.get()) : 0;
01837 }
01838 /*
01839 static void draw_facet_edges( CubitFacet* facet, int color )
01840 {
01841   float x1, y1, z1, x2, y2, z2;
01842   for ( int i = 0; i < 3; i++ )
01843   {
01844     x1 = (float)facet->point(i)->coordinates().x();
01845     y1 = (float)facet->point(i)->coordinates().y();
01846     z1 = (float)facet->point(i)->coordinates().z();
01847     x2 = (float)facet->point((i+1)%3)->coordinates().x();
01848     y2 = (float)facet->point((i+1)%3)->coordinates().y();
01849     z2 = (float)facet->point((i+1)%3)->coordinates().z();
01850     GfxDebug::draw_line(x1,y1,z1,x2,y2,z2,color);
01851   }
01852   GfxDebug::flush();
01853 }
01854 
01855 static void draw_facet_point( CubitPoint* pt, int color )
01856 {
01857   float x = (float)pt->coordinates().x();
01858   float y = (float)pt->coordinates().y();
01859   float z = (float)pt->coordinates().z();
01860   GfxDebug::draw_point( x, y, z, color );
01861   GfxDebug::flush();
01862 }
01863 
01864 static void draw_facet_points( CubitFacet* facet, int color )
01865 {
01866   draw_facet_point(facet->point(0), color);
01867   draw_facet_point(facet->point(1), color);
01868   draw_facet_point(facet->point(2), color);
01869 }
01870 */
01871 
01872 
01873 //-------------------------------------------------------------------------
01874 // Purpose       : Split surface using facet data, given a coedge along
01875 //                 the split chain.
01876 //
01877 // Special Notes : 
01878 //
01879 // Creator       : Jason Kraftcheck
01880 //
01881 // Creation Date : 02/23/03
01882 //-------------------------------------------------------------------------
01883 PartitionSurface* PartitionEngine::split_surface( PartitionSurface* surface,
01884                                                   PartitionCoEdge* new_coedge )
01885 {
01886   int i;
01887 
01888     // get surface facets and make sure marks are cleared
01889   DLIList<CubitFacetData*> faces;
01890   surface->get_facet_data(faces);
01891   for( i = faces.size(); i--; )
01892     faces.get_and_step()->marked(0);
01893 
01894 
01895     // get curve and curve's facet edges
01896   PartitionCurve* new_curve = dynamic_cast<PartitionCurve*>(new_coedge->get_curve());
01897   DLIList<CubitFacetEdgeData*> edges;
01898   new_curve->get_facet_data( edges );
01899   assert(edges.size());
01900   
01901     // get the first point in the curve's facet edges
01902   edges.reset();
01903   CubitFacetEdgeData* edge = edges.get();
01904   CubitPoint* pt = edge->point(0);
01905   if ( TDVGFacetOwner::get(pt) != new_curve->start_point() )
01906   {
01907     pt = edge->point(1);
01908     assert(TDVGFacetOwner::get(pt) == new_curve->start_point());
01909   }
01910   
01911     // get the facets on the surface on the inside size of
01912     // the coedge
01913   bool coedge_forward = new_coedge->sense() == CUBIT_FORWARD;
01914   DLIList<CubitFacetData*> front( faces.size() );
01915   for ( i = edges.size(); i--; )
01916   {
01917     edge = edges.get_and_step();
01918     bool edge_forward = edge->point(0) == pt;
01919     bool sense = edge_forward == coedge_forward;
01920     CubitFacetData* face = find_facet( edge, sense, surface );
01921     if( face->marked() == 0 )
01922     {
01923 //draw_facet_edges(face,CUBIT_RED_INDEX);
01924       face->marked(1);
01925       front.append( face );
01926     }
01927     pt = edge->other_point(pt);
01928   }    
01929 
01930     // mark all adjacent facets traversing only over
01931     // edges that are in the interior of the surface
01932   while( front.size() )
01933   {
01934     CubitFacetData* face = front.pop();
01935     for( i = 0; i < 3; i++ )
01936     {
01937       if( face->edge(i) && TDVGFacetOwner::get(face->edge(i)) )
01938         continue;
01939         
01940       CubitFacetData* other = other_facet( face, i, surface );
01941       if ( other->marked() == 0 )
01942       {
01943 //draw_facet_edges(face,CUBIT_BLUE_INDEX);
01944         other->marked(1);
01945         front.append(other);
01946       }
01947     }
01948   }
01949   
01950     // reuse front to hold all the facets we marked
01951   for( i = faces.size(); i--; )
01952   {
01953     CubitFacetData* face = faces.get_and_step();
01954     if( face->marked() )
01955       front.append( face );
01956   }
01957   
01958     // if we got back all the facets, then the surface
01959     // was not split!
01960   if( front.size() == faces.size() )
01961   {
01962     for( i = faces.size(); i--; )
01963       faces.get_and_step()->marked(0);
01964       
01965     return surface;
01966   }
01967     // split off a new PartitionSurface
01968   PartitionSurface* new_surf = surface->split( front );
01969   
01970     // get list of all loops in surface
01971   DLIList<PartitionLoop*> loops( surface->num_loops() );
01972   PartitionLoop* loop = 0;
01973   while( (loop = surface->next_loop( loop )) )
01974     loops.append( loop );
01975   
01976     // check which loops we need to move to the new surface
01977   while( loops.size() )
01978   {
01979     loop = loops.pop();
01980     PartitionCoEdge* coe = loop->first_coedge();
01981 
01982     if( !coe )
01983       continue;
01984 
01985     PartitionCurve* curve = coe->get_curve();
01986     
01987     CubitFacetData* face =0;
01988     if( PartPTCurve* ptc = dynamic_cast<PartPTCurve*>(curve) )
01989     {
01990       face = find_facet( ptc->start_point()->facet_point(), new_surf );
01991     }
01992     else
01993     {
01994       edges.clean_out();
01995       curve->get_facet_data( edges );
01996       if (edges.size() > 0) // normal facet
01997       {
01998         edges.reset();
01999         edge = edges.get();
02000         CubitPoint* start_pt = curve->start_point()->facet_point();
02001         bool forward = edge->point(0) == start_pt;
02002         assert( forward || edge->point(1) == start_pt );
02003         if ( coe->sense() == CUBIT_REVERSED )
02004           forward = !forward;
02005         face = find_facet( edge, forward, new_surf );
02006       }
02007       else // this is a hardpoint there is a curve with no facets (length)
02008            // and the start and end points are the same
02009       {
02010         TBPoint* hardpoint = curve->start_point()->real_point();
02011         if (hardpoint && curve->start_point() == curve->end_point() )
02012         {
02013           CubitVector hardpoint_coord = hardpoint->coordinates(); 
02014           CubitVector new_closest, old_closest;
02015           new_surf->closest_point_trimmed( hardpoint_coord, new_closest );
02016           surface->closest_point_trimmed( hardpoint_coord,  old_closest );
02017           // It appears that the new_surf is really the original surface
02018           if ( new_closest.length_squared() > old_closest.length_squared() )
02019             face = reinterpret_cast<CubitFacetData*>(1); // just set the point to non-zero (true)
02020         }
02021       }
02022     }
02023     
02024     if( face )
02025     {
02026       surface->remove( loop );
02027       new_surf->add( loop );
02028     }
02029   }
02030 /*  
02031   PartitionCoSurf* cos = 0;
02032   while( (cos = surface->next_co_surface( cos )) )
02033     cos->get_shell()->add( new_surf, cos->sense() );
02034 */  
02035   for( i = faces.size(); i--; )
02036     faces.get_and_step()->marked(0);
02037   
02038   return new_surf;
02039 }
02040 
02041     
02042 //-------------------------------------------------------------------------
02043 // Purpose       : Public interface to surface partitioning.
02044 //
02045 // Special Notes : 
02046 //
02047 // Creator       : Jason Kraftcheck
02048 //
02049 // Creation Date : 02/23/03
02050 //-------------------------------------------------------------------------
02051 Surface* PartitionEngine::insert_curve( Surface* surface,
02052                          DLIList<CubitVector*>& segment_points,
02053                          DLIList<Curve*>& new_curves,
02054                          const double *tolerance_length)
02055 {
02056   DLIList<Surface*> input_surfs(1), output_surfs(2);
02057   input_surfs.append(surface);
02058   if ( ! insert_curve(input_surfs, segment_points, output_surfs, new_curves,
02059                 tolerance_length) )
02060     return 0;
02061 
02062   return output_surfs.size() ? output_surfs.get() : surface;
02063 } 
02064 
02065 //-------------------------------------------------------------------------
02066 // Purpose       : Public interface to surface partitioning
02067 //
02068 // Special Notes : 
02069 //
02070 // Creator       : Jason Kraftcheck
02071 //
02072 // Creation Date : 02/23/03
02073 //-------------------------------------------------------------------------
02074 CubitStatus PartitionEngine::insert_curve( 
02075                                     DLIList<Surface*>& input_surfaces,
02076                                     DLIList<CubitVector*>& segment_points,
02077                                     DLIList<Surface*>& new_surfaces,
02078                                     DLIList<Curve*>& new_curves,
02079                                     const double *tolerance_length,
02080                                     DLIList<Surface*>* surfs_to_reverse)
02081 {
02082   int i;
02083   CubitStatus result = CUBIT_SUCCESS;
02084   
02085   for ( i = input_surfaces.size(); i--; )
02086     if ( dynamic_cast<CompositeSurface*>(input_surfaces.get_and_step()) )
02087       return CompositeEngine::instance().insert_curve(
02088         input_surfaces, segment_points, new_surfaces, new_curves );
02089   
02090   DLIList<SubSurface*> replaced_surfaces;
02091   DLIList<PartitionSurface*> surface_list, new_part_surfs;
02092   DLIList<PartitionCurve*> curve_list;
02093   
02094     // get partition surfaces
02095   for ( i = input_surfaces.size(); i--; )
02096   {
02097     int reverse_surf = 0;
02098     Surface* surf = input_surfaces.get_and_step();
02099 
02100     // We will need to reverse the surface and its facets if it
02101     // is in the passed-in list of surfaces to reverse.
02102     if(surfs_to_reverse && surfs_to_reverse->is_in_list(surf))
02103       reverse_surf = 1;
02104     PartitionSurface* partsurf = dynamic_cast<PartitionSurface*>(surf);
02105     if( partsurf )
02106     {
02107       surface_list.append(partsurf);
02108       if(reverse_surf)
02109         partsurf->reverse_sense();
02110     }
02111     else
02112     {
02113       SubSurface* subsurf = replace_surface(surf);
02114       if (!subsurf)
02115       {
02116         result = CUBIT_FAILURE;
02117         break;
02118       }
02119       
02120       replaced_surfaces.append( subsurf );
02121       surface_list.append(subsurf);
02122       if(reverse_surf)
02123         subsurf->reverse_sense();
02124     }
02125   }
02126   
02127   if (result)
02128   {
02129     result = insert_curve( surface_list, segment_points, new_part_surfs, curve_list,
02130       tolerance_length);
02131   }
02132   if (!result)
02133   {
02134     // we replaced the original surface we need to clean up also
02135     for ( i = replaced_surfaces.size(); i--;  )
02136     {
02137       SubSurface* surf = replaced_surfaces.step_and_get();
02138       restore_surface( surf ); // this also deletes the virtual surface
02139     }
02140 
02141     return result;
02142   }
02143 
02144   CAST_LIST_TO_PARENT(curve_list,new_curves);
02145   CAST_LIST_TO_PARENT(new_part_surfs,new_surfaces);
02146   
02147     // clean up any partition surfaces we created but didn't modify
02148   for ( i = replaced_surfaces.size(); i--;  )
02149   {
02150     SubSurface* surf = replaced_surfaces.step_and_get();
02151     if ( !surf->sub_entity_set().has_lower_order() &&
02152          !surf->next_co_surface(0) )
02153     {
02154       restore_surface( surf );
02155     }
02156     else
02157     {
02158       new_surfaces.append( surf );
02159     }
02160   }
02161   
02162   return result;
02163 } 
02164 
02165 void PartitionEngine::curves_from_surfaces( const DLIList<PartitionSurface*>& surfs,
02166                                             DLIList<PartitionCurve*>& curves )
02167 {
02168   int i;
02169   
02170   for (i = curves.size(); i--; )
02171     curves.step_and_get()->mark = 1;
02172   
02173   for (i = surfs.size(); i--; )
02174   {
02175     PartitionSurface* surf = surfs.next(i);
02176     PartitionLoop* loop = 0;
02177     while ( (loop = surf->next_loop(loop)) )
02178     {
02179       PartitionCoEdge* coedge = loop->first_coedge();
02180       do {
02181         PartitionCurve* curve = coedge->get_curve();
02182         if (!curve->mark)
02183         {
02184           curve->mark = 1;
02185           curves.append(curve);
02186         }
02187       
02188         coedge = loop->next_coedge(coedge);
02189       } while (coedge != loop->first_coedge());
02190     }
02191   }
02192   
02193   for ( i = curves.size(); i--; )
02194     curves.step_and_get()->mark = 0;
02195   curves.reset();
02196 }
02197 
02198 
02199 CubitStatus PartitionEngine::insert_curve( DLIList<PartitionSurface*>& surface_list,
02200                                            DLIList<CubitVector*>& segment_points,
02201                                            DLIList<PartitionSurface*>& new_part_surfs,
02202                                            DLIList<PartitionCurve*>& curve_list,
02203                                            const double *tolerance_length)
02204 {
02205   int i;
02206   const double TOL_SQR = GEOMETRY_RESABS*GEOMETRY_RESABS;
02207   
02208     // Get curves
02209   DLIList<PartitionCurve*> curves;
02210   curves_from_surfaces( surface_list, curves );
02211   
02212     // Check for intersections with boundary curves
02213   segment_points.reset();
02214   curves.reset();
02215   for ( i = segment_points.size(); i--;  )
02216   {
02217     CubitVector& pos = *segment_points.get_and_step();
02218     bool debug = false;
02219     if (debug)
02220     {
02221       GfxDebug::draw_point(pos, CUBIT_BLUE_INDEX);
02222       GfxDebug::mouse_xforms();
02223     }
02224     for ( int j = curves.size(); j--; )
02225     {
02226       PartitionCurve* curve = curves.get_and_step();
02227       if ((curve->start_point()->coordinates() - pos).length_squared() < TOL_SQR)
02228       {
02229         pos = curve->start_point()->coordinates();
02230         break;
02231       }
02232       
02233       if ((curve->end_point()->coordinates() - pos).length_squared() < TOL_SQR)
02234       {
02235         pos = curve->end_point()->coordinates();
02236         break;
02237       }
02238 
02239       CubitVector closest;
02240       curve->closest_point_trimmed( pos, closest );
02241         
02242       if ( (pos - closest).length_squared() > TOL_SQR )
02243         continue;
02244       
02245       if ((curve->start_point()->coordinates() - closest).length_squared() < TOL_SQR)
02246       {
02247         pos = curve->start_point()->coordinates();
02248         break;
02249       }
02250       
02251       if ((curve->end_point()->coordinates() - closest).length_squared() < TOL_SQR)
02252       {
02253         pos = curve->end_point()->coordinates();
02254         break;
02255       }
02256 /*      
02257       double u = curve->u_from_position(closest);
02258       TBPoint* point = insert_point( curve, u );
02259       if (!point)
02260       {
02261         PRINT_ERROR("Error splitting curve.  Aborting.\n");
02262         return CUBIT_FAILURE;
02263       }
02264       pos = point->coordinates();
02265 */
02266       pos = closest;
02267       break;
02268     }
02269   }
02270       
02271   
02272     // get surface facets
02273   DLIList<CubitFacetData*> surf_facets, facet_list;
02274   surface_list.reset();
02275   for ( i = surface_list.size(); i--; )
02276   {
02277     surf_facets.clean_out();
02278     surface_list.get_and_step()->get_facet_data( surf_facets );
02279     facet_list += surf_facets;
02280   }
02281 
02282     // Do facet projection
02283   DLIList<CubitFacetEdgeData*> polyline;
02284   DLIList<CubitPointData*> polyline_pts;
02285   project_to_surface( facet_list, segment_points, polyline, polyline_pts, tolerance_length);
02286 
02287   if(segment_points.size() == polyline_pts.size())
02288   { 
02289     // Move facet points to real geometry
02290     DLIList<CubitFacetEdge*> edge_list;
02291     DLIList<CubitFacet*> pt_facets;
02292     segment_points.reset();
02293     polyline_pts.reset();
02294     int count = 0;
02295     for ( i = segment_points.size(); i--; )
02296     {
02297       CubitPointData* facet_pt = polyline_pts.get_and_step();
02298       CubitVector position( *segment_points.get_and_step() );
02299       if ( !facet_pt )  
02300         continue;
02301     
02302       PartitionPoint* point = dynamic_cast<PartitionPoint*>(TDVGFacetOwner::get(facet_pt));
02303       if ( point ) 
02304       {
02305         count++;
02306         continue;
02307       }
02308 
02309       PartitionCurve* curve = 0;
02310       edge_list.clean_out();
02311       facet_pt->edges( edge_list );      
02312       while ( edge_list.size() )
02313       {
02314 
02315         PartitionEntity* owner = TDVGFacetOwner::get(edge_list.pop());
02316         if ( owner )
02317         {
02318           assert(!curve || curve == owner);
02319           curve = dynamic_cast<PartitionCurve*>(owner);
02320         }
02321       }
02322       if ( curve )
02323       {
02324         Surface* surface = dynamic_cast<Surface*>(curve->partitioned_entity());
02325         if ( surface )
02326         {
02327           CubitVector surf_pos;
02328           surface->closest_point( position, &surf_pos );
02329           if (facet_pt->check_inverted_facets(surf_pos))
02330             facet_pt->set( surf_pos );
02331         }
02332         else
02333           curve->relax_to_geometry( facet_pt, &position );
02334 
02335         continue;
02336       }
02337     
02338       PartitionSurface* surf = 0;
02339       pt_facets.clean_out();
02340       facet_pt->facets( pt_facets );
02341       while ( pt_facets.size() )
02342       {
02343         PartitionEntity* owner = TDVGFacetOwner::get(pt_facets.pop());
02344         if ( owner )
02345         {
02346           assert(!surf || surf == owner);
02347           surf = dynamic_cast<PartitionSurface*>(owner);
02348         }
02349       }
02350       if ( surf && dynamic_cast<SubSurface*>(surf) )
02351       {
02352         surf->relax_to_geometry( facet_pt, &position );
02353       }
02354     }        
02355   }  
02356 
02357   if ( !polyline.size() )
02358     return CUBIT_FAILURE;
02359   
02360   //In the following lines we see if we need to split curves on 
02361   //the boundary of the surface.  This is necessary when the endpoints of 
02362   //the polylines used for partitioning are not coincident with 
02363   //boundary curves.
02364 
02365   //get all the facet points of the polyline
02366   DLIList<CubitPoint*> points_on_polyline;  
02367   for( int k=polyline.size(); k--; )
02368   {
02369     CubitFacetEdgeData *tmp_edge = polyline.get_and_step();
02370     if( !tmp_edge )
02371       continue;
02372     points_on_polyline.append_unique( tmp_edge->start_node() );
02373     points_on_polyline.append_unique( tmp_edge->end_node() );
02374   }
02375   
02376   //get all the resulting facets
02377   DLIList<CubitFacet*> facets_after;
02378   for ( i = surface_list.size(); i--; )
02379   {
02380     surf_facets.clean_out();
02381     surface_list.get_and_step()->get_facet_data( surf_facets );
02382     for( int s=surf_facets.size(); s--; )
02383       facets_after.append( surf_facets.get_and_step() );    
02384   }
02385 
02386   //from the facets, collect all the boundary points
02387   DLIList<CubitPoint*> boundary_pts;
02388   FacetDataUtil::get_boundary_points( facets_after, boundary_pts );
02389 
02390   //for each polyline points...
02391   for( int k=points_on_polyline.size(); k--; )
02392   {
02393     CubitPoint *tmp_pt = points_on_polyline.get_and_step();
02394 
02395     //if the point is on the boundary...
02396     if( boundary_pts.is_in_list( tmp_pt ) )
02397     {
02398       PartitionPoint* point = dynamic_cast<PartitionPoint*>(TDVGFacetOwner::get(tmp_pt));
02399       if( !point ) //if the point is not already a vertex on the boundary...
02400       {
02401         //find the adjacent boundary curve that we'll insert these points into
02402         DLIList<CubitFacetEdge*> adj_edges;
02403         tmp_pt->edges( adj_edges );
02404 
02405         for( int s=adj_edges.size(); s--; )
02406         {
02407           CubitFacetEdge *tmp_edge = adj_edges.get_and_step();
02408           PartitionCurve* curve = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(tmp_edge));
02409           if( curve )
02410           {
02411             DLIList<TopologyBridge*> bridges;
02412             get_tbs_with_bridge_manager_as_owner(curve, bridges );
02413 
02414             if( bridges.size() == 0 )
02415               CompositeEngine::instance().get_tbs_with_bridge_manager_as_owner( curve, bridges );
02416 
02417             RefEdge *ref_edge = dynamic_cast<RefEdge*>(bridges.get()->topology_entity());         
02418             RefEdge *edge1, *edge2;
02419 
02420             //now do the split
02421             PartitionTool::instance()->partition( ref_edge, tmp_pt->coordinates(), edge1, edge2  );
02422             break;
02423           }
02424         }
02425       }
02426     }
02427   }    
02428   
02429     // construct the curves
02430   DLIList<CubitFacetEdgeData*> cubit_edges;
02431   DLIList<CubitFacetEdge*> pt_edges;
02432   polyline.reset();
02433   for ( i = polyline.size(); i > 0; )
02434   {
02435       // get list of FacetPoints for Curve
02436     cubit_edges.clean_out();
02437     CubitFacetEdgeData* edge = polyline.get_and_step();
02438     if (!edge) { i--; continue; } 
02439     
02440     assert(!TDVGFacetOwner::get(edge) && 
02441            edge->num_adj_facets() < 3 &&
02442            edge->num_adj_facets() > 0);
02443            
02444     PartitionEntity* owner = TDVGFacetOwner::get(edge->adj_facet(0));
02445     assert( edge->num_adj_facets() == 1 ||
02446             TDVGFacetOwner::get(edge->adj_facet(1)) == owner );
02447             
02448     cubit_edges.append( edge );
02449     
02450     while( polyline.get() )
02451     {
02452       CubitPoint* pt = edge->shared_point(polyline.get());
02453       edge = polyline.get();
02454       
02455       assert(!TDVGFacetOwner::get(edge) && 
02456              edge->num_adj_facets() < 3 &&
02457              edge->num_adj_facets() > 0 && pt);
02458            
02459       PartitionEntity* tmp = TDVGFacetOwner::get(edge->adj_facet(0));
02460       assert( edge->num_adj_facets() == 1 ||
02461             TDVGFacetOwner::get(edge->adj_facet(1)) == tmp );
02462             
02463       bool edge_owner = false;
02464       pt->edges(pt_edges);
02465       while (pt_edges.size())
02466         if (TDVGFacetOwner::get(pt_edges.pop()))
02467           edge_owner = true;
02468             
02469       if ( tmp != owner || TDVGFacetOwner::get(pt) || edge_owner )
02470         break;
02471         
02472       cubit_edges.append( polyline.get_and_step() );
02473     }
02474     if (NULL == polyline.get())
02475     {
02476       polyline.step();
02477       i -= 1;
02478     }
02479     i -= cubit_edges.size();
02480 
02481       // create curve and partition surface
02482     PartitionCurve* new_curve = insert_curve( cubit_edges, &segment_points );
02483     if ( new_curve )
02484       curve_list.append(new_curve);
02485   }  
02486   
02487     // find new surfaces to return
02488   for ( i = curve_list.size(); i--; )
02489   {
02490     PartitionCurve* curve = curve_list.step_and_get();
02491     PartitionCoEdge* coedge = 0;
02492     while( (coedge = curve->next_coedge(coedge)) )
02493     {
02494       new_part_surfs.append( coedge->get_loop()->get_surface() );
02495     }
02496   }
02497   
02498   if ( curve_list.size() )
02499   {
02500       // do facet cleanup
02501     for ( i = curve_list.size(); i--; )
02502       curve_list.get_and_step()->do_facet_cleanup();
02503     //for ( i = new_part_surfs.size(); i--; )
02504     //  new_part_surfs.get_and_step()->do_facet_cleanup();
02505   }
02506     
02507   
02508   for ( i = new_part_surfs.size(); i--; )
02509     new_part_surfs.step_and_get()->mark = 1;
02510   for ( i = surface_list.size(); i--; )
02511     surface_list.step_and_get()->mark = 0;
02512   for ( i = new_part_surfs.size(); i--; )
02513     if ( new_part_surfs.step_and_get()->mark )
02514       new_part_surfs.get()->mark = 0;
02515     else 
02516       new_part_surfs.change_to(0);
02517   new_part_surfs.remove_all_with_value(0);
02518 
02519   return curve_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
02520 } 
02521 
02522 //-------------------------------------------------------------------------
02523 // Purpose       : Given a polyline-imprint on the surface facetting,
02524 //                 construct a new and insert it in the surface topology.
02525 //
02526 // Special Notes : 
02527 //
02528 // Creator       : Jason Kraftcheck
02529 //
02530 // Creation Date : 02/23/03
02531 //-------------------------------------------------------------------------
02532 SegmentedCurve* PartitionEngine::insert_curve( 
02533                          DLIList<CubitFacetEdgeData*>& segments,
02534                          DLIList<CubitVector*>* /*curve_geom*/ )
02535 {
02536   int i;
02537   
02538     // find surface
02539   PartitionSurface* surface = 0;
02540   DLIList<CubitFacet*> facets;
02541   for ( i = segments.size(); i--; )
02542   {
02543     CubitFacetEdgeData* edge = segments.get_and_step();
02544     facets.clean_out();
02545     edge->facets(facets);
02546     assert(facets.size() == 2);
02547     for (int j = 0; j < facets.size(); j++ )
02548     {
02549       CubitFacet* facet = facets.get_and_step();
02550       PartitionEntity* fowner = TDVGFacetOwner::get(facet);
02551       PartitionSurface* surf = dynamic_cast<PartitionSurface*>(fowner);
02552       if ( !surf || (surface && surf != surface) )
02553       {
02554         PRINT_ERROR("Internal Error in PartitionEngine.  Corrupt facet data.\n");
02555         assert(0);
02556         return 0;
02557       }
02558       surface = surf;
02559     }
02560   }
02561   
02562     // if there is a real surface, relax facet points to surface
02563   Surface* real_surf = dynamic_cast<Surface*>(surface->partitioned_entity());
02564   
02565     // find start and end facet points
02566   CubitPointData* pts[2];
02567   CubitPoint* pt;
02568   
02569   if( segments.size() == 1 )
02570   {
02571     pts[0] = dynamic_cast<CubitPointData*>(segments.get()->point(0));
02572     pts[1] = dynamic_cast<CubitPointData*>(segments.get()->point(1));
02573   }
02574   else
02575   {
02576     segments.last();
02577     pt = segments.get()->shared_point( segments.prev() );
02578     pt = segments.get()->other_point( pt );
02579     pts[1] = dynamic_cast<CubitPointData*>(pt);
02580     segments.reset();
02581     pt = segments.get()->shared_point( segments.next() );
02582     pt = segments.get()->other_point( pt );
02583     pts[0] = dynamic_cast<CubitPointData*>(pt);
02584   }
02585   
02586     // create end points (partition curves if necessary)
02587   bool okay = true;
02588   DLIList<CubitFacetEdge*> edges;
02589   bool created_pts[2] = {false,false};
02590   PartitionPoint* end_pts[2] = {0,0};
02591   for ( i = 0; okay && i < 2; i++ )
02592   {
02593     end_pts[i] = dynamic_cast<PartitionPoint*>(TDVGFacetOwner::get(pts[i]));
02594     if( end_pts[i] ) continue;
02595     
02596     edges.clean_out();
02597     pts[i]->edges(edges);
02598     PartitionCurve* curve = 0;
02599     for ( int j = edges.size(); !curve && j--; )
02600       curve = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(edges.get_and_step()));
02601     
02602     if( curve )
02603     {
02604       curve->relax_to_geometry( pts[i] );
02605       PartitionPoint* new_pt = new PartitionPoint( pts[i]->coordinates(), curve );
02606       if ( insert_point( curve, new_pt ) )
02607       {
02608         end_pts[i] = new_pt;
02609         created_pts[i] = true;
02610         assert( TDVGFacetOwner::get(pts[i]) == new_pt );
02611       }
02612       else
02613       {
02614         delete new_pt;
02615         okay = false;
02616       }
02617       continue;
02618     }
02619     
02620     facets.clean_out();
02621     pts[i]->facets(facets);
02622     for ( int k = facets.size(); k--; )
02623       if( TDVGFacetOwner::get(facets.get_and_step()) != surface )
02624       {
02625         PRINT_ERROR("Internal Error in PartitionEngine.  Corrupt facet data.\n");
02626         okay = false;
02627         break;
02628       }
02629       
02630     if( okay )
02631     {
02632       if( real_surf )
02633         surface->relax_to_geometry( pts[i] );
02634       
02635       end_pts[i] = new PartitionPoint( pts[i]->coordinates(), surface );
02636       end_pts[i]->facet_point( pts[i] );
02637     }
02638   }
02639   
02640     // create curve
02641   SegmentedCurve* curve = 0;
02642   if( okay )
02643   {
02644     DLIList<CubitVector*> vectors(segments.size()+1), *curve_geom_ptr;
02645 //    if( curve_geom )
02646 //    {
02647 //      curve_geom_ptr = curve_geom;
02648 //    }
02649 //    else
02650     {
02651       segments.reset();
02652       pt = pts[0];
02653       vectors.append( new CubitVector( pt->coordinates() ) );
02654       for( i = segments.size(); i--; )
02655       {
02656         pt = segments.get_and_step()->other_point(pt);
02657         if ( real_surf && i > 0 )
02658         {
02659           surface->relax_to_geometry( pt );
02660         }
02661         assert(!!pt);
02662         vectors.append( new CubitVector( pt->coordinates() ) );
02663       }
02664       curve_geom_ptr = &vectors;
02665     }
02666     
02667     curve = new SegmentedCurve( surface, *curve_geom_ptr );
02668     
02669     while( vectors.size() ) delete vectors.pop();
02670     
02671     curve->start_point( end_pts[0] );
02672     curve->end_point( end_pts[1] );
02673     curve->set_facet_data(segments);
02674   
02675     if( insert_curve( surface, curve ) )
02676       return curve;
02677   }
02678   
02679   // If we got this far, then something went wrong.
02680   // Try to clean up.
02681     
02682   if( curve )
02683   {
02684     curve->start_point(0);
02685     curve->end_point(0);
02686     segments.clean_out();
02687     curve->set_facet_data(segments);
02688     delete curve;
02689   }
02690   
02691   for( i = 0; i < 2; i++ )
02692   {
02693     if( ! created_pts[i] ) continue;
02694     
02695     end_pts[i]->facet_point(0);
02696     if( dynamic_cast<Curve*>(end_pts[i]->partitioned_entity()) )
02697       remove_point( end_pts[i] );
02698     else
02699       delete end_pts[i];
02700   }
02701   
02702   return 0;
02703 }
02704 
02705 /*
02706 //-------------------------------------------------------------------------
02707 // Purpose       : Partition a curve using a facet point on the curve.
02708 //
02709 // Special Notes : 
02710 //
02711 // Creator       : Jason Kraftcheck
02712 //
02713 // Creation Date : 02/23/03
02714 //-------------------------------------------------------------------------
02715 PartitionPoint* PartitionEngine::insert_point( CubitPointData* pt )
02716 {
02717   DLIList<CubitFacetEdge*> edges;
02718   pt->edges(edges);
02719   
02720   PartitionCurve* curve = 0;
02721   for ( int i = edges.size(); i--; )
02722   {
02723     CubitFacetEdge* edge = edges.step_and_get();
02724     PartitionCurve* c = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(edge));
02725     if( c )
02726     {
02727       if( !curve )
02728         curve = c;
02729       else if( curve != c )
02730       {
02731         PRINT_ERROR("Internal Error in PartitionEngine.  Corrupt facet data.\n");
02732         return 0;
02733       }
02734     }
02735   }
02736       
02737   DLIList<CubitFacetEdgeData*> segments, other_segments;
02738   curve->get_facet_data(segments);
02739   segments.last();
02740   while( !segments.get()->contains( pt ) )
02741   {
02742     other_segments.append( segments.pop() );
02743     segments.last();
02744   }
02745   other_segments.reverse();
02746   
02747   PartitionPoint* new_point = new PartitionPoint( pt->coordinates(), curve );
02748   PartitionCurve* curve2 = insert_point( curve, new_point );
02749   if( !curve2 )
02750   {
02751     delete new_point;
02752     return 0;
02753   }
02754   
02755   curve->set_facet_data(segments);
02756   curve2->set_facet_data(other_segments);
02757   new_point->facet_point(pt);
02758   return new_point;
02759 }
02760 */
02761 
02762 //-------------------------------------------------------------------------
02763 // Purpose       : Add point to surface facetting.
02764 //
02765 // Special Notes : 
02766 //
02767 // Creator       : Jason Kraftcheck
02768 //
02769 // Creation Date : 02/23/03
02770 //-------------------------------------------------------------------------
02771 CubitPointData* PartitionEngine::project_to_surface( 
02772                                  PartitionSurface* surface,
02773                                  const CubitVector& position )
02774 {
02775   
02776   CubitVector pos;
02777   CubitFacet* facet = surface->closest_facet( position, pos );
02778   surface->closest_point( position, &pos );
02779   CubitFacetData* facet_d = dynamic_cast<CubitFacetData*>(facet);
02780   DLIList<CubitFacetEdge*> pt_edges;
02781   assert(!!facet_d);
02782 
02783   CubitVector p[3], v[3], d[3];
02784   int i;
02785   
02786     // Initialize data
02787   double dist_tol_sqr = CUBIT_DBL_MAX;
02788   for ( i = 0; i < 3; i++ ) {
02789     p[i] = facet_d->point(i)->coordinates();
02790     v[i] = facet_d->point((i+1)%3)->coordinates() - p[i];
02791     double dist_sqr = v[i].length_squared();
02792     if ( dist_sqr < dist_tol_sqr )
02793       dist_tol_sqr = dist_sqr;
02794     d[i] = pos - p[i];
02795   }
02796   dist_tol_sqr *= 0.2;
02797   if( dist_tol_sqr < GEOMETRY_RESABS*GEOMETRY_RESABS )
02798     dist_tol_sqr = GEOMETRY_RESABS*GEOMETRY_RESABS;
02799   
02800     // Check if we are within GEOMETRY_RESABS of a vertex of the
02801     // triangle or if one of the triangle vertices can be moved
02802     // to the input location.
02803   int closest_pt = -1;
02804   double closest_dist = dist_tol_sqr;
02805   for ( i = 0; i < 3; i++ ) {
02806     double dist_sqr = d[i].length_squared();
02807     bool has_owner = (0 != TDVGFacetOwner::get(facet->point(i)));
02808     if( !has_owner && dist_sqr < closest_dist ) {
02809       pt_edges.clean_out();
02810       facet->point(i)->edges( pt_edges);
02811       while( pt_edges.size() )
02812         if ( TDVGFacetOwner::get(pt_edges.pop()) )
02813           has_owner = true;
02814     }
02815     
02816     if ( (!has_owner && dist_sqr < closest_dist) ||
02817          dist_sqr < GEOMETRY_RESABS*GEOMETRY_RESABS ) {
02818       closest_pt = i;
02819       closest_dist = dist_sqr;
02820     }
02821   }
02822   
02823   if( closest_pt >= 0 )
02824   {
02825     facet->point(closest_pt)->set(pos);
02826     return dynamic_cast<CubitPointData*>(facet->point(closest_pt));
02827   }
02828   
02829     // Check if the input position is within GEOMETRY_RESABS of one
02830     // of the triangle edges or if the edge can be 'bent' such that
02831     // the split point is the input position.
02832   int closest_edge = -1;
02833   for ( i = 0; i < 3; i++ ) {
02834     double t = (v[i] % d[i]) / v[i].length_squared();
02835     double dist_sqr = (d[i] - t * v[i]).length_squared();
02836     CubitFacetEdge* edge = facet->point(i)->shared_edge(facet->point((i+1)%3));
02837 
02838     bool has_owner = edge && TDVGFacetOwner::get(edge);
02839     
02840     if( (!has_owner && dist_sqr < closest_dist) ||
02841          dist_sqr < GEOMETRY_RESABS*GEOMETRY_RESABS )
02842     {
02843       CubitFacet* other_facet = 0;
02844       for ( int j = 0; j < edge->num_adj_facets(); j++ )
02845       {
02846         if (edge->adj_facet(j) != facet && 
02847             TDVGFacetOwner::get(edge->adj_facet(j)) == surface)
02848         {
02849           other_facet = edge->adj_facet(j);
02850           break;
02851         }
02852       }
02853       
02854       if (other_facet)
02855       {
02856           // check if splitting the edge will invert some other facet
02857         int edge_index = other_facet->edge_index( edge );
02858         CubitVector other_pt = other_facet->point(edge_index)->coordinates();
02859         CubitVector prev_pt = other_facet->point((edge_index+1)%3)->coordinates();
02860         CubitVector next_pt = other_facet->point((edge_index+2)%3)->coordinates();
02861         prev_pt -= other_pt;
02862         next_pt -= other_pt;
02863         CubitVector norm = prev_pt * next_pt;
02864         CubitVector new_e = pos - other_pt;
02865         
02866         if ( norm.vector_angle_quick(prev_pt, new_e) > CUBIT_PI ||
02867              norm.vector_angle_quick(new_e, next_pt) > CUBIT_PI )
02868           continue;
02869         
02870           // don't create adjacent sliver facets
02871         double prev_t = prev_pt % new_e / prev_pt.length_squared();
02872         prev_pt *= prev_t;
02873         prev_pt += other_pt;
02874         if ( (prev_pt - pos).length_squared() < dist_sqr )
02875           continue;
02876         
02877         double next_t = next_pt % new_e / next_pt.length_squared();
02878         next_pt *= next_t;
02879         next_pt += other_pt;
02880         if ( (next_pt - pos).length_squared() < dist_sqr )
02881           continue;
02882       }
02883         
02884       
02885       closest_dist = dist_sqr;
02886       closest_edge = i;
02887     }
02888   }
02889 
02890   if( closest_edge >= 0 )
02891   {      
02892     CubitPoint* pt1 = facet->point(closest_edge);
02893     CubitPoint* pt2 = facet->point((closest_edge+1)%3);
02894     CubitFacetEdge* edge = pt1->shared_edge(pt2);
02895     CubitFacetEdge* new_edge;
02896     CubitFacet* new_facet;
02897     CubitPoint* new_point;
02898     PartSurfFacetTool::split_edge(edge, pos, 0, new_point, new_edge, new_facet );
02899     if (dynamic_cast<SubSurface*>(surface))
02900       surface->relax_to_geometry( new_point, &position );
02901     return dynamic_cast<CubitPointData*>(new_point);
02902   }
02903   
02904   CubitFacet *new_tri1 = 0, *new_tri2 = 0;
02905   CubitPoint* pt1 = facet->point(0);
02906   CubitPoint* pt2 = facet->point(1);
02907   CubitPoint* pt3 = facet->point(2);
02908   CubitPoint* new_pt = facet->insert_point( pos, new_tri1, new_tri2 );
02909   new CubitFacetEdgeData( new_pt, pt1 );
02910   new CubitFacetEdgeData( new_pt, pt2 );
02911   new CubitFacetEdgeData( new_pt, pt3 );
02912   surface->notify_split( facet, new_tri1 );
02913   surface->notify_split( facet, new_tri2 );
02914 
02915   if (dynamic_cast<SubSurface*>(surface))
02916     surface->relax_to_geometry( new_pt, &position );
02917 
02918   return dynamic_cast<CubitPointData*>(new_pt);
02919 }
02920 
02921 void PartitionEngine::delete_facet( CubitFacet* p_dead )
02922 {
02923 assert(!TDVGFacetOwner::get(p_dead));
02924 assert(dynamic_cast<CubitFacetData*>(p_dead) != NULL);
02925 
02926   CubitFacetEdge* edges[3] = {p_dead->edge(0), p_dead->edge(1), p_dead->edge(2)};
02927   CubitPoint* pts[3] = {p_dead->point(0), p_dead->point(1), p_dead->point(2)};
02928 
02929   int k;
02930   for( k = 0; k < 3; k++ )
02931   {
02932     if( pts[k] )
02933     {  
02934       pts[k]->remove_facet( p_dead );
02935       CubitFacetData *facet_data = static_cast<CubitFacetData*>(p_dead);
02936       facet_data->set_point( NULL, k);
02937       
02938       if( !pts[k]->num_adj_facets() )
02939         delete pts[k];
02940     }
02941   }
02942 
02943   for( k = 0; k < 3; k++ )
02944   {
02945     if( edges[k] )
02946     {
02947       edges[k]->remove_facet(p_dead);
02948       p_dead->edge(NULL, k);
02949       if(!edges[k]->num_adj_facets())
02950         delete edges[k];
02951     }
02952   }
02953   
02954   delete p_dead;
02955 }        
02956 
02957 //-------------------------------------------------------------------------
02958 // Purpose       : Create projection of a polyline in surface facetting.
02959 //
02960 // Special Notes : 
02961 //
02962 // Creator       : Jason Kraftcheck
02963 //
02964 // Creation Date : 02/23/03
02965 //-------------------------------------------------------------------------
02966 CubitStatus PartitionEngine::project_to_surface( 
02967                                  DLIList<CubitFacetData*>& cubit_facets,
02968                                  DLIList<CubitVector*>& polyline,
02969                                  DLIList<CubitFacetEdgeData*>& polyline_out,
02970                                  DLIList<CubitPointData*>& polyline_points,
02971                                  const double *tolerance_length)
02972 {
02973   int i, j;
02974   unsigned u;
02975   PartitionSurface* p_adj_surf;
02976   PartitionCurve* p_curve = 0;
02977   PartitionEntity* p_owner;
02978 
02979   DLIList<PartitionSurface*> surfaces;
02980   for (i = cubit_facets.size(); i--; )
02981     surfaces.append_unique( dynamic_cast<PartitionSurface*>(TDVGFacetOwner::get(cubit_facets.step_and_get())));
02982 
02983     // get points
02984 
02985   DLIList<CubitPoint*> cubit_points(cubit_facets.size() * 3);
02986   DLIList<CubitFacet*> orig_facets;
02987   CAST_LIST_TO_PARENT(cubit_facets, orig_facets);
02988   FacetDataUtil::get_facet_points(orig_facets, cubit_points);
02989 
02990   // get bounding curves from the facets
02991   std::set<PartitionCurve*> boundary_curves;
02992   DLIList<CubitFacetEdge*> free_edges;
02993   FacetDataUtil::edges_by_count(orig_facets, 1, free_edges);
02994   free_edges.reset();
02995   for (i=free_edges.size(); i>0; i--)
02996   {
02997     p_owner = TDVGFacetOwner::get(free_edges.get_and_step());
02998     p_curve = CAST_TO(p_owner, PartitionCurve);
02999     assert(!!p_curve); // every bounding edge should be owned by a curve
03000     boundary_curves.insert(p_curve);
03001   }
03002   
03003   std::vector<double> facet_points(cubit_points.size() * 3);
03004   std::vector<int> simple_facets(cubit_facets.size() * 3);
03005   cubit_points.reset();
03006   for ( i = 0; i < cubit_points.size(); i++ )
03007   {
03008     CubitPoint* pt = cubit_points.get_and_step();
03009     pt->marked( i );
03010     
03011     int j = i * 3;
03012     facet_points[j  ] = pt->coordinates().x();
03013     facet_points[j+1] = pt->coordinates().y();
03014     facet_points[j+2] = pt->coordinates().z();
03015     if (DEBUG_FLAG(145))
03016     {
03017       GfxDebug::draw_point(pt->coordinates(), CUBIT_WHITE_INDEX);
03018       GfxDebug::draw_label(i, (float)(pt->coordinates().x()),
03019                               (float)(pt->coordinates().y()),
03020                               (float)(pt->coordinates().z()),
03021                               CUBIT_WHITE_INDEX);
03022     }
03023   }
03024   
03025   cubit_facets.reset();
03026   for ( i = 0; i < cubit_facets.size(); i++ )
03027   {
03028     CubitFacetData* facet = cubit_facets.get_and_step();
03029     int j = i * 3;
03030     simple_facets[j  ] = facet->point(0)->marked();
03031     simple_facets[j+1] = facet->point(1)->marked();
03032     simple_facets[j+2] = facet->point(2)->marked();
03033     if (DEBUG_FLAG(145))
03034     {
03035       GfxDebug::draw_facet( facet, CUBIT_CYAN_INDEX );
03036       CubitVector c = facet->center();
03037       GfxDebug::draw_label( i, (float)(c.x()),
03038                                (float)(c.y()),
03039                                (float)(c.z()),
03040                                CUBIT_CYAN_INDEX);
03041       PRINT_DEBUG_145("%2d : %2d %2d %2d\n", i,
03042                                              facet->point(0)->marked(),
03043                                              facet->point(1)->marked(),
03044                                              facet->point(2)->marked());
03045     }
03046   }
03047 
03048     // clear point marks
03049   for ( i = 0; i < cubit_points.size(); i++ )
03050     cubit_points.step_and_get()->marked(0);  
03051 /*
03052     // reduce polyline resolution
03053   const double dist_tol = GEOMETRY_RESABS*GEOMETRY_RESABS;
03054   const double COS15 = 0.96592582628906831;
03055   const double angle_tol = COS15*COS15;
03056   DLIList<CubitVector*> polyline2;
03057   polyline.reset();
03058   CubitVector *prev = polyline.get_and_step();
03059   polyline2.append(prev);
03060   for( i = polyline.size() - 2; i--; )
03061   {
03062     CubitVector *pt = polyline.get_and_step();
03063     CubitVector *next = polyline.get();
03064     CubitVector v1(*pt - *prev);
03065     CubitVector v2(*next - *pt);
03066     double len1 = v1.length_squared();
03067     double len2 = v2.length_squared();
03068     double dot = v1 % v2;
03069     if( len1 > dist_tol && len2 > dist_tol &&
03070         ((dot*dot)/(len1*len2)) < angle_tol )
03071     {
03072       polyline2.append(pt);
03073       prev = pt;
03074     }
03075   }
03076   polyline2.append(polyline.get());
03077 */
03078     // Call tool to do projection
03079 
03080   std::vector<double> new_facet_points;
03081   std::vector<int> dead_simple_facets, new_simple_facets, 
03082                    facet_replacement, new_polyline, seg_pts;
03083   FacetProjectTool tool;
03084   if ( !tool.project( polyline, facet_points, simple_facets,
03085                       dead_simple_facets, new_simple_facets,
03086                       facet_replacement, new_facet_points, 
03087                       new_polyline, seg_pts, tolerance_length ) )
03088   {
03089     // output the map between input polyline positions and
03090     // facet points
03091     std::vector<int>::iterator iitor;
03092     for ( iitor = seg_pts.begin(); iitor != seg_pts.end(); ++iitor )
03093     {
03094       int pt_index = *iitor;
03095       if ( pt_index == -1 )
03096       {
03097         polyline_points.append(NULL);
03098       }
03099       else
03100       {
03101         CubitPointData* ptd = NULL;
03102         if(pt_index >= 0 && pt_index < cubit_points.size())
03103         {
03104           CubitPoint* pt = cubit_points.next( pt_index );
03105           ptd = dynamic_cast<CubitPointData*>(pt);
03106         }
03107         polyline_points.append(ptd);
03108       }
03109     }
03110 
03111     return CUBIT_FAILURE;
03112   }
03113 
03114     // Convert back to CubitFacet rep
03115    
03116     // make new points
03117   assert( new_facet_points.size() % 3 == 0 );
03118   std::vector<CubitPointData*> new_cubit_points(new_facet_points.size()/3);
03119   std::vector<CubitPointData*>::iterator cpitor = new_cubit_points.begin();
03120   std::vector<double>::iterator ditor = new_facet_points.begin();
03121   for ( ; cpitor != new_cubit_points.end(); ++cpitor )
03122   {
03123     double x = *ditor++;
03124     double y = *ditor++;
03125     double z = *ditor++;
03126     *cpitor = new CubitPointData(x,y,z);
03127     cubit_points.append(*cpitor);
03128   }
03129 
03130     // make new facets
03131   cubit_facets.reset();
03132   cubit_points.reset();
03133   int prev_index = 0;
03134   assert( new_simple_facets.size() % 3 == 0 );
03135 
03136   std::vector<CubitFacetData*> facet_list;
03137   std::vector<CubitFacetData*>::iterator fitor;
03138   std::vector<int>::iterator iitor = new_simple_facets.begin();
03139 
03140   int id=0; // dummy for CubitFacetData constructor
03141 
03142   for( u = 0; u < dead_simple_facets.size(); u++ )
03143   {
03144       // get number of replacement facets
03145     int index = facet_replacement[u];
03146     int count = (index - prev_index) / 3;
03147     assert(((index - prev_index) % 3) == 0);
03148 
03149       // make a new list to hold data
03150     facet_list.clear();
03151     facet_list.resize(count+1);
03152     fitor = facet_list.begin();
03153 
03154       // put dead facet at beginning of list
03155     CubitFacetData* p_dead = cubit_facets.next(dead_simple_facets[u]);
03156     *fitor++ = p_dead;
03157 
03158     // get the surface that owns the dead facet
03159     p_owner = TDVGFacetOwner::get(p_dead);
03160     PartitionSurface* p_dead_surf = CAST_TO(p_owner, PartitionSurface);
03161     assert(!!p_dead_surf);
03162 
03163       // construct and append replacement facets
03164     for ( j=0; j < count; j++ )
03165     {
03166       CubitPoint* pt1 = cubit_points.next( *iitor++ );
03167       CubitPoint* pt2 = cubit_points.next( *iitor++ );
03168       CubitPoint* pt3 = cubit_points.next( *iitor++ );
03169       *fitor++ = new CubitFacetData(pt1, pt2, pt3, &id);
03170     }
03171 
03172       // set up for next iteration
03173     assert(fitor == facet_list.end());
03174     prev_index = index;
03175 
03176       // do something with "facet_list"
03177 
03178     DLIList<CubitFacetData*> old_facet_list;
03179 
03180     // fill edge replacement lists
03181     std::vector<CubitFacetEdgeData*> edge_lists[3];
03182     get_edge_replacements(facet_list, edge_lists);
03183 
03184     // update edges/facets on curves and adjacent surfaces
03185     CubitFacetEdgeData* old_edge;
03186     for (j=0; j<3; j++)
03187     {
03188       DLIList<CubitFacetEdgeData*> new_edges;
03189       if (edge_lists[j].size()) // check for replacements
03190       {
03191         std::vector<CubitFacetEdgeData*>::iterator eitor = edge_lists[j].begin();
03192         old_edge = *eitor++;
03193 
03194         p_owner = TDVGFacetOwner::get(old_edge);
03195         p_curve = CAST_TO(p_owner, PartitionCurve);
03196 
03197         for (; eitor != edge_lists[j].end(); eitor++)
03198           new_edges.append(*eitor);
03199 
03200         assert(new_edges.size() > 1); // shouldn't ever get 1 to 1 replacement here
03201 
03202         // split facets on adjacent surfaces if the split crosses a curve
03203         // on the outside boundary of the facets
03204         if (boundary_curves.find(p_curve) != boundary_curves.end())
03205         {
03206           // get facets to be replaced on adjacent surf
03207           DLIList<CubitFacetData*> adj_facets;
03208           DLIList<CubitFacet*> tmp_list;
03209           old_edge->facets(tmp_list);
03210           CAST_LIST(tmp_list, adj_facets, CubitFacetData);
03211 
03212           if (adj_facets.size() > 1)
03213           {
03214             DLIList<CubitFacetData*> adj_replacements;
03215             int i_adj;
03216             for (i_adj=adj_facets.size(); i_adj>0; i_adj--)
03217             {
03218               CubitFacetData* p_adjacent = adj_facets.get_and_step();
03219               if (p_adjacent == p_dead)
03220                 continue;
03221 
03222               // create replacement facets
03223               adj_replacements.clean_out();
03224 
03225               // get the point opposite the edge being replaced
03226               int e_index = p_adjacent->edge_index(old_edge);
03227               bool old_reversed = -1 == p_adjacent->edge_use(e_index);
03228               CubitPoint* prev_pt = NULL;
03229               //if old_reversed is false, the new_edge' reversed flag is true
03230               int old_prev_pt_index;
03231               if (old_reversed)
03232               {
03233                  prev_pt = old_edge->point(0);
03234                  old_prev_pt_index = 0;
03235               }
03236               else
03237               {
03238                  prev_pt = old_edge->point(1);
03239                  old_prev_pt_index = 1;
03240               }
03241               CubitPoint* opposite_pt = p_adjacent->point(e_index);
03242               //CubitPoint* opposite_pt = p_adjacent->point(p_adjacent->edge_index(old_edge)); // opposite edge and point have same index
03243               new_edges.reset();
03244               int i_new;
03245               for (i_new=new_edges.size(); i_new>0; i_new--)
03246               {
03247                 CubitFacetEdge* p_edge = new_edges.get_and_step();
03248                 
03249                 prev_pt = p_edge->other_point(prev_pt);
03250                 assert(!!prev_pt);
03251                 bool new_reversed = p_edge->point(old_prev_pt_index) == prev_pt;
03252                 int reversed = (int)(new_reversed != old_reversed);
03253                 
03254                 CubitFacetData* p_facet = new CubitFacetData(p_edge->point(reversed),
03255                                                              p_edge->point(1-reversed),
03256                                                              opposite_pt, &id);
03257                 adj_replacements.append(p_facet);
03258               }
03259 
03260               p_owner = TDVGFacetOwner::get(p_adjacent);
03261               p_adj_surf = CAST_TO(p_owner, PartitionSurface);
03262               assert(!!p_adj_surf);
03263               old_facet_list.clean_out();
03264               old_facet_list.append(p_adjacent);
03265               p_adj_surf->replace_facets(old_facet_list, adj_replacements);
03266               delete_facet( p_adjacent );
03267             }
03268           }
03269         }
03270 
03271         // replace the curve edges
03272         p_curve->replace_facet(old_edge, new_edges);
03273         
03274         // Don't delete edge yet.  It's still connected to
03275         // at least one facet.  Wait 'till the facet is deleted.
03276         //delete old_edge;
03277       }
03278     }
03279 
03280     // replace dead facet
03281     fitor = facet_list.begin();
03282     fitor++; // skip dead facet
03283     DLIList<CubitFacetData*> new_facets;
03284     for (; fitor != facet_list.end(); fitor++)
03285       new_facets.append(*fitor);
03286     old_facet_list.clean_out();
03287     old_facet_list.append(p_dead);
03288     p_dead_surf->replace_facets(old_facet_list, new_facets);
03289     delete_facet(p_dead);
03290   }
03291 
03292   assert(iitor == new_simple_facets.end());
03293 
03294   // output the edges that make up the projected curve
03295   cubit_points.reset();
03296   iitor = new_polyline.begin();
03297   while( *iitor )
03298   {
03299     int count = *iitor++;
03300     CubitPoint* prev_point = cubit_points.next( *iitor++ );
03301     for ( i = 1; i < count; i++ ) {
03302       CubitPoint* pt = cubit_points.next( *iitor++ );
03303       CubitFacetEdge* edge = prev_point->shared_edge(pt);
03304       CubitFacetEdgeData* edge_d = dynamic_cast<CubitFacetEdgeData*>(edge);
03305       assert(!!edge_d);
03306       if (TDVGFacetOwner::get(edge_d)) 
03307         polyline_out.append(0);
03308       else
03309       {
03310         if (edge_d->point(0) == pt)
03311           edge_d->flip();
03312         polyline_out.append(edge_d);
03313       }
03314       prev_point = pt;
03315     }
03316     polyline_out.append(0);
03317   }
03318   
03319   // output the map between input polyline positions and 
03320   // facet points
03321   for ( iitor = seg_pts.begin(); iitor != seg_pts.end(); ++iitor )
03322   {
03323     int pt_index = *iitor;
03324     if ( pt_index == -1 )
03325     {
03326       polyline_points.append(NULL);
03327     }
03328     else
03329     {
03330       assert(pt_index >= 0 && pt_index < cubit_points.size());
03331       CubitPoint* pt = cubit_points.next( pt_index );
03332       CubitPointData* ptd = dynamic_cast<CubitPointData*>(pt);
03333       assert(!!ptd);
03334       polyline_points.append(ptd);
03335     }
03336   }  
03337   
03338 
03339   return CUBIT_SUCCESS;
03340 }
03341   
03342 //-------------------------------------------------------------------------
03343 // Purpose       : Create a point-curve
03344 //
03345 // Special Notes : 
03346 //
03347 // Creator       : Jason Kraftcheck
03348 //
03349 // Creation Date : 02/23/03
03350 //-------------------------------------------------------------------------
03351 TBPoint* PartitionEngine::insert_point_curve( Surface* surf,
03352                                             const CubitVector& position,
03353                                             Surface *&partitioned_surf )
03354 {
03355   if ( CompositeSurface* csurf = dynamic_cast<CompositeSurface*>(surf) )
03356   { 
03357     TBPoint* result = 
03358       CompositeEngine::instance().insert_point_curve(csurf, position); 
03359     partitioned_surf = csurf;
03360     return result;
03361   }
03362   
03363   bool replaced_surface = false;
03364   PartitionSurface* psurf = dynamic_cast<PartitionSurface*>(surf);
03365   if ( ! psurf ) {
03366     psurf = replace_surface(surf);
03367     replaced_surface = true;
03368     if ( ! psurf ) return 0;
03369   }
03370   
03371   CubitPointData* facet_point = project_to_surface( psurf, position );
03372   if ( !facet_point ) {
03373     if( replaced_surface )
03374       restore_surface( dynamic_cast<SubSurface*>(psurf) );
03375     partitioned_surf = NULL;
03376     return 0;
03377   }
03378   
03379   PartitionPoint* result = insert_point_curve( psurf, facet_point );
03380   if ( !result ) {
03381     if( replaced_surface )
03382       restore_surface( dynamic_cast<SubSurface*>(psurf) );
03383     return 0;
03384   }
03385   
03386   PartitionCurve* curve = result->next_curve(0);
03387   if (replaced_surface && !dynamic_cast<PartPTCurve*>(curve))
03388   {
03389     TBPoint* real = result->real_point();
03390     partitioned_surf = restore_surface( dynamic_cast<SubSurface*>(psurf) );
03391     if (real)
03392     {
03393       result = dynamic_cast<PartitionPoint*>(real->owner());
03394       return result ? result : real;
03395     }
03396   }
03397   else 
03398     partitioned_surf = psurf; 
03399 
03400   return result;
03401 }
03402 
03403 
03404 
03405 //-------------------------------------------------------------------------
03406 // Purpose       : Create point-curve
03407 //
03408 // Special Notes : 
03409 //
03410 // Creator       : Jason Kraftcheck
03411 //
03412 // Creation Date : 02/23/03
03413 //-------------------------------------------------------------------------
03414 PartitionPoint* PartitionEngine::insert_point_curve( PartitionSurface* surf,
03415                                                      CubitPointData* point )
03416 {
03417     // If imprint at existing vertex, just return that vertex
03418   if ( TDVGFacetOwner::get(point) )
03419     return dynamic_cast<PartitionPoint*>(TDVGFacetOwner::get(point));
03420   
03421     // Check if imprint point is on a curve of the surface
03422   DLIList<CubitFacetEdge*> edges;
03423   point->edges(edges);
03424   PartitionEntity* owner = 0;
03425   int owner_count = 0;
03426   int owner_edges = 0;
03427   while (edges.size())
03428   {
03429     if (PartitionEntity* ent = TDVGFacetOwner::get(edges.pop()))
03430     {
03431       if (owner != ent)
03432         owner_count++;
03433       owner = ent;
03434       owner_edges++;
03435     }
03436   }
03437   
03438     // If imprint is on curve, split the curve
03439   if (owner)
03440   {
03441     PartitionCurve* curve = dynamic_cast<PartitionCurve*>(owner);
03442 
03443       // check valid facet configuration.  should be only one
03444       // owner, and owner should own exactly two of the adjacent
03445       // edges.  And owner should be a partition curve.
03446     if (!curve || owner_count != 1 || owner_edges != 2)
03447     {
03448       PRINT_ERROR("Internal error at %s:%d\n  Invalid state.\n", __FILE__, __LINE__ );
03449       assert(0);
03450       return NULL;
03451     }
03452     
03453     PartitionPoint* new_point = new PartitionPoint(point->coordinates(), curve);
03454     new_point->facet_point(point);
03455     curve = insert_point( curve, new_point );
03456     if (!curve)
03457     {
03458       delete new_point;
03459       return 0;
03460     }
03461     
03462     return new_point;
03463   }
03464       
03465     // If here, point is in surface interior.  Create point-curve.
03466   PartitionPoint* new_point = new PartitionPoint( point->coordinates(), surf );
03467   new_point->facet_point(point);
03468   PartPTCurve* new_curve = new PartPTCurve( surf );
03469   new_curve->start_point( new_point );
03470   new_curve->end_point( new_point );
03471   
03472   insert_point_curve( surf, new_curve );
03473   
03474   return new_point;
03475 }
03476 
03477 CubitStatus PartitionEngine::insert_point_curve( PartitionSurface* surf,
03478                                                  PartPTCurve* new_curve,
03479                                                  bool update_topology )
03480 {
03481   PartitionCoEdge* new_coedge = new PartitionCoEdge( surf, CUBIT_FORWARD );
03482   new_curve->add( new_coedge );
03483   PartitionLoop* new_loop = new PartitionLoop();
03484   new_loop->insert_after( new_coedge, 0 );
03485   
03486   surf->add( new_loop );
03487   if ( surf->owner() && update_topology )
03488     surf->owner()->notify_topology_modified(surf);
03489   return CUBIT_SUCCESS;
03490 }
03491   
03492 
03493 
03494 //-------------------------------------------------------------------------
03495 // Purpose       : Construct surface for volume partitioning
03496 //
03497 // Special Notes : 
03498 //
03499 // Creator       : Jason Kraftcheck
03500 //
03501 // Creation Date : 01/13/03
03502 //-------------------------------------------------------------------------
03503 Lump* PartitionEngine::insert_surface( Surface* surface, Lump* lump)
03504 {
03505   GMem gmem;
03506   int i;
03507   CubitStatus status = surface->get_geometry_query_engine()->
03508     get_graphics( surface, &gmem );
03509   
03510   if( !status )
03511   {
03512     PRINT_ERROR("PartitionEngine::insert_surface: GeometryEngine::"
03513                 "get_graphics failed for surface.\n");
03514     return 0;
03515   }
03516 
03517   int num_pts = gmem.pointListCount;
03518   
03519   CubitPointData** ptarray = new CubitPointData*[num_pts];
03520   GPoint *p_itor = gmem.point_list();
03521   GPoint *p_end = p_itor + num_pts;
03522   CubitPointData** array_itor = ptarray;
03523   for( ; p_itor < p_end; p_itor++, array_itor++ )
03524     *array_itor = new CubitPointData(CubitVector(p_itor->x,p_itor->y,p_itor->z));
03525   
03526   DLIList<CubitFacetData*> facets;
03527   int* f_itor = gmem.facet_list();
03528   int* f_end = f_itor + gmem.fListCount;
03529   i = 0;
03530   for( ; f_itor < f_end ; f_itor += (1 + *f_itor) )
03531   {
03532     if( *f_itor != 3 )
03533       PRINT_ERROR("Non-triangular facet in PartitionEngine::insert_surface\n");
03534     else
03535       facets.append( new CubitFacetData(ptarray[f_itor[1]],
03536                                         ptarray[f_itor[2]],
03537                                         ptarray[f_itor[3]], &i) );
03538   }
03539     
03540     // clean up any unused points
03541   for( i = 0; i < num_pts; i++ )
03542     if( ptarray[i]->num_adj_facets() == 0 )
03543       delete ptarray[i];
03544   delete [] ptarray;
03545   
03546   
03547     // create partition lump
03548   bool created_lump = false;
03549   PartitionLump* partlump = dynamic_cast<PartitionLump*>(lump);
03550   if( !partlump )
03551   {
03552     created_lump = true;
03553     partlump = replace_lump(lump);
03554     assert(partlump != NULL);
03555   }
03556   
03557     // Get vertex locations
03558   DLIList<CubitVector> coords;
03559   DLIList<TopologyBridge*> loops, coedges, curves, points, all_points;
03560   surface->get_children_virt(loops);
03561   while( loops.size() )
03562   {
03563     loops.pop()->get_children( coedges, true, layer() - 1 );
03564     while ( coedges.size() )
03565     {
03566       coedges.pop()->get_children_virt(curves);
03567       assert(curves.size() == 1);
03568       TopologyBridge* curve = curves.pop();
03569       curve->get_children( points, true, layer() - 1 );
03570       assert ( points.size() < 3 );
03571       all_points.merge_unique( points );
03572       points.clean_out();
03573     }
03574   }
03575   while( all_points.size() )
03576     coords.append(CubitVector( dynamic_cast<TBPoint*>(all_points.pop())->coordinates() ) );
03577   
03578   PartitionLumpImprint tool( partlump );
03579   DLIList<PartitionEntity*> new_entities;
03580   PartitionSurface* new_surf = tool.imprint( facets, coords, new_entities );
03581   if ( !new_surf )
03582   {
03583     if( created_lump ) restore_lump(partlump);
03584     return 0;
03585   }
03586   
03587   PartitionLump* result = insert_surface( partlump, new_surf );
03588   if( !result )
03589   {
03590     destroy_surface( new_surf );
03591     if( created_lump ) restore_lump( partlump );
03592     return 0;
03593   }
03594 
03595   return result;
03596 }
03597 
03598 Surface* PartitionEngine::insert_surface( DLIList<CubitFacet*>& facets, Lump* lump)
03599 {
03600   
03601     // create partition lump and surface
03602   bool created_lump = false;
03603   PartitionLump* partlump = dynamic_cast<PartitionLump*>(lump);
03604   if( !partlump )
03605   {
03606     created_lump = true;
03607     partlump = replace_lump(lump);
03608     if (!partlump)
03609       return 0;
03610   }
03611   
03612   PartitionLumpImprint tool( partlump );
03613   DLIList<PartitionEntity*> new_list;
03614   PartitionSurface* new_surf = tool.imprint( facets, new_list );
03615   if ( !new_surf )
03616   {
03617     if( created_lump ) restore_lump(partlump);
03618     return 0;
03619   }
03620   
03621   PartitionLump* result = insert_surface( partlump, new_surf );
03622   if( !result )
03623   {
03624     destroy_surface( new_surf );
03625     if( created_lump ) restore_lump( partlump );
03626     return 0;
03627   }
03628   
03629   return new_surf;
03630 }
03631 
03632 
03633   
03634 //-------------------------------------------------------------------------
03635 // Purpose       : Insert a surface into a volume
03636 //
03637 // Special Notes : 
03638 //
03639 // Creator       : Jason Kraftcheck
03640 //
03641 // Creation Date : 01/12/03
03642 //-------------------------------------------------------------------------
03643 PartitionLump* PartitionEngine::insert_surface( PartitionLump* lump, 
03644                                            PartitionSurface* surface )
03645 {
03646   assert( &(lump->sub_entity_set()) == &(surface->sub_entity_set()) );
03647   
03648     // Find all affected shells.  If any curve is not part of an
03649     // existing shell in the volume, set all_curves_connected to
03650     // false.  If any curve does not intersect the volume, then
03651     // the volume does not need to be split into two (or the surface
03652     // forms a new void in the volume.)
03653   bool all_curves_connected = true;
03654   DLIList<PartitionShell*> modified_list;
03655   PartitionLoop* loop = 0;
03656   PartitionCoEdge *coedge, *curve_coedge;
03657   PartitionCurve* curve;
03658   PartitionShell* shell;
03659   PartitionCoSurf* cosurf;
03660   while( (loop = surface->next_loop(loop)) )
03661   {
03662     coedge = loop->first_coedge();
03663     do {
03664       curve = coedge->get_curve();
03665       curve_coedge = 0;
03666       shell = 0;
03667       while( (curve_coedge = curve->next_coedge(curve_coedge)) )
03668       {
03669         PartitionSurface* surf = curve_coedge->get_loop()->get_surface();
03670         cosurf = 0;
03671         while( (cosurf = surf->next_co_surface( cosurf )) )
03672         {
03673           if( cosurf->get_shell()->get_lump() == lump )
03674           {
03675             assert( !shell || cosurf->get_shell() == shell );
03676             shell = cosurf->get_shell();
03677           }
03678         }
03679       }
03680       
03681       if( shell )
03682         modified_list.append_unique(shell);
03683       else
03684         all_curves_connected = false;
03685       
03686       coedge = loop->next_coedge(coedge);
03687     } while( coedge != loop->first_coedge() );
03688   }
03689 
03690     // Construct CoSurfaces
03691   PartitionCoSurf* cosurf1 = new PartitionCoSurf(CUBIT_FORWARD);
03692   PartitionCoSurf* cosurf2 = new PartitionCoSurf(CUBIT_REVERSED);
03693   surface->add(cosurf1);
03694   surface->add(cosurf2);
03695   
03696     // If there were no affected shells, we need to make a new
03697     // shell for a possible void in the volume.
03698   PartitionShell* shell_to_split = 0;
03699   if( modified_list.size() == 0 )
03700   {
03701     shell_to_split = new PartitionShell();
03702     lump->add(shell_to_split);
03703     
03704       // If surface is closed, set all_curves_connected
03705       // to true to indicate that volume needs to be split.
03706       // (Creating a one-surface void in the volume.)
03707     loop = 0;
03708     all_curves_connected = true;
03709     while( (loop = surface->next_loop(loop)) )
03710     {
03711       coedge = loop->first_coedge();
03712       do
03713       {
03714         curve = coedge->get_curve();
03715         curve_coedge = 0;
03716         int coedge_count = 0;
03717         while( (curve_coedge = curve->next_coedge(curve_coedge)) )
03718         {
03719           if( curve_coedge->get_loop() == loop )
03720             coedge_count++;
03721           else 
03722             assert(curve_coedge->get_loop()->get_surface() != surface);
03723         }
03724     
03725         if( coedge_count == 1 )
03726           all_curves_connected = false;
03727         else
03728           assert(coedge_count == 2);
03729       
03730         coedge = loop->next_coedge(coedge);
03731       } while( coedge != loop->first_coedge() );
03732     }
03733   }
03734   
03735     // Otherwise combine all the affected shells
03736   else
03737   {
03738     modified_list.reverse();
03739     shell_to_split = modified_list.pop();
03740     while( modified_list.size() )
03741     {
03742       shell = modified_list.pop();
03743       while( PartitionCoSurf* cosurf = shell->next_co_surface() )
03744       {
03745         shell->remove(cosurf);
03746         shell_to_split->add(cosurf);
03747       }
03748       lump->remove(shell);
03749       delete shell;
03750     }
03751   }
03752   
03753   shell_to_split->add(cosurf1);
03754   shell_to_split->add(cosurf2);
03755   
03756     // If we don't need to split the volume, we are done
03757   if( !all_curves_connected )
03758     return lump;
03759     // We probably need to split the the lump...
03760   else    
03761     return split_lump( shell_to_split );
03762 }
03763 
03764 //-------------------------------------------------------------------------
03765 // Purpose       : Test if a PartitionShell needs to be split, and
03766 //                 if so partition the shell and owning lump
03767 //
03768 // Special Notes : 
03769 //
03770 // Creator       : Jason Kraftcheck
03771 //
03772 // Creation Date : 01/13/03
03773 //-------------------------------------------------------------------------
03774 PartitionLump* PartitionEngine::split_lump( PartitionShell* shell_to_split )
03775 {
03776     // Split shell
03777   PartitionShell* new_shell = split_shell(shell_to_split);
03778   if( !new_shell )
03779   {
03780       // shell did not need to be split
03781     return shell_to_split->get_lump();
03782   }
03783    
03784     // Create the new lump and shell
03785   PartitionLump* new_lump = new PartitionLump( shell_to_split->get_lump() );
03786   new_lump->add( new_shell );
03787   
03788     // Check for any remaining shells that need to be moved
03789     // from the old lump to the new lump.
03790   PartitionShell* shell = 0;
03791   PartitionLump* lump = shell_to_split->get_lump();
03792   while( (shell = lump->next_shell(shell)) )
03793   {
03794     if( shell == shell_to_split )
03795       continue;
03796     
03797     bool some_contained = false;
03798     bool all_contained = true;
03799     bool all_tested = true;
03800     PartitionCoSurf* cosurf = 0;
03801     while( (cosurf = shell->next_co_surface(cosurf)) )
03802     {
03803       PartitionSurface* surf = cosurf->get_surface();
03804       CubitVector pt, tmp = surf->bounding_box().center();
03805       surf->closest_point_trimmed( tmp, pt );
03806       switch( new_shell->point_containment(pt) )
03807       {
03808         case CUBIT_PNT_INSIDE:
03809           some_contained = true;
03810           break;
03811         case CUBIT_PNT_OUTSIDE:
03812           all_contained = false;
03813          break;
03814         default:
03815           all_tested = false;
03816           break;
03817       }
03818     }
03819     
03820     
03821     if( !all_tested || (some_contained && !all_contained) )
03822     {
03823       PRINT_ERROR("Error splitting volume.  Could not determine\n"
03824                   "which volume shell belongs in.  Geometry may be\n"
03825                   "invalid.\n");
03826     }
03827     
03828     if(some_contained && all_contained)
03829     {
03830       lump->remove(shell);
03831       new_lump->add(shell);
03832     }
03833   }
03834   
03835   return new_lump;
03836 }
03837 
03838 /*
03839 #include "GfxDebug.hpp"
03840 static void draw_curve( PartitionCurve* curve, int color, bool flush = true )
03841 {
03842   GMem graphics;
03843   int i;
03844   curve->get_geometry_query_engine()->get_graphics( curve, i, &graphics );
03845   GfxDebug::draw_polyline(graphics.point_list(),
03846                                           graphics.pointListCount,
03847                                           color);
03848   if(flush) GfxDebug::flush();
03849 }
03850 
03851 static void draw_surface( PartitionSurface* surface, int color, bool flush = true )
03852 {
03853 //  RefEntity* re = dynamic_cast<RefEntity*>(surface->owner());
03854 //  if( re )
03855 //    GfxDebug::draw_ref_entity( re, color, true, false );
03856 //  else 
03857   for( PartitionLoop* loop = 0; loop = surface->next_loop(loop); )
03858   {
03859     PartitionCoEdge* coe = loop->first_coedge();
03860     do {
03861       draw_curve(coe->get_curve(), color, false);
03862       coe = loop->next_coedge(coe);
03863     } while(coe != loop->first_coedge());
03864   }
03865   if(flush) GfxDebug::flush();
03866 }
03867 
03868 static void draw_cosurface( PartitionCoSurf* cosurf, int color, bool flush = true )
03869 {
03870   //draw_surface(cosurf->get_surface(), color, false);
03871   CubitVector p, n;
03872   n = cosurf->get_surface()->bounding_box().center();
03873   cosurf->get_surface()->closest_point_trimmed( n, p );
03874   cosurf->get_surface()->closest_point( p, 0, &n );
03875   double l = cosurf->get_surface()->bounding_box().diagonal().length() * 0.1;
03876   n.length(l);
03877   if(cosurf->sense() == CUBIT_REVERSED)
03878     n *= -1.0;
03879     GfxDebug::draw_vector(p, p+n, color);
03880   if(flush) GfxDebug::flush();
03881 }
03882 */
03883 
03884 //-------------------------------------------------------------------------
03885 // Purpose       : Test if a PartitionShell needs to be split, and
03886 //                 split it
03887 //
03888 // Special Notes : 
03889 //
03890 // Creator       : Jason Kraftcheck
03891 //
03892 // Creation Date : 01/13/03
03893 //-------------------------------------------------------------------------
03894 PartitionShell* PartitionEngine::split_shell( PartitionShell* shell_to_split )
03895 {
03896     // Make sure all cosurface surface marks are cleared
03897   PartitionCoSurf* cosurf = 0;
03898   while( (cosurf = shell_to_split->next_co_surface( cosurf )) )
03899   {
03900     cosurf->mark = 0;
03901     cosurf->get_surface()->mark = 0;
03902   }
03903   
03904     // Identify non-manifold surfaces, marking them either
03905     // with a 2 if they can be used to split the volume
03906     // (if they are part of a connected patch for which the
03907     // bounadary of that patch intersects the volume boundary
03908     // at all curves) or a 3 if they are other non-manifold
03909     // surfaces.  This will get a bit tricky if there are
03910     // non-manifold surfaces hanging off of the patch of
03911     // split surfaces.
03912   
03913     // First for all non-manifold surfaces, if the surface has
03914     // a curve that is not shared with any other surface, mark
03915     // it with a 3.  Otherwise mark it with a 2.
03916   cosurf = 0;
03917   DLIList<PartitionSurface*> surf_stack;
03918   while ( (cosurf = shell_to_split->next_co_surface(cosurf)) )
03919   {
03920     PartitionSurface* surf = cosurf->get_surface();
03921       // If we haven't done this surface yet and it is non-manifold
03922     if ( !surf->mark && surf->find_next(cosurf) )
03923     {
03924       surf->mark = 2;
03925       bool no_free_curve = true;
03926       PartitionLoop* loop = 0;
03927       while( no_free_curve && (loop = surf->next_loop(loop)) ) 
03928       {
03929         PartitionCoEdge* coedge = loop->first_coedge();
03930         do 
03931         {
03932           PartitionCurve* curve = coedge->get_curve();
03933             // If the curve has more than one coedge, it 
03934             // is not a free curve (this also accounts for
03935             // the case where the curve is a non-manifold 
03936             // curve on the surface interioir -- e.g. a sipe)
03937           if ( !curve->next_coedge(coedge) && 
03938                curve->next_coedge(0) == coedge )
03939           {
03940             no_free_curve = false;
03941             break;
03942           }
03943           coedge = loop->next_coedge(coedge);
03944         } while( coedge != loop->first_coedge() );
03945       }
03946       
03947       if( !no_free_curve )
03948       {
03949         surf->mark = 3;
03950         surf_stack.append( surf );
03951       }
03952     }
03953   }
03954   
03955     // Now for each surface we marked with a three, traverse
03956     // and mark adjacent surfaces until we come to a curve
03957     // connected to more that two surfaces.
03958   while( surf_stack.size() ) 
03959   {
03960     PartitionSurface* surf = surf_stack.pop();
03961     PartitionLoop* loop = 0;
03962     while ( (loop = surf->next_loop(loop)) )
03963     {
03964       PartitionCoEdge* coedge = loop->first_coedge();
03965       do 
03966       {
03967         PartitionCurve* curve = coedge->get_curve();
03968         int split_count = 0;
03969         int boundary_count = 0;
03970         PartitionCoEdge* curve_coe = 0;
03971         while ( (curve_coe = curve->next_coedge(curve_coe) ) != NULL )
03972         {
03973           PartitionSurface* curve_surf = curve_coe->get_loop()->get_surface();
03974           switch ( curve_surf->mark ) 
03975           {
03976             case 0: boundary_count++; break;
03977             case 2: split_count++;    break;
03978           }
03979         }
03980         
03981         if ( split_count == 1 && !boundary_count )
03982         {
03983           curve_coe = 0;
03984           while ( (curve_coe = curve->next_coedge(curve_coe) ) != NULL )
03985           {
03986             PartitionSurface* curve_surf = curve_coe->get_loop()->get_surface();
03987             if ( curve_surf->mark == 2 )
03988             {
03989               curve_surf->mark = 3;
03990               surf_stack.append(curve_surf);
03991             }
03992           }
03993         }
03994         
03995         coedge = loop->next_coedge( coedge );
03996       } while( coedge != loop->first_coedge() );
03997     }
03998   }
03999   
04000     // Now build a new shell by traversing cofaces, marking
04001     // each with that will go in a new shell with a 1.
04002   
04003     // Start with any cosurf that does not have a free
04004     // non-manifold surface (marked with a 3).  We'll handle
04005     // free non-manifold surfaces later.
04006   DLIList<PartitionCoSurf*> cosurf_stack;
04007   cosurf = 0;
04008   while ( (cosurf = shell_to_split->next_co_surface(cosurf)) )
04009     if ( cosurf->get_surface()->mark != 3 )
04010       break;
04011   if ( cosurf )
04012   {
04013     cosurf->mark = 1;
04014     cosurf_stack.append( cosurf );
04015   }
04016   
04017     // Traverse over adjacent cosurfaces, marking them with a 1
04018   while (cosurf_stack.size())
04019   {
04020     cosurf = cosurf_stack.pop();
04021     PartitionSurface* surf = cosurf->get_surface();
04022     PartitionLoop* loop = 0;
04023     while ( (loop = surf->next_loop(loop)) )
04024     {
04025       PartitionCoEdge* coedge = loop->first_coedge();
04026       do
04027       {
04028         PartitionCurve* curve = coedge->get_curve();
04029         PartitionCoEdge* curve_coe = 0;
04030         PartitionCoSurf *boundary_cosurf = 0, *split_cosurf = 0;
04031         int split_cosurf_count = 0;
04032         while ( (curve_coe = curve->next_coedge(curve_coe)) )
04033         {
04034           if ( curve_coe == coedge )
04035             continue;
04036           
04037           bool same_coe_sense = curve_coe->sense() == coedge->sense();
04038           PartitionSurface* curve_surf = curve_coe->get_loop()->get_surface();
04039           PartitionCoSurf* curve_cosurf = 0;
04040           while ( (curve_cosurf = curve_surf->next_co_surface(curve_cosurf)) )
04041           {
04042             if ( curve_cosurf->get_shell() != shell_to_split )
04043               continue;
04044             
04045             bool same_cos_sense = curve_cosurf->sense() == cosurf->sense();
04046             if ( same_cos_sense == same_coe_sense )
04047               continue;
04048             
04049               // Always choose split surface first if we
04050               // found one
04051             if ( curve_cosurf->get_surface()->mark == 2 ) {
04052               split_cosurf_count++;
04053               split_cosurf = curve_cosurf;
04054             }
04055             
04056               // Skip other non-manifold surfaces.  We'll
04057               // handle those later.
04058             else if( curve_cosurf->get_surface()->mark != 3 )
04059               boundary_cosurf = curve_cosurf;
04060           }
04061         }
04062         
04063         PartitionCoSurf* next_cosurf = split_cosurf ? split_cosurf : boundary_cosurf;
04064         if ( !next_cosurf->mark && split_cosurf_count < 2 )
04065         {
04066           next_cosurf->mark = 1;
04067           cosurf_stack.append(next_cosurf);
04068         }
04069       
04070         coedge = loop->next_coedge(coedge);
04071       } while( coedge != loop->first_coedge() );
04072     } // end while (loop)
04073   } // end while (cosurf_stack.size())
04074     
04075   
04076     // build lists of cosurfaces, one for each shell and
04077     // one of other non-manifold surfaces
04078   DLIList<PartitionCoSurf*> marked_list, unmarked_list, other_list;
04079   while( (cosurf = shell_to_split->next_co_surface(0)) )
04080   {
04081     shell_to_split->remove(cosurf);
04082     if ( cosurf->get_surface()->mark == 3 )
04083       other_list.append( cosurf );
04084     else if( cosurf->mark )
04085       marked_list.append( cosurf );
04086     else
04087       unmarked_list.append( cosurf );
04088   }
04089   
04090     // If one of marked_list or unmarked_list is empty,
04091     // we can't split the shell yet.  Put cofaces back in
04092     // shell and exit.
04093   if ( !marked_list.size() || !unmarked_list.size() )
04094   {
04095     marked_list += unmarked_list;
04096     marked_list += other_list;
04097     marked_list.reverse();
04098     while ( marked_list.size() )
04099     {
04100       cosurf = marked_list.pop();
04101       cosurf->mark = 0;
04102       cosurf->get_surface()->mark = 0;
04103       shell_to_split->add( cosurf );
04104     }
04105     return 0;
04106   }
04107   
04108     // Put unmarked list back in old shell
04109   unmarked_list.reverse();
04110   while ( unmarked_list.size() )
04111   {
04112     cosurf = unmarked_list.pop();
04113     cosurf->get_surface()->mark = 0;
04114     shell_to_split->add(cosurf);
04115   }
04116   
04117     // Put marked list in new shell
04118   PartitionShell* new_shell = new PartitionShell;
04119   marked_list.reverse();
04120   while ( marked_list.size() )
04121   {
04122     cosurf = marked_list.pop();
04123     cosurf->mark = 0;
04124     cosurf->get_surface()->mark = 0;
04125     new_shell->add(cosurf);
04126   }
04127   
04128     // Now sort out other non-manifold surfaces
04129   
04130     // Clear marks and get list of surface from cosurfaces
04131   surf_stack.clean_out();
04132   while( other_list.size() )
04133   {
04134     cosurf = other_list.pop();
04135     PartitionSurface* surf = cosurf->get_surface();
04136     if ( surf->mark )
04137     {
04138       surf->mark = 0;
04139       surf_stack.append(surf);
04140     }
04141   }
04142   
04143   insert_nonmanifold_surfaces( surf_stack, shell_to_split, new_shell );
04144   return new_shell;
04145 }
04146   
04147   
04148 //-------------------------------------------------------------------------
04149 // Purpose       : After a shell is split, determine which of the two
04150 //                 resulting shells each non-manifold surface belongs in.
04151 //
04152 // Special Notes : 
04153 //
04154 // Creator       : Jason Kraftcheck
04155 //
04156 // Creation Date : 02/23/03
04157 //-------------------------------------------------------------------------
04158 void PartitionEngine::insert_nonmanifold_surfaces( 
04159                                    DLIList<PartitionSurface*>& surf_stack,
04160                                    PartitionShell* shell1,
04161                                    PartitionShell* shell2 )
04162 {
04163   DLIList<PartitionSurface*> known_list(surf_stack.size()), 
04164                            unknown_list(surf_stack.size());
04165   
04166   PartitionCoSurf* cosurf;
04167   PartitionSurface* surf;
04168   PartitionLoop* loop;
04169   PartitionCoEdge *coedge, *curve_coe;
04170   PartitionCurve* curve;
04171   
04172     // Loop until we've placed all the surfaces in one
04173     // shell or the other.
04174   while ( surf_stack.size() )
04175   {
04176     bool did_some = false;
04177     
04178       // Put any surfaces for which we immediately
04179       // know the shell into the appropriate shell.
04180       // Put others in known_list or unknown_list
04181       // depending on if we can determine which shell
04182       // they go in using a geometric comparison.
04183     known_list.clean_out();
04184     unknown_list.clean_out();
04185 
04186       // Take all surfaces out of stack in this loop.
04187       // We might put some back in after the loop (thus
04188       // the outer loop.)
04189     while ( surf_stack.size() )
04190     {
04191       surf = surf_stack.pop();
04192       
04193       PartitionShell* known_shell = 0;
04194       bool found_shell = false;
04195       loop = 0;
04196       while ( (loop = surf->next_loop(loop)) )
04197       {
04198         coedge = loop->first_coedge();
04199         do
04200         {
04201           curve = coedge->get_curve();
04202           curve_coe = 0;
04203           while ( (curve_coe = curve->next_coedge(curve_coe)) )
04204           {
04205             PartitionSurface* surf = curve_coe->get_loop()->get_surface();
04206             cosurf = 0;
04207             while ( (cosurf = surf->next_co_surface( cosurf )) )
04208             {
04209               if( cosurf->get_shell() == shell1 ||
04210                   cosurf->get_shell() == shell2 )
04211               {
04212                 found_shell = true;
04213                 if ( known_shell && known_shell != cosurf->get_shell() )
04214                   known_shell = 0;
04215                 else
04216                   known_shell = cosurf->get_shell();
04217               }
04218             }
04219           }
04220         
04221           coedge = loop->next_coedge(coedge);
04222         } while( coedge != loop->first_coedge() );
04223       } // end while(loop)
04224         
04225         // This surface does not intersect the shell at
04226         // any curve.  We can't do this one yet.
04227       if ( !found_shell )
04228       {
04229         unknown_list.append( surf );
04230         continue;
04231       }
04232       
04233         // This surface intersected both shells at some
04234         // curves, but did not have a curve that intersected
04235         // only one shell.  We can do this one geometricly
04236         // if we have to.
04237       if ( !known_shell )
04238       {
04239         known_list.append( surf );
04240         continue;
04241       }
04242       
04243         // If we got this far, then the surface had at least
04244         // one curve that intersected only one of the shells.
04245         // We know it goes in that shell.
04246       did_some = true;
04247       PartitionCoSurf* cosurf1 = surf->find_first((PartitionShell*)0);
04248       PartitionCoSurf* cosurf2 = surf->find_next(cosurf1);
04249       known_shell->add(cosurf1);
04250       known_shell->add(cosurf2);
04251     
04252     } // while(surf_stack)  -- the inside one
04253     
04254       // Unknown_list always goes back in surf_stack to
04255       // try again.
04256     surf_stack += unknown_list;
04257     
04258       // If we did some surfaces, then put the rest back
04259       // in surf_stack and try again.  If they intersect
04260       // one of the surfaces we did place in this iteration,
04261       // we can avoid needing to do geometric checks.
04262     if ( did_some )
04263     {
04264       surf_stack += known_list;
04265       continue;
04266     }
04267     
04268       // If known_list is empty, somethings wrong (we're
04269       // going to loop forever.)  Abort the loop and try
04270       // to recover as best we can.
04271     if( !known_list.size() )
04272       break;
04273     
04274       // choose a single surface in do a geometric comparison
04275       // for, and put the rest back in surf_stack
04276     surf = known_list.pop();
04277     surf_stack += known_list;
04278     
04279     bool in_shell = false;
04280     if ( ! inside_shell( shell2, surf, in_shell ) )
04281     {
04282         // if inside_shell failed, abort.
04283       surf_stack.append(surf);
04284       break;
04285     }
04286     
04287     PartitionShell* shell = in_shell ? shell2 : shell1;
04288     shell->add(surf->find_first((PartitionShell*)0));
04289     shell->add(surf->find_first((PartitionShell*)0));
04290   }
04291   
04292     // something went wrong
04293   if( surf_stack.size() )
04294   {
04295     PRINT_ERROR("Internal error splitting volume at %s:%d\n"
04296                 "Topology may be invalid.  Please report this.\n",
04297                 __FILE__, __LINE__);
04298     while( surf_stack.size() ) 
04299     {
04300       PartitionSurface* surf = surf_stack.pop();
04301       cosurf = 0;
04302       while( (cosurf = surf->next_co_surface(cosurf)) )
04303         if( !cosurf->get_shell() )
04304           shell1->add(cosurf);
04305     }
04306   }
04307 }
04308 
04309 
04310 CubitStatus PartitionEngine::inside_shell( PartitionShell* const shell,
04311                                            PartitionSurface* const surf,
04312                                            bool& result )
04313 {
04314     // Find the curve and coedge at which the nonmanifold surface
04315     // intersects the shells
04316   PartitionLoop* loop = 0;
04317   PartitionCoEdge *nonman_coedge = 0;
04318   while ( !nonman_coedge && (loop = surf->next_loop(loop)) )
04319   {
04320     PartitionCoEdge* loop_coedge = loop->first_coedge();
04321     do 
04322     {
04323         // Check if this curve is the curve of intersection
04324         // Iterate through curve coedges.
04325       PartitionCurve* curve = loop_coedge->get_curve();
04326       PartitionCoEdge* curve_coedge = 0;
04327       while ( (curve_coedge = curve->next_coedge(curve_coedge)) )
04328       {
04329         
04330         PartitionSurface* coedge_surf = curve_coedge->get_loop()->get_surface();
04331         if( coedge_surf->find_first(shell) )
04332         {
04333           nonman_coedge = curve_coedge;
04334           break;
04335         }
04336       }
04337     
04338       loop_coedge = loop->next_coedge(loop_coedge);
04339     } while( !nonman_coedge && loop_coedge != loop->first_coedge() );
04340   }
04341   
04342   if ( !nonman_coedge ) // bad input!
04343     return CUBIT_FAILURE;
04344 
04345     // There must exist two surfaces in the shell that are manifold 
04346     // in the shell and that are adjacent to the curve
04347   PartitionCurve* common_curve = nonman_coedge->get_curve();
04348   PartitionCoSurf *cosurf1 = 0, *cosurf2 = 0, *cosurf;
04349   PartitionCoEdge *coedge1 = 0, *coedge2 = 0, *coedge = 0;
04350   while ( (coedge = common_curve->next_coedge(coedge)) )
04351   {
04352     PartitionSurface* surf = coedge->get_loop()->get_surface();
04353     if ( (cosurf = surf->find_first(shell)) && !surf->find_next(cosurf) )
04354     {
04355       if( coedge1 ) {
04356         coedge2 = coedge;
04357         cosurf2 = cosurf;
04358       } else {
04359         coedge1 = coedge;
04360         cosurf1 = cosurf;
04361       }
04362     }
04363   }
04364   if ( !coedge1 || !coedge2 )
04365     return CUBIT_FAILURE;
04366   
04367     // Evaluate normals at midpoint of curve
04368   CubitVector base, tangent, point;
04369   double u = (common_curve->start_param()+common_curve->end_param())/2.0;
04370   common_curve->position_from_u( u, base );
04371   common_curve->closest_point( base, point, &tangent );
04372   tangent.normalize();
04373   
04374   CubitVector normal1, normal2, normal;
04375   surf->closest_point( base, 0, &normal );
04376   cosurf1->get_surface()->closest_point( base, 0, &normal1 );
04377   cosurf2->get_surface()->closest_point( base, 0, &normal2 );
04378   
04379     // Try to handle tangencies
04380   bool fix1 = (normal1 * normal).length_squared() < CUBIT_RESABS;
04381   bool fix2 = (normal2 * normal).length_squared() < CUBIT_RESABS;
04382   if ( fix1 || fix2 )
04383   {
04384     CubitVector dir = tangent * normal;
04385     double len = dir.length();
04386     assert(len > GEOMETRY_RESABS);
04387     dir /= len;
04388     if ( nonman_coedge->sense() == CUBIT_FORWARD )
04389       dir = -dir;
04390       
04391     CubitVector diag = surf->bounding_box().diagonal();
04392     if ( fix1 )
04393     {
04394       CubitVector d = cosurf1->get_surface()->bounding_box().diagonal();
04395       if ( diag.x() < d.x() ) diag.x(d.x());
04396       if ( diag.y() < d.y() ) diag.y(d.y());
04397       if ( diag.z() < d.z() ) diag.z(d.z());
04398     }
04399     if( fix2 )
04400     {
04401       CubitVector d = cosurf2->get_surface()->bounding_box().diagonal();
04402       if ( diag.x() < d.x() ) diag.x(d.x());
04403       if ( diag.y() < d.y() ) diag.y(d.y());
04404       if ( diag.z() < d.z() ) diag.z(d.z());
04405     }
04406     
04407     double step = 1e-3 * fabs( diag % dir );
04408     if ( step < 2*GEOMETRY_RESABS )
04409       step = 2*GEOMETRY_RESABS;
04410     
04411     for ( int i = 0; i < 1000; i++ )
04412     {
04413       point = base + i * step * dir;
04414       surf->closest_point( base, 0, &normal );
04415       if( fix1 )
04416         cosurf1->get_surface()->closest_point( base, 0, &normal1 );
04417       if( fix2 )
04418         cosurf2->get_surface()->closest_point( base, 0, &normal2 );
04419       
04420       bool done1 = !fix1 || (normal1 * normal).length_squared() > CUBIT_RESABS;
04421       bool done2 = !fix2 || (normal2 * normal).length_squared() > CUBIT_RESABS;
04422       if ( done1 && done2 )
04423       {
04424         fix1 = fix2 = false;
04425         break;
04426       }
04427     }
04428   }
04429   
04430   if ( fix1 || fix2 )
04431   {
04432     PRINT_ERROR("Failed to adjust for surface tangencies.\n"
04433                 "This is a BUG.  %s:%d\n", __FILE__, __LINE__ );
04434     return CUBIT_FAILURE;
04435   }
04436   
04437   if ( nonman_coedge->sense() == CUBIT_FORWARD )
04438     normal = -normal;
04439   if ( cosurf1->sense() == coedge1->sense() )
04440     normal1 = -normal1;
04441   if ( cosurf2->sense() == coedge2->sense() )
04442     normal2 = -normal2;
04443   
04444   result = tangent.vector_angle(normal1, normal ) <=
04445            tangent.vector_angle(normal1, normal2);
04446   return CUBIT_SUCCESS;
04447 }
04448 
04449   
04450 
04451 
04452 
04453 
04454 //-------------------------------------------------------------------------
04455 // Purpose       : Remove a partition surface previously inserted in a
04456 //                 lump via insert_surface(..).
04457 //
04458 // Special Notes : 
04459 //
04460 // Creator       : Jason Kraftcheck
04461 //
04462 // Creation Date : 01/13/03
04463 //-------------------------------------------------------------------------
04464 Lump* PartitionEngine::remove_surface( PartitionSurface* surface )
04465 {
04466     // If surface belongs to non-partition volumes, we cannot proceed.
04467   DLIList<TopologyBridge*> shell_bridges;
04468   surface->get_parents_virt( shell_bridges );
04469   while( shell_bridges.size() )
04470     if( ! dynamic_cast<PartitionShell*>(shell_bridges.pop()) )
04471       return 0;
04472   
04473   PartitionCoSurf* cosurf1 = surface->next_co_surface(0);
04474   if( ! cosurf1 )
04475     return 0; // doesn't belong to any PartitionLumps;
04476     
04477   PartitionCoSurf* cosurf2 = surface->next_co_surface(cosurf1);
04478   if( !cosurf2 || surface->next_co_surface(cosurf2) )
04479     return 0; // must have exactly two parent cosurfaces.
04480     
04481   PartitionShell* shell1 = cosurf1->get_shell();
04482   PartitionShell* shell2 = cosurf2->get_shell();
04483   PartitionLump* lump1 = shell1->get_lump();
04484   PartitionLump* lump2 = shell2->get_lump();
04485   
04486   if( surface->partitioned_entity() != lump1->partitioned_entity() )
04487     return 0; // shouldn't have gotten this far, but just in case ...
04488   
04489     // remove and destroy surface
04490   shell1->remove( cosurf1 );
04491   shell2->remove( cosurf2 );
04492   surface->remove(cosurf1);
04493   surface->remove(cosurf2);
04494   delete cosurf1;
04495   delete cosurf2;
04496   destroy_surface(surface);
04497     
04498   
04499     // combine volumes?
04500   if( shell1 != shell2 )
04501   {
04502     assert(lump1 != lump2);
04503     while( PartitionCoSurf* cosurf = shell2->next_co_surface(0) )
04504     {
04505       shell2->remove(cosurf);
04506       shell1->add(cosurf);
04507     }
04508     lump2->remove(shell2);
04509     delete shell2;
04510     
04511     if( !shell1->next_co_surface(0) )
04512     {
04513       lump1->remove(shell1);
04514       delete shell1;
04515     }
04516     
04517     while( PartitionShell* shell = lump2->next_shell(0) )
04518     {
04519       lump2->remove(shell);
04520       lump1->add(shell);
04521     }
04522     delete lump2;
04523   }
04524     // one-surface shell
04525   else if( !shell1->next_co_surface(0) )
04526   {
04527     lump1->remove( shell1 );
04528     delete shell1;
04529   }
04530     // possibly split shells
04531   else 
04532   {
04533     PartitionShell* shell = split_shell( shell1 );
04534     if( shell )
04535       lump1->add(shell);
04536   }
04537     
04538   if( !lump1->sub_entity_set().has_lower_order() )
04539     return restore_lump( lump1 );
04540   else
04541     return lump1;
04542 }
04543 
04544 
04545 //-------------------------------------------------------------------------
04546 // Purpose       : tear down and free a surface
04547 //
04548 // Special Notes : 
04549 //
04550 // Creator       : Jason Kraftcheck
04551 //
04552 // Creation Date : 01/14/03
04553 //-------------------------------------------------------------------------
04554 CubitStatus PartitionEngine::destroy_surface( PartitionSurface* surface )
04555 {
04556   while( PartitionLoop* dead_loop = surface->next_loop(0) )
04557   {
04558     surface->remove(dead_loop);
04559     while( PartitionCoEdge* dead_coe = dead_loop->first_coedge() )
04560     {
04561       PartitionCurve* dead_curve = dead_coe->get_curve();
04562       dead_loop->remove(dead_coe);
04563       dead_curve->remove(dead_coe);
04564       delete dead_coe;
04565       
04566       if( dead_curve->partitioned_entity() == surface->partitioned_entity() )
04567       {
04568         if( dead_curve->next_coedge(0) == 0 )
04569         {
04570           PartitionPoint* start_pt = dead_curve->start_point();
04571           PartitionPoint* end_pt = dead_curve->end_point();
04572           delete dead_curve;
04573           if( start_pt->partitioned_entity() == surface->partitioned_entity() &&
04574               start_pt->next_curve() == 0 )
04575             delete start_pt;
04576           if( end_pt->partitioned_entity() == surface->partitioned_entity() &&
04577               end_pt->next_curve() == 0 )
04578             delete end_pt;
04579         }
04580       }
04581       else if( SubCurve* subcurve = dynamic_cast<SubCurve*>(dead_curve) )
04582       {
04583         restore_curve(subcurve);
04584       }
04585     }
04586     delete dead_loop;
04587   }
04588   delete surface;
04589   return CUBIT_SUCCESS;
04590 }
04591 
04592 
04593 //-------------------------------------------------------------------------
04594 // Purpose       : Retreive entity from UID attrib data.
04595 //
04596 // Special Notes : Used when restoring saved geometry.
04597 //
04598 // Creator       : Jason Kraftcheck
04599 //
04600 // Creation Date : 02/23/03
04601 //-------------------------------------------------------------------------
04602 PartitionEntity* PartitionEngine::entity_from_id( int set_id,
04603                                                   int entity_id,
04604                                                   SubEntitySet& default_set )
04605 {
04606   if( set_id == 0 )
04607     return default_set.entity_from_id( entity_id );
04608   
04609   SubEntitySet* set = get_from_id_map(set_id);
04610   if( set )
04611     return set->entity_from_id( entity_id );
04612   
04613   return 0;
04614 }
04615  
04616 //-------------------------------------------------------------------------
04617 // Purpose       : Restore curve partitions
04618 //
04619 // Special Notes : 
04620 //
04621 // Creator       : Jason Kraftcheck
04622 //
04623 // Creation Date : 02/23/03
04624 //-------------------------------------------------------------------------
04625 CubitStatus PartitionEngine::restore_from_attrib( Curve* curve )
04626 {
04627   int i, id, dim, max_id = 0;
04628   DLIList<CubitSimpleAttrib> attribs, point_attribs, curve_attribs;
04629   DLIList<CubitVector*> empty;
04630   DLIList<int> junk, point_conn;
04631   DLIList<PartitionPoint*> new_points;
04632   CubitStatus result = CUBIT_FAILURE;
04633   
04634   {
04635       // Get list of partition attributes.
04636     curve->get_simple_attribute(PARTITION_GEOM_ATTRIB_NAME,attribs);
04637     if( attribs.size() == 0 )
04638       return CUBIT_SUCCESS;
04639 
04640       // Group attributes into those defining partition points and
04641       // those defining the subcurves.  Also find max ID of all 
04642       // partition geometry on this curve
04643     attribs.reset();
04644     for( i = attribs.size(); i--; )
04645     {
04646       const CubitSimpleAttrib& attrib = attribs.get_and_step();
04647       dim = SubEntitySet::get_geom_dimension(attrib);
04648       if( dim == 0 )
04649         point_attribs.append(attrib);
04650       else if( dim == 1 )
04651         curve_attribs.append(attrib);
04652       else
04653         goto CLEANUP_CURVE_FROM_ATTRIB;
04654 
04655       id = SubEntitySet::get_geom_id( attrib );
04656       if( id > max_id )
04657         max_id = id;
04658     }
04659 
04660       // Create first curve (duplicate of input curve)
04661     PartitionCurve* first_curve = replace_curve( curve );
04662     if( ! first_curve )
04663       goto CLEANUP_CURVE_FROM_ATTRIB;
04664 
04665       // Set up SubEntitySet such that new entities get IDs
04666       // larger than max_id as they are created.
04667     first_curve->sub_entity_set().renumerate( max_id + 1, false );
04668 
04669       // Create all the partition points
04670     point_attribs.reset();
04671     for( i = point_attribs.size(); i--; )
04672     {
04673       const CubitSimpleAttrib& attrib = point_attribs.get_and_step();
04674       PartitionPoint* point = new PartitionPoint( attrib, first_curve );
04675       if( !point )
04676         goto CLEANUP_CURVE_FROM_ATTRIB;
04677 
04678       curve->remove_simple_attribute_virt(attrib);
04679     }
04680 
04681       // Now partition the curve and assign the ID from each
04682       // curve attribute the the appropriate curve partition.
04683       //
04684       // We're going to do this in order along the curve, such
04685       // that the first subcurve will begin at the start_point() of
04686       // the original curve.
04687     PartitionPoint* prev_point = first_curve->start_point();
04688     PartitionCurve* next_curve = first_curve;
04689     while( curve_attribs.size() )
04690     {
04691         // Search for attribute corresponding to curve
04692         // beginning at prev_point
04693       PartitionPoint *start = 0, *end = 0;
04694       CubitSimpleAttrib curve_attrib;
04695       curve_attribs.last();
04696       for( i = curve_attribs.size(); i--; )
04697       {
04698           // Get data from attribute
04699         const CubitSimpleAttrib& attrib = curve_attribs.step_and_get();
04700         point_conn.clean_out();
04701         if( !SubEntitySet::read_geometry(id,dim,empty,junk,point_conn,junk,attrib)
04702             || empty.size() || junk.size() || dim != 1 || point_conn.size() != 4)
04703           goto CLEANUP_CURVE_FROM_ATTRIB;
04704 
04705           // Get start point from IDs
04706         point_conn.reset();
04707         int sid = point_conn.get_and_step();
04708         int eid = point_conn.get_and_step();
04709         PartitionEntity* ent = entity_from_id(sid, eid, first_curve->sub_entity_set());
04710         start = dynamic_cast<PartitionPoint*>(ent);
04711         
04712         if( start == prev_point )
04713         {
04714             // Found the attrib we want. 
04715             // Get the end point and break the loop.
04716           sid = point_conn.get_and_step();
04717           eid = point_conn.get_and_step();
04718           ent = entity_from_id(sid, eid, first_curve->sub_entity_set());
04719           end = dynamic_cast<PartitionPoint*>(ent);
04720 
04721           curve_attrib = curve_attribs.extract();
04722           break;
04723         }
04724       }
04725 
04726         // Make sure we found an attrib to do
04727       if( curve_attrib.isEmpty() || !start || !end )
04728         goto CLEANUP_CURVE_FROM_ATTRIB;
04729 
04730         // Unless this is the last partition (no more splitting
04731         // required), split the curve at the end point.  Make
04732         // next_curve point to the (unpartitioned) remainder of
04733         // the curve.
04734       PartitionCurve* new_curve = next_curve;
04735       if( next_curve->end_point() != end )
04736       {
04737         next_curve = insert_point( new_curve, end );
04738         if( !next_curve )
04739           goto CLEANUP_CURVE_FROM_ATTRIB;
04740       }
04741 
04742         // Set the new curve's ID to whatever it is stored
04743         // as in the attribute.
04744       new_curve->sub_entity_set().set_id( new_curve, 
04745         SubEntitySet::get_geom_id( curve_attrib ) );
04746 
04747         // Remove processed attributes.
04748       curve->remove_simple_attribute_virt( curve_attrib );
04749       
04750         // Next iteration
04751       prev_point = end;
04752     }
04753 
04754       // Compress SubEntitySet ID space
04755     next_curve->sub_entity_set().renumerate( max_id + 1, true );
04756     result = CUBIT_SUCCESS;
04757   }
04758   
04759 CLEANUP_CURVE_FROM_ATTRIB:
04760 
04761   for( i = new_points.size(); i--; )
04762   {
04763     PartitionPoint* pt = new_points.get_and_step();
04764     if( !pt->next_curve(0) )
04765       delete pt;
04766   }
04767   
04768   if (!result)
04769     PRINT_ERROR("Error restoring curve partitions from attributes.\n");
04770     
04771   return result;
04772 }  
04773 
04774 
04775 //-------------------------------------------------------------------------
04776 // Purpose       : Restore surface partitions
04777 //
04778 // Special Notes : 
04779 //
04780 // Creator       : Jason Kraftcheck
04781 //
04782 // Creation Date : 02/23/03
04783 //-------------------------------------------------------------------------
04784 CubitStatus PartitionEngine::restore_from_attrib( Surface* surf )
04785 {
04786   int i, j, k, id, dim, max_id = 0;
04787   DLIList<CubitSimpleAttrib> attribs;
04788   DLIList<CubitFacetEdgeData*> polyline_edges;
04789   DLIList<CubitPointData*> polyline_pts;
04790   DLIList<CubitFacetData*> surf_facets;
04791   DLIList<CubitVector*> positions;
04792   DLIList<PartitionEntity*> new_geom;
04793   DLIList<PartitionLoop*> loops;
04794   DLIList<int> facets(0), connectivity, pt_owners;
04795   CubitStatus result = CUBIT_FAILURE;
04796   SubSurface* first_surf = 0;
04797   
04798   
04799   {
04800       // Get partition attributes from entity.  Return if there aren't any.
04801     surf->get_simple_attribute(PARTITION_GEOM_ATTRIB_NAME,attribs);
04802     if( attribs.size() == 0 )
04803       return CUBIT_SUCCESS;
04804 
04805     PRINT_DEBUG_86("Reading partition geometry on %s %p\n", 
04806       fix_type_name( typeid(*surf).name() ), (void*)surf );
04807       
04808       // Find max ID
04809     attribs.reset();
04810     for( i = attribs.size(); i--; )
04811     {
04812       id = SubEntitySet::get_geom_id( attribs.get_and_step() );
04813       if( id > max_id )
04814         max_id = id;
04815     }
04816 
04817       // Create first partition surface (initially a duplicate of
04818       // the input surface)
04819     first_surf = replace_surface( surf );
04820     if( ! first_surf )
04821     {  
04822       PRINT_ERROR("Internal Error: PartitionEngine::replace_surface() failed.\n");
04823       goto CLEANUP_SURF_FROM_ATTRIB;
04824     }
04825     
04826       // Update SubEntitySet such that new entities get assigned
04827       // IDs greater than max_id when they are created.  This
04828       // leaves the range 0->max_id free so that we can reassign
04829       // the saved IDs after the entities are created.
04830     first_surf->sub_entity_set().renumerate( max_id + 1, false );
04831 
04832       // create all interior vertices
04833     attribs.reset();
04834     for( i = attribs.size(); i--; )
04835     {
04836         // Only want point attributes (dimension of zero)
04837       CubitSimpleAttrib attrib = attribs.get();
04838       if( SubEntitySet::get_geom_dimension(attrib) != 0 )
04839       {
04840         attribs.step();
04841         continue;
04842       }
04843 
04844         // Create the point at the location specified in the attrib.
04845       attribs.extract();
04846       surf->remove_simple_attribute_virt(attrib);
04847       PartitionPoint* new_pt = new PartitionPoint( attrib, first_surf );
04848       CubitPointData* data = project_to_surface( first_surf, new_pt->coordinates() );
04849       new_pt->facet_point(data);
04850       new_geom.append(new_pt);
04851       PRINT_DEBUG_86("  Created Point %p (%d in subset) at (%f,%f,%f)\n", 
04852         (void*)new_pt, new_pt->sub_entity_set().get_id(new_pt),
04853         new_pt->coordinates().x(), new_pt->coordinates().y(), 
04854         new_pt->coordinates().z() );
04855       if (DEBUG_FLAG(86))
04856       {
04857         GfxDebug::draw_point(new_pt->coordinates(), new_pt->sub_entity_set().get_id(new_pt));
04858         GfxDebug::flush();
04859       }
04860     }
04861 
04862       // create all interior curves
04863     attribs.reset();
04864     for( i = attribs.size(); i--; )
04865     {
04866         // Only want curve attributes (dimension of one)
04867       CubitSimpleAttrib attrib = attribs.get();
04868       if( SubEntitySet::get_geom_dimension(attrib) != 1 )
04869       {
04870         attribs.step();
04871         continue;
04872       }
04873 
04874         // Remove this attrib from the real geom, as we are
04875         // handling it
04876       attribs.extract();
04877       surf->remove_simple_attribute_virt(attrib);
04878       
04879       if ( SubEntitySet::get_segment_count(attrib) == 0 )
04880       {
04881         PartPTCurve* pt_curve = PartPTCurve::construct(attrib, first_surf);
04882         if (!pt_curve)
04883         {
04884           PRINT_ERROR("point-curve construction failed -- corrupt data?\n");
04885           goto CLEANUP_SURF_FROM_ATTRIB;
04886         }
04887         new_geom.append( pt_curve );
04888         PRINT_DEBUG_86("  Created point-curve %p (%d in subset) with\n"
04889                        "    point %p (%d in subset) at (%f,%f,%f)\n", 
04890           (void*)pt_curve,
04891           pt_curve->sub_entity_set().get_id(pt_curve), 
04892           (void*)pt_curve->start_point(),
04893           pt_curve->start_point()->sub_entity_set().get_id(pt_curve->start_point()),
04894           pt_curve->start_point()->coordinates().x(),
04895           pt_curve->start_point()->coordinates().y(), 
04896           pt_curve->start_point()->coordinates().z() );
04897 
04898         CubitPointData* pt = project_to_surface( first_surf, pt_curve->start_point()->coordinates() );
04899         if ( !pt )
04900         {
04901           PRINT_ERROR("projection of position onto surface facets failed.\n");
04902           goto CLEANUP_SURF_FROM_ATTRIB;
04903         }
04904           
04905         pt_curve->start_point()->facet_point( pt );
04906         continue;
04907       }
04908       
04909         // Create the curve
04910       SegmentedCurve* new_curve = SegmentedCurve::construct( attrib, first_surf );
04911       if( !new_curve ) 
04912       {
04913         PRINT_ERROR("segmented curve construction failed -- corrupt data?\n");
04914         goto CLEANUP_SURF_FROM_ATTRIB;
04915       }
04916       new_geom.append(new_curve);
04917       PRINT_DEBUG_86("  Created polyline curve %p (%d in subset) with %d segments.\n"
04918                      "    start point %p (%d in subset) at (%f,%f,%f)\n" 
04919                      "      end point %p (%d in subset) at (%f,%f,%f)\n", 
04920           (void*)new_curve,
04921           new_curve->sub_entity_set().get_id(new_curve),
04922           new_curve->point_count() - 1, 
04923           (void*)new_curve->start_point(),
04924           new_curve->start_point()->sub_entity_set().get_id(new_curve->start_point()),
04925           new_curve->start_point()->coordinates().x(),
04926           new_curve->start_point()->coordinates().y(), 
04927           new_curve->start_point()->coordinates().z(),
04928           (void*)new_curve->end_point(),
04929           new_curve->end_point()->sub_entity_set().get_id(new_curve->end_point()),
04930           new_curve->end_point()->coordinates().x(),
04931           new_curve->end_point()->coordinates().y(), 
04932           new_curve->end_point()->coordinates().z() );
04933  
04934         // Get curve segments
04935       positions.clean_out();
04936       polyline_edges.clean_out();
04937       new_curve->get_segments( positions );
04938       
04939       if (DEBUG_FLAG(86))
04940       {
04941         GPoint* array = new GPoint[positions.size()];
04942         positions.reset();
04943         for (int dd = 0; dd < positions.size(); dd++ )
04944         {
04945           array[dd].x = (float)positions.next(dd)->x(); 
04946           array[dd].y = (float)positions.next(dd)->y();
04947           array[dd].z = (float)positions.next(dd)->z();
04948         }
04949         
04950         GfxDebug::draw_polyline(array, positions.size(),
04951                                 new_curve->sub_entity_set().get_id(new_curve));
04952         GfxDebug::flush();
04953       }
04954       
04955         // Make sure segment end points are on curve end points
04956       positions.last();
04957       *positions.get() = new_curve->end_point()->coordinates();
04958       positions.reset();
04959       *positions.get() = new_curve->start_point()->coordinates();
04960       
04961         // Project curve into surface facets
04962       surf_facets.clean_out();
04963       first_surf->get_facet_data( surf_facets );
04964       CubitStatus s = project_to_surface( surf_facets, positions, 
04965                               polyline_edges, polyline_pts );
04966       while( positions.size() ) 
04967       {
04968         CubitVector* position = positions.pop();
04969         if(s)
04970         {
04971    //       assert(polyline_pts.size());
04972           CubitPointData* point = polyline_pts.pop();
04973           if (point && point->check_inverted_facets(*position))
04974             point->set(*position);
04975         }
04976         delete position;
04977       }
04978       if( !s || !polyline_edges.size() ) 
04979       {
04980         PRINT_ERROR("Imprint of polyline onto surface facets failed.\n");
04981         goto CLEANUP_SURF_FROM_ATTRIB;
04982       }
04983       
04984       
04985         // move facet points onto surface
04986       for ( j = 0; j < 2; j++ )
04987         for ( k = polyline_edges.size(); k--; )
04988           if ( CubitFacetEdgeData* edge = polyline_edges.get_and_step() )
04989             edge->point(j)->marked(1);
04990       
04991       for ( j = polyline_edges.size(); j--; )
04992       {
04993         CubitFacetEdgeData* edge = polyline_edges.get_and_step();
04994         if ( !edge ) continue;
04995         for ( k = 0; k < 2; k++ )
04996         {
04997           CubitPoint* pt = edge->point(k);
04998           if ( pt->marked() ) 
04999           {
05000             pt->marked(0);
05001             first_surf->relax_to_geometry(pt);
05002           }
05003         }
05004       }
05005         
05006       
05007         // Associate facet data with geometry
05008         
05009       CubitPoint *last_pt, *first_pt;
05010       polyline_edges.last();
05011       assert(!polyline_edges.get());
05012       polyline_edges.pop();
05013       
05014       if( polyline_edges.size() == 1 )
05015       {
05016         last_pt = polyline_edges.get()->point(1);
05017         first_pt = polyline_edges.get()->point(0);
05018       }
05019       else
05020       {
05021         CubitFacetEdgeData *edge, *neighbor;
05022         
05023         polyline_edges.last();
05024         edge = polyline_edges.get();
05025         neighbor = polyline_edges.prev();
05026         if( !edge || !neighbor )
05027         {
05028           PRINT_ERROR("Bad surface facets.\n");
05029           goto CLEANUP_SURF_FROM_ATTRIB;
05030         }
05031         last_pt = edge->shared_point(neighbor);
05032         last_pt = edge->other_point(last_pt);
05033 
05034         polyline_edges.reset();
05035         edge = polyline_edges.get();
05036         neighbor = polyline_edges.next();
05037         if( !edge || !neighbor )
05038         {
05039           PRINT_ERROR("Bad surface facets.\n");
05040           goto CLEANUP_SURF_FROM_ATTRIB;
05041         }
05042         first_pt = edge->shared_point(neighbor);
05043         first_pt = edge->other_point(first_pt);
05044       }
05045 
05046       PartitionEntity* owner1 = TDVGFacetOwner::get( first_pt );
05047       PartitionEntity* owner2 = TDVGFacetOwner::get( last_pt );
05048 
05049       if ( new_curve->start_point() == new_curve->end_point() )
05050       {
05051         if ( owner1 == owner2 && owner1 == new_curve->start_point() )
05052         {
05053           first_pt = polyline_edges.get()->other_point( first_pt );
05054           polyline_edges.last();
05055           last_pt = polyline_edges.get()->other_point( last_pt );
05056           double u1 = new_curve->u_from_position( first_pt->coordinates() );
05057           double u2 = new_curve->u_from_position( last_pt->coordinates() );
05058           if ( u2 < u1 )
05059             polyline_edges.reverse();
05060           polyline_edges.reset();
05061         }
05062         else
05063         {
05064           s = CUBIT_FAILURE;
05065         }
05066       }
05067       else if ( owner1 == new_curve->end_point() &&
05068                 owner2 == new_curve->start_point() )
05069       {
05070         polyline_edges.reverse();
05071         polyline_edges.reset();
05072       }
05073       else if( owner1 != new_curve->start_point() ||
05074                owner2 != new_curve->end_point() )
05075       {
05076         s = CUBIT_FAILURE;
05077       }
05078      
05079       if (!s) 
05080       {
05081         PRINT_ERROR("Tolerance problems when restoring surface partitions.\n");
05082         goto CLEANUP_SURF_FROM_ATTRIB;
05083       }
05084       
05085       new_curve->set_facet_data( polyline_edges );
05086     }
05087 
05088       // while there are more surface partitions to create
05089     PartitionEntity* ent = 0;
05090     while( attribs.size() )
05091     {
05092         // read attribute
05093       CubitSimpleAttrib surf_attr = attribs.pop();
05094       connectivity.clean_out();
05095       CubitStatus s = SubEntitySet::
05096         read_geometry( id, dim, positions, facets, connectivity, pt_owners, surf_attr );
05097       
05098       if( !s || dim != 2 || positions.size() || facets.size() )
05099       {
05100         PRINT_ERROR("Corrupt/inconsistent subsurface data.\n");
05101         goto CLEANUP_SURF_FROM_ATTRIB;
05102       }
05103       
05104       PRINT_DEBUG_86("  Constructing SubSurface (%d in subset)\n", id);
05105 
05106         // construct surface loops
05107       int j = connectivity.size();
05108       PartitionCoEdge* curve_coedge = 0; // save one non-point-curve coedge
05109       while ( j > 0 )
05110       {
05111         int loop = connectivity.get_and_step();
05112         j--;
05113 
05114         PartitionLoop* new_loop = new PartitionLoop();
05115         loops.append( new_loop );
05116         PartitionCoEdge* prev_coedge = 0;
05117         PRINT_DEBUG_86("   Loop: ");
05118 
05119         while( loop-- )
05120         {
05121           int set_id = connectivity.get_and_step();
05122           int ent_id = connectivity.get_and_step();
05123           int sense = ent_id < 0 ? -1 : 1;
05124           ent_id *= sense;
05125           j -= 2;
05126 
05127           ent = entity_from_id( set_id, ent_id, first_surf->sub_entity_set() );
05128           PartitionCurve* curve = dynamic_cast<PartitionCurve*>(ent);
05129           PRINT_DEBUG_86(" %p,%d,%d%c", (void*)curve, set_id, ent_id*sense, loop?',':'\n');
05130           if(!curve)
05131           {
05132             PRINT_ERROR("Nonexistant curve specified in saved connectivity.\n");
05133             goto CLEANUP_SURF_FROM_ATTRIB;
05134           }
05135 
05136           CubitSense cubit_sense = sense == -1 ? CUBIT_REVERSED : CUBIT_FORWARD;
05137           PartitionCoEdge* coedge = 0;
05138           while ( (coedge = curve->next_coedge(coedge)) )
05139           {
05140             if ( coedge->sense() == cubit_sense &&
05141                  coedge->get_loop() &&
05142                  coedge->get_loop()->get_surface() == first_surf )
05143             {
05144               coedge->get_loop()->remove( coedge );
05145               break;
05146             }
05147           }
05148           if ( !coedge )
05149           {
05150             coedge = new PartitionCoEdge( first_surf, cubit_sense );
05151             curve->add(coedge);
05152           }
05153           
05154           if (!curve_coedge && curve->geometry_type() != POINT_CURVE_TYPE)
05155             curve_coedge = coedge;
05156             
05157           new_loop->insert_after( coedge, prev_coedge );
05158           prev_coedge = coedge;
05159         }
05160       }
05161       
05162       if (!curve_coedge)
05163       {
05164         PRINT_ERROR("Nonexistant co-edge specified in saved connectivity.\n");
05165         goto CLEANUP_SURF_FROM_ATTRIB;
05166       }
05167       
05168       PartitionSurface* new_surf = split_surface( first_surf, curve_coedge );
05169       if (new_surf == first_surf && attribs.size() > 0)
05170       {
05171         PRINT_ERROR("Surface splitting failed -- bad topology?.\n");
05172         goto CLEANUP_SURF_FROM_ATTRIB;
05173       }
05174             
05175       new_surf->sub_entity_set().set_id( new_surf, id );
05176       while ( loops.size() )
05177         new_surf->add( loops.pop() );
05178     }
05179 
05180     result = CUBIT_SUCCESS;
05181   }
05182   
05183 CLEANUP_SURF_FROM_ATTRIB:
05184 
05185     // clean up any unused loops from failed surface creation
05186   while ( loops.size() )
05187   {
05188     PartitionLoop* loop = loops.pop();
05189     while ( loop->first_coedge() )
05190     {
05191       PartitionCoEdge* coedge = loop->first_coedge();
05192       loop->remove(coedge);
05193       if (coedge->get_curve())
05194         coedge->get_curve()->remove(coedge);
05195       delete coedge;
05196     }
05197     delete loop;
05198   }  
05199     
05200     // first_surf will contain dead loops - clean them up
05201   PartitionLoop* surf_loop = 0;
05202   while ( (surf_loop = first_surf->next_loop( surf_loop ) ) != NULL )
05203     if ( !surf_loop->first_coedge() )
05204       loops.append( surf_loop );
05205   while ( loops.size() )
05206   {
05207     surf_loop = loops.pop();
05208     first_surf->remove( surf_loop );
05209     delete surf_loop;
05210   }
05211     
05212   new_geom.reset();
05213   while( new_geom.size() )
05214   {
05215     PartitionEntity* ent = new_geom.pop();
05216     if( PartitionPoint* pt = dynamic_cast<PartitionPoint*>(ent) )
05217     {
05218       if( !pt->next_curve(0) )
05219         delete pt;
05220     }
05221     else if( PartitionCurve* curve = dynamic_cast<PartitionCurve*>(ent) )
05222     {
05223       if( !curve->next_coedge(0) )
05224         delete curve;
05225     }
05226   }
05227   
05228   first_surf->sub_entity_set().renumerate( max_id + 1, true );
05229   
05230   if (!result)
05231     PRINT_ERROR("Error restoring surface partitions from attributes.\n");
05232     
05233   return result;
05234 }
05235 
05236 //-------------------------------------------------------------------------
05237 // Purpose       : Restore volume partitions from an attribute
05238 //
05239 // Special Notes : 
05240 //
05241 // Creator       : Jason Kraftcheck
05242 //
05243 // Creation Date : 01/22/03
05244 //-------------------------------------------------------------------------
05245 CubitStatus PartitionEngine::restore_from_attrib( Lump* lump )
05246 {
05247   int i, id, dim, max_id = 0;
05248   DLIList<CubitSimpleAttrib> attribs;
05249   DLIList<CubitVector*> positions;
05250   DLIList<int> facets, connectivity, pt_owners;
05251   DLIList<PartitionEntity*> new_geom;
05252   CubitStatus result = CUBIT_FAILURE;
05253   PartitionLump* first_lump = 0;
05254   PartitionLump* new_lump = 0;
05255   
05256   { // pseudo-'try'-block
05257   
05258       // get partition attributes from entity.  Return if none.
05259     lump->get_simple_attribute(PARTITION_GEOM_ATTRIB_NAME,attribs);
05260     if( attribs.size() == 0 )
05261       return CUBIT_SUCCESS;
05262 
05263       // find max ID
05264     attribs.reset();
05265     for( i = attribs.size(); i--; )
05266     {
05267       id = SubEntitySet::get_geom_id( attribs.get_and_step() );
05268       if( id > max_id )
05269         max_id = id;
05270     }
05271 
05272       // Create first parition lump (initially a duplicate of
05273       // the input lump)
05274     first_lump = replace_lump( lump );
05275     if( ! first_lump )
05276       goto CLEANUP_LUMP_FROM_ATTRIB;
05277     
05278       // Update SubEntitySet such that new entities get assigned
05279       // IDs greater than max_id when they are created.  This
05280       // leaves the range 0->max_id free so that we can reassign
05281       // the saved IDs after the entities are created.
05282     first_lump->sub_entity_set().renumerate( max_id + 1, false );
05283 
05284       // create all interior vertices
05285     attribs.reset();
05286     for( i = attribs.size(); i--; )
05287     {
05288         // skip any non-point geometry
05289       CubitSimpleAttrib attrib = attribs.get();
05290       if( SubEntitySet::get_geom_dimension(attrib) != 0 )
05291       {
05292         attribs.step();
05293         continue;
05294       }
05295 
05296         // create the point as specified in the attrib
05297       attribs.extract();
05298       lump->remove_simple_attribute_virt(attrib);
05299       PartitionPoint* new_pt = new PartitionPoint( attrib, first_lump );
05300       new_geom.append(new_pt);
05301     }
05302 
05303       // create all interior curves
05304     attribs.reset();
05305     for( i = attribs.size(); i--; )
05306     {
05307         // skip attribs for anything but curves
05308       CubitSimpleAttrib attrib = attribs.get();
05309       if( SubEntitySet::get_geom_dimension(attrib) != 1 )
05310       {
05311         attribs.step();
05312         continue;
05313       }
05314 
05315         // create curve from attrib
05316       attribs.extract();
05317       lump->remove_simple_attribute_virt(attrib);
05318       SegmentedCurve* new_curve = SegmentedCurve::construct( attrib, first_lump );
05319       if( !new_curve )
05320         goto CLEANUP_LUMP_FROM_ATTRIB;
05321 
05322       new_geom.append(new_curve);
05323     }
05324 
05325       // create all interior surfaces
05326     attribs.reset();
05327     for( i = attribs.size(); i--; )
05328     {
05329         // skip non-surface attributes
05330       CubitSimpleAttrib attrib = attribs.get();
05331       if( SubEntitySet::get_geom_dimension(attrib) != 2 )
05332       {
05333         attribs.step();
05334         continue;
05335       }
05336 
05337         // create surface from attribute
05338       attribs.extract();
05339       lump->remove_simple_attribute_virt(attrib);
05340       PartitionSurface* new_surf = PartitionSurface::construct( attrib, first_lump );
05341       if( !new_surf )
05342         goto CLEANUP_LUMP_FROM_ATTRIB;
05343 
05344       new_geom.append(new_surf);
05345     }
05346 
05347 
05348       // while there are more volume partitions to create
05349     PartitionEntity* ent = 0;
05350     while( attribs.size() )
05351     {
05352         // Read data from attribute
05353       const CubitSimpleAttrib& attr = attribs.pop();
05354       connectivity.clean_out();
05355       CubitStatus s = SubEntitySet::
05356         read_geometry( id, dim, positions, facets, connectivity, pt_owners, attr );
05357       if( !s || dim != 3 || positions.size() || facets.size() )
05358       {
05359         new_lump = 0;
05360         goto CLEANUP_LUMP_FROM_ATTRIB;
05361       }
05362       
05363       new_lump = new PartitionLump( first_lump );
05364 
05365         // Get list of bounding co-surfaces from attrib data
05366       int j = connectivity.size();
05367       while( j > 0 )
05368       {
05369         int shell = connectivity.get_and_step();
05370         j--;
05371         PartitionShell* new_shell = new PartitionShell();
05372         new_lump->add(new_shell);
05373         while( shell-- )
05374         {
05375           int set_id = connectivity.get_and_step();
05376           int ent_id = connectivity.get_and_step();
05377           j -= 2;
05378           
05379           CubitSense sense = CUBIT_FORWARD;
05380           if ( ent_id < 0 )
05381           {
05382             ent_id = -ent_id;
05383             sense = CUBIT_REVERSED;
05384           }
05385 
05386           ent = entity_from_id( set_id, ent_id, first_lump->sub_entity_set() );
05387           PartitionSurface* surf = dynamic_cast<PartitionSurface*>(ent);
05388           if(!surf)
05389             goto CLEANUP_LUMP_FROM_ATTRIB;
05390 
05391           PartitionCoSurf* new_cosurf = new PartitionCoSurf(sense);
05392           surf->add(new_cosurf);
05393           new_shell->add(new_cosurf);
05394         }
05395       }
05396 
05397       new_lump->sub_entity_set().set_id( new_lump, id );
05398       new_lump = 0;  // we succeeded with this one, so don't try to 
05399                      // destroy it if we fail before creating the next.
05400     }
05401     
05402     result = CUBIT_SUCCESS;
05403   }
05404   
05405 CLEANUP_LUMP_FROM_ATTRIB:
05406 
05407   if( new_lump ) // created a lump but didn't successfully complete it
05408   {
05409     PartitionShell* shell = 0;
05410     while ( shell )
05411     {
05412       new_lump->remove(shell);
05413       shell->remove_all_surfaces();
05414       PartitionShell* old_shell = shell;
05415       shell = new_lump->next_shell(shell);
05416       delete old_shell;
05417     }
05418   }
05419   
05420   DLIList<PartitionEntity*> lump_list;
05421   if( first_lump )
05422   {
05423       // Get list of other lumps created
05424     first_lump->sub_entity_set().get_sub_entities( lump_list );
05425     lump_list.move_to(first_lump);
05426     assert( lump_list.get() == first_lump );
05427     lump_list.extract();
05428     
05429       // Destroy first_lump (it is the union of all the partitions)
05430     DLIList<PartitionSurface*> surfaces;
05431     PartitionShell* shell = 0;
05432     while ( shell )
05433     {
05434       first_lump->remove(shell);
05435       shell->remove_all_surfaces( &surfaces );
05436       PartitionShell* old_shell = shell;
05437       shell = first_lump->next_shell(shell);
05438       delete old_shell;
05439       while( surfaces.size() )
05440       {
05441         SubSurface* surf = dynamic_cast<SubSurface*>(surfaces.pop());
05442         if ( surf && !surf->next_co_surface(0) && 
05443              !surf->sub_entity_set().has_lower_order() )
05444           restore_surface( surf );
05445       }
05446     }
05447     delete first_lump;
05448   }
05449   
05450     // destroy any unused split geometry
05451   new_geom.reset();
05452   while( new_geom.size() )
05453   {
05454     PartitionEntity* ent = new_geom.pop();
05455     if( PartitionPoint* pt = dynamic_cast<PartitionPoint*>(ent) )
05456     {
05457       if( !pt->next_curve(0) )
05458         delete pt;
05459     }
05460     else if( PartitionCurve* curve = dynamic_cast<PartitionCurve*>(ent) )
05461     {
05462       if( !curve->next_coedge(0) )
05463         delete curve;
05464     }
05465     else if( PartitionSurface* surf = dynamic_cast<PartitionSurface*>(ent) )
05466     {
05467       if( !surf->next_co_surface(0) )
05468         destroy_surface( surf );
05469     }
05470   }
05471   
05472     // if there are any remaining partitions of the volume,
05473     // compress the ID space
05474   if ( lump_list.size() )
05475   {
05476     lump_list.get()->sub_entity_set().renumerate( max_id + 1, true );
05477   }
05478   
05479   if (!result)
05480     PRINT_ERROR("Error restoring volume partitions from attributes.\n");
05481     
05482   return result;
05483 }  
05484 
05485       
05486 
05487 //-------------------------------------------------------------------------
05488 // Purpose       : Save partition geometry
05489 //
05490 // Special Notes : 
05491 //
05492 // Creator       : Jason Kraftcheck
05493 //
05494 // Creation Date : 02/23/03
05495 //-------------------------------------------------------------------------
05496 CubitStatus PartitionEngine::export_geometry( DLIList<TopologyBridge*>& list )
05497 {
05498   int i;
05499   CubitStatus result = CUBIT_SUCCESS;
05500 
05501   if ( CGMApp::instance()->attrib_manager()->auto_update_flag(CA_PARTITION_VG) &&
05502        CGMApp::instance()->attrib_manager()->auto_write_flag(CA_PARTITION_VG) )
05503   {
05504 
05505       // Get all child topology to export
05506 
05507     DLIList<Curve*> curve_list;
05508     DLIList<Surface*> surface_list;
05509     DLIList<Lump*> lump_list;
05510     DLIList<BodySM*> body_list;
05511     DLIList<TopologyBridge*> bridge_list, temp_list, coe_curves(1), surf_curves;
05512 
05513     CAST_LIST( list, curve_list, Curve );
05514     CAST_LIST( list, surface_list, Surface );
05515     CAST_LIST( list, lump_list, Lump );
05516     CAST_LIST( list, body_list, BodySM );
05517 
05518     for( i = body_list.size(); i--; )
05519     {
05520       BodySM* body = body_list.get_and_step();
05521       body->get_children( bridge_list, true, layer() );
05522       while( bridge_list.size() )
05523         lump_list.append( dynamic_cast<Lump*>(bridge_list.pop()) );
05524     }
05525 
05526     for( i = lump_list.size(); i--; )
05527     {
05528       Lump* lump = lump_list.get_and_step();
05529       lump->get_children( bridge_list, true, layer() );
05530       while( bridge_list.size() )
05531       {
05532         bridge_list.pop()->get_children( temp_list, true, layer() );
05533         while( temp_list.size() )
05534           surface_list.append( dynamic_cast<Surface*>(temp_list.pop()) );
05535       }
05536     }
05537 
05538     for( i = surface_list.size(); i--; )
05539     {
05540       Surface* surf = surface_list.get_and_step();
05541       surf->get_children( bridge_list, true, layer() );
05542       while( bridge_list.size() )
05543       {
05544         bridge_list.pop()->get_children( temp_list, true, layer() );
05545         while( temp_list.size() )
05546         {
05547           temp_list.pop()->get_children_virt( coe_curves );
05548           assert(coe_curves.size() == 1);
05549           surf_curves.append(coe_curves.pop());
05550         }
05551       }
05552       surf_curves.uniquify_ordered();
05553       while( surf_curves.size() )
05554         curve_list.append( dynamic_cast<Curve*>(surf_curves.pop()) );
05555     }
05556 
05557 
05558       // save curve partitions
05559 
05560     DLIList<SubEntitySet*> set_list;
05561     for( i = curve_list.size(); i--; )
05562     {
05563       SubCurve* curve = dynamic_cast<SubCurve*>(curve_list.get_and_step());
05564       if( curve )
05565         set_list.append( &(curve->sub_entity_set()) );
05566     }
05567     set_list.uniquify_ordered();
05568     for( i = set_list.size(); i--; )
05569       if( ! set_list.get_and_step()->save_geometry() )
05570         result = CUBIT_FAILURE;
05571 
05572 
05573       // save surface partitions
05574 
05575     set_list.clean_out();
05576     for( i = surface_list.size(); i--; )
05577     {
05578       SubSurface* surf = dynamic_cast<SubSurface*>(surface_list.get_and_step());
05579       if( surf )
05580         set_list.append( &(surf->sub_entity_set()) );
05581     }
05582     set_list.uniquify_ordered();
05583     for( i = set_list.size(); i--; )
05584       if( ! set_list.get_and_step()->save_geometry() )
05585         result = CUBIT_FAILURE;
05586 
05587 
05588       // save volume partitions
05589 
05590     set_list.clean_out();
05591     for( i = lump_list.size(); i--; )
05592     {
05593       PartitionLump* lump = dynamic_cast<PartitionLump*>(lump_list.get_and_step());
05594       if( lump )
05595         set_list.append( &(lump->sub_entity_set()) );
05596     }
05597     set_list.uniquify_ordered();
05598     for( i = set_list.size(); i--; )
05599       if( ! set_list.get_and_step()->save_geometry() )
05600         result = CUBIT_FAILURE;
05601   }
05602     
05603     // replace partitions in passed list with the real
05604     // entities they partition
05605   
05606   PartitionEntity* p_ent = 0; 
05607   list.last() ;
05608   for ( i = list.size(); i--; )
05609   {
05610     if( (p_ent = dynamic_cast<PartitionEntity*>(list.step_and_get())) )
05611     {
05612       if( list.is_in_list(p_ent->partitioned_entity()) )
05613         list.change_to(0);
05614       else
05615         list.change_to(p_ent->partitioned_entity());
05616     }
05617   }
05618   list.remove_all_with_value(0);
05619   
05620   return result;
05621 }
05622 
05623 
05624 //-------------------------------------------------------------------------
05625 // Purpose       : Restore form attributes
05626 //
05627 // Special Notes : 
05628 //
05629 // Creator       : Jason Kraftcheck
05630 //
05631 // Creation Date : 01/23/03
05632 //-------------------------------------------------------------------------
05633 CubitStatus PartitionEngine::import_geometry( DLIList<TopologyBridge*>& list )
05634 {
05635   int i;
05636   CubitStatus result = CUBIT_SUCCESS;
05637   
05638   DLIList<Curve*> curve_list, temp_curves;
05639   DLIList<Surface*> surface_list, temp_surfaces;
05640   DLIList<Lump*> lump_list, temp_lumps;
05641   DLIList<BodySM*> body_list;
05642   
05643   CAST_LIST( list, curve_list, Curve );
05644   CAST_LIST( list, surface_list, Surface );
05645   CAST_LIST( list, lump_list, Lump );
05646   CAST_LIST( list, body_list, BodySM );
05647   
05648   for( i = body_list.size(); i--; )
05649   {
05650     temp_lumps.clean_out();
05651     body_list.get_and_step()->lumps( temp_lumps );
05652     lump_list += temp_lumps;
05653   }
05654   
05655   for( i = lump_list.size(); i--; )
05656   {
05657     temp_surfaces.clean_out();
05658     lump_list.get_and_step()->surfaces( temp_surfaces );
05659     surface_list += temp_surfaces;
05660   }
05661   
05662   for( i = surface_list.size(); i--; )
05663   {
05664     temp_curves.clean_out();
05665     surface_list.get_and_step()->curves( temp_curves );
05666     curve_list += temp_curves;
05667   }
05668   
05669   
05670   if ( CGMApp::instance()->attrib_manager()->auto_actuate_flag(CA_PARTITION_VG) &&
05671        CGMApp::instance()->attrib_manager()->auto_read_flag(CA_PARTITION_VG) )
05672   {
05673   
05674     curve_list.uniquify_ordered();
05675     for( i = curve_list.size(); i--; )
05676       if( ! restore_from_attrib( curve_list.get_and_step() ) )
05677         result = CUBIT_FAILURE;
05678 
05679     surface_list.uniquify_ordered();
05680     for( i = surface_list.size(); i--; )
05681       if( ! restore_from_attrib( surface_list.get_and_step() ) )
05682         result = CUBIT_FAILURE;
05683 
05684     lump_list.uniquify_ordered();
05685     for( i = lump_list.size(); i--; )
05686       if( ! restore_from_attrib( lump_list.get_and_step() ) )
05687         result = CUBIT_FAILURE;
05688 
05689       // update imported list
05690     list.last();
05691     DLIList<PartitionEntity*> entity_list;
05692     DLIList<TopologyBridge*> temp_list;
05693     for( i = list.size(); i--; )
05694     {
05695       TopologyBridge* bridge = list.step_and_get();
05696       SubEntitySet* set = dynamic_cast<SubEntitySet*>(bridge->owner());
05697       if( !set ) continue;
05698 
05699       entity_list.clean_out();
05700       temp_list.clean_out();
05701       set->get_sub_entities( entity_list );
05702       CAST_LIST( entity_list, temp_list, TopologyBridge );
05703 
05704       temp_list.reset();
05705       list.change_to( temp_list.get_and_step() );
05706       for( int j = temp_list.size(); j > 1; j-- )
05707         list.append( temp_list.get_and_step() );
05708     }
05709   }
05710   else
05711   {
05712     curve_list.uniquify_ordered();
05713     surface_list.uniquify_ordered();
05714     lump_list.uniquify_ordered();
05715     
05716     DLIList<TopologyBridge*> point_list(curve_list.size()*2), tmp_points(2);
05717     for ( i = curve_list.size(); i--; )
05718     {
05719       tmp_points.clean_out();
05720       curve_list.get()->get_children(tmp_points);
05721       point_list += tmp_points;
05722       SubEntitySet::strip_attributes( curve_list.get_and_step() );
05723     }
05724     point_list.uniquify_ordered();
05725     for ( i = point_list.size(); i--; )
05726       SubEntitySet::strip_attributes( point_list.get_and_step() );
05727     for ( i = surface_list.size(); i--; )
05728       SubEntitySet::strip_attributes( surface_list.get_and_step() );
05729     for ( i = lump_list.size(); i--; )
05730       SubEntitySet::strip_attributes( lump_list.get_and_step() );
05731   }
05732     
05733   return result;
05734 }
05735 /*
05736 void PartitionEngine::destroy_facet( CubitFacetData* facet )
05737 {
05738   int i;
05739 
05740   for( i = 0; i < 3; i++ )
05741   {
05742     CubitFacetEdgeData* edge = dynamic_cast<CubitFacetEdgeData*>(facet->edge(i));
05743     if( edge )
05744     {
05745       facet->edge(0, i);
05746       if( edge->number_tris() == 0 )
05747         delete edge;
05748     }
05749   }
05750 
05751   for( i = 0; i < 3; i++ )
05752   {
05753     CubitPointData* point = dynamic_cast<CubitPointData*>(facet->point(0));
05754     assert(point);
05755     point->remove_facet( facet );
05756     if( point->num_adj_facets() == 0 )
05757       delete point;
05758   }
05759   
05760   delete facet;
05761 }
05762 */
05763 //-------------------------------------------------------------------------
05764 // Purpose       : Core functionality of make_body( X* ) methods.
05765 //
05766 // Special Notes : 
05767 //
05768 // Creator       : Jason Kraftcheck
05769 //
05770 // Creation Date : 02/23/03
05771 //-------------------------------------------------------------------------
05772 PartitionBody* PartitionEngine::make_body_internal( TopologyBridge* bridge )
05773 {
05774     // query topology for BodySM
05775   DLIList<TopologyBridge*> list;
05776   BodySM* body;
05777   while( !(body = dynamic_cast<BodySM*>(bridge)) )
05778   {
05779     list.clean_out();
05780     bridge->get_parents_virt(list);
05781     if( !list.size() )
05782       return 0;
05783     bridge = list.get();
05784   }
05785   
05786   SubEntitySet* set = dynamic_cast<SubEntitySet*>(body->owner());
05787   if( set )
05788     return set->body();
05789   
05790   PartitionBody* result = new PartitionBody(body);
05791   if( body->owner() )
05792     body->owner()->swap_bridge( body, result, false );
05793   body->owner( &(result->sub_entity_set()) );
05794   return result;
05795 }
05796 
05797 //-------------------------------------------------------------------------
05798 // Purpose       : Find or make an owning bodySM
05799 //
05800 // Special Notes : 
05801 //
05802 // Creator       : Jason Kraftcheck
05803 //
05804 // Creation Date : 02/23/03
05805 //-------------------------------------------------------------------------
05806 PartitionBody* PartitionEngine::make_body( PartitionLump* lump )
05807 {
05808   if( lump->get_body() )
05809     return lump->get_body();
05810   
05811   return make_body_internal( lump );
05812 }
05813 
05814 //-------------------------------------------------------------------------
05815 // Purpose       : Find or make an owning bodySM
05816 //
05817 // Special Notes : 
05818 //
05819 // Creator       : Jason Kraftcheck
05820 //
05821 // Creation Date : 02/23/03
05822 //-------------------------------------------------------------------------
05823 PartitionBody* PartitionEngine::make_body( PartitionSurface* surf )
05824 {
05825   if( surf->sub_entity_set().body() )
05826     return surf->sub_entity_set().body();
05827     
05828   if( surf->next_co_surface(0) )
05829     return make_body(surf->next_co_surface(0)->get_shell()->get_lump());
05830   
05831   return make_body_internal(surf);
05832 }
05833 
05834 //-------------------------------------------------------------------------
05835 // Purpose       : Find or make an owning bodySM
05836 //
05837 // Special Notes : 
05838 //
05839 // Creator       : Jason Kraftcheck
05840 //
05841 // Creation Date : 02/23/03
05842 //-------------------------------------------------------------------------
05843 PartitionBody* PartitionEngine::make_body( PartitionCurve* curve )
05844 {
05845   if( curve->sub_entity_set().body() )
05846     return curve->sub_entity_set().body();
05847     
05848   PartitionCoEdge* coedge = 0;
05849   while( (coedge = curve->next_coedge(coedge)) )
05850     if( coedge->get_loop() )
05851       return make_body(coedge->get_loop()->get_surface());
05852   
05853   return make_body_internal(curve);
05854 }
05855  
05856 //-------------------------------------------------------------------------
05857 // Purpose       : Find or make an owning bodySM
05858 //
05859 // Special Notes : 
05860 //
05861 // Creator       : Jason Kraftcheck
05862 //
05863 // Creation Date : 02/23/03
05864 //-------------------------------------------------------------------------
05865 PartitionBody* PartitionEngine::make_body( PartitionPoint* pt )
05866 {
05867   if( pt->sub_entity_set().body() )
05868     return pt->sub_entity_set().body();
05869     
05870   if( pt->next_curve(0) )
05871     return make_body(pt->next_curve(0));
05872  
05873   return make_body_internal(pt);
05874 }
05875 static CubitStatus get_edge_replacements(
05876                          std::vector<CubitFacetData*> &facet_list,
05877                          std::vector<CubitFacetEdgeData*> replace_edge_lists[3])
05878 {
05879   // first facet is the facet to replace
05880   // make sure more than one facet to replace the first
05881   assert(facet_list.size() > 2);
05882 
05883   // make sure the lists of replacement edges are empty
05884   assert(replace_edge_lists[0].size() == 0);
05885   assert(replace_edge_lists[1].size() == 0);
05886   assert(replace_edge_lists[2].size() == 0);
05887 
05888 
05889   CubitFacetData* p_dead = facet_list[0]; // facet to be replaced
05890 
05891   // look for edges on the facet that are owned by curves
05892   int i;
05893   //int replace_edge = 0;
05894 
05895   // get the edges
05896   CubitFacetEdgeData *edges[3];
05897   for (i=0; i<3; i++)
05898   {
05899     edges[i] = CAST_TO(p_dead->edge(i), CubitFacetEdgeData);
05900     assert(edges[i] != NULL);
05901   }
05902 
05903   PartitionEntity *p_owner;
05904   PartitionCurve *p_curve;
05905 
05906   // see if any are owned by a curve
05907   CubitBoolean b_boundary = CUBIT_FALSE;
05908   for (i=0; i<3 && !b_boundary; i++)
05909   {
05910     p_owner = TDVGFacetOwner::get(edges[i]);
05911     p_curve = CAST_TO(p_owner, PartitionCurve);
05912     if (p_curve)
05913       b_boundary = CUBIT_TRUE;
05914   }
05915 
05916   // if the facet has an edge on a curve, replace the edge with the edges of the
05917   // replacement facets and split the facet on the adjacent surface.
05918   if (b_boundary)
05919   {
05920     // make a list with just the new facets -- skip the first facet
05921     DLIList<CubitFacet*> new_facets(facet_list.size() - 1);
05922     for (unsigned u = 1; u < facet_list.size(); u++)
05923       new_facets.append(facet_list[u]);
05924 
05925     // get a point edge chain around the boundary of the replacement facets
05926     DLIList<FacetEntity*> point_edge_chain;
05927     FacetDataUtil::ordered_point_edge_bdry(new_facets, point_edge_chain);
05928 
05929     // for each edge on a curve get corresponding points and edges from the
05930     // replacement facets
05931     //std::vector<CubitFacetEdgeData*>::iterator eitor;
05932     for (i=0; i<3; i++)
05933     {
05934       p_owner = TDVGFacetOwner::get(edges[i]);
05935       p_curve = CAST_TO(p_owner, PartitionCurve);
05936       if (p_curve)
05937       {
05938         // fill the replacement list for this edge
05939         // add the edge to be replaced first
05940         //eitor = replace_edge_lists[i].begin();
05941 
05942         // get the points from the edge of the dead facet - in the correct order
05943         CubitPoint* pt1;
05944         CubitPoint* pt2;
05945 
05946         p_dead->get_edge_pts(i, pt1, pt2);
05947 
05948         // get the corresponding chain of points and edges from the replacement facets
05949         DLIList<FacetEntity*> replacement_chain;
05950         CubitStatus res = FacetDataUtil::partial_chain(point_edge_chain,
05951                                          pt1, pt2, replacement_chain);
05952         if (CUBIT_FAILURE == res)
05953           return CUBIT_FAILURE;
05954 
05955         // there should be an odd number of list entries, since it includes points
05956         // and edges, beginning and ending with a point
05957         assert( (replacement_chain.size() % 2) == 1 );
05958 
05959         // if only one replacement edge, it should be the same edge
05960         replacement_chain.reset();
05961         if (replacement_chain.size() == 3)
05962         {
05963           assert(replacement_chain.next(1) == edges[i]);
05964         }
05965         else
05966         {
05967           // add the replacement edges to the list - edge to replace first
05968           //*eitor++ = edges[i];
05969           replace_edge_lists[i].push_back(edges[i]);
05970           int j;
05971           CubitFacetEdgeData* p_edge;
05972           for (j=1; j<replacement_chain.size(); j+=2)
05973           {
05974             //replacement_chain.step();
05975             p_edge = CAST_TO(replacement_chain.next(j), CubitFacetEdgeData);
05976             assert(p_edge != NULL);
05977             //*eitor++ = p_edge;
05978             replace_edge_lists[i].push_back(p_edge);
05979           }
05980         }
05981       }
05982     }
05983   }
05984 
05985   return CUBIT_SUCCESS;
05986 }
05987 
05988 //-------------------------------------------------------------------------
05989 // Purpose       : clean up for deleted geometry
05990 //
05991 // Special Notes : 
05992 //
05993 // Creator       : Jason Kraftcheck
05994 //
05995 // Creation Date : 04/03/03
05996 //-------------------------------------------------------------------------
05997 CubitStatus PartitionEngine::delete_solid_model_entities( 
05998                                 PartitionBody* body, BodySM*& real_body )
05999 {
06000   real_body = body->real_body();
06001   body->destroy_all_children();
06002   return CUBIT_SUCCESS;
06003 }
06004 
06005 CubitStatus PartitionEngine::delete_solid_model_entities(
06006                                 PartitionSurface* surf, 
06007                                 Surface*& real_surf )
06008 {
06009   DLIList<TopologyBridge*> parents(0);
06010   surf->get_parents_virt(parents);
06011   if ( parents.size() )
06012     return CUBIT_FAILURE;
06013   
06014   real_surf = 0;
06015   if ( !surf->sub_entity_set().has_multiple_sub_entities() )
06016     real_surf = dynamic_cast<Surface*>(surf->partitioned_entity());
06017   destroy_surface(surf);
06018   return CUBIT_SUCCESS;
06019 }
06020 
06021 CubitStatus PartitionEngine::delete_solid_model_entities(
06022                                 PartitionCurve* curve,
06023                                 Curve*& real_curve )
06024 {
06025   if( curve->next_coedge(0) )
06026     return CUBIT_FAILURE;
06027     
06028   real_curve = 0;
06029   if ( !curve->sub_entity_set().has_multiple_sub_entities() )
06030     real_curve = dynamic_cast<Curve*>(curve->partitioned_entity());
06031   PartitionPoint* start = curve->start_point();
06032   PartitionPoint* end = curve->end_point();
06033   delete curve;
06034   if ( start->num_curves() == 0 )
06035     delete start;
06036   if ( end->num_curves() == 0 )
06037     delete end;
06038   return CUBIT_SUCCESS;
06039 }
06040 
06041 CubitStatus PartitionEngine::translate( PartitionEntity* ent, 
06042                                         const CubitVector& delta )
06043 {
06044   GeometryEntity* geom = dynamic_cast<GeometryEntity*>(ent->partitioned_entity());
06045   if (!geom->get_geometry_query_engine()->translate( geom, delta ))
06046     return CUBIT_FAILURE;
06047   
06048   CubitTransformMatrix xform;
06049   xform.translate( delta );
06050   notify_transform_internal( geom, xform );
06051   return CUBIT_SUCCESS;
06052 }
06053   
06054 CubitStatus PartitionEngine::rotate( PartitionEntity* ent, 
06055                                      const CubitVector& axis, 
06056                                      double degrees )
06057 {
06058   GeometryEntity* geom = dynamic_cast<GeometryEntity*>(ent->partitioned_entity());
06059   if (!geom->get_geometry_query_engine()->rotate( geom, axis, degrees ))
06060     return CUBIT_FAILURE;
06061   
06062   CubitTransformMatrix xform;
06063   xform.rotate( degrees, axis );
06064   notify_transform_internal( geom, xform );
06065   return CUBIT_SUCCESS;
06066 }
06067 
06068 CubitStatus PartitionEngine::scale( PartitionEntity* ent, 
06069                                     const CubitVector& factors )
06070 {
06071   GeometryEntity* geom = dynamic_cast<GeometryEntity*>(ent->partitioned_entity());
06072   if (!geom->get_geometry_query_engine()->scale( geom, factors ))
06073     return CUBIT_FAILURE;
06074   
06075   CubitTransformMatrix xform;
06076   xform.scale_about_origin( factors );
06077   notify_transform_internal( geom, xform );
06078   return CUBIT_SUCCESS;
06079 }
06080 
06081 CubitStatus PartitionEngine::reflect( PartitionEntity* ent, 
06082                                       const CubitVector& axis )
06083 {
06084   GeometryEntity* geom = dynamic_cast<GeometryEntity*>(ent->partitioned_entity());
06085   if (!geom->get_geometry_query_engine()->reflect( geom, axis ))
06086     return CUBIT_FAILURE;
06087   
06088   CubitTransformMatrix xform;
06089   xform.reflect( axis );
06090   notify_transform_internal( geom, xform );
06091   return CUBIT_SUCCESS;
06092 }
06093 
06094 CubitStatus PartitionEngine::translate( PartitionBody* ent, 
06095                                         const CubitVector& delta )
06096 {
06097   BodySM* body = ent->real_body();
06098   if (!body->get_geometry_query_engine()->translate( body, delta ))
06099     return CUBIT_FAILURE;
06100   
06101   CubitTransformMatrix xform;
06102   xform.translate( delta );
06103   notify_transform_internal( ent, xform );
06104   return CUBIT_SUCCESS;
06105 }
06106 
06107 CubitStatus PartitionEngine::rotate( PartitionBody* ent, 
06108                                      const CubitVector& axis, 
06109                                      double degrees )
06110 {
06111   BodySM* body = ent->real_body();
06112   if (!body->get_geometry_query_engine()->rotate( body, axis, degrees ))
06113     return CUBIT_FAILURE;
06114   
06115   CubitTransformMatrix xform;
06116   xform.rotate( degrees, axis );
06117   notify_transform_internal( ent, xform );
06118   return CUBIT_SUCCESS;
06119 }
06120 
06121 CubitStatus PartitionEngine::scale( PartitionBody* ent, 
06122                                     const CubitVector& factors )
06123 {
06124   BodySM* body = ent->real_body();
06125 
06126   if( factors.x() != factors.y() ||
06127       factors.y() != factors.z() ||
06128       factors.x() != factors.z() )
06129   {
06130     GeometryModifyEngine *tmp_engine = GeometryModifyTool::instance()->get_engine( body );
06131     tmp_engine->scale( body, factors );  
06132   }
06133   else if(!body->get_geometry_query_engine()->scale( body, factors ))
06134     return CUBIT_FAILURE;
06135   
06136   CubitTransformMatrix xform;
06137   xform.scale_about_origin( factors );
06138   notify_transform_internal( ent, xform );
06139   return CUBIT_SUCCESS;
06140 }
06141 
06142 CubitStatus PartitionEngine::reflect( PartitionBody* ent, 
06143                                       const CubitVector& axis )
06144 {
06145   BodySM* body = ent->real_body();
06146   if (!body->get_geometry_query_engine()->reflect( body, axis ))
06147     return CUBIT_FAILURE;
06148   
06149   CubitTransformMatrix xform;
06150   xform.reflect( axis );
06151   notify_transform_internal( ent, xform );
06152   return CUBIT_SUCCESS;
06153 }
06154 
06155 CubitStatus PartitionEngine::restore_transform( PartitionBody* ent )
06156 {
06157   BodySM* body = ent->real_body();
06158   CubitTransformMatrix xform;
06159   body->get_transforms( xform );
06160   if (!body->get_geometry_query_engine()->restore_transform( body ))
06161     return CUBIT_FAILURE;
06162   
06163   notify_transform_internal( ent, xform );
06164   return CUBIT_SUCCESS;
06165 }
06166 
06167 CubitStatus PartitionEngine::notify_transform( TopologyBridge* ,
06168                                                const CubitTransformMatrix&  )
06169 {
06170   return CUBIT_SUCCESS;
06171 }
06172 
06173 CubitStatus PartitionEngine::notify_transform_internal( TopologyBridge* ent,
06174                                                const CubitTransformMatrix& xform )
06175 {
06176   int i;
06177   DLIList<Surface*> surfaces;
06178   DLIList<Curve*> curves;
06179   DLIList<TBPoint*> points;
06180   
06181   if (PartitionBody* body = dynamic_cast<PartitionBody*>(ent))
06182   {
06183     DLIList<PartitionEntity*> ent_list;
06184     body->get_all_children( ent_list );
06185     CAST_LIST( ent_list, surfaces, PartitionSurface );
06186     CAST_LIST( ent_list, curves, PartitionCurve );
06187     CAST_LIST( ent_list, points, PartitionPoint );
06188   }
06189   else
06190   {
06191     if(BodySM* bodysm = dynamic_cast<BodySM*>(ent))
06192     {
06193       DLIList<TopologyBridge*> lumps, shells, tmp_surfs;
06194       bodysm->get_children( lumps, true, layer() );
06195       while (lumps.size())
06196       {
06197         lumps.pop()->get_children( shells, true, layer() );
06198         while (shells.size())
06199         {
06200           tmp_surfs.clean_out();
06201           shells.pop()->get_children( tmp_surfs, true, layer() );
06202           while (tmp_surfs.size())
06203             surfaces.append( dynamic_cast<Surface*>(tmp_surfs.pop()) );
06204         }
06205       }
06206       surfaces.uniquify_ordered();
06207     }
06208     else if(Surface* surf = dynamic_cast<Surface*>(ent))
06209       surfaces.append( surf );
06210     else if(Curve* curv = dynamic_cast<Curve*>(ent))
06211       curves.append( curv );
06212     else if(TBPoint* point = dynamic_cast<TBPoint*>(ent))
06213       points.append( point );
06214 
06215     if (surfaces.size())
06216     {
06217       DLIList<TopologyBridge*> loops, coedges, tmp_curves;
06218       for (i = surfaces.size(); i--; )
06219       {
06220         surfaces.get_and_step()->get_children( loops, true, layer() );
06221         while( loops.size() )
06222         {
06223           loops.pop()->get_children( coedges, true, layer() );
06224           while (coedges.size())
06225           {
06226             coedges.pop()->get_children( tmp_curves, true, layer() );
06227             while (tmp_curves.size())
06228               curves.append( dynamic_cast<Curve*>(tmp_curves.pop()) );
06229           }
06230         }
06231       }
06232       curves.uniquify_ordered();
06233     }
06234     
06235     if (curves.size())
06236     {
06237       DLIList<TopologyBridge*> tmp_points;
06238       for (i = curves.size(); i--; )
06239       {
06240         curves.get_and_step()->get_children( tmp_points, true, layer() );
06241         while (tmp_points.size())
06242           points.append( dynamic_cast<TBPoint*>(tmp_points.pop()) );
06243       }
06244       points.uniquify_ordered();
06245     }
06246   }
06247 
06248   // see if the transformation is a reflection
06249   double det = xform.sub_matrix( 3, 3 ).determinant();
06250   bool reflection = det < 0.0;
06251 
06252   while (surfaces.size())
06253   {
06254     PartitionSurface* surf = dynamic_cast<PartitionSurface*>(surfaces.pop());
06255     if (surf)
06256     {
06257       surf->transform( xform );
06258     }
06259   }
06260 
06261   while (curves.size())
06262   {
06263     PartitionCurve* curv = dynamic_cast<PartitionCurve*>(curves.pop());
06264     if (curv)
06265     {
06266       curv->transform( xform );
06267 
06268       if (reflection)
06269       {
06270         // PartitionSurface transform above reverses loops and coedges on Partition
06271         // surfaces.  Need to reverse sense of PartitionCoEdges in loops on non
06272         // partition surfaces
06273         // reverse the coedges of this curve
06274         PartitionCoEdge* p_coedge = 0;
06275         while ((p_coedge = curv->next_coedge(p_coedge)) != NULL)
06276         {
06277           TopologyBridge* loop_bridge = p_coedge->find_parent_loop();
06278           if (loop_bridge)
06279           {
06280             if (0 == dynamic_cast<PartitionLoop*>(loop_bridge))
06281             {
06282               p_coedge->reverse_sense();
06283             }
06284           }
06285         }
06286       }
06287     }
06288   }
06289   
06290   while (points.size())
06291   {
06292     PartitionPoint* pnt = dynamic_cast<PartitionPoint*>(points.pop());
06293     if (pnt)
06294       pnt->transform( xform );
06295   }
06296 
06297   return CUBIT_SUCCESS;
06298 }
06299 
06300 void PartitionEngine::remove_attributes( DLIList<TopologyBridge*> &list )
06301 {
06302   //for each SubEntitySet in map, change it's unique id to zero
06303   std::map<int,SubEntitySet*>::iterator itor = uniqueIdMap.begin();
06304   while( itor != uniqueIdMap.end() )
06305   {
06306     if(itor->second->get_entity())
06307     {
06308       SubEntitySet::strip_attributes( itor->second->get_entity() );
06309       itor->second->reset_unique_id();
06310     }
06311     itor++;
06312   }
06313 
06314   //clean out the map
06315   uniqueIdMap.clear();
06316 }
06317 
06318 void PartitionEngine::notify_deactivated (PartitionBody* body)
06319 {
06320 }
06321 void PartitionEngine::notify_deactivated(PartitionLump* vol)
06322 {
06323 }
06324 void PartitionEngine::add_to_deactivated_list(PartitionLump* vol)
06325 {
06326 }
06327 void PartitionEngine::add_to_deactivated_list(PartitionBody* body)
06328 {
06329 }
06330 void PartitionEngine::notify_deactivated (PartitionSurface* surface)
06331 {
06332 }
06333 void PartitionEngine::add_to_deactivated_list (PartitionSurface* surface)
06334 {
06335 }
06336 void PartitionEngine::notify_deactivated (PartitionCurve* curve)
06337 {
06338 }
06339 void PartitionEngine::add_to_deactivated_list (PartitionCurve* curve)
06340 {
06341 }
06342 void PartitionEngine::notify_deactivated (PartitionPoint* point)
06343 {
06344 }
06345 void PartitionEngine::add_to_deactivated_list (PartitionPoint* point)
06346 {
06347 }
06348 void PartitionEngine::clean_out_deactivated_geometry()
06349 {
06350 }
06351 void PartitionEngine::remove_modified(DLIList<Surface*> &all_surfs,
06352     DLIList<Curve*> &all_curves, DLIList<TBPoint*> &all_pts)
06353 {
06354 }
06355 
06356 void PartitionEngine::get_tbs_with_bridge_manager_as_owner( TopologyBridge *source_bridge, 
06357                                                             DLIList<TopologyBridge*> &tbs )
06358 {  
06359   BridgeManager* bm = dynamic_cast<BridgeManager*>(source_bridge->owner());
06360   if( bm )
06361   {
06362     tbs.append( source_bridge );
06363     return;
06364   }
06365 
06366   SubEntitySet* set = dynamic_cast<SubEntitySet*>(source_bridge->owner());
06367   if( !set ) 
06368     return;
06369 
06370   DLIList<PartitionEntity*> entity_list;
06371   set->get_sub_entities( entity_list );
06372   DLIList<TopologyBridge*> tb_list;
06373   CAST_LIST( entity_list, tb_list, TopologyBridge );
06374   
06375   while( tb_list.size() )
06376   {
06377     TopologyBridge *tb = tb_list.pop();
06378     if( tb->bridge_manager() )    
06379       tbs.append( tb );          
06380     else
06381     {  
06382       TBOwner *owner = tb->owner();
06383       TopologyBridge *tmp_tb = CAST_TO( owner, TopologyBridge );
06384       if( tmp_tb )
06385         tb_list.append( tmp_tb );
06386       else
06387       {
06388         CompositePoint *comp_pt = CAST_TO( tb, CompositePoint );
06389         if( comp_pt )
06390           CompositeEngine::instance().get_tbs_with_bridge_manager_as_owner( tb, tb_list );
06391         else
06392         {
06393           CompositeCurve *comp_curve = CAST_TO( tb, CompositeCurve );
06394           if( comp_curve )
06395             CompositeEngine::instance().get_tbs_with_bridge_manager_as_owner( tb, tb_list );
06396         }
06397       }
06398     }    
06399   }
06400 
06401   tbs.uniquify_ordered();
06402 
06403   return;
06404 }
06405   
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines