1 // Copyright (C) 2014-2020 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "GeomAPI_ShapeHierarchy.h"
22 #include "GeomAPI_ShapeIterator.h"
24 #include <BRep_Builder.hxx>
25 #include <TopoDS_Shape.hxx>
27 void GeomAPI_ShapeHierarchy::addObject(const GeomShapePtr& theObject)
29 myObjects.push_back(theObject);
32 void GeomAPI_ShapeHierarchy::addParent(const GeomShapePtr& theShape,
33 const GeomShapePtr& theParent)
35 myParent[theShape] = theParent;
37 MapShapeToIndex::iterator aFound = myParentIndices.find(theParent);
38 size_t anIndex = myParentIndices.size();
39 if (aFound == myParentIndices.end()) {
40 myParentIndices[theParent] = anIndex;
41 mySubshapes.push_back(ShapeAndSubshapes(theParent, ListOfShape()));
43 anIndex = aFound->second;
45 mySubshapes[anIndex].second.push_back(theShape);
48 GeomShapePtr GeomAPI_ShapeHierarchy::parent(const GeomShapePtr& theShape,
49 bool theMarkProcessed)
51 MapShapeToParent::const_iterator aFound = myParent.find(theShape);
53 if (aFound != myParent.end()) {
54 aParent = aFound->second;
55 if (theMarkProcessed) {
56 // mark the parent and all its subs as processed by Boolean algorithm
57 markProcessed(aParent);
58 const ListOfShape& aSubs = mySubshapes[myParentIndices[aParent]].second;
59 for (ListOfShape::const_iterator anIt = aSubs.begin(); anIt != aSubs.end(); ++anIt)
66 void GeomAPI_ShapeHierarchy::markProcessed(const GeomShapePtr& theShape)
68 myProcessedObjects.insert(theShape);
71 void GeomAPI_ShapeHierarchy::markProcessed(const ListOfShape& theShapes)
73 for (ListOfShape::const_iterator anIt = theShapes.begin(); anIt != theShapes.end(); ++anIt)
77 void GeomAPI_ShapeHierarchy::objectsByType(
78 ListOfShape& theShapesByType,
79 ListOfShape& theOtherShapes,
80 const GeomAPI_Shape::ShapeType theMinType,
81 const GeomAPI_Shape::ShapeType theMaxType) const
83 if (theMinType > theMaxType)
84 return objectsByType(theShapesByType, theOtherShapes, theMaxType, theMinType);
86 // no need to select objects if whole range is specified
87 if (theMinType == GeomAPI_Shape::COMPOUND && theMaxType == GeomAPI_Shape::SHAPE) {
88 theShapesByType.insert(theShapesByType.end(), myObjects.begin(), myObjects.end());
92 for (ListOfShape::const_iterator anIt = myObjects.begin(); anIt != myObjects.end(); ++anIt) {
93 GeomAPI_Shape::ShapeType aType = (*anIt)->shapeType();
94 if (aType >= theMinType && aType <= theMaxType)
95 theShapesByType.push_back(*anIt);
97 theOtherShapes.push_back(*anIt);
102 void GeomAPI_ShapeHierarchy::splitCompound(
103 const GeomShapePtr& theCompShape,
104 ListOfShape& theUsed,
105 ListOfShape& theNotUsed) const
110 MapShapeToIndex::const_iterator aFoundIndex = myParentIndices.find(theCompShape);
111 if (aFoundIndex == myParentIndices.end())
112 return; // no such shape
114 theUsed = mySubshapes[aFoundIndex->second].second;
116 aSubsSet.insert(theUsed.begin(), theUsed.end());
118 for (GeomAPI_ShapeIterator anExp(theCompShape); anExp.more(); anExp.next()) {
119 GeomShapePtr aCurrent = anExp.current();
120 if (aSubsSet.find(aCurrent) == aSubsSet.end())
121 theNotUsed.push_back(aCurrent);
125 bool GeomAPI_ShapeHierarchy::empty() const
127 return myObjects.empty();
130 void GeomAPI_ShapeHierarchy::compoundsOfUnusedObjects(
131 ListOfShape& theDestination) const
133 SetOfShape aUsedObjects = myProcessedObjects;
134 aUsedObjects.insert(myObjects.begin(), myObjects.end());
136 for (std::vector<ShapeAndSubshapes>::const_iterator anIt = mySubshapes.begin();
137 anIt != mySubshapes.end(); ++anIt) {
138 MapShapeToParent::const_iterator aParent = myParent.find(anIt->first);
139 if ((aParent == myParent.end() || !aParent->second) &&
140 anIt->first->shapeType() == GeomAPI_Shape::COMPOUND) {
141 // this is a top-level compound
142 GeomShapePtr aCompound = collectUnusedSubs(anIt->first, aUsedObjects);
143 // add to destination non-empty compounds only
145 theDestination.push_back(aCompound);
150 static void addSubShape(GeomShapePtr theTarget, GeomShapePtr theSub)
152 if (!theTarget.get() || !theSub.get())
155 TopoDS_Shape* aShape = theTarget->implPtr<TopoDS_Shape>();
156 const TopoDS_Shape& aShapeToAdd = theSub->impl<TopoDS_Shape>();
158 static BRep_Builder aBuilder;
159 aBuilder.Add(*aShape, aShapeToAdd);
162 GeomShapePtr GeomAPI_ShapeHierarchy::collectUnusedSubs(
163 GeomShapePtr theTopLevelCompound,
164 const SetOfShape& theUsed) const
166 GeomShapePtr aResult = theTopLevelCompound->emptyCopied();
167 bool isResultEmpty = true;
169 for (GeomAPI_ShapeIterator aSub(theTopLevelCompound); aSub.more(); aSub.next()) {
170 GeomShapePtr aCurrent = aSub.current();
171 if (theUsed.find(aCurrent) != theUsed.end())
172 continue; // already used
174 MapShapeToIndex::const_iterator aFoundIndex = myParentIndices.find(aCurrent);
175 if (aCurrent->shapeType() > GeomAPI_Shape::COMPOUND ||
176 aFoundIndex == myParentIndices.end()) {
177 bool isAddShape = true;
178 // check compsolid is fully unused in the Boolean operation
179 if (aCurrent->shapeType() == GeomAPI_Shape::COMPSOLID) {
180 for (GeomAPI_ShapeIterator anIt(aCurrent); isAddShape && anIt.more(); anIt.next())
181 isAddShape = theUsed.find(anIt.current()) == theUsed.end();
184 if (isAddShape) { // low-level shape, add it
185 addSubShape(aResult, aCurrent);
186 isResultEmpty = false;
189 GeomShapePtr aCompound = collectUnusedSubs(aCurrent, theUsed);
191 addSubShape(aResult, aCompound);
192 isResultEmpty = false;
196 return isResultEmpty ? GeomShapePtr() : aResult;
200 GeomAPI_ShapeHierarchy::iterator GeomAPI_ShapeHierarchy::begin()
202 return iterator(this);
205 GeomAPI_ShapeHierarchy::iterator GeomAPI_ShapeHierarchy::end()
207 return iterator(this, false);
210 GeomAPI_ShapeHierarchy::iterator::iterator(
211 GeomAPI_ShapeHierarchy* theHierarchy, bool isBegin)
212 : myHierarchy(theHierarchy)
215 myObject = myHierarchy->myObjects.begin();
216 skipAlreadyProcessed();
218 myObject = myHierarchy->myObjects.end();
221 void GeomAPI_ShapeHierarchy::iterator::skipAlreadyProcessed()
223 while (myObject != myHierarchy->myObjects.end() &&
224 myHierarchy->myProcessedObjects.find(*myObject) != myHierarchy->myProcessedObjects.end())
228 bool GeomAPI_ShapeHierarchy::iterator::operator==(const iterator& theOther) const
230 return myObject == theOther.myObject;
233 bool GeomAPI_ShapeHierarchy::iterator::operator!=(const iterator& theOther) const
235 return !operator==(theOther);
238 GeomAPI_ShapeHierarchy::iterator& GeomAPI_ShapeHierarchy::iterator::operator++()
241 skipAlreadyProcessed();
245 GeomAPI_ShapeHierarchy::iterator GeomAPI_ShapeHierarchy::iterator::operator++(int)
248 aCurrent.myHierarchy = myHierarchy;
249 aCurrent.myObject = myObject;
257 GeomShapePtr GeomAPI_ShapeHierarchy::iterator::operator*() const
259 myHierarchy->markProcessed(*myObject);