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