1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include "FeaturesPlugin_Boolean.h"
23 #include <ModelAPI_Data.h>
24 #include <ModelAPI_Document.h>
25 #include <ModelAPI_AttributeReference.h>
26 #include <ModelAPI_AttributeInteger.h>
27 #include <ModelAPI_ResultCompSolid.h>
28 #include <ModelAPI_ResultBody.h>
29 #include <ModelAPI_AttributeSelectionList.h>
30 #include <ModelAPI_Session.h>
31 #include <ModelAPI_Validator.h>
32 #include <ModelAPI_Tools.h>
34 #include <GeomAlgoAPI_Boolean.h>
35 #include <GeomAlgoAPI_MakeShapeCustom.h>
36 #include <GeomAlgoAPI_MakeShapeList.h>
37 #include <GeomAlgoAPI_Partition.h>
38 #include <GeomAlgoAPI_PaveFiller.h>
39 #include <GeomAlgoAPI_ShapeTools.h>
40 #include <GeomAPI_Face.h>
41 #include <GeomAPI_ShapeExplorer.h>
42 #include <GeomAPI_ShapeIterator.h>
47 //=================================================================================================
48 FeaturesPlugin_Boolean::FeaturesPlugin_Boolean(const OperationType theOperationType)
49 : myOperationType(theOperationType)
53 //=================================================================================================
54 void FeaturesPlugin_Boolean::initAttributes()
56 AttributeSelectionListPtr aSelection =
57 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
58 FeaturesPlugin_Boolean::OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
60 aSelection = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
61 FeaturesPlugin_Boolean::TOOL_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
63 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), OBJECT_LIST_ID());
64 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TOOL_LIST_ID());
67 //=================================================================================================
68 std::shared_ptr<GeomAPI_Shape> FeaturesPlugin_Boolean::getShape(const std::string& theAttrName)
70 std::shared_ptr<ModelAPI_AttributeReference> aObjRef = std::dynamic_pointer_cast<
71 ModelAPI_AttributeReference>(data()->attribute(theAttrName));
73 std::shared_ptr<ModelAPI_ResultBody> aConstr = std::dynamic_pointer_cast<
74 ModelAPI_ResultBody>(aObjRef->value());
76 return aConstr->shape();
78 return std::shared_ptr<GeomAPI_Shape>();
81 //=================================================================================================
82 FeaturesPlugin_Boolean::OperationType FeaturesPlugin_Boolean::operationType()
84 return myOperationType;
87 //=================================================================================================
88 void FeaturesPlugin_Boolean::execute()
90 ListOfShape anObjects, aTools, anEdgesAndFaces, aPlanes;
91 std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape> aCompSolidsObjects;
94 AttributeSelectionListPtr anObjectsSelList =
95 selectionList(FeaturesPlugin_Boolean::OBJECT_LIST_ID());
96 for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
97 AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex);
98 std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
102 ResultPtr aContext = anObjectAttr->context();
103 ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
104 if(aResCompSolidPtr.get()
105 && aResCompSolidPtr->shape()->shapeType() == GeomAPI_Shape::COMPSOLID) {
106 std::shared_ptr<GeomAPI_Shape> aContextShape = aResCompSolidPtr->shape();
107 std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
108 anIt = aCompSolidsObjects.begin();
109 for(; anIt != aCompSolidsObjects.end(); anIt++) {
110 if(anIt->first->isEqual(aContextShape)) {
111 aCompSolidsObjects[anIt->first].push_back(anObject);
115 if(anIt == aCompSolidsObjects.end()) {
116 aCompSolidsObjects[aContextShape].push_back(anObject);
119 if(myOperationType != BOOL_FILL
120 && (anObject->shapeType() == GeomAPI_Shape::EDGE
121 || anObject->shapeType() == GeomAPI_Shape::FACE))
123 anEdgesAndFaces.push_back(anObject);
127 anObjects.push_back(anObject);
133 AttributeSelectionListPtr aToolsSelList = selectionList(FeaturesPlugin_Boolean::TOOL_LIST_ID());
134 for(int aToolsIndex = 0; aToolsIndex < aToolsSelList->size(); aToolsIndex++) {
135 AttributeSelectionPtr aToolAttr = aToolsSelList->value(aToolsIndex);
136 GeomShapePtr aTool = aToolAttr->value();
138 // It could be a construction plane.
139 ResultPtr aContext = aToolAttr->context();
140 aPlanes.push_back(aToolAttr->context()->shape());
142 else if (myOperationType != BOOL_FILL
143 && (aTool->shapeType() == GeomAPI_Shape::EDGE
144 || aTool->shapeType() == GeomAPI_Shape::FACE))
146 anEdgesAndFaces.push_back(aTool);
148 aTools.push_back(aTool);
152 int aResultIndex = 0;
154 switch(myOperationType) {
158 if((anObjects.empty() && aCompSolidsObjects.empty())
159 || (aTools.empty() && aPlanes.empty())) {
160 std::string aFeatureError = "Error: Not enough objects for boolean operation.";
161 setError(aFeatureError);
165 // For solids cut each object with all tools.
166 for(ListOfShape::iterator
167 anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end(); anObjectsIt++) {
168 std::shared_ptr<GeomAPI_Shape> anObject = *anObjectsIt;
169 ListOfShape aListWithObject;
170 aListWithObject.push_back(anObject);
171 GeomAlgoAPI_MakeShapeList aMakeShapeList;
172 std::shared_ptr<GeomAlgoAPI_MakeShape> aBoolAlgo;
173 GeomShapePtr aResShape;
175 switch(myOperationType) {
177 aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aListWithObject,
179 GeomAlgoAPI_Boolean::BOOL_CUT));
180 aResShape = aBoolAlgo->shape();
184 aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aListWithObject,
186 GeomAlgoAPI_Boolean::BOOL_COMMON));
187 aResShape = aBoolAlgo->shape();
191 std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints =
192 GeomAlgoAPI_ShapeTools::getBoundingBox(aListWithObject, 1.0);
195 ListOfShape aToolsWithPlanes = aTools;
196 for(ListOfShape::const_iterator anIt = aPlanes.cbegin();
197 anIt != aPlanes.cend();
200 GeomShapePtr aPlane = *anIt;
201 GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints);
202 std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aMkShCustom(
203 new GeomAlgoAPI_MakeShapeCustom);
204 aMkShCustom->addModified(aPlane, aTool);
205 aMakeShapeList.appendAlgo(aMkShCustom);
206 aToolsWithPlanes.push_back(aTool);
209 aBoolAlgo.reset(new GeomAlgoAPI_Partition(aListWithObject, aToolsWithPlanes));
210 aResShape = aBoolAlgo->shape();
211 if(aResShape->shapeType() == GeomAPI_Shape::COMPOUND) {
212 int aSubResultsNb = 0;
213 GeomAPI_ShapeIterator anIt(aResShape);
214 for(; anIt.more(); anIt.next()) {
217 if(aSubResultsNb == 1) {
218 anIt.init(aResShape);
220 aResShape = anIt.current();
228 // Checking that the algorithm worked properly.
229 if(!aBoolAlgo->isDone()) {
230 static const std::string aFeatureError = "Error: Boolean algorithm failed.";
231 setError(aFeatureError);
234 if(aResShape->isNull()) {
235 static const std::string aShapeError = "Error: Resulting shape is Null.";
236 setError(aShapeError);
239 if(!aBoolAlgo->isValid()) {
240 std::string aFeatureError = "Error: Resulting shape is not valid.";
241 setError(aFeatureError);
245 aMakeShapeList.appendAlgo(aBoolAlgo);
247 if(GeomAlgoAPI_ShapeTools::volume(aResShape) > 1.e-27
248 || (myOperationType != BOOL_CUT && myOperationType != BOOL_COMMON))
250 std::shared_ptr<ModelAPI_ResultBody> aResultBody =
251 document()->createBody(data(), aResultIndex);
253 ListOfShape aUsedTools = aTools;
254 if (myOperationType == BOOL_FILL) {
255 aUsedTools.insert(aUsedTools.end(), aPlanes.begin(), aPlanes.end());
258 loadNamingDS(aResultBody, anObject, aUsedTools, aResShape,
259 aMakeShapeList, *(aBoolAlgo->mapOfSubShapes()),
260 myOperationType == BOOL_FILL);
261 setResult(aResultBody, aResultIndex);
266 // Compsolids handling
267 for(std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
268 anIt = aCompSolidsObjects.begin();
269 anIt != aCompSolidsObjects.end(); anIt++) {
270 std::shared_ptr<GeomAPI_Shape> aCompSolid = anIt->first;
271 ListOfShape& aUsedInOperationSolids = anIt->second;
273 // Collecting solids from compsolids which will not be modified in boolean operation.
274 ListOfShape aNotUsedSolids;
275 for(GeomAPI_ShapeExplorer
276 anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) {
277 std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
278 ListOfShape::iterator anIt = aUsedInOperationSolids.begin();
279 for(; anIt != aUsedInOperationSolids.end(); anIt++) {
280 if(aSolidInCompSolid->isEqual(*anIt)) {
284 if(anIt == aUsedInOperationSolids.end()) {
285 aNotUsedSolids.push_back(aSolidInCompSolid);
289 GeomAlgoAPI_MakeShapeList aMakeShapeList;
290 std::shared_ptr<GeomAlgoAPI_MakeShape> aBoolAlgo;
292 switch(myOperationType) {
294 aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aUsedInOperationSolids,
296 GeomAlgoAPI_Boolean::BOOL_CUT));
300 aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aUsedInOperationSolids,
302 GeomAlgoAPI_Boolean::BOOL_COMMON));
306 std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints =
307 GeomAlgoAPI_ShapeTools::getBoundingBox(aUsedInOperationSolids, 1.0);
310 ListOfShape aToolsWithPlanes = aTools;
311 for(ListOfShape::const_iterator anIt = aPlanes.cbegin();
312 anIt != aPlanes.cend();
315 GeomShapePtr aPlane = *anIt;
316 GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints);
317 std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aMkShCustom(
318 new GeomAlgoAPI_MakeShapeCustom);
319 aMkShCustom->addModified(aPlane, aTool);
320 aMakeShapeList.appendAlgo(aMkShCustom);
321 aToolsWithPlanes.push_back(aTool);
324 aBoolAlgo.reset(new GeomAlgoAPI_Partition(aUsedInOperationSolids, aToolsWithPlanes));
329 // Checking that the algorithm worked properly.
330 if(!aBoolAlgo->isDone()) {
331 static const std::string aFeatureError = "Error: Boolean algorithm failed.";
332 setError(aFeatureError);
335 if(aBoolAlgo->shape()->isNull()) {
336 static const std::string aShapeError = "Error: Resulting shape is Null.";
337 setError(aShapeError);
340 if(!aBoolAlgo->isValid()) {
341 std::string aFeatureError = "Error: Resulting shape is not valid.";
342 setError(aFeatureError);
346 aMakeShapeList.appendAlgo(aBoolAlgo);
347 GeomAPI_DataMapOfShapeShape aMapOfShapes;
348 aMapOfShapes.merge(aBoolAlgo->mapOfSubShapes());
349 GeomShapePtr aResultShape = aBoolAlgo->shape();
351 // Add result to not used solids from compsolid.
352 if(!aNotUsedSolids.empty()) {
353 ListOfShape aShapesToAdd = aNotUsedSolids;
354 aShapesToAdd.push_back(aBoolAlgo->shape());
355 std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(
356 new GeomAlgoAPI_PaveFiller(aShapesToAdd, true));
357 if(!aFillerAlgo->isDone()) {
358 std::string aFeatureError = "Error: PaveFiller algorithm failed.";
359 setError(aFeatureError);
363 aMakeShapeList.appendAlgo(aFillerAlgo);
364 aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
365 aResultShape = aFillerAlgo->shape();
368 if(GeomAlgoAPI_ShapeTools::volume(aResultShape) > 1.e-27
369 || (myOperationType != BOOL_CUT && myOperationType != BOOL_COMMON))
371 std::shared_ptr<ModelAPI_ResultBody> aResultBody =
372 document()->createBody(data(), aResultIndex);
374 ListOfShape aUsedTools = aTools;
375 if (myOperationType == BOOL_FILL) {
376 aUsedTools.insert(aUsedTools.end(), aPlanes.begin(), aPlanes.end());
379 loadNamingDS(aResultBody,
385 myOperationType == BOOL_FILL);
386 setResult(aResultBody, aResultIndex);
393 if((anObjects.size() + aTools.size() +
394 aCompSolidsObjects.size() + anEdgesAndFaces.size()) < 2) {
395 std::string aFeatureError = "Error: Not enough objects for boolean operation.";
396 setError(aFeatureError);
400 // Collecting all solids which will be fused.
401 ListOfShape aSolidsToFuse;
402 aSolidsToFuse.insert(aSolidsToFuse.end(), anObjects.begin(), anObjects.end());
403 aSolidsToFuse.insert(aSolidsToFuse.end(), aTools.begin(), aTools.end());
405 // Collecting solids from compsolids which will not be modified
406 // in boolean operation and will be added to result.
407 ListOfShape aShapesToAdd;
408 for(std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
409 anIt = aCompSolidsObjects.begin();
410 anIt != aCompSolidsObjects.end(); anIt++) {
411 std::shared_ptr<GeomAPI_Shape> aCompSolid = anIt->first;
412 ListOfShape& aUsedInOperationSolids = anIt->second;
413 aSolidsToFuse.insert(aSolidsToFuse.end(), aUsedInOperationSolids.begin(),
414 aUsedInOperationSolids.end());
416 // Collect solids from compsolid which will not be modified in boolean operation.
417 for(GeomAPI_ShapeExplorer
418 anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) {
419 std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
420 ListOfShape::iterator anIt = aUsedInOperationSolids.begin();
421 for(; anIt != aUsedInOperationSolids.end(); anIt++) {
422 if(aSolidInCompSolid->isEqual(*anIt)) {
426 if(anIt == aUsedInOperationSolids.end()) {
427 aShapesToAdd.push_back(aSolidInCompSolid);
432 ListOfShape anOriginalShapes = aSolidsToFuse;
433 anOriginalShapes.insert(anOriginalShapes.end(), aShapesToAdd.begin(), aShapesToAdd.end());
435 // Cut edges and faces(if we have any) with solids.
436 GeomAlgoAPI_MakeShapeList aMakeShapeList;
437 GeomAPI_DataMapOfShapeShape aMapOfShapes;
438 std::shared_ptr<GeomAPI_Shape> aCuttedEdgesAndFaces;
439 if(!anEdgesAndFaces.empty()) {
440 std::shared_ptr<GeomAlgoAPI_Boolean> aCutAlgo(new GeomAlgoAPI_Boolean(anEdgesAndFaces,
441 anOriginalShapes, GeomAlgoAPI_Boolean::BOOL_CUT));
442 if(aCutAlgo->isDone()) {
443 aCuttedEdgesAndFaces = aCutAlgo->shape();
444 aMakeShapeList.appendAlgo(aCutAlgo);
445 aMapOfShapes.merge(aCutAlgo->mapOfSubShapes());
448 anOriginalShapes.insert(anOriginalShapes.end(), anEdgesAndFaces.begin(),
449 anEdgesAndFaces.end());
451 // If we have compsolids then cut with not used solids all others.
452 if(!aShapesToAdd.empty()) {
453 aSolidsToFuse.clear();
454 for(ListOfShape::iterator
455 anIt = anOriginalShapes.begin(); anIt != anOriginalShapes.end(); anIt++) {
456 ListOfShape aOneObjectList;
457 aOneObjectList.push_back(*anIt);
458 std::shared_ptr<GeomAlgoAPI_Boolean> aCutAlgo(
459 new GeomAlgoAPI_Boolean(aOneObjectList, aShapesToAdd, GeomAlgoAPI_Boolean::BOOL_CUT));
461 if(GeomAlgoAPI_ShapeTools::volume(aCutAlgo->shape()) > 1.e-27) {
462 aSolidsToFuse.push_back(aCutAlgo->shape());
463 aMakeShapeList.appendAlgo(aCutAlgo);
464 aMapOfShapes.merge(aCutAlgo->mapOfSubShapes());
469 if(!aSolidsToFuse.empty()) {
471 anObjects.push_back(aSolidsToFuse.back());
472 aSolidsToFuse.pop_back();
473 aTools = aSolidsToFuse;
476 // Fuse all objects and all tools.
477 std::shared_ptr<GeomAPI_Shape> aShape;
478 if(anObjects.size() == 1 && aTools.empty()) {
479 aShape = anObjects.front();
480 } else if(anObjects.empty() && aTools.size() == 1) {
481 aShape = aTools.front();
482 } else if((anObjects.size() + aTools.size()) > 1){
483 std::shared_ptr<GeomAlgoAPI_Boolean> aFuseAlgo(new GeomAlgoAPI_Boolean(anObjects,
485 GeomAlgoAPI_Boolean::BOOL_FUSE));
487 // Checking that the algorithm worked properly.
488 if(!aFuseAlgo->isDone()) {
489 static const std::string aFeatureError = "Error: Boolean algorithm failed.";
490 setError(aFeatureError);
493 if(aFuseAlgo->shape()->isNull()) {
494 static const std::string aShapeError = "Error: Resulting shape is Null.";
495 setError(aShapeError);
498 if(!aFuseAlgo->isValid()) {
499 std::string aFeatureError = "Error: Resulting shape is not valid.";
500 setError(aFeatureError);
504 aShape = aFuseAlgo->shape();
505 aMakeShapeList.appendAlgo(aFuseAlgo);
506 aMapOfShapes.merge(aFuseAlgo->mapOfSubShapes());
509 // Combine result with not used solids from compsolid and edges and faces (if we have any).
510 if(aCuttedEdgesAndFaces.get() && !aCuttedEdgesAndFaces->isNull()) {
511 aShapesToAdd.push_back(aCuttedEdgesAndFaces);
513 aShapesToAdd.insert(aShapesToAdd.end(), anEdgesAndFaces.begin(), anEdgesAndFaces.end());
515 if(!aShapesToAdd.empty()) {
517 aShapesToAdd.push_back(aShape);
519 std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(
520 new GeomAlgoAPI_PaveFiller(aShapesToAdd, true));
521 if(!aFillerAlgo->isDone()) {
522 std::string aFeatureError = "Error: PaveFiller algorithm failed.";
523 setError(aFeatureError);
526 if(aFillerAlgo->shape()->isNull()) {
527 static const std::string aShapeError = "Error: Resulting shape is Null.";
528 setError(aShapeError);
531 if(!aFillerAlgo->isValid()) {
532 std::string aFeatureError = "Error: Resulting shape is not valid.";
533 setError(aFeatureError);
537 aShape = aFillerAlgo->shape();
538 aMakeShapeList.appendAlgo(aFillerAlgo);
539 aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
542 std::shared_ptr<GeomAPI_Shape> aBackShape = anOriginalShapes.back();
543 anOriginalShapes.pop_back();
544 std::shared_ptr<ModelAPI_ResultBody> aResultBody =
545 document()->createBody(data(), aResultIndex);
546 loadNamingDS(aResultBody, aBackShape, anOriginalShapes,
547 aShape, aMakeShapeList, aMapOfShapes);
548 setResult(aResultBody, aResultIndex);
553 if((anObjects.empty() && aCompSolidsObjects.empty()) || aTools.empty()) {
554 std::string aFeatureError = "Error: Not enough objects for boolean operation.";
555 setError(aFeatureError);
559 // List of original solids for naming.
560 ListOfShape anOriginalShapes;
561 anOriginalShapes.insert(anOriginalShapes.end(), anObjects.begin(), anObjects.end());
562 anOriginalShapes.insert(anOriginalShapes.end(), aTools.begin(), aTools.end());
564 // Collecting all solids which will be smashed.
565 ListOfShape aShapesToSmash;
566 aShapesToSmash.insert(aShapesToSmash.end(), anObjects.begin(), anObjects.end());
568 // Collecting solids from compsolids which will not be modified in
569 // boolean operation and will be added to result.
570 ListOfShape aShapesToAdd;
571 for(std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
572 anIt = aCompSolidsObjects.begin();
573 anIt != aCompSolidsObjects.end(); anIt++) {
574 std::shared_ptr<GeomAPI_Shape> aCompSolid = anIt->first;
575 ListOfShape& aUsedInOperationSolids = anIt->second;
576 anOriginalShapes.push_back(aCompSolid);
577 aShapesToSmash.insert(aShapesToSmash.end(), aUsedInOperationSolids.begin(),
578 aUsedInOperationSolids.end());
580 // Collect solids from compsolid which will not be modified in boolean operation.
581 for(GeomAPI_ShapeExplorer
582 anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) {
583 std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
584 ListOfShape::iterator anIt = aUsedInOperationSolids.begin();
585 for(; anIt != aUsedInOperationSolids.end(); anIt++) {
586 if(aSolidInCompSolid->isEqual(*anIt)) {
590 if(anIt == aUsedInOperationSolids.end()) {
591 aShapesToAdd.push_back(aSolidInCompSolid);
596 GeomAlgoAPI_MakeShapeList aMakeShapeList;
597 GeomAPI_DataMapOfShapeShape aMapOfShapes;
598 if(!aShapesToAdd.empty()) {
599 // Cut objects with not used solids.
600 std::shared_ptr<GeomAlgoAPI_Boolean> anObjectsCutAlgo(new GeomAlgoAPI_Boolean(
603 GeomAlgoAPI_Boolean::BOOL_CUT));
605 if(GeomAlgoAPI_ShapeTools::volume(anObjectsCutAlgo->shape()) > 1.e-27) {
606 aShapesToSmash.clear();
607 aShapesToSmash.push_back(anObjectsCutAlgo->shape());
608 aMakeShapeList.appendAlgo(anObjectsCutAlgo);
609 aMapOfShapes.merge(anObjectsCutAlgo->mapOfSubShapes());
612 // Cut tools with not used solids.
613 std::shared_ptr<GeomAlgoAPI_Boolean> aToolsCutAlgo(new GeomAlgoAPI_Boolean(aTools,
615 GeomAlgoAPI_Boolean::BOOL_CUT));
617 if(GeomAlgoAPI_ShapeTools::volume(aToolsCutAlgo->shape()) > 1.e-27) {
619 aTools.push_back(aToolsCutAlgo->shape());
620 aMakeShapeList.appendAlgo(aToolsCutAlgo);
621 aMapOfShapes.merge(aToolsCutAlgo->mapOfSubShapes());
625 // Cut objects with tools.
626 std::shared_ptr<GeomAlgoAPI_Boolean> aBoolAlgo(new GeomAlgoAPI_Boolean(aShapesToSmash,
628 GeomAlgoAPI_Boolean::BOOL_CUT));
630 // Checking that the algorithm worked properly.
631 if(!aBoolAlgo->isDone()) {
632 static const std::string aFeatureError = "Error: Boolean algorithm failed.";
633 setError(aFeatureError);
636 if(aBoolAlgo->shape()->isNull()) {
637 static const std::string aShapeError = "Error: Resulting shape is Null.";
638 setError(aShapeError);
641 if(!aBoolAlgo->isValid()) {
642 std::string aFeatureError = "Error: Resulting shape is not valid.";
643 setError(aFeatureError);
646 aMakeShapeList.appendAlgo(aBoolAlgo);
647 aMapOfShapes.merge(aBoolAlgo->mapOfSubShapes());
649 // Put all (cut result, tools and not used solids) to PaveFiller.
650 aShapesToAdd.push_back(aBoolAlgo->shape());
651 aShapesToAdd.insert(aShapesToAdd.end(), aTools.begin(), aTools.end());
653 std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(new GeomAlgoAPI_PaveFiller(aShapesToAdd,
655 if(!aFillerAlgo->isDone()) {
656 std::string aFeatureError = "Error: PaveFiller algorithm failed.";
657 setError(aFeatureError);
660 if(aFillerAlgo->shape()->isNull()) {
661 static const std::string aShapeError = "Error: Resulting shape is Null.";
662 setError(aShapeError);
665 if(!aFillerAlgo->isValid()) {
666 std::string aFeatureError = "Error: Resulting shape is not valid.";
667 setError(aFeatureError);
671 std::shared_ptr<GeomAPI_Shape> aShape = aFillerAlgo->shape();
672 aMakeShapeList.appendAlgo(aFillerAlgo);
673 aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
675 std::shared_ptr<GeomAPI_Shape> aFrontShape = anOriginalShapes.front();
676 anOriginalShapes.pop_front();
677 std::shared_ptr<ModelAPI_ResultBody> aResultBody =
678 document()->createBody(data(), aResultIndex);
679 loadNamingDS(aResultBody, aFrontShape, anOriginalShapes,
680 aShape, aMakeShapeList, aMapOfShapes);
681 setResult(aResultBody, aResultIndex);
687 std::string anOperationError = "Error: Wrong type of operation";
688 setError(anOperationError);
692 // remove the rest results if there were produced in the previous pass
693 removeResults(aResultIndex);
696 //=================================================================================================
697 void FeaturesPlugin_Boolean::loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> theResultBody,
698 const std::shared_ptr<GeomAPI_Shape> theBaseShape,
699 const ListOfShape& theTools,
700 const std::shared_ptr<GeomAPI_Shape> theResultShape,
701 GeomAlgoAPI_MakeShape& theMakeShape,
702 GeomAPI_DataMapOfShapeShape& theMapOfShapes,
703 const bool theIsStoreAsGenerated)
706 if(theBaseShape->isEqual(theResultShape)) {
707 theResultBody->store(theResultShape, false);
709 const int aModifyTag = 1;
710 const int aModifyEdgeTag = 2;
711 const int aModifyFaceTag = 3;
712 const int aDeletedTag = 4;
713 /// sub solids will be placed at labels 5, 6, etc. if result is compound of solids
714 const int aSubsolidsTag = 5;
716 theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag);
718 const std::string aModName = "Modified";
719 const std::string aModEName = "Modified_Edge";
720 const std::string aModFName = "Modified_Face";
722 theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::EDGE,
723 aModifyEdgeTag, aModEName, theMapOfShapes, false, theIsStoreAsGenerated, true);
724 theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE,
725 aModifyFaceTag, aModFName, theMapOfShapes, false, theIsStoreAsGenerated, true);
726 theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape,
727 GeomAPI_Shape::FACE, aDeletedTag);
731 for(ListOfShape::const_iterator
732 anIter = theTools.begin(); anIter != theTools.end(); anIter++) {
733 if((*anIter)->shapeType() <= GeomAPI_Shape::FACE) {
734 aTag = aModifyFaceTag;
737 aTag = aModifyEdgeTag;
740 theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter,
741 aName == aModEName ? GeomAPI_Shape::EDGE : GeomAPI_Shape::FACE,
742 aTag, aName, theMapOfShapes, false, theIsStoreAsGenerated, true);
743 theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, aDeletedTag);