From a46f7249facdd4c19b7ec79c7f1c67cc22f5557d Mon Sep 17 00:00:00 2001 From: dbv Date: Wed, 3 Oct 2018 20:07:47 +0300 Subject: [PATCH] Some fixes. --- .../FeaturesPlugin_BooleanCommon.cpp | 211 +++++++++++++++++- .../FeaturesPlugin_CompositeBoolean.cpp | 45 +++- .../FeaturesPlugin_CompositeBoolean.h | 13 ++ .../FeaturesPlugin_Validators.cpp | 4 +- 4 files changed, 260 insertions(+), 13 deletions(-) diff --git a/src/FeaturesPlugin/FeaturesPlugin_BooleanCommon.cpp b/src/FeaturesPlugin/FeaturesPlugin_BooleanCommon.cpp index c180f725d..c8cee6318 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_BooleanCommon.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_BooleanCommon.cpp @@ -31,6 +31,9 @@ #include #include #include +#include +#include +#include //================================================================================================== @@ -53,6 +56,7 @@ void FeaturesPlugin_BooleanCommon::execute() { ListOfShape anObjects, aTools, aPlanes; std::map, ListOfShape> aCompSolidsObjects; + std::map, ListOfShape> aCompoundObjects; bool isSimpleMode = false; @@ -63,8 +67,7 @@ void FeaturesPlugin_BooleanCommon::execute() } // Getting objects. - AttributeSelectionListPtr anObjectsSelList = - selectionList(FeaturesPlugin_Boolean::OBJECT_LIST_ID()); + AttributeSelectionListPtr anObjectsSelList = selectionList(OBJECT_LIST_ID()); for (int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) { AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex); std::shared_ptr anObject = anObjectAttr->value(); @@ -73,22 +76,27 @@ void FeaturesPlugin_BooleanCommon::execute() } ResultPtr aContext = anObjectAttr->context(); ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext); - if (!isSimpleMode - && aResCompSolidPtr.get() - && aResCompSolidPtr->shape()->shapeType() == GeomAPI_Shape::COMPSOLID) { + if (aResCompSolidPtr.get()) + { std::shared_ptr aContextShape = aResCompSolidPtr->shape(); + GeomAPI_Shape::ShapeType aShapeType = aResCompSolidPtr->shape()->shapeType(); + std::map, ListOfShape>& aMap = + aShapeType == GeomAPI_Shape::COMPSOLID ? aCompSolidsObjects : aCompoundObjects; + std::map, ListOfShape>::iterator - anIt = aCompSolidsObjects.begin(); - for (; anIt != aCompSolidsObjects.end(); anIt++) { + anIt = aMap.begin(); + for (; anIt != aMap.end(); anIt++) { if (anIt->first->isEqual(aContextShape)) { - aCompSolidsObjects[anIt->first].push_back(anObject); + aMap[anIt->first].push_back(anObject); break; } } - if (anIt == aCompSolidsObjects.end()) { - aCompSolidsObjects[aContextShape].push_back(anObject); + if (anIt == aMap.end()) { + aMap[aContextShape].push_back(anObject); } - } else { + + } + else { anObjects.push_back(anObject); } } @@ -224,6 +232,187 @@ void FeaturesPlugin_BooleanCommon::execute() aResultIndex++; } } + + // Compsolids handling + for (std::map, ListOfShape>::iterator + anIt = aCompSolidsObjects.begin(); + anIt != aCompSolidsObjects.end(); + ++anIt) + { + std::shared_ptr aCompSolid = anIt->first; + ListOfShape& aUsedInOperationSolids = 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 aUsedIt = aUsedInOperationSolids.begin(); + for (; aUsedIt != aUsedInOperationSolids.end(); aUsedIt++) { + if (aSolidInCompSolid->isEqual(*aUsedIt)) { + break; + } + } + if (aUsedIt == aUsedInOperationSolids.end()) { + aNotUsedSolids.push_back(aSolidInCompSolid); + } + } + + std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); + std::shared_ptr aCommonAlgo( + new GeomAlgoAPI_Boolean(aUsedInOperationSolids, + aTools, + GeomAlgoAPI_Boolean::BOOL_COMMON)); + + // Checking that the algorithm worked properly. + if (!aCommonAlgo->isDone()) { + static const std::string aFeatureError = "Error: Boolean algorithm failed."; + setError(aFeatureError); + return; + } + if (aCommonAlgo->shape()->isNull()) { + static const std::string aShapeError = "Error: Resulting shape is Null."; + setError(aShapeError); + return; + } + if (!aCommonAlgo->isValid()) { + std::string aFeatureError = "Error: Resulting shape is not valid."; + setError(aFeatureError); + return; + } + + aMakeShapeList->appendAlgo(aCommonAlgo); + GeomAPI_DataMapOfShapeShape aMapOfShapes; + aMapOfShapes.merge(aCommonAlgo->mapOfSubShapes()); + GeomShapePtr aResultShape = aCommonAlgo->shape(); + + // Add result to not used solids from compsolid. + if (!aNotUsedSolids.empty()) { + ListOfShape aShapesToAdd = aNotUsedSolids; + aShapesToAdd.push_back(aCommonAlgo->shape()); + std::shared_ptr aFillerAlgo( + new GeomAlgoAPI_PaveFiller(aShapesToAdd, true)); + if (!aFillerAlgo->isDone()) { + std::string aFeatureError = "Error: PaveFiller algorithm failed."; + setError(aFeatureError); + return; + } + + aMakeShapeList->appendAlgo(aFillerAlgo); + aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes()); + aResultShape = aFillerAlgo->shape(); + } + + GeomAPI_ShapeIterator aShapeIt(aResultShape); + if (aShapeIt.more() || aResultShape->shapeType() == GeomAPI_Shape::VERTEX) + { + std::shared_ptr aResultBody = + document()->createBody(data(), aResultIndex); + + loadNamingDS(aResultBody, + aCompSolid, + aTools, + aResultShape, + *aMakeShapeList, + aMapOfShapes); + setResult(aResultBody, aResultIndex); + aResultIndex++; + } + } + + // Compounds handling + for (std::map, ListOfShape>::iterator + anIt = aCompoundObjects.begin(); + anIt != aCompoundObjects.end(); + ++anIt) + { + std::shared_ptr aCompound = anIt->first; + ListOfShape& aUsedInOperationShapes = anIt->second; + + // Collecting shapes from compound which will not be modified in boolean operation. + ListOfShape aNotUsedShapes; + for (GeomAPI_ShapeIterator aCompIt(aCompound); + aCompIt.more(); + aCompIt.next()) + { + std::shared_ptr aShapeInCompound = aCompIt.current(); + ListOfShape::iterator aUsedIt = aUsedInOperationShapes.begin(); + for (; aUsedIt != aUsedInOperationShapes.end(); aUsedIt++) { + if (aShapeInCompound->isEqual(*aUsedIt)) { + break; + } + } + if (aUsedIt == aUsedInOperationShapes.end()) { + aNotUsedShapes.push_back(aShapeInCompound); + } + } + + std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); + std::shared_ptr aCommonAlgo( + new GeomAlgoAPI_Boolean(aUsedInOperationShapes, + aTools, + GeomAlgoAPI_Boolean::BOOL_COMMON)); + + // Checking that the algorithm worked properly. + if (!aCommonAlgo->isDone()) { + static const std::string aFeatureError = "Error: Boolean algorithm failed."; + setError(aFeatureError); + return; + } + if (aCommonAlgo->shape()->isNull()) { + static const std::string aShapeError = "Error: Resulting shape is Null."; + setError(aShapeError); + return; + } + if (!aCommonAlgo->isValid()) { + std::string aFeatureError = "Error: Resulting shape is not valid."; + setError(aFeatureError); + return; + } + + aMakeShapeList->appendAlgo(aCommonAlgo); + GeomAPI_DataMapOfShapeShape aMapOfShapes; + aMapOfShapes.merge(aCommonAlgo->mapOfSubShapes()); + GeomShapePtr aResultShape = aCommonAlgo->shape(); + + // Add result to not used shape from compound. + if (!aNotUsedShapes.empty()) { + ListOfShape aShapesForResult = aNotUsedShapes; + if (aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) { + for (GeomAPI_ShapeIterator aResultIt(aResultShape); aResultIt.more(); aResultIt.next()) { + aShapesForResult.push_back(aResultIt.current()); + } + } + else { + aShapesForResult.push_back(aResultShape); + } + + if (aShapesForResult.size() == 1) { + aResultShape = aShapesForResult.front(); + } + else { + aResultShape = GeomAlgoAPI_CompoundBuilder::compound(aShapesForResult); + } + } + + GeomAPI_ShapeIterator aShapeIt(aResultShape); + if (aShapeIt.more() || aResultShape->shapeType() == GeomAPI_Shape::VERTEX) { + std::shared_ptr aResultBody = + document()->createBody(data(), aResultIndex); + + loadNamingDS(aResultBody, + aCompound, + aTools, + aResultShape, + *aMakeShapeList, + aMapOfShapes); + setResult(aResultBody, aResultIndex); + aResultIndex++; + } + } + } // remove the rest results if there were produced in the previous pass diff --git a/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp b/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp index 9cdf2b7cc..6f0d65f4d 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -69,6 +70,8 @@ void FeaturesPlugin_CompositeBoolean::executeCompositeBoolean() // 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(); @@ -97,11 +100,24 @@ void FeaturesPlugin_CompositeBoolean::executeCompositeBoolean() int aModTag = aTag; storeModificationHistory(aResultBody, *aBoolObjIt, aTools, *aBoolMSIt, aModTag); + + ResultBaseAlgo aRBA; + aRBA.resultBody = aResultBody; + aRBA.baseShape = *aBoolObjIt; + aRBA.makeShape = *aBoolMSIt; + aRBA.delTag = aModTag; + aResultBaseAlgoList.push_back(aRBA); + aResultShapesList.push_back((*aBoolMSIt)->shape()); } myFeature->setResult(aResultBody, aResultIndex++); } + // 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); } @@ -396,6 +412,33 @@ void FeaturesPlugin_CompositeBoolean::storeModificationHistory(ResultBodyPtr the theResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), *anIt, (*anIt)->shapeType() == GeomAPI_Shape::EDGE ? GeomAPI_Shape::EDGE : GeomAPI_Shape::FACE, aTag, aName, *aMap.get(), false, false, true); - theResultBody->loadDeletedShapes(theMakeShape.get(), *anIt, 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.get(), + aRCA.baseShape, + GeomAPI_Shape::FACE, + aRCA.delTag, + theResultShapesCompound); + + for (ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++) + { + aRCA.resultBody->loadDeletedShapes(aRCA.makeShape.get(), + *anIter, + GeomAPI_Shape::FACE, + aRCA.delTag, + theResultShapesCompound); + } } } diff --git a/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.h b/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.h index 1e6a28175..3f07d107b 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.h +++ b/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.h @@ -50,6 +50,14 @@ public: /// Creates a new part document if needed. FEATURESPLUGIN_EXPORT virtual void executeCompositeBoolean(); +protected: + struct ResultBaseAlgo { + ResultBodyPtr resultBody; + GeomShapePtr baseShape; + std::shared_ptr makeShape; + int delTag; + }; + protected: FeaturesPlugin_CompositeBoolean(){}; @@ -82,6 +90,11 @@ protected: const std::shared_ptr theMakeShape, int& theTag); + /// Stores deleted shapes. + void storeDeletedShapes(std::vector& theResultBaseAlgoList, + const ListOfShape& theTools, + const GeomShapePtr theResultShapesCompound); + protected: ModelAPI_Feature* myFeature; OperationType myOperationType; diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp index 1b8c4d13e..d46d29316 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp @@ -1688,8 +1688,10 @@ bool FeaturesPlugin_ValidatorBooleanCommonSelection::isValid( } std::shared_ptr aShape = anAttrSelection->value(); GeomShapePtr aContextShape; - if (!aShape.get() && aContext.get()) { + if (aContext.get()) { aContextShape = aContext->shape(); + } + if (!aShape.get()) { aShape = aContextShape; } if (!aShape.get()) { -- 2.30.2