]> SALOME platform Git repositories - modules/shaper.git/blob - src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp
Salome HOME
3.6 Separation of Boolean operations
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Boolean.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_Boolean.h"
22
23 #include <ModelAPI_Data.h>
24 #include <ModelAPI_Document.h>
25 #include <ModelAPI_AttributeReference.h>
26 #include <ModelAPI_AttributeInteger.h>
27 #include <ModelAPI_ResultCompSolid.h>
28 #include <ModelAPI_ResultBody.h>
29 #include <ModelAPI_AttributeSelectionList.h>
30 #include <ModelAPI_Session.h>
31 #include <ModelAPI_Validator.h>
32 #include <ModelAPI_Tools.h>
33
34 #include <GeomAlgoAPI_Boolean.h>
35 #include <GeomAlgoAPI_MakeShapeCustom.h>
36 #include <GeomAlgoAPI_MakeShapeList.h>
37 #include <GeomAlgoAPI_Partition.h>
38 #include <GeomAlgoAPI_PaveFiller.h>
39 #include <GeomAlgoAPI_ShapeTools.h>
40 #include <GeomAPI_Face.h>
41 #include <GeomAPI_ShapeExplorer.h>
42 #include <GeomAPI_ShapeIterator.h>
43
44 #include <algorithm>
45 #include <map>
46
47 //=================================================================================================
48 FeaturesPlugin_Boolean::FeaturesPlugin_Boolean(const OperationType theOperationType)
49 : myOperationType(theOperationType)
50 {
51 }
52
53 //=================================================================================================
54 void FeaturesPlugin_Boolean::initAttributes()
55 {
56   AttributeSelectionListPtr aSelection =
57     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
58     FeaturesPlugin_Boolean::OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
59
60   aSelection = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
61     FeaturesPlugin_Boolean::TOOL_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
62
63   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), OBJECT_LIST_ID());
64   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TOOL_LIST_ID());
65 }
66
67 //=================================================================================================
68 std::shared_ptr<GeomAPI_Shape> FeaturesPlugin_Boolean::getShape(const std::string& theAttrName)
69 {
70   std::shared_ptr<ModelAPI_AttributeReference> aObjRef = std::dynamic_pointer_cast<
71       ModelAPI_AttributeReference>(data()->attribute(theAttrName));
72   if (aObjRef) {
73     std::shared_ptr<ModelAPI_ResultBody> aConstr = std::dynamic_pointer_cast<
74         ModelAPI_ResultBody>(aObjRef->value());
75     if (aConstr)
76       return aConstr->shape();
77   }
78   return std::shared_ptr<GeomAPI_Shape>();
79 }
80
81 //=================================================================================================
82 FeaturesPlugin_Boolean::OperationType FeaturesPlugin_Boolean::operationType()
83 {
84   return myOperationType;
85 }
86
87 //=================================================================================================
88 void FeaturesPlugin_Boolean::execute()
89 {
90   ListOfShape anObjects, aTools, anEdgesAndFaces, aPlanes;
91   std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape> aCompSolidsObjects;
92
93   // Getting objects.
94   AttributeSelectionListPtr anObjectsSelList =
95     selectionList(FeaturesPlugin_Boolean::OBJECT_LIST_ID());
96   for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
97     AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex);
98     std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
99     if(!anObject.get()) {
100       return;
101     }
102     ResultPtr aContext = anObjectAttr->context();
103     ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
104     if(aResCompSolidPtr.get()
105         && aResCompSolidPtr->shape()->shapeType() == GeomAPI_Shape::COMPSOLID) {
106       std::shared_ptr<GeomAPI_Shape> aContextShape = aResCompSolidPtr->shape();
107       std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
108         anIt = aCompSolidsObjects.begin();
109       for(; anIt != aCompSolidsObjects.end(); anIt++) {
110         if(anIt->first->isEqual(aContextShape)) {
111           aCompSolidsObjects[anIt->first].push_back(anObject);
112           break;
113         }
114       }
115       if(anIt == aCompSolidsObjects.end()) {
116         aCompSolidsObjects[aContextShape].push_back(anObject);
117       }
118     } else {
119       if(myOperationType != BOOL_FILL
120         && (anObject->shapeType() == GeomAPI_Shape::EDGE
121           || anObject->shapeType() == GeomAPI_Shape::FACE))
122       {
123         anEdgesAndFaces.push_back(anObject);
124       }
125       else
126       {
127         anObjects.push_back(anObject);
128       }
129     }
130   }
131
132   // Getting tools.
133   AttributeSelectionListPtr aToolsSelList = selectionList(FeaturesPlugin_Boolean::TOOL_LIST_ID());
134   for(int aToolsIndex = 0; aToolsIndex < aToolsSelList->size(); aToolsIndex++) {
135     AttributeSelectionPtr aToolAttr = aToolsSelList->value(aToolsIndex);
136     GeomShapePtr aTool = aToolAttr->value();
137     if(!aTool.get()) {
138       // It could be a construction plane.
139       ResultPtr aContext = aToolAttr->context();
140       aPlanes.push_back(aToolAttr->context()->shape());
141     }
142     else if (myOperationType != BOOL_FILL
143       && (aTool->shapeType() == GeomAPI_Shape::EDGE
144         || aTool->shapeType() == GeomAPI_Shape::FACE))
145     {
146       anEdgesAndFaces.push_back(aTool);
147     } else {
148       aTools.push_back(aTool);
149     }
150   }
151
152   int aResultIndex = 0;
153
154   switch(myOperationType) {
155     case BOOL_CUT:
156     case BOOL_COMMON:
157     case BOOL_FILL: {
158       if((anObjects.empty() && aCompSolidsObjects.empty())
159           || (aTools.empty() && aPlanes.empty())) {
160         std::string aFeatureError = "Error: Not enough objects for boolean operation.";
161         setError(aFeatureError);
162         return;
163       }
164
165       // For solids cut each object with all tools.
166       for(ListOfShape::iterator
167           anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end(); anObjectsIt++) {
168         std::shared_ptr<GeomAPI_Shape> anObject = *anObjectsIt;
169         ListOfShape aListWithObject;
170         aListWithObject.push_back(anObject);
171         GeomAlgoAPI_MakeShapeList aMakeShapeList;
172         std::shared_ptr<GeomAlgoAPI_MakeShape> aBoolAlgo;
173         GeomShapePtr aResShape;
174
175         switch(myOperationType) {
176           case BOOL_CUT: {
177             aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aListWithObject,
178                                                     aTools,
179                                                     GeomAlgoAPI_Boolean::BOOL_CUT));
180             aResShape = aBoolAlgo->shape();
181             break;
182           }
183           case BOOL_COMMON: {
184             aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aListWithObject,
185                                                     aTools,
186                                                     GeomAlgoAPI_Boolean::BOOL_COMMON));
187             aResShape = aBoolAlgo->shape();
188             break;
189           }
190           case BOOL_FILL: {
191               std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints =
192                 GeomAlgoAPI_ShapeTools::getBoundingBox(aListWithObject, 1.0);
193
194             // Resize planes.
195             ListOfShape aToolsWithPlanes = aTools;
196             for(ListOfShape::const_iterator anIt = aPlanes.cbegin();
197                                             anIt != aPlanes.cend();
198                                             ++anIt)
199             {
200               GeomShapePtr aPlane = *anIt;
201               GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints);
202               std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aMkShCustom(
203                 new GeomAlgoAPI_MakeShapeCustom);
204               aMkShCustom->addModified(aPlane, aTool);
205               aMakeShapeList.appendAlgo(aMkShCustom);
206               aToolsWithPlanes.push_back(aTool);
207             }
208
209             aBoolAlgo.reset(new GeomAlgoAPI_Partition(aListWithObject, aToolsWithPlanes));
210             aResShape = aBoolAlgo->shape();
211             if(aResShape->shapeType() == GeomAPI_Shape::COMPOUND) {
212               int aSubResultsNb = 0;
213               GeomAPI_ShapeIterator anIt(aResShape);
214               for(; anIt.more(); anIt.next()) {
215                 ++aSubResultsNb;
216               }
217               if(aSubResultsNb == 1) {
218                 anIt.init(aResShape);
219                 if(anIt.more()) {
220                   aResShape = anIt.current();
221                 }
222               }
223             }
224             break;
225           }
226         }
227
228         // Checking that the algorithm worked properly.
229         if(!aBoolAlgo->isDone()) {
230           static const std::string aFeatureError = "Error: Boolean algorithm failed.";
231           setError(aFeatureError);
232           return;
233         }
234         if(aResShape->isNull()) {
235           static const std::string aShapeError = "Error: Resulting shape is Null.";
236           setError(aShapeError);
237           return;
238         }
239         if(!aBoolAlgo->isValid()) {
240           std::string aFeatureError = "Error: Resulting shape is not valid.";
241           setError(aFeatureError);
242           return;
243         }
244
245         aMakeShapeList.appendAlgo(aBoolAlgo);
246
247         if(GeomAlgoAPI_ShapeTools::volume(aResShape) > 1.e-27
248            || (myOperationType != BOOL_CUT && myOperationType != BOOL_COMMON))
249         {
250           std::shared_ptr<ModelAPI_ResultBody> aResultBody =
251             document()->createBody(data(), aResultIndex);
252
253           ListOfShape aUsedTools = aTools;
254           if (myOperationType == BOOL_FILL) {
255             aUsedTools.insert(aUsedTools.end(), aPlanes.begin(), aPlanes.end());
256           }
257
258           loadNamingDS(aResultBody, anObject, aUsedTools, aResShape,
259                        aMakeShapeList, *(aBoolAlgo->mapOfSubShapes()),
260                        myOperationType == BOOL_FILL);
261           setResult(aResultBody, aResultIndex);
262           aResultIndex++;
263         }
264       }
265
266       // Compsolids handling
267       for(std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
268           anIt = aCompSolidsObjects.begin();
269           anIt != aCompSolidsObjects.end(); anIt++) {
270         std::shared_ptr<GeomAPI_Shape> aCompSolid = anIt->first;
271         ListOfShape& aUsedInOperationSolids = anIt->second;
272
273         // Collecting solids from compsolids which will not be modified in boolean operation.
274         ListOfShape aNotUsedSolids;
275         for(GeomAPI_ShapeExplorer
276             anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) {
277           std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
278           ListOfShape::iterator anIt = aUsedInOperationSolids.begin();
279           for(; anIt != aUsedInOperationSolids.end(); anIt++) {
280             if(aSolidInCompSolid->isEqual(*anIt)) {
281               break;
282             }
283           }
284           if(anIt == aUsedInOperationSolids.end()) {
285             aNotUsedSolids.push_back(aSolidInCompSolid);
286           }
287         }
288
289         GeomAlgoAPI_MakeShapeList aMakeShapeList;
290         std::shared_ptr<GeomAlgoAPI_MakeShape> aBoolAlgo;
291
292         switch(myOperationType) {
293           case BOOL_CUT: {
294             aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aUsedInOperationSolids,
295                                                     aTools,
296                                                     GeomAlgoAPI_Boolean::BOOL_CUT));
297             break;
298           }
299           case BOOL_COMMON: {
300             aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aUsedInOperationSolids,
301                                                     aTools,
302                                                     GeomAlgoAPI_Boolean::BOOL_COMMON));
303             break;
304           }
305           case BOOL_FILL: {
306             std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints =
307               GeomAlgoAPI_ShapeTools::getBoundingBox(aUsedInOperationSolids, 1.0);
308
309             // Resize planes.
310             ListOfShape aToolsWithPlanes = aTools;
311             for(ListOfShape::const_iterator anIt = aPlanes.cbegin();
312                                             anIt != aPlanes.cend();
313                                             ++anIt)
314             {
315               GeomShapePtr aPlane = *anIt;
316               GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints);
317               std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aMkShCustom(
318                 new GeomAlgoAPI_MakeShapeCustom);
319               aMkShCustom->addModified(aPlane, aTool);
320               aMakeShapeList.appendAlgo(aMkShCustom);
321               aToolsWithPlanes.push_back(aTool);
322             }
323
324             aBoolAlgo.reset(new GeomAlgoAPI_Partition(aUsedInOperationSolids, aToolsWithPlanes));
325             break;
326           }
327         }
328
329         // Checking that the algorithm worked properly.
330         if(!aBoolAlgo->isDone()) {
331           static const std::string aFeatureError = "Error: Boolean algorithm failed.";
332           setError(aFeatureError);
333           return;
334         }
335         if(aBoolAlgo->shape()->isNull()) {
336           static const std::string aShapeError = "Error: Resulting shape is Null.";
337           setError(aShapeError);
338           return;
339         }
340         if(!aBoolAlgo->isValid()) {
341           std::string aFeatureError = "Error: Resulting shape is not valid.";
342           setError(aFeatureError);
343           return;
344         }
345
346         aMakeShapeList.appendAlgo(aBoolAlgo);
347         GeomAPI_DataMapOfShapeShape aMapOfShapes;
348         aMapOfShapes.merge(aBoolAlgo->mapOfSubShapes());
349         GeomShapePtr aResultShape = aBoolAlgo->shape();
350
351         // Add result to not used solids from compsolid.
352         if(!aNotUsedSolids.empty()) {
353           ListOfShape aShapesToAdd = aNotUsedSolids;
354           aShapesToAdd.push_back(aBoolAlgo->shape());
355           std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(
356             new GeomAlgoAPI_PaveFiller(aShapesToAdd, true));
357           if(!aFillerAlgo->isDone()) {
358             std::string aFeatureError = "Error: PaveFiller algorithm failed.";
359             setError(aFeatureError);
360             return;
361           }
362
363           aMakeShapeList.appendAlgo(aFillerAlgo);
364           aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
365           aResultShape = aFillerAlgo->shape();
366         }
367
368         if(GeomAlgoAPI_ShapeTools::volume(aResultShape) > 1.e-27
369            || (myOperationType != BOOL_CUT && myOperationType != BOOL_COMMON))
370         {
371           std::shared_ptr<ModelAPI_ResultBody> aResultBody =
372             document()->createBody(data(), aResultIndex);
373
374           ListOfShape aUsedTools = aTools;
375           if (myOperationType == BOOL_FILL) {
376             aUsedTools.insert(aUsedTools.end(), aPlanes.begin(), aPlanes.end());
377           }
378
379           loadNamingDS(aResultBody,
380                        aCompSolid,
381                        aUsedTools,
382                        aResultShape,
383                        aMakeShapeList,
384                        aMapOfShapes,
385                        myOperationType == BOOL_FILL);
386           setResult(aResultBody, aResultIndex);
387           aResultIndex++;
388         }
389       }
390       break;
391     }
392     case BOOL_FUSE: {
393       if((anObjects.size() + aTools.size() +
394           aCompSolidsObjects.size() + anEdgesAndFaces.size()) < 2) {
395         std::string aFeatureError = "Error: Not enough objects for boolean operation.";
396         setError(aFeatureError);
397         return;
398       }
399
400       // Collecting all solids which will be fused.
401       ListOfShape aSolidsToFuse;
402       aSolidsToFuse.insert(aSolidsToFuse.end(), anObjects.begin(), anObjects.end());
403       aSolidsToFuse.insert(aSolidsToFuse.end(), aTools.begin(), aTools.end());
404
405       // Collecting solids from compsolids which will not be modified
406       // in boolean operation and will be added to result.
407       ListOfShape aShapesToAdd;
408       for(std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
409           anIt = aCompSolidsObjects.begin();
410           anIt != aCompSolidsObjects.end(); anIt++) {
411         std::shared_ptr<GeomAPI_Shape> aCompSolid = anIt->first;
412         ListOfShape& aUsedInOperationSolids = anIt->second;
413         aSolidsToFuse.insert(aSolidsToFuse.end(), aUsedInOperationSolids.begin(),
414                              aUsedInOperationSolids.end());
415
416         // Collect solids from compsolid which will not be modified in boolean operation.
417         for(GeomAPI_ShapeExplorer
418             anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) {
419           std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
420           ListOfShape::iterator anIt = aUsedInOperationSolids.begin();
421           for(; anIt != aUsedInOperationSolids.end(); anIt++) {
422             if(aSolidInCompSolid->isEqual(*anIt)) {
423               break;
424             }
425           }
426           if(anIt == aUsedInOperationSolids.end()) {
427             aShapesToAdd.push_back(aSolidInCompSolid);
428           }
429         }
430       }
431
432       ListOfShape anOriginalShapes = aSolidsToFuse;
433       anOriginalShapes.insert(anOriginalShapes.end(), aShapesToAdd.begin(), aShapesToAdd.end());
434
435       // Cut edges and faces(if we have any) with solids.
436       GeomAlgoAPI_MakeShapeList aMakeShapeList;
437       GeomAPI_DataMapOfShapeShape aMapOfShapes;
438       std::shared_ptr<GeomAPI_Shape> aCuttedEdgesAndFaces;
439       if(!anEdgesAndFaces.empty()) {
440         std::shared_ptr<GeomAlgoAPI_Boolean> aCutAlgo(new GeomAlgoAPI_Boolean(anEdgesAndFaces,
441                                             anOriginalShapes, GeomAlgoAPI_Boolean::BOOL_CUT));
442         if(aCutAlgo->isDone()) {
443           aCuttedEdgesAndFaces = aCutAlgo->shape();
444           aMakeShapeList.appendAlgo(aCutAlgo);
445           aMapOfShapes.merge(aCutAlgo->mapOfSubShapes());
446         }
447       }
448       anOriginalShapes.insert(anOriginalShapes.end(), anEdgesAndFaces.begin(),
449                               anEdgesAndFaces.end());
450
451       // If we have compsolids then cut with not used solids all others.
452       if(!aShapesToAdd.empty()) {
453         aSolidsToFuse.clear();
454         for(ListOfShape::iterator
455             anIt = anOriginalShapes.begin(); anIt != anOriginalShapes.end(); anIt++) {
456           ListOfShape aOneObjectList;
457           aOneObjectList.push_back(*anIt);
458           std::shared_ptr<GeomAlgoAPI_Boolean> aCutAlgo(
459             new GeomAlgoAPI_Boolean(aOneObjectList, aShapesToAdd, GeomAlgoAPI_Boolean::BOOL_CUT));
460
461           if(GeomAlgoAPI_ShapeTools::volume(aCutAlgo->shape()) > 1.e-27) {
462             aSolidsToFuse.push_back(aCutAlgo->shape());
463             aMakeShapeList.appendAlgo(aCutAlgo);
464             aMapOfShapes.merge(aCutAlgo->mapOfSubShapes());
465           }
466         }
467       }
468
469       if(!aSolidsToFuse.empty()) {
470         anObjects.clear();
471         anObjects.push_back(aSolidsToFuse.back());
472         aSolidsToFuse.pop_back();
473         aTools = aSolidsToFuse;
474       }
475
476       // Fuse all objects and all tools.
477       std::shared_ptr<GeomAPI_Shape> aShape;
478       if(anObjects.size() == 1 && aTools.empty()) {
479         aShape = anObjects.front();
480       } else if(anObjects.empty() && aTools.size() == 1) {
481         aShape = aTools.front();
482       } else if((anObjects.size() + aTools.size()) > 1){
483         std::shared_ptr<GeomAlgoAPI_Boolean> aFuseAlgo(new GeomAlgoAPI_Boolean(anObjects,
484                                                                 aTools,
485                                                                 GeomAlgoAPI_Boolean::BOOL_FUSE));
486
487         // Checking that the algorithm worked properly.
488         if(!aFuseAlgo->isDone()) {
489           static const std::string aFeatureError = "Error: Boolean algorithm failed.";
490           setError(aFeatureError);
491           return;
492         }
493         if(aFuseAlgo->shape()->isNull()) {
494           static const std::string aShapeError = "Error: Resulting shape is Null.";
495           setError(aShapeError);
496           return;
497         }
498         if(!aFuseAlgo->isValid()) {
499           std::string aFeatureError = "Error: Resulting shape is not valid.";
500           setError(aFeatureError);
501           return;
502         }
503
504         aShape = aFuseAlgo->shape();
505         aMakeShapeList.appendAlgo(aFuseAlgo);
506         aMapOfShapes.merge(aFuseAlgo->mapOfSubShapes());
507       }
508
509       // Combine result with not used solids from compsolid and edges and faces (if we have any).
510       if(aCuttedEdgesAndFaces.get() && !aCuttedEdgesAndFaces->isNull()) {
511         aShapesToAdd.push_back(aCuttedEdgesAndFaces);
512       } else {
513         aShapesToAdd.insert(aShapesToAdd.end(), anEdgesAndFaces.begin(), anEdgesAndFaces.end());
514       }
515       if(!aShapesToAdd.empty()) {
516         if(aShape.get()) {
517           aShapesToAdd.push_back(aShape);
518         }
519         std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(
520           new GeomAlgoAPI_PaveFiller(aShapesToAdd, true));
521         if(!aFillerAlgo->isDone()) {
522           std::string aFeatureError = "Error: PaveFiller algorithm failed.";
523           setError(aFeatureError);
524           return;
525         }
526         if(aFillerAlgo->shape()->isNull()) {
527           static const std::string aShapeError = "Error: Resulting shape is Null.";
528           setError(aShapeError);
529           return;
530         }
531         if(!aFillerAlgo->isValid()) {
532           std::string aFeatureError = "Error: Resulting shape is not valid.";
533           setError(aFeatureError);
534           return;
535         }
536
537         aShape = aFillerAlgo->shape();
538         aMakeShapeList.appendAlgo(aFillerAlgo);
539         aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
540       }
541
542       std::shared_ptr<GeomAPI_Shape> aBackShape = anOriginalShapes.back();
543       anOriginalShapes.pop_back();
544       std::shared_ptr<ModelAPI_ResultBody> aResultBody =
545         document()->createBody(data(), aResultIndex);
546       loadNamingDS(aResultBody, aBackShape, anOriginalShapes,
547                    aShape, aMakeShapeList, aMapOfShapes);
548       setResult(aResultBody, aResultIndex);
549       aResultIndex++;
550       break;
551     }
552     case BOOL_SMASH: {
553       if((anObjects.empty() && aCompSolidsObjects.empty()) || aTools.empty()) {
554         std::string aFeatureError = "Error: Not enough objects for boolean operation.";
555         setError(aFeatureError);
556         return;
557       }
558
559       // List of original solids for naming.
560       ListOfShape anOriginalShapes;
561       anOriginalShapes.insert(anOriginalShapes.end(), anObjects.begin(), anObjects.end());
562       anOriginalShapes.insert(anOriginalShapes.end(), aTools.begin(), aTools.end());
563
564       // Collecting all solids which will be smashed.
565       ListOfShape aShapesToSmash;
566       aShapesToSmash.insert(aShapesToSmash.end(), anObjects.begin(), anObjects.end());
567
568       // Collecting solids from compsolids which will not be modified in
569       // boolean operation and will be added to result.
570       ListOfShape aShapesToAdd;
571       for(std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
572         anIt = aCompSolidsObjects.begin();
573         anIt != aCompSolidsObjects.end(); anIt++) {
574         std::shared_ptr<GeomAPI_Shape> aCompSolid = anIt->first;
575         ListOfShape& aUsedInOperationSolids = anIt->second;
576         anOriginalShapes.push_back(aCompSolid);
577         aShapesToSmash.insert(aShapesToSmash.end(), aUsedInOperationSolids.begin(),
578                               aUsedInOperationSolids.end());
579
580         // Collect solids from compsolid which will not be modified in boolean operation.
581         for(GeomAPI_ShapeExplorer
582             anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) {
583           std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
584           ListOfShape::iterator anIt = aUsedInOperationSolids.begin();
585           for(; anIt != aUsedInOperationSolids.end(); anIt++) {
586             if(aSolidInCompSolid->isEqual(*anIt)) {
587               break;
588             }
589           }
590           if(anIt == aUsedInOperationSolids.end()) {
591             aShapesToAdd.push_back(aSolidInCompSolid);
592           }
593         }
594       }
595
596       GeomAlgoAPI_MakeShapeList aMakeShapeList;
597       GeomAPI_DataMapOfShapeShape aMapOfShapes;
598       if(!aShapesToAdd.empty()) {
599         // Cut objects with not used solids.
600         std::shared_ptr<GeomAlgoAPI_Boolean> anObjectsCutAlgo(new GeomAlgoAPI_Boolean(
601                                                               aShapesToSmash,
602                                                               aShapesToAdd,
603                                                               GeomAlgoAPI_Boolean::BOOL_CUT));
604
605         if(GeomAlgoAPI_ShapeTools::volume(anObjectsCutAlgo->shape()) > 1.e-27) {
606           aShapesToSmash.clear();
607           aShapesToSmash.push_back(anObjectsCutAlgo->shape());
608           aMakeShapeList.appendAlgo(anObjectsCutAlgo);
609           aMapOfShapes.merge(anObjectsCutAlgo->mapOfSubShapes());
610         }
611
612         // Cut tools with not used solids.
613         std::shared_ptr<GeomAlgoAPI_Boolean> aToolsCutAlgo(new GeomAlgoAPI_Boolean(aTools,
614                                                               aShapesToAdd,
615                                                               GeomAlgoAPI_Boolean::BOOL_CUT));
616
617         if(GeomAlgoAPI_ShapeTools::volume(aToolsCutAlgo->shape()) > 1.e-27) {
618           aTools.clear();
619           aTools.push_back(aToolsCutAlgo->shape());
620           aMakeShapeList.appendAlgo(aToolsCutAlgo);
621           aMapOfShapes.merge(aToolsCutAlgo->mapOfSubShapes());
622         }
623       }
624
625       // Cut objects with tools.
626       std::shared_ptr<GeomAlgoAPI_Boolean> aBoolAlgo(new GeomAlgoAPI_Boolean(aShapesToSmash,
627                                                                 aTools,
628                                                                 GeomAlgoAPI_Boolean::BOOL_CUT));
629
630       // Checking that the algorithm worked properly.
631       if(!aBoolAlgo->isDone()) {
632         static const std::string aFeatureError = "Error: Boolean algorithm failed.";
633         setError(aFeatureError);
634         return;
635       }
636       if(aBoolAlgo->shape()->isNull()) {
637         static const std::string aShapeError = "Error: Resulting shape is Null.";
638         setError(aShapeError);
639         return;
640       }
641       if(!aBoolAlgo->isValid()) {
642         std::string aFeatureError = "Error: Resulting shape is not valid.";
643         setError(aFeatureError);
644         return;
645       }
646       aMakeShapeList.appendAlgo(aBoolAlgo);
647       aMapOfShapes.merge(aBoolAlgo->mapOfSubShapes());
648
649       // Put all (cut result, tools and not used solids) to PaveFiller.
650       aShapesToAdd.push_back(aBoolAlgo->shape());
651       aShapesToAdd.insert(aShapesToAdd.end(), aTools.begin(), aTools.end());
652
653       std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(new GeomAlgoAPI_PaveFiller(aShapesToAdd,
654                                                                                      true));
655       if(!aFillerAlgo->isDone()) {
656         std::string aFeatureError = "Error: PaveFiller algorithm failed.";
657         setError(aFeatureError);
658         return;
659       }
660       if(aFillerAlgo->shape()->isNull()) {
661         static const std::string aShapeError = "Error: Resulting shape is Null.";
662         setError(aShapeError);
663         return;
664       }
665       if(!aFillerAlgo->isValid()) {
666         std::string aFeatureError = "Error: Resulting shape is not valid.";
667         setError(aFeatureError);
668         return;
669       }
670
671       std::shared_ptr<GeomAPI_Shape> aShape = aFillerAlgo->shape();
672       aMakeShapeList.appendAlgo(aFillerAlgo);
673       aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
674
675       std::shared_ptr<GeomAPI_Shape> aFrontShape = anOriginalShapes.front();
676       anOriginalShapes.pop_front();
677       std::shared_ptr<ModelAPI_ResultBody> aResultBody =
678         document()->createBody(data(), aResultIndex);
679       loadNamingDS(aResultBody, aFrontShape, anOriginalShapes,
680         aShape, aMakeShapeList, aMapOfShapes);
681       setResult(aResultBody, aResultIndex);
682       aResultIndex++;
683
684       break;
685     }
686     default: {
687       std::string anOperationError = "Error: Wrong type of operation";
688       setError(anOperationError);
689       return;
690     }
691   }
692   // remove the rest results if there were produced in the previous pass
693   removeResults(aResultIndex);
694 }
695
696 //=================================================================================================
697 void FeaturesPlugin_Boolean::loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> theResultBody,
698                                           const std::shared_ptr<GeomAPI_Shape> theBaseShape,
699                                           const ListOfShape& theTools,
700                                           const std::shared_ptr<GeomAPI_Shape> theResultShape,
701                                           GeomAlgoAPI_MakeShape& theMakeShape,
702                                           GeomAPI_DataMapOfShapeShape& theMapOfShapes,
703                                           const bool theIsStoreAsGenerated)
704 {
705   //load result
706   if(theBaseShape->isEqual(theResultShape)) {
707     theResultBody->store(theResultShape, false);
708   } else {
709     const int aModifyTag = 1;
710     const int aModifyEdgeTag = 2;
711     const int aModifyFaceTag = 3;
712     const int aDeletedTag = 4;
713     /// sub solids will be placed at labels 5, 6, etc. if result is compound of solids
714     const int aSubsolidsTag = 5;
715
716     theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag);
717
718     const std::string aModName = "Modified";
719     const std::string aModEName = "Modified_Edge";
720     const std::string aModFName = "Modified_Face";
721
722     theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::EDGE,
723       aModifyEdgeTag, aModEName, theMapOfShapes, false, theIsStoreAsGenerated, true);
724     theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE,
725       aModifyFaceTag, aModFName, theMapOfShapes, false, theIsStoreAsGenerated, true);
726     theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape,
727                                      GeomAPI_Shape::FACE, aDeletedTag);
728
729     int aTag;
730     std::string aName;
731     for(ListOfShape::const_iterator
732         anIter = theTools.begin(); anIter != theTools.end(); anIter++) {
733       if((*anIter)->shapeType() <= GeomAPI_Shape::FACE) {
734         aTag = aModifyFaceTag;
735         aName = aModFName;
736       } else {
737         aTag = aModifyEdgeTag;
738         aName = aModEName;
739       }
740       theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter,
741         aName == aModEName ? GeomAPI_Shape::EDGE : GeomAPI_Shape::FACE,
742         aTag, aName, theMapOfShapes, false, theIsStoreAsGenerated, true);
743       theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, aDeletedTag);
744     }
745   }
746 }