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 MapShapeToShape::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);
63 void GeomAPI_ShapeHierarchy::markProcessed(const GeomShapePtr& theShape)
65 myProcessedObjects.insert(theShape);
66 // mark sub-shapes of the compound as processed too
67 MapShapeToIndex::iterator aFoundInd = myParentIndices.find(theShape);
68 if (aFoundInd != myParentIndices.end()) {
69 const ListOfShape& aSubs = mySubshapes[aFoundInd->second].second;
70 for (ListOfShape::const_iterator anIt = aSubs.begin(); anIt != aSubs.end(); ++anIt)
75 void GeomAPI_ShapeHierarchy::markProcessed(const ListOfShape& theShapes)
77 for (ListOfShape::const_iterator anIt = theShapes.begin(); anIt != theShapes.end(); ++anIt)
81 void GeomAPI_ShapeHierarchy::markModified(const GeomShapePtr& theSource,
82 const GeomShapePtr& theModified)
84 myModifiedObjects[theSource] = theModified;
87 void GeomAPI_ShapeHierarchy::objectsByType(
88 ListOfShape& theShapesByType,
89 ListOfShape& theOtherShapes,
90 const GeomAPI_Shape::ShapeType theMinType,
91 const GeomAPI_Shape::ShapeType theMaxType) const
93 if (theMinType > theMaxType)
94 return objectsByType(theShapesByType, theOtherShapes, theMaxType, theMinType);
96 // no need to select objects if whole range is specified
97 if (theMinType == GeomAPI_Shape::COMPOUND && theMaxType == GeomAPI_Shape::SHAPE) {
98 theShapesByType.insert(theShapesByType.end(), myObjects.begin(), myObjects.end());
102 for (ListOfShape::const_iterator anIt = myObjects.begin(); anIt != myObjects.end(); ++anIt) {
103 GeomAPI_Shape::ShapeType aType = (*anIt)->shapeType();
104 if (aType >= theMinType && aType <= theMaxType)
105 theShapesByType.push_back(*anIt);
107 theOtherShapes.push_back(*anIt);
112 void GeomAPI_ShapeHierarchy::splitCompound(
113 const GeomShapePtr& theCompShape,
114 ListOfShape& theUsed,
115 ListOfShape& theNotUsed) const
120 MapShapeToIndex::const_iterator aFoundIndex = myParentIndices.find(theCompShape);
121 if (aFoundIndex == myParentIndices.end())
122 return; // no such shape
124 theUsed = mySubshapes[aFoundIndex->second].second;
126 aSubsSet.insert(theUsed.begin(), theUsed.end());
128 for (GeomAPI_ShapeIterator anExp(theCompShape); anExp.more(); anExp.next()) {
129 GeomShapePtr aCurrent = anExp.current();
130 if (aSubsSet.find(aCurrent) == aSubsSet.end())
131 theNotUsed.push_back(aCurrent);
135 bool GeomAPI_ShapeHierarchy::empty() const
137 return myObjects.empty();
140 void GeomAPI_ShapeHierarchy::topLevelObjects(ListOfShape& theDestination) const
142 GeomAPI_ShapeHierarchy* aThis = const_cast<GeomAPI_ShapeHierarchy*>(this);
143 SetOfShape aProcessed = myProcessedObjects;
144 aThis->myProcessedObjects.clear();
146 iterator anIt = aThis->begin(), aEnd = aThis->end();
147 for (; anIt != aEnd; ++anIt) {
148 GeomShapePtr aShape = *anIt;
149 GeomShapePtr aParent = aThis->parent(aShape);
150 GeomShapePtr aRoot = aParent;
152 aParent = aThis->parent(aRoot);
158 // compose a compund with the modified shapes
159 aShape = collectSubs(aRoot, SetOfShape(), myModifiedObjects);
162 // check the current shape was modified
163 MapShapeToShape::const_iterator aFound = myModifiedObjects.find(aShape);
164 if (aFound != myModifiedObjects.end())
165 aShape = aFound->second;
168 theDestination.push_back(aShape);
171 aThis->myProcessedObjects = aProcessed;
174 void GeomAPI_ShapeHierarchy::compoundsOfUnusedObjects(
175 ListOfShape& theDestination) const
177 SetOfShape aUsedObjects = myProcessedObjects;
178 aUsedObjects.insert(myObjects.begin(), myObjects.end());
180 for (std::vector<ShapeAndSubshapes>::const_iterator anIt = mySubshapes.begin();
181 anIt != mySubshapes.end(); ++anIt) {
182 MapShapeToShape::const_iterator aParent = myParent.find(anIt->first);
183 if ((aParent == myParent.end() || !aParent->second) &&
184 anIt->first->shapeType() == GeomAPI_Shape::COMPOUND) {
185 // this is a top-level compound
186 GeomShapePtr aCompound = collectSubs(anIt->first, aUsedObjects);
187 // add to destination non-empty compounds only
189 theDestination.push_back(aCompound);
194 static void addSubShape(GeomShapePtr theTarget, GeomShapePtr theSub,
195 const std::map<GeomShapePtr, GeomShapePtr, GeomAPI_Shape::Comparator>& theModified)
197 if (!theTarget.get() || !theSub.get())
200 TopoDS_Shape* aShape = theTarget->implPtr<TopoDS_Shape>();
202 std::map<GeomShapePtr, GeomShapePtr, GeomAPI_Shape::Comparator>::const_iterator
203 aFound = theModified.find(theSub);
204 const TopoDS_Shape& aShapeToAdd =
205 (aFound == theModified.end() ? theSub : aFound->second)->impl<TopoDS_Shape>();
207 static BRep_Builder aBuilder;
208 aBuilder.Add(*aShape, aShapeToAdd);
211 GeomShapePtr GeomAPI_ShapeHierarchy::collectSubs(
212 GeomShapePtr theTopLevelCompound,
213 const SetOfShape& theExcluded,
214 const MapShapeToShape& theModified) const
216 GeomShapePtr aResult = theTopLevelCompound->emptyCopied();
217 bool isResultEmpty = true;
219 for (GeomAPI_ShapeIterator aSub(theTopLevelCompound); aSub.more(); aSub.next()) {
220 GeomShapePtr aCurrent = aSub.current();
221 if (theExcluded.find(aCurrent) != theExcluded.end())
222 continue; // already used
224 MapShapeToIndex::const_iterator aFoundIndex = myParentIndices.find(aCurrent);
225 if (aCurrent->shapeType() > GeomAPI_Shape::COMPOUND ||
226 aFoundIndex == myParentIndices.end()) {
227 bool isAddShape = true;
228 // check compsolid is fully unused in the Boolean operation
229 if (aCurrent->shapeType() == GeomAPI_Shape::COMPSOLID) {
230 for (GeomAPI_ShapeIterator anIt(aCurrent); isAddShape && anIt.more(); anIt.next())
231 isAddShape = theExcluded.find(anIt.current()) == theExcluded.end();
234 if (isAddShape) { // low-level shape, add it
235 addSubShape(aResult, aCurrent, theModified);
236 isResultEmpty = false;
239 GeomShapePtr aCompound = collectSubs(aCurrent, theExcluded, theModified);
241 addSubShape(aResult, aCompound, theModified);
242 isResultEmpty = false;
246 return isResultEmpty ? GeomShapePtr() : aResult;
250 GeomAPI_ShapeHierarchy::iterator GeomAPI_ShapeHierarchy::begin()
252 return iterator(this);
255 GeomAPI_ShapeHierarchy::iterator GeomAPI_ShapeHierarchy::end()
257 return iterator(this, false);
260 GeomAPI_ShapeHierarchy::iterator::iterator(
261 GeomAPI_ShapeHierarchy* theHierarchy, bool isBegin)
262 : myHierarchy(theHierarchy)
265 myObject = myHierarchy->myObjects.begin();
266 skipAlreadyProcessed();
268 myObject = myHierarchy->myObjects.end();
271 void GeomAPI_ShapeHierarchy::iterator::skipAlreadyProcessed()
273 while (myObject != myHierarchy->myObjects.end() &&
274 myHierarchy->myProcessedObjects.find(*myObject) != myHierarchy->myProcessedObjects.end())
278 bool GeomAPI_ShapeHierarchy::iterator::operator==(const iterator& theOther) const
280 return myObject == theOther.myObject;
283 bool GeomAPI_ShapeHierarchy::iterator::operator!=(const iterator& theOther) const
285 return !operator==(theOther);
288 GeomAPI_ShapeHierarchy::iterator& GeomAPI_ShapeHierarchy::iterator::operator++()
291 skipAlreadyProcessed();
295 GeomAPI_ShapeHierarchy::iterator GeomAPI_ShapeHierarchy::iterator::operator++(int)
298 aCurrent.myHierarchy = myHierarchy;
299 aCurrent.myObject = myObject;
307 GeomShapePtr GeomAPI_ShapeHierarchy::iterator::operator*() const
309 myHierarchy->markProcessed(*myObject);