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