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()
52 //=================================================================================================
53 void FeaturesPlugin_Boolean::initAttributes()
55 data()->addAttribute(FeaturesPlugin_Boolean::TYPE_ID(), ModelAPI_AttributeInteger::typeId());
57 AttributeSelectionListPtr aSelection =
58 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
59 FeaturesPlugin_Boolean::OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
61 aSelection = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
62 FeaturesPlugin_Boolean::TOOL_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
64 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), OBJECT_LIST_ID());
65 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TOOL_LIST_ID());
68 //=================================================================================================
69 std::shared_ptr<GeomAPI_Shape> FeaturesPlugin_Boolean::getShape(const std::string& theAttrName)
71 std::shared_ptr<ModelAPI_AttributeReference> aObjRef = std::dynamic_pointer_cast<
72 ModelAPI_AttributeReference>(data()->attribute(theAttrName));
74 std::shared_ptr<ModelAPI_ResultBody> aConstr = std::dynamic_pointer_cast<
75 ModelAPI_ResultBody>(aObjRef->value());
77 return aConstr->shape();
79 return std::shared_ptr<GeomAPI_Shape>();
82 //=================================================================================================
83 void FeaturesPlugin_Boolean::execute()
85 // Getting operation type.
86 std::shared_ptr<ModelAPI_AttributeInteger> aTypeAttr = std::dynamic_pointer_cast<
87 ModelAPI_AttributeInteger>(data()->attribute(FeaturesPlugin_Boolean::TYPE_ID()));
90 OperationType aType = (FeaturesPlugin_Boolean::OperationType)aTypeAttr->value();
92 ListOfShape anObjects, aTools, anEdgesAndFaces, aPlanes;
93 std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape> aCompSolidsObjects;
96 AttributeSelectionListPtr anObjectsSelList =
97 selectionList(FeaturesPlugin_Boolean::OBJECT_LIST_ID());
98 for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
99 AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex);
100 std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
101 if(!anObject.get()) {
104 ResultPtr aContext = anObjectAttr->context();
105 ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
106 if(aResCompSolidPtr.get()
107 && aResCompSolidPtr->shape()->shapeType() == GeomAPI_Shape::COMPSOLID) {
108 std::shared_ptr<GeomAPI_Shape> aContextShape = aResCompSolidPtr->shape();
109 std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
110 anIt = aCompSolidsObjects.begin();
111 for(; anIt != aCompSolidsObjects.end(); anIt++) {
112 if(anIt->first->isEqual(aContextShape)) {
113 aCompSolidsObjects[anIt->first].push_back(anObject);
117 if(anIt == aCompSolidsObjects.end()) {
118 aCompSolidsObjects[aContextShape].push_back(anObject);
121 if(aType != BOOL_FILL
122 && (anObject->shapeType() == GeomAPI_Shape::EDGE
123 || anObject->shapeType() == GeomAPI_Shape::FACE))
125 anEdgesAndFaces.push_back(anObject);
129 anObjects.push_back(anObject);
135 AttributeSelectionListPtr aToolsSelList = selectionList(FeaturesPlugin_Boolean::TOOL_LIST_ID());
136 for(int aToolsIndex = 0; aToolsIndex < aToolsSelList->size(); aToolsIndex++) {
137 AttributeSelectionPtr aToolAttr = aToolsSelList->value(aToolsIndex);
138 GeomShapePtr aTool = aToolAttr->value();
140 // It could be a construction plane.
141 ResultPtr aContext = aToolAttr->context();
142 aPlanes.push_back(aToolAttr->context()->shape());
144 else if(aType != BOOL_FILL
145 && (aTool->shapeType() == GeomAPI_Shape::EDGE
146 || aTool->shapeType() == GeomAPI_Shape::FACE))
148 anEdgesAndFaces.push_back(aTool);
150 aTools.push_back(aTool);
154 int aResultIndex = 0;
160 if((anObjects.empty() && aCompSolidsObjects.empty())
161 || (aTools.empty() && aPlanes.empty())) {
162 std::string aFeatureError = "Error: Not enough objects for boolean operation.";
163 setError(aFeatureError);
167 // For solids cut each object with all tools.
168 for(ListOfShape::iterator
169 anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end(); anObjectsIt++) {
170 std::shared_ptr<GeomAPI_Shape> anObject = *anObjectsIt;
171 ListOfShape aListWithObject;
172 aListWithObject.push_back(anObject);
173 GeomAlgoAPI_MakeShapeList aMakeShapeList;
174 std::shared_ptr<GeomAlgoAPI_MakeShape> aBoolAlgo;
175 GeomShapePtr aResShape;
179 aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aListWithObject,
181 GeomAlgoAPI_Boolean::BOOL_CUT));
182 aResShape = aBoolAlgo->shape();
186 aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aListWithObject,
188 GeomAlgoAPI_Boolean::BOOL_COMMON));
189 aResShape = aBoolAlgo->shape();
193 std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints =
194 GeomAlgoAPI_ShapeTools::getBoundingBox(aListWithObject, 1.0);
197 ListOfShape aToolsWithPlanes = aTools;
198 for(ListOfShape::const_iterator anIt = aPlanes.cbegin();
199 anIt != aPlanes.cend();
202 GeomShapePtr aPlane = *anIt;
203 GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints);
204 std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aMkShCustom(
205 new GeomAlgoAPI_MakeShapeCustom);
206 aMkShCustom->addModified(aPlane, aTool);
207 aMakeShapeList.appendAlgo(aMkShCustom);
208 aToolsWithPlanes.push_back(aTool);
211 aBoolAlgo.reset(new GeomAlgoAPI_Partition(aListWithObject, aToolsWithPlanes));
212 aResShape = aBoolAlgo->shape();
213 if(aResShape->shapeType() == GeomAPI_Shape::COMPOUND) {
214 int aSubResultsNb = 0;
215 GeomAPI_ShapeIterator anIt(aResShape);
216 for(; anIt.more(); anIt.next()) {
219 if(aSubResultsNb == 1) {
220 anIt.init(aResShape);
222 aResShape = anIt.current();
230 // Checking that the algorithm worked properly.
231 if(!aBoolAlgo->isDone()) {
232 static const std::string aFeatureError = "Error: Boolean algorithm failed.";
233 setError(aFeatureError);
236 if(aResShape->isNull()) {
237 static const std::string aShapeError = "Error: Resulting shape is Null.";
238 setError(aShapeError);
241 if(!aBoolAlgo->isValid()) {
242 std::string aFeatureError = "Error: Resulting shape is not valid.";
243 setError(aFeatureError);
247 aMakeShapeList.appendAlgo(aBoolAlgo);
249 if(GeomAlgoAPI_ShapeTools::volume(aResShape) > 1.e-27
250 || (aType != BOOL_CUT && aType != BOOL_COMMON))
252 std::shared_ptr<ModelAPI_ResultBody> aResultBody =
253 document()->createBody(data(), aResultIndex);
255 ListOfShape aUsedTools = aTools;
256 if (aType == BOOL_FILL) {
257 aUsedTools.insert(aUsedTools.end(), aPlanes.begin(), aPlanes.end());
260 loadNamingDS(aResultBody, anObject, aUsedTools, aResShape,
261 aMakeShapeList, *(aBoolAlgo->mapOfSubShapes()), aType == BOOL_FILL);
262 setResult(aResultBody, aResultIndex);
267 // Compsolids handling
268 for(std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
269 anIt = aCompSolidsObjects.begin();
270 anIt != aCompSolidsObjects.end(); anIt++) {
271 std::shared_ptr<GeomAPI_Shape> aCompSolid = anIt->first;
272 ListOfShape& aUsedInOperationSolids = anIt->second;
274 // Collecting solids from compsolids which will not be modified in boolean operation.
275 ListOfShape aNotUsedSolids;
276 for(GeomAPI_ShapeExplorer
277 anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) {
278 std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
279 ListOfShape::iterator anIt = aUsedInOperationSolids.begin();
280 for(; anIt != aUsedInOperationSolids.end(); anIt++) {
281 if(aSolidInCompSolid->isEqual(*anIt)) {
285 if(anIt == aUsedInOperationSolids.end()) {
286 aNotUsedSolids.push_back(aSolidInCompSolid);
290 GeomAlgoAPI_MakeShapeList aMakeShapeList;
291 std::shared_ptr<GeomAlgoAPI_MakeShape> aBoolAlgo;
295 aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aUsedInOperationSolids,
297 GeomAlgoAPI_Boolean::BOOL_CUT));
301 aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aUsedInOperationSolids,
303 GeomAlgoAPI_Boolean::BOOL_COMMON));
307 std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints =
308 GeomAlgoAPI_ShapeTools::getBoundingBox(aUsedInOperationSolids, 1.0);
311 ListOfShape aToolsWithPlanes = aTools;
312 for(ListOfShape::const_iterator anIt = aPlanes.cbegin();
313 anIt != aPlanes.cend();
316 GeomShapePtr aPlane = *anIt;
317 GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints);
318 std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aMkShCustom(
319 new GeomAlgoAPI_MakeShapeCustom);
320 aMkShCustom->addModified(aPlane, aTool);
321 aMakeShapeList.appendAlgo(aMkShCustom);
322 aToolsWithPlanes.push_back(aTool);
325 aBoolAlgo.reset(new GeomAlgoAPI_Partition(aUsedInOperationSolids, aToolsWithPlanes));
330 // Checking that the algorithm worked properly.
331 if(!aBoolAlgo->isDone()) {
332 static const std::string aFeatureError = "Error: Boolean algorithm failed.";
333 setError(aFeatureError);
336 if(aBoolAlgo->shape()->isNull()) {
337 static const std::string aShapeError = "Error: Resulting shape is Null.";
338 setError(aShapeError);
341 if(!aBoolAlgo->isValid()) {
342 std::string aFeatureError = "Error: Resulting shape is not valid.";
343 setError(aFeatureError);
347 aMakeShapeList.appendAlgo(aBoolAlgo);
348 GeomAPI_DataMapOfShapeShape aMapOfShapes;
349 aMapOfShapes.merge(aBoolAlgo->mapOfSubShapes());
350 GeomShapePtr aResultShape = aBoolAlgo->shape();
352 // Add result to not used solids from compsolid.
353 if(!aNotUsedSolids.empty()) {
354 ListOfShape aShapesToAdd = aNotUsedSolids;
355 aShapesToAdd.push_back(aBoolAlgo->shape());
356 std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(
357 new GeomAlgoAPI_PaveFiller(aShapesToAdd, true));
358 if(!aFillerAlgo->isDone()) {
359 std::string aFeatureError = "Error: PaveFiller algorithm failed.";
360 setError(aFeatureError);
364 aMakeShapeList.appendAlgo(aFillerAlgo);
365 aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
366 aResultShape = aFillerAlgo->shape();
369 if(GeomAlgoAPI_ShapeTools::volume(aResultShape) > 1.e-27
370 || (aType != BOOL_CUT && aType != BOOL_COMMON))
372 std::shared_ptr<ModelAPI_ResultBody> aResultBody =
373 document()->createBody(data(), aResultIndex);
375 ListOfShape aUsedTools = aTools;
376 if (aType == BOOL_FILL) {
377 aUsedTools.insert(aUsedTools.end(), aPlanes.begin(), aPlanes.end());
380 loadNamingDS(aResultBody,
387 setResult(aResultBody, aResultIndex);
394 if((anObjects.size() + aTools.size() +
395 aCompSolidsObjects.size() + anEdgesAndFaces.size()) < 2) {
396 std::string aFeatureError = "Error: Not enough objects for boolean operation.";
397 setError(aFeatureError);
401 // Collecting all solids which will be fused.
402 ListOfShape aSolidsToFuse;
403 aSolidsToFuse.insert(aSolidsToFuse.end(), anObjects.begin(), anObjects.end());
404 aSolidsToFuse.insert(aSolidsToFuse.end(), aTools.begin(), aTools.end());
406 // Collecting solids from compsolids which will not be modified
407 // in boolean operation and will be added to result.
408 ListOfShape aShapesToAdd;
409 for(std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
410 anIt = aCompSolidsObjects.begin();
411 anIt != aCompSolidsObjects.end(); anIt++) {
412 std::shared_ptr<GeomAPI_Shape> aCompSolid = anIt->first;
413 ListOfShape& aUsedInOperationSolids = anIt->second;
414 aSolidsToFuse.insert(aSolidsToFuse.end(), aUsedInOperationSolids.begin(),
415 aUsedInOperationSolids.end());
417 // Collect solids from compsolid which will not be modified in boolean operation.
418 for(GeomAPI_ShapeExplorer
419 anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) {
420 std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
421 ListOfShape::iterator anIt = aUsedInOperationSolids.begin();
422 for(; anIt != aUsedInOperationSolids.end(); anIt++) {
423 if(aSolidInCompSolid->isEqual(*anIt)) {
427 if(anIt == aUsedInOperationSolids.end()) {
428 aShapesToAdd.push_back(aSolidInCompSolid);
433 ListOfShape anOriginalShapes = aSolidsToFuse;
434 anOriginalShapes.insert(anOriginalShapes.end(), aShapesToAdd.begin(), aShapesToAdd.end());
436 // Cut edges and faces(if we have any) with solids.
437 GeomAlgoAPI_MakeShapeList aMakeShapeList;
438 GeomAPI_DataMapOfShapeShape aMapOfShapes;
439 std::shared_ptr<GeomAPI_Shape> aCuttedEdgesAndFaces;
440 if(!anEdgesAndFaces.empty()) {
441 std::shared_ptr<GeomAlgoAPI_Boolean> aCutAlgo(new GeomAlgoAPI_Boolean(anEdgesAndFaces,
442 anOriginalShapes, GeomAlgoAPI_Boolean::BOOL_CUT));
443 if(aCutAlgo->isDone()) {
444 aCuttedEdgesAndFaces = aCutAlgo->shape();
445 aMakeShapeList.appendAlgo(aCutAlgo);
446 aMapOfShapes.merge(aCutAlgo->mapOfSubShapes());
449 anOriginalShapes.insert(anOriginalShapes.end(), anEdgesAndFaces.begin(),
450 anEdgesAndFaces.end());
452 // If we have compsolids then cut with not used solids all others.
453 if(!aShapesToAdd.empty()) {
454 aSolidsToFuse.clear();
455 for(ListOfShape::iterator
456 anIt = anOriginalShapes.begin(); anIt != anOriginalShapes.end(); anIt++) {
457 ListOfShape aOneObjectList;
458 aOneObjectList.push_back(*anIt);
459 std::shared_ptr<GeomAlgoAPI_Boolean> aCutAlgo(
460 new GeomAlgoAPI_Boolean(aOneObjectList, aShapesToAdd, GeomAlgoAPI_Boolean::BOOL_CUT));
462 if(GeomAlgoAPI_ShapeTools::volume(aCutAlgo->shape()) > 1.e-27) {
463 aSolidsToFuse.push_back(aCutAlgo->shape());
464 aMakeShapeList.appendAlgo(aCutAlgo);
465 aMapOfShapes.merge(aCutAlgo->mapOfSubShapes());
470 if(!aSolidsToFuse.empty()) {
472 anObjects.push_back(aSolidsToFuse.back());
473 aSolidsToFuse.pop_back();
474 aTools = aSolidsToFuse;
477 // Fuse all objects and all tools.
478 std::shared_ptr<GeomAPI_Shape> aShape;
479 if(anObjects.size() == 1 && aTools.empty()) {
480 aShape = anObjects.front();
481 } else if(anObjects.empty() && aTools.size() == 1) {
482 aShape = aTools.front();
483 } else if((anObjects.size() + aTools.size()) > 1){
484 std::shared_ptr<GeomAlgoAPI_Boolean> aFuseAlgo(new GeomAlgoAPI_Boolean(anObjects,
486 GeomAlgoAPI_Boolean::BOOL_FUSE));
488 // Checking that the algorithm worked properly.
489 if(!aFuseAlgo->isDone()) {
490 static const std::string aFeatureError = "Error: Boolean algorithm failed.";
491 setError(aFeatureError);
494 if(aFuseAlgo->shape()->isNull()) {
495 static const std::string aShapeError = "Error: Resulting shape is Null.";
496 setError(aShapeError);
499 if(!aFuseAlgo->isValid()) {
500 std::string aFeatureError = "Error: Resulting shape is not valid.";
501 setError(aFeatureError);
505 aShape = aFuseAlgo->shape();
506 aMakeShapeList.appendAlgo(aFuseAlgo);
507 aMapOfShapes.merge(aFuseAlgo->mapOfSubShapes());
510 // Combine result with not used solids from compsolid and edges and faces (if we have any).
511 if(aCuttedEdgesAndFaces.get() && !aCuttedEdgesAndFaces->isNull()) {
512 aShapesToAdd.push_back(aCuttedEdgesAndFaces);
514 aShapesToAdd.insert(aShapesToAdd.end(), anEdgesAndFaces.begin(), anEdgesAndFaces.end());
516 if(!aShapesToAdd.empty()) {
518 aShapesToAdd.push_back(aShape);
520 std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(
521 new GeomAlgoAPI_PaveFiller(aShapesToAdd, true));
522 if(!aFillerAlgo->isDone()) {
523 std::string aFeatureError = "Error: PaveFiller algorithm failed.";
524 setError(aFeatureError);
527 if(aFillerAlgo->shape()->isNull()) {
528 static const std::string aShapeError = "Error: Resulting shape is Null.";
529 setError(aShapeError);
532 if(!aFillerAlgo->isValid()) {
533 std::string aFeatureError = "Error: Resulting shape is not valid.";
534 setError(aFeatureError);
538 aShape = aFillerAlgo->shape();
539 aMakeShapeList.appendAlgo(aFillerAlgo);
540 aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
543 std::shared_ptr<GeomAPI_Shape> aBackShape = anOriginalShapes.back();
544 anOriginalShapes.pop_back();
545 std::shared_ptr<ModelAPI_ResultBody> aResultBody =
546 document()->createBody(data(), aResultIndex);
547 loadNamingDS(aResultBody, aBackShape, anOriginalShapes,
548 aShape, aMakeShapeList, aMapOfShapes);
549 setResult(aResultBody, aResultIndex);
554 if((anObjects.empty() && aCompSolidsObjects.empty()) || aTools.empty()) {
555 std::string aFeatureError = "Error: Not enough objects for boolean operation.";
556 setError(aFeatureError);
560 // List of original solids for naming.
561 ListOfShape anOriginalShapes;
562 anOriginalShapes.insert(anOriginalShapes.end(), anObjects.begin(), anObjects.end());
563 anOriginalShapes.insert(anOriginalShapes.end(), aTools.begin(), aTools.end());
565 // Collecting all solids which will be smashed.
566 ListOfShape aShapesToSmash;
567 aShapesToSmash.insert(aShapesToSmash.end(), anObjects.begin(), anObjects.end());
569 // Collecting solids from compsolids which will not be modified in
570 // boolean operation and will be added to result.
571 ListOfShape aShapesToAdd;
572 for(std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
573 anIt = aCompSolidsObjects.begin();
574 anIt != aCompSolidsObjects.end(); anIt++) {
575 std::shared_ptr<GeomAPI_Shape> aCompSolid = anIt->first;
576 ListOfShape& aUsedInOperationSolids = anIt->second;
577 anOriginalShapes.push_back(aCompSolid);
578 aShapesToSmash.insert(aShapesToSmash.end(), aUsedInOperationSolids.begin(),
579 aUsedInOperationSolids.end());
581 // Collect solids from compsolid which will not be modified in boolean operation.
582 for(GeomAPI_ShapeExplorer
583 anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) {
584 std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
585 ListOfShape::iterator anIt = aUsedInOperationSolids.begin();
586 for(; anIt != aUsedInOperationSolids.end(); anIt++) {
587 if(aSolidInCompSolid->isEqual(*anIt)) {
591 if(anIt == aUsedInOperationSolids.end()) {
592 aShapesToAdd.push_back(aSolidInCompSolid);
597 GeomAlgoAPI_MakeShapeList aMakeShapeList;
598 GeomAPI_DataMapOfShapeShape aMapOfShapes;
599 if(!aShapesToAdd.empty()) {
600 // Cut objects with not used solids.
601 std::shared_ptr<GeomAlgoAPI_Boolean> anObjectsCutAlgo(new GeomAlgoAPI_Boolean(
604 GeomAlgoAPI_Boolean::BOOL_CUT));
606 if(GeomAlgoAPI_ShapeTools::volume(anObjectsCutAlgo->shape()) > 1.e-27) {
607 aShapesToSmash.clear();
608 aShapesToSmash.push_back(anObjectsCutAlgo->shape());
609 aMakeShapeList.appendAlgo(anObjectsCutAlgo);
610 aMapOfShapes.merge(anObjectsCutAlgo->mapOfSubShapes());
613 // Cut tools with not used solids.
614 std::shared_ptr<GeomAlgoAPI_Boolean> aToolsCutAlgo(new GeomAlgoAPI_Boolean(aTools,
616 GeomAlgoAPI_Boolean::BOOL_CUT));
618 if(GeomAlgoAPI_ShapeTools::volume(aToolsCutAlgo->shape()) > 1.e-27) {
620 aTools.push_back(aToolsCutAlgo->shape());
621 aMakeShapeList.appendAlgo(aToolsCutAlgo);
622 aMapOfShapes.merge(aToolsCutAlgo->mapOfSubShapes());
626 // Cut objects with tools.
627 std::shared_ptr<GeomAlgoAPI_Boolean> aBoolAlgo(new GeomAlgoAPI_Boolean(aShapesToSmash,
629 GeomAlgoAPI_Boolean::BOOL_CUT));
631 // Checking that the algorithm worked properly.
632 if(!aBoolAlgo->isDone()) {
633 static const std::string aFeatureError = "Error: Boolean algorithm failed.";
634 setError(aFeatureError);
637 if(aBoolAlgo->shape()->isNull()) {
638 static const std::string aShapeError = "Error: Resulting shape is Null.";
639 setError(aShapeError);
642 if(!aBoolAlgo->isValid()) {
643 std::string aFeatureError = "Error: Resulting shape is not valid.";
644 setError(aFeatureError);
647 aMakeShapeList.appendAlgo(aBoolAlgo);
648 aMapOfShapes.merge(aBoolAlgo->mapOfSubShapes());
650 // Put all (cut result, tools and not used solids) to PaveFiller.
651 aShapesToAdd.push_back(aBoolAlgo->shape());
652 aShapesToAdd.insert(aShapesToAdd.end(), aTools.begin(), aTools.end());
654 std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(new GeomAlgoAPI_PaveFiller(aShapesToAdd,
656 if(!aFillerAlgo->isDone()) {
657 std::string aFeatureError = "Error: PaveFiller algorithm failed.";
658 setError(aFeatureError);
661 if(aFillerAlgo->shape()->isNull()) {
662 static const std::string aShapeError = "Error: Resulting shape is Null.";
663 setError(aShapeError);
666 if(!aFillerAlgo->isValid()) {
667 std::string aFeatureError = "Error: Resulting shape is not valid.";
668 setError(aFeatureError);
672 std::shared_ptr<GeomAPI_Shape> aShape = aFillerAlgo->shape();
673 aMakeShapeList.appendAlgo(aFillerAlgo);
674 aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
676 std::shared_ptr<GeomAPI_Shape> aFrontShape = anOriginalShapes.front();
677 anOriginalShapes.pop_front();
678 std::shared_ptr<ModelAPI_ResultBody> aResultBody =
679 document()->createBody(data(), aResultIndex);
680 loadNamingDS(aResultBody, aFrontShape, anOriginalShapes,
681 aShape, aMakeShapeList, aMapOfShapes);
682 setResult(aResultBody, aResultIndex);
688 std::string anOperationError = "Error: Wrong type of operation";
689 setError(anOperationError);
693 // remove the rest results if there were produced in the previous pass
694 removeResults(aResultIndex);
697 //=================================================================================================
698 void FeaturesPlugin_Boolean::loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> theResultBody,
699 const std::shared_ptr<GeomAPI_Shape> theBaseShape,
700 const ListOfShape& theTools,
701 const std::shared_ptr<GeomAPI_Shape> theResultShape,
702 GeomAlgoAPI_MakeShape& theMakeShape,
703 GeomAPI_DataMapOfShapeShape& theMapOfShapes,
704 const bool theIsStoreAsGenerated)
707 if(theBaseShape->isEqual(theResultShape)) {
708 theResultBody->store(theResultShape, false);
710 const int aModifyTag = 1;
711 const int aModifyEdgeTag = 2;
712 const int aModifyFaceTag = 3;
713 const int aDeletedTag = 4;
714 /// sub solids will be placed at labels 5, 6, etc. if result is compound of solids
715 const int aSubsolidsTag = 5;
717 theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag);
719 const std::string aModName = "Modified";
720 const std::string aModEName = "Modified_Edge";
721 const std::string aModFName = "Modified_Face";
723 theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::EDGE,
724 aModifyEdgeTag, aModEName, theMapOfShapes, false, theIsStoreAsGenerated, true);
725 theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE,
726 aModifyFaceTag, aModFName, theMapOfShapes, false, theIsStoreAsGenerated, true);
727 theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape,
728 GeomAPI_Shape::FACE, aDeletedTag);
732 for(ListOfShape::const_iterator
733 anIter = theTools.begin(); anIter != theTools.end(); anIter++) {
734 if((*anIter)->shapeType() <= GeomAPI_Shape::FACE) {
735 aTag = aModifyFaceTag;
738 aTag = aModifyEdgeTag;
741 theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter,
742 aName == aModEName ? GeomAPI_Shape::EDGE : GeomAPI_Shape::FACE,
743 aTag, aName, theMapOfShapes, false, theIsStoreAsGenerated, true);
744 theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, aDeletedTag);