Salome HOME
336d67bc643130facbaee3b1251ab46093107761
[modules/geom.git] / src / GEOMAlgo / GEOMAlgo_Extractor.cxx
1 // Copyright (C) 2007-2023  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File:        GEOMAlgo_Extractor.cxx
24 // Created:
25 // Author:      Sergey KHROMOV
26 //
27
28
29 #include <GEOMAlgo_Extractor.hxx>
30
31 #include <BRep_Builder.hxx>
32 #include <BRep_Tool.hxx>
33 #include <BRepClass3d.hxx>
34 #include <BRepTools.hxx>
35 #include <BRepTools_WireExplorer.hxx>
36 #include <NCollection_Sequence.hxx>
37 #include <TopExp.hxx>
38 #include <TopExp_Explorer.hxx>
39 #include <TColStd_MapOfInteger.hxx>
40 #include <TopoDS.hxx>
41 #include <TopoDS_Edge.hxx>
42 #include <TopoDS_Face.hxx>
43 #include <TopoDS_Iterator.hxx>
44 #include <TopTools_IndexedMapOfShape.hxx>
45 #include <TopTools_ListIteratorOfListOfShape.hxx>
46 #include <TopTools_MapIteratorOfMapOfShape.hxx>
47 #include <TopTools_MapOfShape.hxx>
48
49
50 //=======================================================================
51 //function : GEOMAlgo_Extractor
52 //purpose  :
53 //=======================================================================
54 GEOMAlgo_Extractor::GEOMAlgo_Extractor()
55 {
56 }
57
58 //=======================================================================
59 //function : ~GEOMAlgo_Extractor
60 //purpose  :
61 //=======================================================================
62 GEOMAlgo_Extractor::~GEOMAlgo_Extractor()
63 {
64 }
65
66 //=======================================================================
67 //function : SetShape
68 //purpose  :
69 //=======================================================================
70 void GEOMAlgo_Extractor::SetShape(const TopoDS_Shape &theShape)
71 {
72   myShape = theShape;
73   myMapShapeAnc.Clear();
74   clear();
75 }
76
77 //=======================================================================
78 //function : SetShapesToRemove
79 //purpose  :
80 //=======================================================================
81 void GEOMAlgo_Extractor::SetShapesToRemove
82                         (const TopTools_ListOfShape &theSubShapes)
83 {
84   mySubShapes.Assign(theSubShapes);
85   clear();
86 }
87
88 //=======================================================================
89 //function : Perform
90 //purpose  :
91 //=======================================================================
92 void GEOMAlgo_Extractor::Perform()
93 {
94   clear();
95   myErrorStatus = 0;
96   //
97   checkData();
98
99   if(myErrorStatus) {
100     return;
101   }
102
103   if (myWarningStatus == 10) {
104     // The result is the same shape. Nothing is modified.
105     myResult = myShape;
106     return;
107   }
108
109   // Mark sub-shapes as removed and modified.
110   markShapes();
111
112   // Process Edges.
113   processShapes(TopAbs_EDGE);
114
115   // Process Wires.
116   processShapes(TopAbs_WIRE);
117
118   // Process Faces.
119   processShapes(TopAbs_FACE);
120
121   // Process Shells.
122   processShapes(TopAbs_SHELL);
123
124   // Process Solids.
125   processShapes(TopAbs_SOLID);
126
127   // Process Comp-Solids.
128   processShapes(TopAbs_COMPSOLID);
129
130   // Process Compounds.
131   processShapes(TopAbs_COMPOUND);
132
133   // Make the result.
134   myResult = makeResult(myShape);
135
136   TopTools_MapOfShape aMapFence;
137
138   makeHistory(myShape, aMapFence);
139 }
140
141 //=======================================================================
142 //function : GetResult
143 //purpose  :
144 //=======================================================================
145 const TopoDS_Shape &GEOMAlgo_Extractor::GetResult() const
146 {
147   return myResult;
148 }
149
150 //=======================================================================
151 //function : clear
152 //purpose  :
153 //=======================================================================
154 void GEOMAlgo_Extractor::clear()
155 {
156   myErrorStatus   = 1;
157   myWarningStatus = 0;
158   myResult.Nullify();
159   myRemoved.Clear();
160   myModified.Clear();
161   myNew.Clear();
162   myMapRemoved.Clear();
163   myMapModified.Clear();
164   myMapNewShapeAnc.Clear();
165 }
166
167 //=======================================================================
168 //function : checkData
169 //purpose  :
170 //=======================================================================
171 void GEOMAlgo_Extractor::checkData()
172 {
173   if (myShape.IsNull()) {
174     myErrorStatus = 10;
175     return;
176   }
177
178   if (mySubShapes.IsEmpty()) {
179     myWarningStatus = 10;
180     return;
181   }
182
183   TopTools_ListIteratorOfListOfShape anIter(mySubShapes);
184   TopTools_IndexedMapOfShape         anIndices;
185   TopTools_MapOfShape                aMapFence;
186
187   TopExp::MapShapes(myShape, anIndices);
188
189   while (anIter.More()) {
190     const TopoDS_Shape &aSubShape = anIter.Value();
191
192     if (aMapFence.Add(aSubShape)) {
193       // Check if it is a sub-shape of the given shape.
194       if (!anIndices.Contains(aSubShape)) {
195         myErrorStatus = 11;
196         return;
197       }
198
199       // Check if it is a main shape.
200       if (aSubShape.IsSame(myShape)) {
201         myErrorStatus = 12;
202         return;
203       }
204
205       anIter.Next();
206     } else {
207       // Remove duplicated index.
208       mySubShapes.Remove(anIter);
209     }
210   }
211
212   if (myMapShapeAnc.IsEmpty()) {
213     // Fill the map of shapes - ancestors.
214     makeMapShapeAncestors(myShape);
215   }
216
217   // Check if there are seam or degenerated edges on faces.
218   for (anIter.Initialize(mySubShapes); anIter.More(); anIter.Next()) {
219     const TopoDS_Shape &aSubShape = anIter.Value();
220
221     if (aSubShape.ShapeType() == TopAbs_EDGE) {
222       // Get the list of ancestor wires.
223       TopTools_ListOfShape               anAncWires;
224       TopTools_ListIteratorOfListOfShape anAncIt;
225
226       if (myMapShapeAnc.IsBound(aSubShape)) {
227         anAncIt.Initialize(myMapShapeAnc.Find(aSubShape));
228
229         for (; anAncIt.More(); anAncIt.Next()) {
230           const TopoDS_Shape &anAncShape = anAncIt.Value();
231
232           if (anAncShape.ShapeType() == TopAbs_WIRE) {
233             anAncWires.Append(anAncShape);
234           }
235         }
236       }
237
238       if (!anAncWires.IsEmpty()) {
239         // Check the ancestor faces.
240         Standard_Boolean hasFaces = Standard_False;
241         TopoDS_Edge      anEdge   = TopoDS::Edge(aSubShape);
242
243         for (anAncIt.Initialize(anAncWires); anAncIt.More(); anAncIt.Next()) {
244           const TopoDS_Shape &anAncShape = anAncIt.Value();
245
246           if (anAncShape.ShapeType() == TopAbs_FACE) {
247             TopoDS_Face aFace = TopoDS::Face(anAncShape);
248
249             if (BRepTools::IsReallyClosed(anEdge, aFace)) {
250               // Deletion of face's seam edge is not allowed
251               myErrorStatus = 13;
252               return;
253             }
254
255             hasFaces = Standard_True;
256           }
257         }
258
259         if (hasFaces && BRep_Tool::Degenerated(anEdge)) {
260           myErrorStatus = 14;
261           return;
262         }
263       }
264     }
265   }
266 }
267
268 //=======================================================================
269 //function : makeMapShapeAncestors
270 //purpose  :
271 //=======================================================================
272 void GEOMAlgo_Extractor::makeMapShapeAncestors(const TopoDS_Shape &theShape)
273 {
274   if (theShape.ShapeType() == TopAbs_VERTEX) {
275     // Vertex is the lowest type. It has no ancestors.
276     return;
277   }
278
279   TopoDS_Iterator     anIter(theShape);
280   TopTools_MapOfShape aMapFence;
281
282   for (; anIter.More(); anIter.Next()) {
283     const TopoDS_Shape &aSubShape = anIter.Value();
284
285     if (aMapFence.Add(aSubShape)) {
286       // Add theShape as an ancestor shape.
287       if (!myMapShapeAnc.IsBound(aSubShape)) {
288         myMapShapeAnc.Bind(aSubShape, TopTools_ListOfShape());
289       }
290
291       myMapShapeAnc.ChangeFind(aSubShape).Append(theShape);
292
293       // Recursively call this method for a sub-shape.
294       makeMapShapeAncestors(aSubShape);
295     }
296   }
297 }
298
299 //=======================================================================
300 //function : markShapes
301 //purpose  :
302 //=======================================================================
303 void GEOMAlgo_Extractor::markShapes()
304 {
305   TopTools_ListIteratorOfListOfShape anIter(mySubShapes);
306
307   // Mark sub-shapes as removed.
308   for (; anIter.More(); anIter.Next()) {
309     const TopoDS_Shape &aSubShape = anIter.Value();
310
311     markRemoved(aSubShape);
312   }
313
314   // Mark undestors of sub-shapes as modified.
315   for (anIter.Initialize(mySubShapes); anIter.More(); anIter.Next()) {
316     const TopoDS_Shape &aSubShape = anIter.Value();
317
318     markAncestorsModified(aSubShape);
319   }
320 }
321
322 //=======================================================================
323 //function : markRemoved
324 //purpose  :
325 //=======================================================================
326 void GEOMAlgo_Extractor::markRemoved(const TopoDS_Shape &theShape)
327 {
328   if (myMapRemoved.Add(theShape)) {
329     // Check sub-shapes.
330     TopoDS_Iterator     anIter(theShape);
331     TopTools_MapOfShape aMapFence;
332
333     for (; anIter.More(); anIter.Next()) {
334       const TopoDS_Shape &aSubShape = anIter.Value();
335
336       if (aMapFence.Add(aSubShape)) {
337         TopTools_ListIteratorOfListOfShape anAncIt
338                                 (myMapShapeAnc.Find(aSubShape));
339         Standard_Boolean                   isToRm = Standard_True;
340
341         for (; anAncIt.More(); anAncIt.Next()) {
342           const TopoDS_Shape &anAncShape = anAncIt.Value();
343
344           if (!myMapRemoved.Contains(anAncShape)) {
345             isToRm = Standard_False;
346             break;
347           }
348         }
349
350         if (isToRm) {
351           // Mark sub-shape as removed.
352           markRemoved(aSubShape);
353         }
354       }
355     }
356   }
357 }
358
359 //=======================================================================
360 //function : markAncestorsModified
361 //purpose  :
362 //=======================================================================
363 void GEOMAlgo_Extractor::markAncestorsModified(const TopoDS_Shape &theShape)
364 {
365   if (myMapShapeAnc.IsBound(theShape)) {
366     TopTools_ListIteratorOfListOfShape anAncIt(myMapShapeAnc.Find(theShape));
367
368     for (; anAncIt.More(); anAncIt.Next()) {
369       const TopoDS_Shape &anAncShape = anAncIt.Value();
370
371       if (!myMapRemoved.Contains(anAncShape) &&
372           !myMapModified.IsBound(anAncShape)) {
373         // Mark anAncShape as modified.
374         myMapModified.Bind(anAncShape, TopTools_ListOfShape());
375
376         // Mark its ancestors as modified.
377         markAncestorsModified(anAncShape);
378       }
379     }
380   }
381 }
382
383 //=======================================================================
384 //function : processShapes
385 //purpose  :
386 //=======================================================================
387 void GEOMAlgo_Extractor::processShapes(const TopAbs_ShapeEnum &theType)
388 {
389   TopExp_Explorer     anExp(myShape, theType);
390   TopTools_MapOfShape aMapFence;
391
392   for (; anExp.More(); anExp.Next()) {
393     TopoDS_Shape aShape = anExp.Current(); // Copy
394
395     if (aMapFence.Add(aShape)) {
396       if (myMapRemoved.Contains(aShape) ||
397           !myMapModified.IsBound(aShape)) {
398         // Skip removed or not modified shape.
399         continue;
400       }
401
402       aShape.Orientation(TopAbs_FORWARD);
403
404       switch(theType) {
405         case TopAbs_EDGE:
406           processEdge(aShape);
407           break;
408         case TopAbs_WIRE:
409           processWire(aShape);
410           break;
411         case TopAbs_FACE:
412         case TopAbs_SOLID:
413           processFOrSo(aShape);
414           break;
415         case TopAbs_SHELL:
416         case TopAbs_COMPSOLID:
417           processShOrCS(aShape);
418           break;
419         case TopAbs_COMPOUND:
420           processCompound(aShape);
421           break;
422         default:
423           break;
424       }
425     }
426   }
427
428   if (theType == TopAbs_FACE || theType == TopAbs_SOLID) {
429     // Clear duplicated edges from the faces and faces from solids
430     removeBoundsOnFOrSo(theType);
431   }
432 }
433
434 //=======================================================================
435 //function : processEdge
436 //purpose  :
437 //=======================================================================
438 void GEOMAlgo_Extractor::processEdge(const TopoDS_Shape &theEdge)
439 {
440   TopoDS_Iterator      anIter(theEdge);
441   TopTools_MapOfShape  aMapFence;
442   TopTools_ListOfShape aVtxList;
443
444   for (; anIter.More(); anIter.Next()) {
445     const TopoDS_Shape &aShapeVertex = anIter.Value();
446
447     if (aMapFence.Add(aShapeVertex)) {
448       if (myMapRemoved.Contains(aShapeVertex)) {
449         // This vertex is removed.
450         const TopAbs_Orientation anOri = aShapeVertex.Orientation();
451
452         if (anOri == TopAbs_FORWARD || anOri == TopAbs_REVERSED) {
453           // This edge will disappear from the result.
454           return;
455         }
456       } else {
457         // This vertex is not removed.
458         aVtxList.Append(aShapeVertex);
459       }
460     }
461   }
462
463   TopoDS_Shape aNewEdge = makeShape(theEdge, aVtxList);
464
465   myMapModified.ChangeFind(theEdge).Append(aNewEdge);
466 }
467
468 //=======================================================================
469 //function : processWire
470 //purpose  :
471 //=======================================================================
472 void GEOMAlgo_Extractor::processWire(const TopoDS_Shape &theWire)
473 {
474   // Get parent face for the wire.
475   TopoDS_Face aFace;
476
477   if (myMapShapeAnc.IsBound(theWire)) {
478     TopTools_ListIteratorOfListOfShape anIter(myMapShapeAnc.Find(theWire));
479
480     for (; anIter.More(); anIter.Next()) {
481       const TopoDS_Shape &aParent = anIter.Value();
482
483       if (aParent.ShapeType() == TopAbs_FACE) {
484         aFace = TopoDS::Face(aParent.Oriented(TopAbs_FORWARD));
485         break;
486       }
487     }
488   }
489
490   TopoDS_Wire                            aWire = TopoDS::Wire(theWire);
491   BRepTools_WireExplorer                 anExp(aWire, aFace);
492   NCollection_List<TopTools_ListOfShape> aListListEdges;
493   TopTools_ListOfShape                   aListEdges;
494
495   for (; anExp.More(); anExp.Next()) {
496     const TopoDS_Edge &anEdge = anExp.Current();
497
498     if (myMapRemoved.Contains(anEdge)) {
499       // This edge is removed.
500       if (!aListEdges.IsEmpty()) {
501         aListListEdges.Append(aListEdges);
502         aListEdges.Clear();
503       }
504     } else if (myMapModified.IsBound(anEdge)) {
505       // This edge is modified.
506       TopTools_ListOfShape aModifEdges;
507
508       getModified(anEdge, aModifEdges);
509
510       if (aModifEdges.IsEmpty()) {
511         // This edge is not created.
512         if (!aListEdges.IsEmpty()) {
513           aListListEdges.Append(aListEdges);
514           aListEdges.Clear();
515         }
516       } else {
517         const TopoDS_Shape aModifEdge = oriented(aModifEdges.First(), anEdge);
518
519         aListEdges.Append(aModifEdge);
520       }
521     } else {
522       // Get an edge as it is.
523       aListEdges.Append(anEdge);
524     }
525   }
526
527   if (!aListEdges.IsEmpty()) {
528     aListListEdges.Append(aListEdges);
529   }
530
531   if (!aListListEdges.IsEmpty()) {
532     TopTools_ListOfShape aListWires;
533
534     makeWires(theWire, aListListEdges, aListWires);
535     myMapModified.ChangeFind(theWire) = aListWires;
536   }
537 }
538
539 //=======================================================================
540 //function : processFOrSo
541 //purpose  :
542 //=======================================================================
543 void GEOMAlgo_Extractor::processFOrSo(const TopoDS_Shape &theFOrSo)
544 {
545   Standard_Boolean     isToCreate = Standard_True;
546   TopTools_ListOfShape aClosedSubShapes;
547   TopTools_ListOfShape aNewShapes;
548   TopoDS_Shape         anOuterSubShape;
549   //TopAbs_ShapeEnum     aShapeType;
550   TopAbs_ShapeEnum     aSubShapeType;
551
552   if (theFOrSo.ShapeType() == TopAbs_FACE) {
553     //aShapeType      = TopAbs_FACE;
554     aSubShapeType   = TopAbs_WIRE;
555     anOuterSubShape = BRepTools::OuterWire(TopoDS::Face(theFOrSo));
556   } else {
557     //aShapeType      = TopAbs_SOLID;
558     aSubShapeType   = TopAbs_SHELL;
559     anOuterSubShape = BRepClass3d::OuterShell(TopoDS::Solid(theFOrSo));
560   }
561
562   // Process an outer sub-shape.
563   if (myMapRemoved.Contains(anOuterSubShape)) {
564     isToCreate = Standard_False;
565   } else if (myMapModified.IsBound(anOuterSubShape)) {
566     TopTools_ListOfShape aModifSubShapes;
567
568     getModified(anOuterSubShape, aModifSubShapes);
569
570     // Check if there is a closed direct sub-shape.
571     TopTools_ListIteratorOfListOfShape anIter(aModifSubShapes);
572     TopoDS_Shape                       aClosedSubShape;
573
574     for (isToCreate = Standard_False; anIter.More(); anIter.Next()) {
575       const TopoDS_Shape &aSubShape = anIter.Value();
576
577       if (aSubShape.ShapeType() == aSubShapeType && aSubShape.Closed()) {
578         if (isToCreate) {
579           // There is another closed sub-shape. NEVERREACHED.
580           // No need to create a new shape.
581           isToCreate = Standard_False;
582           break;
583         } else {
584           // Remember the closed sub-shape.
585           isToCreate      = Standard_True;
586           aClosedSubShape = aSubShape;
587         }
588       }
589     }
590
591     if (isToCreate) {
592       // Add a closed sub-shape.
593       const TopoDS_Shape aNewSubShape =
594         oriented(aClosedSubShape, anOuterSubShape);
595
596       aClosedSubShapes.Append(aNewSubShape);
597     }
598
599     // Copy shapes to the list of other shapes.
600     for (anIter.Initialize(aModifSubShapes); anIter.More(); anIter.Next()) {
601       const TopoDS_Shape aNewShape = oriented(anIter.Value(), anOuterSubShape);
602
603       if (!isToCreate || !aNewShape.IsSame(aClosedSubShape)) {
604         aNewShapes.Append(aNewShape);
605       }
606     }
607   } else {
608     aClosedSubShapes.Append(anOuterSubShape);
609   }
610
611   // Treat holes.
612   TopoDS_Iterator anIter(theFOrSo);
613
614   for (; anIter.More(); anIter.Next()) {
615     const TopoDS_Shape &aSubShape = anIter.Value();
616
617     if (aSubShape.IsSame(anOuterSubShape)) {
618       // Skip an outer sub-shape.
619       continue;
620     }
621
622     if (myMapModified.IsBound(aSubShape)) {
623       // This is a modified sub-shape.
624       TopTools_ListOfShape aModifSubShapes;
625
626       getModified(aSubShape, aModifSubShapes);
627
628       TopTools_ListIteratorOfListOfShape anIter(aModifSubShapes);
629
630       for (; anIter.More(); anIter.Next()) {
631         const TopoDS_Shape aNewShape = oriented(anIter.Value(), aSubShape);
632
633         if (isToCreate) {
634           if (aNewShape.ShapeType() == aSubShapeType && aNewShape.Closed()) {
635             // This is a closed sub-shape.
636             aClosedSubShapes.Append(aNewShape);
637           } else {
638             aNewShapes.Append(aNewShape);
639           }
640         } else {
641           aNewShapes.Append(aNewShape);
642         }
643       }
644     } else if (!myMapRemoved.Contains(aSubShape)) {
645       // The shape is not modified.
646       if (isToCreate) {
647         aClosedSubShapes.Append(aSubShape);
648       } else {
649         aNewShapes.Append(aSubShape);
650       }
651     }
652   }
653
654   if (isToCreate) {
655     // Create a new shape.
656     TopoDS_Shape aNewShape = makeShape(theFOrSo, aClosedSubShapes);
657
658     aNewShapes.Prepend(aNewShape);
659   }
660
661   if (!aNewShapes.IsEmpty()) {
662     // Store modified shapes.
663     myMapModified.ChangeFind(theFOrSo) = aNewShapes;
664   }
665 }
666
667 //=======================================================================
668 //function : processShOrCS
669 //purpose  :
670 //=======================================================================
671 void GEOMAlgo_Extractor::processShOrCS(const TopoDS_Shape &theShOrCS)
672 {
673   // Treat sub-shapes.
674   TopoDS_Iterator      anIter(theShOrCS);
675   TopTools_ListOfShape aNewSubShapes;
676   TopTools_ListOfShape aNewOtherShapes;
677   TopAbs_ShapeEnum     aSubShapeType;
678   //TopAbs_ShapeEnum     aSubSubShapeType;
679
680   if (theShOrCS.ShapeType() == TopAbs_SHELL) {
681     aSubShapeType    = TopAbs_FACE;
682     //aSubSubShapeType = TopAbs_EDGE;
683   } else { // comp-solid
684     aSubShapeType    = TopAbs_SOLID;
685     //aSubSubShapeType = TopAbs_FACE;
686   }
687
688   for (; anIter.More(); anIter.Next()) {
689     const TopoDS_Shape &aSubShape = anIter.Value();
690
691     if (myMapModified.IsBound(aSubShape)) {
692       TopTools_ListOfShape aModifList;
693
694       getModified(aSubShape, aModifList);
695
696       // Copy shapes to the list of other shapes.
697       TopTools_ListIteratorOfListOfShape anIter(aModifList);
698
699       for (; anIter.More(); anIter.Next()) {
700         const TopoDS_Shape aNewShape = oriented(anIter.Value(), aSubShape);
701
702         if (aNewShape.ShapeType() == aSubShapeType) {
703           aNewSubShapes.Append(aNewShape);
704         } else {
705           aNewOtherShapes.Append(aNewShape);
706         }
707       }
708     } else if (!myMapRemoved.Contains(aSubShape)) {
709       // Shape is neither removed nor modified. Add it as it is.
710       if (aSubShape.ShapeType() == aSubShapeType) {
711         aNewSubShapes.Append(aSubShape);
712       } else {
713         aNewOtherShapes.Append(aSubShape);
714       }
715     }
716   }
717
718   // Group sub-shapes via bounds
719   TopTools_ListOfShape aNewShapes;
720
721   groupViaBounds(theShOrCS, aNewSubShapes, aNewShapes);
722   aNewOtherShapes.Prepend(aNewShapes);
723
724   if (!aNewOtherShapes.IsEmpty()) {
725     // Store modified shapes.
726     myMapModified.ChangeFind(theShOrCS) = aNewOtherShapes;
727   }
728 }
729
730 //=======================================================================
731 //function : processCompound
732 //purpose  :
733 //=======================================================================
734 void GEOMAlgo_Extractor::processCompound(const TopoDS_Shape &theCompound)
735 {
736   // Treat sub-shapes.
737   TopoDS_Iterator      anIter(theCompound);
738   TopTools_ListOfShape aNewSubShapes;
739
740   for (; anIter.More(); anIter.Next()) {
741     const TopoDS_Shape &aSubShape = anIter.Value();
742
743     if (myMapModified.IsBound(aSubShape)) {
744       TopTools_ListOfShape aModifList;
745
746       getModified(aSubShape, aModifList);
747
748       // Copy shapes to the list of other shapes.
749       TopTools_ListIteratorOfListOfShape anIter(aModifList);
750
751       for (; anIter.More(); anIter.Next()) {
752         const TopoDS_Shape aNewShape = oriented(anIter.Value(), aSubShape);
753
754         aNewSubShapes.Append(aNewShape);
755       }
756     } else if (!myMapRemoved.Contains(aSubShape)) {
757       // Shape is neither removed nor modified. Add it as it is.
758       aNewSubShapes.Append(aSubShape);
759     }
760   }
761
762   if (!aNewSubShapes.IsEmpty()) {
763     if (aNewSubShapes.Extent() == 1) {
764       // Avoid creation of new compound for a single sub-shape.
765       myMapModified.ChangeFind(theCompound).Append(aNewSubShapes.First());
766     } else {
767       TopoDS_Shape aNewShape = makeShape(theCompound, aNewSubShapes);
768
769       // Store modified shapes.
770       myMapModified.ChangeFind(theCompound).Append(aNewShape);
771     }
772   }
773 }
774
775 //=======================================================================
776 //function : removeBoundsOnFOrSo
777 //purpose  :
778 //=======================================================================
779 void GEOMAlgo_Extractor::removeBoundsOnFOrSo(const TopAbs_ShapeEnum theType)
780 {
781   // Get bounds on faces or solids.
782   TopExp_Explorer            anExp(myShape, theType);
783   TopTools_MapOfShape        aMapFence;
784   TopAbs_ShapeEnum           aBoundType;
785   TopAbs_ShapeEnum           aComplexBndType;
786   TopTools_IndexedMapOfShape aMapBounds;
787
788   if (theType == TopAbs_FACE) {
789     aBoundType      = TopAbs_EDGE;
790     aComplexBndType = TopAbs_WIRE;
791   } else { // solid
792     aBoundType      = TopAbs_FACE;
793     aComplexBndType = TopAbs_SHELL;
794   }
795
796   for (; anExp.More(); anExp.Next()) {
797     const TopoDS_Shape &aShape = anExp.Current();
798
799     if (aMapFence.Add(aShape)) {
800       if (myMapRemoved.Contains(aShape)) {
801         continue;
802       }
803
804       if (myMapModified.IsBound(aShape)) {
805         TopTools_ListOfShape aNewShapes;
806
807         getModified(aShape, aNewShapes);
808
809         if (!aNewShapes.IsEmpty()) {
810           const TopoDS_Shape &aNewShape = aNewShapes.First();
811
812           if (aNewShape.ShapeType() == theType) {
813             // Get bounds from the modified shape.
814             TopExp::MapShapes(aNewShape, aBoundType, aMapBounds);
815           }
816         }
817       } else {
818         // Get bounds from the original shapes.
819         TopExp::MapShapes(aShape, aBoundType, aMapBounds);
820       }
821     }
822   }
823
824   // Remove duplicated bounds from the faces or solids
825   aMapFence.Clear();
826
827   for (anExp.Init(myShape, theType); anExp.More(); anExp.Next()) {
828     const TopoDS_Shape &aShape = anExp.Current();
829
830     if (aMapFence.Add(aShape)) {
831       if (myMapModified.IsBound(aShape)) {
832         TopTools_ListOfShape               &aNewShapes =
833                                        myMapModified.ChangeFind(aShape);
834         TopTools_ListIteratorOfListOfShape  anIter(aNewShapes);
835
836         while (anIter.More()) {
837           const TopoDS_Shape &aSubShape = anIter.Value();
838           Standard_Boolean    isToRm    = Standard_False;
839
840           if (aSubShape.ShapeType() == aBoundType) {
841             // edge or face
842             isToRm = aMapBounds.Contains(aSubShape);
843           } else if (aSubShape.ShapeType() == aComplexBndType) {
844             // wire or shell
845             TopTools_ListOfShape aNewBounds;
846             Standard_Boolean     isModified;
847
848             if (theType == TopAbs_FACE) {
849               isModified = removeCommonEdges(aSubShape, aMapBounds, aNewBounds);
850             } else {
851               isModified = removeCommonFaces(aSubShape, aMapBounds, aNewBounds);
852             }
853
854             if (isModified) {
855               myMapModified.Bind(aSubShape, aNewBounds);
856               aNewShapes.InsertBefore(aNewBounds, anIter);
857               isToRm = Standard_True; // To remove unmodified bound.
858             }
859           }
860
861           if (isToRm) {
862             aNewShapes.Remove(anIter);
863           } else {
864             anIter.Next();
865           }
866         }
867       }
868     }
869   }
870 }
871
872 //=======================================================================
873 //function : oriented
874 //purpose  :
875 //=======================================================================
876 TopoDS_Shape GEOMAlgo_Extractor::oriented(const TopoDS_Shape &theShape,
877                                           const TopoDS_Shape &theContext)
878 {
879   const TopAbs_Orientation aShapeOri   = theShape.Orientation();
880   const TopAbs_Orientation aContextOri = theContext.Orientation();
881   TopoDS_Shape             aResult     = theShape;
882
883   aResult.Orientation(TopAbs::Compose(aShapeOri, aContextOri));
884
885   return aResult;
886 }
887
888 //=======================================================================
889 //function : makeShape
890 //purpose  :
891 //=======================================================================
892 TopoDS_Shape GEOMAlgo_Extractor::makeShape
893                         (const TopoDS_Shape         &theShape,
894                          const TopTools_ListOfShape &theSubShapes)
895 {
896   TopoDS_Shape aResult = getShapeFromSubShapes(theShape, theSubShapes);
897
898   if (aResult.IsNull()) {
899     // Create a new shape.
900     BRep_Builder                       aBuilder;
901     TopTools_ListIteratorOfListOfShape anIter(theSubShapes);
902     TopTools_MapOfShape                aMapFence;
903
904     aResult = theShape.EmptyCopied();
905     aMapFence.Clear();
906
907     for (; anIter.More(); anIter.Next()) {
908       const TopoDS_Shape &aSubShape = anIter.Value();
909
910       if (aMapFence.Add(aSubShape)) {
911         aBuilder.Add(aResult, aSubShape);
912
913         // Fill the map of new shape - ancestors.
914         if (!myMapNewShapeAnc.IsBound(aSubShape)) {
915           myMapNewShapeAnc.Bind(aSubShape, TopTools_ListOfShape());
916         }
917
918         myMapNewShapeAnc.ChangeFind(aSubShape).Append(aResult);
919       }
920     }
921   }
922
923   return aResult;
924 }
925
926 //=======================================================================
927 //function : getShapeFromSubShapes
928 //purpose  :
929 //=======================================================================
930 TopoDS_Shape GEOMAlgo_Extractor::getShapeFromSubShapes
931                               (const TopoDS_Shape         &theShape,
932                                const TopTools_ListOfShape &theSubShapes)
933 {
934   // Fill the map of sub-shapes.
935   TopTools_ListIteratorOfListOfShape anIter(theSubShapes);
936   TopTools_MapOfShape                aMapSubShapes;
937   TopoDS_Shape                       aFirstSubShape = theSubShapes.First();
938   TopoDS_Shape                       aResult;
939
940   for (; anIter.More(); anIter.Next()) {
941     aMapSubShapes.Add(anIter.Value());
942   }
943
944   // Check if such a shape is already created.
945   if (!aMapSubShapes.IsEmpty()) {
946     TopTools_MapIteratorOfMapOfShape aMapIt(aMapSubShapes);
947     Standard_Boolean                 isFirst = Standard_True;
948     TopTools_MapOfShape              aMapAncs[2];
949     Standard_Integer                 iCur    = 0;
950     Standard_Integer                 iPrev   = 1;
951
952     for (; aMapIt.More(); aMapIt.Next()) {
953       const TopoDS_Shape &aSubShape = aMapIt.Key();
954
955       // Switch iCur and iPrev.
956       iCur  = iCur  ? 0 : 1;
957       iPrev = iPrev ? 0 : 1;
958
959       if (myMapNewShapeAnc.IsBound(aSubShape)) {
960         TopTools_ListIteratorOfListOfShape
961                       anAncIt(myMapNewShapeAnc.Find(aSubShape));
962
963         if (isFirst) {
964           // This is a first loop. Just fill the map of ancestors.
965           for (; anAncIt.More(); anAncIt.Next()) {
966             aMapAncs[iCur].Add(anAncIt.Value());
967           }
968         } else {
969           // Add in aMapAnc[iCur] elements that are only in aMapAnc[iPrev].
970           for (aMapAncs[iCur].Clear(); anAncIt.More(); anAncIt.Next()) {
971             const TopoDS_Shape &anAncestor = anAncIt.Value();
972
973             if (aMapAncs[iPrev].Contains(anAncestor)) {
974               aMapAncs[iCur].Add(anAncIt.Value());
975             }
976           }
977         }
978
979         if (aMapAncs[iCur].IsEmpty()) {
980           // There is no common shape. It means that
981           // the result should be a new shape.
982           aMapAncs[iCur].Clear();
983           break;
984         }
985       } else {
986         // This is a new sub-shape. So the result shape is new.
987         aMapAncs[iCur].Clear();
988         break;
989       }
990     }
991
992     if (!aMapAncs[iCur].IsEmpty()) {
993       // Get exactly the same shape.
994       const TopAbs_ShapeEnum aType = theShape.ShapeType();
995
996       for (aMapIt.Initialize(aMapAncs[iCur]); aMapIt.More(); aMapIt.Next()) {
997         const TopoDS_Shape &aShape = aMapIt.Key();
998
999         if (aShape.ShapeType() == aType) {
1000           // Check sub-shapes.
1001           TopoDS_Iterator    aSubShIt(aShape);
1002           TopAbs_Orientation aNewOri       = TopAbs_FORWARD;
1003           Standard_Boolean   isComposedOri = Standard_False;
1004
1005           for (; aSubShIt.More(); aSubShIt.Next()) {
1006             const TopoDS_Shape &aSubSh = aSubShIt.Value();
1007
1008             if (!aMapSubShapes.Contains(aSubSh)) {
1009               // There are another sub-shapes in the ancestor.
1010               break;
1011             }
1012
1013             if (!isComposedOri && aSubSh.IsSame(aFirstSubShape)) {
1014               // Compose orientaiton.
1015               isComposedOri = Standard_True;
1016               aNewOri       = TopAbs::Compose
1017                 (aFirstSubShape.Orientation(), aSubSh.Orientation());
1018             }
1019           }
1020
1021           if (!aSubShIt.More()) {
1022             // That is the same shape. Compose the orientation.
1023             aResult = aShape;
1024             aResult.Orientation(aNewOri);
1025             break;
1026           }
1027         }
1028       }
1029     }
1030   }
1031
1032   return aResult;
1033 }
1034
1035 //=======================================================================
1036 //function : makeResult
1037 //purpose  :
1038 //=======================================================================
1039 TopoDS_Shape GEOMAlgo_Extractor::makeResult(const TopoDS_Shape &theShape)
1040 {
1041   TopoDS_Shape aResult;
1042
1043   if (!myMapRemoved.Contains(theShape)) {
1044     if (myMapModified.IsBound(theShape)) {
1045       // The shape is modified.
1046       TopTools_ListOfShape aListModif;
1047
1048       getModified(theShape, aListModif);
1049
1050       const Standard_Integer aNbShapes = aListModif.Extent();
1051
1052       if (aNbShapes == 1) {
1053         aResult = oriented(aListModif.First(), theShape);
1054       } else if (aNbShapes > 1) {
1055         // Build a result as a compound
1056         TopTools_ListIteratorOfListOfShape anIter(aListModif);
1057         BRep_Builder                       aBuilder;
1058         TopoDS_Compound                    aCompound;
1059         TopTools_MapOfShape                aMapFence;
1060
1061         aBuilder.MakeCompound(aCompound);
1062
1063         for (; anIter.More(); anIter.Next()) {
1064           const TopoDS_Shape aModifShape = oriented(anIter.Value(), theShape);
1065
1066           if (aMapFence.Add(aModifShape)) {
1067             aBuilder.Add(aCompound, aModifShape);
1068           }
1069         }
1070
1071         aResult = aCompound;
1072       }
1073     } else {
1074       // The result is not modified shape.
1075       aResult = theShape;
1076     }
1077   }
1078
1079   return aResult;
1080 }
1081
1082 //=======================================================================
1083 //function : makeHistory
1084 //purpose  :
1085 //=======================================================================
1086 void GEOMAlgo_Extractor::makeHistory(const TopoDS_Shape        &theShape,
1087                                            TopTools_MapOfShape &theMapFence)
1088 {
1089   if (theMapFence.Add(theShape)) {
1090     Standard_Boolean isKept = Standard_True;
1091
1092     if (myMapRemoved.Contains(theShape)) {
1093       myRemoved.Append(theShape);
1094       isKept = Standard_False;
1095     } else if (myMapModified.IsBound(theShape)) {
1096       TopTools_ListOfShape aListModif;
1097
1098       getModified(theShape, aListModif, theShape.ShapeType());
1099
1100       Standard_Boolean       isModif = !aListModif.IsEmpty();
1101       //const TopAbs_ShapeEnum aType   = theShape.ShapeType();
1102
1103       if (isModif) {
1104         // Add the new shapes.
1105         TopTools_ListIteratorOfListOfShape anIter(aListModif);
1106
1107         // Skip the first shape.
1108         for (anIter.Next(); anIter.More(); anIter.Next()) {
1109           myNew.Append(anIter.Value());
1110         }
1111       }
1112
1113       if (isModif) {
1114         myModified.Append(theShape);
1115       } else {
1116         myRemoved.Append(theShape);
1117       }
1118
1119       isKept = Standard_False;
1120     }
1121
1122     if (!isKept) {
1123       // Collect history for children.
1124       TopoDS_Iterator anIter(theShape);
1125
1126       for (; anIter.More(); anIter.Next()) {
1127         const TopoDS_Shape &aSubShape = anIter.Value();
1128
1129         makeHistory(aSubShape, theMapFence);
1130       }
1131     }
1132   }
1133 }
1134
1135 //=======================================================================
1136 //function : removeCommonEdges
1137 //purpose  :
1138 //=======================================================================
1139 Standard_Boolean GEOMAlgo_Extractor::removeCommonEdges
1140                      (const TopoDS_Shape               &theWire,
1141                       const TopTools_IndexedMapOfShape &theMapEdgesToRm,
1142                             TopTools_ListOfShape       &theNewWires)
1143 {
1144   TopExp_Explorer                        anExp(theWire, TopAbs_EDGE);
1145   NCollection_List<TopTools_ListOfShape> aListListEdges;
1146   TopTools_ListOfShape                   aListEdges;
1147   Standard_Boolean                       isModified = Standard_False;
1148   TopoDS_Vertex                          aVtx[2];
1149
1150   for (; anExp.More(); anExp.Next()) {
1151     const TopoDS_Shape &anEdge = anExp.Current();
1152
1153     if (theMapEdgesToRm.Contains(anEdge)) {
1154       // This edge is removed.
1155       TopExp::Vertices(TopoDS::Edge(anEdge), aVtx[0], aVtx[1]);
1156
1157       // Skip edges that have same first and last vertices.
1158       if (aVtx[0].IsNull() || !aVtx[0].IsSame(aVtx[1])) {
1159         if (!aListEdges.IsEmpty()) {
1160           aListListEdges.Append(aListEdges);
1161           aListEdges.Clear();
1162         }
1163       }
1164
1165       isModified = Standard_True;
1166     } else {
1167       aListEdges.Append(anEdge);
1168     }
1169   }
1170
1171   if (!aListEdges.IsEmpty()) {
1172     aListListEdges.Append(aListEdges);
1173   }
1174
1175   if (isModified && !aListListEdges.IsEmpty()) {
1176     // Make wires.
1177     makeWires(theWire, aListListEdges, theNewWires);
1178   }
1179
1180   return isModified;
1181 }
1182
1183 //=======================================================================
1184 //function : removeCommonFaces
1185 //purpose  :
1186 //=======================================================================
1187 Standard_Boolean GEOMAlgo_Extractor::removeCommonFaces
1188                      (const TopoDS_Shape               &theShell,
1189                       const TopTools_IndexedMapOfShape &theMapFacesToRm,
1190                             TopTools_ListOfShape       &theNewShells)
1191 {
1192   TopExp_Explorer      anExp(theShell, TopAbs_FACE);
1193   TopTools_ListOfShape aListFaces;
1194   Standard_Boolean     isModified = Standard_False;
1195
1196   for (; anExp.More(); anExp.Next()) {
1197     const TopoDS_Shape &aFace = anExp.Current();
1198
1199     if (theMapFacesToRm.Contains(aFace)) {
1200       isModified = Standard_True;
1201     } else {
1202       aListFaces.Append(aFace);
1203     }
1204   }
1205
1206   if (isModified && !aListFaces.IsEmpty()) {
1207     // Create new shells.
1208     groupViaBounds(theShell, aListFaces, theNewShells);
1209   }
1210
1211   return isModified;
1212 }
1213
1214 //=======================================================================
1215 //function : makeWires
1216 //purpose  :
1217 //=======================================================================
1218 void GEOMAlgo_Extractor::makeWires
1219             (const TopoDS_Shape                           &theWire,
1220                    NCollection_List<TopTools_ListOfShape> &theListListEdges,
1221                    TopTools_ListOfShape                   &theWires)
1222 {
1223   if (theListListEdges.Size() > 1) {
1224     // Check if it is possible to merge first and last lists of edges.
1225     TopoDS_Edge   anEdgeFirst = TopoDS::Edge(theListListEdges.First().First());
1226     TopoDS_Edge   anEdgeLast  = TopoDS::Edge(theListListEdges.Last().Last());
1227     TopoDS_Vertex aCommonVtx;
1228
1229     if (TopExp::CommonVertex(anEdgeFirst, anEdgeLast, aCommonVtx)) {
1230       // Merge First and last lists of edges.
1231       theListListEdges.First().Prepend(theListListEdges.Last());
1232       // Remove the last list.
1233       NCollection_List<TopTools_ListOfShape>::Iterator anIter(theListListEdges);
1234
1235       for (;anIter.More(); anIter.Next()) {
1236         if (anIter.Value().IsEmpty()) {
1237           theListListEdges.Remove(anIter);
1238           break;
1239         }
1240       }
1241     }
1242   }
1243
1244   // Create wires.
1245   NCollection_List<TopTools_ListOfShape>::Iterator anIter(theListListEdges);
1246
1247   for (;anIter.More(); anIter.Next()) {
1248     const TopTools_ListOfShape &anEdges       = anIter.Value();
1249     TopoDS_Shape                aNewWireShape = makeShape(theWire, anEdges);
1250     TopoDS_Wire                 aNewWire      = TopoDS::Wire(aNewWireShape);
1251     TopoDS_Vertex               aV[2];
1252
1253     TopExp::Vertices(aNewWire, aV[0], aV[1]);
1254
1255     if (!aV[0].IsNull() && !aV[1].IsNull()) {
1256       aNewWire.Closed(aV[0].IsSame(aV[1]));
1257     }
1258
1259     theWires.Append(aNewWire);
1260   }
1261 }
1262
1263 //=======================================================================
1264 //function : groupViaBounds
1265 //purpose  :
1266 //=======================================================================
1267 void GEOMAlgo_Extractor::groupViaBounds
1268                        (const TopoDS_Shape         &theShape,
1269                         const TopTools_ListOfShape &theSubShapes,
1270                               TopTools_ListOfShape &theNewShapes)
1271 {
1272   const Standard_Boolean isShell = theShape.ShapeType() == TopAbs_SHELL;
1273   TopAbs_ShapeEnum       aBoundType;
1274
1275   if (isShell) {
1276     aBoundType = TopAbs_EDGE;
1277   } else { // comp-solid
1278     aBoundType = TopAbs_FACE;
1279   }
1280
1281   // Group connected sub-shapes.
1282   NCollection_Sequence<TopTools_ListOfShape> aGroupedSubShapes;
1283   NCollection_Sequence<TopTools_MapOfShape>  aBounds;
1284   TopTools_ListIteratorOfListOfShape         anIt(theSubShapes);
1285   Standard_Integer                           i;
1286
1287   for (; anIt.More(); anIt.Next()) {
1288     // Find a zone a sub-shape is connected to.
1289     const TopoDS_Shape     &aSubShape = anIt.Value();
1290     TColStd_MapOfInteger    aMapIndices;
1291     const Standard_Integer  aNbZones  = aBounds.Size();
1292     TopExp_Explorer         anExp(aSubShape, aBoundType);
1293     Standard_Integer        j;
1294
1295     for (; anExp.More(); anExp.Next()) {
1296       const TopoDS_Shape &aSubSubShape = anExp.Current();
1297
1298       // Check each zone.
1299       for (i = 1; i <= aNbZones; ++i) {
1300         if (!aMapIndices.Contains(i)) {
1301           if (aBounds.Value(i).Contains(aSubSubShape)) {
1302             // The current sub-shape belongs to this zone.
1303             aMapIndices.Add(i);
1304             break;
1305           }
1306         }
1307       }
1308     }
1309
1310     if (aMapIndices.IsEmpty()) {
1311       // Create a new zone.
1312       aGroupedSubShapes.Append(TopTools_ListOfShape());
1313       aBounds.Append(TopTools_MapOfShape());
1314       aGroupedSubShapes.ChangeLast().Append(aSubShape);
1315       anExp.Init(aSubShape, aBoundType);
1316
1317       TopTools_MapOfShape &aLastZoneBound = aBounds.ChangeLast();
1318
1319       for (; anExp.More(); anExp.Next()) {
1320         aLastZoneBound.Add(anExp.Current());
1321       }
1322     } else {
1323       // Merge zones. Get the first zone.
1324       for (i = 1; i <= aNbZones; ++i) {
1325         if (aMapIndices.Contains(i)) {
1326           break;
1327         }
1328       }
1329
1330       // Merge other zones with the first one.
1331       TopTools_ListOfShape &aZoneSubShapes = aGroupedSubShapes.ChangeValue(i);
1332       TopTools_MapOfShape  &aZoneBounds    = aBounds.ChangeValue(i);
1333
1334       for (j = i + 1; j <= aNbZones; ++j) {
1335         if (aMapIndices.Contains(j)) {
1336           aZoneSubShapes.Append(aGroupedSubShapes.ChangeValue(j));
1337
1338           TopTools_MapIteratorOfMapOfShape aMapIt(aBounds.Value(j));
1339
1340           for (; aMapIt.More(); aMapIt.Next()) {
1341             aZoneBounds.Add(aMapIt.Key());
1342           }
1343         }
1344       }
1345
1346       // Remove merged zones.
1347       for (j = aNbZones; j > i; --j) {
1348         aGroupedSubShapes.Remove(j);
1349         aBounds.Remove(j);
1350       }
1351
1352       // Add aSubShape to merged zone.
1353       aZoneSubShapes.Append(aSubShape);
1354       anExp.Init(aSubShape, aBoundType);
1355
1356       for (; anExp.More(); anExp.Next()) {
1357         const TopoDS_Shape &aSubSubShape = anExp.Current();
1358
1359         if (!aZoneBounds.Add(aSubSubShape)) {
1360           aZoneBounds.Remove(aSubSubShape);
1361         }
1362       }
1363     }
1364   }
1365
1366   // Construct new shapes from sub-shapes.
1367   const Standard_Integer aNbGroups = aGroupedSubShapes.Size();
1368   TopTools_ListOfShape   aNewSubShapes;
1369
1370   for (i = 1; i <= aNbGroups; ++i) {
1371     const TopTools_ListOfShape &aListSubShapes = aGroupedSubShapes.Value(i);
1372
1373     if (!isShell && aListSubShapes.Extent() == 1) {
1374       // Avoid creation of comp-solid with a single solid.
1375       aNewSubShapes.Append(aListSubShapes.First());
1376     } else {
1377       TopoDS_Shape aNewShape = makeShape(theShape, aListSubShapes);
1378
1379       if (aBounds.Value(i).IsEmpty()) {
1380         // This is a closed shape.
1381         aNewShape.Closed(Standard_True);
1382       }
1383
1384       theNewShapes.Append(aNewShape);
1385     }
1386   }
1387
1388   // Append the list of single solids (if it is filled).
1389   theNewShapes.Append(aNewSubShapes);
1390 }
1391
1392 //=======================================================================
1393 //function : getModified
1394 //purpose  :
1395 //=======================================================================
1396 void GEOMAlgo_Extractor::getModified(const TopoDS_Shape         &theShape,
1397                                            TopTools_ListOfShape &theModifShapes,
1398                                      const TopAbs_ShapeEnum      theShapeType)
1399 {
1400   // This shape is modified.
1401   TopTools_ListIteratorOfListOfShape anIt(myMapModified.Find(theShape));
1402
1403   for (; anIt.More(); anIt.Next()) {
1404     const TopoDS_Shape &aSubShape = anIt.Value();
1405
1406     if (theShapeType == TopAbs_SHAPE || aSubShape.ShapeType() == theShapeType) {
1407       if (myMapModified.IsBound(aSubShape)) {
1408         getModified(aSubShape, theModifShapes);
1409       } else {
1410         theModifShapes.Append(aSubShape);
1411       }
1412     }
1413   }
1414 }
1415
1416
1417 //
1418 // myErrorStatus :
1419 //
1420 // 10 -myShape=NULL
1421 // 11 -mySubShapes contains not only sub-shapes of myShape.
1422 // 12 -Can't remove the main shape.
1423 // 13 -mySubShapes contains seam edges in context of faces.
1424 // 14 -mySubShapes contains degenerated edges in context of faces.
1425 //
1426 // myWarningStatus :
1427 //
1428 // 10 -mySubShapes is empty
1429 //