X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FFeaturesPlugin%2FFeaturesPlugin_CompositeBoolean.cpp;h=f1b693c5bd005bce3f87cf806297fac7453d82dc;hb=bc68c24f2be18a091832a8215428c4039bac5ddf;hp=27cc3c6e8c95facea374d8dc4055a6b4ab4d5a5d;hpb=f328eabbb64e9fe347f36728710ebe1ebb00de6e;p=modules%2Fshaper.git diff --git a/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp b/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp index 27cc3c6e8..f1b693c5b 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp @@ -1,278 +1,419 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: FeaturesPlugin_CompositeBoolean.cpp -// Created: 11 June 2015 -// Author: Dmitry Bobylev - -#include +// Copyright (C) 2014-2017 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 -//================================================================================================= -void FeaturesPlugin_CompositeBoolean::initAttributes() -{ - data()->addAttribute(SKETCH_OBJECT_ID(), ModelAPI_AttributeReference::typeId()); +#include - // 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 //================================================================================================= -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) const -{ - 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 -{ - std::shared_ptr aFeature = subFeature(theIndex); - if (aFeature.get()) - return aFeature->data()->featureId(); - return -1; -} + // Make boolean. + ListOfShape aBooleanObjects; + ListOfMakeShape aBooleanMakeShapes; + if(!makeBoolean(aTools, aBooleanObjects, aBooleanMakeShapes)) { + return; + } -//================================================================================================= -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); + int aTag = 1; + + 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()); + + aTag += 5000; + + // Store generation history. + ListOfShape::const_iterator aGenBaseIt = aGenBaseShapes.cbegin(); + ListOfMakeShape::const_iterator aGenMSIt = aGenMakeShapes.cbegin(); + for(; aGenBaseIt != aGenBaseShapes.cend() && aGenMSIt != aGenMakeShapes.cend(); + ++aGenBaseIt, ++aGenMSIt) { + storeGenerationHistory(aResultBody, *aGenBaseIt, *aGenMSIt); + } + 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) { - return; - } - ResultPtr aSketchRes = aSketchFeature->results().front(); - ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aSketchRes); - if(!aConstruction.get()) { - return; - } - int aSketchFacesNum = aConstruction->facesNum(); - if(aSketchFacesNum == 0) { - return; //TODO: set error message - } - ListOfShape aSketchFacesList; - for(int aFaceIndex = 0; aFaceIndex < aSketchFacesNum; aFaceIndex++) { - std::shared_ptr aFace = std::dynamic_pointer_cast(aConstruction->face(aFaceIndex)); - aSketchFacesList.push_back(aFace); - } + ResultBaseAlgo aRBA; + aRBA.resultBody = aResultBody; + aRBA.baseShape = *aBoolObjIt; + aRBA.makeShape = *aBoolMSIt; + aResultBaseAlgoList.push_back(aRBA); + aResultShapesList.push_back((*aBoolMSIt)->shape()); + } - // Pass faces to soldis creation function. - ListOfShape aBooleanTools; - std::list> theSolidsAlgos; - makeSolids(aSketchFacesList, aBooleanTools, theSolidsAlgos); - if(aBooleanTools.empty()) { - return; + myFeature->setResult(aResultBody, aResultIndex++); } - // Getting objects for boolean operation. - ListOfShape aBooleanObjects; - AttributeSelectionListPtr anObjectsSelList = selectionList(BOOLEAN_OBJECTS_ID()); - if (anObjectsSelList->size() == 0) { - return; - } + // 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); + + myFeature->removeResults(aResultIndex); +} + +//================================================================================================= +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++) { - std::shared_ptr anObjectAttr = anObjectsSelList->value(anObjectsIndex); - std::shared_ptr anObject = anObjectAttr->value(); + AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex); + GeomShapePtr anObject = anObjectAttr->value(); if(!anObject.get()) { - return; + myFeature->setError("Error: Could not get object."); + return false; + } + ResultPtr aContext = anObjectAttr->context(); + ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext); + if(aResCompSolidPtr.get()) { + 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); + break; + } + } + if(anIt == aCompSolidsObjects.end()) { + aCompSolidsObjects[aContextShape].push_back(anObject); + aCompSolids.push_back(aContextShape); + } + } else { + if(anObject->shapeType() == GeomAPI_Shape::EDGE || + anObject->shapeType() == GeomAPI_Shape::FACE) { + anEdgesAndFaces.push_back(anObject); + } else { + anObjects.push_back(anObject); + } } - aBooleanObjects.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 = aBooleanObjects.begin(); anObjectsIt != aBooleanObjects.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, aBooleanTools, myBooleanOperationType); + std::shared_ptr aBoolAlgo(new GeomAlgoAPI_Boolean(aListWithObject, + theTools, + GeomAlgoAPI_Boolean::BOOL_CUT)); + + // Checking that the algorithm worked properly. + if(!aBoolAlgo->isDone() || aBoolAlgo->shape()->isNull() || !aBoolAlgo->isValid()) { + myFeature->setError("Error: Boolean algorithm failed."); + return false; + } + + if(GeomAlgoAPI_ShapeTools::volume(aBoolAlgo->shape()) > 1.e-27) { + theObjects.push_back(anObject); + theMakeShapes.push_back(aBoolAlgo); + } + } + + // Compsolids handling + 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 aShapesToAdd; + for(GeomAPI_ShapeExplorer + anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) { + GeomShapePtr aSolidInCompSolid = anExp.current(); + ListOfShape::const_iterator aUsedShapesIt = aUsedShapes.cbegin(); + for(; aUsedShapesIt != aUsedShapes.cend(); ++aUsedShapesIt) { + if(aSolidInCompSolid->isEqual(*aUsedShapesIt)) { + break; + } + } + if(aUsedShapesIt == aUsedShapes.end()) { + aShapesToAdd.push_back(aSolidInCompSolid); + } + } + + std::shared_ptr aBoolAlgo(new GeomAlgoAPI_Boolean(aUsedShapes, + theTools, + GeomAlgoAPI_Boolean::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, anObject, aSketchFacesList, theSolidsAlgos, aBooleanTools, aBoolAlgo); - setResult(aResultBody, aResultIndex); - aResultIndex++; + std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); + aMakeShapeList->appendAlgo(aBoolAlgo); + + // Add result to not used solids from compsolid. + aShapesToAdd.push_back(aBoolAlgo->shape()); + 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; + } + + aMakeShapeList->appendAlgo(aFillerAlgo); + + if(GeomAlgoAPI_ShapeTools::volume(aFillerAlgo->shape()) > 1.e-27) { + theObjects.push_back(aCompSolid); + theMakeShapes.push_back(aMakeShapeList); } } break; } - case GeomAlgoAPI_Boolean::BOOL_FUSE: { - // Fuse all objects and all tools. - GeomAlgoAPI_Boolean aBoolAlgo(aBooleanObjects, aBooleanTools, myBooleanOperationType); + 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); + } + } - // Checking that the algorithm worked properly. - if(!aBoolAlgo.isDone() || aBoolAlgo.shape()->isNull() || !aBoolAlgo.isValid()) { - setError("Boolean algorithm failed"); - return; + if((anObjects.size() + aTools.size() + + aCompSolidsObjects.size() + anEdgesAndFaces.size()) < 2) { + myFeature->setError("Error: Not enough objects for boolean operation."); + return false; } - std::shared_ptr aResultBody = document()->createBody(data(), aResultIndex); - loadNamingDS(aResultBody, aBooleanObjects.front(), aSketchFacesList, theSolidsAlgos, aBooleanTools, aBoolAlgo); - setResult(aResultBody, aResultIndex); - aResultIndex++; - break; - } - default: { - setError("Error: wrong type of boolean operation"); - return; - } - } + // 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 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()) { + GeomShapePtr aSolidInCompSolid = anExp.current(); + ListOfShape::iterator anIt = aUsedShapes.begin(); + for(; anIt != aUsedShapes.end(); anIt++) { + if(aSolidInCompSolid->isEqual(*anIt)) { + break; + } + } + if(anIt == aUsedShapes.end()) { + aShapesToAdd.push_back(aSolidInCompSolid); + } + } + } - // Remove the rest results if there were produced in the previous pass. - removeResults(aResultIndex); -} + // 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_Boolean::BOOL_CUT)); + if(aCutAlgo->isDone() && !aCutAlgo->shape()->isNull() && aCutAlgo->isValid()) { + anEdgesAndFaces.clear(); + anEdgesAndFaces.push_back(aCutAlgo->shape()); + aMakeShapeList->appendAlgo(aCutAlgo); + } + } -//================================================================================================= -void FeaturesPlugin_CompositeBoolean::loadNamingDS(std::shared_ptr theResultBody, - const std::shared_ptr& theBaseShape, - const ListOfShape& theFaces, - const std::list>& theSolidsAlgos, - const ListOfShape& theTools, - const GeomAlgoAPI_Boolean& theAlgo) -{ - //load result - if(theBaseShape->isEqual(theAlgo.shape())) { - theResultBody->store(theAlgo.shape()); - } else { - const int aGenTag = 1; - const int aFrTag = 2; - const int aToTag = 3; - const int aModTag = 4; - const int aDelTag = 5; - const int aSubsolidsTag=6; /// sub solids will be placed at labels 6, 7, etc. if result is compound of solids - const std::string aGenName = "Generated"; - const std::string aModName = "Modified"; - const std::string aLatName = "LateralFace"; - const std::string aFrName = "FromFace"; - const std::string aToName = "ToFace"; - - theResultBody->storeModified(theBaseShape, theAlgo.shape(), aSubsolidsTag); - - ListOfShape::const_iterator aFaceIter = theFaces.begin(); - std::list>::const_iterator aSolidsAlgosIter = theSolidsAlgos.begin(); - for(; aFaceIter != theFaces.end() && aSolidsAlgosIter != theSolidsAlgos.end(); aFaceIter++, aSolidsAlgosIter++) { - std::shared_ptr aFromFace; - std::shared_ptr aToFace; - std::shared_ptr aSubShapes; - - //Insert lateral face : Face from Edge - if(std::dynamic_pointer_cast(*aSolidsAlgosIter)) { - std::shared_ptr aPrismAlgo = std::dynamic_pointer_cast(*aSolidsAlgosIter); - aSubShapes = aPrismAlgo->mapOfShapes(); - theResultBody->loadAndOrientGeneratedShapes(aPrismAlgo->makeShape().get(), *aFaceIter, GeomAPI_Shape::EDGE, aGenTag, - aLatName, *aSubShapes.get()); - //TODO:fix - //aFromFace = aPrismAlgo->firstShape(); - //aToFace = aPrismAlgo->lastShape(); - } else if(std::dynamic_pointer_cast(*aSolidsAlgosIter)) { - std::shared_ptr aRevolAlgo = std::dynamic_pointer_cast(*aSolidsAlgosIter); - aSubShapes = aRevolAlgo->mapOfShapes(); - theResultBody->loadAndOrientGeneratedShapes(aRevolAlgo->makeShape().get(), *aFaceIter, GeomAPI_Shape::EDGE, aGenTag, - aLatName, *aSubShapes.get()); - aFromFace = aRevolAlgo->firstShape(); - aToFace = aRevolAlgo->lastShape(); + // If we have compsolids then cut with not used solids all others. + if(!aShapesToAdd.empty()) { + std::shared_ptr aCutAlgo(new GeomAlgoAPI_Boolean(aSolidsToFuse, + aShapesToAdd, + GeomAlgoAPI_Boolean::BOOL_CUT)); + if(aCutAlgo->isDone() && GeomAlgoAPI_ShapeTools::volume(aCutAlgo->shape()) > 1.e-27) { + aSolidsToFuse.clear(); + aSolidsToFuse.push_back(aCutAlgo->shape()); + aMakeShapeList->appendAlgo(aCutAlgo); + } } - //Insert bottom face - if(!aFromFace->isNull()) { - if(aSubShapes->isBound(aFromFace)) { - aFromFace = aSubShapes->find(aFromFace); + // Fuse all objects and all tools. + 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_Boolean::BOOL_FUSE)); + + // Checking that the algorithm worked properly. + if(!aFuseAlgo->isDone() || aFuseAlgo->shape()->isNull() || !aFuseAlgo->isValid()) { + myFeature->setError("Error: Boolean algorithm failed."); + return false; } - theResultBody->generated(aFromFace, aFrName, aFrTag); + + aFusedShape = aFuseAlgo->shape(); + aMakeShapeList->appendAlgo(aFuseAlgo); } - //Insert top face - if (!aToFace->isNull()) { - if (aSubShapes->isBound(aToFace)) { - aToFace = aSubShapes->find(aToFace); + // 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); } - theResultBody->generated(aToFace, aToName, aToTag); + + 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; + } + + aMakeShapeList->appendAlgo(aFillerAlgo); } + + theMakeShapes.push_back(aMakeShapeList); + break; } + } - theResultBody->loadAndOrientModifiedShapes(theAlgo.makeShape().get(), theBaseShape, GeomAPI_Shape::FACE, - aModTag, aModName, *theAlgo.mapOfShapes().get()); - theResultBody->loadDeletedShapes(theAlgo.makeShape().get(), theBaseShape, GeomAPI_Shape::FACE, aDelTag); + return true; +} - for(ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++) { - theResultBody->loadAndOrientModifiedShapes(theAlgo.makeShape().get(), *anIter, GeomAPI_Shape::FACE, - aModTag, aModName, *theAlgo.mapOfShapes().get()); - theResultBody->loadDeletedShapes(theAlgo.makeShape().get(), *anIter, GeomAPI_Shape::FACE, aDelTag); +//================================================================================================= +void FeaturesPlugin_CompositeBoolean::storeModificationHistory(ResultBodyPtr theResultBody, + const GeomShapePtr theObject, + const ListOfShape& theTools, + const std::shared_ptr theMakeShape) +{ + ListOfShape aTools = theTools; + aTools.push_back(theObject); + + std::string aName; + 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); + } +} + +//================================================================================================== +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); } } }