X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FFeaturesPlugin%2FFeaturesPlugin_CompositeBoolean.cpp;h=2a3eed919a472b5cf595d19fed4f5940b288b053;hb=1dfcab3d738e427bea678317e167c587dfbff195;hp=b47952c5dbbc97c950b8c92bc3d073e7e7038287;hpb=3a2638195da6b4304161c70f3c4f76cf970adf37;p=modules%2Fshaper.git diff --git a/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp b/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp index b47952c5d..2a3eed919 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp @@ -1,172 +1,143 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: FeaturesPlugin_CompositeBoolean.cpp -// Created: 11 June 2015 -// Author: Dmitry Bobylev +// Copyright (C) 2014-2020 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// #include "FeaturesPlugin_CompositeBoolean.h" #include -#include -#include -#include -#include #include -#include +#include #include #include -#include #include -#include -#include #include -#include - -//================================================================================================= -void FeaturesPlugin_CompositeBoolean::initAttributes() -{ - data()->addAttribute(SKETCH_OBJECT_ID(), ModelAPI_AttributeReference::typeId()); - - // Boolean works with solids always. - data()->addAttribute(BOOLEAN_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId()); - AttributeSelectionListPtr aSelection = data()->selectionList(BOOLEAN_OBJECTS_ID()); - aSelection->setSelectionType("SOLID"); - initMakeSolidsAttributes(); +#include - data()->addAttribute(SKETCH_SELECTION_ID(), ModelAPI_AttributeSelection::typeId()); - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SKETCH_SELECTION_ID()); -} +#include //================================================================================================= -std::shared_ptr FeaturesPlugin_CompositeBoolean::addFeature(std::string theID) +void FeaturesPlugin_CompositeBoolean::initBooleanAttributes() { - std::shared_ptr aNew = document()->addFeature(theID, false); - if (aNew) { - data()->reference(SKETCH_OBJECT_ID())->setValue(aNew); - } - // set as current also after it becomes sub to set correctly enabled for other sketch subs - document()->setCurrentFeature(aNew, false); - return aNew; + myFeature->data()->addAttribute(OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId()); } //================================================================================================= -int FeaturesPlugin_CompositeBoolean::numberOfSubs(bool forTree) const +void FeaturesPlugin_CompositeBoolean::executeCompositeBoolean() { - ObjectPtr aObj = data()->reference(SKETCH_OBJECT_ID())->value(); - return aObj.get()? 1 : 0; -} + // Make generation. + ListOfShape aGenBaseShapes; + ListOfMakeShape aGenMakeShapes; + if(!makeGeneration(aGenBaseShapes, aGenMakeShapes)) { + return; + } -//================================================================================================= -std::shared_ptr FeaturesPlugin_CompositeBoolean::subFeature(const int theIndex, bool forTree) -{ - if (theIndex == 0) - return std::dynamic_pointer_cast(data()->reference(SKETCH_OBJECT_ID())->value()); - return std::shared_ptr(); -} + // Getting tools. + ListOfShape aTools; + for(ListOfMakeShape::const_iterator + anIt = aGenMakeShapes.cbegin(); anIt != aGenMakeShapes.cend(); ++anIt) { + aTools.push_back((*anIt)->shape()); + } -//================================================================================================= -int FeaturesPlugin_CompositeBoolean::subFeatureId(const int theIndex) const -{ - if (theIndex == 0) { - FeaturePtr aFeature = - std::dynamic_pointer_cast(data()->reference(SKETCH_OBJECT_ID())->value()); - if (aFeature.get()) - return aFeature->data()->featureId(); + // Make boolean. + ListOfShape aBooleanObjects; + ListOfMakeShape aBooleanMakeShapes; + if(!makeBoolean(aTools, aBooleanObjects, aBooleanMakeShapes)) { + return; } - return -1; -} -//================================================================================================= -bool FeaturesPlugin_CompositeBoolean::isSub(ObjectPtr theObject) const -{ - // check is this feature of result - FeaturePtr aFeature = std::dynamic_pointer_cast(theObject); - if (!aFeature) - return false; - - ObjectPtr aSub = data()->reference(SKETCH_OBJECT_ID())->value(); - return aSub == theObject; -} + if(myOperationType == BOOL_FUSE) { + aTools.splice(aTools.begin(), aBooleanObjects); + aBooleanObjects.splice(aBooleanObjects.begin(), aTools, aTools.begin()); + } -//================================================================================================= -void FeaturesPlugin_CompositeBoolean::removeFeature(std::shared_ptr theFeature) -{ -} + // Store result. + int aResultIndex = 0; + std::vector aResultBaseAlgoList; + ListOfShape aResultShapesList; + ListOfShape::const_iterator aBoolObjIt = aBooleanObjects.cbegin(); + ListOfMakeShape::const_iterator aBoolMSIt = aBooleanMakeShapes.cbegin(); + for(; aBoolObjIt != aBooleanObjects.cend() && aBoolMSIt != aBooleanMakeShapes.cend(); + ++aBoolObjIt, ++aBoolMSIt) { -//================================================================================================= -void FeaturesPlugin_CompositeBoolean::erase() -{ - if (data().get() && data()->isValid()) { // on abort of sketch of this composite it may be invalid - FeaturePtr aSketch = - std::dynamic_pointer_cast(data()->reference(SKETCH_OBJECT_ID())->value()); - if (aSketch.get() && aSketch->data()->isValid()) { - document()->removeFeature(aSketch); + ResultBodyPtr aResultBody = myFeature->document()->createBody(myFeature->data(), aResultIndex); + + if((*aBoolObjIt)->isEqual((*aBoolMSIt)->shape())) { + aResultBody->store((*aBoolMSIt)->shape(), false); } - } - ModelAPI_CompositeFeature::erase(); -} + else + { + aResultBody->storeModified(*aBoolObjIt, (*aBoolMSIt)->shape()); + + // Store generation history. + ListOfShape::const_iterator aGenBaseIt = aGenBaseShapes.cbegin(); + ListOfMakeShape::const_iterator aGenMSIt = aGenMakeShapes.cbegin(); + for(; aGenBaseIt != aGenBaseShapes.cend() && aGenMSIt != aGenMakeShapes.cend(); + ++aGenBaseIt, ++aGenMSIt) { + std::shared_ptr aMSList(new GeomAlgoAPI_MakeShapeList()); + aMSList->appendAlgo(*aGenMSIt); + aMSList->appendAlgo(*aBoolMSIt); + storeGenerationHistory(aResultBody, *aGenBaseIt, aMSList); + } + storeModificationHistory(aResultBody, *aBoolObjIt, aTools, *aBoolMSIt); -//================================================================================================= -void FeaturesPlugin_CompositeBoolean::execute() -{ - // Getting faces to create solids. - std::shared_ptr aSketchFeature = std::dynamic_pointer_cast( - reference(SKETCH_OBJECT_ID())->value()); - if(!aSketchFeature || aSketchFeature->results().empty()) { - return; - } - ResultPtr aSketchRes = aSketchFeature->results().front(); - ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aSketchRes); - if(!aConstruction.get()) { - return; - } - selection(SKETCH_SELECTION_ID())->setValue(aSketchRes, std::shared_ptr()); - int aSketchFacesNum = aConstruction->facesNum(); - if(aSketchFacesNum == 0) { - return; - } - ListOfShape aFacesList; - for(int aFaceIndex = 0; aFaceIndex < aSketchFacesNum; aFaceIndex++) { - std::shared_ptr aFace = std::dynamic_pointer_cast(aConstruction->face(aFaceIndex)); - aFacesList.push_back(aFace); + ResultBaseAlgo aRBA; + aRBA.resultBody = aResultBody; + aRBA.baseShape = *aBoolObjIt; + aRBA.makeShape = *aBoolMSIt; + aResultBaseAlgoList.push_back(aRBA); + aResultShapesList.push_back((*aBoolMSIt)->shape()); + } + + myFeature->setResult(aResultBody, aResultIndex++); } - // Searching faces with common edges. - ListOfShape aShells; - ListOfShape aFreeFaces; - std::shared_ptr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aFacesList); - GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL, aShells, aFreeFaces); - aShells.insert(aShells.end(), aFreeFaces.begin(), aFreeFaces.end()); + // Store deleted shapes after all results has been proceeded. This is to avoid issue when in one + // result shape has been deleted, but in another it was modified or stayed. + GeomShapePtr aResultShapesCompound = GeomAlgoAPI_CompoundBuilder::compound(aResultShapesList); + storeDeletedShapes(aResultBaseAlgoList, aTools, aResultShapesCompound); - // Pass shells/faces to solids creation function. - ListOfShape aTools; - ListOfMakeShape aSolidsAlgos; - makeSolids(aShells, aTools, aSolidsAlgos); - if(aTools.empty()) { - return; - } + myFeature->removeResults(aResultIndex); +} - // Getting objects for boolean operation. - ListOfShape anObjects; - std::map, ListOfShape> aCompSolidsObjects; - AttributeSelectionListPtr anObjectsSelList = selectionList(BOOLEAN_OBJECTS_ID()); - if(anObjectsSelList->size() == 0) { - return; - } +//================================================================================================= +bool FeaturesPlugin_CompositeBoolean::makeBoolean(const ListOfShape& theTools, + ListOfShape& theObjects, + ListOfMakeShape& theMakeShapes) +{ + // Getting objects. + ListOfShape anObjects, anEdgesAndFaces, aCompSolids; + std::map aCompSolidsObjects; + AttributeSelectionListPtr anObjectsSelList = myFeature->selectionList(OBJECTS_ID()); for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) { AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex); - std::shared_ptr anObject = anObjectAttr->value(); + GeomShapePtr anObject = anObjectAttr->value(); if(!anObject.get()) { - return; + myFeature->setError("Error: Could not get object."); + return false; } ResultPtr aContext = anObjectAttr->context(); - ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext); + ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext); if(aResCompSolidPtr.get()) { - std::shared_ptr aContextShape = aResCompSolidPtr->shape(); - std::map, ListOfShape>::iterator anIt = aCompSolidsObjects.begin(); + GeomShapePtr aContextShape = aResCompSolidPtr->shape(); + std::map::iterator anIt = aCompSolidsObjects.begin(); for(; anIt != aCompSolidsObjects.end(); anIt++) { if(anIt->first->isEqual(aContextShape)) { aCompSolidsObjects[anIt->first].push_back(anObject); @@ -175,279 +146,280 @@ void FeaturesPlugin_CompositeBoolean::execute() } if(anIt == aCompSolidsObjects.end()) { aCompSolidsObjects[aContextShape].push_back(anObject); + aCompSolids.push_back(aContextShape); } } else { - anObjects.push_back(anObject); + if(anObject->shapeType() == GeomAPI_Shape::EDGE || + anObject->shapeType() == GeomAPI_Shape::FACE) { + anEdgesAndFaces.push_back(anObject); + } else { + anObjects.push_back(anObject); + } } } - // Cut from each object solids. - int aResultIndex = 0; + switch(myOperationType) { + case BOOL_CUT: { + if((anObjects.empty() && aCompSolidsObjects.empty()) || theTools.empty()) { + myFeature->setError("Error: Not enough objects for boolean operation."); + return false; + } - switch(myBooleanOperationType) { - case GeomAlgoAPI_Boolean::BOOL_CUT: - case GeomAlgoAPI_Boolean::BOOL_COMMON:{ - // Cut each object with all tools - for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end(); anObjectsIt++) { - std::shared_ptr anObject = *anObjectsIt; + // For solids cut each object with all tools. + for(ListOfShape::const_iterator + anIt = anObjects.cbegin(); anIt != anObjects.cend(); ++anIt) { + GeomShapePtr anObject = *anIt; ListOfShape aListWithObject; aListWithObject.push_back(anObject); - GeomAlgoAPI_Boolean aBoolAlgo(aListWithObject, aTools, myBooleanOperationType); + std::shared_ptr aBoolAlgo(new GeomAlgoAPI_Boolean(aListWithObject, + theTools, + GeomAlgoAPI_Tools::BOOL_CUT)); // Checking that the algorithm worked properly. - if(!aBoolAlgo.isDone() || aBoolAlgo.shape()->isNull() || !aBoolAlgo.isValid()) { - setError("Boolean algorithm failed"); - return; + if(!aBoolAlgo->isDone() || aBoolAlgo->shape()->isNull() || !aBoolAlgo->isValid()) { + myFeature->setError("Error: Boolean algorithm failed."); + return false; } - if(GeomAlgoAPI_ShapeTools::volume(aBoolAlgo.shape()) > 1.e-7) { - std::shared_ptr aResultBody = document()->createBody(data(), aResultIndex); - loadNamingDS(aResultBody, aShells, aSolidsAlgos, anObject, aTools, aBoolAlgo.shape(), - aBoolAlgo, *aBoolAlgo.mapOfSubShapes().get()); - setResult(aResultBody, aResultIndex); - aResultIndex++; + if(GeomAlgoAPI_ShapeTools::volume(aBoolAlgo->shape()) > 1.e-27) { + theObjects.push_back(anObject); + theMakeShapes.push_back(aBoolAlgo); } } // Compsolids handling - for(std::map, ListOfShape>::iterator anIt = aCompSolidsObjects.begin(); - anIt != aCompSolidsObjects.end(); anIt++) { - std::shared_ptr aCompSolid = anIt->first; - ListOfShape& aUsedInOperationSolids = anIt->second; + for(std::map::const_iterator anIt = aCompSolidsObjects.cbegin(); + anIt != aCompSolidsObjects.cend(); ++anIt) { + GeomShapePtr aCompSolid = anIt->first; + const ListOfShape& aUsedShapes = anIt->second; // Collecting solids from compsolids which will not be modified in boolean operation. - ListOfShape aNotUsedSolids; - for(GeomAPI_ShapeExplorer anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) { - std::shared_ptr aSolidInCompSolid = anExp.current(); - ListOfShape::iterator anIt = aUsedInOperationSolids.begin(); - for(; anIt != aUsedInOperationSolids.end(); anIt++) { - if(aSolidInCompSolid->isEqual(*anIt)) { + ListOfShape aShapesToAdd; + for (GeomAPI_ShapeIterator aCompSolidIt(aCompSolid); + aCompSolidIt.more(); + aCompSolidIt.next()) + { + GeomShapePtr aSolidInCompSolid = aCompSolidIt.current(); + ListOfShape::const_iterator aUsedShapesIt = aUsedShapes.cbegin(); + for(; aUsedShapesIt != aUsedShapes.cend(); ++aUsedShapesIt) { + if(aSolidInCompSolid->isEqual(*aUsedShapesIt)) { break; } } - if(anIt == aUsedInOperationSolids.end()) { - aNotUsedSolids.push_back(aSolidInCompSolid); + if(aUsedShapesIt == aUsedShapes.end()) { + aShapesToAdd.push_back(aSolidInCompSolid); } } - std::shared_ptr aBoolAlgo(new GeomAlgoAPI_Boolean(aUsedInOperationSolids, aTools, myBooleanOperationType)); + std::shared_ptr aBoolAlgo(new GeomAlgoAPI_Boolean(aUsedShapes, + theTools, + GeomAlgoAPI_Tools::BOOL_CUT)); // Checking that the algorithm worked properly. if(!aBoolAlgo->isDone() || aBoolAlgo->shape()->isNull() || !aBoolAlgo->isValid()) { - setError("Boolean algorithm failed"); - return; + myFeature->setError("Error: Boolean algorithm failed."); + return false; } - GeomAlgoAPI_MakeShapeList aMakeShapeList; - aMakeShapeList.appendAlgo(aBoolAlgo); - GeomAPI_DataMapOfShapeShape aMapOfShapes; - aMapOfShapes.merge(aBoolAlgo->mapOfSubShapes()); + std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); + aMakeShapeList->appendAlgo(aBoolAlgo); // Add result to not used solids from compsolid. - ListOfShape aShapesToAdd = aNotUsedSolids; - aShapesToAdd.push_back(aBoolAlgo->shape()); - std::shared_ptr aFillerAlgo(new GeomAlgoAPI_PaveFiller(aShapesToAdd, true)); - if(!aFillerAlgo->isDone()) { - std::string aFeatureError = "PaveFiller algorithm failed"; - setError(aFeatureError); - return; + GeomShapePtr aBoolRes = aBoolAlgo->shape(); + if (!aShapesToAdd.empty()) { + aShapesToAdd.push_back(aBoolRes); + std::shared_ptr aFillerAlgo( + new GeomAlgoAPI_PaveFiller(aShapesToAdd, true)); + if(!aFillerAlgo->isDone() || aFillerAlgo->shape()->isNull() || !aFillerAlgo->isValid()) { + myFeature->setError("Error: PaveFiller algorithm failed."); + return false; + } + aBoolRes = aFillerAlgo->shape(); + aMakeShapeList->appendAlgo(aFillerAlgo); } - aMakeShapeList.appendAlgo(aFillerAlgo); - aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes()); - - if(GeomAlgoAPI_ShapeTools::volume(aFillerAlgo->shape()) > 1.e-7) { - std::shared_ptr aResultBody = document()->createBody(data(), aResultIndex); - loadNamingDS(aResultBody, aShells, aSolidsAlgos, aCompSolid, aTools, aFillerAlgo->shape(), aMakeShapeList, aMapOfShapes); - setResult(aResultBody, aResultIndex); - aResultIndex++; + if(GeomAlgoAPI_ShapeTools::volume(aBoolRes) > 1.e-27) { + theObjects.push_back(aCompSolid); + theMakeShapes.push_back(aMakeShapeList); } } break; } - case GeomAlgoAPI_Boolean::BOOL_FUSE: { + case BOOL_FUSE: { + // Set objects. + theObjects.insert(theObjects.end(), anEdgesAndFaces.begin(), anEdgesAndFaces.end()); + theObjects.insert(theObjects.end(), anObjects.begin(), anObjects.end()); + theObjects.insert(theObjects.end(), aCompSolids.begin(), aCompSolids.end()); + + // Filter edges and faces in tools. + ListOfShape aTools; + for(ListOfShape::const_iterator anIt = theTools.cbegin(); anIt != theTools.cend(); ++anIt) { + if((*anIt)->shapeType() == GeomAPI_Shape::EDGE || + (*anIt)->shapeType() == GeomAPI_Shape::FACE) { + anEdgesAndFaces.push_back(*anIt); + } else { + aTools.push_back(*anIt); + } + } + + if((anObjects.size() + aTools.size() + + aCompSolidsObjects.size() + anEdgesAndFaces.size()) < 2) { + myFeature->setError("Error: Not enough objects for boolean operation."); + return false; + } + // Collecting all solids which will be fused. ListOfShape aSolidsToFuse; aSolidsToFuse.insert(aSolidsToFuse.end(), anObjects.begin(), anObjects.end()); aSolidsToFuse.insert(aSolidsToFuse.end(), aTools.begin(), aTools.end()); - // Collecting solids from compsolids which will not be modified in boolean operation. - ListOfShape aNotUsedSolids; - for(std::map, ListOfShape>::iterator anIt = aCompSolidsObjects.begin(); - anIt != aCompSolidsObjects.end(); anIt++) { - std::shared_ptr aCompSolid = anIt->first; - ListOfShape& aUsedInOperationSolids = anIt->second; - aSolidsToFuse.insert(aSolidsToFuse.end(), aUsedInOperationSolids.begin(), aUsedInOperationSolids.end()); + // Collecting solids from compsolids which will not be + // modified in boolean operation and will be added to result. + ListOfShape aShapesToAdd; + for(std::map::iterator anIt = aCompSolidsObjects.begin(); + anIt != aCompSolidsObjects.end(); anIt++) { + GeomShapePtr aCompSolid = anIt->first; + ListOfShape& aUsedShapes = anIt->second; + aSolidsToFuse.insert(aSolidsToFuse.end(), aUsedShapes.begin(), aUsedShapes.end()); // Collect solids from compsolid which will not be modified in boolean operation. - for(GeomAPI_ShapeExplorer anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) { - std::shared_ptr aSolidInCompSolid = anExp.current(); - ListOfShape::iterator anIt = aUsedInOperationSolids.begin(); - for(; anIt != aUsedInOperationSolids.end(); anIt++) { + for (GeomAPI_ShapeIterator aCompSolidIt(aCompSolid); + aCompSolidIt.more(); + aCompSolidIt.next()) + { + GeomShapePtr aSolidInCompSolid = aCompSolidIt.current(); + ListOfShape::iterator anIt = aUsedShapes.begin(); + for(; anIt != aUsedShapes.end(); anIt++) { if(aSolidInCompSolid->isEqual(*anIt)) { break; } } - if(anIt == aUsedInOperationSolids.end()) { - aNotUsedSolids.push_back(aSolidInCompSolid); + if(anIt == aUsedShapes.end()) { + aShapesToAdd.push_back(aSolidInCompSolid); } } } - ListOfShape anOriginalSolids = aSolidsToFuse; - anOriginalSolids.insert(anOriginalSolids.end(), aNotUsedSolids.begin(), aNotUsedSolids.end()); - GeomAlgoAPI_MakeShapeList aMakeShapeList; - GeomAPI_DataMapOfShapeShape aMapOfShapes; + // Cut edges and faces(if we have any) with solids. + ListOfShape aCutTools; + aCutTools.insert(aCutTools.end(), anObjects.begin(), anObjects.end()); + aCutTools.insert(aCutTools.end(), aCompSolids.begin(), aCompSolids.end()); + aCutTools.insert(aCutTools.end(), aTools.begin(), aTools.end()); + + std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); + if(!anEdgesAndFaces.empty() && !aCutTools.empty()) { + std::shared_ptr aCutAlgo(new GeomAlgoAPI_Boolean(anEdgesAndFaces, + aCutTools, + GeomAlgoAPI_Tools::BOOL_CUT)); + if(aCutAlgo->isDone() && !aCutAlgo->shape()->isNull() && aCutAlgo->isValid()) { + anEdgesAndFaces.clear(); + anEdgesAndFaces.push_back(aCutAlgo->shape()); + aMakeShapeList->appendAlgo(aCutAlgo); + } + } // If we have compsolids then cut with not used solids all others. - if(!aNotUsedSolids.empty()) { - aSolidsToFuse.clear(); - for(ListOfShape::iterator anIt = anOriginalSolids.begin(); anIt != anOriginalSolids.end(); anIt++) { - ListOfShape aOneObjectList; - aOneObjectList.push_back(*anIt); - std::shared_ptr aCutAlgo(new GeomAlgoAPI_Boolean(aOneObjectList, aNotUsedSolids, GeomAlgoAPI_Boolean::BOOL_CUT)); - - if(GeomAlgoAPI_ShapeTools::volume(aCutAlgo->shape()) > 1.e-7) { - aSolidsToFuse.push_back(aCutAlgo->shape()); - aMakeShapeList.appendAlgo(aCutAlgo); - aMapOfShapes.merge(aCutAlgo->mapOfSubShapes()); - } + if(!aShapesToAdd.empty()) { + std::shared_ptr aCutAlgo(new GeomAlgoAPI_Boolean(aSolidsToFuse, + aShapesToAdd, + GeomAlgoAPI_Tools::BOOL_CUT)); + if(aCutAlgo->isDone() && GeomAlgoAPI_ShapeTools::volume(aCutAlgo->shape()) > 1.e-27) { + aSolidsToFuse.clear(); + aSolidsToFuse.push_back(aCutAlgo->shape()); + aMakeShapeList->appendAlgo(aCutAlgo); } } - anObjects.clear(); - anObjects.push_back(aSolidsToFuse.back()); - aSolidsToFuse.pop_back(); - aTools = aSolidsToFuse; - // Fuse all objects and all tools. - std::shared_ptr aFuseAlgo(new GeomAlgoAPI_Boolean(anObjects, aTools, myBooleanOperationType)); + GeomShapePtr aFusedShape; + if(aSolidsToFuse.size() == 1) { + aFusedShape = aSolidsToFuse.front(); + } else if(aSolidsToFuse.size() > 1){ + anObjects.clear(); + anObjects.push_back(aSolidsToFuse.front()); + aSolidsToFuse.pop_front(); + aTools = aSolidsToFuse; + + std::shared_ptr aFuseAlgo(new GeomAlgoAPI_Boolean(anObjects, + aTools, + GeomAlgoAPI_Tools::BOOL_FUSE)); + + // Checking that the algorithm worked properly. + if(!aFuseAlgo->isDone() || aFuseAlgo->shape()->isNull() || !aFuseAlgo->isValid()) { + myFeature->setError("Error: Boolean algorithm failed."); + return false; + } - // Checking that the algorithm worked properly. - if(!aFuseAlgo->isDone() || aFuseAlgo->shape()->isNull() || !aFuseAlgo->isValid()) { - static const std::string aFeatureError = "Boolean algorithm failed"; - setError(aFeatureError); - return; + aFusedShape = aFuseAlgo->shape(); + aMakeShapeList->appendAlgo(aFuseAlgo); } - std::shared_ptr aShape = aFuseAlgo->shape(); - aMakeShapeList.appendAlgo(aFuseAlgo); - aMapOfShapes.merge(aFuseAlgo->mapOfSubShapes()); - - // Add result to not used solids from compsolid (if we have any). - if(!aNotUsedSolids.empty()) { - aNotUsedSolids.push_back(aShape); - std::shared_ptr aFillerAlgo(new GeomAlgoAPI_PaveFiller(aNotUsedSolids, true)); - if(!aFillerAlgo->isDone()) { - std::string aFeatureError = "PaveFiller algorithm failed"; - setError(aFeatureError); - return; - } - if(aFillerAlgo->shape()->isNull()) { - static const std::string aShapeError = "Resulting shape is Null"; - setError(aShapeError); - return; + // Combine result with not used solids from compsolid and edges and faces (if we have any). + aShapesToAdd.insert(aShapesToAdd.end(), anEdgesAndFaces.begin(), anEdgesAndFaces.end()); + if(!aShapesToAdd.empty()) { + if(aFusedShape.get()) { + aShapesToAdd.push_back(aFusedShape); } - if(!aFillerAlgo->isValid()) { - std::string aFeatureError = "Warning: resulting shape is not valid"; - setError(aFeatureError); - return; + + std::shared_ptr aFillerAlgo( + new GeomAlgoAPI_PaveFiller(aShapesToAdd, true)); + if(!aFillerAlgo->isDone() || aFillerAlgo->shape()->isNull() || !aFillerAlgo->isValid()) { + myFeature->setError("Error: PaveFiller algorithm failed."); + return false; } - aShape = aFillerAlgo->shape(); - aMakeShapeList.appendAlgo(aFillerAlgo); - aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes()); + aMakeShapeList->appendAlgo(aFillerAlgo); } - std::shared_ptr aResultBody = document()->createBody(data(), aResultIndex); - loadNamingDS(aResultBody, aShells, aSolidsAlgos, anOriginalSolids.front(), anOriginalSolids, aShape, aMakeShapeList, aMapOfShapes); - setResult(aResultBody, aResultIndex); - aResultIndex++; + theMakeShapes.push_back(aMakeShapeList); break; } - default: { - setError("Error: wrong type of boolean operation"); - return; - } + default: // [to avoid compilation warnings] + break; } - // Remove the rest results if there were produced in the previous pass. - removeResults(aResultIndex); + return true; } //================================================================================================= -void FeaturesPlugin_CompositeBoolean::loadNamingDS(std::shared_ptr theResultBody, - const ListOfShape& theShells, - ListOfMakeShape& theSolidsAlgos, - const std::shared_ptr theBaseShape, - const ListOfShape& theTools, - const std::shared_ptr theResultShape, - GeomAlgoAPI_MakeShape& theMakeShape, - GeomAPI_DataMapOfShapeShape& theMapOfShapes) +void FeaturesPlugin_CompositeBoolean::storeModificationHistory(ResultBodyPtr theResultBody, + const GeomShapePtr theObject, + const ListOfShape& theTools, + const std::shared_ptr theMakeShape) { - //load result - if(theBaseShape->isEqual(theResultShape)) { - theResultBody->store(theResultShape); - } else { - const int aGenTag = 1; - const int aModTag = 2; - const int aDelTag = 3; - const int aSubsolidsTag=4; /// sub solids will be placed at labels 6, 7, etc. if result is compound of solids - int aToTag = 5000; // may be many labels, starting from this index - int aFromTag = 10000; // may be many labels, starting from this index or last aToTag index - const std::string aGenName = "Generated"; - const std::string aModName = "Modified"; - const std::string aLatName = "LateralFace"; - const std::string aFromName = "FromFace"; - const std::string aToName = "ToFace"; - - theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag); - - ListOfShape::const_iterator aShellsIter = theShells.begin(); - ListOfMakeShape::const_iterator aSolidsAlgosIter = theSolidsAlgos.begin(); - for(; aShellsIter != theShells.end() && aSolidsAlgosIter != theSolidsAlgos.end(); aShellsIter++, aSolidsAlgosIter++) { - //Insert lateral face : Face from Edge - std::shared_ptr aSolidAlgo = std::dynamic_pointer_cast(*aSolidsAlgosIter); - if(aSolidAlgo.get()) { - std::shared_ptr aSubShapes = aSolidAlgo->mapOfSubShapes(); - theResultBody->loadAndOrientGeneratedShapes(aSolidAlgo.get(), *aShellsIter, GeomAPI_Shape::EDGE, aGenTag, - aLatName, *aSubShapes.get()); - - - std::shared_ptr aSweepAlgo = std::dynamic_pointer_cast(aSolidAlgo); - if(aSweepAlgo.get()) { - //Insert to faces - const ListOfShape& aToFaces = aSweepAlgo->toFaces(); - for(ListOfShape::const_iterator anIt = aToFaces.cbegin(); anIt != aToFaces.cend(); anIt++) { - std::shared_ptr aToFace = *anIt; - if(aSubShapes->isBound(aToFace)) { - aToFace = aSubShapes->find(aToFace); - } - theResultBody->generated(aToFace, aToName, aToTag++); - } - - //Insert from faces - const ListOfShape& aFromFaces = aSweepAlgo->fromFaces(); - if (aFromTag < aToTag) aFromTag = aToTag; - for(ListOfShape::const_iterator anIt = aFromFaces.cbegin(); anIt != aFromFaces.cend(); anIt++) { - std::shared_ptr aFromFace = *anIt; - if(aSubShapes->isBound(aFromFace)) { - aFromFace = aSubShapes->find(aFromFace); - } - theResultBody->generated(aFromFace, aFromName, aFromTag++); - } - } - } - } - - theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE, - aModTag, aModName, theMapOfShapes); - theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE, aDelTag); + ListOfShape aTools = theTools; + aTools.push_back(theObject); + + for(ListOfShape::const_iterator anIt = aTools.begin(); anIt != aTools.end(); anIt++) { + theResultBody->loadModifiedShapes(theMakeShape, *anIt, + (*anIt)->shapeType() == GeomAPI_Shape::EDGE ? + GeomAPI_Shape::EDGE : + GeomAPI_Shape::FACE); + } +} - for(ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++) { - theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, - aModTag, aModName, theMapOfShapes); - theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, aDelTag); +//================================================================================================== +void FeaturesPlugin_CompositeBoolean::storeDeletedShapes( + std::vector& theResultBaseAlgoList, + const ListOfShape& theTools, + const GeomShapePtr theResultShapesCompound) +{ + for (std::vector::iterator anIt = theResultBaseAlgoList.begin(); + anIt != theResultBaseAlgoList.end(); + ++anIt) + { + ResultBaseAlgo& aRCA = *anIt; + aRCA.resultBody->loadDeletedShapes(aRCA.makeShape, + aRCA.baseShape, + GeomAPI_Shape::FACE, + theResultShapesCompound); + + for (ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++) + { + aRCA.resultBody->loadDeletedShapes(aRCA.makeShape, + *anIter, + GeomAPI_Shape::FACE, + theResultShapesCompound); } } }