From 9dbbe3f702912178277da09aa66a59e6debb6372 Mon Sep 17 00:00:00 2001 From: dbv Date: Sat, 11 Aug 2018 19:18:10 +0300 Subject: [PATCH] Issue #2564: CEA 2018-1 SMASH Added possibility to select planar faces in Boolean Smash feature. --- src/FeaturesPlugin/CMakeLists.txt | 3 + .../FeaturesPlugin_BooleanSmash.cpp | 306 ++++++++++++++++++ .../FeaturesPlugin_BooleanSmash.h | 36 ++- src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp | 2 + .../FeaturesPlugin_Validators.cpp | 136 ++++++++ .../FeaturesPlugin_Validators.h | 15 + .../Test/TestBooleanSmash_Face_Face.py | 52 +++ src/FeaturesPlugin/boolean_smash_widget.xml | 43 +++ src/FeaturesPlugin/plugin-Features.xml | 2 +- 9 files changed, 592 insertions(+), 3 deletions(-) create mode 100644 src/FeaturesPlugin/FeaturesPlugin_BooleanSmash.cpp create mode 100644 src/FeaturesPlugin/Test/TestBooleanSmash_Face_Face.py create mode 100644 src/FeaturesPlugin/boolean_smash_widget.xml diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index e111b5906..f2667acbe 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -69,6 +69,7 @@ SET(PROJECT_SOURCES FeaturesPlugin_Translation.cpp FeaturesPlugin_Boolean.cpp FeaturesPlugin_BooleanCut.cpp + FeaturesPlugin_BooleanSmash.cpp FeaturesPlugin_Intersection.cpp FeaturesPlugin_Partition.cpp FeaturesPlugin_Pipe.cpp @@ -105,6 +106,7 @@ SET(XML_RESOURCES rotation_widget.xml translation_widget.xml boolean_widget.xml + boolean_smash_widget.xml recover_widget.xml partition_widget.xml placement_widget.xml @@ -292,4 +294,5 @@ ADD_UNIT_TESTS(TestExtrusion.py TestBooleanCut_Wire_Face.py TestBooleanCut_Wire_Wire.py TestBooleanCut_WireCompound_WireCompound.py + TestBooleanSmash_Face_Face.py ) diff --git a/src/FeaturesPlugin/FeaturesPlugin_BooleanSmash.cpp b/src/FeaturesPlugin/FeaturesPlugin_BooleanSmash.cpp new file mode 100644 index 000000000..ebc654958 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_BooleanSmash.cpp @@ -0,0 +1,306 @@ +// 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_BooleanSmash.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +//================================================================================================== +FeaturesPlugin_BooleanSmash::FeaturesPlugin_BooleanSmash() +: FeaturesPlugin_Boolean(FeaturesPlugin_Boolean::BOOL_SMASH) +{ +} + +//================================================================================================== +void FeaturesPlugin_BooleanSmash::initAttributes() +{ + data()->addAttribute(OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()); + data()->addAttribute(TOOL_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()); +} + +//================================================================================================== +void FeaturesPlugin_BooleanSmash::execute() +{ + ListOfShape anObjects, aTools; + std::map, ListOfShape> aCompSolidsObjects; + + // Getting objects. + 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(); + if(!anObject.get()) { + return; + } + ResultPtr aContext = anObjectAttr->context(); + ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext); + if (aResCompSolidPtr.get()) + { + 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(TOOL_LIST_ID()); + for(int aToolsIndex = 0; aToolsIndex < aToolsSelList->size(); aToolsIndex++) { + AttributeSelectionPtr aToolAttr = aToolsSelList->value(aToolsIndex); + GeomShapePtr aTool = aToolAttr->value(); + if(!aTool.get()) { + return; + } + aTools.push_back(aTool); + } + + int aResultIndex = 0; + + if((anObjects.empty() && aCompSolidsObjects.empty()) + || aTools.empty()) { + std::string aFeatureError = "Error: Not enough objects for boolean operation."; + setError(aFeatureError); + return; + } + + // List of original shapes for naming. + ListOfShape anOriginalShapes; + anOriginalShapes.insert(anOriginalShapes.end(), anObjects.begin(), anObjects.end()); + anOriginalShapes.insert(anOriginalShapes.end(), aTools.begin(), aTools.end()); + + // Collecting all shapes 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-27) { + 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-27) { + 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++; + + // remove the rest results if there were produced in the previous pass + removeResults(aResultIndex); +} + +//================================================================================================== +void FeaturesPlugin_BooleanSmash::loadNamingDS(ResultBodyPtr theResultBody, + const GeomShapePtr theBaseShape, + const ListOfShape& theTools, + const GeomShapePtr theResultShape, + GeomAlgoAPI_MakeShape& theMakeShape, + GeomAPI_DataMapOfShapeShape& theMapOfShapes) +{ + //load result + if(theBaseShape->isEqual(theResultShape)) { + theResultBody->store(theResultShape, false); + } else { + const int aModifyVTag = 1; + const int aModifyETag = 2; + const int aModifyFTag = 3; + const int aDeletedTag = 4; + /// sub solids will be placed at labels 5, 6, etc. if result is compound of solids + const int aSubsolidsTag = 5; + + theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag); + + const std::string aModVName = "Modified_Vertex"; + const std::string aModEName = "Modified_Edge"; + const std::string aModFName = "Modified_Face"; + + theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::VERTEX, + aModifyVTag, aModVName, theMapOfShapes, false, + true, true); + theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::EDGE, + aModifyETag, aModEName, theMapOfShapes, false, + true, true); + theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE, + aModifyFTag, aModFName, theMapOfShapes, false, + true, true); + + theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape, + GeomAPI_Shape::VERTEX, aDeletedTag); + theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape, + GeomAPI_Shape::EDGE, aDeletedTag); + theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape, + GeomAPI_Shape::FACE, aDeletedTag); + + for (ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++) + { + theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, GeomAPI_Shape::VERTEX, + aModifyVTag, aModVName, theMapOfShapes, false, + true, true); + + theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, GeomAPI_Shape::EDGE, + aModifyETag, aModEName, theMapOfShapes, false, + true, true); + + theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, + aModifyFTag, aModFName, theMapOfShapes, false, + true, true); + + theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::VERTEX, aDeletedTag); + theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::EDGE, aDeletedTag); + theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, aDeletedTag); + } + } +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_BooleanSmash.h b/src/FeaturesPlugin/FeaturesPlugin_BooleanSmash.h index 86809f9eb..0238d2712 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_BooleanSmash.h +++ b/src/FeaturesPlugin/FeaturesPlugin_BooleanSmash.h @@ -23,6 +23,8 @@ #include "FeaturesPlugin_Boolean.h" +#include + /// \class FeaturesPlugin_BooleanSmash /// \ingroup Plugins /// \brief Feature for applying of Boolean Smash operation. @@ -44,10 +46,40 @@ public: return MY_KIND; } + /// 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 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; + } + + /// Request for initialization of data model of the feature: adding all attributes. + FEATURESPLUGIN_EXPORT virtual void initAttributes(); + + /// Creates a new part document if needed. + FEATURESPLUGIN_EXPORT virtual void execute(); + public: - /// Use plugin manager for features creation. - FeaturesPlugin_BooleanSmash(): FeaturesPlugin_Boolean(BOOL_SMASH) {}; + /// Use plugin manager for features creation. + FeaturesPlugin_BooleanSmash(); + +private: + + /// Load Naming data structure of the feature to the document + void loadNamingDS(ResultBodyPtr theResultBody, + const GeomShapePtr theBaseShape, + const ListOfShape& theTools, + const GeomShapePtr theResultShape, + GeomAlgoAPI_MakeShape& theMakeShape, + GeomAPI_DataMapOfShapeShape& theMapOfShapes); }; diff --git a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp index 33f256c1f..9d61541af 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp @@ -96,6 +96,8 @@ FeaturesPlugin_Plugin::FeaturesPlugin_Plugin() new FeaturesPlugin_ValidatorCircular); aFactory->registerValidator("FeaturesPlugin_ValidatorBooleanArguments", new FeaturesPlugin_ValidatorBooleanArguments); + aFactory->registerValidator("FeaturesPlugin_ValidatorBooleanSmashSelection", + new FeaturesPlugin_ValidatorBooleanSmashSelection); // register this plugin ModelAPI_Session::get()->registerPlugin(this); diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp index 97c82b524..cfe4ed743 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp @@ -21,6 +21,7 @@ #include "FeaturesPlugin_Validators.h" #include "FeaturesPlugin_Boolean.h" +#include "FeaturesPlugin_BooleanSmash.h" #include "FeaturesPlugin_Union.h" #include @@ -44,6 +45,7 @@ #include #include #include +#include #include #include @@ -1153,3 +1155,137 @@ bool FeaturesPlugin_ValidatorBooleanArguments::isNotObligatory(std::string theFe return false; } + +//================================================================================================== +bool FeaturesPlugin_ValidatorBooleanSmashSelection::isValid( + const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + std::shared_ptr aFeature = + std::dynamic_pointer_cast(theAttribute->owner()); + + AttributeSelectionListPtr anAttrSelectionList = + std::dynamic_pointer_cast(theAttribute); + if (!aFeature.get() || !anAttrSelectionList.get()) { + theError = + "Error: Validator used in wrong feature or attribute"; + return false; + } + + AttributeSelectionListPtr anOtherAttrSelectionList; + if (theAttribute->id() == FeaturesPlugin_BooleanSmash::OBJECT_LIST_ID()) { + anOtherAttrSelectionList = + aFeature->selectionList(FeaturesPlugin_BooleanSmash::TOOL_LIST_ID()); + } else { + anOtherAttrSelectionList = + aFeature->selectionList(FeaturesPlugin_BooleanSmash::OBJECT_LIST_ID()); + } + + GeomAPI_Shape::ShapeType aSelectedShapesType = GeomAPI_Shape::SHAPE; + GeomAPI_DataMapOfShapeShape aSelectedCompSolidsInOtherList; + GeomPlanePtr aFacesPln; + + for (int anIndex = 0; anIndex < anOtherAttrSelectionList->size(); ++anIndex) { + AttributeSelectionPtr anAttrSelection = anOtherAttrSelectionList->value(anIndex); + ResultPtr aContext = anAttrSelection->context(); + std::shared_ptr aShape = anAttrSelection->value(); + GeomShapePtr aContextShape = aContext->shape(); + if (!aShape.get()) { + aShape = aContextShape; + } + + if (aShape->isSolid() || aShape->isCompSolid()) { + aSelectedShapesType = GeomAPI_Shape::SOLID; + ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext); + if (aResCompSolidPtr.get()) { + GeomShapePtr aCompSolidShape = aResCompSolidPtr->shape(); + aSelectedCompSolidsInOtherList.bind(aCompSolidShape, aCompSolidShape); + } + } else { + aSelectedShapesType = GeomAPI_Shape::FACE; + GeomAPI_Face aFace(aShape); + aFacesPln = aFace.getPlane(); + break; + } + } + + for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) { + AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex); + if (!anAttrSelection.get()) { + theError = "Error: Empty attribute selection."; + return false; + } + ResultPtr aContext = anAttrSelection->context(); + if (!aContext.get()) { + theError = "Error: Empty selection context."; + return false; + } + ResultConstructionPtr aResultConstruction = + std::dynamic_pointer_cast(aContext); + if (aResultConstruction.get()) { + theError = "Error: Result construction not allowed for selection."; + return false; + } + std::shared_ptr aShape = anAttrSelection->value(); + GeomShapePtr aContextShape = aContext->shape(); + if (!aShape.get()) { + aShape = aContextShape; + } + if (!aShape.get()) { + theError = "Error: Empty shape."; + return false; + } + if (!aShape->isEqual(aContextShape)) { + theError = "Error: Local selection not allowed."; + return false; + } + + if (aSelectedShapesType == GeomAPI_Shape::SHAPE) { + // Other list is empty. + if (aShape->isSolid() || aShape->isCompSolid()) { + aSelectedShapesType = GeomAPI_Shape::SOLID; + } else { + aSelectedShapesType = GeomAPI_Shape::FACE; + GeomAPI_Face aFace(aShape); + aFacesPln = aFace.getPlane(); + + if (!aFacesPln.get()) { + theError = "Error: Only planar faces allowed."; + return false; + } + } + + continue; + } else if (aSelectedShapesType == GeomAPI_Shape::SOLID) { + if (!aShape->isSolid() && !aShape->isCompSolid()) { + theError = "Error: Selected shapes should have the same type."; + return false; + } + + ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext); + if (aResCompSolidPtr.get()) { + GeomShapePtr aCompSolidShape = aResCompSolidPtr->shape(); + if (aSelectedCompSolidsInOtherList.isBound(aCompSolidShape)) { + theError = "Error: Solids from compsolid in other list not allowed."; + return false; + } + } + } else { + GeomAPI_Face aFace(aShape); + GeomPlanePtr aPln = aFace.getPlane(); + + if (!aPln.get()) { + theError = "Error: Only planar faces allowed."; + return false; + } + + if (!aFacesPln->isCoincident(aPln)) { + theError = "Error: Only coincident faces allowed."; + return false; + } + } + } + + return true; +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.h b/src/FeaturesPlugin/FeaturesPlugin_Validators.h index c75ad9737..ca731ef0e 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.h @@ -288,4 +288,19 @@ public: virtual bool isNotObligatory(std::string theFeature, std::string theAttribute); }; +/// \class FeaturesPlugin_ValidatorBooleanSmashSelection +/// \ingroup Validators +/// \brief Verifies the selected object for boolean smash feature +class FeaturesPlugin_ValidatorBooleanSmashSelection: public ModelAPI_AttributeValidator +{ +public: + //! \return True if the attribute is valid. + //! \param[in] theAttribute the checked attribute. + //! \param[in] theArguments arguments of the attribute. + //! \param[out] theError error message. + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const; +}; + #endif diff --git a/src/FeaturesPlugin/Test/TestBooleanSmash_Face_Face.py b/src/FeaturesPlugin/Test/TestBooleanSmash_Face_Face.py new file mode 100644 index 000000000..5ac6d4743 --- /dev/null +++ b/src/FeaturesPlugin/Test/TestBooleanSmash_Face_Face.py @@ -0,0 +1,52 @@ +## 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 +## + +from salome.shaper import model + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchCircle_1 = Sketch_1.addCircle(-31.7032590051458, 14.72555746140652, 29.35516607310447) +SketchCircle_1.result().setColor(225, 0, 0) +SketchCircle_1.results()[1].setColor(225, 0, 0) +model.do() +Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchCircle_2 = Sketch_2.addCircle(12.30017152658664, 14.37907375643225, 29.61574408620473) +SketchCircle_2.result().setColor(225, 0, 0) +SketchCircle_2.results()[1].setColor(225, 0, 0) +model.do() +Face_1 = model.addFace(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f"), model.selection("FACE", "Sketch_2/Face-SketchCircle_2_2f")]) +Smash_1 = model.addSmash(Part_1_doc, [model.selection("FACE", "Face_1_1")], [model.selection("FACE", "Face_1_2")]) +model.testHaveNamingSubshapes(Smash_1, model, Part_1_doc) +model.do() +model.end() + +from GeomAPI import GeomAPI_Shape + +model.testNbResults(Smash_1, 1) +model.testNbSubResults(Smash_1, [2]) +model.testNbSubShapes(Smash_1, GeomAPI_Shape.SOLID, [0]) +model.testNbSubShapes(Smash_1, GeomAPI_Shape.FACE, [2]) +model.testNbSubShapes(Smash_1, GeomAPI_Shape.EDGE, [5]) +model.testNbSubShapes(Smash_1, GeomAPI_Shape.VERTEX, [10]) + +assert(model.checkPythonDump()) diff --git a/src/FeaturesPlugin/boolean_smash_widget.xml b/src/FeaturesPlugin/boolean_smash_widget.xml new file mode 100644 index 000000000..cb755c187 --- /dev/null +++ b/src/FeaturesPlugin/boolean_smash_widget.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + diff --git a/src/FeaturesPlugin/plugin-Features.xml b/src/FeaturesPlugin/plugin-Features.xml index 4095ed581..e5b261cbc 100644 --- a/src/FeaturesPlugin/plugin-Features.xml +++ b/src/FeaturesPlugin/plugin-Features.xml @@ -80,7 +80,7 @@ email : webmaster.salome@opencascade.com - + -- 2.30.2