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 GeomShapePtr GeomAPI_ShapeHierarchy::root(const GeomShapePtr& theShape,
64 bool theMarkProcessed)
66 GeomShapePtr aParent = parent(theShape, theMarkProcessed);
67 GeomShapePtr aRoot = aParent;
69 aParent = parent(aRoot, theMarkProcessed);
76 void GeomAPI_ShapeHierarchy::markProcessed(const GeomShapePtr& theShape)
78 myProcessedObjects.insert(theShape);
79 // mark sub-shapes of the compound as processed too
80 MapShapeToIndex::iterator aFoundInd = myParentIndices.find(theShape);
81 if (aFoundInd != myParentIndices.end()) {
82 const ListOfShape& aSubs = mySubshapes[aFoundInd->second].second;
83 for (ListOfShape::const_iterator anIt = aSubs.begin(); anIt != aSubs.end(); ++anIt)
88 void GeomAPI_ShapeHierarchy::markProcessed(const ListOfShape& theShapes)
90 for (ListOfShape::const_iterator anIt = theShapes.begin(); anIt != theShapes.end(); ++anIt)
94 void GeomAPI_ShapeHierarchy::markModified(const GeomShapePtr& theSource,
95 const GeomShapePtr& theModified)
97 myModifiedObjects[theSource] = theModified;
100 const ListOfShape& GeomAPI_ShapeHierarchy::objects(GeomShapePtr theParent) const
102 MapShapeToIndex::const_iterator aFoundIndex = myParentIndices.find(theParent);
103 if (aFoundIndex == myParentIndices.end()) {
104 static const ListOfShape THE_DUMMY = ListOfShape();
105 return THE_DUMMY; // no such shape
108 return mySubshapes[aFoundIndex->second].second;
111 void GeomAPI_ShapeHierarchy::objectsByType(
112 ListOfShape& theShapesByType,
113 ListOfShape& theOtherShapes,
114 const GeomAPI_Shape::ShapeType theMinType,
115 const GeomAPI_Shape::ShapeType theMaxType) const
117 if (theMinType > theMaxType)
118 return objectsByType(theShapesByType, theOtherShapes, theMaxType, theMinType);
120 // no need to select objects if whole range is specified
121 if (theMinType == GeomAPI_Shape::COMPOUND && theMaxType == GeomAPI_Shape::SHAPE) {
122 theShapesByType.insert(theShapesByType.end(), myObjects.begin(), myObjects.end());
126 for (ListOfShape::const_iterator anIt = myObjects.begin(); anIt != myObjects.end(); ++anIt) {
127 GeomAPI_Shape::ShapeType aType = (*anIt)->shapeType();
128 if (aType >= theMinType && aType <= theMaxType)
129 theShapesByType.push_back(*anIt);
131 theOtherShapes.push_back(*anIt);
136 void GeomAPI_ShapeHierarchy::splitCompound(
137 const GeomShapePtr& theCompShape,
138 ListOfShape& theUsed,
139 ListOfShape& theNotUsed) const
144 MapShapeToIndex::const_iterator aFoundIndex = myParentIndices.find(theCompShape);
145 if (aFoundIndex == myParentIndices.end())
146 return; // no such shape
148 theUsed = mySubshapes[aFoundIndex->second].second;
150 aSubsSet.insert(theUsed.begin(), theUsed.end());
152 for (GeomAPI_ShapeIterator anExp(theCompShape); anExp.more(); anExp.next()) {
153 GeomShapePtr aCurrent = anExp.current();
154 if (aSubsSet.find(aCurrent) == aSubsSet.end())
155 theNotUsed.push_back(aCurrent);
159 bool GeomAPI_ShapeHierarchy::empty() const
161 return myObjects.empty();
164 void GeomAPI_ShapeHierarchy::topLevelObjects(ListOfShape& theDestination) const
166 GeomAPI_ShapeHierarchy* aThis = const_cast<GeomAPI_ShapeHierarchy*>(this);
167 SetOfShape aProcessed = myProcessedObjects;
168 aThis->myProcessedObjects.clear();
170 iterator anIt = aThis->begin(), aEnd = aThis->end();
171 for (; anIt != aEnd; ++anIt) {
172 GeomShapePtr aShape = *anIt;
173 GeomShapePtr aRoot = aThis->root(aShape);
175 // check the current shape was modified
176 MapShapeToShape::const_iterator aFound = myModifiedObjects.find(aRoot);
177 if (aFound != myModifiedObjects.end())
178 aShape = aFound->second;
180 // compose a compund with the modified shapes
181 aShape = collectSubs(aRoot, SetOfShape(), myModifiedObjects);
185 // check the current shape was modified
186 MapShapeToShape::const_iterator aFound = myModifiedObjects.find(aShape);
187 if (aFound != myModifiedObjects.end())
188 aShape = aFound->second;
191 theDestination.push_back(aShape);
194 aThis->myProcessedObjects = aProcessed;
197 void GeomAPI_ShapeHierarchy::compoundsOfUnusedObjects(
198 ListOfShape& theDestination) const
200 SetOfShape aUsedObjects = myProcessedObjects;
201 aUsedObjects.insert(myObjects.begin(), myObjects.end());
203 for (std::vector<ShapeAndSubshapes>::const_iterator anIt = mySubshapes.begin();
204 anIt != mySubshapes.end(); ++anIt) {
205 MapShapeToShape::const_iterator aParent = myParent.find(anIt->first);
206 if ((aParent == myParent.end() || !aParent->second) &&
207 anIt->first->shapeType() == GeomAPI_Shape::COMPOUND) {
208 // this is a top-level compound
209 GeomShapePtr aCompound = collectSubs(anIt->first, aUsedObjects);
210 // add to destination non-empty compounds only
212 theDestination.push_back(aCompound);
217 static void addSubShape(GeomShapePtr theTarget, GeomShapePtr theSub,
218 const std::map<GeomShapePtr, GeomShapePtr, GeomAPI_Shape::Comparator>& theModified)
220 if (!theTarget.get() || !theSub.get())
223 TopoDS_Shape* aShape = theTarget->implPtr<TopoDS_Shape>();
225 std::map<GeomShapePtr, GeomShapePtr, GeomAPI_Shape::Comparator>::const_iterator
226 aFound = theModified.find(theSub);
227 const TopoDS_Shape& aShapeToAdd =
228 (aFound == theModified.end() ? theSub : aFound->second)->impl<TopoDS_Shape>();
230 static BRep_Builder aBuilder;
231 aBuilder.Add(*aShape, aShapeToAdd);
234 GeomShapePtr GeomAPI_ShapeHierarchy::collectSubs(
235 GeomShapePtr theTopLevelCompound,
236 const SetOfShape& theExcluded,
237 const MapShapeToShape& theModified) const
239 GeomShapePtr aResult = theTopLevelCompound->emptyCopied();
240 bool isResultEmpty = true;
242 for (GeomAPI_ShapeIterator aSub(theTopLevelCompound); aSub.more(); aSub.next()) {
243 GeomShapePtr aCurrent = aSub.current();
244 if (theExcluded.find(aCurrent) != theExcluded.end())
245 continue; // already used
247 MapShapeToIndex::const_iterator aFoundIndex = myParentIndices.find(aCurrent);
248 if (aCurrent->shapeType() > GeomAPI_Shape::COMPOUND ||
249 aFoundIndex == myParentIndices.end()) {
250 bool isAddShape = true;
251 // check compsolid is fully unused in the Boolean operation
252 if (aCurrent->shapeType() == GeomAPI_Shape::COMPSOLID) {
253 for (GeomAPI_ShapeIterator anIt(aCurrent); isAddShape && anIt.more(); anIt.next())
254 isAddShape = theExcluded.find(anIt.current()) == theExcluded.end();
257 if (isAddShape) { // low-level shape, add it
258 addSubShape(aResult, aCurrent, theModified);
259 isResultEmpty = false;
262 GeomShapePtr aCompound = collectSubs(aCurrent, theExcluded, theModified);
264 addSubShape(aResult, aCompound, theModified);
265 isResultEmpty = false;
269 return isResultEmpty ? GeomShapePtr() : aResult;
273 GeomAPI_ShapeHierarchy::iterator GeomAPI_ShapeHierarchy::begin()
275 return iterator(this);
278 GeomAPI_ShapeHierarchy::iterator GeomAPI_ShapeHierarchy::end()
280 return iterator(this, false);
283 GeomAPI_ShapeHierarchy::iterator::iterator(
284 GeomAPI_ShapeHierarchy* theHierarchy, bool isBegin)
285 : myHierarchy(theHierarchy)
288 myObject = myHierarchy->myObjects.begin();
289 skipAlreadyProcessed();
291 myObject = myHierarchy->myObjects.end();
294 void GeomAPI_ShapeHierarchy::iterator::skipAlreadyProcessed()
296 while (myObject != myHierarchy->myObjects.end() &&
297 myHierarchy->myProcessedObjects.find(*myObject) != myHierarchy->myProcessedObjects.end())
301 bool GeomAPI_ShapeHierarchy::iterator::operator==(const iterator& theOther) const
303 return myObject == theOther.myObject;
306 bool GeomAPI_ShapeHierarchy::iterator::operator!=(const iterator& theOther) const
308 return !operator==(theOther);
311 GeomAPI_ShapeHierarchy::iterator& GeomAPI_ShapeHierarchy::iterator::operator++()
314 skipAlreadyProcessed();
318 GeomAPI_ShapeHierarchy::iterator GeomAPI_ShapeHierarchy::iterator::operator++(int)
321 aCurrent.myHierarchy = myHierarchy;
322 aCurrent.myObject = myObject;
330 GeomShapePtr GeomAPI_ShapeHierarchy::iterator::operator*() const
332 myHierarchy->markProcessed(*myObject);