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