]> SALOME platform Git repositories - modules/shaper.git/blob - src/GeomAPI/GeomAPI_ShapeHierarchy.cpp
Salome HOME
cac15eabe4d78435489629b17e9fae0374b55e51
[modules/shaper.git] / src / GeomAPI / GeomAPI_ShapeHierarchy.cpp
1 // Copyright (C) 2014-2020  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "GeomAPI_ShapeHierarchy.h"
21
22 #include "GeomAPI_ShapeIterator.h"
23
24 #include <BRep_Builder.hxx>
25 #include <TopoDS_Shape.hxx>
26
27 void GeomAPI_ShapeHierarchy::addObject(const GeomShapePtr& theObject)
28 {
29   myObjects.push_back(theObject);
30 }
31
32 void GeomAPI_ShapeHierarchy::addParent(const GeomShapePtr& theShape,
33                                        const GeomShapePtr& theParent)
34 {
35   myParent[theShape] = theParent;
36
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()));
42   } else
43     anIndex = aFound->second;
44
45   mySubshapes[anIndex].second.push_back(theShape);
46 }
47
48 GeomShapePtr GeomAPI_ShapeHierarchy::parent(const GeomShapePtr& theShape,
49                                             bool theMarkProcessed)
50 {
51   MapShapeToShape::const_iterator aFound = myParent.find(theShape);
52   GeomShapePtr aParent;
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     }
59   }
60   return aParent;
61 }
62
63 void GeomAPI_ShapeHierarchy::markProcessed(const GeomShapePtr& theShape)
64 {
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)
71       markProcessed(*anIt);
72   }
73 }
74
75 void GeomAPI_ShapeHierarchy::markProcessed(const ListOfShape& theShapes)
76 {
77   for (ListOfShape::const_iterator anIt = theShapes.begin(); anIt != theShapes.end(); ++anIt)
78     markProcessed(*anIt);
79 }
80
81 void GeomAPI_ShapeHierarchy::markModified(const GeomShapePtr& theSource,
82                                           const GeomShapePtr& theModified)
83 {
84   myModifiedObjects[theSource] = theModified;
85 }
86
87 void GeomAPI_ShapeHierarchy::objectsByType(
88     ListOfShape& theShapesByType,
89     ListOfShape& theOtherShapes,
90     const GeomAPI_Shape::ShapeType theMinType,
91     const GeomAPI_Shape::ShapeType theMaxType) const
92 {
93   if (theMinType > theMaxType)
94     return objectsByType(theShapesByType, theOtherShapes, theMaxType, theMinType);
95
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());
99     return;
100   }
101
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);
106     else
107       theOtherShapes.push_back(*anIt);
108   }
109 }
110
111
112 void GeomAPI_ShapeHierarchy::splitCompound(
113     const GeomShapePtr& theCompShape,
114     ListOfShape& theUsed,
115     ListOfShape& theNotUsed) const
116 {
117   theUsed.clear();
118   theNotUsed.clear();
119
120   MapShapeToIndex::const_iterator aFoundIndex = myParentIndices.find(theCompShape);
121   if (aFoundIndex == myParentIndices.end())
122     return; // no such shape
123
124   theUsed = mySubshapes[aFoundIndex->second].second;
125   SetOfShape aSubsSet;
126   aSubsSet.insert(theUsed.begin(), theUsed.end());
127
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);
132   }
133 }
134
135 bool GeomAPI_ShapeHierarchy::empty() const
136 {
137   return myObjects.empty();
138 }
139
140 void GeomAPI_ShapeHierarchy::topLevelObjects(ListOfShape& theDestination) const
141 {
142   GeomAPI_ShapeHierarchy* aThis = const_cast<GeomAPI_ShapeHierarchy*>(this);
143   SetOfShape aProcessed = myProcessedObjects;
144   aThis->myProcessedObjects.clear();
145
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;
151     while (aParent) {
152       aParent = aThis->parent(aRoot);
153       if (aParent)
154         aRoot = aParent;
155     }
156
157     if (aRoot) {
158       // compose a compund with the modified shapes
159       aShape = collectSubs(aRoot, SetOfShape(), myModifiedObjects);
160     }
161     else {
162       // check the current shape was modified
163       MapShapeToShape::const_iterator aFound = myModifiedObjects.find(aShape);
164       if (aFound != myModifiedObjects.end())
165         aShape = aFound->second;
166     }
167
168     theDestination.push_back(aShape);
169   }
170
171   aThis->myProcessedObjects = aProcessed;
172 }
173
174 void GeomAPI_ShapeHierarchy::compoundsOfUnusedObjects(
175     ListOfShape& theDestination) const
176 {
177   SetOfShape aUsedObjects = myProcessedObjects;
178   aUsedObjects.insert(myObjects.begin(), myObjects.end());
179
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
188       if (aCompound)
189         theDestination.push_back(aCompound);
190     }
191   }
192 }
193
194 static void addSubShape(GeomShapePtr theTarget, GeomShapePtr theSub,
195     const std::map<GeomShapePtr, GeomShapePtr, GeomAPI_Shape::Comparator>& theModified)
196 {
197   if (!theTarget.get() || !theSub.get())
198     return;
199
200   TopoDS_Shape* aShape = theTarget->implPtr<TopoDS_Shape>();
201
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>();
206
207   static BRep_Builder aBuilder;
208   aBuilder.Add(*aShape, aShapeToAdd);
209 }
210
211 GeomShapePtr GeomAPI_ShapeHierarchy::collectSubs(
212     GeomShapePtr theTopLevelCompound,
213     const SetOfShape& theExcluded,
214     const MapShapeToShape& theModified) const
215 {
216   GeomShapePtr aResult = theTopLevelCompound->emptyCopied();
217   bool isResultEmpty = true;
218
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
223
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();
232       }
233
234       if (isAddShape) { // low-level shape, add it
235         addSubShape(aResult, aCurrent, theModified);
236         isResultEmpty = false;
237       }
238     } else {
239       GeomShapePtr aCompound = collectSubs(aCurrent, theExcluded, theModified);
240       if (aCompound) {
241         addSubShape(aResult, aCompound, theModified);
242         isResultEmpty = false;
243       }
244     }
245   }
246   return isResultEmpty ? GeomShapePtr() : aResult;
247 }
248
249
250 GeomAPI_ShapeHierarchy::iterator GeomAPI_ShapeHierarchy::begin()
251 {
252   return iterator(this);
253 }
254
255 GeomAPI_ShapeHierarchy::iterator GeomAPI_ShapeHierarchy::end()
256 {
257   return iterator(this, false);
258 }
259
260 GeomAPI_ShapeHierarchy::iterator::iterator(
261     GeomAPI_ShapeHierarchy* theHierarchy, bool isBegin)
262   : myHierarchy(theHierarchy)
263 {
264   if (isBegin) {
265     myObject = myHierarchy->myObjects.begin();
266     skipAlreadyProcessed();
267   } else
268     myObject = myHierarchy->myObjects.end();
269 }
270
271 void GeomAPI_ShapeHierarchy::iterator::skipAlreadyProcessed()
272 {
273   while (myObject != myHierarchy->myObjects.end() &&
274          myHierarchy->myProcessedObjects.find(*myObject) != myHierarchy->myProcessedObjects.end())
275     ++myObject;
276 }
277
278 bool GeomAPI_ShapeHierarchy::iterator::operator==(const iterator& theOther) const
279 {
280   return myObject == theOther.myObject;
281 }
282
283 bool GeomAPI_ShapeHierarchy::iterator::operator!=(const iterator& theOther) const
284 {
285   return !operator==(theOther);
286 }
287
288 GeomAPI_ShapeHierarchy::iterator& GeomAPI_ShapeHierarchy::iterator::operator++()
289 {
290   ++myObject;
291   skipAlreadyProcessed();
292   return *this;
293 }
294
295 GeomAPI_ShapeHierarchy::iterator GeomAPI_ShapeHierarchy::iterator::operator++(int)
296 {
297   iterator aCurrent;
298   aCurrent.myHierarchy = myHierarchy;
299   aCurrent.myObject = myObject;
300
301   // increase iterator
302   operator++();
303
304   return aCurrent;
305 }
306
307 GeomShapePtr GeomAPI_ShapeHierarchy::iterator::operator*() const
308 {
309   myHierarchy->markProcessed(*myObject);
310   return *myObject;
311 }