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