]> SALOME platform Git repositories - modules/shaper.git/blob - src/FeaturesPlugin/FeaturesPlugin_BooleanCut.cpp
Salome HOME
Implementation and part of tests of High Level Objects History task for Common, Cut...
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_BooleanCut.cpp
1 // Copyright (C) 2014-2017  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
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include "FeaturesPlugin_BooleanCut.h"
22
23 #include "FeaturesPlugin_Tools.h"
24
25 #include <ModelAPI_ResultBody.h>
26 #include <ModelAPI_AttributeSelectionList.h>
27 #include <ModelAPI_Tools.h>
28
29 #include <GeomAlgoAPI_Boolean.h>
30 #include <GeomAlgoAPI_CompoundBuilder.h>
31 #include <GeomAlgoAPI_MakeShapeList.h>
32 #include <GeomAlgoAPI_PaveFiller.h>
33 #include <GeomAlgoAPI_ShapeTools.h>
34 #include <GeomAlgoAPI_Tools.h>
35
36 #include <GeomAPI_ShapeExplorer.h>
37 #include <GeomAPI_ShapeIterator.h>
38
39 //==================================================================================================
40 FeaturesPlugin_BooleanCut::FeaturesPlugin_BooleanCut()
41 : FeaturesPlugin_Boolean(FeaturesPlugin_Boolean::BOOL_CUT)
42 {
43 }
44
45 //==================================================================================================
46 void FeaturesPlugin_BooleanCut::execute()
47 {
48   ListOfShape anObjects, aTools;
49   std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape> aCompSolidsObjects;
50   std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape> aCompoundObjects;
51
52   // Getting objects.
53   AttributeSelectionListPtr anObjectsSelList = selectionList(OBJECT_LIST_ID());
54   for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
55     AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex);
56     std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
57     if(!anObject.get()) {
58       return;
59     }
60     ResultPtr aContext = anObjectAttr->context();
61     ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
62     if (aResCompSolidPtr.get())
63     {
64       std::shared_ptr<GeomAPI_Shape> aContextShape = aResCompSolidPtr->shape();
65       GeomAPI_Shape::ShapeType aShapeType = aResCompSolidPtr->shape()->shapeType();
66       std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>& aMap =
67         aShapeType == GeomAPI_Shape::COMPSOLID ? aCompSolidsObjects : aCompoundObjects;
68
69         std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
70           anIt = aMap.begin();
71         for (; anIt != aMap.end(); anIt++) {
72           if (anIt->first->isEqual(aContextShape)) {
73             aMap[anIt->first].push_back(anObject);
74             break;
75           }
76         }
77         if (anIt == aMap.end()) {
78           aMap[aContextShape].push_back(anObject);
79         }
80
81     } else {
82       anObjects.push_back(anObject);
83     }
84   }
85
86   // Getting tools.
87   AttributeSelectionListPtr aToolsSelList = selectionList(TOOL_LIST_ID());
88   for(int aToolsIndex = 0; aToolsIndex < aToolsSelList->size(); aToolsIndex++) {
89     AttributeSelectionPtr aToolAttr = aToolsSelList->value(aToolsIndex);
90     GeomShapePtr aTool = aToolAttr->value();
91     if(!aTool.get()) {
92       return;
93     }
94     aTools.push_back(aTool);
95   }
96
97   int aResultIndex = 0;
98
99   if((anObjects.empty() && aCompSolidsObjects.empty() && aCompoundObjects.empty())
100      || aTools.empty()) {
101     std::string aFeatureError = "Error: Not enough objects for boolean operation.";
102     setError(aFeatureError);
103     return;
104   }
105
106   std::vector<FeaturesPlugin_Tools::ResultBaseAlgo> aResultBaseAlgoList;
107   ListOfShape aResultShapesList;
108   std::string anError;
109
110   // For solids cut each object with all tools.
111   for(ListOfShape::iterator anObjectsIt = anObjects.begin();
112       anObjectsIt != anObjects.end();
113       ++anObjectsIt) {
114     std::shared_ptr<GeomAPI_Shape> anObject = *anObjectsIt;
115     std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList());
116     std::shared_ptr<GeomAlgoAPI_Boolean> aCutAlgo(
117       new GeomAlgoAPI_Boolean(anObject,
118                               aTools,
119                               GeomAlgoAPI_Boolean::BOOL_CUT));
120     GeomShapePtr aResShape = aCutAlgo->shape();
121
122     // Checking that the algorithm worked properly.
123     if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aCutAlgo, getKind(), anError)) {
124       setError(anError);
125       return;
126     }
127
128     aMakeShapeList->appendAlgo(aCutAlgo);
129
130     GeomAPI_ShapeIterator aShapeIt(aResShape);
131     if (aShapeIt.more() || aResShape->shapeType() == GeomAPI_Shape::VERTEX)
132     {
133       std::shared_ptr<ModelAPI_ResultBody> aResultBody =
134         document()->createBody(data(), aResultIndex);
135
136       ListOfShape anObjectList;
137       anObjectList.push_back(anObject);
138       FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
139                                                anObjectList,
140                                                aTools,
141                                                aMakeShapeList,
142                                                aResShape);
143       setResult(aResultBody, aResultIndex);
144       aResultIndex++;
145
146       FeaturesPlugin_Tools::ResultBaseAlgo aRBA;
147       aRBA.resultBody = aResultBody;
148       aRBA.baseShape = anObject;
149       aRBA.makeShape = aMakeShapeList;
150       aResultBaseAlgoList.push_back(aRBA);
151       aResultShapesList.push_back(aResShape);
152     }
153   }
154
155   // Compsolids handling
156   for (std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
157        anIt = aCompSolidsObjects.begin();
158        anIt != aCompSolidsObjects.end();
159        ++anIt)
160   {
161     std::shared_ptr<GeomAPI_Shape> aCompSolid = anIt->first;
162     ListOfShape& aUsedInOperationSolids = anIt->second;
163
164     // Collecting solids from compsolids which will not be modified in boolean operation.
165     ListOfShape aNotUsedSolids;
166     for(GeomAPI_ShapeExplorer anExp(aCompSolid, GeomAPI_Shape::SOLID);
167         anExp.more();
168         anExp.next())
169     {
170       std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
171       ListOfShape::iterator aUsedIt = aUsedInOperationSolids.begin();
172       for (; aUsedIt != aUsedInOperationSolids.end(); aUsedIt++) {
173         if (aSolidInCompSolid->isEqual(*aUsedIt)) {
174           break;
175         }
176       }
177       if (aUsedIt == aUsedInOperationSolids.end()) {
178         aNotUsedSolids.push_back(aSolidInCompSolid);
179       }
180     }
181
182     std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList());
183     std::shared_ptr<GeomAlgoAPI_Boolean> aCutAlgo(
184       new GeomAlgoAPI_Boolean(aUsedInOperationSolids,
185                               aTools,
186                               GeomAlgoAPI_Boolean::BOOL_CUT));
187
188     // Checking that the algorithm worked properly.
189     if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aCutAlgo, getKind(), anError)) {
190       setError(anError);
191       return;
192     }
193
194     aMakeShapeList->appendAlgo(aCutAlgo);
195     GeomShapePtr aResultShape = aCutAlgo->shape();
196
197     // Add result to not used solids from compsolid.
198     if(!aNotUsedSolids.empty()) {
199       ListOfShape aShapesToAdd = aNotUsedSolids;
200       aShapesToAdd.push_back(aCutAlgo->shape());
201       std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(
202         new GeomAlgoAPI_PaveFiller(aShapesToAdd, true));
203       if(!aFillerAlgo->isDone()) {
204         std::string aFeatureError = "Error: PaveFiller algorithm failed.";
205         setError(aFeatureError);
206         return;
207       }
208
209       aMakeShapeList->appendAlgo(aFillerAlgo);
210       aResultShape = aFillerAlgo->shape();
211     }
212
213     GeomAPI_ShapeIterator aShapeIt(aResultShape);
214     if (aShapeIt.more() || aResultShape->shapeType() == GeomAPI_Shape::VERTEX)
215     {
216       std::shared_ptr<ModelAPI_ResultBody> aResultBody =
217         document()->createBody(data(), aResultIndex);
218
219       ListOfShape anObjectList;
220       anObjectList.push_back(aCompSolid);
221       FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
222                                                anObjectList,
223                                                aTools,
224                                                aMakeShapeList,
225                                                aResultShape);
226       setResult(aResultBody, aResultIndex);
227       aResultIndex++;
228
229       FeaturesPlugin_Tools::ResultBaseAlgo aRBA;
230       aRBA.resultBody = aResultBody;
231       aRBA.baseShape = aCompSolid;
232       aRBA.makeShape = aMakeShapeList;
233       aResultBaseAlgoList.push_back(aRBA);
234       aResultShapesList.push_back(aResultShape);
235     }
236   }
237
238   // Compounds handling
239   for (std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
240        anIt = aCompoundObjects.begin();
241        anIt != aCompoundObjects.end();
242        ++anIt)
243   {
244     std::shared_ptr<GeomAPI_Shape> aCompound = anIt->first;
245     ListOfShape& aUsedInOperationShapes = anIt->second;
246
247     // Collecting shapes from compound which will not be modified in boolean operation.
248     ListOfShape aNotUsedShapes;
249     for (GeomAPI_ShapeIterator aCompIt(aCompound);
250          aCompIt.more();
251          aCompIt.next())
252     {
253       std::shared_ptr<GeomAPI_Shape> aShapeInCompound = aCompIt.current();
254       ListOfShape::iterator aUsedIt = aUsedInOperationShapes.begin();
255       for (; aUsedIt != aUsedInOperationShapes.end(); aUsedIt++) {
256         if (aShapeInCompound->isEqual(*aUsedIt)) {
257           break;
258         }
259       }
260       if (aUsedIt == aUsedInOperationShapes.end()) {
261         aNotUsedShapes.push_back(aShapeInCompound);
262       }
263     }
264
265     std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList());
266     std::shared_ptr<GeomAlgoAPI_Boolean> aCutAlgo(
267       new GeomAlgoAPI_Boolean(aUsedInOperationShapes,
268                               aTools,
269                               GeomAlgoAPI_Boolean::BOOL_CUT));
270
271     // Checking that the algorithm worked properly.
272     if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aCutAlgo, getKind(), anError)) {
273       setError(anError);
274       return;
275     }
276
277     aMakeShapeList->appendAlgo(aCutAlgo);
278     GeomShapePtr aResultShape = aCutAlgo->shape();
279
280     // Add result to not used shape from compound.
281     if (!aNotUsedShapes.empty()) {
282       ListOfShape aShapesForResult = aNotUsedShapes;
283       if (aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
284         for (GeomAPI_ShapeIterator aResultIt(aResultShape); aResultIt.more(); aResultIt.next()) {
285           aShapesForResult.push_back(aResultIt.current());
286         }
287       } else {
288         aShapesForResult.push_back(aResultShape);
289       }
290
291       if (aShapesForResult.size() == 1) {
292         aResultShape = aShapesForResult.front();
293       } else {
294         aResultShape = GeomAlgoAPI_CompoundBuilder::compound(aShapesForResult);
295       }
296     }
297
298     GeomAPI_ShapeIterator aShapeIt(aResultShape);
299     if (aShapeIt.more() || aResultShape->shapeType() == GeomAPI_Shape::VERTEX) {
300       std::shared_ptr<ModelAPI_ResultBody> aResultBody =
301         document()->createBody(data(), aResultIndex);
302
303       ListOfShape anObjectList;
304       anObjectList.push_back(aCompound);
305       FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
306                                                anObjectList,
307                                                aTools,
308                                                aMakeShapeList,
309                                                aResultShape);
310       setResult(aResultBody, aResultIndex);
311       aResultIndex++;
312
313       FeaturesPlugin_Tools::ResultBaseAlgo aRBA;
314       aRBA.resultBody = aResultBody;
315       aRBA.baseShape = aCompound;
316       aRBA.makeShape = aMakeShapeList;
317       aResultBaseAlgoList.push_back(aRBA);
318       aResultShapesList.push_back(aResultShape);
319     }
320   }
321
322   // Store deleted shapes after all results has been proceeded. This is to avoid issue when in one
323   // result shape has been deleted, but in another it was modified or stayed.
324   GeomShapePtr aResultShapesCompound = GeomAlgoAPI_CompoundBuilder::compound(aResultShapesList);
325   FeaturesPlugin_Tools::loadDeletedShapes(aResultBaseAlgoList, aTools, aResultShapesCompound);
326
327   // remove the rest results if there were produced in the previous pass
328   removeResults(aResultIndex);
329 }