From: dbv Date: Thu, 16 Aug 2018 13:44:10 +0000 (+0300) Subject: Issue #2562: CEA 2018-1 Fuse X-Git-Tag: SHAPER_V9_1_0RC1~74 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=c8e4c6d6463eb3d0268c6042ed527c72a898e083;p=modules%2Fshaper.git Issue #2562: CEA 2018-1 Fuse Fuse now have simple mode with only one field. --- diff --git a/src/FeaturesAPI/FeaturesAPI_BooleanFuse.cpp b/src/FeaturesAPI/FeaturesAPI_BooleanFuse.cpp index c1a043d67..b0e1c76a4 100644 --- a/src/FeaturesAPI/FeaturesAPI_BooleanFuse.cpp +++ b/src/FeaturesAPI/FeaturesAPI_BooleanFuse.cpp @@ -36,12 +36,20 @@ FeaturesAPI_BooleanFuse::FeaturesAPI_BooleanFuse( FeaturesAPI_BooleanFuse::FeaturesAPI_BooleanFuse( const std::shared_ptr& theFeature, const std::list& theMainObjects, - const std::list& theToolObjects) + const std::list& theToolObjects, + const bool theRemoveEdges) : ModelHighAPI_Interface(theFeature) { if(initialize()) { + if (theToolObjects.empty()) { + fillAttribute(FeaturesPlugin_BooleanFuse::CREATION_METHOD_SIMPLE(), mycreationMethod); + } else { + fillAttribute(FeaturesPlugin_BooleanFuse::CREATION_METHOD_ADVANCED(), mycreationMethod); + } + fillAttribute(theMainObjects, mymainObjects); fillAttribute(theToolObjects, mytoolObjects); + fillAttribute(theRemoveEdges, myremoveEdges); execute(false); } @@ -68,6 +76,20 @@ void FeaturesAPI_BooleanFuse::setToolObjects( { fillAttribute(theToolObjects, mytoolObjects); + if (theToolObjects.empty()) { + fillAttribute(FeaturesPlugin_BooleanFuse::CREATION_METHOD_SIMPLE(), mycreationMethod); + } else { + fillAttribute(FeaturesPlugin_BooleanFuse::CREATION_METHOD_ADVANCED(), mycreationMethod); + } + + execute(); +} + +//================================================================================================== +void FeaturesAPI_BooleanFuse::setRemoveEdges(const bool theRemoveEdges) +{ + fillAttribute(theRemoveEdges, myremoveEdges); + execute(); } @@ -83,28 +105,44 @@ void FeaturesAPI_BooleanFuse::dump(ModelHighAPI_Dumper& theDumper) const aBase->selectionList(FeaturesPlugin_BooleanFuse::OBJECT_LIST_ID()); AttributeSelectionListPtr aTools = aBase->selectionList(FeaturesPlugin_BooleanFuse::TOOL_LIST_ID()); + AttributeBooleanPtr aRemoveEdges = + aBase->boolean(FeaturesPlugin_BooleanFuse::REMOVE_INTERSECTION_EDGES_ID()); + + theDumper << "(" << aDocName << ", " << anObjects; + + if (aTools->size() > 0) { + theDumper << ", " << aTools; + } + + if (aRemoveEdges->value()) { + theDumper << ", " << true; + } - theDumper << "(" << aDocName << ", " << anObjects << ", " << aTools << ")" << std::endl; + theDumper << ")" << std::endl; } //================================================================================================== BooleanFusePtr addFuse(const std::shared_ptr& thePart, - const std::list& theObjects) + const std::list& theObjects, + const bool theRemoveEdges) { std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_BooleanFuse::ID()); std::list aToolObjects; return BooleanFusePtr(new FeaturesAPI_BooleanFuse(aFeature, theObjects, - aToolObjects)); + aToolObjects, + theRemoveEdges)); } //================================================================================================== BooleanFusePtr addFuse(const std::shared_ptr& thePart, const std::list& theMainObjects, - const std::list& theToolObjects) + const std::list& theToolObjects, + const bool theRemoveEdges) { std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_BooleanFuse::ID()); return BooleanFusePtr(new FeaturesAPI_BooleanFuse(aFeature, theMainObjects, - theToolObjects)); + theToolObjects, + theRemoveEdges)); } diff --git a/src/FeaturesAPI/FeaturesAPI_BooleanFuse.h b/src/FeaturesAPI/FeaturesAPI_BooleanFuse.h index 17b72f7f2..495add44e 100644 --- a/src/FeaturesAPI/FeaturesAPI_BooleanFuse.h +++ b/src/FeaturesAPI/FeaturesAPI_BooleanFuse.h @@ -45,17 +45,22 @@ public: FEATURESAPI_EXPORT FeaturesAPI_BooleanFuse(const std::shared_ptr& theFeature, const std::list& theMainObjects, - const std::list& theToolObjects); + const std::list& theToolObjects, + const bool theRemoveEdges = false); /// Destructor. FEATURESAPI_EXPORT virtual ~FeaturesAPI_BooleanFuse(); - INTERFACE_2(FeaturesPlugin_BooleanFuse::ID(), + INTERFACE_4(FeaturesPlugin_BooleanFuse::ID(), + creationMethod, FeaturesPlugin_BooleanFuse::CREATION_METHOD(), + ModelAPI_AttributeString, /** Creation method */, mainObjects, FeaturesPlugin_BooleanFuse::OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList, /** Main objects */, toolObjects, FeaturesPlugin_BooleanFuse::TOOL_LIST_ID(), - ModelAPI_AttributeSelectionList, /** Tool objects*/) + ModelAPI_AttributeSelectionList, /** Tool objects*/, + removeEdges, FeaturesPlugin_BooleanFuse::REMOVE_INTERSECTION_EDGES_ID(), + ModelAPI_AttributeBoolean, /** Remove edges */) /// Set main objects. FEATURESAPI_EXPORT @@ -65,6 +70,10 @@ public: FEATURESAPI_EXPORT void setToolObjects(const std::list& theToolObjects); + /// Set remove edges. + FEATURESAPI_EXPORT + void setRemoveEdges(const bool theRemoveEdges); + /// Dump wrapped feature FEATURESAPI_EXPORT virtual void dump(ModelHighAPI_Dumper& theDumper) const; @@ -77,13 +86,15 @@ typedef std::shared_ptr BooleanFusePtr; /// \brief Create Boolean Fuse feature. FEATURESAPI_EXPORT BooleanFusePtr addFuse(const std::shared_ptr& thePart, - const std::list& theObjects); + const std::list& theObjects, + const bool theRemoveEdges = false); /// \ingroup CPPHighAPI /// \brief Create Boolean Fuse feature. FEATURESAPI_EXPORT BooleanFusePtr addFuse(const std::shared_ptr& thePart, const std::list& theMainObjects, - const std::list& theToolObjects); + const std::list& theToolObjects, + const bool theRemoveEdges = false); #endif // FeaturesAPI_BooleanFuse_H_ diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index 3a60a545c..0b8054f01 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -70,6 +70,7 @@ SET(PROJECT_SOURCES FeaturesPlugin_Translation.cpp FeaturesPlugin_Boolean.cpp FeaturesPlugin_BooleanCut.cpp + FeaturesPlugin_BooleanFuse.cpp FeaturesPlugin_BooleanSmash.cpp FeaturesPlugin_Intersection.cpp FeaturesPlugin_Partition.cpp @@ -108,6 +109,7 @@ SET(XML_RESOURCES rotation_widget.xml translation_widget.xml boolean_widget.xml + boolean_fuse_widget.xml boolean_smash_widget.xml recover_widget.xml partition_widget.xml @@ -299,4 +301,6 @@ ADD_UNIT_TESTS(TestExtrusion.py TestBooleanCut_Wire_Wire.py TestBooleanCut_WireCompound_WireCompound.py TestBooleanSmash_Face_Face.py + TestBooleanFuse_SimpleMode.py + TestBooleanFuse_RemoveEdges.py ) diff --git a/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp b/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp new file mode 100644 index 000000000..1d7d14a5f --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp @@ -0,0 +1,374 @@ +// 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_BooleanFuse.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +//================================================================================================== +FeaturesPlugin_BooleanFuse::FeaturesPlugin_BooleanFuse() +: FeaturesPlugin_Boolean(FeaturesPlugin_Boolean::BOOL_FUSE) +{ +} + +//================================================================================================== +void FeaturesPlugin_BooleanFuse::initAttributes() +{ + data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId()); + + data()->addAttribute(OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()); + data()->addAttribute(TOOL_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()); + + data()->addAttribute(REMOVE_INTERSECTION_EDGES_ID(), ModelAPI_AttributeBoolean::typeId()); + + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), OBJECT_LIST_ID()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TOOL_LIST_ID()); +} + +//================================================================================================== +void FeaturesPlugin_BooleanFuse::execute() +{ + ListOfShape anObjects, aTools, anEdgesAndFaces, aPlanes; + std::map, ListOfShape> aCompSolidsObjects; + + bool isSimpleCreation = false; + + AttributeStringPtr aCreationMethodAttr = string(CREATION_METHOD()); + if (aCreationMethodAttr.get() + && aCreationMethodAttr->value() == CREATION_METHOD_SIMPLE()) { + isSimpleCreation = true; + } + + // 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(); + ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext); + if (!isSimpleCreation + && 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 (anObject->shapeType() == GeomAPI_Shape::EDGE + || anObject->shapeType() == GeomAPI_Shape::FACE) { + anEdgesAndFaces.push_back(anObject); + } else { + anObjects.push_back(anObject); + } + } + } + + // Getting tools. + if (!isSimpleCreation) { + 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 (aTool->shapeType() == GeomAPI_Shape::EDGE + || aTool->shapeType() == GeomAPI_Shape::FACE) { + anEdgesAndFaces.push_back(aTool); + } else { + aTools.push_back(aTool); + } + } + } + + 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. + GeomAlgoAPI_MakeShapeList aMakeShapeList; + GeomAPI_DataMapOfShapeShape aMapOfShapes; + 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); + aMapOfShapes.merge(aCutAlgo->mapOfSubShapes()); + } + } + 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); + aMapOfShapes.merge(aCutAlgo->mapOfSubShapes()); + } + } + } + + 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); + aMapOfShapes.merge(aFuseAlgo->mapOfSubShapes()); + } + + // 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); + aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes()); + } + + bool isRemoveEdges = false; + AttributeBooleanPtr removeEdgesAttr = boolean(REMOVE_INTERSECTION_EDGES_ID()); + if (removeEdgesAttr.get()) { + isRemoveEdges = removeEdgesAttr->value(); + } + + if (isRemoveEdges) { + std::shared_ptr aUnifyAlgo( + new GeomAlgoAPI_UnifySameDomain(aShape)); + + if (!aUnifyAlgo->isDone()) { + std::string aFeatureError = "Error: PaveFiller algorithm failed."; + setError(aFeatureError); + return; + } + if (aUnifyAlgo->shape()->isNull()) { + static const std::string aShapeError = "Error: Resulting shape is Null."; + setError(aShapeError); + return; + } + if (!aUnifyAlgo->isValid()) { + std::string aFeatureError = "Error: Resulting shape is not valid."; + setError(aFeatureError); + return; + } + + aShape = aUnifyAlgo->shape(); + aMakeShapeList.appendAlgo(aUnifyAlgo); + aMapOfShapes.merge(aUnifyAlgo->mapOfSubShapes()); + } + + int aResultIndex = 0; + + std::shared_ptr aBackShape = anOriginalShapes.back(); + anOriginalShapes.pop_back(); + std::shared_ptr aResultBody = + document()->createBody(data(), aResultIndex); + loadNamingDS(aResultBody, aBackShape, anOriginalShapes, + aShape, aMakeShapeList, aMapOfShapes); + setResult(aResultBody, aResultIndex); + aResultIndex++; + + // remove the rest results if there were produced in the previous pass + removeResults(aResultIndex); +} + +//================================================================================================== +void FeaturesPlugin_BooleanFuse::loadNamingDS(std::shared_ptr theResultBody, + const std::shared_ptr theBaseShape, + const ListOfShape& theTools, + const std::shared_ptr theResultShape, + GeomAlgoAPI_MakeShape& theMakeShape, + GeomAPI_DataMapOfShapeShape& theMapOfShapes) +{ + //load result + if (theBaseShape->isEqual(theResultShape)) { + theResultBody->store(theResultShape, false); + } else { + const int aModifyTag = 1; + const int aModifyEdgeTag = 2; + const int aModifyFaceTag = 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 aModName = "Modified"; + const std::string aModEName = "Modified_Edge"; + const std::string aModFName = "Modified_Face"; + + theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::EDGE, + aModifyEdgeTag, aModEName, theMapOfShapes, false, + false, true); + theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE, + aModifyFaceTag, aModFName, theMapOfShapes, false, + false, true); + theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape, + GeomAPI_Shape::FACE, aDeletedTag); + + int aTag; + std::string aName; + for (ListOfShape::const_iterator + anIter = theTools.begin(); anIter != theTools.end(); anIter++) { + if ((*anIter)->shapeType() <= GeomAPI_Shape::FACE) { + aTag = aModifyFaceTag; + aName = aModFName; + } else { + aTag = aModifyEdgeTag; + aName = aModEName; + } + theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, + aName == aModEName ? GeomAPI_Shape::EDGE + : GeomAPI_Shape::FACE, + aTag, aName, theMapOfShapes, false, false, true); + theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, aDeletedTag); + } + } +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.h b/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.h index bbd6216ba..950b8223f 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.h +++ b/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.h @@ -44,11 +44,67 @@ public: return MY_KIND; } + /// Attribute name for creation method. + inline static const std::string& CREATION_METHOD() + { + static const std::string MY_CREATION_METHOD_ID("creation_method"); + return MY_CREATION_METHOD_ID; + } + + /// Attribute name for creation method. + inline static const std::string& CREATION_METHOD_SIMPLE() + { + static const std::string MY_CREATION_METHOD_ID("simple"); + return MY_CREATION_METHOD_ID; + } + + /// Attribute name for creation method. + inline static const std::string& CREATION_METHOD_ADVANCED() + { + static const std::string MY_CREATION_METHOD_ID("advanced"); + return MY_CREATION_METHOD_ID; + } + + /// 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; + } + + /// Attribute name of remove edges option. + inline static const std::string& REMOVE_INTERSECTION_EDGES_ID() + { + static const std::string MY_TOOL_LIST_ID("remove_intersection_edges"); + 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_BooleanFuse(): FeaturesPlugin_Boolean(BOOL_FUSE) {}; + /// Use plugin manager for features creation. + FeaturesPlugin_BooleanFuse(); +private: + /// Load Naming data structure of the feature to the document + void loadNamingDS(std::shared_ptr theResultBody, + const std::shared_ptr theBaseShape, + const ListOfShape& theTools, + const std::shared_ptr theResultShape, + GeomAlgoAPI_MakeShape& theMakeShape, + GeomAPI_DataMapOfShapeShape& theMapOfShapes); }; #endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp index cb75e5700..3f1da2fd1 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp @@ -101,6 +101,10 @@ FeaturesPlugin_Plugin::FeaturesPlugin_Plugin() new FeaturesPlugin_ValidatorBooleanSmashSelection); aFactory->registerValidator("FeaturesPlugin_IntersectionSelection", new FeaturesPlugin_IntersectionSelection); + aFactory->registerValidator("FeaturesPlugin_ValidatorBooleanFuseSelection", + new FeaturesPlugin_ValidatorBooleanFuseSelection); + aFactory->registerValidator("FeaturesPlugin_ValidatorBooleanFuseArguments", + new FeaturesPlugin_ValidatorBooleanFuseArguments); // register this plugin ModelAPI_Session::get()->registerPlugin(this); diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp index f0005c790..13b2c6caf 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_BooleanFuse.h" #include "FeaturesPlugin_BooleanSmash.h" #include "FeaturesPlugin_Union.h" @@ -1354,3 +1355,144 @@ bool FeaturesPlugin_IntersectionSelection::isValid(const AttributePtr& theAttrib return true; } + +//================================================================================================== +bool FeaturesPlugin_ValidatorBooleanFuseSelection::isValid( + const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + AttributeSelectionListPtr anAttrSelectionList = + std::dynamic_pointer_cast(theAttribute); + if (!anAttrSelectionList.get()) { + theError = + "Error: This validator can only work with selection list attributes in \"Boolean\" feature."; + return false; + } + + 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; + } + } + + return true; +} + +//================================================================================================= +bool FeaturesPlugin_ValidatorBooleanFuseArguments::isValid( + const std::shared_ptr& theFeature, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + if (theArguments.size() != 2) { + theError = "Wrong number of arguments (expected 2)."; + return false; + } + + std::shared_ptr aFeature = + std::dynamic_pointer_cast(theFeature); + + int anObjectsNb = 0, aToolsNb = 0; + + std::list::const_iterator anIt = theArguments.begin(), aLast = theArguments.end(); + + bool isAllInSameCompSolid = true; + ResultCompSolidPtr aCompSolid; + + AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt); + if (anAttrSelList) { + anObjectsNb = anAttrSelList->size(); + for (int anIndex = 0; anIndex < anObjectsNb; ++anIndex) { + AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex); + ResultPtr aContext = anAttr->context(); + ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext); + if (aResCompSolidPtr.get()) { + if (aCompSolid.get()) { + isAllInSameCompSolid = aCompSolid == aResCompSolidPtr; + } else { + aCompSolid = aResCompSolidPtr; + } + } else { + isAllInSameCompSolid = false; + break; + } + } + } + anIt++; + + if (aFeature->string(FeaturesPlugin_BooleanFuse::CREATION_METHOD())->value() + == FeaturesPlugin_BooleanFuse::CREATION_METHOD_ADVANCED()) { + anAttrSelList = theFeature->selectionList(*anIt); + if (anAttrSelList) { + aToolsNb = anAttrSelList->size(); + if (isAllInSameCompSolid) { + for (int anIndex = 0; anIndex < aToolsNb; ++anIndex) { + AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex); + ResultPtr aContext = anAttr->context(); + ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext); + if (aResCompSolidPtr.get()) { + if (aCompSolid.get()) { + isAllInSameCompSolid = aCompSolid == aResCompSolidPtr; + } else { + aCompSolid = aResCompSolidPtr; + } + } else { + isAllInSameCompSolid = false; + break; + } + } + } + } + } + + anIt++; + + if (anObjectsNb + aToolsNb < 2) { + theError = "Not enough arguments for Fuse operation."; + return false; + } else if (isAllInSameCompSolid) { + theError = "Operations only between sub-shapes of the same shape not allowed."; + return false; + } + + return true; +} + +//================================================================================================= +bool FeaturesPlugin_ValidatorBooleanFuseArguments::isNotObligatory( + std::string theFeature, + std::string theAttribute) +{ + if (theAttribute == "main_objects" || theAttribute == "tool_objects") { + return true; + } + + return false; +} \ No newline at end of file diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.h b/src/FeaturesPlugin/FeaturesPlugin_Validators.h index 0001a37fb..389ebb261 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.h @@ -318,4 +318,40 @@ public: Events_InfoMessage& theError) const; }; +/// \class FeaturesPlugin_ValidatorBooleanFuseSelection +/// \ingroup Validators +/// \brief Verifies the selected object for boolean fuse feature +class FeaturesPlugin_ValidatorBooleanFuseSelection: 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; +}; + +/** \class FeaturesPlugin_ValidatorBooleanFuseArguments +* \ingroup Validators +* \brief Validates that boolean operation have enough arguments. +*/ +class FeaturesPlugin_ValidatorBooleanFuseArguments: public ModelAPI_FeatureValidator +{ +public: + /** \brief Returns true if feature and/or attributes are valid. + * \param[in] theFeature the validated feature. + * \param[in] theArguments the arguments in the configuration file for this validator. + * \param[out] theError error message. + * \returns true if feature is valid. + */ + virtual bool isValid(const std::shared_ptr& theFeature, + const std::list& theArguments, + Events_InfoMessage& theError) const; + + /// \return true if the attribute in feature is not obligatory for the feature execution. + virtual bool isNotObligatory(std::string theFeature, std::string theAttribute); +}; + #endif diff --git a/src/FeaturesPlugin/Test/Test2394.py b/src/FeaturesPlugin/Test/Test2394.py deleted file mode 100644 index 13639bba7..000000000 --- a/src/FeaturesPlugin/Test/Test2394.py +++ /dev/null @@ -1,258 +0,0 @@ -# -*- coding: utf-8 -*- - -## Copyright (C) 2018-20xx 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 GeomAPI import * -from SketchAPI import * - -from salome.shaper import model - -model.begin() -partSet = model.moduleDocument() -Part_1 = model.addPart(partSet) -Part_1_doc = Part_1.document() - -model.addParameter(Part_1_doc, "R", "58") -model.addParameter(Part_1_doc, "cote_cube", "R/2") -model.addParameter(Part_1_doc, "theta", "54") -model.addParameter(Part_1_doc, "phi", "36") -model.addParameter(Part_1_doc, "pi", "3.141592653589793") -model.addParameter(Part_1_doc, "x", "R*sin(phi/180*pi)*cos(theta/180*pi)") -model.addParameter(Part_1_doc, "y", "R*sin(phi/180*pi)*sin(theta/180*pi)") -model.addParameter(Part_1_doc, "z", "R*cos(phi/180*pi)") -model.addParameter(Part_1_doc, "haut_ext_tuyau", "5") -model.addParameter(Part_1_doc, "haut_int_tuyau", "14") -Param_Diam = model.addParameter(Part_1_doc, "diam_tuyau", "10") - -Revolution_1 = model.addRevolution(Part_1_doc, [], model.selection("EDGE", "PartSet/OZ"), 90, 0) -Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ")) -SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False) -SketchPoint_1 = SketchProjection_1.createdFeature() -SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False) -SketchLine_1 = SketchProjection_2.createdFeature() -SketchArc_1 = Sketch_1.addArc(0, 0, 58, 0, 0, -58, True) -SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchArc_1.center()) -SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.result(), SketchArc_1.startPoint()) -SketchLine_2 = Sketch_1.addLine(0, -58, 0, 0) -SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_2.startPoint()) -SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.endPoint()) -SketchLine_3 = Sketch_1.addLine(0, 0, 58, 0) -SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) -SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_3.endPoint()) -SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result()) -SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_2.result(), "R") -Revolution_1.setNestedSketch(Sketch_1) - -Extrusion_1 = model.addExtrusion(Part_1_doc, [], model.selection(), 0, "cote_cube") -Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Revolution_1_1/Generated_Face_2")) -SketchLine_4 = Sketch_2.addLine(29, 0, 0, 0) -SketchLine_5 = Sketch_2.addLine(0, 0, 0, 29) -SketchLine_6 = Sketch_2.addLine(0, 29, 29, 29) -SketchLine_7 = Sketch_2.addLine(29, 29, 29, 0) -SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_4.startPoint()) -SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint()) -SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint()) -SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint()) -SketchConstraintHorizontal_1 = Sketch_2.setHorizontal(SketchLine_4.result()) -SketchConstraintVertical_2 = Sketch_2.setVertical(SketchLine_5.result()) -SketchConstraintHorizontal_2 = Sketch_2.setHorizontal(SketchLine_6.result()) -SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_7.result()) -SketchConstraintLength_2 = Sketch_2.setLength(SketchLine_6.result(), "cote_cube") -SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_6.result(), SketchLine_7.result()) -SketchProjection_3 = Sketch_2.addProjection(model.selection("EDGE", "Revolution_1_1/Generated_Face_2&Revolution_1_1/To_Face_1"), False) -SketchLine_8 = SketchProjection_3.createdFeature() -SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_8.result()) -SketchProjection_4 = Sketch_2.addProjection(model.selection("EDGE", "Revolution_1_1/Generated_Face_2&Revolution_1_1/From_Face_1"), False) -SketchLine_9 = SketchProjection_4.createdFeature() -SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchLine_4.startPoint(), SketchLine_9.result()) -Extrusion_1.setNestedSketch(Sketch_2) - -Fill_1 = model.addFill(Part_1_doc, [model.selection("SOLID", "Revolution_1_1")], [model.selection("SOLID", "Extrusion_1_1")]) - -Point_2 = model.addPoint(Part_1_doc, "x", "y", "-z") -Axis_4 = model.addAxis(Part_1_doc, model.selection("VERTEX", "Point_1"), model.selection("VERTEX", "Fill_1_1_2/Modified_Face_3&Fill_1_1_2/Modified_Face_2&Fill_1_1_2/Modified_Face_1")) -Plane_4 = model.addPlane(Part_1_doc, model.selection("EDGE", "Axis_1"), model.selection("VERTEX", "Point_1"), True) -Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Plane_1"), "haut_ext_tuyau", True) -Plane_5.result().setName("Plane_2 arrivee tuyau") -Plane_6 = model.addPlane(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_3"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/From_Face_1"), 45) -Plane_7 = model.addPlane(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/From_Face_1"), 45) -Plane_8 = model.addPlane(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_4"), "90+45") - -Fill_2 = model.addFill(Part_1_doc, [model.selection("SOLID", "Fill_1_1_1")], [model.selection("FACE", "Plane_5")]) -Fill_3 = model.addFill(Part_1_doc, [model.selection("SOLID", "Fill_2_1_2")], [model.selection("FACE", "Plane_3")]) -Fill_4 = model.addFill(Part_1_doc, [model.selection("SOLID", "Fill_3_1_2")], [model.selection("FACE", "Plane_4")]) -Fill_4.result().setColor(102, 51, 51) -Fill_4.result().subResult(0).setColor(153, 153, 76) -Fill_4.result().subResult(1).setColor(0, 204, 204) -Fill_4.result().subResult(2).setColor(51, 51, 102) -Fill_4.result().subResult(3).setColor(102, 204, 102) -Fill_4.result().subResult(4).setColor(204, 204, 0) - -Union_1 = model.addUnion(Part_1_doc, [model.selection("SOLID", "Fill_4_1_4"), model.selection("SOLID", "Fill_4_1_2")]) - -Point_3 = model.addPoint(Part_1_doc, model.selection("EDGE", "Axis_1"), model.selection("FACE", "Plane_2 arrivee tuyau")) - -Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_2 arrivee tuyau")) -SketchProjection_5 = Sketch_3.addProjection(model.selection("VERTEX", "Point_2"), False) -SketchPoint_2 = SketchProjection_5.createdFeature() -SketchCircle_1 = Sketch_3.addCircle(0, 0, 10) -SketchConstraintCoincidence_13 = Sketch_3.setCoincident(SketchPoint_2.result(), SketchCircle_1.center()) -SketchConstraintRadius_1 = Sketch_3.setRadius(SketchCircle_1.results()[1], "diam_tuyau") -SketchLine_10 = Sketch_3.addLine(-5, 5, 5, 5) -SketchLine_11 = Sketch_3.addLine(5, 5, 5, -5) -SketchLine_12 = Sketch_3.addLine(5, -5, -5, -5) -SketchLine_13 = Sketch_3.addLine(-5, -5, -5, 5) -SketchConstraintCoincidence_14 = Sketch_3.setCoincident(SketchLine_13.endPoint(), SketchLine_10.startPoint()) -SketchConstraintCoincidence_15 = Sketch_3.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint()) -SketchConstraintCoincidence_16 = Sketch_3.setCoincident(SketchLine_11.endPoint(), SketchLine_12.startPoint()) -SketchConstraintCoincidence_17 = Sketch_3.setCoincident(SketchLine_12.endPoint(), SketchLine_13.startPoint()) -SketchConstraintHorizontal_3 = Sketch_3.setHorizontal(SketchLine_10.result()) -SketchConstraintVertical_4 = Sketch_3.setVertical(SketchLine_11.result()) -SketchConstraintHorizontal_4 = Sketch_3.setHorizontal(SketchLine_12.result()) -SketchConstraintVertical_5 = Sketch_3.setVertical(SketchLine_13.result()) -SketchConstraintEqual_2 = Sketch_3.setEqual(SketchLine_10.result(), SketchLine_13.result()) -SketchLine_14 = Sketch_3.addLine(5, 5, 7.071067811865479, 7.071067811865475) -SketchConstraintCoincidence_18 = Sketch_3.setCoincident(SketchLine_10.endPoint(), SketchLine_14.startPoint()) -SketchConstraintCoincidence_19 = Sketch_3.setCoincident(SketchLine_14.endPoint(), SketchCircle_1.results()[1]) -SketchLine_15 = Sketch_3.addLine(-5, -5, -7.071067811865472, -7.071067811865476) -SketchConstraintCoincidence_20 = Sketch_3.setCoincident(SketchLine_12.endPoint(), SketchLine_15.startPoint()) -SketchConstraintCoincidence_21 = Sketch_3.setCoincident(SketchLine_15.endPoint(), SketchCircle_1.results()[1]) -SketchConstraintCollinear_1 = Sketch_3.setCollinear(SketchLine_14.result(), SketchLine_15.result()) -SketchLine_16 = Sketch_3.addLine(7.071067811865478, -7.071067811865476, 5, -5) -SketchConstraintCoincidence_22 = Sketch_3.setCoincident(SketchLine_16.startPoint(), SketchCircle_1.results()[1]) -SketchConstraintCoincidence_23 = Sketch_3.setCoincident(SketchLine_11.endPoint(), SketchLine_16.endPoint()) -SketchLine_17 = Sketch_3.addLine(-5, 5, -7.071067811865472, 7.071067811865476) -SketchConstraintCoincidence_24 = Sketch_3.setCoincident(SketchLine_10.startPoint(), SketchLine_17.startPoint()) -SketchConstraintCoincidence_25 = Sketch_3.setCoincident(SketchLine_17.endPoint(), SketchCircle_1.results()[1]) -SketchConstraintCollinear_2 = Sketch_3.setCollinear(SketchLine_17.result(), SketchLine_16.result()) -SketchConstraintEqual_3 = Sketch_3.setEqual(SketchLine_14.result(), SketchLine_15.result()) -SketchConstraintEqual_4 = Sketch_3.setEqual(SketchLine_17.result(), SketchLine_16.result()) -SketchConstraintLength_3 = Sketch_3.setLength(SketchLine_10.result(), "diam_tuyau") -model.do() - -Extrusion_2_objects = [model.selection("FACE", "Sketch_3/Face-SketchCircle_1_2f-SketchLine_11f-SketchLine_14r-SketchLine_16r"), model.selection("FACE", "Sketch_3/Face-SketchCircle_1_2f-SketchLine_10f-SketchLine_14f-SketchLine_17r"), model.selection("FACE", "Sketch_3/Face-SketchCircle_1_2f-SketchLine_13f-SketchLine_15r-SketchLine_17f"), model.selection("FACE", "Sketch_3/Face-SketchCircle_1_2f-SketchLine_12f-SketchLine_15f-SketchLine_16f")] -Extrusion_2 = model.addExtrusion(Part_1_doc, Extrusion_2_objects, model.selection(), 10, 0) -Extrusion_3 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_10r-SketchLine_11r-SketchLine_12r-SketchLine_13r")], model.selection(), "haut_int_tuyau", 0) - -Sketch_4 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_2_1/To_Face_3")) -SketchProjection_6 = Sketch_4.addProjection(model.selection("VERTEX", "Extrusion_2_1/Generated_Face_2&Extrusion_2_1/Generated_Face_4&Extrusion_2_1/To_Face_4"), False) -SketchPoint_3 = SketchProjection_6.createdFeature() -SketchProjection_7 = Sketch_4.addProjection(model.selection("VERTEX", "Extrusion_2_1/Generated_Face_5&Extrusion_2_1/Generated_Face_7&Extrusion_2_1/To_Face_3"), False) -SketchPoint_4 = SketchProjection_7.createdFeature() -SketchArc_2 = Sketch_4.addArc(0, 0, -7.071067811865476, -7.071067811865472, 7.071067811865476, 7.071067811865472, True) -SketchConstraintCoincidence_26 = Sketch_4.setCoincident(SketchPoint_3.result(), SketchArc_2.startPoint()) -SketchConstraintCoincidence_27 = Sketch_4.setCoincident(SketchPoint_4.result(), SketchArc_2.results()[1]) -SketchLine_18 = Sketch_4.addLine(7.071067811865476, 7.071067811865472, -7.071067811865476, -7.071067811865472) -SketchConstraintCoincidence_28 = Sketch_4.setCoincident(SketchArc_2.endPoint(), SketchLine_18.startPoint()) -SketchConstraintCoincidence_29 = Sketch_4.setCoincident(SketchAPI_Point(SketchPoint_3).coordinates(), SketchLine_18.endPoint()) -SketchProjection_8 = Sketch_4.addProjection(model.selection("VERTEX", "Extrusion_2_1/Generated_Face_13&Extrusion_2_1/Generated_Face_12&Extrusion_2_1/To_Face_1"), False) -SketchPoint_5 = SketchProjection_8.createdFeature() -SketchConstraintCoincidence_30 = Sketch_4.setCoincident(SketchArc_2.endPoint(), SketchAPI_Point(SketchPoint_5).coordinates()) -model.do() - -Revolution_2 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_4/Face-SketchArc_2_2f-SketchLine_18r")], model.selection("EDGE", "Sketch_4/Edge-SketchLine_18"), 0, 180) - -Cut_1 = model.addCut(Part_1_doc, [model.selection("SOLID", "Revolution_2_1")], [model.selection("SOLID", "Extrusion_3_1")]) -Cut_1.result().setName("demi-sphere") - -Plane_9 = model.addPlane(Part_1_doc, model.selection("VERTEX", "Extrusion_2_1/Generated_Face_10&Extrusion_2_1/Generated_Face_1&Extrusion_2_1/From_Face_4"), model.selection("VERTEX", "Extrusion_2_1/Generated_Face_10&Extrusion_2_1/Generated_Face_1&Extrusion_2_1/To_Face_4"), model.selection("VERTEX", "Extrusion_2_1/Generated_Face_2&Extrusion_2_1/Generated_Face_10&Extrusion_2_1/To_Face_4")) -Plane_10 = model.addPlane(Part_1_doc, model.selection("VERTEX", "Extrusion_2_1/Generated_Face_12&Extrusion_2_1/Generated_Face_11&Extrusion_2_1/To_Face_1"), model.selection("VERTEX", "Extrusion_2_1/Generated_Face_13&Extrusion_2_1/Generated_Face_12&Extrusion_2_1/To_Face_1"), model.selection("VERTEX", "Extrusion_2_1/Generated_Face_13&Extrusion_2_1/Generated_Face_12&Extrusion_2_1/From_Face_1")) -Plane_11 = model.addPlane(Part_1_doc, model.selection("VERTEX", "Extrusion_2_1/Generated_Face_5&Extrusion_2_1/Generated_Face_7&Extrusion_2_1/To_Face_3"), model.selection("VERTEX", "Extrusion_2_1/Generated_Face_3&Extrusion_2_1/Generated_Face_7&Extrusion_2_1/To_Face_3"), model.selection("VERTEX", "Extrusion_2_1/Generated_Face_5&Extrusion_2_1/Generated_Face_7&Extrusion_2_1/From_Face_3")) -Plane_12 = model.addPlane(Part_1_doc, model.selection("VERTEX", "Extrusion_2_1/Generated_Face_1&Extrusion_2_1/Generated_Face_4&Extrusion_2_1/To_Face_4"), model.selection("VERTEX", "Extrusion_2_1/Generated_Face_2&Extrusion_2_1/Generated_Face_4&Extrusion_2_1/To_Face_4"), model.selection("VERTEX", "Extrusion_2_1/Generated_Face_2&Extrusion_2_1/Generated_Face_4&Extrusion_2_1/From_Face_4")) - -Recover_1 = model.addRecover(Part_1_doc, Cut_1, [Extrusion_3.result()]) - -Plane_13 = model.addPlane(Part_1_doc, model.selection("FACE", "Recover_1_1/Shape4"), model.selection("EDGE", "Recover_1_1/Shape4&Recover_1_1/Shape6"), "90+45") -Plane_14 = model.addPlane(Part_1_doc, model.selection("FACE", "Recover_1_1/Shape1"), model.selection("EDGE", "Recover_1_1/Shape1&Recover_1_1/Shape6"), "90+45") -Plane_15 = model.addPlane(Part_1_doc, model.selection("FACE", "Recover_1_1/Shape2"), model.selection("EDGE", "Recover_1_1/Shape2&Recover_1_1/Shape6"), "90+45") -Plane_16 = model.addPlane(Part_1_doc, model.selection("FACE", "Recover_1_1/Shape6"), model.selection("EDGE", "Recover_1_1/Shape3&Recover_1_1/Shape6"), 45) - -Fill_5_objects_2 = [model.selection("FACE", "Plane_6"), model.selection("FACE", "Plane_7"), model.selection("FACE", "Plane_8"), model.selection("FACE", "Plane_9"), model.selection("FACE", "Plane_10"), model.selection("FACE", "Plane_11"), model.selection("FACE", "Plane_12"), model.selection("FACE", "Plane_13")] -Fill_5 = model.addFill(Part_1_doc, [model.selection("SOLID", "demi-sphere")], Fill_5_objects_2) - -Union_2_objects = [model.selection("SOLID", "Fill_5_1_14"), model.selection("SOLID", "Fill_5_1_15"), model.selection("SOLID", "Fill_5_1_16")] -Union_2 = model.addUnion(Part_1_doc, Union_2_objects) -Union_3_objects = [model.selection("SOLID", "Fill_5_1_8/Fill_5_1_8"), model.selection("SOLID", "Fill_5_1_4/Fill_5_1_4"), model.selection("SOLID", "Fill_5_1_9/Fill_5_1_9"), model.selection("SOLID", "Fill_5_1_11/Fill_5_1_11")] -Union_3 = model.addUnion(Part_1_doc, Union_3_objects) -Union_4_objects = [model.selection("SOLID", "Fill_5_1_6/Fill_5_1_6"), model.selection("SOLID", "Fill_5_1_10/Fill_5_1_10"), model.selection("SOLID", "Fill_5_1_13/Fill_5_1_13")] -Union_4 = model.addUnion(Part_1_doc, Union_4_objects) -Union_5_objects = [model.selection("SOLID", "Fill_5_1_2/Fill_5_1_2"), model.selection("SOLID", "Fill_5_1_1/Fill_5_1_1"), model.selection("SOLID", "Fill_5_1_3/Fill_5_1_3")] -Union_5 = model.addUnion(Part_1_doc, Union_5_objects) -Union_6_objects = [model.selection("SOLID", "Fill_5_1_5/Fill_5_1_5"), model.selection("SOLID", "Fill_5_1_7/Fill_5_1_7"), model.selection("SOLID", "Fill_5_1_12/Fill_5_1_12")] -Union_6 = model.addUnion(Part_1_doc, Union_6_objects) -Union_6.result().setColor(0, 0, 204) -Union_6.result().subResult(0).setColor(204, 102, 102) -Union_6.result().subResult(1).setColor(127, 254, 127) -Union_6.result().subResult(2).setColor(102, 51, 102) -Union_6.result().subResult(3).setColor(76, 76, 153) -Union_6.result().subResult(4).setColor(0, 0, 254) - -Partition_1_objects = [model.selection("SOLID", "Recover_1_1"), model.selection("COMPSOLID", "Union_1_1"), model.selection("COMPSOLID", "Extrusion_2_1"), model.selection("COMPSOLID", "demi-sphere")] -Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects) -Partition_1.result().setColor(102, 0, 0) -Partition_1.result().subResult(0).setColor(255, 255, 0) -Partition_1.result().subResult(1).setColor(0, 254, 0) -Partition_1.result().subResult(2).setColor(0, 255, 255) -Partition_1.result().subResult(3).setColor(255, 85, 0) -Partition_1.result().subResult(4).setColor(153, 0, 0) -Partition_1.result().subResult(5).setColor(254, 0, 254) -Partition_1.result().subResult(6).setColor(127, 127, 254) -Partition_1.result().subResult(7).setColor(102, 204, 102) -Partition_1.result().subResult(8).setColor(127, 254, 127) -Partition_1.result().subResult(9).setColor(153, 153, 76) -Partition_1.result().subResult(10).setColor(204, 102, 102) -Partition_1.result().subResult(11).setColor(127, 254, 254) -Partition_1.result().subResult(12).setColor(255, 255, 0) -Partition_1.result().subResult(13).setColor(102, 51, 102) -Partition_1.result().subResult(14).setColor(102, 204, 204) -Partition_1.result().subResult(15).setColor(254, 127, 254) -Partition_1.result().subResult(16).setColor(153, 153, 0) -Partition_1.result().subResult(17).setColor(153, 153, 0) -Partition_1.result().subResult(18).setColor(204, 0, 204) - -Folder_1 = model.addFolder(Part_1_doc, Revolution_1, Union_1) -Folder_2 = model.addFolder(Part_1_doc, Point_3, Union_6) -model.do() - -# check the result -model.testNbResults(Partition_1, 1) -model.testNbSubResults(Partition_1, [19]) -model.testNbSubShapes(Partition_1, GeomAPI_Shape.SOLID, [19]) -model.testNbSubShapes(Partition_1, GeomAPI_Shape.FACE, [199]) -model.testNbSubShapes(Partition_1, GeomAPI_Shape.EDGE, [814]) -model.testNbSubShapes(Partition_1, GeomAPI_Shape.VERTEX, [1628]) -model.testResultsVolumes(Partition_1, [103867.289635450288187712430953979]) - -# change parameter and check validity of the result -Param_Diam.setValue(8) -model.do() - -model.testNbResults(Partition_1, 1) -model.testNbSubResults(Partition_1, [19]) -model.testNbSubShapes(Partition_1, GeomAPI_Shape.SOLID, [19]) -model.testNbSubShapes(Partition_1, GeomAPI_Shape.FACE, [191]) -model.testNbSubShapes(Partition_1, GeomAPI_Shape.EDGE, [744]) -model.testNbSubShapes(Partition_1, GeomAPI_Shape.VERTEX, [1488]) -model.testResultsVolumes(Partition_1, [103221.354557478349306620657444]) - -model.end() - -#assert(model.checkPythonDump()) diff --git a/src/FeaturesPlugin/Test/TestBooleanCompSolids.py b/src/FeaturesPlugin/Test/TestBooleanCompSolids.py index aad16ba71..23dfe5c97 100644 --- a/src/FeaturesPlugin/Test/TestBooleanCompSolids.py +++ b/src/FeaturesPlugin/Test/TestBooleanCompSolids.py @@ -133,8 +133,10 @@ aSession.undo() #========================================================================= aSession.startOperation() aBooleanFt = aPart.addFeature("Fuse") +aBooleanFt.string("creation_method").setValue("advanced") aBooleanFt.selectionList("main_objects").append(modelAPI_ResultCompSolid(extrudedObjects[0]).subResult(1), None) aBooleanFt.selectionList("tool_objects").append(extrudedObjects[1], None) +aBooleanFt.boolean("remove_intersection_edges").setValue(False) aBooleanFt.execute() aSession.finishOperation() diff --git a/src/FeaturesPlugin/Test/TestBooleanFuse_RemoveEdges.py b/src/FeaturesPlugin/Test/TestBooleanFuse_RemoveEdges.py new file mode 100644 index 000000000..6065be805 --- /dev/null +++ b/src/FeaturesPlugin/Test/TestBooleanFuse_RemoveEdges.py @@ -0,0 +1,44 @@ +## 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() +Box_1 = model.addBox(Part_1_doc, 10, 10, 10) +Box_2 = model.addBox(Part_1_doc, 10, 10, 10) +Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_2_1")], model.selection("EDGE", "PartSet/OX"), 5) +Fuse_1 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Box_1_1"), model.selection("SOLID", "Translation_1_1")], True) +model.testHaveNamingSubshapes(Fuse_1, model, Part_1_doc) +model.do() +model.end() + +from GeomAPI import GeomAPI_Shape + +model.testNbResults(Fuse_1, 1) +model.testNbSubResults(Fuse_1, [0]) +model.testNbSubShapes(Fuse_1, GeomAPI_Shape.SOLID, [1]) +model.testNbSubShapes(Fuse_1, GeomAPI_Shape.FACE, [6]) +model.testNbSubShapes(Fuse_1, GeomAPI_Shape.EDGE, [24]) +model.testNbSubShapes(Fuse_1, GeomAPI_Shape.VERTEX, [48]) + +assert(model.checkPythonDump()) diff --git a/src/FeaturesPlugin/Test/TestBooleanFuse_SimpleMode.py b/src/FeaturesPlugin/Test/TestBooleanFuse_SimpleMode.py new file mode 100644 index 000000000..e985d2876 --- /dev/null +++ b/src/FeaturesPlugin/Test/TestBooleanFuse_SimpleMode.py @@ -0,0 +1,44 @@ +## 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() +Box_1 = model.addBox(Part_1_doc, 10, 10, 10) +Box_2 = model.addBox(Part_1_doc, 10, 10, 10) +Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_2_1")], model.selection("EDGE", "PartSet/OX"), 5) +Fuse_1 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Box_1_1"), model.selection("SOLID", "Translation_1_1")]) +model.testHaveNamingSubshapes(Fuse_1, model, Part_1_doc) +model.do() +model.end() + +from GeomAPI import GeomAPI_Shape + +model.testNbResults(Fuse_1, 1) +model.testNbSubResults(Fuse_1, [0]) +model.testNbSubShapes(Fuse_1, GeomAPI_Shape.SOLID, [1]) +model.testNbSubShapes(Fuse_1, GeomAPI_Shape.FACE, [14]) +model.testNbSubShapes(Fuse_1, GeomAPI_Shape.EDGE, [56]) +model.testNbSubShapes(Fuse_1, GeomAPI_Shape.VERTEX, [112]) + +assert(model.checkPythonDump()) diff --git a/src/FeaturesPlugin/Test/_Test2394.py b/src/FeaturesPlugin/Test/_Test2394.py new file mode 100644 index 000000000..13639bba7 --- /dev/null +++ b/src/FeaturesPlugin/Test/_Test2394.py @@ -0,0 +1,258 @@ +# -*- coding: utf-8 -*- + +## Copyright (C) 2018-20xx 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 GeomAPI import * +from SketchAPI import * + +from salome.shaper import model + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() + +model.addParameter(Part_1_doc, "R", "58") +model.addParameter(Part_1_doc, "cote_cube", "R/2") +model.addParameter(Part_1_doc, "theta", "54") +model.addParameter(Part_1_doc, "phi", "36") +model.addParameter(Part_1_doc, "pi", "3.141592653589793") +model.addParameter(Part_1_doc, "x", "R*sin(phi/180*pi)*cos(theta/180*pi)") +model.addParameter(Part_1_doc, "y", "R*sin(phi/180*pi)*sin(theta/180*pi)") +model.addParameter(Part_1_doc, "z", "R*cos(phi/180*pi)") +model.addParameter(Part_1_doc, "haut_ext_tuyau", "5") +model.addParameter(Part_1_doc, "haut_int_tuyau", "14") +Param_Diam = model.addParameter(Part_1_doc, "diam_tuyau", "10") + +Revolution_1 = model.addRevolution(Part_1_doc, [], model.selection("EDGE", "PartSet/OZ"), 90, 0) +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ")) +SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False) +SketchPoint_1 = SketchProjection_1.createdFeature() +SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False) +SketchLine_1 = SketchProjection_2.createdFeature() +SketchArc_1 = Sketch_1.addArc(0, 0, 58, 0, 0, -58, True) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchArc_1.center()) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.result(), SketchArc_1.startPoint()) +SketchLine_2 = Sketch_1.addLine(0, -58, 0, 0) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_2.startPoint()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.endPoint()) +SketchLine_3 = Sketch_1.addLine(0, 0, 58, 0) +SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_3.endPoint()) +SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result()) +SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_2.result(), "R") +Revolution_1.setNestedSketch(Sketch_1) + +Extrusion_1 = model.addExtrusion(Part_1_doc, [], model.selection(), 0, "cote_cube") +Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Revolution_1_1/Generated_Face_2")) +SketchLine_4 = Sketch_2.addLine(29, 0, 0, 0) +SketchLine_5 = Sketch_2.addLine(0, 0, 0, 29) +SketchLine_6 = Sketch_2.addLine(0, 29, 29, 29) +SketchLine_7 = Sketch_2.addLine(29, 29, 29, 0) +SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_4.startPoint()) +SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint()) +SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint()) +SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint()) +SketchConstraintHorizontal_1 = Sketch_2.setHorizontal(SketchLine_4.result()) +SketchConstraintVertical_2 = Sketch_2.setVertical(SketchLine_5.result()) +SketchConstraintHorizontal_2 = Sketch_2.setHorizontal(SketchLine_6.result()) +SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_7.result()) +SketchConstraintLength_2 = Sketch_2.setLength(SketchLine_6.result(), "cote_cube") +SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_6.result(), SketchLine_7.result()) +SketchProjection_3 = Sketch_2.addProjection(model.selection("EDGE", "Revolution_1_1/Generated_Face_2&Revolution_1_1/To_Face_1"), False) +SketchLine_8 = SketchProjection_3.createdFeature() +SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_8.result()) +SketchProjection_4 = Sketch_2.addProjection(model.selection("EDGE", "Revolution_1_1/Generated_Face_2&Revolution_1_1/From_Face_1"), False) +SketchLine_9 = SketchProjection_4.createdFeature() +SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchLine_4.startPoint(), SketchLine_9.result()) +Extrusion_1.setNestedSketch(Sketch_2) + +Fill_1 = model.addFill(Part_1_doc, [model.selection("SOLID", "Revolution_1_1")], [model.selection("SOLID", "Extrusion_1_1")]) + +Point_2 = model.addPoint(Part_1_doc, "x", "y", "-z") +Axis_4 = model.addAxis(Part_1_doc, model.selection("VERTEX", "Point_1"), model.selection("VERTEX", "Fill_1_1_2/Modified_Face_3&Fill_1_1_2/Modified_Face_2&Fill_1_1_2/Modified_Face_1")) +Plane_4 = model.addPlane(Part_1_doc, model.selection("EDGE", "Axis_1"), model.selection("VERTEX", "Point_1"), True) +Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Plane_1"), "haut_ext_tuyau", True) +Plane_5.result().setName("Plane_2 arrivee tuyau") +Plane_6 = model.addPlane(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_3"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/From_Face_1"), 45) +Plane_7 = model.addPlane(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/From_Face_1"), 45) +Plane_8 = model.addPlane(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_4"), "90+45") + +Fill_2 = model.addFill(Part_1_doc, [model.selection("SOLID", "Fill_1_1_1")], [model.selection("FACE", "Plane_5")]) +Fill_3 = model.addFill(Part_1_doc, [model.selection("SOLID", "Fill_2_1_2")], [model.selection("FACE", "Plane_3")]) +Fill_4 = model.addFill(Part_1_doc, [model.selection("SOLID", "Fill_3_1_2")], [model.selection("FACE", "Plane_4")]) +Fill_4.result().setColor(102, 51, 51) +Fill_4.result().subResult(0).setColor(153, 153, 76) +Fill_4.result().subResult(1).setColor(0, 204, 204) +Fill_4.result().subResult(2).setColor(51, 51, 102) +Fill_4.result().subResult(3).setColor(102, 204, 102) +Fill_4.result().subResult(4).setColor(204, 204, 0) + +Union_1 = model.addUnion(Part_1_doc, [model.selection("SOLID", "Fill_4_1_4"), model.selection("SOLID", "Fill_4_1_2")]) + +Point_3 = model.addPoint(Part_1_doc, model.selection("EDGE", "Axis_1"), model.selection("FACE", "Plane_2 arrivee tuyau")) + +Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_2 arrivee tuyau")) +SketchProjection_5 = Sketch_3.addProjection(model.selection("VERTEX", "Point_2"), False) +SketchPoint_2 = SketchProjection_5.createdFeature() +SketchCircle_1 = Sketch_3.addCircle(0, 0, 10) +SketchConstraintCoincidence_13 = Sketch_3.setCoincident(SketchPoint_2.result(), SketchCircle_1.center()) +SketchConstraintRadius_1 = Sketch_3.setRadius(SketchCircle_1.results()[1], "diam_tuyau") +SketchLine_10 = Sketch_3.addLine(-5, 5, 5, 5) +SketchLine_11 = Sketch_3.addLine(5, 5, 5, -5) +SketchLine_12 = Sketch_3.addLine(5, -5, -5, -5) +SketchLine_13 = Sketch_3.addLine(-5, -5, -5, 5) +SketchConstraintCoincidence_14 = Sketch_3.setCoincident(SketchLine_13.endPoint(), SketchLine_10.startPoint()) +SketchConstraintCoincidence_15 = Sketch_3.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint()) +SketchConstraintCoincidence_16 = Sketch_3.setCoincident(SketchLine_11.endPoint(), SketchLine_12.startPoint()) +SketchConstraintCoincidence_17 = Sketch_3.setCoincident(SketchLine_12.endPoint(), SketchLine_13.startPoint()) +SketchConstraintHorizontal_3 = Sketch_3.setHorizontal(SketchLine_10.result()) +SketchConstraintVertical_4 = Sketch_3.setVertical(SketchLine_11.result()) +SketchConstraintHorizontal_4 = Sketch_3.setHorizontal(SketchLine_12.result()) +SketchConstraintVertical_5 = Sketch_3.setVertical(SketchLine_13.result()) +SketchConstraintEqual_2 = Sketch_3.setEqual(SketchLine_10.result(), SketchLine_13.result()) +SketchLine_14 = Sketch_3.addLine(5, 5, 7.071067811865479, 7.071067811865475) +SketchConstraintCoincidence_18 = Sketch_3.setCoincident(SketchLine_10.endPoint(), SketchLine_14.startPoint()) +SketchConstraintCoincidence_19 = Sketch_3.setCoincident(SketchLine_14.endPoint(), SketchCircle_1.results()[1]) +SketchLine_15 = Sketch_3.addLine(-5, -5, -7.071067811865472, -7.071067811865476) +SketchConstraintCoincidence_20 = Sketch_3.setCoincident(SketchLine_12.endPoint(), SketchLine_15.startPoint()) +SketchConstraintCoincidence_21 = Sketch_3.setCoincident(SketchLine_15.endPoint(), SketchCircle_1.results()[1]) +SketchConstraintCollinear_1 = Sketch_3.setCollinear(SketchLine_14.result(), SketchLine_15.result()) +SketchLine_16 = Sketch_3.addLine(7.071067811865478, -7.071067811865476, 5, -5) +SketchConstraintCoincidence_22 = Sketch_3.setCoincident(SketchLine_16.startPoint(), SketchCircle_1.results()[1]) +SketchConstraintCoincidence_23 = Sketch_3.setCoincident(SketchLine_11.endPoint(), SketchLine_16.endPoint()) +SketchLine_17 = Sketch_3.addLine(-5, 5, -7.071067811865472, 7.071067811865476) +SketchConstraintCoincidence_24 = Sketch_3.setCoincident(SketchLine_10.startPoint(), SketchLine_17.startPoint()) +SketchConstraintCoincidence_25 = Sketch_3.setCoincident(SketchLine_17.endPoint(), SketchCircle_1.results()[1]) +SketchConstraintCollinear_2 = Sketch_3.setCollinear(SketchLine_17.result(), SketchLine_16.result()) +SketchConstraintEqual_3 = Sketch_3.setEqual(SketchLine_14.result(), SketchLine_15.result()) +SketchConstraintEqual_4 = Sketch_3.setEqual(SketchLine_17.result(), SketchLine_16.result()) +SketchConstraintLength_3 = Sketch_3.setLength(SketchLine_10.result(), "diam_tuyau") +model.do() + +Extrusion_2_objects = [model.selection("FACE", "Sketch_3/Face-SketchCircle_1_2f-SketchLine_11f-SketchLine_14r-SketchLine_16r"), model.selection("FACE", "Sketch_3/Face-SketchCircle_1_2f-SketchLine_10f-SketchLine_14f-SketchLine_17r"), model.selection("FACE", "Sketch_3/Face-SketchCircle_1_2f-SketchLine_13f-SketchLine_15r-SketchLine_17f"), model.selection("FACE", "Sketch_3/Face-SketchCircle_1_2f-SketchLine_12f-SketchLine_15f-SketchLine_16f")] +Extrusion_2 = model.addExtrusion(Part_1_doc, Extrusion_2_objects, model.selection(), 10, 0) +Extrusion_3 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_10r-SketchLine_11r-SketchLine_12r-SketchLine_13r")], model.selection(), "haut_int_tuyau", 0) + +Sketch_4 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_2_1/To_Face_3")) +SketchProjection_6 = Sketch_4.addProjection(model.selection("VERTEX", "Extrusion_2_1/Generated_Face_2&Extrusion_2_1/Generated_Face_4&Extrusion_2_1/To_Face_4"), False) +SketchPoint_3 = SketchProjection_6.createdFeature() +SketchProjection_7 = Sketch_4.addProjection(model.selection("VERTEX", "Extrusion_2_1/Generated_Face_5&Extrusion_2_1/Generated_Face_7&Extrusion_2_1/To_Face_3"), False) +SketchPoint_4 = SketchProjection_7.createdFeature() +SketchArc_2 = Sketch_4.addArc(0, 0, -7.071067811865476, -7.071067811865472, 7.071067811865476, 7.071067811865472, True) +SketchConstraintCoincidence_26 = Sketch_4.setCoincident(SketchPoint_3.result(), SketchArc_2.startPoint()) +SketchConstraintCoincidence_27 = Sketch_4.setCoincident(SketchPoint_4.result(), SketchArc_2.results()[1]) +SketchLine_18 = Sketch_4.addLine(7.071067811865476, 7.071067811865472, -7.071067811865476, -7.071067811865472) +SketchConstraintCoincidence_28 = Sketch_4.setCoincident(SketchArc_2.endPoint(), SketchLine_18.startPoint()) +SketchConstraintCoincidence_29 = Sketch_4.setCoincident(SketchAPI_Point(SketchPoint_3).coordinates(), SketchLine_18.endPoint()) +SketchProjection_8 = Sketch_4.addProjection(model.selection("VERTEX", "Extrusion_2_1/Generated_Face_13&Extrusion_2_1/Generated_Face_12&Extrusion_2_1/To_Face_1"), False) +SketchPoint_5 = SketchProjection_8.createdFeature() +SketchConstraintCoincidence_30 = Sketch_4.setCoincident(SketchArc_2.endPoint(), SketchAPI_Point(SketchPoint_5).coordinates()) +model.do() + +Revolution_2 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_4/Face-SketchArc_2_2f-SketchLine_18r")], model.selection("EDGE", "Sketch_4/Edge-SketchLine_18"), 0, 180) + +Cut_1 = model.addCut(Part_1_doc, [model.selection("SOLID", "Revolution_2_1")], [model.selection("SOLID", "Extrusion_3_1")]) +Cut_1.result().setName("demi-sphere") + +Plane_9 = model.addPlane(Part_1_doc, model.selection("VERTEX", "Extrusion_2_1/Generated_Face_10&Extrusion_2_1/Generated_Face_1&Extrusion_2_1/From_Face_4"), model.selection("VERTEX", "Extrusion_2_1/Generated_Face_10&Extrusion_2_1/Generated_Face_1&Extrusion_2_1/To_Face_4"), model.selection("VERTEX", "Extrusion_2_1/Generated_Face_2&Extrusion_2_1/Generated_Face_10&Extrusion_2_1/To_Face_4")) +Plane_10 = model.addPlane(Part_1_doc, model.selection("VERTEX", "Extrusion_2_1/Generated_Face_12&Extrusion_2_1/Generated_Face_11&Extrusion_2_1/To_Face_1"), model.selection("VERTEX", "Extrusion_2_1/Generated_Face_13&Extrusion_2_1/Generated_Face_12&Extrusion_2_1/To_Face_1"), model.selection("VERTEX", "Extrusion_2_1/Generated_Face_13&Extrusion_2_1/Generated_Face_12&Extrusion_2_1/From_Face_1")) +Plane_11 = model.addPlane(Part_1_doc, model.selection("VERTEX", "Extrusion_2_1/Generated_Face_5&Extrusion_2_1/Generated_Face_7&Extrusion_2_1/To_Face_3"), model.selection("VERTEX", "Extrusion_2_1/Generated_Face_3&Extrusion_2_1/Generated_Face_7&Extrusion_2_1/To_Face_3"), model.selection("VERTEX", "Extrusion_2_1/Generated_Face_5&Extrusion_2_1/Generated_Face_7&Extrusion_2_1/From_Face_3")) +Plane_12 = model.addPlane(Part_1_doc, model.selection("VERTEX", "Extrusion_2_1/Generated_Face_1&Extrusion_2_1/Generated_Face_4&Extrusion_2_1/To_Face_4"), model.selection("VERTEX", "Extrusion_2_1/Generated_Face_2&Extrusion_2_1/Generated_Face_4&Extrusion_2_1/To_Face_4"), model.selection("VERTEX", "Extrusion_2_1/Generated_Face_2&Extrusion_2_1/Generated_Face_4&Extrusion_2_1/From_Face_4")) + +Recover_1 = model.addRecover(Part_1_doc, Cut_1, [Extrusion_3.result()]) + +Plane_13 = model.addPlane(Part_1_doc, model.selection("FACE", "Recover_1_1/Shape4"), model.selection("EDGE", "Recover_1_1/Shape4&Recover_1_1/Shape6"), "90+45") +Plane_14 = model.addPlane(Part_1_doc, model.selection("FACE", "Recover_1_1/Shape1"), model.selection("EDGE", "Recover_1_1/Shape1&Recover_1_1/Shape6"), "90+45") +Plane_15 = model.addPlane(Part_1_doc, model.selection("FACE", "Recover_1_1/Shape2"), model.selection("EDGE", "Recover_1_1/Shape2&Recover_1_1/Shape6"), "90+45") +Plane_16 = model.addPlane(Part_1_doc, model.selection("FACE", "Recover_1_1/Shape6"), model.selection("EDGE", "Recover_1_1/Shape3&Recover_1_1/Shape6"), 45) + +Fill_5_objects_2 = [model.selection("FACE", "Plane_6"), model.selection("FACE", "Plane_7"), model.selection("FACE", "Plane_8"), model.selection("FACE", "Plane_9"), model.selection("FACE", "Plane_10"), model.selection("FACE", "Plane_11"), model.selection("FACE", "Plane_12"), model.selection("FACE", "Plane_13")] +Fill_5 = model.addFill(Part_1_doc, [model.selection("SOLID", "demi-sphere")], Fill_5_objects_2) + +Union_2_objects = [model.selection("SOLID", "Fill_5_1_14"), model.selection("SOLID", "Fill_5_1_15"), model.selection("SOLID", "Fill_5_1_16")] +Union_2 = model.addUnion(Part_1_doc, Union_2_objects) +Union_3_objects = [model.selection("SOLID", "Fill_5_1_8/Fill_5_1_8"), model.selection("SOLID", "Fill_5_1_4/Fill_5_1_4"), model.selection("SOLID", "Fill_5_1_9/Fill_5_1_9"), model.selection("SOLID", "Fill_5_1_11/Fill_5_1_11")] +Union_3 = model.addUnion(Part_1_doc, Union_3_objects) +Union_4_objects = [model.selection("SOLID", "Fill_5_1_6/Fill_5_1_6"), model.selection("SOLID", "Fill_5_1_10/Fill_5_1_10"), model.selection("SOLID", "Fill_5_1_13/Fill_5_1_13")] +Union_4 = model.addUnion(Part_1_doc, Union_4_objects) +Union_5_objects = [model.selection("SOLID", "Fill_5_1_2/Fill_5_1_2"), model.selection("SOLID", "Fill_5_1_1/Fill_5_1_1"), model.selection("SOLID", "Fill_5_1_3/Fill_5_1_3")] +Union_5 = model.addUnion(Part_1_doc, Union_5_objects) +Union_6_objects = [model.selection("SOLID", "Fill_5_1_5/Fill_5_1_5"), model.selection("SOLID", "Fill_5_1_7/Fill_5_1_7"), model.selection("SOLID", "Fill_5_1_12/Fill_5_1_12")] +Union_6 = model.addUnion(Part_1_doc, Union_6_objects) +Union_6.result().setColor(0, 0, 204) +Union_6.result().subResult(0).setColor(204, 102, 102) +Union_6.result().subResult(1).setColor(127, 254, 127) +Union_6.result().subResult(2).setColor(102, 51, 102) +Union_6.result().subResult(3).setColor(76, 76, 153) +Union_6.result().subResult(4).setColor(0, 0, 254) + +Partition_1_objects = [model.selection("SOLID", "Recover_1_1"), model.selection("COMPSOLID", "Union_1_1"), model.selection("COMPSOLID", "Extrusion_2_1"), model.selection("COMPSOLID", "demi-sphere")] +Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects) +Partition_1.result().setColor(102, 0, 0) +Partition_1.result().subResult(0).setColor(255, 255, 0) +Partition_1.result().subResult(1).setColor(0, 254, 0) +Partition_1.result().subResult(2).setColor(0, 255, 255) +Partition_1.result().subResult(3).setColor(255, 85, 0) +Partition_1.result().subResult(4).setColor(153, 0, 0) +Partition_1.result().subResult(5).setColor(254, 0, 254) +Partition_1.result().subResult(6).setColor(127, 127, 254) +Partition_1.result().subResult(7).setColor(102, 204, 102) +Partition_1.result().subResult(8).setColor(127, 254, 127) +Partition_1.result().subResult(9).setColor(153, 153, 76) +Partition_1.result().subResult(10).setColor(204, 102, 102) +Partition_1.result().subResult(11).setColor(127, 254, 254) +Partition_1.result().subResult(12).setColor(255, 255, 0) +Partition_1.result().subResult(13).setColor(102, 51, 102) +Partition_1.result().subResult(14).setColor(102, 204, 204) +Partition_1.result().subResult(15).setColor(254, 127, 254) +Partition_1.result().subResult(16).setColor(153, 153, 0) +Partition_1.result().subResult(17).setColor(153, 153, 0) +Partition_1.result().subResult(18).setColor(204, 0, 204) + +Folder_1 = model.addFolder(Part_1_doc, Revolution_1, Union_1) +Folder_2 = model.addFolder(Part_1_doc, Point_3, Union_6) +model.do() + +# check the result +model.testNbResults(Partition_1, 1) +model.testNbSubResults(Partition_1, [19]) +model.testNbSubShapes(Partition_1, GeomAPI_Shape.SOLID, [19]) +model.testNbSubShapes(Partition_1, GeomAPI_Shape.FACE, [199]) +model.testNbSubShapes(Partition_1, GeomAPI_Shape.EDGE, [814]) +model.testNbSubShapes(Partition_1, GeomAPI_Shape.VERTEX, [1628]) +model.testResultsVolumes(Partition_1, [103867.289635450288187712430953979]) + +# change parameter and check validity of the result +Param_Diam.setValue(8) +model.do() + +model.testNbResults(Partition_1, 1) +model.testNbSubResults(Partition_1, [19]) +model.testNbSubShapes(Partition_1, GeomAPI_Shape.SOLID, [19]) +model.testNbSubShapes(Partition_1, GeomAPI_Shape.FACE, [191]) +model.testNbSubShapes(Partition_1, GeomAPI_Shape.EDGE, [744]) +model.testNbSubShapes(Partition_1, GeomAPI_Shape.VERTEX, [1488]) +model.testResultsVolumes(Partition_1, [103221.354557478349306620657444]) + +model.end() + +#assert(model.checkPythonDump()) diff --git a/src/FeaturesPlugin/boolean_fuse_widget.xml b/src/FeaturesPlugin/boolean_fuse_widget.xml new file mode 100644 index 000000000..149c79b84 --- /dev/null +++ b/src/FeaturesPlugin/boolean_fuse_widget.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/FeaturesPlugin/icons/bool_fuse_advanced.png b/src/FeaturesPlugin/icons/bool_fuse_advanced.png new file mode 100644 index 000000000..c96a1d559 Binary files /dev/null and b/src/FeaturesPlugin/icons/bool_fuse_advanced.png differ diff --git a/src/FeaturesPlugin/icons/bool_fuse_simple.png b/src/FeaturesPlugin/icons/bool_fuse_simple.png new file mode 100644 index 000000000..9d86c9bfb Binary files /dev/null and b/src/FeaturesPlugin/icons/bool_fuse_simple.png differ diff --git a/src/FeaturesPlugin/plugin-Features.xml b/src/FeaturesPlugin/plugin-Features.xml index 72b4b181c..68b139b51 100644 --- a/src/FeaturesPlugin/plugin-Features.xml +++ b/src/FeaturesPlugin/plugin-Features.xml @@ -70,7 +70,7 @@ email : webmaster.salome@opencascade.com - +