]> SALOME platform Git repositories - modules/shaper.git/blob - src/GeomAPI/GeomAPI_ShapeHierarchy.cpp
Salome HOME
Extract ShapeHierarchy as a separate object
[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   MapShapeToParent::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       const ListOfShape& aSubs = mySubshapes[myParentIndices[aParent]].second;
59       for (ListOfShape::const_iterator anIt = aSubs.begin(); anIt != aSubs.end(); ++anIt)
60         markProcessed(*anIt);
61     }
62   }
63   return aParent;
64 }
65
66 void GeomAPI_ShapeHierarchy::markProcessed(const GeomShapePtr& theShape)
67 {
68   myProcessedObjects.insert(theShape);
69 }
70
71 void GeomAPI_ShapeHierarchy::markProcessed(const ListOfShape& theShapes)
72 {
73   for (ListOfShape::const_iterator anIt = theShapes.begin(); anIt != theShapes.end(); ++anIt)
74     markProcessed(*anIt);
75 }
76
77 void GeomAPI_ShapeHierarchy::objectsByType(
78     ListOfShape& theShapesByType,
79     ListOfShape& theOtherShapes,
80     const GeomAPI_Shape::ShapeType theMinType,
81     const GeomAPI_Shape::ShapeType theMaxType) const
82 {
83   if (theMinType > theMaxType)
84     return objectsByType(theShapesByType, theOtherShapes, theMaxType, theMinType);
85
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());
89     return;
90   }
91
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);
96     else
97       theOtherShapes.push_back(*anIt);
98   }
99 }
100
101
102 void GeomAPI_ShapeHierarchy::splitCompound(
103     const GeomShapePtr& theCompShape,
104     ListOfShape& theUsed,
105     ListOfShape& theNotUsed) const
106 {
107   theUsed.clear();
108   theNotUsed.clear();
109
110   MapShapeToIndex::const_iterator aFoundIndex = myParentIndices.find(theCompShape);
111   if (aFoundIndex == myParentIndices.end())
112     return; // no such shape
113
114   theUsed = mySubshapes[aFoundIndex->second].second;
115   SetOfShape aSubsSet;
116   aSubsSet.insert(theUsed.begin(), theUsed.end());
117
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);
122   }
123 }
124
125 bool GeomAPI_ShapeHierarchy::empty() const
126 {
127   return myObjects.empty();
128 }
129
130 void GeomAPI_ShapeHierarchy::compoundsOfUnusedObjects(
131     ListOfShape& theDestination) const
132 {
133   SetOfShape aUsedObjects = myProcessedObjects;
134   aUsedObjects.insert(myObjects.begin(), myObjects.end());
135
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
144       if (aCompound)
145         theDestination.push_back(aCompound);
146     }
147   }
148 }
149
150 static void addSubShape(GeomShapePtr theTarget, GeomShapePtr theSub)
151 {
152   if (!theTarget.get() || !theSub.get())
153     return;
154
155   TopoDS_Shape* aShape = theTarget->implPtr<TopoDS_Shape>();
156   const TopoDS_Shape& aShapeToAdd = theSub->impl<TopoDS_Shape>();
157
158   static BRep_Builder aBuilder;
159   aBuilder.Add(*aShape, aShapeToAdd);
160 }
161
162 GeomShapePtr GeomAPI_ShapeHierarchy::collectUnusedSubs(
163     GeomShapePtr theTopLevelCompound,
164     const SetOfShape& theUsed) const
165 {
166   GeomShapePtr aResult = theTopLevelCompound->emptyCopied();
167   bool isResultEmpty = true;
168
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
173
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();
182       }
183
184       if (isAddShape) { // low-level shape, add it
185         addSubShape(aResult, aCurrent);
186         isResultEmpty = false;
187       }
188     } else {
189       GeomShapePtr aCompound = collectUnusedSubs(aCurrent, theUsed);
190       if (aCompound) {
191         addSubShape(aResult, aCompound);
192         isResultEmpty = false;
193       }
194     }
195   }
196   return isResultEmpty ? GeomShapePtr() : aResult;
197 }
198
199
200 GeomAPI_ShapeHierarchy::iterator GeomAPI_ShapeHierarchy::begin()
201 {
202   return iterator(this);
203 }
204
205 GeomAPI_ShapeHierarchy::iterator GeomAPI_ShapeHierarchy::end()
206 {
207   return iterator(this, false);
208 }
209
210 GeomAPI_ShapeHierarchy::iterator::iterator(
211     GeomAPI_ShapeHierarchy* theHierarchy, bool isBegin)
212   : myHierarchy(theHierarchy)
213 {
214   if (isBegin) {
215     myObject = myHierarchy->myObjects.begin();
216     skipAlreadyProcessed();
217   } else
218     myObject = myHierarchy->myObjects.end();
219 }
220
221 void GeomAPI_ShapeHierarchy::iterator::skipAlreadyProcessed()
222 {
223   while (myObject != myHierarchy->myObjects.end() &&
224          myHierarchy->myProcessedObjects.find(*myObject) != myHierarchy->myProcessedObjects.end())
225     ++myObject;
226 }
227
228 bool GeomAPI_ShapeHierarchy::iterator::operator==(const iterator& theOther) const
229 {
230   return myObject == theOther.myObject;
231 }
232
233 bool GeomAPI_ShapeHierarchy::iterator::operator!=(const iterator& theOther) const
234 {
235   return !operator==(theOther);
236 }
237
238 GeomAPI_ShapeHierarchy::iterator& GeomAPI_ShapeHierarchy::iterator::operator++()
239 {
240   ++myObject;
241   skipAlreadyProcessed();
242   return *this;
243 }
244
245 GeomAPI_ShapeHierarchy::iterator GeomAPI_ShapeHierarchy::iterator::operator++(int)
246 {
247   iterator aCurrent;
248   aCurrent.myHierarchy = myHierarchy;
249   aCurrent.myObject = myObject;
250
251   // increase iterator
252   operator++();
253
254   return aCurrent;
255 }
256
257 GeomShapePtr GeomAPI_ShapeHierarchy::iterator::operator*() const
258 {
259   myHierarchy->markProcessed(*myObject);
260   return *myObject;
261 }