1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File: GEOMAlgo_Extractor.cxx
25 // Author: Sergey KHROMOV
29 #include <GEOMAlgo_Extractor.hxx>
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>
38 #include <TopExp_Explorer.hxx>
39 #include <TColStd_MapOfInteger.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>
50 //=======================================================================
51 //function : GEOMAlgo_Extractor
53 //=======================================================================
54 GEOMAlgo_Extractor::GEOMAlgo_Extractor()
58 //=======================================================================
59 //function : ~GEOMAlgo_Extractor
61 //=======================================================================
62 GEOMAlgo_Extractor::~GEOMAlgo_Extractor()
66 //=======================================================================
69 //=======================================================================
70 void GEOMAlgo_Extractor::SetShape(const TopoDS_Shape &theShape)
73 myMapShapeAnc.Clear();
77 //=======================================================================
78 //function : SetShapesToRemove
80 //=======================================================================
81 void GEOMAlgo_Extractor::SetShapesToRemove
82 (const TopTools_ListOfShape &theSubShapes)
84 mySubShapes.Assign(theSubShapes);
88 //=======================================================================
91 //=======================================================================
92 void GEOMAlgo_Extractor::Perform()
103 if (myWarningStatus == 10) {
104 // The result is the same shape. Nothing is modified.
109 // Mark sub-shapes as removed and modified.
113 processShapes(TopAbs_EDGE);
116 processShapes(TopAbs_WIRE);
119 processShapes(TopAbs_FACE);
122 processShapes(TopAbs_SHELL);
125 processShapes(TopAbs_SOLID);
127 // Process Comp-Solids.
128 processShapes(TopAbs_COMPSOLID);
130 // Process Compounds.
131 processShapes(TopAbs_COMPOUND);
134 myResult = makeResult(myShape);
136 TopTools_MapOfShape aMapFence;
138 makeHistory(myShape, aMapFence);
141 //=======================================================================
142 //function : GetResult
144 //=======================================================================
145 const TopoDS_Shape &GEOMAlgo_Extractor::GetResult() const
150 //=======================================================================
153 //=======================================================================
154 void GEOMAlgo_Extractor::clear()
162 myMapRemoved.Clear();
163 myMapModified.Clear();
164 myMapNewShapeAnc.Clear();
167 //=======================================================================
168 //function : checkData
170 //=======================================================================
171 void GEOMAlgo_Extractor::checkData()
173 if (myShape.IsNull()) {
178 if (mySubShapes.IsEmpty()) {
179 myWarningStatus = 10;
183 TopTools_ListIteratorOfListOfShape anIter(mySubShapes);
184 TopTools_IndexedMapOfShape anIndices;
185 TopTools_MapOfShape aMapFence;
187 TopExp::MapShapes(myShape, anIndices);
189 while (anIter.More()) {
190 const TopoDS_Shape &aSubShape = anIter.Value();
192 if (aMapFence.Add(aSubShape)) {
193 // Check if it is a sub-shape of the given shape.
194 if (!anIndices.Contains(aSubShape)) {
199 // Check if it is a main shape.
200 if (aSubShape.IsSame(myShape)) {
207 // Remove duplicated index.
208 mySubShapes.Remove(anIter);
212 if (myMapShapeAnc.IsEmpty()) {
213 // Fill the map of shapes - ancestors.
214 makeMapShapeAncestors(myShape);
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();
221 if (aSubShape.ShapeType() == TopAbs_EDGE) {
222 // Get the list of ancestor wires.
223 TopTools_ListOfShape anAncWires;
224 TopTools_ListIteratorOfListOfShape anAncIt;
226 if (myMapShapeAnc.IsBound(aSubShape)) {
227 anAncIt.Initialize(myMapShapeAnc.Find(aSubShape));
229 for (; anAncIt.More(); anAncIt.Next()) {
230 const TopoDS_Shape &anAncShape = anAncIt.Value();
232 if (anAncShape.ShapeType() == TopAbs_WIRE) {
233 anAncWires.Append(anAncShape);
238 if (!anAncWires.IsEmpty()) {
239 // Check the ancestor faces.
240 Standard_Boolean hasFaces = Standard_False;
241 TopoDS_Edge anEdge = TopoDS::Edge(aSubShape);
243 for (anAncIt.Initialize(anAncWires); anAncIt.More(); anAncIt.Next()) {
244 const TopoDS_Shape &anAncShape = anAncIt.Value();
246 if (anAncShape.ShapeType() == TopAbs_FACE) {
247 TopoDS_Face aFace = TopoDS::Face(anAncShape);
249 if (BRepTools::IsReallyClosed(anEdge, aFace)) {
250 // Deletion of face's seam edge is not allowed
255 hasFaces = Standard_True;
259 if (hasFaces && BRep_Tool::Degenerated(anEdge)) {
268 //=======================================================================
269 //function : makeMapShapeAncestors
271 //=======================================================================
272 void GEOMAlgo_Extractor::makeMapShapeAncestors(const TopoDS_Shape &theShape)
274 if (theShape.ShapeType() == TopAbs_VERTEX) {
275 // Vertex is the lowest type. It has no ancestors.
279 TopoDS_Iterator anIter(theShape);
280 TopTools_MapOfShape aMapFence;
282 for (; anIter.More(); anIter.Next()) {
283 const TopoDS_Shape &aSubShape = anIter.Value();
285 if (aMapFence.Add(aSubShape)) {
286 // Add theShape as an ancestor shape.
287 if (!myMapShapeAnc.IsBound(aSubShape)) {
288 myMapShapeAnc.Bind(aSubShape, TopTools_ListOfShape());
291 myMapShapeAnc.ChangeFind(aSubShape).Append(theShape);
293 // Recursively call this method for a sub-shape.
294 makeMapShapeAncestors(aSubShape);
299 //=======================================================================
300 //function : markShapes
302 //=======================================================================
303 void GEOMAlgo_Extractor::markShapes()
305 TopTools_ListIteratorOfListOfShape anIter(mySubShapes);
307 // Mark sub-shapes as removed.
308 for (; anIter.More(); anIter.Next()) {
309 const TopoDS_Shape &aSubShape = anIter.Value();
311 markRemoved(aSubShape);
314 // Mark undestors of sub-shapes as modified.
315 for (anIter.Initialize(mySubShapes); anIter.More(); anIter.Next()) {
316 const TopoDS_Shape &aSubShape = anIter.Value();
318 markAncestorsModified(aSubShape);
322 //=======================================================================
323 //function : markRemoved
325 //=======================================================================
326 void GEOMAlgo_Extractor::markRemoved(const TopoDS_Shape &theShape)
328 if (myMapRemoved.Add(theShape)) {
330 TopoDS_Iterator anIter(theShape);
331 TopTools_MapOfShape aMapFence;
333 for (; anIter.More(); anIter.Next()) {
334 const TopoDS_Shape &aSubShape = anIter.Value();
336 if (aMapFence.Add(aSubShape)) {
337 TopTools_ListIteratorOfListOfShape anAncIt
338 (myMapShapeAnc.Find(aSubShape));
339 Standard_Boolean isToRm = Standard_True;
341 for (; anAncIt.More(); anAncIt.Next()) {
342 const TopoDS_Shape &anAncShape = anAncIt.Value();
344 if (!myMapRemoved.Contains(anAncShape)) {
345 isToRm = Standard_False;
351 // Mark sub-shape as removed.
352 markRemoved(aSubShape);
359 //=======================================================================
360 //function : markAncestorsModified
362 //=======================================================================
363 void GEOMAlgo_Extractor::markAncestorsModified(const TopoDS_Shape &theShape)
365 if (myMapShapeAnc.IsBound(theShape)) {
366 TopTools_ListIteratorOfListOfShape anAncIt(myMapShapeAnc.Find(theShape));
368 for (; anAncIt.More(); anAncIt.Next()) {
369 const TopoDS_Shape &anAncShape = anAncIt.Value();
371 if (!myMapRemoved.Contains(anAncShape) &&
372 !myMapModified.IsBound(anAncShape)) {
373 // Mark anAncShape as modified.
374 myMapModified.Bind(anAncShape, TopTools_ListOfShape());
376 // Mark its ancestors as modified.
377 markAncestorsModified(anAncShape);
383 //=======================================================================
384 //function : processShapes
386 //=======================================================================
387 void GEOMAlgo_Extractor::processShapes(const TopAbs_ShapeEnum &theType)
389 TopExp_Explorer anExp(myShape, theType);
390 TopTools_MapOfShape aMapFence;
392 for (; anExp.More(); anExp.Next()) {
393 TopoDS_Shape aShape = anExp.Current(); // Copy
395 if (aMapFence.Add(aShape)) {
396 if (myMapRemoved.Contains(aShape) ||
397 !myMapModified.IsBound(aShape)) {
398 // Skip removed or not modified shape.
402 aShape.Orientation(TopAbs_FORWARD);
413 processFOrSo(aShape);
416 case TopAbs_COMPSOLID:
417 processShOrCS(aShape);
419 case TopAbs_COMPOUND:
420 processCompound(aShape);
428 if (theType == TopAbs_FACE || theType == TopAbs_SOLID) {
429 // Clear duplicated edges from the faces and faces from solids
430 removeBoundsOnFOrSo(theType);
434 //=======================================================================
435 //function : processEdge
437 //=======================================================================
438 void GEOMAlgo_Extractor::processEdge(const TopoDS_Shape &theEdge)
440 TopoDS_Iterator anIter(theEdge);
441 TopTools_MapOfShape aMapFence;
442 TopTools_ListOfShape aVtxList;
444 for (; anIter.More(); anIter.Next()) {
445 const TopoDS_Shape &aShapeVertex = anIter.Value();
447 if (aMapFence.Add(aShapeVertex)) {
448 if (myMapRemoved.Contains(aShapeVertex)) {
449 // This vertex is removed.
450 const TopAbs_Orientation anOri = aShapeVertex.Orientation();
452 if (anOri == TopAbs_FORWARD || anOri == TopAbs_REVERSED) {
453 // This edge will disappear from the result.
457 // This vertex is not removed.
458 aVtxList.Append(aShapeVertex);
463 TopoDS_Shape aNewEdge = makeShape(theEdge, aVtxList);
465 myMapModified.ChangeFind(theEdge).Append(aNewEdge);
468 //=======================================================================
469 //function : processWire
471 //=======================================================================
472 void GEOMAlgo_Extractor::processWire(const TopoDS_Shape &theWire)
474 // Get parent face for the wire.
477 if (myMapShapeAnc.IsBound(theWire)) {
478 TopTools_ListIteratorOfListOfShape anIter(myMapShapeAnc.Find(theWire));
480 for (; anIter.More(); anIter.Next()) {
481 const TopoDS_Shape &aParent = anIter.Value();
483 if (aParent.ShapeType() == TopAbs_FACE) {
484 aFace = TopoDS::Face(aParent.Oriented(TopAbs_FORWARD));
490 TopoDS_Wire aWire = TopoDS::Wire(theWire);
491 BRepTools_WireExplorer anExp(aWire, aFace);
492 NCollection_List<TopTools_ListOfShape> aListListEdges;
493 TopTools_ListOfShape aListEdges;
495 for (; anExp.More(); anExp.Next()) {
496 const TopoDS_Edge &anEdge = anExp.Current();
498 if (myMapRemoved.Contains(anEdge)) {
499 // This edge is removed.
500 if (!aListEdges.IsEmpty()) {
501 aListListEdges.Append(aListEdges);
504 } else if (myMapModified.IsBound(anEdge)) {
505 // This edge is modified.
506 TopTools_ListOfShape aModifEdges;
508 getModified(anEdge, aModifEdges);
510 if (aModifEdges.IsEmpty()) {
511 // This edge is not created.
512 if (!aListEdges.IsEmpty()) {
513 aListListEdges.Append(aListEdges);
517 const TopoDS_Shape aModifEdge = oriented(aModifEdges.First(), anEdge);
519 aListEdges.Append(aModifEdge);
522 // Get an edge as it is.
523 aListEdges.Append(anEdge);
527 if (!aListEdges.IsEmpty()) {
528 aListListEdges.Append(aListEdges);
531 if (!aListListEdges.IsEmpty()) {
532 TopTools_ListOfShape aListWires;
534 makeWires(theWire, aListListEdges, aListWires);
535 myMapModified.ChangeFind(theWire) = aListWires;
539 //=======================================================================
540 //function : processFOrSo
542 //=======================================================================
543 void GEOMAlgo_Extractor::processFOrSo(const TopoDS_Shape &theFOrSo)
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;
552 if (theFOrSo.ShapeType() == TopAbs_FACE) {
553 aShapeType = TopAbs_FACE;
554 aSubShapeType = TopAbs_WIRE;
555 anOuterSubShape = BRepTools::OuterWire(TopoDS::Face(theFOrSo));
557 aShapeType = TopAbs_SOLID;
558 aSubShapeType = TopAbs_SHELL;
559 anOuterSubShape = BRepClass3d::OuterShell(TopoDS::Solid(theFOrSo));
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;
568 getModified(anOuterSubShape, aModifSubShapes);
570 // Check if there is a closed direct sub-shape.
571 TopTools_ListIteratorOfListOfShape anIter(aModifSubShapes);
572 TopoDS_Shape aClosedSubShape;
574 for (isToCreate = Standard_False; anIter.More(); anIter.Next()) {
575 const TopoDS_Shape &aSubShape = anIter.Value();
577 if (aSubShape.ShapeType() == aSubShapeType && aSubShape.Closed()) {
579 // There is another closed sub-shape. NEVERREACHED.
580 // No need to create a new shape.
581 isToCreate = Standard_False;
584 // Remember the closed sub-shape.
585 isToCreate = Standard_True;
586 aClosedSubShape = aSubShape;
592 // Add a closed sub-shape.
593 const TopoDS_Shape aNewSubShape =
594 oriented(aClosedSubShape, anOuterSubShape);
596 aClosedSubShapes.Append(aNewSubShape);
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);
603 if (!isToCreate || !aNewShape.IsSame(aClosedSubShape)) {
604 aNewShapes.Append(aNewShape);
608 aClosedSubShapes.Append(anOuterSubShape);
612 TopoDS_Iterator anIter(theFOrSo);
614 for (; anIter.More(); anIter.Next()) {
615 const TopoDS_Shape &aSubShape = anIter.Value();
617 if (aSubShape.IsSame(anOuterSubShape)) {
618 // Skip an outer sub-shape.
622 if (myMapModified.IsBound(aSubShape)) {
623 // This is a modified sub-shape.
624 TopTools_ListOfShape aModifSubShapes;
626 getModified(aSubShape, aModifSubShapes);
628 TopTools_ListIteratorOfListOfShape anIter(aModifSubShapes);
630 for (; anIter.More(); anIter.Next()) {
631 const TopoDS_Shape aNewShape = oriented(anIter.Value(), aSubShape);
634 if (aNewShape.ShapeType() == aSubShapeType && aNewShape.Closed()) {
635 // This is a closed sub-shape.
636 aClosedSubShapes.Append(aNewShape);
638 aNewShapes.Append(aNewShape);
641 aNewShapes.Append(aNewShape);
644 } else if (!myMapRemoved.Contains(aSubShape)) {
645 // The shape is not modified.
647 aClosedSubShapes.Append(aSubShape);
649 aNewShapes.Append(aSubShape);
655 // Create a new shape.
656 TopoDS_Shape aNewShape = makeShape(theFOrSo, aClosedSubShapes);
658 aNewShapes.Prepend(aNewShape);
661 if (!aNewShapes.IsEmpty()) {
662 // Store modified shapes.
663 myMapModified.ChangeFind(theFOrSo) = aNewShapes;
667 //=======================================================================
668 //function : processShOrCS
670 //=======================================================================
671 void GEOMAlgo_Extractor::processShOrCS(const TopoDS_Shape &theShOrCS)
674 TopoDS_Iterator anIter(theShOrCS);
675 TopTools_ListOfShape aNewSubShapes;
676 TopTools_ListOfShape aNewOtherShapes;
677 TopAbs_ShapeEnum aSubShapeType;
678 TopAbs_ShapeEnum aSubSubShapeType;
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;
688 for (; anIter.More(); anIter.Next()) {
689 const TopoDS_Shape &aSubShape = anIter.Value();
691 if (myMapModified.IsBound(aSubShape)) {
692 TopTools_ListOfShape aModifList;
694 getModified(aSubShape, aModifList);
696 // Copy shapes to the list of other shapes.
697 TopTools_ListIteratorOfListOfShape anIter(aModifList);
699 for (; anIter.More(); anIter.Next()) {
700 const TopoDS_Shape aNewShape = oriented(anIter.Value(), aSubShape);
702 if (aNewShape.ShapeType() == aSubShapeType) {
703 aNewSubShapes.Append(aNewShape);
705 aNewOtherShapes.Append(aNewShape);
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);
713 aNewOtherShapes.Append(aSubShape);
718 // Group sub-shapes via bounds
719 TopTools_ListOfShape aNewShapes;
721 groupViaBounds(theShOrCS, aNewSubShapes, aNewShapes);
722 aNewOtherShapes.Prepend(aNewShapes);
724 if (!aNewOtherShapes.IsEmpty()) {
725 // Store modified shapes.
726 myMapModified.ChangeFind(theShOrCS) = aNewOtherShapes;
730 //=======================================================================
731 //function : processCompound
733 //=======================================================================
734 void GEOMAlgo_Extractor::processCompound(const TopoDS_Shape &theCompound)
737 TopoDS_Iterator anIter(theCompound);
738 TopTools_ListOfShape aNewSubShapes;
740 for (; anIter.More(); anIter.Next()) {
741 const TopoDS_Shape &aSubShape = anIter.Value();
743 if (myMapModified.IsBound(aSubShape)) {
744 TopTools_ListOfShape aModifList;
746 getModified(aSubShape, aModifList);
748 // Copy shapes to the list of other shapes.
749 TopTools_ListIteratorOfListOfShape anIter(aModifList);
751 for (; anIter.More(); anIter.Next()) {
752 const TopoDS_Shape aNewShape = oriented(anIter.Value(), aSubShape);
754 aNewSubShapes.Append(aNewShape);
756 } else if (!myMapRemoved.Contains(aSubShape)) {
757 // Shape is neither removed nor modified. Add it as it is.
758 aNewSubShapes.Append(aSubShape);
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());
767 TopoDS_Shape aNewShape = makeShape(theCompound, aNewSubShapes);
769 // Store modified shapes.
770 myMapModified.ChangeFind(theCompound).Append(aNewShape);
775 //=======================================================================
776 //function : removeBoundsOnFOrSo
778 //=======================================================================
779 void GEOMAlgo_Extractor::removeBoundsOnFOrSo(const TopAbs_ShapeEnum theType)
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;
788 if (theType == TopAbs_FACE) {
789 aBoundType = TopAbs_EDGE;
790 aComplexBndType = TopAbs_WIRE;
792 aBoundType = TopAbs_FACE;
793 aComplexBndType = TopAbs_SHELL;
796 for (; anExp.More(); anExp.Next()) {
797 const TopoDS_Shape &aShape = anExp.Current();
799 if (aMapFence.Add(aShape)) {
800 if (myMapRemoved.Contains(aShape)) {
804 if (myMapModified.IsBound(aShape)) {
805 TopTools_ListOfShape aNewShapes;
807 getModified(aShape, aNewShapes);
809 if (!aNewShapes.IsEmpty()) {
810 const TopoDS_Shape &aNewShape = aNewShapes.First();
812 if (aNewShape.ShapeType() == theType) {
813 // Get bounds from the modified shape.
814 TopExp::MapShapes(aNewShape, aBoundType, aMapBounds);
818 // Get bounds from the original shapes.
819 TopExp::MapShapes(aShape, aBoundType, aMapBounds);
824 // Remove duplicated bounds from the faces or solids
827 for (anExp.Init(myShape, theType); anExp.More(); anExp.Next()) {
828 const TopoDS_Shape &aShape = anExp.Current();
830 if (aMapFence.Add(aShape)) {
831 if (myMapModified.IsBound(aShape)) {
832 TopTools_ListOfShape &aNewShapes =
833 myMapModified.ChangeFind(aShape);
834 TopTools_ListIteratorOfListOfShape anIter(aNewShapes);
836 while (anIter.More()) {
837 const TopoDS_Shape &aSubShape = anIter.Value();
838 Standard_Boolean isToRm = Standard_False;
840 if (aSubShape.ShapeType() == aBoundType) {
842 isToRm = aMapBounds.Contains(aSubShape);
843 } else if (aSubShape.ShapeType() == aComplexBndType) {
845 TopTools_ListOfShape aNewBounds;
846 Standard_Boolean isModified;
848 if (theType == TopAbs_FACE) {
849 isModified = removeCommonEdges(aSubShape, aMapBounds, aNewBounds);
851 isModified = removeCommonFaces(aSubShape, aMapBounds, aNewBounds);
855 myMapModified.Bind(aSubShape, aNewBounds);
856 aNewShapes.InsertBefore(aNewBounds, anIter);
857 isToRm = Standard_True; // To remove unmodified bound.
862 aNewShapes.Remove(anIter);
872 //=======================================================================
873 //function : oriented
875 //=======================================================================
876 TopoDS_Shape GEOMAlgo_Extractor::oriented(const TopoDS_Shape &theShape,
877 const TopoDS_Shape &theContext)
879 const TopAbs_Orientation aShapeOri = theShape.Orientation();
880 const TopAbs_Orientation aContextOri = theContext.Orientation();
881 TopoDS_Shape aResult = theShape;
883 aResult.Orientation(TopAbs::Compose(aShapeOri, aContextOri));
888 //=======================================================================
889 //function : makeShape
891 //=======================================================================
892 TopoDS_Shape GEOMAlgo_Extractor::makeShape
893 (const TopoDS_Shape &theShape,
894 const TopTools_ListOfShape &theSubShapes)
896 TopoDS_Shape aResult = getShapeFromSubShapes(theShape, theSubShapes);
898 if (aResult.IsNull()) {
899 // Create a new shape.
900 BRep_Builder aBuilder;
901 TopTools_ListIteratorOfListOfShape anIter(theSubShapes);
902 TopTools_MapOfShape aMapFence;
904 aResult = theShape.EmptyCopied();
907 for (; anIter.More(); anIter.Next()) {
908 const TopoDS_Shape &aSubShape = anIter.Value();
910 if (aMapFence.Add(aSubShape)) {
911 aBuilder.Add(aResult, aSubShape);
913 // Fill the map of new shape - ancestors.
914 if (!myMapNewShapeAnc.IsBound(aSubShape)) {
915 myMapNewShapeAnc.Bind(aSubShape, TopTools_ListOfShape());
918 myMapNewShapeAnc.ChangeFind(aSubShape).Append(aResult);
926 //=======================================================================
927 //function : getShapeFromSubShapes
929 //=======================================================================
930 TopoDS_Shape GEOMAlgo_Extractor::getShapeFromSubShapes
931 (const TopoDS_Shape &theShape,
932 const TopTools_ListOfShape &theSubShapes)
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;
940 for (; anIter.More(); anIter.Next()) {
941 aMapSubShapes.Add(anIter.Value());
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;
952 for (; aMapIt.More(); aMapIt.Next()) {
953 const TopoDS_Shape &aSubShape = aMapIt.Key();
955 // Switch iCur and iPrev.
957 iPrev = iPrev ? 0 : 1;
959 if (myMapNewShapeAnc.IsBound(aSubShape)) {
960 TopTools_ListIteratorOfListOfShape
961 anAncIt(myMapNewShapeAnc.Find(aSubShape));
964 // This is a first loop. Just fill the map of ancestors.
965 for (; anAncIt.More(); anAncIt.Next()) {
966 aMapAncs[iCur].Add(anAncIt.Value());
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();
973 if (aMapAncs[iPrev].Contains(anAncestor)) {
974 aMapAncs[iCur].Add(anAncIt.Value());
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();
986 // This is a new sub-shape. So the result shape is new.
987 aMapAncs[iCur].Clear();
992 if (!aMapAncs[iCur].IsEmpty()) {
993 // Get exactly the same shape.
994 const TopAbs_ShapeEnum aType = theShape.ShapeType();
996 for (aMapIt.Initialize(aMapAncs[iCur]); aMapIt.More(); aMapIt.Next()) {
997 const TopoDS_Shape &aShape = aMapIt.Key();
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;
1005 for (; aSubShIt.More(); aSubShIt.Next()) {
1006 const TopoDS_Shape &aSubSh = aSubShIt.Value();
1008 if (!aMapSubShapes.Contains(aSubSh)) {
1009 // There are another sub-shapes in the ancestor.
1013 if (!isComposedOri && aSubSh.IsSame(aFirstSubShape)) {
1014 // Compose orientaiton.
1015 isComposedOri = Standard_True;
1016 aNewOri = TopAbs::Compose
1017 (aFirstSubShape.Orientation(), aSubSh.Orientation());
1021 if (!aSubShIt.More()) {
1022 // That is the same shape. Compose the orientation.
1024 aResult.Orientation(aNewOri);
1035 //=======================================================================
1036 //function : makeResult
1038 //=======================================================================
1039 TopoDS_Shape GEOMAlgo_Extractor::makeResult(const TopoDS_Shape &theShape)
1041 TopoDS_Shape aResult;
1043 if (!myMapRemoved.Contains(theShape)) {
1044 if (myMapModified.IsBound(theShape)) {
1045 // The shape is modified.
1046 TopTools_ListOfShape aListModif;
1048 getModified(theShape, aListModif);
1050 const Standard_Integer aNbShapes = aListModif.Extent();
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;
1061 aBuilder.MakeCompound(aCompound);
1063 for (; anIter.More(); anIter.Next()) {
1064 const TopoDS_Shape aModifShape = oriented(anIter.Value(), theShape);
1066 if (aMapFence.Add(aModifShape)) {
1067 aBuilder.Add(aCompound, aModifShape);
1071 aResult = aCompound;
1074 // The result is not modified shape.
1082 //=======================================================================
1083 //function : makeHistory
1085 //=======================================================================
1086 void GEOMAlgo_Extractor::makeHistory(const TopoDS_Shape &theShape,
1087 TopTools_MapOfShape &theMapFence)
1089 if (theMapFence.Add(theShape)) {
1090 Standard_Boolean isKept = Standard_True;
1092 if (myMapRemoved.Contains(theShape)) {
1093 myRemoved.Append(theShape);
1094 isKept = Standard_False;
1095 } else if (myMapModified.IsBound(theShape)) {
1096 TopTools_ListOfShape aListModif;
1098 getModified(theShape, aListModif, theShape.ShapeType());
1100 Standard_Boolean isModif = !aListModif.IsEmpty();
1101 const TopAbs_ShapeEnum aType = theShape.ShapeType();
1104 // Add the new shapes.
1105 TopTools_ListIteratorOfListOfShape anIter(aListModif);
1107 // Skip the first shape.
1108 for (anIter.Next(); anIter.More(); anIter.Next()) {
1109 myNew.Append(anIter.Value());
1114 myModified.Append(theShape);
1116 myRemoved.Append(theShape);
1119 isKept = Standard_False;
1123 // Collect history for children.
1124 TopoDS_Iterator anIter(theShape);
1126 for (; anIter.More(); anIter.Next()) {
1127 const TopoDS_Shape &aSubShape = anIter.Value();
1129 makeHistory(aSubShape, theMapFence);
1135 //=======================================================================
1136 //function : removeCommonEdges
1138 //=======================================================================
1139 Standard_Boolean GEOMAlgo_Extractor::removeCommonEdges
1140 (const TopoDS_Shape &theWire,
1141 const TopTools_IndexedMapOfShape &theMapEdgesToRm,
1142 TopTools_ListOfShape &theNewWires)
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];
1150 for (; anExp.More(); anExp.Next()) {
1151 const TopoDS_Shape &anEdge = anExp.Current();
1153 if (theMapEdgesToRm.Contains(anEdge)) {
1154 // This edge is removed.
1155 TopExp::Vertices(TopoDS::Edge(anEdge), aVtx[0], aVtx[1]);
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);
1165 isModified = Standard_True;
1167 aListEdges.Append(anEdge);
1171 if (!aListEdges.IsEmpty()) {
1172 aListListEdges.Append(aListEdges);
1175 if (isModified && !aListListEdges.IsEmpty()) {
1177 makeWires(theWire, aListListEdges, theNewWires);
1183 //=======================================================================
1184 //function : removeCommonFaces
1186 //=======================================================================
1187 Standard_Boolean GEOMAlgo_Extractor::removeCommonFaces
1188 (const TopoDS_Shape &theShell,
1189 const TopTools_IndexedMapOfShape &theMapFacesToRm,
1190 TopTools_ListOfShape &theNewShells)
1192 TopExp_Explorer anExp(theShell, TopAbs_FACE);
1193 TopTools_ListOfShape aListFaces;
1194 Standard_Boolean isModified = Standard_False;
1196 for (; anExp.More(); anExp.Next()) {
1197 const TopoDS_Shape &aFace = anExp.Current();
1199 if (theMapFacesToRm.Contains(aFace)) {
1200 isModified = Standard_True;
1202 aListFaces.Append(aFace);
1206 if (isModified && !aListFaces.IsEmpty()) {
1207 // Create new shells.
1208 groupViaBounds(theShell, aListFaces, theNewShells);
1214 //=======================================================================
1215 //function : makeWires
1217 //=======================================================================
1218 void GEOMAlgo_Extractor::makeWires
1219 (const TopoDS_Shape &theWire,
1220 NCollection_List<TopTools_ListOfShape> &theListListEdges,
1221 TopTools_ListOfShape &theWires)
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;
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);
1235 for (;anIter.More(); anIter.Next()) {
1236 if (anIter.Value().IsEmpty()) {
1237 theListListEdges.Remove(anIter);
1245 NCollection_List<TopTools_ListOfShape>::Iterator anIter(theListListEdges);
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];
1253 TopExp::Vertices(aNewWire, aV[0], aV[1]);
1255 if (!aV[0].IsNull() && !aV[1].IsNull()) {
1256 aNewWire.Closed(aV[0].IsSame(aV[1]));
1259 theWires.Append(aNewWire);
1263 //=======================================================================
1264 //function : groupViaBounds
1266 //=======================================================================
1267 void GEOMAlgo_Extractor::groupViaBounds
1268 (const TopoDS_Shape &theShape,
1269 const TopTools_ListOfShape &theSubShapes,
1270 TopTools_ListOfShape &theNewShapes)
1272 const Standard_Boolean isShell = theShape.ShapeType() == TopAbs_SHELL;
1273 TopAbs_ShapeEnum aBoundType;
1276 aBoundType = TopAbs_EDGE;
1277 } else { // comp-solid
1278 aBoundType = TopAbs_FACE;
1281 // Group connected sub-shapes.
1282 NCollection_Sequence<TopTools_ListOfShape> aGroupedSubShapes;
1283 NCollection_Sequence<TopTools_MapOfShape> aBounds;
1284 TopTools_ListIteratorOfListOfShape anIt(theSubShapes);
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);
1295 for (; anExp.More(); anExp.Next()) {
1296 const TopoDS_Shape &aSubSubShape = anExp.Current();
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.
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);
1317 TopTools_MapOfShape &aLastZoneBound = aBounds.ChangeLast();
1319 for (; anExp.More(); anExp.Next()) {
1320 aLastZoneBound.Add(anExp.Current());
1323 // Merge zones. Get the first zone.
1324 for (i = 1; i <= aNbZones; ++i) {
1325 if (aMapIndices.Contains(i)) {
1330 // Merge other zones with the first one.
1331 TopTools_ListOfShape &aZoneSubShapes = aGroupedSubShapes.ChangeValue(i);
1332 TopTools_MapOfShape &aZoneBounds = aBounds.ChangeValue(i);
1334 for (j = i + 1; j <= aNbZones; ++j) {
1335 if (aMapIndices.Contains(j)) {
1336 aZoneSubShapes.Append(aGroupedSubShapes.ChangeValue(j));
1338 TopTools_MapIteratorOfMapOfShape aMapIt(aBounds.Value(j));
1340 for (; aMapIt.More(); aMapIt.Next()) {
1341 aZoneBounds.Add(aMapIt.Key());
1346 // Remove merged zones.
1347 for (j = aNbZones; j > i; --j) {
1348 aGroupedSubShapes.Remove(j);
1352 // Add aSubShape to merged zone.
1353 aZoneSubShapes.Append(aSubShape);
1354 anExp.Init(aSubShape, aBoundType);
1356 for (; anExp.More(); anExp.Next()) {
1357 const TopoDS_Shape &aSubSubShape = anExp.Current();
1359 if (!aZoneBounds.Add(aSubSubShape)) {
1360 aZoneBounds.Remove(aSubSubShape);
1366 // Construct new shapes from sub-shapes.
1367 const Standard_Integer aNbGroups = aGroupedSubShapes.Size();
1368 TopTools_ListOfShape aNewSubShapes;
1370 for (i = 1; i <= aNbGroups; ++i) {
1371 const TopTools_ListOfShape &aListSubShapes = aGroupedSubShapes.Value(i);
1373 if (!isShell && aListSubShapes.Extent() == 1) {
1374 // Avoid creation of comp-solid with a single solid.
1375 aNewSubShapes.Append(aListSubShapes.First());
1377 TopoDS_Shape aNewShape = makeShape(theShape, aListSubShapes);
1379 if (aBounds.Value(i).IsEmpty()) {
1380 // This is a closed shape.
1381 aNewShape.Closed(Standard_True);
1384 theNewShapes.Append(aNewShape);
1388 // Append the list of single solids (if it is filled).
1389 theNewShapes.Append(aNewSubShapes);
1392 //=======================================================================
1393 //function : getModified
1395 //=======================================================================
1396 void GEOMAlgo_Extractor::getModified(const TopoDS_Shape &theShape,
1397 TopTools_ListOfShape &theModifShapes,
1398 const TopAbs_ShapeEnum theShapeType)
1400 // This shape is modified.
1401 TopTools_ListIteratorOfListOfShape anIt(myMapModified.Find(theShape));
1403 for (; anIt.More(); anIt.Next()) {
1404 const TopoDS_Shape &aSubShape = anIt.Value();
1406 if (theShapeType == TopAbs_SHAPE || aSubShape.ShapeType() == theShapeType) {
1407 if (myMapModified.IsBound(aSubShape)) {
1408 getModified(aSubShape, theModifShapes);
1410 theModifShapes.Append(aSubShape);
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.
1426 // myWarningStatus :
1428 // 10 -mySubShapes is empty