From: dbv Date: Wed, 9 Mar 2016 12:06:25 +0000 (+0300) Subject: Boolean Smash feature X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=49bb50cdc4ba4340877e84a50738a2803f1b77b9;p=modules%2Fshaper.git Boolean Smash feature --- diff --git a/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp b/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp index 7360f443c..701017b52 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp @@ -71,7 +71,7 @@ void FeaturesPlugin_Boolean::execute() ModelAPI_AttributeInteger>(data()->attribute(FeaturesPlugin_Boolean::TYPE_ID())); if (!aTypeAttr) return; - GeomAlgoAPI_Boolean::OperationType aType = (GeomAlgoAPI_Boolean::OperationType)aTypeAttr->value(); + OperationType aType = (FeaturesPlugin_Boolean::OperationType)aTypeAttr->value(); ListOfShape anObjects, aTools, anEdgesAndFaces; std::map, ListOfShape> aCompSolidsObjects; @@ -127,8 +127,8 @@ void FeaturesPlugin_Boolean::execute() int aResultIndex = 0; switch(aType) { - case GeomAlgoAPI_Boolean::BOOL_CUT: - case GeomAlgoAPI_Boolean::BOOL_COMMON:{ + case BOOL_CUT: + case BOOL_COMMON:{ if((anObjects.empty() && aCompSolidsObjects.empty()) || aTools.empty()) { std::string aFeatureError = "Error: Not enough objects for boolean operation."; setError(aFeatureError); @@ -140,7 +140,7 @@ void FeaturesPlugin_Boolean::execute() std::shared_ptr anObject = *anObjectsIt; ListOfShape aListWithObject; aListWithObject.push_back(anObject); - GeomAlgoAPI_Boolean aBoolAlgo(aListWithObject, aTools, aType); + GeomAlgoAPI_Boolean aBoolAlgo(aListWithObject, aTools, (GeomAlgoAPI_Boolean::OperationType)aType); // Checking that the algorithm worked properly. if(!aBoolAlgo.isDone()) { @@ -188,7 +188,9 @@ void FeaturesPlugin_Boolean::execute() } } - std::shared_ptr aBoolAlgo(new GeomAlgoAPI_Boolean(aUsedInOperationSolids, aTools, aType)); + std::shared_ptr aBoolAlgo(new GeomAlgoAPI_Boolean(aUsedInOperationSolids, + aTools, + (GeomAlgoAPI_Boolean::OperationType)aType)); // Checking that the algorithm worked properly. if(!aBoolAlgo->isDone()) { @@ -234,7 +236,7 @@ void FeaturesPlugin_Boolean::execute() } break; } - case GeomAlgoAPI_Boolean::BOOL_FUSE: { + 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); @@ -316,7 +318,9 @@ void FeaturesPlugin_Boolean::execute() } 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, aType)); + std::shared_ptr aFuseAlgo(new GeomAlgoAPI_Boolean(anObjects, + aTools, + (GeomAlgoAPI_Boolean::OperationType)aType)); // Checking that the algorithm worked properly. if(!aFuseAlgo->isDone()) { @@ -380,6 +384,132 @@ void FeaturesPlugin_Boolean::execute() 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); + } + } + } + + GeomAlgoAPI_MakeShapeList aMakeShapeList; + GeomAPI_DataMapOfShapeShape aMapOfShapes; + 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-7) { + aShapesToSmash.clear(); + aShapesToSmash.push_back(anObjectsCutAlgo->shape()); + aMakeShapeList.appendAlgo(anObjectsCutAlgo); + aMapOfShapes.merge(anObjectsCutAlgo->mapOfSubShapes()); + } + + // 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-7) { + aTools.clear(); + aTools.push_back(aToolsCutAlgo->shape()); + aMakeShapeList.appendAlgo(aToolsCutAlgo); + aMapOfShapes.merge(aToolsCutAlgo->mapOfSubShapes()); + } + } + + // 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); + aMapOfShapes.merge(aBoolAlgo->mapOfSubShapes()); + + // 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); + aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes()); + + std::shared_ptr aFrontShape = anOriginalShapes.front(); + anOriginalShapes.pop_front(); + std::shared_ptr aResultBody = document()->createBody(data(), aResultIndex); + loadNamingDS(aResultBody, aFrontShape, anOriginalShapes, aShape, aMakeShapeList, aMapOfShapes); + setResult(aResultBody, aResultIndex); + aResultIndex++; + + break; + } default: { std::string anOperationError = "Error: Wrong type of operation"; setError(anOperationError); diff --git a/src/FeaturesPlugin/FeaturesPlugin_Boolean.h b/src/FeaturesPlugin/FeaturesPlugin_Boolean.h index 0a072e822..fd25cff88 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Boolean.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Boolean.h @@ -8,79 +8,67 @@ #define FeaturesPlugin_Cut_H_ #include "FeaturesPlugin.h" -#include -#include +#include -class GeomAlgoAPI_MakeShapeList; +#include -/**\class FeaturesPlugin_Boolean - * \ingroup Plugins - * \brief Feature for applying of Boolean operations on Solids. - * - * Supports three kinds of Boolean operations: Cut, Fuse and Common. - * For all of them requires two Solids: object and tool. - */ +/// \class FeaturesPlugin_Boolean +/// \ingroup Plugins +/// \brief Feature for applying of Boolean operations on Solids. +/// Supports four kinds of Boolean operations: Cut, Fuse, Common and Smash. class FeaturesPlugin_Boolean : public ModelAPI_Feature { public: - /// Extrusion kind + enum OperationType { + BOOL_CUT, + BOOL_FUSE, + BOOL_COMMON, + BOOL_SMASH + }; + + /// Feature kind. inline static const std::string& ID() { static const std::string MY_ID("Boolean"); return MY_ID; } - /// attribute name of referenced object + + /// Attribute name of main objects. inline static const std::string& OBJECT_LIST_ID() { static const std::string MY_OBJECT_LIST_ID("main_objects"); return MY_OBJECT_LIST_ID; } - /// attribute name of referenced object - inline static const std::string& OBJECT_ID() - { - static const std::string MY_OBJECT_ID("main_object"); - return MY_OBJECT_ID; - } - /// attribute name of tool object - inline static const std::string& TOOL_ID() - { - static const std::string MY_TOOL_ID("tool_object"); - return MY_TOOL_ID; - } - /// attribute name of tool object + + /// Attribute name of tool objects. inline static const std::string& TOOL_LIST_ID() { static const std::string MY_TOOL_LIST_ID("tool_objects"); return MY_TOOL_LIST_ID; } - /// attribute name of operation type + + /// Attribute name of operation type. inline static const std::string& TYPE_ID() { static const std::string MY_TYPE_ID("bool_type"); return MY_TYPE_ID; } - enum { - BOOL_CUT, - BOOL_FUSE, - BOOL_COMMON - }; - - /// Returns the kind of a feature + /// \return the kind of a feature. FEATURESPLUGIN_EXPORT virtual const std::string& getKind() { static std::string MY_KIND = FeaturesPlugin_Boolean::ID(); return MY_KIND; } - /// Creates a new part document if needed + /// Creates a new part document if needed. FEATURESPLUGIN_EXPORT virtual void execute(); - /// Request for initialization of data model of the feature: adding all attributes + /// Request for initialization of data model of the feature: adding all attributes. FEATURESPLUGIN_EXPORT virtual void initAttributes(); - /// Use plugin manager for features creation + /// Use plugin manager for features creation. FeaturesPlugin_Boolean(); private: diff --git a/src/FeaturesPlugin/boolean_widget.xml b/src/FeaturesPlugin/boolean_widget.xml index 99d5ca699..f7d687d7b 100644 --- a/src/FeaturesPlugin/boolean_widget.xml +++ b/src/FeaturesPlugin/boolean_widget.xml @@ -6,8 +6,8 @@ buttons_dir="horizontal" label="Operation type" tooltip="Type of boolean operation" - string_list="Cut Fuse Common" - icons_list=":icons/bool_cut.png :icons/bool_fuse.png :icons/bool_common.png" + string_list="Cut Fuse Common Smash" + icons_list=":icons/bool_cut.png :icons/bool_fuse.png :icons/bool_common.png :icons/bool_smash.png" default="0" /> * \endcode * Aditionally can be used: diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index a4e5d07a0..e02492914 100755 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -1187,6 +1187,9 @@ void PartSet_Module::onBooleanOperationChange(int theOperation) case 2: aPanel->setWindowTitle(tr("Common")); break; + case 3: + aPanel->setWindowTitle(tr("Smash")); + break; } } diff --git a/src/PartSet/PartSet_icons.qrc b/src/PartSet/PartSet_icons.qrc index 150fffa4f..50267fb8b 100644 --- a/src/PartSet/PartSet_icons.qrc +++ b/src/PartSet/PartSet_icons.qrc @@ -86,6 +86,7 @@ icons/bool_cut.png icons/bool_fuse.png icons/bool_common.png + icons/bool_smash.png icons/plane_view.png icons/collinear.png icons/middlepoint.png diff --git a/src/PartSet/icons/bool_smash.png b/src/PartSet/icons/bool_smash.png new file mode 100644 index 000000000..bf82ac272 Binary files /dev/null and b/src/PartSet/icons/bool_smash.png differ