Salome HOME
Issue #1916: Fatal error when create sketch on body Remove subshapes
[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
275         // Add result to not used solids from compsolid.
276         ListOfShape aShapesToAdd = aNotUsedSolids;
277         aShapesToAdd.push_back(aBoolAlgo->shape());
278         std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(
279           new GeomAlgoAPI_PaveFiller(aShapesToAdd, true));
280         if(!aFillerAlgo->isDone()) {
281           std::string aFeatureError = "Error: PaveFiller algorithm failed.";
282           setError(aFeatureError);
283           return;
284         }
285
286         aMakeShapeList.appendAlgo(aFillerAlgo);
287         aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
288
289         if(GeomAlgoAPI_ShapeTools::volume(aFillerAlgo->shape()) > 1.e-27) {
290           std::shared_ptr<ModelAPI_ResultBody> aResultBody =
291             document()->createBody(data(), aResultIndex);
292           loadNamingDS(aResultBody, aCompSolid, aTools,
293                        aFillerAlgo->shape(), aMakeShapeList, aMapOfShapes);
294           setResult(aResultBody, aResultIndex);
295           aResultIndex++;
296         }
297       }
298       break;
299     }
300     case BOOL_FUSE: {
301       if((anObjects.size() + aTools.size() +
302           aCompSolidsObjects.size() + anEdgesAndFaces.size()) < 2) {
303         std::string aFeatureError = "Error: Not enough objects for boolean operation.";
304         setError(aFeatureError);
305         return;
306       }
307
308       // Collecting all solids which will be fused.
309       ListOfShape aSolidsToFuse;
310       aSolidsToFuse.insert(aSolidsToFuse.end(), anObjects.begin(), anObjects.end());
311       aSolidsToFuse.insert(aSolidsToFuse.end(), aTools.begin(), aTools.end());
312
313       // Collecting solids from compsolids which will not be modified
314       // in boolean operation and will be added to result.
315       ListOfShape aShapesToAdd;
316       for(std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
317           anIt = aCompSolidsObjects.begin();
318           anIt != aCompSolidsObjects.end(); anIt++) {
319         std::shared_ptr<GeomAPI_Shape> aCompSolid = anIt->first;
320         ListOfShape& aUsedInOperationSolids = anIt->second;
321         aSolidsToFuse.insert(aSolidsToFuse.end(), aUsedInOperationSolids.begin(),
322                              aUsedInOperationSolids.end());
323
324         // Collect solids from compsolid which will not be modified in boolean operation.
325         for(GeomAPI_ShapeExplorer
326             anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) {
327           std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
328           ListOfShape::iterator anIt = aUsedInOperationSolids.begin();
329           for(; anIt != aUsedInOperationSolids.end(); anIt++) {
330             if(aSolidInCompSolid->isEqual(*anIt)) {
331               break;
332             }
333           }
334           if(anIt == aUsedInOperationSolids.end()) {
335             aShapesToAdd.push_back(aSolidInCompSolid);
336           }
337         }
338       }
339
340       ListOfShape anOriginalShapes = aSolidsToFuse;
341       anOriginalShapes.insert(anOriginalShapes.end(), aShapesToAdd.begin(), aShapesToAdd.end());
342
343       // Cut edges and faces(if we have any) with solids.
344       GeomAlgoAPI_MakeShapeList aMakeShapeList;
345       GeomAPI_DataMapOfShapeShape aMapOfShapes;
346       std::shared_ptr<GeomAPI_Shape> aCuttedEdgesAndFaces;
347       if(!anEdgesAndFaces.empty()) {
348         std::shared_ptr<GeomAlgoAPI_Boolean> aCutAlgo(new GeomAlgoAPI_Boolean(anEdgesAndFaces,
349                                             anOriginalShapes, GeomAlgoAPI_Boolean::BOOL_CUT));
350         if(aCutAlgo->isDone()) {
351           aCuttedEdgesAndFaces = aCutAlgo->shape();
352           aMakeShapeList.appendAlgo(aCutAlgo);
353           aMapOfShapes.merge(aCutAlgo->mapOfSubShapes());
354         }
355       }
356       anOriginalShapes.insert(anOriginalShapes.end(), anEdgesAndFaces.begin(),
357                               anEdgesAndFaces.end());
358
359       // If we have compsolids then cut with not used solids all others.
360       if(!aShapesToAdd.empty()) {
361         aSolidsToFuse.clear();
362         for(ListOfShape::iterator
363             anIt = anOriginalShapes.begin(); anIt != anOriginalShapes.end(); anIt++) {
364           ListOfShape aOneObjectList;
365           aOneObjectList.push_back(*anIt);
366           std::shared_ptr<GeomAlgoAPI_Boolean> aCutAlgo(
367             new GeomAlgoAPI_Boolean(aOneObjectList, aShapesToAdd, GeomAlgoAPI_Boolean::BOOL_CUT));
368
369           if(GeomAlgoAPI_ShapeTools::volume(aCutAlgo->shape()) > 1.e-27) {
370             aSolidsToFuse.push_back(aCutAlgo->shape());
371             aMakeShapeList.appendAlgo(aCutAlgo);
372             aMapOfShapes.merge(aCutAlgo->mapOfSubShapes());
373           }
374         }
375       }
376
377       if(!aSolidsToFuse.empty()) {
378         anObjects.clear();
379         anObjects.push_back(aSolidsToFuse.back());
380         aSolidsToFuse.pop_back();
381         aTools = aSolidsToFuse;
382       }
383
384       // Fuse all objects and all tools.
385       std::shared_ptr<GeomAPI_Shape> aShape;
386       if(anObjects.size() == 1 && aTools.empty()) {
387         aShape = anObjects.front();
388       } else if(anObjects.empty() && aTools.size() == 1) {
389         aShape = aTools.front();
390       } else if((anObjects.size() + aTools.size()) > 1){
391         std::shared_ptr<GeomAlgoAPI_Boolean> aFuseAlgo(new GeomAlgoAPI_Boolean(anObjects,
392                                                                 aTools,
393                                                                 GeomAlgoAPI_Boolean::BOOL_FUSE));
394
395         // Checking that the algorithm worked properly.
396         if(!aFuseAlgo->isDone()) {
397           static const std::string aFeatureError = "Error: Boolean algorithm failed.";
398           setError(aFeatureError);
399           return;
400         }
401         if(aFuseAlgo->shape()->isNull()) {
402           static const std::string aShapeError = "Error: Resulting shape is Null.";
403           setError(aShapeError);
404           return;
405         }
406         if(!aFuseAlgo->isValid()) {
407           std::string aFeatureError = "Error: Resulting shape is not valid.";
408           setError(aFeatureError);
409           return;
410         }
411
412         aShape = aFuseAlgo->shape();
413         aMakeShapeList.appendAlgo(aFuseAlgo);
414         aMapOfShapes.merge(aFuseAlgo->mapOfSubShapes());
415       }
416
417       // Combine result with not used solids from compsolid and edges and faces (if we have any).
418       if(aCuttedEdgesAndFaces.get() && !aCuttedEdgesAndFaces->isNull()) {
419         aShapesToAdd.push_back(aCuttedEdgesAndFaces);
420       } else {
421         aShapesToAdd.insert(aShapesToAdd.end(), anEdgesAndFaces.begin(), anEdgesAndFaces.end());
422       }
423       if(!aShapesToAdd.empty()) {
424         if(aShape.get()) {
425           aShapesToAdd.push_back(aShape);
426         }
427         std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(
428           new GeomAlgoAPI_PaveFiller(aShapesToAdd, true));
429         if(!aFillerAlgo->isDone()) {
430           std::string aFeatureError = "Error: PaveFiller algorithm failed.";
431           setError(aFeatureError);
432           return;
433         }
434         if(aFillerAlgo->shape()->isNull()) {
435           static const std::string aShapeError = "Error: Resulting shape is Null.";
436           setError(aShapeError);
437           return;
438         }
439         if(!aFillerAlgo->isValid()) {
440           std::string aFeatureError = "Error: Resulting shape is not valid.";
441           setError(aFeatureError);
442           return;
443         }
444
445         aShape = aFillerAlgo->shape();
446         aMakeShapeList.appendAlgo(aFillerAlgo);
447         aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
448       }
449
450       std::shared_ptr<GeomAPI_Shape> aBackShape = anOriginalShapes.back();
451       anOriginalShapes.pop_back();
452       std::shared_ptr<ModelAPI_ResultBody> aResultBody =
453         document()->createBody(data(), aResultIndex);
454       loadNamingDS(aResultBody, aBackShape, anOriginalShapes,
455                    aShape, aMakeShapeList, aMapOfShapes);
456       setResult(aResultBody, aResultIndex);
457       aResultIndex++;
458       break;
459     }
460     case BOOL_SMASH: {
461       if((anObjects.empty() && aCompSolidsObjects.empty()) || aTools.empty()) {
462         std::string aFeatureError = "Error: Not enough objects for boolean operation.";
463         setError(aFeatureError);
464         return;
465       }
466
467       // List of original solids for naming.
468       ListOfShape anOriginalShapes;
469       anOriginalShapes.insert(anOriginalShapes.end(), anObjects.begin(), anObjects.end());
470       anOriginalShapes.insert(anOriginalShapes.end(), aTools.begin(), aTools.end());
471
472       // Collecting all solids which will be smashed.
473       ListOfShape aShapesToSmash;
474       aShapesToSmash.insert(aShapesToSmash.end(), anObjects.begin(), anObjects.end());
475
476       // Collecting solids from compsolids which will not be modified in
477       // boolean operation and will be added to result.
478       ListOfShape aShapesToAdd;
479       for(std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
480         anIt = aCompSolidsObjects.begin();
481         anIt != aCompSolidsObjects.end(); anIt++) {
482         std::shared_ptr<GeomAPI_Shape> aCompSolid = anIt->first;
483         ListOfShape& aUsedInOperationSolids = anIt->second;
484         anOriginalShapes.push_back(aCompSolid);
485         aShapesToSmash.insert(aShapesToSmash.end(), aUsedInOperationSolids.begin(),
486                               aUsedInOperationSolids.end());
487
488         // Collect solids from compsolid which will not be modified in boolean operation.
489         for(GeomAPI_ShapeExplorer
490             anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) {
491           std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
492           ListOfShape::iterator anIt = aUsedInOperationSolids.begin();
493           for(; anIt != aUsedInOperationSolids.end(); anIt++) {
494             if(aSolidInCompSolid->isEqual(*anIt)) {
495               break;
496             }
497           }
498           if(anIt == aUsedInOperationSolids.end()) {
499             aShapesToAdd.push_back(aSolidInCompSolid);
500           }
501         }
502       }
503
504       GeomAlgoAPI_MakeShapeList aMakeShapeList;
505       GeomAPI_DataMapOfShapeShape aMapOfShapes;
506       if(!aShapesToAdd.empty()) {
507         // Cut objects with not used solids.
508         std::shared_ptr<GeomAlgoAPI_Boolean> anObjectsCutAlgo(new GeomAlgoAPI_Boolean(
509                                                               aShapesToSmash,
510                                                               aShapesToAdd,
511                                                               GeomAlgoAPI_Boolean::BOOL_CUT));
512
513         if(GeomAlgoAPI_ShapeTools::volume(anObjectsCutAlgo->shape()) > 1.e-27) {
514           aShapesToSmash.clear();
515           aShapesToSmash.push_back(anObjectsCutAlgo->shape());
516           aMakeShapeList.appendAlgo(anObjectsCutAlgo);
517           aMapOfShapes.merge(anObjectsCutAlgo->mapOfSubShapes());
518         }
519
520         // Cut tools with not used solids.
521         std::shared_ptr<GeomAlgoAPI_Boolean> aToolsCutAlgo(new GeomAlgoAPI_Boolean(aTools,
522                                                               aShapesToAdd,
523                                                               GeomAlgoAPI_Boolean::BOOL_CUT));
524
525         if(GeomAlgoAPI_ShapeTools::volume(aToolsCutAlgo->shape()) > 1.e-27) {
526           aTools.clear();
527           aTools.push_back(aToolsCutAlgo->shape());
528           aMakeShapeList.appendAlgo(aToolsCutAlgo);
529           aMapOfShapes.merge(aToolsCutAlgo->mapOfSubShapes());
530         }
531       }
532
533       // Cut objects with tools.
534       std::shared_ptr<GeomAlgoAPI_Boolean> aBoolAlgo(new GeomAlgoAPI_Boolean(aShapesToSmash,
535                                                                 aTools,
536                                                                 GeomAlgoAPI_Boolean::BOOL_CUT));
537
538       // Checking that the algorithm worked properly.
539       if(!aBoolAlgo->isDone()) {
540         static const std::string aFeatureError = "Error: Boolean algorithm failed.";
541         setError(aFeatureError);
542         return;
543       }
544       if(aBoolAlgo->shape()->isNull()) {
545         static const std::string aShapeError = "Error: Resulting shape is Null.";
546         setError(aShapeError);
547         return;
548       }
549       if(!aBoolAlgo->isValid()) {
550         std::string aFeatureError = "Error: Resulting shape is not valid.";
551         setError(aFeatureError);
552         return;
553       }
554       aMakeShapeList.appendAlgo(aBoolAlgo);
555       aMapOfShapes.merge(aBoolAlgo->mapOfSubShapes());
556
557       // Put all (cut result, tools and not used solids) to PaveFiller.
558       aShapesToAdd.push_back(aBoolAlgo->shape());
559       aShapesToAdd.insert(aShapesToAdd.end(), aTools.begin(), aTools.end());
560
561       std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(new GeomAlgoAPI_PaveFiller(aShapesToAdd,
562                                                                                      true));
563       if(!aFillerAlgo->isDone()) {
564         std::string aFeatureError = "Error: PaveFiller algorithm failed.";
565         setError(aFeatureError);
566         return;
567       }
568       if(aFillerAlgo->shape()->isNull()) {
569         static const std::string aShapeError = "Error: Resulting shape is Null.";
570         setError(aShapeError);
571         return;
572       }
573       if(!aFillerAlgo->isValid()) {
574         std::string aFeatureError = "Error: Resulting shape is not valid.";
575         setError(aFeatureError);
576         return;
577       }
578
579       std::shared_ptr<GeomAPI_Shape> aShape = aFillerAlgo->shape();
580       aMakeShapeList.appendAlgo(aFillerAlgo);
581       aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
582
583       std::shared_ptr<GeomAPI_Shape> aFrontShape = anOriginalShapes.front();
584       anOriginalShapes.pop_front();
585       std::shared_ptr<ModelAPI_ResultBody> aResultBody =
586         document()->createBody(data(), aResultIndex);
587       loadNamingDS(aResultBody, aFrontShape, anOriginalShapes,
588         aShape, aMakeShapeList, aMapOfShapes);
589       setResult(aResultBody, aResultIndex);
590       aResultIndex++;
591
592       break;
593     }
594     default: {
595       std::string anOperationError = "Error: Wrong type of operation";
596       setError(anOperationError);
597       return;
598     }
599   }
600   // remove the rest results if there were produced in the previous pass
601   removeResults(aResultIndex);
602 }
603
604 //=================================================================================================
605 void FeaturesPlugin_Boolean::loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> theResultBody,
606                                           const std::shared_ptr<GeomAPI_Shape> theBaseShape,
607                                           const ListOfShape& theTools,
608                                           const std::shared_ptr<GeomAPI_Shape> theResultShape,
609                                           GeomAlgoAPI_MakeShape& theMakeShape,
610                                           GeomAPI_DataMapOfShapeShape& theMapOfShapes)
611 {
612   //load result
613   if(theBaseShape->isEqual(theResultShape)) {
614     theResultBody->store(theResultShape);
615   } else {
616     const int aModifyTag = 1;
617     const int aDeletedTag = 2;
618     /// sub solids will be placed at labels 3, 4, etc. if result is compound of solids
619     const int aSubsolidsTag = 3;
620     const int anEdgesAndFacesTag = 10000;
621
622     theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag);
623
624     const std::string aModName = "Modified";
625     const std::string aModEName = "Modified_Edge";
626     const std::string aModFName = "Modified_Face";
627
628     theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE,
629                                                aModifyTag, aModName, theMapOfShapes);
630     theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape,
631                                      GeomAPI_Shape::FACE, aDeletedTag);
632
633     int aTag;
634     std::string aName;
635     for(ListOfShape::const_iterator
636         anIter = theTools.begin(); anIter != theTools.end(); anIter++) {
637       if((*anIter)->shapeType() == GeomAPI_Shape::EDGE) {
638         aTag = anEdgesAndFacesTag;
639         aName = aModEName;
640       }
641       else if((*anIter)->shapeType() == GeomAPI_Shape::FACE) {
642         aTag = anEdgesAndFacesTag;
643         aName = aModFName;
644       } else {
645         aTag = aModifyTag;
646         aName = aModName;
647       }
648       theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter,
649         aName == aModEName ? GeomAPI_Shape::EDGE : GeomAPI_Shape::FACE,
650         aTag, aName, theMapOfShapes);
651       theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, aDeletedTag);
652     }
653   }
654 }