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(anObject->shapeType() == GeomAPI_Shape::EDGE ||
122 anObject->shapeType() == GeomAPI_Shape::FACE) {
123 anEdgesAndFaces.push_back(anObject);
125 anObjects.push_back(anObject);
131 AttributeSelectionListPtr aToolsSelList = selectionList(FeaturesPlugin_Boolean::TOOL_LIST_ID());
132 for(int aToolsIndex = 0; aToolsIndex < aToolsSelList->size(); aToolsIndex++) {
133 AttributeSelectionPtr aToolAttr = aToolsSelList->value(aToolsIndex);
134 GeomShapePtr aTool = aToolAttr->value();
136 // It could be a construction plane.
137 ResultPtr aContext = aToolAttr->context();
138 aPlanes.push_back(aToolAttr->context()->shape());
139 } else if(aTool->shapeType() == GeomAPI_Shape::EDGE ||
140 aTool->shapeType() == GeomAPI_Shape::FACE) {
141 anEdgesAndFaces.push_back(aTool);
143 aTools.push_back(aTool);
147 int aResultIndex = 0;
153 if((anObjects.empty() && aCompSolidsObjects.empty())
154 || (aTools.empty() && aPlanes.empty())) {
155 std::string aFeatureError = "Error: Not enough objects for boolean operation.";
156 setError(aFeatureError);
160 // For solids cut each object with all tools.
161 for(ListOfShape::iterator
162 anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end(); anObjectsIt++) {
163 std::shared_ptr<GeomAPI_Shape> anObject = *anObjectsIt;
164 ListOfShape aListWithObject;
165 aListWithObject.push_back(anObject);
166 GeomAlgoAPI_MakeShapeList aMakeShapeList;
167 std::shared_ptr<GeomAlgoAPI_MakeShape> aBoolAlgo;
168 GeomShapePtr aResShape;
172 aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aListWithObject,
174 GeomAlgoAPI_Boolean::BOOL_CUT));
175 aResShape = aBoolAlgo->shape();
179 aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aListWithObject,
181 GeomAlgoAPI_Boolean::BOOL_COMMON));
182 aResShape = aBoolAlgo->shape();
186 std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints =
187 GeomAlgoAPI_ShapeTools::getBoundingBox(aListWithObject, 1.0);
190 ListOfShape aToolsWithPlanes = aTools;
191 for(ListOfShape::const_iterator anIt = aPlanes.cbegin();
192 anIt != aPlanes.cend();
195 GeomShapePtr aPlane = *anIt;
196 GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints);
197 std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aMkShCustom(
198 new GeomAlgoAPI_MakeShapeCustom);
199 aMkShCustom->addModified(aPlane, aTool);
200 aMakeShapeList.appendAlgo(aMkShCustom);
201 aToolsWithPlanes.push_back(aTool);
204 aBoolAlgo.reset(new GeomAlgoAPI_Partition(aListWithObject, aToolsWithPlanes));
205 aResShape = aBoolAlgo->shape();
206 if(aResShape->shapeType() == GeomAPI_Shape::COMPOUND) {
207 int aSubResultsNb = 0;
208 GeomAPI_ShapeIterator anIt(aResShape);
209 for(; anIt.more(); anIt.next()) {
212 if(aSubResultsNb == 1) {
213 anIt.init(aResShape);
215 aResShape = anIt.current();
223 // Checking that the algorithm worked properly.
224 if(!aBoolAlgo->isDone()) {
225 static const std::string aFeatureError = "Error: Boolean algorithm failed.";
226 setError(aFeatureError);
229 if(aResShape->isNull()) {
230 static const std::string aShapeError = "Error: Resulting shape is Null.";
231 setError(aShapeError);
234 if(!aBoolAlgo->isValid()) {
235 std::string aFeatureError = "Error: Resulting shape is not valid.";
236 setError(aFeatureError);
240 aMakeShapeList.appendAlgo(aBoolAlgo);
242 if(GeomAlgoAPI_ShapeTools::volume(aResShape) > 1.e-27) {
243 std::shared_ptr<ModelAPI_ResultBody> aResultBody =
244 document()->createBody(data(), aResultIndex);
246 ListOfShape aUsedTools = aTools;
247 if (aType == BOOL_FILL) {
248 aUsedTools.insert(aUsedTools.end(), aPlanes.begin(), aPlanes.end());
251 loadNamingDS(aResultBody, anObject, aUsedTools, aResShape,
252 aMakeShapeList, *(aBoolAlgo->mapOfSubShapes()), aType == BOOL_FILL);
253 setResult(aResultBody, aResultIndex);
258 // Compsolids handling
259 for(std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
260 anIt = aCompSolidsObjects.begin();
261 anIt != aCompSolidsObjects.end(); anIt++) {
262 std::shared_ptr<GeomAPI_Shape> aCompSolid = anIt->first;
263 ListOfShape& aUsedInOperationSolids = anIt->second;
265 // Collecting solids from compsolids which will not be modified in boolean operation.
266 ListOfShape aNotUsedSolids;
267 for(GeomAPI_ShapeExplorer
268 anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) {
269 std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
270 ListOfShape::iterator anIt = aUsedInOperationSolids.begin();
271 for(; anIt != aUsedInOperationSolids.end(); anIt++) {
272 if(aSolidInCompSolid->isEqual(*anIt)) {
276 if(anIt == aUsedInOperationSolids.end()) {
277 aNotUsedSolids.push_back(aSolidInCompSolid);
281 GeomAlgoAPI_MakeShapeList aMakeShapeList;
282 std::shared_ptr<GeomAlgoAPI_MakeShape> aBoolAlgo;
286 aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aUsedInOperationSolids,
288 GeomAlgoAPI_Boolean::BOOL_CUT));
292 aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aUsedInOperationSolids,
294 GeomAlgoAPI_Boolean::BOOL_COMMON));
298 std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints =
299 GeomAlgoAPI_ShapeTools::getBoundingBox(aUsedInOperationSolids, 1.0);
302 ListOfShape aToolsWithPlanes = aTools;
303 for(ListOfShape::const_iterator anIt = aPlanes.cbegin();
304 anIt != aPlanes.cend();
307 GeomShapePtr aPlane = *anIt;
308 GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints);
309 std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aMkShCustom(
310 new GeomAlgoAPI_MakeShapeCustom);
311 aMkShCustom->addModified(aPlane, aTool);
312 aMakeShapeList.appendAlgo(aMkShCustom);
313 aToolsWithPlanes.push_back(aTool);
316 aBoolAlgo.reset(new GeomAlgoAPI_Partition(aUsedInOperationSolids, aToolsWithPlanes));
321 // Checking that the algorithm worked properly.
322 if(!aBoolAlgo->isDone()) {
323 static const std::string aFeatureError = "Error: Boolean algorithm failed.";
324 setError(aFeatureError);
327 if(aBoolAlgo->shape()->isNull()) {
328 static const std::string aShapeError = "Error: Resulting shape is Null.";
329 setError(aShapeError);
332 if(!aBoolAlgo->isValid()) {
333 std::string aFeatureError = "Error: Resulting shape is not valid.";
334 setError(aFeatureError);
338 aMakeShapeList.appendAlgo(aBoolAlgo);
339 GeomAPI_DataMapOfShapeShape aMapOfShapes;
340 aMapOfShapes.merge(aBoolAlgo->mapOfSubShapes());
341 GeomShapePtr aResultShape = aBoolAlgo->shape();
343 // Add result to not used solids from compsolid.
344 if(!aNotUsedSolids.empty()) {
345 ListOfShape aShapesToAdd = aNotUsedSolids;
346 aShapesToAdd.push_back(aBoolAlgo->shape());
347 std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(
348 new GeomAlgoAPI_PaveFiller(aShapesToAdd, true));
349 if(!aFillerAlgo->isDone()) {
350 std::string aFeatureError = "Error: PaveFiller algorithm failed.";
351 setError(aFeatureError);
355 aMakeShapeList.appendAlgo(aFillerAlgo);
356 aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
357 aResultShape = aFillerAlgo->shape();
360 if(GeomAlgoAPI_ShapeTools::volume(aResultShape) > 1.e-27) {
361 std::shared_ptr<ModelAPI_ResultBody> aResultBody =
362 document()->createBody(data(), aResultIndex);
364 ListOfShape aUsedTools = aTools;
365 if (aType == BOOL_FILL) {
366 aUsedTools.insert(aUsedTools.end(), aPlanes.begin(), aPlanes.end());
369 loadNamingDS(aResultBody,
376 setResult(aResultBody, aResultIndex);
383 if((anObjects.size() + aTools.size() +
384 aCompSolidsObjects.size() + anEdgesAndFaces.size()) < 2) {
385 std::string aFeatureError = "Error: Not enough objects for boolean operation.";
386 setError(aFeatureError);
390 // Collecting all solids which will be fused.
391 ListOfShape aSolidsToFuse;
392 aSolidsToFuse.insert(aSolidsToFuse.end(), anObjects.begin(), anObjects.end());
393 aSolidsToFuse.insert(aSolidsToFuse.end(), aTools.begin(), aTools.end());
395 // Collecting solids from compsolids which will not be modified
396 // in boolean operation and will be added to result.
397 ListOfShape aShapesToAdd;
398 for(std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
399 anIt = aCompSolidsObjects.begin();
400 anIt != aCompSolidsObjects.end(); anIt++) {
401 std::shared_ptr<GeomAPI_Shape> aCompSolid = anIt->first;
402 ListOfShape& aUsedInOperationSolids = anIt->second;
403 aSolidsToFuse.insert(aSolidsToFuse.end(), aUsedInOperationSolids.begin(),
404 aUsedInOperationSolids.end());
406 // Collect solids from compsolid which will not be modified in boolean operation.
407 for(GeomAPI_ShapeExplorer
408 anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) {
409 std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
410 ListOfShape::iterator anIt = aUsedInOperationSolids.begin();
411 for(; anIt != aUsedInOperationSolids.end(); anIt++) {
412 if(aSolidInCompSolid->isEqual(*anIt)) {
416 if(anIt == aUsedInOperationSolids.end()) {
417 aShapesToAdd.push_back(aSolidInCompSolid);
422 ListOfShape anOriginalShapes = aSolidsToFuse;
423 anOriginalShapes.insert(anOriginalShapes.end(), aShapesToAdd.begin(), aShapesToAdd.end());
425 // Cut edges and faces(if we have any) with solids.
426 GeomAlgoAPI_MakeShapeList aMakeShapeList;
427 GeomAPI_DataMapOfShapeShape aMapOfShapes;
428 std::shared_ptr<GeomAPI_Shape> aCuttedEdgesAndFaces;
429 if(!anEdgesAndFaces.empty()) {
430 std::shared_ptr<GeomAlgoAPI_Boolean> aCutAlgo(new GeomAlgoAPI_Boolean(anEdgesAndFaces,
431 anOriginalShapes, GeomAlgoAPI_Boolean::BOOL_CUT));
432 if(aCutAlgo->isDone()) {
433 aCuttedEdgesAndFaces = aCutAlgo->shape();
434 aMakeShapeList.appendAlgo(aCutAlgo);
435 aMapOfShapes.merge(aCutAlgo->mapOfSubShapes());
438 anOriginalShapes.insert(anOriginalShapes.end(), anEdgesAndFaces.begin(),
439 anEdgesAndFaces.end());
441 // If we have compsolids then cut with not used solids all others.
442 if(!aShapesToAdd.empty()) {
443 aSolidsToFuse.clear();
444 for(ListOfShape::iterator
445 anIt = anOriginalShapes.begin(); anIt != anOriginalShapes.end(); anIt++) {
446 ListOfShape aOneObjectList;
447 aOneObjectList.push_back(*anIt);
448 std::shared_ptr<GeomAlgoAPI_Boolean> aCutAlgo(
449 new GeomAlgoAPI_Boolean(aOneObjectList, aShapesToAdd, GeomAlgoAPI_Boolean::BOOL_CUT));
451 if(GeomAlgoAPI_ShapeTools::volume(aCutAlgo->shape()) > 1.e-27) {
452 aSolidsToFuse.push_back(aCutAlgo->shape());
453 aMakeShapeList.appendAlgo(aCutAlgo);
454 aMapOfShapes.merge(aCutAlgo->mapOfSubShapes());
459 if(!aSolidsToFuse.empty()) {
461 anObjects.push_back(aSolidsToFuse.back());
462 aSolidsToFuse.pop_back();
463 aTools = aSolidsToFuse;
466 // Fuse all objects and all tools.
467 std::shared_ptr<GeomAPI_Shape> aShape;
468 if(anObjects.size() == 1 && aTools.empty()) {
469 aShape = anObjects.front();
470 } else if(anObjects.empty() && aTools.size() == 1) {
471 aShape = aTools.front();
472 } else if((anObjects.size() + aTools.size()) > 1){
473 std::shared_ptr<GeomAlgoAPI_Boolean> aFuseAlgo(new GeomAlgoAPI_Boolean(anObjects,
475 GeomAlgoAPI_Boolean::BOOL_FUSE));
477 // Checking that the algorithm worked properly.
478 if(!aFuseAlgo->isDone()) {
479 static const std::string aFeatureError = "Error: Boolean algorithm failed.";
480 setError(aFeatureError);
483 if(aFuseAlgo->shape()->isNull()) {
484 static const std::string aShapeError = "Error: Resulting shape is Null.";
485 setError(aShapeError);
488 if(!aFuseAlgo->isValid()) {
489 std::string aFeatureError = "Error: Resulting shape is not valid.";
490 setError(aFeatureError);
494 aShape = aFuseAlgo->shape();
495 aMakeShapeList.appendAlgo(aFuseAlgo);
496 aMapOfShapes.merge(aFuseAlgo->mapOfSubShapes());
499 // Combine result with not used solids from compsolid and edges and faces (if we have any).
500 if(aCuttedEdgesAndFaces.get() && !aCuttedEdgesAndFaces->isNull()) {
501 aShapesToAdd.push_back(aCuttedEdgesAndFaces);
503 aShapesToAdd.insert(aShapesToAdd.end(), anEdgesAndFaces.begin(), anEdgesAndFaces.end());
505 if(!aShapesToAdd.empty()) {
507 aShapesToAdd.push_back(aShape);
509 std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(
510 new GeomAlgoAPI_PaveFiller(aShapesToAdd, true));
511 if(!aFillerAlgo->isDone()) {
512 std::string aFeatureError = "Error: PaveFiller algorithm failed.";
513 setError(aFeatureError);
516 if(aFillerAlgo->shape()->isNull()) {
517 static const std::string aShapeError = "Error: Resulting shape is Null.";
518 setError(aShapeError);
521 if(!aFillerAlgo->isValid()) {
522 std::string aFeatureError = "Error: Resulting shape is not valid.";
523 setError(aFeatureError);
527 aShape = aFillerAlgo->shape();
528 aMakeShapeList.appendAlgo(aFillerAlgo);
529 aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
532 std::shared_ptr<GeomAPI_Shape> aBackShape = anOriginalShapes.back();
533 anOriginalShapes.pop_back();
534 std::shared_ptr<ModelAPI_ResultBody> aResultBody =
535 document()->createBody(data(), aResultIndex);
536 loadNamingDS(aResultBody, aBackShape, anOriginalShapes,
537 aShape, aMakeShapeList, aMapOfShapes);
538 setResult(aResultBody, aResultIndex);
543 if((anObjects.empty() && aCompSolidsObjects.empty()) || aTools.empty()) {
544 std::string aFeatureError = "Error: Not enough objects for boolean operation.";
545 setError(aFeatureError);
549 // List of original solids for naming.
550 ListOfShape anOriginalShapes;
551 anOriginalShapes.insert(anOriginalShapes.end(), anObjects.begin(), anObjects.end());
552 anOriginalShapes.insert(anOriginalShapes.end(), aTools.begin(), aTools.end());
554 // Collecting all solids which will be smashed.
555 ListOfShape aShapesToSmash;
556 aShapesToSmash.insert(aShapesToSmash.end(), anObjects.begin(), anObjects.end());
558 // Collecting solids from compsolids which will not be modified in
559 // boolean operation and will be added to result.
560 ListOfShape aShapesToAdd;
561 for(std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
562 anIt = aCompSolidsObjects.begin();
563 anIt != aCompSolidsObjects.end(); anIt++) {
564 std::shared_ptr<GeomAPI_Shape> aCompSolid = anIt->first;
565 ListOfShape& aUsedInOperationSolids = anIt->second;
566 anOriginalShapes.push_back(aCompSolid);
567 aShapesToSmash.insert(aShapesToSmash.end(), aUsedInOperationSolids.begin(),
568 aUsedInOperationSolids.end());
570 // Collect solids from compsolid which will not be modified in boolean operation.
571 for(GeomAPI_ShapeExplorer
572 anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) {
573 std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
574 ListOfShape::iterator anIt = aUsedInOperationSolids.begin();
575 for(; anIt != aUsedInOperationSolids.end(); anIt++) {
576 if(aSolidInCompSolid->isEqual(*anIt)) {
580 if(anIt == aUsedInOperationSolids.end()) {
581 aShapesToAdd.push_back(aSolidInCompSolid);
586 GeomAlgoAPI_MakeShapeList aMakeShapeList;
587 GeomAPI_DataMapOfShapeShape aMapOfShapes;
588 if(!aShapesToAdd.empty()) {
589 // Cut objects with not used solids.
590 std::shared_ptr<GeomAlgoAPI_Boolean> anObjectsCutAlgo(new GeomAlgoAPI_Boolean(
593 GeomAlgoAPI_Boolean::BOOL_CUT));
595 if(GeomAlgoAPI_ShapeTools::volume(anObjectsCutAlgo->shape()) > 1.e-27) {
596 aShapesToSmash.clear();
597 aShapesToSmash.push_back(anObjectsCutAlgo->shape());
598 aMakeShapeList.appendAlgo(anObjectsCutAlgo);
599 aMapOfShapes.merge(anObjectsCutAlgo->mapOfSubShapes());
602 // Cut tools with not used solids.
603 std::shared_ptr<GeomAlgoAPI_Boolean> aToolsCutAlgo(new GeomAlgoAPI_Boolean(aTools,
605 GeomAlgoAPI_Boolean::BOOL_CUT));
607 if(GeomAlgoAPI_ShapeTools::volume(aToolsCutAlgo->shape()) > 1.e-27) {
609 aTools.push_back(aToolsCutAlgo->shape());
610 aMakeShapeList.appendAlgo(aToolsCutAlgo);
611 aMapOfShapes.merge(aToolsCutAlgo->mapOfSubShapes());
615 // Cut objects with tools.
616 std::shared_ptr<GeomAlgoAPI_Boolean> aBoolAlgo(new GeomAlgoAPI_Boolean(aShapesToSmash,
618 GeomAlgoAPI_Boolean::BOOL_CUT));
620 // Checking that the algorithm worked properly.
621 if(!aBoolAlgo->isDone()) {
622 static const std::string aFeatureError = "Error: Boolean algorithm failed.";
623 setError(aFeatureError);
626 if(aBoolAlgo->shape()->isNull()) {
627 static const std::string aShapeError = "Error: Resulting shape is Null.";
628 setError(aShapeError);
631 if(!aBoolAlgo->isValid()) {
632 std::string aFeatureError = "Error: Resulting shape is not valid.";
633 setError(aFeatureError);
636 aMakeShapeList.appendAlgo(aBoolAlgo);
637 aMapOfShapes.merge(aBoolAlgo->mapOfSubShapes());
639 // Put all (cut result, tools and not used solids) to PaveFiller.
640 aShapesToAdd.push_back(aBoolAlgo->shape());
641 aShapesToAdd.insert(aShapesToAdd.end(), aTools.begin(), aTools.end());
643 std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(new GeomAlgoAPI_PaveFiller(aShapesToAdd,
645 if(!aFillerAlgo->isDone()) {
646 std::string aFeatureError = "Error: PaveFiller algorithm failed.";
647 setError(aFeatureError);
650 if(aFillerAlgo->shape()->isNull()) {
651 static const std::string aShapeError = "Error: Resulting shape is Null.";
652 setError(aShapeError);
655 if(!aFillerAlgo->isValid()) {
656 std::string aFeatureError = "Error: Resulting shape is not valid.";
657 setError(aFeatureError);
661 std::shared_ptr<GeomAPI_Shape> aShape = aFillerAlgo->shape();
662 aMakeShapeList.appendAlgo(aFillerAlgo);
663 aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
665 std::shared_ptr<GeomAPI_Shape> aFrontShape = anOriginalShapes.front();
666 anOriginalShapes.pop_front();
667 std::shared_ptr<ModelAPI_ResultBody> aResultBody =
668 document()->createBody(data(), aResultIndex);
669 loadNamingDS(aResultBody, aFrontShape, anOriginalShapes,
670 aShape, aMakeShapeList, aMapOfShapes);
671 setResult(aResultBody, aResultIndex);
677 std::string anOperationError = "Error: Wrong type of operation";
678 setError(anOperationError);
682 // remove the rest results if there were produced in the previous pass
683 removeResults(aResultIndex);
686 //=================================================================================================
687 void FeaturesPlugin_Boolean::loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> theResultBody,
688 const std::shared_ptr<GeomAPI_Shape> theBaseShape,
689 const ListOfShape& theTools,
690 const std::shared_ptr<GeomAPI_Shape> theResultShape,
691 GeomAlgoAPI_MakeShape& theMakeShape,
692 GeomAPI_DataMapOfShapeShape& theMapOfShapes,
693 const bool theIsStoreAsGenerated)
696 if(theBaseShape->isEqual(theResultShape)) {
697 theResultBody->store(theResultShape, false);
699 const int aModifyTag = 1;
700 const int aDeletedTag = 2;
701 /// sub solids will be placed at labels 3, 4, etc. if result is compound of solids
702 const int aSubsolidsTag = 3;
703 const int anEdgesAndFacesTag = 10000;
705 theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag);
707 const std::string aModName = "Modified";
708 const std::string aModEName = "Modified_Edge";
709 const std::string aModFName = "Modified_Face";
711 theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE,
712 aModifyTag, aModName, theMapOfShapes, false, theIsStoreAsGenerated, true);
713 theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape,
714 GeomAPI_Shape::FACE, aDeletedTag);
718 for(ListOfShape::const_iterator
719 anIter = theTools.begin(); anIter != theTools.end(); anIter++) {
720 if((*anIter)->shapeType() == GeomAPI_Shape::EDGE) {
721 aTag = anEdgesAndFacesTag;
724 else if((*anIter)->shapeType() == GeomAPI_Shape::FACE) {
725 aTag = anEdgesAndFacesTag;
731 theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter,
732 aName == aModEName ? GeomAPI_Shape::EDGE : GeomAPI_Shape::FACE,
733 aTag, aName, theMapOfShapes, false, theIsStoreAsGenerated, true);
734 theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, aDeletedTag);