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