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