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