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