root/cgm/trunk/geom/virtual/CompositeEngine.cpp

Revision 1047, 201.2 KB (checked in by tautges, 2 years ago)

Changes from 10.2 to version sent by Kevin Pendley to Tim Tautges approximately
12/15/2006.

Line 
1#include <assert.h>
2
3#include "CompositeEngine.hpp"
4#include "PartitionEngine.hpp"
5
6#include "DLIList.hpp"
7#include "TDUniqueId.hpp"
8#include "CubitTransformMatrix.hpp"
9
10#include "CompositePoint.hpp"
11#include "CompositeCurve.hpp"
12#include "CompositeCoEdge.hpp"
13#include "CompositeLoop.hpp"
14#include "CompositeSurface.hpp"
15#include "CompositeShell.hpp"
16#include "CompositeLump.hpp"
17#include "CompositeBody.hpp"
18
19#include "PartitionPoint.hpp"
20#include "SegmentedCurve.hpp"
21
22#include "CADefines.hpp"
23
24#include "VGLoopTool.hpp"
25#include "Body.hpp"
26
27#include "GeometryQueryTool.hpp"
28
29typedef VGLoopTool<CompositeSurface,
30                   CompositeLoop,
31                   CompositeCoEdge,
32                   CompositeCurve,
33                   CompositePoint> CompLoopTool;
34
35CompositeEngine::~CompositeEngine() {}
36
37CompositeEngine& CompositeEngine::instance()
38{
39  static CompositeEngine* instance_ = new CompositeEngine();
40  return *instance_;
41}
42
43// This function goes through all of the curves and vertices and
44// removes any named attributes specified below.
45void CompositeEngine::remove_imprint_attributes_after_modify( DLIList<BodySM*> &old_sms,
46                                DLIList<BodySM*> &new_sms )
47{
48  int k, m, q, w, g, b, s, t;
49  CubitString name("IMPRINT_PREEXISTING");
50  DLIList<CubitString*> string_list;
51  string_list.append( &name );
52  CubitSimpleAttrib geom_attrib( &string_list, 0, 0 );
53
54  DLIList<BodySM*> all_sms = old_sms;
55  all_sms += new_sms;
56  DLIList<TopologyBridge*> top_bridges;
57  CAST_LIST_TO_PARENT(all_sms, top_bridges);
58  for(k=top_bridges.size(); k--;)
59  {
60    TopologyBridge *cur_body = top_bridges.get_and_step();
61    DLIList<TopologyBridge*> lumps;
62    cur_body->get_children_virt(lumps);
63    for(m=lumps.size(); m--;)
64    {
65      TopologyBridge *cur_lump = lumps.get_and_step();
66      DLIList<TopologyBridge*> shells;
67      cur_lump->get_children_virt(shells);
68      for(q=shells.size(); q--;)
69      {
70        TopologyBridge *cur_shell = shells.get_and_step();
71        DLIList<TopologyBridge*> surfaces;
72        cur_shell->get_children_virt(surfaces);
73        for(w=surfaces.size(); w--;)
74        {
75          TopologyBridge *cur_surface = surfaces.get_and_step();
76          DLIList<TopologyBridge*> loops;
77          cur_surface->get_children_virt(loops);
78          for(g=loops.size(); g--;)
79          {
80            TopologyBridge *cur_loop = loops.get_and_step();
81            DLIList<TopologyBridge*> coedges;
82            cur_loop->get_children_virt(coedges);
83            for(b=coedges.size(); b--;)
84            {
85              TopologyBridge *cur_coedge = coedges.get_and_step();
86              DLIList<TopologyBridge*> curves;
87              cur_coedge->get_children_virt(curves);
88              for(s=curves.size(); s--;)
89              {
90                TopologyBridge *cur_curve = curves.get_and_step();
91                DLIList<CubitSimpleAttrib*> list;
92                cur_curve->get_simple_attribute("IMPRINT_PREEXISTING",list);
93                if(list.size() != 0)
94                  cur_curve->remove_simple_attribute_virt(list.get());
95                DLIList<TopologyBridge*> pts;
96                cur_curve->get_children_virt(pts);
97                for(t=pts.size(); t--;)
98                {
99                  TopologyBridge *cur_pt = pts.get_and_step();
100                  list.clean_out();
101                  cur_pt->get_simple_attribute("IMPRINT_PREEXISTING",list);
102                  if(list.size() != 0)
103                    cur_pt->remove_simple_attribute_virt(list.get());
104                }
105              }
106            }
107          }
108        }
109      }
110    }
111  }
112}
113
114// This function pushes specified named attributes onto all curves
115// and vertices.
116void CompositeEngine::push_imprint_attributes_before_modify
117                     ( DLIList<BodySM*> &bodies )
118{
119  int k, m, q, w, g, b, s, t;
120  CubitString name("IMPRINT_PREEXISTING");
121  DLIList<CubitString*> string_list;
122  string_list.append( &name );
123  CubitSimpleAttrib geom_attrib( &string_list, 0, 0 );
124
125  DLIList<TopologyBridge*> top_bridges;
126  CAST_LIST_TO_PARENT(bodies, top_bridges);
127  for(k=top_bridges.size(); k--;)
128  {
129    TopologyBridge *cur_body = top_bridges.get_and_step();
130    DLIList<TopologyBridge*> lumps;
131    cur_body->get_children_virt(lumps);
132    for(m=lumps.size(); m--;)
133    {
134      TopologyBridge *cur_lump = lumps.get_and_step();
135      DLIList<TopologyBridge*> shells;
136      cur_lump->get_children_virt(shells);
137      for(q=shells.size(); q--;)
138      {
139        TopologyBridge *cur_shell = shells.get_and_step();
140        DLIList<TopologyBridge*> surfaces;
141        cur_shell->get_children_virt(surfaces);
142        for(w=surfaces.size(); w--;)
143        {
144          TopologyBridge *cur_surface = surfaces.get_and_step();
145          DLIList<TopologyBridge*> loops;
146          cur_surface->get_children_virt(loops);
147          for(g=loops.size(); g--;)
148          {
149            TopologyBridge *cur_loop = loops.get_and_step();
150            DLIList<TopologyBridge*> coedges;
151            cur_loop->get_children_virt(coedges);
152            for(b=coedges.size(); b--;)
153            {
154              TopologyBridge *cur_coedge = coedges.get_and_step();
155              DLIList<TopologyBridge*> curves;
156              cur_coedge->get_children_virt(curves);
157              for(s=curves.size(); s--;)
158              {
159                TopologyBridge *cur_curve = curves.get_and_step();
160                DLIList<CubitSimpleAttrib*> list;
161                cur_curve->get_simple_attribute("COMPOSITE_GEOM",list);
162                if(list.size() == 0)
163                  append_attrib( cur_curve, &geom_attrib );
164                DLIList<TopologyBridge*> pts;
165                cur_curve->get_children_virt(pts);
166                for(t=pts.size(); t--;)
167                {
168                  TopologyBridge *cur_pt = pts.get_and_step();
169                  list.clean_out();
170                  cur_pt->get_simple_attribute("COMPOSITE_GEOM",list);
171                  if(list.size() == 0)
172                    append_attrib( cur_pt, &geom_attrib );
173                }
174              }
175            }
176          }
177        }
178      }
179    }
180  }
181}
182
183// Function to apply/remove COMPOSITE_GEOM attributes as necessary based
184// on imprinting.
185void CompositeEngine::attribute_after_imprinting( DLIList<TopologyBridge*> &new_tbs,
186                                                    DLIList<TopologyBridge*> &att_tbs,
187                                                    DLIList<BodySM*> &new_sms,
188                                                        DLIList<Body*> &old_bodies)
189{
190  DLIList<TopologyBridge*> old_bridges(old_bodies.size());
191  DLIList<TopologyBridge*> new_bridges(new_sms.size());
192  DLIList<TopologyBridge*> all_bodies;
193  CAST_LIST(new_sms, new_bridges, TopologyBridge);
194
195  all_bodies = new_bridges;
196  int k, m, q, w, g, b, s, t;
197  for(k = old_bodies.size(); k>0; k--)
198  {
199    Body *body = old_bodies.get_and_step();
200    TopologyBridge *tb = body->bridge_manager()->topology_bridge();
201    if(tb)
202    {
203      old_bridges.append(tb);
204      all_bodies.append_unique(tb);
205    }
206  }
207
208  DLIList<DLIList<TopologyBridge*>*> lists_of_curves;
209  DLIList<DLIList<TopologyBridge*>*> lists_of_points;
210
211  // Get lists of curves and points for each body in the
212  // list all_bodies.
213  all_bodies.reset();
214  for(k=all_bodies.size(); k--;)
215  {
216    DLIList<TopologyBridge*> *new_curve_list = new DLIList<TopologyBridge*>;
217    DLIList<TopologyBridge*> *new_point_list = new DLIList<TopologyBridge*>;
218    lists_of_curves.append(new_curve_list);
219    lists_of_points.append(new_point_list);
220    TopologyBridge *cur_body = all_bodies.get_and_step();
221    DLIList<TopologyBridge*> lumps;
222    cur_body->get_children_virt(lumps);
223    for(m=lumps.size(); m--;)
224    {
225      TopologyBridge *cur_lump = lumps.get_and_step();
226      DLIList<TopologyBridge*> shells;
227      cur_lump->get_children_virt(shells);
228      for(q=shells.size(); q--;)
229      {
230        TopologyBridge *cur_shell = shells.get_and_step();
231        DLIList<TopologyBridge*> surfaces;
232        cur_shell->get_children_virt(surfaces);
233        for(w=surfaces.size(); w--;)
234        {
235          TopologyBridge *cur_surface = surfaces.get_and_step();
236          DLIList<TopologyBridge*> loops;
237          cur_surface->get_children_virt(loops);
238          for(g=loops.size(); g--;)
239          {
240            TopologyBridge *cur_loop = loops.get_and_step();
241            DLIList<TopologyBridge*> coedges;
242            cur_loop->get_children_virt(coedges);
243            for(b=coedges.size(); b--;)
244            {
245              TopologyBridge *cur_coedge = coedges.get_and_step();
246              DLIList<TopologyBridge*> curves;
247              cur_coedge->get_children_virt(curves);
248              for(s=curves.size(); s--;)
249              {
250                TopologyBridge *cur_curve = curves.get_and_step();
251                new_curve_list->append_unique(cur_curve);
252                DLIList<TopologyBridge*> pts;
253                cur_curve->get_children_virt(pts);
254                for(t=pts.size(); t--;)
255                {
256                  TopologyBridge *cur_pt = pts.get_and_step();
257                  new_point_list->append_unique(cur_pt);
258                }
259              }
260            }
261          }
262        }
263      }
264    }
265  }
266
267
268  int i, j, h;
269  CubitSense rel_sense;
270  double geom_factor = GeometryQueryTool::get_geometry_factor();
271
272  // This code will look at all of the topology bridges that have
273  // COMPOSITE_GEOM attributes on them and determine whether to
274  // keep these attributes, remove them, or pass them on to bridges
275  // on other volumes based on the expected results from the imprinting operation.
276
277  // Loop twice, once for the curves and then once for the points.
278  for(h=0; h<2; h++)
279  {
280    for(i=att_tbs.size(); i--;)
281    {
282      TopologyBridge *att_tb = att_tbs.get_and_step();
283      Curve *att_cur = dynamic_cast<Curve*>(att_tb);
284      Point *att_pt = dynamic_cast<Point*>(att_tb);
285      Curve *match_cur;
286      Point *match_pt;
287
288      // Force curves to be done first.
289      if(h==0 && att_cur)
290      {
291        match_cur = NULL;
292        CubitBox att_box = att_cur->bounding_box();
293
294        // First check the list of new bridges as the corresponding
295        // curve will often be there.
296        for(j=new_tbs.size(); !match_cur && j; j--)
297        {
298          TopologyBridge *new_tb = new_tbs.get_and_step();
299          Curve *new_cur = dynamic_cast<Curve*>(new_tb);
300          if(new_cur && new_cur != att_cur)
301          {
302            CubitBox new_box = new_cur->bounding_box();
303            if(att_box.overlap(GEOMETRY_RESABS, new_box))
304            {
305              if(this->about_spatially_equal(new_cur, att_cur, rel_sense, geom_factor, 0))
306              {
307                match_cur = new_cur;
308                process_curves_after_imprint(att_cur, new_cur, new_sms);
309              }
310            }
311          }
312        }
313
314        // If we didn't find a matching curve in the new bridge list
315        // look at all of the rest of the curves.
316        if(!match_cur)
317        {
318          BodySM *att_body = att_cur->bodysm();
319          all_bodies.reset();
320          lists_of_curves.reset();
321          for(j=all_bodies.size(); !match_cur && j; j--)
322          {
323            TopologyBridge *cur_body = all_bodies.get_and_step();
324            DLIList<TopologyBridge*> *curves = lists_of_curves.get_and_step();
325            BodySM *cur_bodysm = cur_body->bodysm();
326
327            // Don't look at curves from the same body.
328            if(att_body != cur_bodysm)
329            {
330              for(m=curves->size(); !match_cur && m; m--)
331              {
332                TopologyBridge *curtb = curves->get_and_step();
333                Curve *cur = dynamic_cast<Curve*>(curtb);
334                if(cur && cur != att_cur)
335                {
336                  CubitBox new_box = cur->bounding_box();
337                  if(att_box.overlap(GEOMETRY_RESABS, new_box))
338                  {
339                    if(this->about_spatially_equal(cur, att_cur, rel_sense, geom_factor, 0))
340                    {
341                      match_cur = cur;
342                      process_curves_after_imprint(att_cur, cur, new_sms);
343                    }
344                  }
345                }
346              }
347            }
348          }
349        }
350      }
351
352      // Force points to be done second.
353      else if(h==1 && att_pt)
354      {
355        match_pt = NULL;
356        CubitBox att_box = att_pt->bounding_box();
357
358        // First check the list of new bridges as the corresponding
359        // point will often be there.
360        for(j=new_tbs.size(); !match_pt && j; j--)
361        {
362          TopologyBridge *new_tb = new_tbs.get_and_step();
363          Point *new_pt = dynamic_cast<Point*>(new_tb);
364          if(new_pt && new_pt != att_pt)
365          {
366            CubitBox new_box = new_pt->bounding_box();
367            if(att_box.overlap(GEOMETRY_RESABS, new_box))
368            {
369              if(GeometryQueryTool::instance()->about_spatially_equal(new_pt->coordinates(), 
370                                    att_pt->coordinates(), geom_factor))
371              {
372                match_pt = new_pt;
373                process_points_after_imprint(att_pt, new_pt, new_sms);
374              }
375            }
376          }
377        }
378        // If we didn't find a matching point in the new bridge list
379        // look at all of the rest of the points.
380        if(!match_pt)
381        {
382          BodySM *att_body = att_pt->bodysm();
383          all_bodies.reset();
384          lists_of_points.reset();
385          for(j=all_bodies.size(); !match_pt && j; j--)
386          {
387            TopologyBridge *cur_body = all_bodies.get_and_step();
388            DLIList<TopologyBridge*> *points = lists_of_points.get_and_step();
389            BodySM *cur_bodysm = cur_body->bodysm();
390           
391            // Don't look at points from the same body.
392            if(att_body != cur_bodysm)
393            {
394              for(m=points->size(); !match_pt && m; m--)
395              {
396                TopologyBridge *curtb = points->get_and_step();
397                Point *pt = dynamic_cast<Point*>(curtb);
398                if(pt && pt != att_pt)
399                {
400                  CubitBox new_box = pt->bounding_box();
401                  if(att_box.overlap(GEOMETRY_RESABS, new_box))
402                  {
403                    if(GeometryQueryTool::instance()->about_spatially_equal(pt->coordinates(), 
404                                          att_pt->coordinates(), geom_factor))
405                    {
406                      match_pt = pt;
407                      process_points_after_imprint(att_pt, pt, new_sms);
408                    }
409                  }
410                }
411              }
412            }
413          }
414        }
415      }
416    }
417  }
418}
419
420void CompositeEngine::process_curves_after_imprint(Curve *att_cur, 
421                                                   Curve *other_cur,
422                                                   DLIList<BodySM*> &new_sms)
423{
424  DLIList<CubitSimpleAttrib*> list;
425
426  other_cur->get_simple_attribute("IMPRINT_PREEXISTING",list);
427  if(list.size() == 0)
428  {
429    // This is a new bridge created by imprinting this hidden bridge.  In
430    // this case we need to add a COMPOSITE_GEOM attribute to the new bridge
431    // so we don't see a resulting imprinted bridge from the hidden bridge.
432    list.clean_out();
433    att_cur->get_simple_attribute("COMPOSITE_GEOM",list);
434    other_cur->append_simple_attribute_virt(new CubitSimpleAttrib(list.get()));
435  }
436  else
437  {
438    // This bridge existed before the imprint operation.  Therefore it
439    // could also have a COMPOSITE_GEOM attribute on it.  Check this.
440    list.clean_out();
441    other_cur->get_simple_attribute("COMPOSITE_GEOM",list);
442    if(list.size() == 0)
443    {
444      // It doesn't have a COMPOSITE_GEOM attribute so we need to remove
445      // the COMPOSITE_GEOM from att_bridge because the hidden nature gets
446      // wiped out by the imprinting process.
447      att_cur->get_simple_attribute("COMPOSITE_GEOM",list);
448      att_cur->remove_simple_attribute_virt(list.get());
449      BodySM *bsm = att_cur->bodysm();
450      if(bsm)
451        new_sms.append_unique(bsm);
452      TBOwner *bridge_owner = att_cur->owner();
453      CompositeCurve *cc_bridge_owner = dynamic_cast<CompositeCurve*>(bridge_owner);
454      if(cc_bridge_owner)
455      {
456        TBOwner *cc_owner = cc_bridge_owner->owner();
457        HiddenEntitySet *hes = dynamic_cast<HiddenEntitySet*>(cc_owner);
458        if(hes)
459        {
460          CompositeSurface *cs = dynamic_cast<CompositeSurface*>(hes->owner());
461          if(cs)
462            cs->HadBridgeRemoved = 1;
463            // This is currently how we are notifying the owning CompositeSurface
464            // that it needs to be deactivated and rebuilt.  It really has
465            // nothing to do with the bridge being removed though.  Bad.
466        }
467      }
468    }
469    else
470    {
471      // This bridge was also hidden so do nothing.
472    }
473  }
474}
475
476void CompositeEngine::process_points_after_imprint(Point *att_pt, 
477                                                   Point *other_pt,
478                                                   DLIList<BodySM*> &new_sms)
479{
480  int i;
481  DLIList<CubitSimpleAttrib*> list;
482
483  other_pt->get_simple_attribute("IMPRINT_PREEXISTING",list);
484  if(list.size() == 0)
485  {
486    // This is a new bridge created by imprinting this hidden bridge.  In
487    // this case we need to add a COMPOSITE_GEOM attribute to the new bridge
488    // if possible so we don't see a resulting imprinted bridge from the hidden bridge.
489    int num_visible_curves = 0;
490    DLIList<TopologyBridge*> curves;
491    att_pt->get_parents_virt(curves);
492    for(i=curves.size(); i--;)
493    {
494      list.clean_out();
495      TopologyBridge *c = curves.get_and_step();
496      c->get_simple_attribute("COMPOSITE_GEOM", list);
497      if(list.size() == 0)
498        num_visible_curves++;
499    }
500    if(num_visible_curves > 2)
501    {
502      list.clean_out();
503      att_pt->get_simple_attribute("COMPOSITE_GEOM",list);
504      att_pt->remove_simple_attribute_virt(list.get());
505      BodySM *bsm = att_pt->bodysm();
506      if(bsm)
507        new_sms.append_unique(bsm);
508      TBOwner *bridge_owner = att_pt->owner();
509      CompositePoint *cp_bridge_owner = dynamic_cast<CompositePoint*>(bridge_owner);
510      if(cp_bridge_owner)
511      {
512        TBOwner *cp_owner = cp_bridge_owner->owner();
513        HiddenEntitySet *hes = dynamic_cast<HiddenEntitySet*>(cp_owner);
514        if(hes)
515        {
516          CompositeCurve *cc = dynamic_cast<CompositeCurve*>(hes->owner());
517          if(cc)
518            cc->HadBridgeRemoved = 1;
519            // This is currently how we are notifying the owning CompositeCurve
520            // that it needs to be deactivated and rebuilt.  It really has
521            // nothing to do with the bridge being removed though.  Bad.
522        }
523      }
524    }
525    else
526    {
527      list.clean_out();
528      att_pt->get_simple_attribute("COMPOSITE_GEOM",list);
529      other_pt->append_simple_attribute_virt(new CubitSimpleAttrib(list.get()));
530    }
531  }
532  else
533  {
534    // This bridge existed before the imprint operation.  Therefore it
535    // could also have a COMPOSITE_GEOM attribute on it.  Check this.
536    list.clean_out();
537    other_pt->get_simple_attribute("COMPOSITE_GEOM",list);
538    if(list.size() == 0)
539    {
540      // It doesn't have a COMPOSITE_GEOM attribute so we need to remove
541      // the COMPOSITE_GEOM from att_bridge because the hidden nature gets
542      // wiped out by the imprinting process.
543      att_pt->get_simple_attribute("COMPOSITE_GEOM",list);
544      att_pt->remove_simple_attribute_virt(list.get());
545      BodySM *bsm = att_pt->bodysm();
546      if(bsm)
547        new_sms.append_unique(bsm);
548      TBOwner *bridge_owner = att_pt->owner();
549      CompositePoint *cp_bridge_owner = dynamic_cast<CompositePoint*>(bridge_owner);
550      if(cp_bridge_owner)
551      {
552        TBOwner *cp_owner = cp_bridge_owner->owner();
553        HiddenEntitySet *hes = dynamic_cast<HiddenEntitySet*>(cp_owner);
554        if(hes)
555        {
556          CompositeCurve *cc = dynamic_cast<CompositeCurve*>(hes->owner());
557          if(cc)
558            cc->HadBridgeRemoved = 1;
559            // This is currently how we are notifying the owning CompositeCurve
560            // that it needs to be deactivated and rebuilt.  It really has
561            // nothing to do with the bridge being removed though.  Bad.
562        }
563      }
564    }
565    else
566    {
567      // This bridge was also hidden so do nothing.
568    }
569  }
570}
571
572// This is a copy of the function in MergeTool with the difference that it
573// accepts a layer flag to dictate at which level the topology is traversed
574// (solid modeler level or virtual level).
575CubitBoolean CompositeEngine::about_spatially_equal( Curve *curve_1, Curve *curve_2,
576                                               CubitSense &relative_sense, 
577                                               double tolerance_factor,
578                                               int layer)
579{
580  if( curve_1 == curve_2 )
581    return CUBIT_TRUE;
582
583  relative_sense = CUBIT_FORWARD;
584  const double ONE_THIRD = 1.0/3.0;
585
586  // Find the point 1/3 along curve_1
587  CubitVector test_point_1, test_point_2;
588  if( curve_1->position_from_fraction( ONE_THIRD, test_point_1 ) != CUBIT_SUCCESS )
589    return CUBIT_FALSE;
590
591  // See if the 1/3 point on curve_1 lies on curve_2
592  if ( curve_2->closest_point_trimmed(test_point_1, test_point_2)
593       != CUBIT_SUCCESS )
594  {
595    return CUBIT_FALSE;
596  }
597
598  if ( GeometryQueryTool::instance()->
599       about_spatially_equal(test_point_1, test_point_2, tolerance_factor )
600       != CUBIT_SUCCESS )
601  {
602    return CUBIT_FALSE;
603  }
604 
605  CubitVector tangent_1, tangent_2;
606  if( curve_1->closest_point(test_point_2, test_point_1, &tangent_1) != CUBIT_SUCCESS )
607    return CUBIT_FALSE;
608  if( curve_2->closest_point(test_point_1, test_point_2, &tangent_2) != CUBIT_SUCCESS )
609    return CUBIT_FALSE;
610
611  //If one of the curves is zero-length, it will have a zero
612  //tangent vector.
613  double len_product = tangent_1.length() * tangent_2.length();
614  if( len_product > CUBIT_DBL_MIN )
615  {
616    double dot_product = (tangent_1 % tangent_2);
617    if (dot_product < 0)
618    relative_sense = CUBIT_REVERSED;
619  }
620  else
621  {
622    //If one of the tangents is zero-length, one of the curves had
623    //better be as well.
624    assert( (curve_1->measure() * curve_2->measure()) < CUBIT_RESABS );
625  }
626
627  //compare the start and end vertices to be spatially equal.
628  DLIList<Point*> curve_1_points(2), curve_2_points(2);
629  DLIList<TopologyBridge*> c1pts, c2pts;
630  curve_1->get_children(c1pts, false, layer);
631  curve_2->get_children(c2pts, false, layer);
632  CAST_LIST( c1pts, curve_1_points, Point );
633  CAST_LIST( c2pts, curve_2_points, Point );
634
635  if( curve_1->bridge_sense() == CUBIT_REVERSED )
636    curve_1_points.reverse();
637  if( curve_2->bridge_sense() == CUBIT_REVERSED )
638    curve_2_points.reverse();
639
640  Point* curve_1_start = curve_1_points.get(); 
641  curve_1_points.last();
642  Point* curve_1_end =  curve_1_points.get();
643
644  Point* curve_2_start = curve_2_points.get(); 
645  curve_2_points.last();
646  Point* curve_2_end =  curve_2_points.get();
647
648  if (relative_sense == CUBIT_REVERSED)
649    std::swap(curve_2_start, curve_2_end);
650
651  if (curve_1_start == curve_1_end ||curve_2_start == curve_2_end)
652  {
653    CubitVector c1start = curve_1_start->coordinates();
654    CubitVector c2start = curve_2_start->coordinates();
655    if ((curve_1_start != curve_1_end) ||
656        (curve_2_start != curve_2_end) ||
657        !GeometryQueryTool::instance()->about_spatially_equal(c1start, c2start, tolerance_factor))
658      return CUBIT_FALSE;
659  }
660  else
661  {
662    CubitVector c1start = curve_1_start->coordinates();
663    CubitVector c1end = curve_1_end->coordinates();
664    CubitVector c2start = curve_2_start->coordinates();
665    CubitVector c2end = curve_2_end->coordinates();
666    if ((curve_1_start == curve_2_end) ||
667        (curve_1_end == curve_2_start) ||
668        !GeometryQueryTool::instance()->about_spatially_equal(c1start, c2start, tolerance_factor ) ||
669        !GeometryQueryTool::instance()->about_spatially_equal(c1end, c2end, tolerance_factor ))
670      return CUBIT_FALSE;
671  }
672
673  return CUBIT_TRUE;
674
675}
676
677// This function will try to determine if virtual topology bridges have
678// been modified and if so will deactivate them so that they can be
679// rebuilt later using the COMPOSITE_GEOM attributes on the underlying
680// solid model topology.
681void CompositeEngine::remove_modified(DLIList<TopologyBridge*>& geometry_list)
682{
683  clean_out_deactivated_geometry();
684
685  int i, j, k, m, n, w;
686  int deactivate;
687  int something_changed = 1;
688  DLIList<Point*> already_deactivated_points;
689  DLIList<Curve*> already_deactivated_curves;
690  DLIList<Surface*> already_deactivated_surfs;
691
692  while(something_changed)
693  {
694    something_changed = 0;
695
696    for (i=geometry_list.size(); i--; )
697    {
698      // This code will first look for portions of the left over virtual
699      // topology layer that need to be blown away (deactivated).  It
700      // will put its findings in lists.  Then it will loop through
701      // and actualy deactivate everything.
702      TopologyBridge* geom_bridge = geometry_list.get_and_step();
703
704      DLIList<Surface*> surfaces;
705      DLIList<Curve*> curves;
706      DLIList<Point*> points;
707      DLIList<Point*> deactivated_points;
708      DLIList<Curve*> deactivated_curves;
709      DLIList<Surface*> deactivated_surfs;
710
711      geom_bridge->surfaces(surfaces);
712      geom_bridge->curves(curves);
713      geom_bridge->points(points);
714
715      // Look for composite points that are out of date.
716      while(points.size())
717      {
718        CompositePoint *p = dynamic_cast<CompositePoint*>(points.pop());
719        if(p && !already_deactivated_points.is_in_list(p))
720        {
721          Point *real_point = p->get_point();
722
723          deactivate = 0;
724
725          if(p->HadBridgeRemoved)
726            deactivate = 1;
727
728          // Check the curve attached to this point and make sure the
729          // virtual layer still matches the solid model layer.
730          if(!deactivate)
731          {
732            // Get the curves at this point using the virtual layer.
733            DLIList<Curve*> curves_referenced_by_virtual;
734            DLIList<Curve*> crvs;
735            p->curves(crvs);
736            for(j=crvs.size(); j--;)
737            {
738              Curve *c = crvs.get_and_step();
739              CompositeCurve *cc = dynamic_cast<CompositeCurve*>(c);
740              if(cc)
741              {
742                int num_curves = cc->num_curves();
743                for(k=0; k<num_curves; ++k)
744                {
745                  Curve *cur_c = cc->get_curve(k);
746                  DLIList<TopologyBridge*> pts;
747                  cur_c->get_children(pts, false, 0);
748                  if(pts.is_in_list(real_point))
749                    curves_referenced_by_virtual.append_unique(cur_c);
750                }
751              }
752              else
753                curves_referenced_by_virtual.append_unique(c);
754            }
755
756            // Get the curves refernced by the solid model layer.
757            DLIList<Curve*> curves_referenced_by_solid_model_layer;
758            DLIList<TopologyBridge*> sm_crvs;
759            real_point->get_parents_virt(sm_crvs);
760            CAST_LIST(sm_crvs, curves_referenced_by_solid_model_layer, Curve);
761
762            // Now check to make sure all of the curves referenced from the virtual
763            // layer show up in the ones referenced by the solid model layer.  If
764            // they don't we know something has been modified and this CompositePoint
765            // is no longer valid.
766            for(j=curves_referenced_by_virtual.size(); j && !deactivate; j--)
767            {
768              Curve *c = curves_referenced_by_virtual.get_and_step();
769              if(!curves_referenced_by_solid_model_layer.is_in_list(c))
770                deactivate = 1;
771            }
772          }
773
774          if(deactivate)
775            deactivated_points.append_unique(p);
776        }
777      }
778
779      // Look for composite curves that are out of date.
780      for(w=curves.size(); w--;)
781      {
782        Curve *current_curve = curves.get_and_step();
783        CompositeCurve *cur = dynamic_cast<CompositeCurve*>(current_curve);
784        if(cur && !already_deactivated_curves.is_in_list(cur))
785        {
786          deactivate = 0;
787
788          if(cur->HadBridgeRemoved)
789            deactivate = 1;
790
791          // Deactivate this curve if any of its points have been
792          // deactivated.
793          if(!deactivate)
794          {
795            DLIList<Point*> hidden_pts;
796            DLIList<Point*> boundary_pts;
797
798            cur->get_hidden_points(hidden_pts);
799            for(j=hidden_pts.size(); j && !deactivate; j--)
800            {
801              Point *pt = hidden_pts.get_and_step();
802              if(deactivated_points.is_in_list(pt))
803                deactivate = 1;
804            }
805
806            cur->points(boundary_pts);
807            for(j=boundary_pts.size(); j && !deactivate; j--)
808            {
809              Point *pt = boundary_pts.get_and_step();
810              if(deactivated_points.is_in_list(pt))
811                deactivate = 1;
812            }
813          }
814
815          // Deactivate this curve if the coedges stored at the
816          // virtual layer are out of sync with the solid model layer.
817          if(!deactivate)
818          {
819            // Get all of the coedges seen from the virtual layer.
820            DLIList<CoEdgeSM*> virt_coedges;
821            DLIList<TopologyBridge*> coedge_list;
822            cur->get_parents(coedge_list);
823            for(j=coedge_list.size(); j--;)
824            {
825              CoEdgeSM *csm = dynamic_cast<CoEdgeSM*>(coedge_list.get_and_step());
826              if(csm)
827              {
828                CompositeCoEdge *cce = dynamic_cast<CompositeCoEdge*>(csm);
829                if(cce)
830                {
831                  int num_coedges = cce->num_coedges();
832                  for(k=0; k<num_coedges; k++)
833                  {
834                    CoEdgeSM *cur_coedge = cce->get_coedge(k);
835                    virt_coedges.append_unique(cur_coedge);
836                  }
837                }
838                else
839                  virt_coedges.append_unique(csm);
840              }
841            }
842
843            // Get all of the coedges seen from the solid model layer.
844            DLIList<CoEdgeSM*> real_coedges;
845            int num_curves = cur->num_curves();
846            for(j=0; j<num_curves; j++)
847            {
848              Curve *cur_c = cur->get_curve(j);
849              DLIList<TopologyBridge*> tb_list;
850              cur_c->get_parents_virt(tb_list);
851              for(k=tb_list.size(); k--;)
852              {
853                CoEdgeSM *cur_ce = dynamic_cast<CoEdgeSM*>(tb_list.get_and_step());
854                if(cur_ce)
855                  real_coedges.append_unique(cur_ce);
856              }
857            }
858
859            // Now make sure all of the coedges seen from the virtual layer actually
860            // still exist in the solid model layer.
861            for(j=virt_coedges.size(); j && !deactivate; j--)
862            {
863              if(!real_coedges.is_in_list(virt_coedges.get_and_step()))
864                deactivate = 1;
865            }
866          }
867
868          // Deactivate this curve if any of the points seen from the virtual
869          // layer are out of date.
870          if(!deactivate)
871          {
872            DLIList<Point*> points_referenced_by_virtual;
873            DLIList<Point*> points_referenced_by_solid_model_layer;
874
875            // Get all of the hidden points in virtual layer.
876            DLIList<Point*> hidden_pts;
877            cur->get_hidden_points(hidden_pts);
878            for(j=hidden_pts.size(); j--;)
879            {
880              Point *cur_point = hidden_pts.get_and_step();
881              CompositePoint *cur_cpoint = dynamic_cast<CompositePoint*>(cur_point);
882              if(cur_cpoint)
883                cur_point = cur_cpoint->get_point();
884              points_referenced_by_virtual.append_unique(cur_point);
885            }
886
887            // Get the end points in virtual layer.
888            DLIList<Point*> end_pts;
889            cur->points(end_pts);
890            for(j=end_pts.size(); j--;)
891            {
892              Point *cur_point = end_pts.get_and_step();
893              CompositePoint *cur_cpoint = dynamic_cast<CompositePoint*>(cur_point);
894              if(cur_cpoint)
895                cur_point = cur_cpoint->get_point();
896              points_referenced_by_virtual.append_unique(cur_point);
897            }
898           
899            // Get the points of all of the curves from the solid model layer.
900            int num_curves = cur->num_curves();
901            for(j=0; j<num_curves; ++j)
902            {
903              DLIList<TopologyBridge*> pts;
904              Curve *c = cur->get_curve(j);
905              c->get_children(pts, false, 0);
906              for(k=pts.size(); k--;)
907                points_referenced_by_solid_model_layer.
908                        append_unique(dynamic_cast<Point*>(pts.get_and_step()));
909            }
910
911            // Now that we have gathered all of the info we can check to make sure
912            // that all of the points in the virtual layer actually exist in the
913            // solid model layer.
914            for(j=points_referenced_by_virtual.size(); j && !deactivate; j--)
915            {
916              Point *cur_point = points_referenced_by_virtual.get_and_step();
917              if(!points_referenced_by_solid_model_layer.is_in_list(cur_point))
918                deactivate = 1;
919            }
920          }
921
922          // Check to see if there is a hidden entity that doesn't have a
923          // COMPOSITE_GEOM attribute.  This can happen if the geometry
924          // modification operation cut the body right through a hidden
925          // entity without splitting it.  In this case a merge_owner event
926          // gets triggered and the COMPOSITE_GEOM attribute gets removed
927          // from the hidden entity.  In this case we want to remove the
928          // composite.
929          if(!deactivate)
930          {
931            DLIList<Point*> hidden_points;
932            cur->get_hidden_points(hidden_points);
933            for(j=hidden_points.size(); j>0 && !deactivate; j--)
934            {
935              DLIList<CubitSimpleAttrib*> att_list;
936              hidden_points.get_and_step()->get_simple_attribute("COMPOSITE_GEOM", att_list);
937              if(att_list.size() == 0)
938                deactivate = 1;
939            }
940          }
941
942          // This block checks to see if any of the hidden points in
943          // a composite curve are the endpoints of an actual curve of
944          // the passed in geometry list.  This can happen if the hidden
945          // curve of a composite surface was cut by a real operation and
946          // an end point of the original hidden curve was a hidden point
947          // in a composite curve.  In this case we want to deactivate the
948          // composite curve.  If the composite curve is still valid it will
949          // get reconstructed by the composite attributes later.
950          if(!deactivate)
951          {
952            DLIList<Point*> hidden;
953            cur->get_hidden_points(hidden);
954            for (j=hidden.size(); j && !deactivate; j--)
955            {
956              Point *pt = hidden.pop();
957              DLIList<TopologyBridge*> point_curves;
958              pt->get_parents_virt(point_curves);
959              for(k=point_curves.size(); k && !deactivate; k--)
960              {
961                Curve *c = dynamic_cast<Curve*>(point_curves.get_and_step());
962                if(c && c != current_curve && curves.is_in_list(c))
963                  deactivate = 1;
964              }
965            }
966          }
967
968          // Check to see if the existing CompositeCurve end points match the
969          // underlying geometry end points.  In some geometry modification
970          // operations I found that a curve can be modified in place so that
971          // the underlying entity was changed but owner attribute wasn't blown
972          // away.  As a result you end up with the same toplogy bridge which can
973          // be out of date.  The case I saw was where the Point in the CompositePoint
974          // at one of the ends of the CompositeCurve was out of date and didn't
975          // match the new Point that was created during the geometry modification.
976          if(!deactivate)
977          {
978            // Not quite sure how to handle multiple curve cases yet so we
979            // will do our best for now.
980            if(cur->num_curves() == 1)
981            {
982              DLIList<TopologyBridge*> underlying_points;
983              cur->get_curve(0)->get_children_virt(underlying_points);
984              if(underlying_points.size() == 2)
985              {
986                Point *p1 = dynamic_cast<Point*>(underlying_points.get_and_step());
987                Point *p2 = dynamic_cast<Point*>(underlying_points.get());
988
989                CompositePoint *cp1 = cur->start_point();
990                CompositePoint *cp2 = cur->end_point();
991
992                if(!cp1 || !cp2)
993                  deactivate = 1;
994                else
995                {
996                  Point *cpp1 = cp1->get_point();
997                  Point *cpp2 = cp2->get_point();
998                  if((p1 != cpp1 && p2 != cpp1) || (p1 != cpp2 && p2 != cpp2))
999                    deactivate = 1;
1000                }
1001              }
1002            }
1003          }
1004
1005          if(deactivate)
1006            deactivated_curves.append_unique(cur);
1007
1008        }
1009      }
1010
1011      // Look for composite surfaces that are out of date.
1012      while (surfaces.size())
1013      {
1014        CompositeSurface* csurf = dynamic_cast<CompositeSurface*> (surfaces.pop());
1015        if (csurf && !already_deactivated_surfs.is_in_list(csurf))
1016        {
1017          deactivate = 0;
1018
1019          // If one of the surfaces was removed from the compGeom list we
1020          // suspect this composite surface was modified so we need to remove it.
1021          if(csurf->HadBridgeRemoved)
1022            deactivate = 1;
1023
1024          // Deactivate this surface if any of its curves were deactivated.
1025          if(!deactivate)
1026          {
1027            DLIList<Curve*> hidden_curves;
1028            DLIList<Curve*> boundary_curves;
1029
1030            csurf->get_hidden_curves(hidden_curves);
1031            for(j=hidden_curves.size(); j && !deactivate; j--)
1032            {
1033              Curve *curve = hidden_curves.get_and_step();
1034              if(deactivated_curves.is_in_list(curve))
1035                deactivate = 1;
1036            }
1037
1038            csurf->curves(boundary_curves);
1039            for(j=boundary_curves.size(); j && !deactivate; j--)
1040            {
1041              Curve *curve = boundary_curves.get_and_step();
1042              if(deactivated_curves.is_in_list(curve))
1043                deactivate = 1;
1044            }
1045          }
1046
1047          // Deactivate this surface if any of its curves seen from the
1048          // virtual layer are out of date.
1049          if(!deactivate)
1050          {
1051            DLIList<Curve*> curves_referenced_by_virtual;
1052            DLIList<Curve*> curves_referenced_by_solid_model_layer;
1053
1054            // Get all of the hidden curves in virtual layer.
1055            DLIList<Curve*> hidden_curves;
1056            csurf->get_hidden_curves(hidden_curves);
1057            for(j=hidden_curves.size(); j--;)
1058            {
1059              Curve *cur_curve = hidden_curves.get_and_step();
1060              CompositeCurve *cur_ccurve = dynamic_cast<CompositeCurve*>(cur_curve);
1061              if(cur_ccurve)
1062              {
1063                for(k=cur_ccurve->num_curves()-1; k>-1; k--)
1064                {
1065                  Curve *cur = cur_ccurve->get_curve(k);
1066                  curves_referenced_by_virtual.append_unique(cur);
1067                }
1068              }
1069              else
1070                curves_referenced_by_virtual.append_unique(cur_curve);
1071            }
1072
1073            // Get the boundary curves in virtual layer.
1074            DLIList<Curve*> end_curves;
1075            csurf->curves(end_curves);
1076            for(j=end_curves.size(); j--;)
1077            {
1078              Curve *cur_curve = end_curves.get_and_step();
1079              CompositeCurve *cur_ccurve = dynamic_cast<CompositeCurve*>(cur_curve);
1080              if(cur_ccurve)
1081              {
1082                for(k=cur_ccurve->num_curves()-1; k>-1; k--)
1083                {
1084                  Curve *cur = cur_ccurve->get_curve(k);
1085                  curves_referenced_by_virtual.append_unique(cur);
1086                }
1087              }
1088              else
1089                curves_referenced_by_virtual.append_unique(cur_curve);
1090            }
1091           
1092            // Get the curves of all of the surfaces from the solid model layer.
1093            int num_surfs = csurf->num_surfs();
1094            for(j=0; j<num_surfs; ++j)
1095            {
1096              Surface *s = csurf->get_surface(j);
1097              DLIList<TopologyBridge*> loops;
1098              s->get_children(loops, false, 0);
1099              for(k=loops.size(); k--;)
1100              {
1101                LoopSM *cur_loop = dynamic_cast<LoopSM*>(loops.get_and_step());
1102                DLIList<TopologyBridge*> coedges;
1103                cur_loop->get_children(coedges, false, 0);
1104                for(m=coedges.size(); m--;)
1105                {
1106                  CoEdgeSM *cur_coedge = dynamic_cast<CoEdgeSM*>(coedges.get_and_step());
1107                  DLIList<TopologyBridge*> crvs;
1108                  cur_coedge->get_children(crvs, false, 0);
1109                  for(n=crvs.size(); n--;)
1110                  {
1111                    Curve *cur_curve = dynamic_cast<Curve*>(crvs.get_and_step());
1112                    curves_referenced_by_solid_model_layer.append_unique(cur_curve);
1113                  }
1114                }
1115              }
1116            }
1117
1118            // Now that we have gathered all of the info we can check to make sure
1119            // that all of the curves in the virtual layer actually exist in the
1120            // solid model layer.
1121            if(curves_referenced_by_virtual.size() != 
1122              curves_referenced_by_solid_model_layer.size())
1123            {
1124              deactivate = 1;
1125            }
1126            else
1127            {
1128              for(j=curves_referenced_by_virtual.size(); j && !deactivate; j--)
1129              {
1130                Curve *cur_curve = curves_referenced_by_virtual.get_and_step();
1131                if(!curves_referenced_by_solid_model_layer.is_in_list(cur_curve))
1132                  deactivate = 1;
1133              }
1134            }
1135          }
1136
1137          // Check to see if there is a hidden entity that doesn't have a
1138          // COMPOSITE_GEOM attribute.  This can happen if the geometry
1139          // modification operation cut the body right through a hidden
1140          // entity without splitting it.  In this case a merge_owner event
1141          // gets triggered and the COMPOSITE_GEOM attribute gets removed
1142          // from the hidden entity.  In this case we want to remove the
1143          // composite.
1144          if(!deactivate)
1145          {
1146            DLIList<Curve*> hidden_curves;
1147            csurf->get_hidden_curves(hidden_curves);
1148            for(j=hidden_curves.size(); j>0 && !deactivate; j--)
1149            {
1150              DLIList<CubitSimpleAttrib*> att_list;
1151              hidden_curves.get_and_step()->get_simple_attribute("COMPOSITE_GEOM", att_list);
1152              if(att_list.size() == 0)
1153                deactivate = 1;
1154            }
1155          }
1156
1157          if(deactivate)
1158            deactivated_surfs.append_unique(csurf);
1159        }
1160      }
1161
1162      already_deactivated_points += deactivated_points;
1163      already_deactivated_curves += deactivated_curves;
1164      already_deactivated_surfs += deactivated_surfs;
1165
1166      something_changed += deactivated_surfs.size() + deactivated_curves.size() +
1167        deactivated_points.size();
1168
1169      // Now actually deactivate the out of date composite surfs.
1170      for(j=deactivated_surfs.size(); j--;)
1171      {
1172        CompositeSurface *csurf = dynamic_cast<CompositeSurface*>(deactivated_surfs.get_and_step());
1173
1174        // We have to also deactivate the boundary curves.  When we deactivate
1175        // the CompositeSurface it removes all of the CompositeCoEdges associated
1176        // with it.  However, it doesn't deactivate the composite curves associated
1177        // with the composite coedges.  Therefore you can end up with a regular
1178        // CoEdge pointing to a CompositeCurve and if the CompositeCurve has more
1179        // than 1 curve in it later calls to replace_surface (which will in turn
1180        // call replace_curve) will fail.
1181        DLIList<Curve*> boundary_curves;
1182        csurf->curves(boundary_curves);
1183        for (k=boundary_curves.size(); k--; )
1184        {
1185          CompositeCurve* c = dynamic_cast<CompositeCurve*>(boundary_curves.get_and_step());
1186          assert(NULL != c);
1187
1188          notify_deactivated(c);
1189        }
1190
1191        notify_deactivated(csurf);
1192
1193        DLIList<Curve*> hidden;
1194        csurf->get_hidden_curves(hidden);
1195        for (k=hidden.size(); k--; )
1196        {
1197          CompositeCurve* hcurve = dynamic_cast<CompositeCurve*>(hidden.pop());
1198          assert(NULL != hcurve);
1199
1200          notify_deactivated(hcurve);
1201
1202          if(hcurve->num_curves() == 1)
1203          {
1204            Curve *c = hcurve->get_curve(0);
1205            DLIList<TopologyBridge*> end_pts;
1206            c->get_children(end_pts, false, 0);
1207            for(m=end_pts.size(); m--;)
1208            {
1209              Point *cur_p = dynamic_cast<Point*>(end_pts.get_and_step());
1210              if(cur_p)
1211              {
1212                CompositePoint* cp = dynamic_cast<CompositePoint*>(cur_p->owner());
1213                if(cp)
1214                  cur_p = (Point*)cp;
1215                TBOwner *own = cur_p->owner();
1216                HiddenEntitySet *hes = dynamic_cast<HiddenEntitySet*>(own);
1217                if(hes)
1218                {
1219                  CompositeCurve *cc = dynamic_cast<CompositeCurve*>(hes->owner());
1220                  if(cc)
1221                  {
1222                    notify_deactivated(cc);
1223
1224                    DLIList<Point*> hidden_pts;
1225                    cc->get_hidden_points(hidden_pts);
1226                    for (n=hidden_pts.size(); n--; )
1227                    {
1228                      CompositePoint *hpoint = dynamic_cast<CompositePoint*>(hidden_pts.pop());
1229                      assert(NULL != hpoint);
1230                      notify_deactivated(hpoint);
1231                    }
1232                  }
1233                }
1234              }
1235            }
1236          }
1237        }
1238      }
1239
1240      // Now actually deactivate the out of date composite curves.
1241      for(j=deactivated_curves.size(); j--;)
1242      {
1243        CompositeCurve *ccurve = dynamic_cast<CompositeCurve*>(deactivated_curves.get_and_step());
1244
1245        notify_deactivated(ccurve);
1246
1247        int j;
1248        DLIList<Point*> hidden;
1249        ccurve->get_hidden_points(hidden);
1250        for (j=hidden.size(); j--; )
1251        {
1252          CompositePoint *hpoint = dynamic_cast<CompositePoint*>(hidden.pop());
1253          assert(NULL != hpoint);
1254          notify_deactivated(hpoint);
1255        }
1256      }
1257
1258      // Now actually deactivate the out of date composite points.
1259      for(j=deactivated_points.size(); j--;)
1260      {
1261        CompositePoint* cpoint = dynamic_cast<CompositePoint*> (deactivated_points.pop());
1262        notify_deactivated(cpoint);
1263      }
1264    }
1265  }
1266}
1267
1268//-------------------------------------------------------------------------
1269// Purpose       : Constructor
1270//
1271// Special Notes :
1272//
1273// Creator       : Jason Kraftcheck
1274//
1275// Creation Date : 08/25/03
1276//-------------------------------------------------------------------------
1277CompositeEngine::CompositeEngine()
1278{
1279  CubitStatus result = GeometryQueryTool::instance()->
1280    register_intermediate_engine( this );
1281  assert(result == CUBIT_SUCCESS);
1282}
1283
1284//-------------------------------------------------------------------------
1285// Purpose       : Get composite-level query results from
1286//                 query of underlying topology.
1287//
1288// Special Notes :
1289//
1290// Creator       : Jason Kraftcheck
1291//
1292// Creation Date : 03/13/02
1293//-------------------------------------------------------------------------
1294/*
1295void CompositeEngine::fix_up_query_results( DLIList<TopologyBridge*>& list,
1296                                            bool keep_hidden )
1297{
1298  DLIList<TopologyBridge*> tmp_list;
1299  int i;
1300 
1301  list.reset();
1302  for( i = list.size(); i--; )
1303  {
1304    TopologyBridge* bridge = list.get();
1305    TBOwnerSet* set = dynamic_cast<TBOwnerSet*>(bridge->owner());
1306    if( set )
1307    {
1308      tmp_list.clean_out();
1309      set->get_owners( tmp_list );
1310      if( tmp_list.size() )
1311      {
1312        tmp_list.reset();
1313        list.change_to( tmp_list.get_and_step() );
1314        for( int j = 1; j < tmp_list.size(); j++ )
1315          list.insert( tmp_list.get_and_step() );
1316      }
1317      else
1318      {
1319        list.change_to(0);
1320      }
1321    }
1322    list.step();
1323  }
1324 
1325  list.remove_all_with_value( 0 );
1326 
1327  list.reset();
1328  for( i = list.size(); i--; )
1329  {
1330    TopologyBridge* bridge = list.get();
1331    TopologyBridge *next = 0;
1332    while( next = dynamic_cast<TopologyBridge*>(bridge->owner()) )
1333      bridge = next;
1334   
1335    if( !keep_hidden && dynamic_cast<HiddenEntitySet*>(bridge->owner()) )
1336    {
1337      list.change_to(0);
1338    }
1339    else if( list.get() != bridge )
1340    {
1341      if( list.is_in_list( bridge ) )
1342        list.change_to(0);
1343      else
1344        list.change_to(bridge);
1345    }
1346   
1347    list.step();
1348  }
1349 
1350  list.remove_all_with_value( 0 );
1351}
1352*/
1353
1354
1355//-------------------------------------------------------------------------
1356// Purpose       : Combine two curves
1357//
1358// Special Notes :
1359//
1360// Creator       : Jason Kraftcheck
1361//
1362// Creation Date : 03/13/02
1363//-------------------------------------------------------------------------
1364CompositeCurve* CompositeEngine::composite( Curve* keep_curve,
1365                                            Curve* dead_curve,
1366                                            Point* keep_point,
1367                                            bool remove_partition )
1368{
1369  if( keep_curve == dead_curve )
1370  {
1371    PRINT_ERROR("Cannot remove vertex from single-vertex curve.\n");
1372    return 0;
1373  }
1374 
1375  CompositeCurve* result = 0;
1376  CompositeCurve* ckeep = dynamic_cast<CompositeCurve*>(keep_curve);
1377  CompositeCurve* cdead = dynamic_cast<CompositeCurve*>(dead_curve);
1378  bool replaced1 = false;
1379  bool replaced2 = false;
1380 
1381  if( !ckeep )
1382  {
1383    ckeep = replace_curve( keep_curve );
1384    replaced1 = true;
1385  }
1386  if( !cdead )
1387  {
1388    cdead = replace_curve( dead_curve );
1389    replaced2 = true;
1390  }
1391 
1392  CompositePoint* comppoint = dynamic_cast<CompositePoint*>(keep_point);
1393  if( keep_point && !comppoint )
1394  {
1395    comppoint = dynamic_cast<CompositePoint*>(keep_point->owner());
1396    assert( comppoint!= NULL );
1397  }
1398 
1399  if( !ckeep || !cdead || 
1400      !(result = combine(ckeep, cdead, comppoint, remove_partition)) )
1401  {
1402    if( replaced1 && ckeep )
1403    {
1404      Curve* s = remove_composite( ckeep );
1405      assert( s != 0 );
1406    }
1407    if( replaced2 && cdead )
1408    {
1409      Curve* s = remove_composite( cdead );
1410      assert( s != 0 );
1411    }
1412  }
1413 
1414  return result;
1415}
1416
1417//-------------------------------------------------------------------------
1418// Purpose       : Replace a "point" curve with a composite
1419//
1420// Special Notes :
1421//
1422// Creator       : Jason Kraftcheck
1423//
1424// Creation Date : 11/26/02
1425//-------------------------------------------------------------------------
1426CompositePoint* CompositeEngine::replace_point( Point* point )
1427{
1428  assert( !dynamic_cast<CompositePoint*>(point) );
1429  return new CompositePoint( point );
1430}
1431
1432//-------------------------------------------------------------------------
1433// Purpose       : Replace a "real" curve with a composite
1434//
1435// Special Notes :
1436//
1437// Creator       : Jason Kraftcheck
1438//
1439// Creation Date : 03/13/02
1440//-------------------------------------------------------------------------
1441CompositeCurve* CompositeEngine::replace_curve( Curve* curve )
1442{
1443#ifdef BOYD17
1444  DLIList<TopologyBridge*> points, coedges, loops;
1445#endif
1446  DLIList<TopologyBridge*> points, coedges;
1447  //curve->get_children_virt( points );
1448  //fix_up_query_results(points);
1449  curve->get_children( points, true, COMPOSITE_LAYER );
1450
1451  if(points.size() > 2)
1452    return 0;
1453   
1454  points.reset();
1455  Point* start_pt = dynamic_cast<Point*>(points.get_and_step());
1456  Point*   end_pt = dynamic_cast<Point*>(points.get_and_step());
1457
1458  CompositeCurve* composite = dynamic_cast<CompositeCurve*>(curve);
1459 
1460  if(!composite)
1461    composite = new CompositeCurve( curve );
1462  else
1463  {
1464    if(composite->num_curves() > 1)
1465    {
1466      PRINT_ERROR("Error replacing existing composite curve with more than one underlying curve\n");
1467      return 0;
1468    }
1469  }
1470
1471  CompositePoint* start = dynamic_cast<CompositePoint*>(start_pt);
1472  if( !start ) 
1473    start = replace_point( start_pt );
1474  CompositePoint* end = 0;
1475  if ( end_pt == start_pt )
1476    end = start;
1477  else if ( !(end = dynamic_cast<CompositePoint*>(end_pt)) )
1478    end = replace_point( end_pt );
1479  assert( start && end );
1480
1481  composite->start_point( start );
1482  composite->  end_point(   end );
1483
1484  DLIList<TopologyBridge*> existing_composite_coedges;
1485  if(dynamic_cast<CompositeCurve*>(curve))
1486  {
1487    dynamic_cast<CompositeCurve*>(curve)->get_curve(0)->get_parents_virt(coedges);
1488    curve->get_parents_virt(existing_composite_coedges);
1489  }
1490  else
1491  {
1492    curve->get_parents_virt( coedges );
1493  }
1494  for( int i = coedges.size(); i--; )
1495  {
1496    CoEdgeSM* coedge = dynamic_cast<CoEdgeSM*>(coedges.get_and_step());
1497    assert(coedge);
1498    CompositeCoEdge* ccoedge = NULL;
1499    for(int h=existing_composite_coedges.size(); h>0; h--)
1500    {
1501      CompositeCoEdge *temp = dynamic_cast<CompositeCoEdge*>(existing_composite_coedges.get_and_step());
1502      if(temp->get_coedge(0) == coedge)
1503      {
1504        ccoedge = temp;
1505        h = 0;
1506      }
1507    }
1508    if(!ccoedge)
1509    {
1510      ccoedge = new CompositeCoEdge( coedge );
1511      if( composite->get_sense(0) == CUBIT_REVERSED )
1512        ccoedge->reverse();
1513     
1514      assert( ccoedge->get_curve() == 0 );
1515      composite->add( ccoedge );
1516    }
1517  }
1518 
1519  return composite;
1520}
1521
1522
1523//-------------------------------------------------------------------------
1524// Purpose       : Replace a "real" surface with a composite
1525//
1526// Special Notes :
1527//
1528// Creator       : Jason Kraftcheck
1529//
1530// Creation Date : 03/13/02
1531//-------------------------------------------------------------------------
1532CompositeSurface* CompositeEngine::replace_surface( Surface* surface )
1533{
1534  DLIList<TopologyBridge*> loops, coedges, curves;
1535  int i, j;
1536  if( dynamic_cast<CompositeSurface*>(surface) )
1537    return 0;
1538 
1539  CompositeSurface* compsurf = new CompositeSurface( surface );
1540  //surface->get_children_virt( loops );
1541  //fix_up_query_results(loops);
1542  surface->get_children( loops, false, COMPOSITE_LAYER );
1543  loops.reset();
1544  for( i = loops.size();i--; )
1545  {
1546    TopologyBridge* loop_bridge = loops.get_and_step();
1547    CompositeLoop* comploop = new CompositeLoop();
1548    compsurf->add( comploop );
1549    if( loop_bridge->owner() )
1550    {
1551      loop_bridge->owner()->swap_bridge( loop_bridge, comploop, false );
1552      loop_bridge->owner(0);
1553    }
1554    //compsurf->hidden_entities().hide( loop_bridge );
1555   
1556    coedges.clean_out();
1557    //loop_bridge->get_children_virt( coedges );
1558    //fix_up_query_results(coedges);
1559    loop_bridge->get_children( coedges, false, COMPOSITE_LAYER );
1560   
1561    coedges.reset();
1562    CompositeCoEdge* prev = 0;
1563    for( j = coedges.size(); j--; )
1564    {
1565      CoEdgeSM* coedge = dynamic_cast<CoEdgeSM*>(coedges.get_and_step());
1566      CompositeCoEdge* comp_coedge = dynamic_cast<CompositeCoEdge*>(coedge);
1567      if( !comp_coedge )
1568      {
1569        curves.clean_out();
1570        //coedge->get_children_virt( curves );
1571        //fix_up_query_results(curves);
1572        coedge->get_children(curves, false, COMPOSITE_LAYER);
1573        assert( curves.size() == 1 );
1574        replace_curve( dynamic_cast<Curve*>(curves.get()) );
1575        comp_coedge = dynamic_cast<CompositeCoEdge*>(coedge->owner());
1576        assert( comp_coedge!= NULL );
1577      }
1578      else
1579      {
1580        /*
1581        PRINT_INFO("\nStart: %lf %lf %lf", comp_coedge->start_point()->coordinates().x(),
1582          comp_coedge->start_point()->coordinates().y(), comp_coedge->start_point()->coordinates().z());
1583        PRINT_INFO("\nEnd: %lf %lf %lf", comp_coedge->end_point()->coordinates().x(),
1584          comp_coedge->end_point()->coordinates().y(), comp_coedge->end_point()->coordinates().z());
1585       */
1586      }
1587      comploop->insert_after( comp_coedge, prev );
1588      prev = comp_coedge;
1589    }
1590  }
1591 
1592  return compsurf;
1593}
1594     
1595
1596
1597//-------------------------------------------------------------------------
1598// Purpose       : Replace a "real" lump with a composite
1599//
1600// Special Notes :
1601//
1602// Creator       : Jason Kraftcheck
1603//
1604// Creation Date : 07/19/02
1605//-------------------------------------------------------------------------
1606CompositeLump* CompositeEngine::replace_lump( Lump* lump )
1607{
1608  DLIList<TopologyBridge*> shells, surfaces;
1609  int i, j;
1610  if( dynamic_cast<CompositeLump*>(lump) )
1611    return 0;
1612 
1613  CompositeLump* complump = new CompositeLump( lump );
1614  //lump->get_children_virt( shells );
1615  //fix_up_query_results(shells);
1616  lump->get_children(shells, false, COMPOSITE_LAYER);
1617  shells.reset();
1618  for( i = shells.size();i--; )
1619  {
1620    CompositeShell* compshell = new CompositeShell();
1621    complump->add( compshell );
1622    TopologyBridge* shell_bridge = shells.get_and_step();
1623    if( shell_bridge->owner() )
1624    {
1625      shell_bridge->owner()->swap_bridge(shell_bridge, compshell, false);
1626      shell_bridge->owner(0);
1627    }
1628    //complump->hidden_entities().hide( shell_bridge );
1629   
1630   
1631    surfaces.clean_out();
1632    //shell_bridge->get_children_virt( surfaces );
1633    //fix_up_query_results(surfaces);
1634    shell_bridge->get_children(surfaces, false, COMPOSITE_LAYER);
1635   
1636    surfaces.reset();
1637    for( j = surfaces.size(); j--; )
1638    {
1639      Surface* surface = dynamic_cast<Surface*>(surfaces.get_and_step());
1640      CompositeSurface* compsurf = dynamic_cast<CompositeSurface*>(surface);
1641      if( !compsurf )
1642      {
1643        compsurf = replace_surface( surface );
1644        assert( compsurf!= NULL );
1645      }
1646
1647      compshell->add( compsurf, CUBIT_FORWARD );
1648    }
1649  }
1650 
1651  return complump;
1652}
1653     
1654
1655
1656//-------------------------------------------------------------------------
1657// Purpose       : Replace a "real" bodysm with a composite
1658//
1659// Special Notes :
1660//
1661// Creator       : Jason Kraftcheck
1662//
1663// Creation Date : 07/19/02
1664//-------------------------------------------------------------------------
1665CompositeBody* CompositeEngine::replace_body( BodySM* body )
1666{
1667  DLIList<TopologyBridge*> lumps;
1668  int i;
1669  if( dynamic_cast<CompositeBody*>(body) )
1670    return 0;
1671 
1672  CompositeBody* compbody = new CompositeBody( );
1673  compbody->add(body);
1674  body->get_children( lumps, false, COMPOSITE_LAYER );
1675  lumps.reset();
1676  for( i = lumps.size();i--; )
1677  {
1678    Lump* lump = dynamic_cast<Lump*>(lumps.get_and_step());
1679    CompositeLump* complump = dynamic_cast<CompositeLump*>(lump);
1680    if( !complump )
1681      complump = replace_lump( lump );
1682    compbody->add( complump );
1683  }
1684 
1685  return compbody;
1686}
1687
1688Point* CompositeEngine::remove_composite( CompositePoint* composite )
1689{
1690  assert( composite->next_curve() == 0 );
1691  assert( !dynamic_cast<HiddenEntitySet*>(composite->owner()) );
1692  Point* result = composite->get_point();
1693  delete composite;
1694  return result;
1695}
1696
1697
1698
1699//-------------------------------------------------------------------------
1700// Purpose       : Reomve a 1-curve composite
1701//
1702// Special Notes : Inverse of replace_curve(..)
1703//
1704// Creator       : Jason Kraftcheck
1705//
1706// Creation Date : 03/13/02
1707//-------------------------------------------------------------------------
1708Curve* CompositeEngine::remove_composite( CompositeCurve* composite )
1709{
1710  assert( composite->num_curves() == 1 && 
1711          !composite->has_parent_composite_surface() &&
1712          !dynamic_cast<HiddenEntitySet*>(composite->owner()) &&
1713          !composite->is_stitched() );
1714
1715  CompositeCoEdge* coedge = 0;
1716  while( (coedge = composite->first_coedge()) )
1717  {
1718    assert( !coedge->get_loop() && coedge->num_coedges() == 1 );
1719    composite->remove( coedge );
1720    CoEdgeSM* real_coedge = coedge->get_coedge(0);
1721    coedge->remove_coedge( 0 );
1722    if( coedge->owner() )
1723      coedge->owner()->swap_bridge( coedge, real_coedge, false );
1724    delete coedge;
1725  }
1726 
1727  CompositePoint* sp = composite->start_point();
1728  CompositePoint* ep = composite->end_point();
1729  Curve* curve = composite->get_curve( 0 );
1730  bool reversed = composite->get_sense(0) == CUBIT_REVERSED;
1731  composite->remove_curve(0);
1732  if( composite->owner() )
1733    composite->owner()->swap_bridge( composite, curve, reversed );
1734 
1735  composite->start_point(0);
1736  composite->end_point(0);
1737  delete composite;
1738 
1739  if( ! sp->next_curve() )
1740    remove_composite(sp);
1741  if( ep != sp && !ep->next_curve() )
1742    remove_composite(ep);
1743 
1744  // we must notify the graphics of the modify from "real" to virtual -- KGM
1745  // I realize that this is not where the other notifies are completed but there
1746  // is no knowledge of the change later on.
1747  CubitObservable* observer = dynamic_cast<CubitObservable*>(curve->topology_entity());
1748  if (observer)
1749  {
1750    observer->notify_all_observers(GEOMETRY_MODIFIED);
1751  }
1752
1753  return curve;
1754}
1755
1756
1757//-------------------------------------------------------------------------
1758// Purpose       : Remove a 1-surface composite
1759//
1760// Special Notes : inverse of replace_surface(..)
1761//
1762// Creator       : Jason Kraftcheck
1763//
1764// Creation Date : 03/13/02
1765//-------------------------------------------------------------------------
1766Surface* CompositeEngine::remove_composite( CompositeSurface* composite )
1767{
1768  assert( ! composite->has_hidden_entities() );
1769  assert( composite->next_co_surface(0) == 0 );
1770  CompositeLoop* loop;
1771  CompositeCoEdge* coedge;
1772  CompositeCurve* curve;
1773 
1774  while( (loop = composite->first_loop()) )
1775  {
1776    composite->remove( loop );
1777    while( (coedge = loop->first_coedge()) )
1778    {
1779      loop->remove(coedge);
1780      curve = coedge->get_curve();
1781      if( curve->num_curves() == 1 &&
1782          !curve->has_parent_composite_surface() &&
1783          !curve->is_stitched()) 
1784        remove_composite(curve);
1785    }
1786    delete loop;
1787  }
1788 
1789  Surface* surface = composite->get_surface( 0 );
1790  bool reversed = composite->get_sense(0) == CUBIT_REVERSED;
1791  composite->remove_surface(0);
1792  if( composite->owner() )
1793    composite->owner()->swap_bridge( composite, surface, reversed );
1794  delete composite;
1795 
1796  return surface;
1797}
1798
1799//-------------------------------------------------------------------------
1800// Purpose       : Remove a 1-lump composite
1801//
1802// Special Notes : inverse of replace_lump(..)
1803//
1804// Creator       : Jason Kraftcheck
1805//
1806// Creation Date : 07/19/02
1807//-------------------------------------------------------------------------
1808Lump* CompositeEngine::remove_composite( CompositeLump* composite )
1809{
1810  assert( composite->num_lumps() == 1 );
1811  assert( composite->get_body() == 0 );
1812 
1813  for( CompositeShell* shell = composite->first_shell();
1814       shell != 0;
1815       shell = composite->next_shell( shell ) )
1816  {
1817    composite->remove( shell );
1818    while( shell->first_co_surf() )
1819    {
1820      CompositeCoSurf* cos = shell->first_co_surf();
1821      CompositeSurface* surface = cos->get_surface();
1822      shell->remove( cos );
1823      surface->remove( cos );
1824      delete cos;
1825     
1826      if( surface->next_co_surface() == 0 &&
1827          !surface->has_hidden_entities() )
1828        remove_composite( surface );
1829    }
1830    delete shell;
1831  }
1832 
1833  Lump* result = composite->get_lump( 0 );
1834  composite->remove_bridge(result);
1835  if( composite->owner() )
1836    composite->owner()->swap_bridge( composite, result, false );
1837  delete composite;
1838 
1839  return result;
1840}
1841
1842
1843//-------------------------------------------------------------------------
1844// Purpose       : Remove a 1-body composite
1845//
1846// Special Notes : inverse of replace_body(..)
1847//
1848// Creator       : Jason Kraftcheck
1849//
1850// Creation Date : 07/19/02
1851//-------------------------------------------------------------------------
1852BodySM* CompositeEngine::remove_composite( CompositeBody* composite )
1853{
1854  assert( composite->num_bodies() == 1 );
1855 
1856  while( CompositeLump* lump = composite->next_lump() )
1857  {
1858    composite->remove( lump );
1859    remove_composite( lump );
1860  }
1861 
1862  BodySM* result = composite->get_body( 0 );
1863  composite->remove_bridge(result);
1864  if( composite->owner() )
1865    composite->owner()->swap_bridge( composite, result, false );
1866  delete composite;
1867 
1868  return result;
1869}
1870
1871 
1872//-------------------------------------------------------------------------
1873// Purpose       : Combine two curves into a composite
1874//
1875// Special Notes :
1876//
1877// Creator       : Jason Kraftcheck
1878//
1879// Creation Date : 03/13/02
1880//-------------------------------------------------------------------------
1881CompositeCurve* CompositeEngine::combine( CompositeCurve* keep, 
1882                                          CompositeCurve* dead,
1883                                          CompositePoint* keep_point,
1884                                          bool remove_partitions )
1885{
1886  if( keep->start_point() == keep->end_point() ||
1887      dead->start_point() == dead->end_point() )
1888    return 0;
1889 
1890    // find the point to remove by compositing.
1891  CompositePoint* common = keep->common_point( dead );
1892  if (!common)
1893    return 0;
1894   
1895  if (keep_point && common == keep_point)
1896  {
1897    common = keep->other_point(common);
1898    if (dead->other_point(common) != keep_point)
1899      return 0;
1900  }
1901 
1902  bool prepend = (common == keep->start_point());
1903  bool reverse = ((common == dead->end_point()) != prepend);
1904 
1905    // Order coedges such that each coedge from the
1906    // dead curve is grouped with the corresponding
1907    // coedge from the curve to be kept.
1908  DLIList<CompositeCoEdge*> dead_coedges, sorted_coedges;
1909  CompositeCoEdge* coedge;
1910  for( coedge = dead->first_coedge();
1911       coedge != 0;
1912       coedge = dead->next_coedge( coedge ) )
1913    dead_coedges.append( coedge );
1914 
1915  int keep_count = 0;
1916  CompositeCoEdge *keep_coedge = NULL;
1917  for( keep_coedge = keep->first_coedge();
1918       keep_coedge != 0;
1919       keep_coedge = keep->next_coedge( keep_coedge ) )
1920  {
1921    keep_count++;
1922    LoopSM* keep_loop = keep_coedge->get_parent_loop();
1923    CubitSense keep_sense = keep_coedge->sense();
1924   
1925    for( int j = dead_coedges.size(); j--;  )
1926    {
1927      CompositeCoEdge* dead_coedge = dead_coedges.step_and_get();
1928      if( dead_coedge->get_parent_loop() == keep_loop &&
1929         (reverse == (keep_sense != dead_coedge->sense()) ) )
1930      {
1931        dead_coedges.extract();
1932        sorted_coedges.append( dead_coedge );
1933        break;
1934      }
1935    }
1936  }
1937 
1938    // If not all coedges were paired up, can't proceed.
1939  if( sorted_coedges.size() != keep_count )
1940    return 0;
1941 
1942    // If dead is reversed wrt keep, reverse it such that
1943    // both curves have the same relative sense.
1944  if( reverse )
1945  {
1946    dead->reverse();
1947    for( coedge = dead->first_coedge();
1948         coedge != 0;
1949         coedge = dead->next_coedge( coedge) )
1950      coedge->reverse();
1951  }
1952 
1953    // Combine the CoEdges
1954  sorted_coedges.reset();
1955  for ( keep_coedge = keep->first_coedge();
1956        keep_coedge != 0;
1957        keep_coedge = keep->next_coedge( keep_coedge ) )
1958  {
1959    CompositeCoEdge* dead_coedge = sorted_coedges.get_and_step();
1960    keep_coedge->combine( dead_coedge, prepend );
1961   
1962    if ( dead_coedge->owner() )
1963      dead_coedge->owner()->remove_bridge( dead_coedge );
1964    delete dead_coedge;
1965  }
1966 
1967 
1968    // hide point
1969  keep->hidden_entities().hide( common );
1970 
1971    // combine curves
1972  keep->combine( dead, prepend );
1973  if (prepend)
1974    keep->start_point( dead->other_point( common ) );
1975  else
1976    keep->end_point( dead->other_point( common ) );
1977 
1978  if (dead->owner())
1979    dead->owner()->remove_bridge(dead);
1980  dead->start_point(0);
1981  dead->end_point(0);
1982  delete dead;
1983 
1984  if( remove_partitions )
1985    remove_partition_point( common );
1986 
1987  return keep;
1988}
1989
1990
1991//-------------------------------------------------------------------------
1992// Purpose       : Restore hidden point
1993//
1994// Special Notes : May create point-curve if point is hidden by a surface.
1995//
1996// Creator       : Jason Kraftcheck
1997//
1998// Creation Date : 02/27/04
1999//-------------------------------------------------------------------------
2000CubitStatus CompositeEngine::restore_point( Point* point )
2001{
2002  HiddenEntitySet* set;
2003 
2004  CompositePoint* comp = dynamic_cast<CompositePoint*>(point);
2005  if (!comp)
2006    comp = dynamic_cast<CompositePoint*>(point->owner());
2007  if (!comp)
2008    return CUBIT_FAILURE;
2009 
2010  set = dynamic_cast<HiddenEntitySet*>(comp->owner());
2011  if (!set)
2012    return CUBIT_FAILURE;
2013 
2014  if (dynamic_cast<CompositeCurve*>(set->owner()))
2015  {
2016    point = comp->get_point();
2017    if (!restore_point_in_curve(comp))
2018      return CUBIT_FAILURE;
2019   
2020      // check if we still have a composite point
2021      // if this was the only point splitting the curve,
2022      // then the composite point will have been destroyed.
2023    comp = dynamic_cast<CompositePoint*>(point->owner());
2024    if (!comp)
2025      return CUBIT_SUCCESS;
2026   
2027      // If the point is no longer hidden, we're done.
2028    set = dynamic_cast<HiddenEntitySet*>(comp->owner());
2029    if (!set)
2030      return CUBIT_SUCCESS;
2031  }
2032 
2033    // Need to create point-curve?
2034  if (dynamic_cast<CompositeSurface*>(set->owner()))
2035  {
2036    if (!restore_point_in_surface(comp))
2037      return CUBIT_FAILURE;
2038   
2039      // If the point is no longer hidden, we're done.
2040    set = dynamic_cast<HiddenEntitySet*>(comp->owner());
2041    if (!set)
2042      return CUBIT_SUCCESS;
2043  }
2044 
2045    // Something went wrong.
2046  return CUBIT_FAILURE;
2047}
2048   
2049
2050
2051//-------------------------------------------------------------------------
2052// Purpose       : Restore a point removed when a curve was composited
2053//                 (split a composite point)
2054//
2055// Special Notes :
2056//
2057// Creator       : Jason Kraftcheck
2058//
2059// Creation Date : 03/13/02
2060//-------------------------------------------------------------------------
2061CubitStatus CompositeEngine::restore_point_in_curve( Point* point )
2062{
2063    // find CompositePoint
2064  CompositePoint* comppoint = dynamic_cast<CompositePoint*>(point);
2065  if( !comppoint )
2066    comppoint = dynamic_cast<CompositePoint*>(point->owner());
2067  if( !comppoint )
2068    return CUBIT_FAILURE;
2069
2070  // find CompositeCurve.
2071  HiddenEntitySet* hs = dynamic_cast<HiddenEntitySet*>(comppoint->owner());
2072  if( !hs )
2073    return CUBIT_FAILURE;
2074  CompositeCurve* compcurve = dynamic_cast<CompositeCurve*>(hs->owner());
2075  if( !compcurve )
2076    return CUBIT_FAILURE;
2077 
2078    // find which curves in the composite contain the point
2079  DLIList<TopologyBridge*> points;
2080  int index = -1;
2081  for( int i = 0; i < compcurve->num_curves() && index < 0; i++ )
2082  {
2083    Curve* curve = compcurve->get_curve(i);
2084    points.clean_out();
2085    curve->get_children( points, true, COMPOSITE_LAYER );
2086    for( int j = points.size(); j--; )
2087    {
2088      Point* pt = dynamic_cast<Point*>(points.get_and_step());
2089      assert( pt!= NULL );
2090      if( pt == comppoint )
2091      {
2092        index = i;
2093        break;
2094      }
2095    }
2096  }
2097 
2098  assert( index >= 0 );
2099  Curve *curve1, *curve2;
2100  return split( compcurve, index, curve1, curve2 );
2101}
2102
2103
2104 
2105 
2106 
2107
2108//-------------------------------------------------------------------------
2109// Purpose       : Split a composite at the index-th point (after the
2110//                 index-th underlying curve)
2111//
2112// Special Notes :
2113//
2114// Creator       : Jason Kraftcheck
2115//
2116// Creation Date : 03/13/02
2117//-------------------------------------------------------------------------
2118CubitStatus CompositeEngine::split( CompositeCurve* curve, int index,
2119                                    Curve*& result1, Curve*& result2 )
2120{
2121  result1 = result2 = 0;
2122 
2123    // Split the composite geometry
2124  CompositeCurve* new_curve = curve->split( curve->get_curve(index) );
2125  if( !new_curve )
2126    return CUBIT_FAILURE;
2127  HiddenEntitySet* ownerSet = dynamic_cast<HiddenEntitySet*>(curve->owner());
2128  if( ownerSet )
2129    ownerSet->hide(new_curve);
2130 
2131    // Split owning CoEdges
2132  for( CompositeCoEdge* old_coe = curve->first_coedge();
2133       old_coe != 0;
2134       old_coe = curve->next_coedge( old_coe ) )
2135  {
2136    CompositeCoEdge* new_coe = old_coe->split( index );
2137    assert( new_coe != NULL );
2138    new_curve->add( new_coe );
2139    if( ownerSet )
2140      ownerSet->hide(new_coe);
2141   
2142    if( old_coe->get_loop() )
2143        old_coe->get_loop()->insert_after( new_coe, old_coe );
2144  }
2145 
2146    // update end point of original curve
2147  DLIList<TopologyBridge*> children;
2148  int last = curve->num_curves() - 1;
2149  Curve* last_curve = curve->get_curve(last);
2150  children.clean_out();
2151  last_curve->get_children( children, true, COMPOSITE_LAYER );
2152  assert( children.size() == 2 );
2153  children.reset();
2154  if( curve->get_sense(last) == CUBIT_FORWARD )
2155    children.step();
2156  CompositePoint* endpt = dynamic_cast<CompositePoint*>(children.get());
2157  assert( !!endpt );
2158  CompositePoint* oldendpt = curve->end_point();
2159  curve->end_point( endpt );
2160 
2161    // attach start and end point to new curve
2162  children.clean_out();
2163  Curve* first_curve = new_curve->get_curve(0);
2164  first_curve->get_children( children, true, COMPOSITE_LAYER );
2165  assert( children.size() == 2 );
2166  children.reset();
2167  if( new_curve->get_sense(0) == CUBIT_REVERSED )
2168    children.step();
2169  CompositePoint* startpt = dynamic_cast<CompositePoint*>(children.get());
2170  assert( startpt!= NULL );
2171  new_curve->start_point( startpt );
2172  new_curve->end_point( oldendpt );
2173
2174    // unhide restored (split) point
2175  HiddenEntitySet& old_hidden = curve->hidden_entities();
2176  old_hidden.restore( curve->end_point() );
2177  old_hidden.restore( new_curve->start_point() );
2178  if( ownerSet )
2179  {
2180    ownerSet->hide(curve->end_point());
2181    if(new_curve->start_point() != curve->end_point() )
2182      ownerSet->hide(new_curve->start_point());
2183  }
2184 
2185    // move other hidden points from old curve to new curve
2186    // as needed
2187  for( int j = 0; j < new_curve->num_curves(); j++ )
2188  {
2189    Curve* r_curve = new_curve->get_curve(j);
2190    children.clean_out();
2191    r_curve->get_children( children, true, COMPOSITE_LAYER );
2192    Point* sp = dynamic_cast<Point*>(children.get_and_step() );
2193    Point* ep = dynamic_cast<Point*>(children.get_and_step() );
2194    assert( sp && ep && sp != ep );
2195    if( old_hidden.restore( sp ) )
2196      new_curve->hidden_entities().hide( sp );
2197    if( old_hidden.restore( ep ) )
2198      new_curve->hidden_entities().hide( ep );
2199  }
2200
2201    // Remove composite geometry if a 'composite' of one curve
2202  result1 = curve;
2203  result2 = new_curve;
2204  if( curve->num_curves() == 1 && !ownerSet &&
2205      !curve->has_parent_composite_surface() )
2206    result1 = remove_composite( curve );
2207  if( new_curve->num_curves() == 1 && !ownerSet && 
2208      !new_curve->has_parent_composite_surface() )
2209    result2 = remove_composite( new_curve );
2210   
2211  return CUBIT_SUCCESS;
2212}
2213
2214
2215//-------------------------------------------------------------------------
2216// Purpose       : Create a composite surface by removing a curve
2217//
2218// Special Notes :
2219//
2220// Creator       : Jason Kraftcheck
2221//
2222// Creation Date : 03/13/02
2223//-------------------------------------------------------------------------
2224CompositeSurface* CompositeEngine::remove_curve( Curve* dead_curve,
2225                                                 bool remove_partitions,
2226                                                 Surface* survivor )
2227{
2228  DLIList<TopologyBridge*> temp, coedges, loops, surfaces, curves,
2229                           surf1_shells, surf2_shells;
2230 
2231  if( dynamic_cast<CompositeCurve*>(dead_curve->owner()) )
2232    dead_curve = dynamic_cast<Curve*>(dead_curve->owner());
2233 
2234    // If this is a null-geometry composite curve (a composite
2235    // point-curve without a corresponding real point-curve),
2236    // just destroy it and hide the defining point.
2237  CompositeCurve* compcurve = dynamic_cast<CompositeCurve*>(dead_curve);
2238  if (compcurve && compcurve->num_curves() == 0)
2239  {
2240    CompositeSurface* surf = compcurve->first_coedge()->get_loop()->get_surface();
2241    CompositePoint* geom_pt = destroy_point_curve(compcurve);
2242    surf->hidden_entities().hide(geom_pt);
2243    return surf;
2244  }
2245 
2246    // Get two coedges to remove, and put curve(s) in 'curves'
2247  dead_curve->get_parents_virt( coedges );
2248  if( coedges.size() != 2 ) 
2249    return 0;
2250 
2251  coedges.reset();
2252  TopologyBridge* coedge1 = coedges.get_and_step();
2253  TopologyBridge* coedge2 = coedges.get_and_step();
2254 
2255    // Get surfaces corresponding to loops
2256  loops.clean_out();
2257  coedge1->get_parents_virt( loops );
2258  assert( loops.size() == 1 );
2259  surfaces.clean_out();
2260  loops.get()->get_parents_virt( surfaces );
2261  assert( surfaces.size() == 1 );
2262  Surface* surface1 = dynamic_cast<Surface*>(surfaces.get());
2263 
2264  loops.clean_out();
2265  coedge2->get_parents_virt( loops );
2266  assert( loops.size() == 1 );
2267  surfaces.clean_out();
2268  loops.get()->get_parents_virt( surfaces );
2269  assert( surfaces.size() == 1 );
2270  Surface* surface2 = dynamic_cast<Surface*>(surfaces.get());
2271 
2272  if (surface2 == survivor)
2273    std::swap(surface1,surface2);
2274 
2275    // Make sure surfaces have same parent shells
2276  surface1->get_parents_virt( surf1_shells );
2277  surface2->get_parents_virt( surf2_shells );
2278  if( surf1_shells != surf2_shells )
2279    return 0;
2280 
2281    // get/make composites of surfaces
2282  bool created_surf1 = false, created_surf2 = false;
2283  CompositeSurface* compsurf1 = dynamic_cast<CompositeSurface*>(surface1);
2284  if( ! compsurf1 )
2285  {
2286    compsurf1 = replace_surface( surface1 );
2287    created_surf1 = true;
2288  }
2289 
2290  CompositeSurface* compsurf2 = 0;
2291  if( surface2 == surface1 )
2292  {
2293    compsurf2 = compsurf1;
2294  }
2295  else
2296  {
2297    compsurf2 = dynamic_cast<CompositeSurface*>(surface2);
2298    if( !compsurf2 )
2299    {
2300      compsurf2 = replace_surface( surface2 );
2301      created_surf2 = true;
2302    }
2303  }
2304  assert( compsurf1 && compsurf2 );
2305 
2306    // get composite(s) of curve(s)
2307  compcurve = dynamic_cast<CompositeCurve*>(dead_curve);
2308  if( !compcurve) 
2309    compcurve = dynamic_cast<CompositeCurve*>(dead_curve->owner());
2310  assert( !!compcurve );
2311 
2312    // Get composite coedges
2313  CompositeCoEdge *compcoedge1 = dynamic_cast<CompositeCoEdge*>(coedge1);
2314  if (!compcoedge1)
2315    compcoedge1 = dynamic_cast<CompositeCoEdge*>(coedge1->owner());
2316  CompositeCoEdge *compcoedge2 = dynamic_cast<CompositeCoEdge*>(coedge2);
2317  if (!compcoedge2)
2318    compcoedge2 = dynamic_cast<CompositeCoEdge*>(coedge2->owner());
2319 
2320    // combine the composite surfaces (not loops yet.)
2321  if( compsurf1 != compsurf2 )
2322  {
2323      // If second surface has opposite sense, fix it so
2324      // that both have the same sense.
2325    if( compcoedge2->sense() == compcoedge1->sense() )
2326    {
2327      bool b_reverse_coedges = true; // automatically handle reversing the coedges for the loop
2328      compsurf2->reverse_sense();
2329      for( CompositeLoop* loop = compsurf2->first_loop();
2330           loop != 0;
2331           loop = compsurf2->next_loop( loop ) )
2332        loop->reverse(b_reverse_coedges);
2333    }
2334   
2335      // Move all loops from old surface to new
2336    while( CompositeLoop* loop = compsurf2->first_loop() )
2337    {
2338      compsurf2->remove( loop );
2339      compsurf1->add( loop );
2340    }
2341   
2342      // Combine the set of underlying, real surfaces
2343    compsurf1->combine( compsurf2 );
2344    if( compsurf2->owner() )
2345      compsurf2->owner()->remove_bridge( compsurf2 );
2346    delete compsurf2;
2347    compsurf2 = 0;
2348  }
2349 
2350  CompositeLoop* loop1 = compcoedge1->get_loop();
2351  CompositeLoop* loop2 = compcoedge2->get_loop();
2352    // same loop => remove sipe || split loop
2353  if( loop1 == loop2 ) 
2354  {
2355      // split loop
2356    if( loop1->next_coedge( compcoedge1 ) != compcoedge2 &&
2357        loop1->prev_coedge( compcoedge1 ) != compcoedge2 )
2358    {
2359      loop2 = new CompositeLoop();
2360      CompositeCoEdge* coedge = loop1->next_coedge( compcoedge1 );
2361      CompositeCoEdge* prev = 0;
2362      while( coedge != compcoedge2 )
2363      {
2364        loop1->remove( coedge );
2365        loop2->insert_after( coedge, prev );
2366        prev = coedge;
2367        coedge = loop1->next_coedge( compcoedge1 );
2368      }
2369      compsurf1->add( loop2 );
2370    }
2371     
2372    loop1->remove( compcoedge1 );
2373    loop1->remove( compcoedge2 );
2374    if( loop1->num_coedges() == 0 )
2375    {
2376      compsurf1->remove( loop1 );
2377      delete loop1;
2378    }
2379  }
2380    // stitch loops
2381  else 
2382  {
2383    CompositeCoEdge* coedge;
2384   
2385      // insert coedges
2386    while( loop2->num_coedges() > 1 )  // all but the dead one
2387    {
2388      coedge = loop2->next_coedge( compcoedge2 );
2389      loop2->remove( coedge );
2390      loop1->insert_before( coedge, compcoedge1 );
2391    }
2392    loop1->remove( compcoedge1 );
2393    loop2->remove( compcoedge2 );
2394    assert( loop2->num_coedges() == 0 );
2395    if( loop2->get_surface() )
2396      loop2->get_surface()->remove( loop2 );
2397    delete loop2;
2398   
2399      // If loops only had one coedge each, then we
2400      // just removed a hole.
2401    if( loop1->num_coedges() == 0 )
2402    {
2403      if( loop1->get_surface() )
2404        loop1->get_surface()->remove( loop1 );
2405      delete loop1;
2406    }
2407  }
2408 
2409  compsurf1->hidden_entities().hide( compcoedge1 );
2410  compsurf1->hidden_entities().hide( compcoedge2 );
2411 
2412    // clean up dead curve(s) and points
2413  curves.clean_out();
2414  compcurve->start_point()->get_parents_virt( curves );
2415  if( curves.size() == 1 )
2416    compsurf1->hidden_entities().hide( compcurve->start_point() );
2417  curves.clean_out();
2418  compcurve->end_point()->get_parents_virt( curves );
2419  if( curves.size() == 1 )
2420    compsurf1->hidden_entities().hide( compcurve->end_point() );
2421  compsurf1->hidden_entities().hide( compcurve );
2422 
2423  if( remove_partitions )
2424    remove_partition_curves( compcurve );
2425 
2426  return compsurf1;
2427}
2428
2429
2430static void cme_hide_surface( HiddenEntitySet& set,
2431                              CompositeSurface* surface )
2432{
2433  set.hide( surface );
2434  CompositeLoop* loop = 0;
2435  while (NULL != (loop = surface->next_loop( loop )))
2436  {
2437    set.hide( loop );
2438    CompositeCoEdge* coedge = loop->first_coedge();
2439    do {
2440      set.hide( coedge );
2441     
2442      bool hide_curve = true;
2443      CompositeCurve* curve = coedge->get_curve();
2444      CompositeCoEdge* curve_coedge = 0;
2445      while ((curve_coedge = curve->next_coedge( curve_coedge )))
2446        if (curve_coedge->owner() != &set)
2447          { hide_curve = false; break; }
2448     
2449      if (hide_curve)
2450      {
2451        set.hide( curve );
2452        int num_pts = 1 + (curve->start_point() == curve->end_point());
2453        for (int i = 0; i < num_pts; i++)
2454        {
2455          CompositePoint* pnt = i ? curve->end_point() : curve->start_point();
2456          bool hide_pnt = true;
2457          CompositeCurve* pnt_curve = 0;
2458          while ((pnt_curve = pnt->next_curve( pnt_curve )))
2459            if (pnt_curve->owner() != &set)
2460              { hide_pnt = false; break; }
2461         
2462          if (hide_pnt)
2463            set.hide( pnt );
2464        }
2465      }
2466    } while((coedge = loop->next_coedge(coedge)) != loop->first_coedge());
2467  }
2468}
2469
2470static void cme_unhide_surface( CompositeSurface* surf )
2471{
2472  HiddenEntitySet* set = dynamic_cast<HiddenEntitySet*>(surf->owner());
2473  assert( !!set );
2474  set->restore( surf );
2475  CompositeLoop* loop = 0;
2476  while (NULL != (loop = surf->next_loop( loop )))
2477  {
2478    set->restore( loop );
2479    CompositeCoEdge* coedge = loop->first_coedge();
2480    do {
2481      if (coedge->owner() == set)
2482      {
2483        CompositeCurve* curve = coedge->get_curve();
2484        set->restore( coedge );
2485        set->restore( curve );
2486        if (curve->start_point()->owner() == set)
2487          set->restore( curve->start_point() );
2488        if (curve->end_point()->owner() == set)
2489          set->restore( curve->end_point() );
2490      }
2491    } while ((coedge = loop->next_coedge(coedge)) != loop->first_coedge());
2492  }
2493}
2494 
2495
2496
2497//-------------------------------------------------------------------------
2498// Purpose       : Create composite volume by removing a surface
2499//
2500// Special Notes :
2501//
2502// Creator       : Jason Kraftcheck
2503//
2504// Creation Date : 06/10/04
2505//-------------------------------------------------------------------------
2506CompositeLump* CompositeEngine::remove_surface( Surface* dead_surf,
2507                                                Surface* stitch_partner,
2508                                                bool /*remove_partitions*/  )
2509{
2510  bool okay = true;
2511  Surface* sptr;
2512  if ((sptr = dynamic_cast<Surface*>(dead_surf->owner())))
2513    dead_surf = sptr;
2514  if ((sptr = dynamic_cast<Surface*>(stitch_partner->owner())))
2515    stitch_partner = sptr;
2516 
2517    // Get composite surfaces
2518  bool replaced_1 = false, replaced_2 = false;
2519  CompositeSurface *surf1 = 0, *surf2 = 0;
2520  if (NULL == (surf1 = dynamic_cast<CompositeSurface*>(dead_surf)))
2521  {
2522    surf1 = replace_surface( dead_surf );
2523    replaced_1 = true;
2524  }
2525  if (NULL == stitch_partner)
2526  {
2527    surf2 = surf1;
2528  }
2529  else if (NULL == (surf2 = dynamic_cast<CompositeSurface*>(stitch_partner)))
2530  {
2531    surf2 = replace_surface( stitch_partner );
2532    replaced_2 = true;
2533  } 
2534 
2535    // Check if surfaces are stitched
2536  if (surf2 != surf1)
2537  {
2538    std::set<CompositeLoop*> used_loops;
2539    CompositeLoop* loop = 0;
2540    while (NULL != (loop = surf1->next_loop(loop)))
2541    {
2542      CompositeCoEdge* coedge1 = loop->first_coedge();
2543      CompositeCurve* curve = coedge1->get_curve();
2544      CompositeCoEdge* coedge2 = 0;
2545      while (NULL != (coedge2 = curve->next_coedge(coedge2)))
2546        if (coedge2->get_loop() &&
2547            coedge2->get_loop()->get_surface() == surf2)
2548          break;
2549     
2550      if (!coedge2) 
2551      {
2552        break;
2553        okay = false;
2554      }
2555     
2556      CompositeLoop* loop2 = coedge2->get_loop();
2557      if (used_loops.insert( loop2 ).second == false)
2558      {
2559        okay = false;
2560        break;
2561      }
2562     
2563      CompositeCoEdge* coedge = coedge1;
2564      while ((coedge = loop->next_coedge(coedge)) != coedge1)
2565      {
2566        curve = coedge->get_curve();
2567        coedge2 = 0;
2568        while (NULL != (coedge2 = curve->next_coedge(coedge2)))
2569          if (coedge2->get_loop() == loop2)
2570            break;
2571       
2572        if (!coedge2)
2573        {
2574          okay = false;
2575          break;
2576        }
2577      }
2578    }
2579    surf1->stitch( surf2 );
2580   
2581    if (!okay)
2582    {
2583      if (replaced_1)
2584        remove_composite( surf1 );
2585      if (replaced_2)
2586        remove_composite( surf2 );
2587      return 0;
2588    }
2589  }
2590 
2591    // Replace volumes/bodies with composites, combine bodies if necessary
2592  bool combined_bodies = false;
2593  bool replaced_body = false;
2594  DLIList<BodySM*> body_list;
2595  surf1->bodysms( body_list );
2596  if (body_list.size() != 1)
2597    return 0;
2598 
2599  BodySM* body1 = body_list.pop();
2600  BodySM* body2 = 0;
2601  CompositeBody* body = 0;
2602 
2603  if (surf2)
2604  {
2605    surf2->bodysms( body_list );
2606    if (body_list.size() != 1)
2607      return 0;
2608    body2 = body_list.pop();
2609  }
2610 
2611  if (body2 && body2 != body1)
2612  {
2613    body = combine_bodies( body1, body2 );
2614    combined_bodies = true;
2615  }
2616  else
2617  {
2618    if (NULL == (body = dynamic_cast<CompositeBody*>(body1)) &&
2619        NULL == (body = dynamic_cast<CompositeBody*>(body1->owner())))
2620    {
2621      body = replace_body( body1 );
2622      replaced_body = true;
2623    }
2624  }
2625 
2626  if (!body)
2627    return 0;
2628 
2629    // Get CoSurfaces to combine must be exactly two of them.
2630  CompositeCoSurf *cosurf1 = 0, *cosurf2 = 0;
2631  cosurf1 = surf1->next_co_surface(NULL);
2632  cosurf2 = surf1->next_co_surface(cosurf1);
2633  if (!cosurf1)
2634  {
2635    okay = false;
2636  }
2637  else if (cosurf2)
2638  {
2639    if (surf2 || surf1->next_co_surface(cosurf2))
2640      okay = false;
2641  }
2642  else if (surf2)
2643  {
2644    cosurf2 = surf2->next_co_surface(NULL);
2645    if (!cosurf2 || surf2->next_co_surface(cosurf2))
2646      okay = false;
2647  }
2648  if (!okay)
2649  {
2650//    if (replaced_body)
2651//      restore_body( body );
2652    return 0;
2653  }
2654 
2655 
2656    // combine the composite lumps (not shells yet.)
2657  CompositeLump* lump1 = cosurf1->get_shell()->get_lump();
2658  CompositeLump* lump2 = cosurf2->get_shell()->get_lump();
2659  if( lump1 != lump2 )
2660  {
2661   
2662      // Move all shells from old lump to new
2663    while( CompositeShell* shell = lump2->first_shell() )
2664    {
2665      lump2->remove( shell );
2666      lump1->add( shell );
2667    }
2668   
2669      // Combine the set of underlying, real lumps
2670    lump1->combine( lump2 );
2671    if( lump2->owner() )
2672      lump2->owner()->remove_bridge( lump2 );
2673    body->remove(lump2);
2674    delete lump2;
2675    lump2 = 0;
2676  }
2677 
2678    // remove surface(s)
2679  CompositeShell* shell1 = cosurf1->get_shell();
2680  CompositeShell* shell2 = cosurf2->get_shell();
2681  cme_hide_surface( lump1->hidden_entities(), surf1 );
2682  if (surf2)
2683    cme_hide_surface( lump1->hidden_entities(), surf2 );
2684  delete cosurf1;
2685  delete cosurf2;
2686
2687  if (shell1 != shell2)
2688  {
2689    while (CompositeCoSurf* cosurf = shell2->next_co_surf(0))
2690    {
2691      shell2->remove( cosurf );
2692      shell1->add( cosurf );
2693    }
2694    lump1->remove( shell2 );
2695    delete shell2;
2696  }
2697  else // if (shell1 == shell2)
2698  {
2699    shell2 = split_shell( shell1 );
2700    if (shell2)
2701      lump1->add( shell2 );
2702  }
2703 
2704  return lump1;
2705}
2706
2707
2708//-------------------------------------------------------------------------
2709// Purpose       : Test if a CompositeShell needs to be split, and
2710//                 split it
2711//
2712// Special Notes : Copied from PartitionEngine::split_shell
2713//
2714// Creator       : Jason Kraftcheck
2715//
2716// Creation Date : 06/11/04
2717//-------------------------------------------------------------------------
2718CompositeShell* CompositeEngine::split_shell( CompositeShell* shell_to_split )
2719{
2720  std::map<CompositeSurface*, int> marks;
2721
2722    // Make sure all cosurface surface marks are cleared
2723#ifdef BOYD17
2724  DLIList<CompositeCoEdge*> coedge_list;
2725#endif
2726  CompositeCoSurf* cosurf = 0;
2727  while( (cosurf = shell_to_split->next_co_surf( cosurf )) )
2728    marks[cosurf->get_surface()] = 0;
2729 
2730    // Identify non-manifold surfaces, marking them either
2731    // with a 2 if they can be used to split the volume
2732    // (if they are part of a connected patch for which the
2733    // bounadary of that patch intersects the volume boundary
2734    // at all curves) or a 3 if they are other non-manifold
2735    // surfaces.  This will get a bit tricky if there are
2736    // non-manifold surfaces hanging off of the patch of
2737    // split surfaces.
2738 
2739    // First for all non-manifold surfaces, if the surface has
2740    // a curve that is not shared with any other surface, mark
2741    // it with a 3.  Otherwise mark it with a 2.
2742  cosurf = 0;
2743  DLIList<CompositeSurface*> surf_stack;
2744  while ( (cosurf = shell_to_split->next_co_surf(cosurf)) )
2745  {
2746    CompositeSurface* surf = cosurf->get_surface();
2747      // If we haven't done this surface yet and it is non-manifold
2748    if ( !marks[surf] && surf->find_next(cosurf) )
2749    {
2750      marks[surf] = 2;
2751      bool no_free_curve = true;
2752      CompositeLoop* loop = 0;
2753      while( no_free_curve && (loop = surf->next_loop(loop)) ) 
2754      {
2755        CompositeCoEdge* coedge = loop->first_coedge();
2756        do 
2757        {
2758          CompositeCurve* curve = coedge->get_curve();
2759            // If the curve has more than one coedge, it
2760            // is not a free curve (this also accounts for
2761            // the case where the curve is a non-manifold
2762            // curve on the surface interioir -- e.g. a sipe)
2763          if ( !curve->next_coedge(coedge) && 
2764               curve->next_coedge(0) == coedge )
2765          {
2766            no_free_curve = false;
2767            break;
2768          }
2769          coedge = loop->next_coedge(coedge);
2770        } while( coedge != loop->first_coedge() );
2771      }
2772     
2773      if( !no_free_curve )
2774      {
2775        marks[surf] = 3;
2776        surf_stack.append( surf );
2777      }
2778    }
2779  }
2780 
2781    // Now for each surface we marked with a three, traverse
2782    // and mark adjacent surfaces until we come to a curve
2783    // connected to more that two surfaces.
2784  while( surf_stack.size() ) 
2785  {
2786    CompositeSurface* surf = surf_stack.pop();
2787    CompositeLoop* loop = 0;
2788    while ( (loop = surf->next_loop(loop)) )
2789    {
2790      CompositeCoEdge* coedge = loop->first_coedge();
2791      do 
2792      {
2793        CompositeCurve* curve = coedge->get_curve();
2794        int split_count = 0;
2795        int boundary_count = 0;
2796        CompositeCoEdge* curve_coe = 0;
2797        while ( (curve_coe = curve->next_coedge(curve_coe) ) != NULL )
2798        {
2799          CompositeSurface* curve_surf = curve_coe->get_loop()->get_surface();
2800          switch ( marks[curve_surf] ) 
2801          {
2802            case 0: boundary_count++; break;
2803            case 2: split_count++;    break;
2804          }
2805        }
2806       
2807        if ( split_count == 1 && !boundary_count )
2808        {
2809          curve_coe = 0;
2810          while ( (curve_coe = curve->next_coedge(curve_coe) ) != NULL )
2811          {
2812            CompositeSurface* curve_surf = curve_coe->get_loop()->get_surface();
2813            if ( marks[curve_surf] == 2 )
2814            {
2815              marks[curve_surf] = 3;
2816              surf_stack.append(curve_surf);
2817            }
2818          }
2819        }
2820       
2821        coedge = loop->next_coedge( coedge );
2822      } while( coedge != loop->first_coedge() );
2823    }
2824  }
2825 
2826    // Now build a new shell by traversing cofaces, marking
2827    // each with that will go in a new shell with a 1.
2828 
2829    // Start with any cosurf that does not have a free
2830    // non-manifold surface (marked with a 3).  We'll handle
2831    // free non-manifold surfaces later.
2832  std::set<CompositeCoSurf*> marked_cosurfs;
2833  DLIList<CompositeCoSurf*> cosurf_stack;
2834  cosurf = 0;
2835  while ( (cosurf = shell_to_split->next_co_surf(cosurf)) )
2836    if ( marks[cosurf->get_surface()] != 3 )
2837      break;
2838  if ( cosurf )
2839  {
2840    marked_cosurfs.insert(cosurf);
2841    cosurf_stack.append( cosurf );
2842  }
2843 
2844    // Traverse over adjacent cosurfaces, marking them with a 1
2845  while (cosurf_stack.size())
2846  {
2847    cosurf = cosurf_stack.pop();
2848    CompositeSurface* surf = cosurf->get_surface();
2849    CompositeLoop* loop = 0;
2850    while ( (loop = surf->next_loop(loop)) )
2851    {
2852      CompositeCoEdge* coedge = loop->first_coedge();
2853      do
2854      {
2855        CompositeCurve* curve = coedge->get_curve();
2856        CompositeCoEdge* curve_coe = 0;
2857        CompositeCoSurf *boundary_cosurf = 0, *split_cosurf = 0;
2858        int split_cosurf_count = 0;
2859        while ( (curve_coe = curve->next_coedge(curve_coe)) )
2860        {
2861          if ( curve_coe == coedge )
2862            continue;
2863         
2864          bool same_coe_sense = curve_coe->sense() == coedge->sense();
2865          CompositeSurface* curve_surf = curve_coe->get_loop()->get_surface();
2866          CompositeCoSurf* curve_cosurf = 0;
2867          while ( (curve_cosurf = curve_surf->next_co_surface(curve_cosurf)) )
2868          {
2869            if ( curve_cosurf->get_shell() != shell_to_split )
2870              continue;
2871           
2872            bool same_cos_sense = curve_cosurf->sense() == cosurf->sense();
2873            if ( same_cos_sense == same_coe_sense )
2874              continue;
2875           
2876              // Always choose split surface first if we
2877              // found one
2878            if ( marks[curve_cosurf->get_surface()] == 2 ) {
2879              split_cosurf_count++;
2880              split_cosurf = curve_cosurf;
2881            }
2882           
2883              // Skip other non-manifold surfaces.  We'll
2884              // handle those later.
2885            else if( marks[curve_cosurf->get_surface()] != 3 )
2886              boundary_cosurf = curve_cosurf;
2887          }
2888        }
2889       
2890        CompositeCoSurf* next_cosurf = split_cosurf ? split_cosurf : boundary_cosurf;
2891        if ( marked_cosurfs.find(next_cosurf) == marked_cosurfs.end()
2892             && split_cosurf_count < 2 )
2893        {
2894          marked_cosurfs.insert(next_cosurf);
2895          cosurf_stack.append(next_cosurf);
2896        }
2897     
2898        coedge = loop->next_coedge(coedge);
2899      } while( coedge != loop->first_coedge() );
2900    } // end while (loop)
2901  } // end while (cosurf_stack.size())
2902   
2903 
2904    // build lists of cosurfaces, one for each shell and
2905    // one of other non-manifold surfaces
2906  DLIList<CompositeCoSurf*> marked_list, unmarked_list, other_list;
2907  while( (cosurf = shell_to_split->next_co_surf(0)) )
2908  {
2909    shell_to_split->remove(cosurf);
2910    if ( marks[cosurf->get_surface()] == 3 )
2911      other_list.append( cosurf );
2912    else if( marked_cosurfs.find(cosurf) != marked_cosurfs.end() )
2913      marked_list.append( cosurf );
2914    else
2915      unmarked_list.append( cosurf );
2916  }
2917 
2918    // If one of marked_list or unmarked_list is empty,
2919    // we can't split the shell yet.  Put cofaces back in
2920    // shell and exit.
2921  if ( !marked_list.size() || !unmarked_list.size() )
2922  {
2923    marked_list += unmarked_list;
2924    marked_list += other_list;
2925    marked_list.reverse();
2926    while ( marked_list.size() )
2927    {
2928      cosurf = marked_list.pop();
2929      shell_to_split->add( cosurf );
2930    }
2931    return 0;
2932  }
2933 
2934    // Put unmarked list back in old shell
2935  unmarked_list.reverse();
2936  while ( unmarked_list.size() )
2937  {
2938    cosurf = unmarked_list.pop();
2939    shell_to_split->add(cosurf);
2940  }
2941 
2942    // Put marked list in new shell
2943  CompositeShell* new_shell = new CompositeShell;
2944  marked_list.reverse();
2945  while ( marked_list.size() )
2946  {
2947    cosurf = marked_list.pop();
2948    new_shell->add(cosurf);
2949  }
2950 
2951    // Now sort out other non-manifold surfaces
2952 
2953    // Clear marks and get list of surface from cosurfaces
2954  surf_stack.clean_out();
2955  while( other_list.size() )
2956  {
2957    cosurf = other_list.pop();
2958    CompositeSurface* surf = cosurf->get_surface();
2959    if ( marks[surf] )
2960      surf_stack.append(surf);
2961  }
2962 
2963  insert_nonmanifold_surfaces( surf_stack, shell_to_split, new_shell );
2964  return new_shell;
2965}
2966 
2967//-------------------------------------------------------------------------
2968// Purpose       : After a shell is split, determine which of the two
2969//                 resulting shells each non-manifold surface belongs in.
2970//
2971// Special Notes : Copied from PartitionEngine::insert_nonmanifold_surfaces
2972//
2973// Creator       : Jason Kraftcheck
2974//
2975// Creation Date : 06/11/04
2976//-------------------------------------------------------------------------
2977void CompositeEngine::insert_nonmanifold_surfaces( 
2978                                   DLIList<CompositeSurface*>& surf_stack,
2979                                   CompositeShell* shell1,
2980                                   CompositeShell* shell2 )
2981{
2982  DLIList<CompositeSurface*> known_list(surf_stack.size()), 
2983                           unknown_list(surf_stack.size());
2984 
2985  CompositeCoSurf* cosurf;
2986  CompositeSurface* surf;
2987  CompositeLoop* loop;
2988  CompositeCoEdge *coedge, *curve_coe;
2989  CompositeCurve* curve;
2990 
2991    // Loop until we've placed all the surfaces in one
2992    // shell or the other.
2993  while ( surf_stack.size() )
2994  {
2995    bool did_some = false;
2996   
2997      // Put any surfaces for which we immediately
2998      // know the shell into the appropriate shell.
2999      // Put others in known_list or unknown_list
3000      // depending on if we can determine which shell
3001      // they go in using a geometric comparison.
3002    known_list.clean_out();
3003    unknown_list.clean_out();
3004
3005      // Take all surfaces out of stack in this loop.
3006      // We might put some back in after the loop (thus
3007      // the outer loop.)
3008    while ( surf_stack.size() )
3009    {
3010      surf = surf_stack.pop();
3011     
3012      CompositeShell* known_shell = 0;
3013      bool found_shell = false;
3014      loop = 0;
3015      while ( (loop = surf->next_loop(loop)) )
3016      {
3017        coedge = loop->first_coedge();
3018        do
3019        {
3020          curve = coedge->get_curve();
3021          curve_coe = 0;
3022          while ( (curve_coe = curve->next_coedge(curve_coe)) )
3023          {
3024            CompositeSurface* surf = curve_coe->get_loop()->get_surface();
3025            cosurf = 0;
3026            while ( (cosurf = surf->next_co_surface( cosurf )) )
3027            {
3028              if( cosurf->get_shell() == shell1 ||
3029                  cosurf->get_shell() == shell2 )
3030              {
3031                found_shell = true;
3032                if ( known_shell && known_shell != cosurf->get_shell() )
3033                  known_shell = 0;
3034                else
3035                  known_shell = cosurf->get_shell();
3036              }
3037            }
3038          }
3039       
3040          coedge = loop->next_coedge(coedge);
3041        } while( coedge != loop->first_coedge() );
3042      } // end while(loop)
3043       
3044        // This surface does not intersect the shell at
3045        // any curve.  We can't do this one yet.
3046      if ( !found_shell )
3047      {
3048        unknown_list.append( surf );
3049        continue;
3050      }
3051     
3052        // This surface intersected both shells at some
3053        // curves, but did not have a curve that intersected
3054        // only one shell.  We can do this one geometricly
3055        // if we have to.
3056      if ( !known_shell )
3057      {
3058        known_list.append( surf );
3059        continue;
3060      }
3061     
3062        // If we got this far, then the surface had at least
3063        // one curve that intersected only one of the shells.
3064        // We know it goes in that shell.
3065      did_some = true;
3066      CompositeCoSurf* cosurf1 = surf->find_first((CompositeShell*)0);
3067      CompositeCoSurf* cosurf2 = surf->find_next(cosurf1);
3068      known_shell->add(cosurf1);
3069      known_shell->add(cosurf2);
3070   
3071    } // while(surf_stack)  -- the inside one
3072   
3073      // Unknown_list always goes back in surf_stack to
3074      // try again.
3075    surf_stack += unknown_list;
3076   
3077      // If we did some surfaces, then put the rest back
3078      // in surf_stack and try again.  If they intersect
3079      // one of the surfaces we did place in this iteration,
3080      // we can avoid needing to do geometric checks.
3081    if ( did_some )
3082    {
3083      surf_stack += known_list;
3084      continue;
3085    }
3086   
3087      // If known_list is empty, somethings wrong (we're
3088      // going to loop forever.)  Abort the loop and try
3089      // to recover as best we can.
3090    if( !known_list.size() )
3091      break;
3092   
3093      // choose a single surface in do a geometric comparison
3094      // for, and put the rest back in surf_stack
3095    surf = known_list.pop();
3096    surf_stack += known_list;
3097   
3098    bool in_shell = false;
3099    if ( ! inside_shell( shell2, surf, in_shell ) )
3100    {
3101        // if inside_shell failed, abort.
3102      surf_stack.append(surf);
3103      break;
3104    }
3105   
3106    CompositeShell* shell = in_shell ? shell2 : shell1;
3107    shell->add(surf->find_first((CompositeShell*)0));
3108    shell->add(surf->find_first((CompositeShell*)0));
3109  }
3110 
3111    // something went wrong
3112  if( surf_stack.size() )
3113  {
3114    PRINT_ERROR("Internal error splitting volume at %s:%d\n"
3115                "Topology may be invalid.  Please report this.\n",
3116                __FILE__, __LINE__);
3117    while( surf_stack.size() ) 
3118    {
3119      CompositeSurface* surf = surf_stack.pop();
3120      cosurf = 0;
3121      while( (cosurf = surf->next_co_surface(cosurf)) )
3122        if( !cosurf->get_shell() )
3123          shell1->add(cosurf);
3124    }
3125  }
3126}
3127
3128
3129CubitStatus CompositeEngine::inside_shell( CompositeShell* const shell,
3130                                           CompositeSurface* const surf,
3131                                           bool& result )
3132{
3133    // Find the curve and coedge at which the nonmanifold surface
3134    // intersects the shells
3135  CompositeLoop* loop = 0;
3136  CompositeCoEdge *nonman_coedge = 0;
3137  while ( !nonman_coedge && (loop = surf->next_loop(loop)) )
3138  {
3139    CompositeCoEdge* loop_coedge = loop->first_coedge();
3140    do 
3141    {
3142        // Check if this curve is the curve of intersection
3143        // Iterate through curve coedges.
3144      CompositeCurve* curve = loop_coedge->get_curve();
3145      CompositeCoEdge* curve_coedge = 0;
3146      while ( (curve_coedge = curve->next_coedge(curve_coedge)) )
3147      {
3148       
3149        CompositeSurface* coedge_surf = curve_coedge->get_loop()->get_surface();
3150        if( coedge_surf->find_first(shell) )
3151        {
3152          nonman_coedge = curve_coedge;
3153          break;
3154        }
3155      }
3156   
3157      loop_coedge = loop->next_coedge(loop_coedge);
3158    } while( !nonman_coedge && loop_coedge != loop->first_coedge