From c458464ec86d4031ff1a476d2b368146bc3c932a Mon Sep 17 00:00:00 2001 From: azv Date: Wed, 5 Dec 2018 13:48:25 +0300 Subject: [PATCH] [Code coverage FeaturesPlugin]: Move Fill feature to separate class --- src/FeaturesPlugin/CMakeLists.txt | 1 + src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp | 591 ------------------ src/FeaturesPlugin/FeaturesPlugin_Boolean.h | 4 - .../FeaturesPlugin_BooleanFill.cpp | 279 +++++++++ .../FeaturesPlugin_BooleanFill.h | 5 +- 5 files changed, 284 insertions(+), 596 deletions(-) create mode 100644 src/FeaturesPlugin/FeaturesPlugin_BooleanFill.cpp diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index b482ba091..b75d4a17c 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -73,6 +73,7 @@ SET(PROJECT_SOURCES FeaturesPlugin_BooleanFuse.cpp FeaturesPlugin_BooleanCommon.cpp FeaturesPlugin_BooleanSmash.cpp + FeaturesPlugin_BooleanFill.cpp FeaturesPlugin_Intersection.cpp FeaturesPlugin_Partition.cpp FeaturesPlugin_Pipe.cpp diff --git a/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp b/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp index 63a7834b0..81848ff11 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp @@ -83,597 +83,6 @@ FeaturesPlugin_Boolean::OperationType FeaturesPlugin_Boolean::operationType() return myOperationType; } -//================================================================================================= -void FeaturesPlugin_Boolean::execute() -{ - ListOfShape anObjects, aTools, anEdgesAndFaces, aPlanes; - std::map, ListOfShape> aCompSolidsObjects; - - // Getting objects. - AttributeSelectionListPtr anObjectsSelList = - selectionList(FeaturesPlugin_Boolean::OBJECT_LIST_ID()); - for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) { - AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex); - std::shared_ptr anObject = anObjectAttr->value(); - if(!anObject.get()) { - return; - } - ResultPtr aContext = anObjectAttr->context(); - ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext); - if(aResCompSolidPtr.get() - && aResCompSolidPtr->shape()->shapeType() == GeomAPI_Shape::COMPSOLID) { - std::shared_ptr aContextShape = aResCompSolidPtr->shape(); - std::map, ListOfShape>::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); - } - } else { - if(myOperationType != BOOL_FILL - && (anObject->shapeType() == GeomAPI_Shape::EDGE - || anObject->shapeType() == GeomAPI_Shape::FACE)) - { - anEdgesAndFaces.push_back(anObject); - } - else - { - anObjects.push_back(anObject); - } - } - } - - // Getting tools. - AttributeSelectionListPtr aToolsSelList = selectionList(FeaturesPlugin_Boolean::TOOL_LIST_ID()); - for(int aToolsIndex = 0; aToolsIndex < aToolsSelList->size(); aToolsIndex++) { - AttributeSelectionPtr aToolAttr = aToolsSelList->value(aToolsIndex); - GeomShapePtr aTool = aToolAttr->value(); - if(!aTool.get()) { - // It could be a construction plane. - ResultPtr aContext = aToolAttr->context(); - aPlanes.push_back(aToolAttr->context()->shape()); - } - else if (myOperationType != BOOL_FILL - && (aTool->shapeType() == GeomAPI_Shape::EDGE - || aTool->shapeType() == GeomAPI_Shape::FACE)) - { - anEdgesAndFaces.push_back(aTool); - } else { - aTools.push_back(aTool); - } - } - - int aResultIndex = 0; - - switch(myOperationType) { - case BOOL_CUT: - case BOOL_COMMON: - case BOOL_FILL: { - if((anObjects.empty() && aCompSolidsObjects.empty()) - || (aTools.empty() && aPlanes.empty())) { - std::string aFeatureError = "Error: Not enough objects for boolean operation."; - setError(aFeatureError); - return; - } - - // For solids cut each object with all tools. - for(ListOfShape::iterator - anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end(); anObjectsIt++) { - std::shared_ptr anObject = *anObjectsIt; - ListOfShape aListWithObject; - aListWithObject.push_back(anObject); - std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); - std::shared_ptr aBoolAlgo; - GeomShapePtr aResShape; - - switch(myOperationType) { - case BOOL_CUT: { - aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aListWithObject, - aTools, - GeomAlgoAPI_Boolean::BOOL_CUT)); - aResShape = aBoolAlgo->shape(); - break; - } - case BOOL_COMMON: { - aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aListWithObject, - aTools, - GeomAlgoAPI_Boolean::BOOL_COMMON)); - aResShape = aBoolAlgo->shape(); - break; - } - case BOOL_FILL: { - std::list > aBoundingPoints = - GeomAlgoAPI_ShapeTools::getBoundingBox(aListWithObject, 1.0); - - // Resize planes. - ListOfShape aToolsWithPlanes = aTools; - for(ListOfShape::const_iterator anIt = aPlanes.cbegin(); - anIt != aPlanes.cend(); - ++anIt) - { - GeomShapePtr aPlane = *anIt; - GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints); - std::shared_ptr aMkShCustom( - new GeomAlgoAPI_MakeShapeCustom); - aMkShCustom->addModified(aPlane, aTool); - aMakeShapeList->appendAlgo(aMkShCustom); - aToolsWithPlanes.push_back(aTool); - } - - aBoolAlgo.reset(new GeomAlgoAPI_Partition(aListWithObject, aToolsWithPlanes)); - aResShape = aBoolAlgo->shape(); - if (aResShape.get() && aResShape->shapeType() == GeomAPI_Shape::COMPOUND) { - int aSubResultsNb = 0; - GeomAPI_ShapeIterator anIt(aResShape); - for(; anIt.more(); anIt.next()) { - ++aSubResultsNb; - } - if(aSubResultsNb == 1) { - anIt.init(aResShape); - if(anIt.more()) { - aResShape = anIt.current(); - } - } - } - break; - } - } - - // Checking that the algorithm worked properly. - if(!aBoolAlgo->isDone()) { - static const std::string aFeatureError = "Error: Boolean algorithm failed."; - setError(aFeatureError); - return; - } - if(aResShape->isNull()) { - static const std::string aShapeError = "Error: Resulting shape is Null."; - setError(aShapeError); - return; - } - if(!aBoolAlgo->isValid()) { - std::string aFeatureError = "Error: Resulting shape is not valid."; - setError(aFeatureError); - return; - } - - aMakeShapeList->appendAlgo(aBoolAlgo); - - if(GeomAlgoAPI_ShapeTools::volume(aResShape) > 1.e-27 - || (myOperationType != BOOL_CUT && myOperationType != BOOL_COMMON)) - { - std::shared_ptr aResultBody = - document()->createBody(data(), aResultIndex); - - ListOfShape aUsedTools = aTools; - if (myOperationType == BOOL_FILL) { - aUsedTools.insert(aUsedTools.end(), aPlanes.begin(), aPlanes.end()); - } - - loadNamingDS(aResultBody, anObject, aUsedTools, aResShape, aMakeShapeList); - setResult(aResultBody, aResultIndex); - 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 anIt = aUsedInOperationSolids.begin(); - for(; anIt != aUsedInOperationSolids.end(); anIt++) { - if(aSolidInCompSolid->isEqual(*anIt)) { - break; - } - } - if(anIt == aUsedInOperationSolids.end()) { - aNotUsedSolids.push_back(aSolidInCompSolid); - } - } - - std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); - std::shared_ptr aBoolAlgo; - - switch(myOperationType) { - case BOOL_CUT: { - aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aUsedInOperationSolids, - aTools, - GeomAlgoAPI_Boolean::BOOL_CUT)); - break; - } - case BOOL_COMMON: { - aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aUsedInOperationSolids, - aTools, - GeomAlgoAPI_Boolean::BOOL_COMMON)); - break; - } - case BOOL_FILL: { - std::list > aBoundingPoints = - GeomAlgoAPI_ShapeTools::getBoundingBox(aUsedInOperationSolids, 1.0); - - // Resize planes. - ListOfShape aToolsWithPlanes = aTools; - for(ListOfShape::const_iterator anIt = aPlanes.cbegin(); - anIt != aPlanes.cend(); - ++anIt) - { - GeomShapePtr aPlane = *anIt; - GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints); - std::shared_ptr aMkShCustom( - new GeomAlgoAPI_MakeShapeCustom); - aMkShCustom->addModified(aPlane, aTool); - aMakeShapeList->appendAlgo(aMkShCustom); - aToolsWithPlanes.push_back(aTool); - } - - aBoolAlgo.reset(new GeomAlgoAPI_Partition(aUsedInOperationSolids, aToolsWithPlanes)); - break; - } - } - - // Checking that the algorithm worked properly. - if(!aBoolAlgo->isDone()) { - static const std::string aFeatureError = "Error: Boolean algorithm failed."; - setError(aFeatureError); - return; - } - if(aBoolAlgo->shape()->isNull()) { - static const std::string aShapeError = "Error: Resulting shape is Null."; - setError(aShapeError); - return; - } - if(!aBoolAlgo->isValid()) { - std::string aFeatureError = "Error: Resulting shape is not valid."; - setError(aFeatureError); - return; - } - - aMakeShapeList->appendAlgo(aBoolAlgo); - GeomShapePtr aResultShape = aBoolAlgo->shape(); - - // Add result to not used solids from compsolid. - if(!aNotUsedSolids.empty()) { - ListOfShape aShapesToAdd = aNotUsedSolids; - aShapesToAdd.push_back(aBoolAlgo->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); - aResultShape = aFillerAlgo->shape(); - } - - if(GeomAlgoAPI_ShapeTools::volume(aResultShape) > 1.e-27 - || (myOperationType != BOOL_CUT && myOperationType != BOOL_COMMON)) - { - std::shared_ptr aResultBody = - document()->createBody(data(), aResultIndex); - - ListOfShape aUsedTools = aTools; - if (myOperationType == BOOL_FILL) { - aUsedTools.insert(aUsedTools.end(), aPlanes.begin(), aPlanes.end()); - } - - loadNamingDS(aResultBody, - aCompSolid, - aUsedTools, - aResultShape, - aMakeShapeList); - setResult(aResultBody, aResultIndex); - aResultIndex++; - } - } - break; - } - case BOOL_FUSE: { - if((anObjects.size() + aTools.size() + - aCompSolidsObjects.size() + anEdgesAndFaces.size()) < 2) { - std::string aFeatureError = "Error: Not enough objects for boolean operation."; - setError(aFeatureError); - 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, 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()); - - // 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++) { - if(aSolidInCompSolid->isEqual(*anIt)) { - break; - } - } - if(anIt == aUsedInOperationSolids.end()) { - aShapesToAdd.push_back(aSolidInCompSolid); - } - } - } - - ListOfShape anOriginalShapes = aSolidsToFuse; - anOriginalShapes.insert(anOriginalShapes.end(), aShapesToAdd.begin(), aShapesToAdd.end()); - - // Cut edges and faces(if we have any) with solids. - std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); - std::shared_ptr aCuttedEdgesAndFaces; - if(!anEdgesAndFaces.empty()) { - std::shared_ptr aCutAlgo(new GeomAlgoAPI_Boolean(anEdgesAndFaces, - anOriginalShapes, GeomAlgoAPI_Boolean::BOOL_CUT)); - if(aCutAlgo->isDone()) { - aCuttedEdgesAndFaces = aCutAlgo->shape(); - aMakeShapeList->appendAlgo(aCutAlgo); - } - } - anOriginalShapes.insert(anOriginalShapes.end(), anEdgesAndFaces.begin(), - anEdgesAndFaces.end()); - - // If we have compsolids then cut with not used solids all others. - if(!aShapesToAdd.empty()) { - aSolidsToFuse.clear(); - for(ListOfShape::iterator - anIt = anOriginalShapes.begin(); anIt != anOriginalShapes.end(); anIt++) { - ListOfShape aOneObjectList; - aOneObjectList.push_back(*anIt); - std::shared_ptr aCutAlgo( - new GeomAlgoAPI_Boolean(aOneObjectList, aShapesToAdd, GeomAlgoAPI_Boolean::BOOL_CUT)); - - if(GeomAlgoAPI_ShapeTools::volume(aCutAlgo->shape()) > 1.e-27) { - aSolidsToFuse.push_back(aCutAlgo->shape()); - aMakeShapeList->appendAlgo(aCutAlgo); - } - } - } - - if(!aSolidsToFuse.empty()) { - anObjects.clear(); - anObjects.push_back(aSolidsToFuse.back()); - aSolidsToFuse.pop_back(); - aTools = aSolidsToFuse; - } - - // Fuse all objects and all tools. - std::shared_ptr aShape; - if(anObjects.size() == 1 && aTools.empty()) { - aShape = anObjects.front(); - } else if(anObjects.empty() && aTools.size() == 1) { - aShape = aTools.front(); - } else if((anObjects.size() + aTools.size()) > 1){ - std::shared_ptr aFuseAlgo(new GeomAlgoAPI_Boolean(anObjects, - aTools, - GeomAlgoAPI_Boolean::BOOL_FUSE)); - - // Checking that the algorithm worked properly. - if(!aFuseAlgo->isDone()) { - static const std::string aFeatureError = "Error: Boolean algorithm failed."; - setError(aFeatureError); - return; - } - if(aFuseAlgo->shape()->isNull()) { - static const std::string aShapeError = "Error: Resulting shape is Null."; - setError(aShapeError); - return; - } - if(!aFuseAlgo->isValid()) { - std::string aFeatureError = "Error: Resulting shape is not valid."; - setError(aFeatureError); - return; - } - - aShape = aFuseAlgo->shape(); - aMakeShapeList->appendAlgo(aFuseAlgo); - } - - // Combine result with not used solids from compsolid and edges and faces (if we have any). - if(aCuttedEdgesAndFaces.get() && !aCuttedEdgesAndFaces->isNull()) { - aShapesToAdd.push_back(aCuttedEdgesAndFaces); - } else { - aShapesToAdd.insert(aShapesToAdd.end(), anEdgesAndFaces.begin(), anEdgesAndFaces.end()); - } - if(!aShapesToAdd.empty()) { - if(aShape.get()) { - aShapesToAdd.push_back(aShape); - } - std::shared_ptr aFillerAlgo( - new GeomAlgoAPI_PaveFiller(aShapesToAdd, true)); - if(!aFillerAlgo->isDone()) { - std::string aFeatureError = "Error: PaveFiller algorithm failed."; - setError(aFeatureError); - return; - } - if(aFillerAlgo->shape()->isNull()) { - static const std::string aShapeError = "Error: Resulting shape is Null."; - setError(aShapeError); - return; - } - if(!aFillerAlgo->isValid()) { - std::string aFeatureError = "Error: Resulting shape is not valid."; - setError(aFeatureError); - return; - } - - aShape = aFillerAlgo->shape(); - aMakeShapeList->appendAlgo(aFillerAlgo); - } - - std::shared_ptr aBackShape = anOriginalShapes.back(); - anOriginalShapes.pop_back(); - std::shared_ptr aResultBody = - document()->createBody(data(), aResultIndex); - loadNamingDS(aResultBody, aBackShape, anOriginalShapes, - aShape, aMakeShapeList); - setResult(aResultBody, aResultIndex); - aResultIndex++; - break; - } - case BOOL_SMASH: { - if((anObjects.empty() && aCompSolidsObjects.empty()) || aTools.empty()) { - std::string aFeatureError = "Error: Not enough objects for boolean operation."; - setError(aFeatureError); - return; - } - - // List of original solids for naming. - ListOfShape anOriginalShapes; - anOriginalShapes.insert(anOriginalShapes.end(), anObjects.begin(), anObjects.end()); - anOriginalShapes.insert(anOriginalShapes.end(), aTools.begin(), aTools.end()); - - // Collecting all solids which will be smashed. - ListOfShape aShapesToSmash; - aShapesToSmash.insert(aShapesToSmash.end(), anObjects.begin(), anObjects.end()); - - // Collecting solids from compsolids which will not be modified in - // boolean operation and will be added to result. - ListOfShape aShapesToAdd; - for(std::map, ListOfShape>::iterator - anIt = aCompSolidsObjects.begin(); - anIt != aCompSolidsObjects.end(); anIt++) { - std::shared_ptr aCompSolid = anIt->first; - ListOfShape& aUsedInOperationSolids = anIt->second; - anOriginalShapes.push_back(aCompSolid); - aShapesToSmash.insert(aShapesToSmash.end(), aUsedInOperationSolids.begin(), - aUsedInOperationSolids.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++) { - if(aSolidInCompSolid->isEqual(*anIt)) { - break; - } - } - if(anIt == aUsedInOperationSolids.end()) { - aShapesToAdd.push_back(aSolidInCompSolid); - } - } - } - - std::shared_ptr aMakeShapeList; - if(!aShapesToAdd.empty()) { - // Cut objects with not used solids. - std::shared_ptr anObjectsCutAlgo(new GeomAlgoAPI_Boolean( - aShapesToSmash, - aShapesToAdd, - GeomAlgoAPI_Boolean::BOOL_CUT)); - - if(GeomAlgoAPI_ShapeTools::volume(anObjectsCutAlgo->shape()) > 1.e-27) { - aShapesToSmash.clear(); - aShapesToSmash.push_back(anObjectsCutAlgo->shape()); - aMakeShapeList->appendAlgo(anObjectsCutAlgo); - } - - // Cut tools with not used solids. - std::shared_ptr aToolsCutAlgo(new GeomAlgoAPI_Boolean(aTools, - aShapesToAdd, - GeomAlgoAPI_Boolean::BOOL_CUT)); - - if(GeomAlgoAPI_ShapeTools::volume(aToolsCutAlgo->shape()) > 1.e-27) { - aTools.clear(); - aTools.push_back(aToolsCutAlgo->shape()); - aMakeShapeList->appendAlgo(aToolsCutAlgo); - } - } - - // Cut objects with tools. - std::shared_ptr aBoolAlgo(new GeomAlgoAPI_Boolean(aShapesToSmash, - aTools, - GeomAlgoAPI_Boolean::BOOL_CUT)); - - // Checking that the algorithm worked properly. - if(!aBoolAlgo->isDone()) { - static const std::string aFeatureError = "Error: Boolean algorithm failed."; - setError(aFeatureError); - return; - } - if(aBoolAlgo->shape()->isNull()) { - static const std::string aShapeError = "Error: Resulting shape is Null."; - setError(aShapeError); - return; - } - if(!aBoolAlgo->isValid()) { - std::string aFeatureError = "Error: Resulting shape is not valid."; - setError(aFeatureError); - return; - } - aMakeShapeList->appendAlgo(aBoolAlgo); - - // Put all (cut result, tools and not used solids) to PaveFiller. - aShapesToAdd.push_back(aBoolAlgo->shape()); - aShapesToAdd.insert(aShapesToAdd.end(), aTools.begin(), aTools.end()); - - std::shared_ptr aFillerAlgo(new GeomAlgoAPI_PaveFiller(aShapesToAdd, - true)); - if(!aFillerAlgo->isDone()) { - std::string aFeatureError = "Error: PaveFiller algorithm failed."; - setError(aFeatureError); - return; - } - if(aFillerAlgo->shape()->isNull()) { - static const std::string aShapeError = "Error: Resulting shape is Null."; - setError(aShapeError); - return; - } - if(!aFillerAlgo->isValid()) { - std::string aFeatureError = "Error: Resulting shape is not valid."; - setError(aFeatureError); - return; - } - - std::shared_ptr aShape = aFillerAlgo->shape(); - aMakeShapeList->appendAlgo(aFillerAlgo); - - std::shared_ptr aFrontShape = anOriginalShapes.front(); - anOriginalShapes.pop_front(); - std::shared_ptr aResultBody = - document()->createBody(data(), aResultIndex); - loadNamingDS(aResultBody, aFrontShape, anOriginalShapes, aShape, aMakeShapeList); - setResult(aResultBody, aResultIndex); - aResultIndex++; - - break; - } - default: { - std::string anOperationError = "Error: Wrong type of operation"; - setError(anOperationError); - return; - } - } - // remove the rest results if there were produced in the previous pass - removeResults(aResultIndex); -} - //================================================================================================= void FeaturesPlugin_Boolean::loadNamingDS(std::shared_ptr theResultBody, const std::shared_ptr theBaseShape, diff --git a/src/FeaturesPlugin/FeaturesPlugin_Boolean.h b/src/FeaturesPlugin/FeaturesPlugin_Boolean.h index 95db06460..618f9e18e 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Boolean.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Boolean.h @@ -59,9 +59,6 @@ public: /// \return boolean operation type. FEATURESPLUGIN_EXPORT OperationType operationType(); - /// Creates a new part document if needed. - FEATURESPLUGIN_EXPORT virtual void execute(); - /// Request for initialization of data model of the feature: adding all attributes. FEATURESPLUGIN_EXPORT virtual void initAttributes(); @@ -70,7 +67,6 @@ protected: /// Use plugin manager for features creation. FeaturesPlugin_Boolean(const OperationType theOperationType); -private: std::shared_ptr getShape(const std::string& theAttrName); /// Load Naming data structure of the feature to the document diff --git a/src/FeaturesPlugin/FeaturesPlugin_BooleanFill.cpp b/src/FeaturesPlugin/FeaturesPlugin_BooleanFill.cpp new file mode 100644 index 000000000..1bf980942 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_BooleanFill.cpp @@ -0,0 +1,279 @@ +// 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_BooleanFill.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +//================================================================================================= +FeaturesPlugin_BooleanFill::FeaturesPlugin_BooleanFill() + : FeaturesPlugin_Boolean(FeaturesPlugin_Boolean::BOOL_FILL) +{ +} + +//================================================================================================= +void FeaturesPlugin_BooleanFill::execute() +{ + ListOfShape anObjects, aTools, anEdgesAndFaces, aPlanes; + std::map, ListOfShape> aCompSolidsObjects; + + // Getting objects. + AttributeSelectionListPtr anObjectsSelList = + selectionList(FeaturesPlugin_Boolean::OBJECT_LIST_ID()); + for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) { + AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex); + std::shared_ptr anObject = anObjectAttr->value(); + if(!anObject.get()) { + return; + } + ResultPtr aContext = anObjectAttr->context(); + ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext); + if(aResCompSolidPtr.get() + && aResCompSolidPtr->shape()->shapeType() == GeomAPI_Shape::COMPSOLID) { + std::shared_ptr aContextShape = aResCompSolidPtr->shape(); + std::map, ListOfShape>::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); + } + } else { + anObjects.push_back(anObject); + } + } + + // Getting tools. + AttributeSelectionListPtr aToolsSelList = selectionList(FeaturesPlugin_Boolean::TOOL_LIST_ID()); + for(int aToolsIndex = 0; aToolsIndex < aToolsSelList->size(); aToolsIndex++) { + AttributeSelectionPtr aToolAttr = aToolsSelList->value(aToolsIndex); + GeomShapePtr aTool = aToolAttr->value(); + if(!aTool.get()) { + // It could be a construction plane. + ResultPtr aContext = aToolAttr->context(); + aPlanes.push_back(aToolAttr->context()->shape()); + } + else { + aTools.push_back(aTool); + } + } + + int aResultIndex = 0; + + if ((anObjects.empty() && aCompSolidsObjects.empty()) + || (aTools.empty() && aPlanes.empty())) { + std::string aFeatureError = "Error: Not enough objects for boolean operation."; + setError(aFeatureError); + return; + } + + // For solids cut each object with all tools. + for(ListOfShape::iterator + anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end(); anObjectsIt++) { + std::shared_ptr anObject = *anObjectsIt; + ListOfShape aListWithObject; + aListWithObject.push_back(anObject); + std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); + std::shared_ptr aBoolAlgo; + GeomShapePtr aResShape; + + std::list > aBoundingPoints = + GeomAlgoAPI_ShapeTools::getBoundingBox(aListWithObject, 1.0); + + // Resize planes. + ListOfShape aToolsWithPlanes = aTools; + for(ListOfShape::const_iterator anIt = aPlanes.cbegin(); + anIt != aPlanes.cend(); + ++anIt) + { + GeomShapePtr aPlane = *anIt; + GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints); + std::shared_ptr aMkShCustom( + new GeomAlgoAPI_MakeShapeCustom); + aMkShCustom->addModified(aPlane, aTool); + aMakeShapeList->appendAlgo(aMkShCustom); + aToolsWithPlanes.push_back(aTool); + } + + aBoolAlgo.reset(new GeomAlgoAPI_Partition(aListWithObject, aToolsWithPlanes)); + aResShape = aBoolAlgo->shape(); + if (aResShape.get() && aResShape->shapeType() == GeomAPI_Shape::COMPOUND) { + int aSubResultsNb = 0; + GeomAPI_ShapeIterator anIt(aResShape); + for(; anIt.more(); anIt.next()) { + ++aSubResultsNb; + } + if(aSubResultsNb == 1) { + anIt.init(aResShape); + if(anIt.more()) { + aResShape = anIt.current(); + } + } + } + + // Checking that the algorithm worked properly. + if(!aBoolAlgo->isDone()) { + static const std::string aFeatureError = "Error: Boolean algorithm failed."; + setError(aFeatureError); + return; + } + if(aResShape->isNull()) { + static const std::string aShapeError = "Error: Resulting shape is Null."; + setError(aShapeError); + return; + } + if(!aBoolAlgo->isValid()) { + std::string aFeatureError = "Error: Resulting shape is not valid."; + setError(aFeatureError); + return; + } + + aMakeShapeList->appendAlgo(aBoolAlgo); + + std::shared_ptr aResultBody = + document()->createBody(data(), aResultIndex); + + ListOfShape aUsedTools = aTools; + aUsedTools.insert(aUsedTools.end(), aPlanes.begin(), aPlanes.end()); + + loadNamingDS(aResultBody, anObject, aUsedTools, aResShape, aMakeShapeList); + setResult(aResultBody, aResultIndex); + 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 anIt = aUsedInOperationSolids.begin(); + for(; anIt != aUsedInOperationSolids.end(); anIt++) { + if(aSolidInCompSolid->isEqual(*anIt)) { + break; + } + } + if(anIt == aUsedInOperationSolids.end()) { + aNotUsedSolids.push_back(aSolidInCompSolid); + } + } + + std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); + std::shared_ptr aBoolAlgo; + + std::list > aBoundingPoints = + GeomAlgoAPI_ShapeTools::getBoundingBox(aUsedInOperationSolids, 1.0); + + // Resize planes. + ListOfShape aToolsWithPlanes = aTools; + for(ListOfShape::const_iterator anIt = aPlanes.cbegin(); + anIt != aPlanes.cend(); + ++anIt) + { + GeomShapePtr aPlane = *anIt; + GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints); + std::shared_ptr aMkShCustom( + new GeomAlgoAPI_MakeShapeCustom); + aMkShCustom->addModified(aPlane, aTool); + aMakeShapeList->appendAlgo(aMkShCustom); + aToolsWithPlanes.push_back(aTool); + } + + aBoolAlgo.reset(new GeomAlgoAPI_Partition(aUsedInOperationSolids, aToolsWithPlanes)); + + // Checking that the algorithm worked properly. + if(!aBoolAlgo->isDone()) { + static const std::string aFeatureError = "Error: Boolean algorithm failed."; + setError(aFeatureError); + return; + } + if(aBoolAlgo->shape()->isNull()) { + static const std::string aShapeError = "Error: Resulting shape is Null."; + setError(aShapeError); + return; + } + if(!aBoolAlgo->isValid()) { + std::string aFeatureError = "Error: Resulting shape is not valid."; + setError(aFeatureError); + return; + } + + aMakeShapeList->appendAlgo(aBoolAlgo); + GeomShapePtr aResultShape = aBoolAlgo->shape(); + + // Add result to not used solids from compsolid. + if(!aNotUsedSolids.empty()) { + ListOfShape aShapesToAdd = aNotUsedSolids; + aShapesToAdd.push_back(aBoolAlgo->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); + aResultShape = aFillerAlgo->shape(); + } + + std::shared_ptr aResultBody = + document()->createBody(data(), aResultIndex); + + ListOfShape aUsedTools = aTools; + aUsedTools.insert(aUsedTools.end(), aPlanes.begin(), aPlanes.end()); + + loadNamingDS(aResultBody, + aCompSolid, + aUsedTools, + aResultShape, + aMakeShapeList); + setResult(aResultBody, aResultIndex); + aResultIndex++; + } + + // remove the rest results if there were produced in the previous pass + removeResults(aResultIndex); +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_BooleanFill.h b/src/FeaturesPlugin/FeaturesPlugin_BooleanFill.h index b4cb73b94..88b53213d 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_BooleanFill.h +++ b/src/FeaturesPlugin/FeaturesPlugin_BooleanFill.h @@ -44,10 +44,13 @@ public: return MY_KIND; } + /// Creates a new part document if needed. + FEATURESPLUGIN_EXPORT virtual void execute(); + public: /// Use plugin manager for features creation. - FeaturesPlugin_BooleanFill(): FeaturesPlugin_Boolean(BOOL_FILL) {}; + FeaturesPlugin_BooleanFill(); }; -- 2.39.2