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