From 3c59f3791eb40076c14ad4cd2e5c0d260ec643fa Mon Sep 17 00:00:00 2001 From: azv Date: Wed, 15 May 2019 10:12:15 +0300 Subject: [PATCH] Task 3.2. Concealment into multi-level Compounds Update behavior of UNION operation to keep hierarchy of compounds. --- src/FeaturesAPI/FeaturesAPI_Union.cpp | 19 ++- src/FeaturesAPI/FeaturesAPI_Union.h | 6 +- src/FeaturesPlugin/CMakeLists.txt | 3 + src/FeaturesPlugin/FeaturesPlugin_Union.cpp | 159 +++++++----------- src/FeaturesPlugin/FeaturesPlugin_Union.h | 9 +- .../FeaturesPlugin_VersionedBoolean.cpp | 59 +++++-- .../FeaturesPlugin_VersionedBoolean.h | 9 +- .../Test/TestUnionFaces_v20190506.py | 45 +++++ .../Test/TestUnion_MultiLevelCompound_v0.py | 87 ++++++++++ .../TestUnion_MultiLevelCompound_v20190506.py | 87 ++++++++++ 10 files changed, 359 insertions(+), 124 deletions(-) create mode 100644 src/FeaturesPlugin/Test/TestUnionFaces_v20190506.py create mode 100644 src/FeaturesPlugin/Test/TestUnion_MultiLevelCompound_v0.py create mode 100644 src/FeaturesPlugin/Test/TestUnion_MultiLevelCompound_v20190506.py diff --git a/src/FeaturesAPI/FeaturesAPI_Union.cpp b/src/FeaturesAPI/FeaturesAPI_Union.cpp index e32efa1ae..7c960b135 100644 --- a/src/FeaturesAPI/FeaturesAPI_Union.cpp +++ b/src/FeaturesAPI/FeaturesAPI_Union.cpp @@ -31,10 +31,12 @@ FeaturesAPI_Union::FeaturesAPI_Union(const std::shared_ptr& th //================================================================================================ FeaturesAPI_Union::FeaturesAPI_Union(const std::shared_ptr& theFeature, - const std::list& theBaseObjects) + const std::list& theBaseObjects, + const int theVersion) : ModelHighAPI_Interface(theFeature) { if(initialize()) { + fillAttribute(theVersion, theFeature->integer(FeaturesPlugin_VersionedBoolean::VERSION_ID())); setBase(theBaseObjects); } } @@ -61,15 +63,22 @@ void FeaturesAPI_Union::dump(ModelHighAPI_Dumper& theDumper) const AttributeSelectionListPtr anAttrObjects = aBase->selectionList(FeaturesPlugin_Union::BASE_OBJECTS_ID()); + AttributeIntegerPtr aVersion = + aBase->integer(FeaturesPlugin_Union::VERSION_ID()); - theDumper << aBase << " = model.addUnion(" << aDocName << - ", " << anAttrObjects << ")" << std::endl; + theDumper << aBase << " = model.addUnion(" << aDocName << ", " << anAttrObjects; + + if (aVersion && aVersion->isInitialized()) + theDumper << ", " << aVersion->value(); + + theDumper << ")" << std::endl; } //================================================================================================== UnionPtr addUnion(const std::shared_ptr& thePart, - const std::list& theBaseObjects) + const std::list& theBaseObjects, + const int theVersion) { std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_Union::ID()); - return UnionPtr(new FeaturesAPI_Union(aFeature, theBaseObjects)); + return UnionPtr(new FeaturesAPI_Union(aFeature, theBaseObjects, theVersion)); } diff --git a/src/FeaturesAPI/FeaturesAPI_Union.h b/src/FeaturesAPI/FeaturesAPI_Union.h index cc977c62e..ff1f7820a 100644 --- a/src/FeaturesAPI/FeaturesAPI_Union.h +++ b/src/FeaturesAPI/FeaturesAPI_Union.h @@ -43,7 +43,8 @@ public: /// Constructor with values. FEATURESAPI_EXPORT explicit FeaturesAPI_Union(const std::shared_ptr& theFeature, - const std::list& theBaseObjects); + const std::list& theBaseObjects, + const int theVersion = 0); /// Destructor. FEATURESAPI_EXPORT @@ -69,6 +70,7 @@ typedef std::shared_ptr UnionPtr; /// \brief Create Union feature. FEATURESAPI_EXPORT UnionPtr addUnion(const std::shared_ptr& thePart, - const std::list& theBaseObjects); + const std::list& theBaseObjects, + const int theVersion = 0); #endif // FeaturesAPI_Union_H_ diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index 417760da5..0ceae4e1c 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -492,4 +492,7 @@ ADD_UNIT_TESTS(TestExtrusion.py TestPartition_MultiLevelCompound_v20190506_1.py TestPartition_MultiLevelCompound_v20190506_2.py TestPartition_MultiLevelCompound_v20190506_3.py + TestUnion_MultiLevelCompound_v0.py + TestUnion_MultiLevelCompound_v20190506.py + TestUnionFaces_v20190506.py ) diff --git a/src/FeaturesPlugin/FeaturesPlugin_Union.cpp b/src/FeaturesPlugin/FeaturesPlugin_Union.cpp index 8daf2723e..c2385e938 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Union.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Union.cpp @@ -20,10 +20,11 @@ #include "FeaturesPlugin_Union.h" #include +#include #include #include +#include #include -#include #include #include @@ -32,6 +33,8 @@ #include #include +static const int THE_UNION_VERSION_1 = 20190506; + //================================================================================================= FeaturesPlugin_Union::FeaturesPlugin_Union() { @@ -41,124 +44,90 @@ FeaturesPlugin_Union::FeaturesPlugin_Union() void FeaturesPlugin_Union::initAttributes() { data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId()); + initVersion(THE_UNION_VERSION_1, selectionList(BASE_OBJECTS_ID())); } //================================================================================================= void FeaturesPlugin_Union::execute() { - ListOfShape anObjects; - std::map, ListOfShape> aCompSolidsObjects; + ObjectHierarchy anObjects; + ListOfShape anEmptyList; // Getting objects. - AttributeSelectionListPtr anObjectsSelList = - selectionList(FeaturesPlugin_Union::BASE_OBJECTS_ID()); - for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) { - AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex); - std::shared_ptr anObject = anObjectAttr->value(); - if(!anObject.get()) { - return; - } - ResultPtr aContext = anObjectAttr->context(); - ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext); - if(aResCompSolidPtr.get()) { - 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); - } - } - - // 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; - anObjects.insert(anObjects.end(), aUsedInOperationSolids.begin(), aUsedInOperationSolids.end()); - - // Collect solids from compsolid which will not be modified in boolean operation. - for(GeomAPI_ShapeIterator anExp(aCompSolid); 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); - } - } - } + if (!processAttribute(BASE_OBJECTS_ID(), anObjects, anEmptyList)) + return; - if(anObjects.size() < 2) { + if(anObjects.Objects().size() < 2) { setError("Error: Not enough objects for operation. Should be at least 2."); return; } - // Fuse objects. std::string anError; - std::shared_ptr anAlgo; - ListOfShape aTools; - if (anObjects.front()->shapeType() == GeomAPI_Shape::SOLID) { - aTools.splice(aTools.begin(), anObjects, anObjects.begin()); - anAlgo.reset(new GeomAlgoAPI_Boolean(anObjects, - aTools, - GeomAlgoAPI_Tools::BOOL_FUSE)); - } else { - anAlgo.reset(new GeomAlgoAPI_UnifySameDomain(anObjects)); + int aResultIndex = 0; + std::vector aResultBaseAlgoList; + ListOfShape aResultShapesList; + + int aUnionVersion = version(); + GeomShapePtr aResultCompound = GeomAlgoAPI_CompoundBuilder::compound(ListOfShape()); + + // Fuse objects. + bool isOk = true; + for (ObjectHierarchy::Iterator anObjectsIt = anObjects.Begin(); + anObjectsIt != anObjects.End() && isOk; + ++anObjectsIt) { + GeomShapePtr anObject = *anObjectsIt; + GeomShapePtr aParent = anObjects.Parent(anObject, false); + + if (aParent && aParent->shapeType() <= GeomAPI_Shape::COMPSOLID) { + // get parent once again to mark it and the subs as processed + aParent = anObjects.Parent(anObject); + // compsolid handling + isOk = processCompsolid(GeomAlgoAPI_Tools::BOOL_FUSE, + anObjects, aParent, anEmptyList, anEmptyList, + aResultIndex, aResultBaseAlgoList, aResultShapesList, + aResultCompound); + } else { + // process object as is + isOk = processObject(GeomAlgoAPI_Tools::BOOL_FUSE, + anObject, anEmptyList, anEmptyList, + aResultIndex, aResultBaseAlgoList, aResultShapesList, + aResultCompound); + } } - // Checking that the algorithm worked properly. std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); - GeomAPI_DataMapOfShapeShape aMapOfShapes; - if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(anAlgo, getKind(), anError)) { - setError(anError); - return; + for (std::vector::iterator + aRBAIt = aResultBaseAlgoList.begin(); + aRBAIt != aResultBaseAlgoList.end(); ++aRBAIt) { + aMakeShapeList->appendAlgo(aRBAIt->makeShape); } - GeomShapePtr aShape = anAlgo->shape(); - aMakeShapeList->appendAlgo(anAlgo); - aMapOfShapes.merge(anAlgo->mapOfSubShapes()); - - // Store original shapes for naming. - anObjects.splice(anObjects.begin(), aTools); - anObjects.insert(anObjects.end(), aShapesToAdd.begin(), aShapesToAdd.end()); - - // Combine result with not used solids from compsolid. - if(aShapesToAdd.size() > 0) { - aShapesToAdd.push_back(aShape); - std::shared_ptr aFillerAlgo( - new GeomAlgoAPI_PaveFiller(aShapesToAdd, true)); - if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aFillerAlgo, getKind(), anError)) { - setError(anError); - return; + GeomShapePtr aShape; + GeomAPI_ShapeIterator aCIt(aResultCompound); + if (aUnionVersion < THE_UNION_VERSION_1) { + // if the compound consists of a single sub-shape, take it, + // otherwise, take the full compound + aShape = aCIt.current(); + aCIt.next(); + if (aCIt.more()) + aShape = aResultCompound; + } + else { + // merge hierarchies of compounds containing objects and tools + aShape = keepUnusedSubsOfCompound(aCIt.current(), anObjects, ObjectHierarchy(), aMakeShapeList); + for (aCIt.next(); aCIt.more(); aCIt.next()) { + std::shared_ptr aBuilder(new GeomAlgoAPI_ShapeBuilder); + aBuilder->add(aShape, aCIt.current()); + aMakeShapeList->appendAlgo(aBuilder); } - - aShape = aFillerAlgo->shape(); - aMakeShapeList->appendAlgo(aFillerAlgo); - aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes()); } - // workaround: make copy to name edges correctly // Store result and naming. - std::shared_ptr aResultBody = document()->createBody(data()); - aResultBody->storeModified(anObjects.front(), aShape); + ListOfShape anObjectsList = anObjects.Objects(); + aResultBody->storeModified(anObjectsList.front(), aShape); - for(ListOfShape::const_iterator anIter = anObjects.begin(); anIter != anObjects.end(); ++anIter) { + for(ListOfShape::const_iterator anIter = anObjectsList.begin(); anIter != anObjectsList.end(); ++anIter) { aResultBody->loadModifiedShapes(aMakeShapeList, *anIter, GeomAPI_Shape::EDGE); aResultBody->loadModifiedShapes(aMakeShapeList, *anIter, GeomAPI_Shape::FACE); //aResultBody->loadDeletedShapes(&aMakeShapeList, *anIter, GeomAPI_Shape::FACE, aDeletedTag); diff --git a/src/FeaturesPlugin/FeaturesPlugin_Union.h b/src/FeaturesPlugin/FeaturesPlugin_Union.h index f0bd1d722..797a5573f 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Union.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Union.h @@ -20,18 +20,13 @@ #ifndef FeaturesPlugin_Union_H_ #define FeaturesPlugin_Union_H_ -#include "FeaturesPlugin.h" -#include - -#include - -class GeomAlgoAPI_MakeShape; +#include "FeaturesPlugin_VersionedBoolean.h" /// \class FeaturesPlugin_Union /// \ingroup Plugins /// \brief Feature for applying of Union operations on Shapes. Union removes shared shapes from /// several shapes and combines them into one. -class FeaturesPlugin_Union : public ModelAPI_Feature +class FeaturesPlugin_Union : public FeaturesPlugin_VersionedBoolean { public: /// Feature kind. diff --git a/src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.cpp b/src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.cpp index 9021a192f..ddb04e593 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -45,6 +46,30 @@ #include #include +static void performBoolean(const GeomAlgoAPI_Tools::BOPType theBooleanType, + GeomMakeShapePtr& theBooleanAlgo, + const ListOfShape& theObjects, + const ListOfShape& theTools) +{ + if (theBooleanType == GeomAlgoAPI_Tools::BOOL_PARTITION) + theBooleanAlgo.reset(new GeomAlgoAPI_Partition(theObjects, theTools)); + else { + // separate processing of FUSE, if only objects are given + if (theBooleanType == GeomAlgoAPI_Tools::BOOL_FUSE && theTools.empty()) { + if (theObjects.front()->shapeType() == GeomAPI_Shape::FACE) + theBooleanAlgo.reset(new GeomAlgoAPI_UnifySameDomain(theObjects)); + else { + ListOfShape anObjects = theObjects; + ListOfShape aTools; + aTools.splice(aTools.begin(), anObjects, anObjects.begin()); + theBooleanAlgo.reset(new GeomAlgoAPI_Boolean(anObjects, aTools, theBooleanType)); + } + } + else + theBooleanAlgo.reset(new GeomAlgoAPI_Boolean(theObjects, theTools, theBooleanType)); + } +} + //================================================================================================= void FeaturesPlugin_VersionedBoolean::initVersion(const int theVersion, const AttributePtr theObjectsAttr, @@ -198,7 +223,7 @@ bool FeaturesPlugin_VersionedBoolean::processObject( //================================================================================================= bool FeaturesPlugin_VersionedBoolean::processCompsolid( const GeomAlgoAPI_Tools::BOPType theBooleanType, - const ObjectHierarchy& theCompsolidHierarchy, + ObjectHierarchy& theCompsolidHierarchy, const GeomShapePtr& theCompsolid, const ListOfShape& theTools, const ListOfShape& thePlanes, @@ -220,12 +245,7 @@ bool FeaturesPlugin_VersionedBoolean::processCompsolid( aToolsWithPlanes.insert(aToolsWithPlanes.end(), aPlanesCopy.begin(), aPlanesCopy.end()); std::shared_ptr aBoolAlgo; - if (theBooleanType == GeomAlgoAPI_Tools::BOOL_PARTITION) - aBoolAlgo.reset(new GeomAlgoAPI_Partition(aUsedInOperationSolids, aToolsWithPlanes)); - else - aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aUsedInOperationSolids, - aToolsWithPlanes, - theBooleanType)); + performBoolean(theBooleanType, aBoolAlgo, aUsedInOperationSolids, aToolsWithPlanes); // Checking that the algorithm worked properly. std::string anError; @@ -239,6 +259,8 @@ bool FeaturesPlugin_VersionedBoolean::processCompsolid( // Add result to not used solids from compsolid. if (!aNotUsedSolids.empty()) { + theCompsolidHierarchy.MarkProcessed(aNotUsedSolids); + ListOfShape aShapesToAdd = aNotUsedSolids; aShapesToAdd.push_back(aBoolAlgo->shape()); std::shared_ptr aFillerAlgo( @@ -296,7 +318,7 @@ bool FeaturesPlugin_VersionedBoolean::processCompsolid( //================================================================================================= bool FeaturesPlugin_VersionedBoolean::processCompound( const GeomAlgoAPI_Tools::BOPType theBooleanType, - const ObjectHierarchy& theCompoundHierarchy, + ObjectHierarchy& theCompoundHierarchy, const GeomShapePtr& theCompound, const ListOfShape& theTools, int& theResultIndex, @@ -314,10 +336,8 @@ bool FeaturesPlugin_VersionedBoolean::processCompound( } std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); - std::shared_ptr aBoolAlgo( - new GeomAlgoAPI_Boolean(aUsedInOperationShapes, - theTools, - theBooleanType)); + std::shared_ptr aBoolAlgo; + performBoolean(theBooleanType, aBoolAlgo, aUsedInOperationShapes, theTools); // Checking that the algorithm worked properly. std::string anError; @@ -331,6 +351,8 @@ bool FeaturesPlugin_VersionedBoolean::processCompound( // Add result to not used shape from compound. if (!aNotUsedShapes.empty()) { + theCompoundHierarchy.MarkProcessed(aNotUsedShapes); + ListOfShape aShapesForResult = aNotUsedShapes; if (aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) { for (GeomAPI_ShapeIterator aResultIt(aResultShape); aResultIt.more(); aResultIt.next()) { @@ -486,6 +508,17 @@ GeomShapePtr FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Parent(const Geom return aParent; } +void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::MarkProcessed(const GeomShapePtr& theShape) +{ + myProcessedObjects.insert(theShape); +} + +void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::MarkProcessed(const ListOfShape& theShapes) +{ + for (ListOfShape::const_iterator anIt = theShapes.begin(); anIt != theShapes.end(); ++anIt) + MarkProcessed(*anIt); +} + void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::ObjectsByType( ListOfShape& theShapesByType, ListOfShape& theOtherShapes, @@ -542,7 +575,7 @@ bool FeaturesPlugin_VersionedBoolean::ObjectHierarchy::IsEmpty() const void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::CompoundsOfUnusedObjects( ListOfShape& theDestination) const { - SetOfShape aUsedObjects; + SetOfShape aUsedObjects = myProcessedObjects; aUsedObjects.insert(myObjects.begin(), myObjects.end()); for (std::vector::const_iterator anIt = mySubshapes.begin(); diff --git a/src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.h b/src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.h index 97266c776..4d95da152 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.h +++ b/src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.h @@ -87,6 +87,11 @@ protected: /// By default, the parent and all its subshapes are marked as processed for further skip. GeomShapePtr Parent(const GeomShapePtr& theShape, bool theMarkProcessed = true); + /// Marke the shape as already processed + void MarkProcessed(const GeomShapePtr& theShape); + /// Marke list ofshapes as already processed + void MarkProcessed(const ListOfShape& theShapes); + /// Split compound/compsolid shape for subshapes selected for Boolean operation and the other. void SplitCompound(const GeomShapePtr& theCompShape, ListOfShape& theUsed, @@ -159,7 +164,7 @@ protected: /// is added to this compound, and corresponding ResultBody is not generated. /// \return \c false if something went wrong bool processCompsolid(const GeomAlgoAPI_Tools::BOPType theBooleanType, - const ObjectHierarchy& theCompsolidHierarchy, + ObjectHierarchy& theCompsolidHierarchy, const GeomShapePtr& theCompsolid, const ListOfShape& theTools, const ListOfShape& thePlanes, @@ -173,7 +178,7 @@ protected: /// is added to this compound, and corresponding ResultBody is not generated. /// \return \c false if something went wrong bool processCompound(const GeomAlgoAPI_Tools::BOPType theBooleanType, - const ObjectHierarchy& theCompoundHierarchy, + ObjectHierarchy& theCompoundHierarchy, const GeomShapePtr& theCompound, const ListOfShape& theTools, int& theResultIndex, diff --git a/src/FeaturesPlugin/Test/TestUnionFaces_v20190506.py b/src/FeaturesPlugin/Test/TestUnionFaces_v20190506.py new file mode 100644 index 000000000..21beac1c6 --- /dev/null +++ b/src/FeaturesPlugin/Test/TestUnionFaces_v20190506.py @@ -0,0 +1,45 @@ +# Copyright (C) 2014-2019 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(-5.197255574614073, 0.1732418524871273, 67.586529314451) +model.do() +Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_1/SketchCircle_1_2")]) +Partition_1_objects = [model.selection("FACE", "Face_1_1"), model.selection("FACE", "PartSet/YOZ"), model.selection("FACE", "PartSet/XOZ")] +Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects) +Union_1 = model.addUnion(Part_1_doc, [model.selection("FACE", "Partition_1_1_1"), model.selection("FACE", "Partition_1_1_2")], 20190506) +model.do() +model.end() + +from GeomAPI import GeomAPI_Shape + +model.testNbResults(Union_1, 1) +model.testNbSubResults(Union_1, [3]) +model.testNbSubShapes(Union_1, GeomAPI_Shape.SOLID, [0]) +model.testNbSubShapes(Union_1, GeomAPI_Shape.FACE, [3]) +model.testNbSubShapes(Union_1, GeomAPI_Shape.EDGE, [10]) +model.testNbSubShapes(Union_1, GeomAPI_Shape.VERTEX, [20]) + +assert(model.checkPythonDump()) diff --git a/src/FeaturesPlugin/Test/TestUnion_MultiLevelCompound_v0.py b/src/FeaturesPlugin/Test/TestUnion_MultiLevelCompound_v0.py new file mode 100644 index 000000000..f4dd6fed3 --- /dev/null +++ b/src/FeaturesPlugin/Test/TestUnion_MultiLevelCompound_v0.py @@ -0,0 +1,87 @@ +# Copyright (C) 2014-2019 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 SketchAPI import * + +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")) +SketchLine_1 = Sketch_1.addLine(25, -25, -25, -25) +SketchLine_2 = Sketch_1.addLine(-25, -25, -25, 25) +SketchLine_3 = Sketch_1.addLine(-25, 25, 25, 25) +SketchLine_4 = Sketch_1.addLine(25, 25, 25, -25) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint()) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result()) +SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result()) +SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result()) +SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result()) +SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_2.result()) +SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 50) +SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False) +SketchPoint_1 = SketchProjection_1.createdFeature() +SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.result(), 25, True) +SketchConstraintDistance_2 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.result(), 25, True) +SketchMultiRotation_1_objects = [SketchLine_1.result(), SketchLine_2.result(), SketchLine_3.result(), SketchLine_4.result()] +SketchMultiRotation_1 = Sketch_1.addRotation(SketchMultiRotation_1_objects, SketchAPI_Point(SketchPoint_1).coordinates(), 45, 2, True) +[SketchLine_5, SketchLine_6, SketchLine_7, SketchLine_8] = SketchMultiRotation_1.rotated() +SketchLine_8.setName("SketchLine_14") +SketchLine_8.result().setName("SketchLine_14") +SketchLine_7.setName("SketchLine_11") +SketchLine_7.result().setName("SketchLine_11") +SketchLine_6.setName("SketchLine_8") +SketchLine_6.result().setName("SketchLine_8") +SketchCircle_1 = Sketch_1.addCircle(80, 0, 20) +SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 20) +SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False) +SketchLine_9 = SketchProjection_2.createdFeature() +SketchLine_9.setName("SketchLine_9") +SketchLine_9.result().setName("SketchLine_9") +SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchCircle_1.center(), SketchLine_9.result()) +SketchConstraintDistance_3 = Sketch_1.setDistance(SketchAPI_Line(SketchLine_9).startPoint(), SketchCircle_1.center(), 80, True) +SketchMultiRotation_2 = Sketch_1.addRotation([SketchCircle_1.results()[1]], SketchAPI_Line(SketchLine_9).startPoint(), 360, 8, True) +[SketchCircle_2, SketchCircle_3, SketchCircle_4, SketchCircle_5, SketchCircle_6, SketchCircle_7, SketchCircle_8] = SketchMultiRotation_2.rotated() +model.do() +Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), 50, 0) +Compound_1_objects = [model.selection("COMPSOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_1_2"), model.selection("SOLID", "Extrusion_1_3"), model.selection("SOLID", "Extrusion_1_4"), model.selection("SOLID", "Extrusion_1_5"), model.selection("SOLID", "Extrusion_1_6"), model.selection("SOLID", "Extrusion_1_7"), model.selection("SOLID", "Extrusion_1_8"), model.selection("SOLID", "Extrusion_1_9")] +Compound_1 = model.addCompound(Part_1_doc, Compound_1_objects) +Union_1_objects = [model.selection("SOLID", "Compound_1_1_1_1"), model.selection("SOLID", "Compound_1_1_1_2"), model.selection("SOLID", "Compound_1_1_1_3")] +Union_1 = model.addUnion(Part_1_doc, Union_1_objects) + +model.testHaveNamingSubshapes(Union_1, model, Part_1_doc) + +model.end() + +from GeomAPI import GeomAPI_Shape + +model.testNbResults(Union_1, 1) +model.testNbSubResults(Union_1, [7]) +model.testNbSubShapes(Union_1, GeomAPI_Shape.SOLID, [7]) +model.testNbSubShapes(Union_1, GeomAPI_Shape.FACE, [46]) +model.testNbSubShapes(Union_1, GeomAPI_Shape.EDGE, [176]) +model.testNbSubShapes(Union_1, GeomAPI_Shape.VERTEX, [352]) +model.testResultsVolumes(Union_1, [146446.6094067262311]) + +assert(model.checkPythonDump()) diff --git a/src/FeaturesPlugin/Test/TestUnion_MultiLevelCompound_v20190506.py b/src/FeaturesPlugin/Test/TestUnion_MultiLevelCompound_v20190506.py new file mode 100644 index 000000000..63d3e03cb --- /dev/null +++ b/src/FeaturesPlugin/Test/TestUnion_MultiLevelCompound_v20190506.py @@ -0,0 +1,87 @@ +# Copyright (C) 2014-2019 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 SketchAPI import * + +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")) +SketchLine_1 = Sketch_1.addLine(25, -25, -25, -25) +SketchLine_2 = Sketch_1.addLine(-25, -25, -25, 25) +SketchLine_3 = Sketch_1.addLine(-25, 25, 25, 25) +SketchLine_4 = Sketch_1.addLine(25, 25, 25, -25) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint()) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result()) +SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result()) +SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result()) +SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result()) +SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_2.result()) +SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 50) +SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False) +SketchPoint_1 = SketchProjection_1.createdFeature() +SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.result(), 25, True) +SketchConstraintDistance_2 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.result(), 25, True) +SketchMultiRotation_1_objects = [SketchLine_1.result(), SketchLine_2.result(), SketchLine_3.result(), SketchLine_4.result()] +SketchMultiRotation_1 = Sketch_1.addRotation(SketchMultiRotation_1_objects, SketchAPI_Point(SketchPoint_1).coordinates(), 45, 2, True) +[SketchLine_5, SketchLine_6, SketchLine_7, SketchLine_8] = SketchMultiRotation_1.rotated() +SketchLine_8.setName("SketchLine_14") +SketchLine_8.result().setName("SketchLine_14") +SketchLine_7.setName("SketchLine_11") +SketchLine_7.result().setName("SketchLine_11") +SketchLine_6.setName("SketchLine_8") +SketchLine_6.result().setName("SketchLine_8") +SketchCircle_1 = Sketch_1.addCircle(80, 0, 20) +SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 20) +SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False) +SketchLine_9 = SketchProjection_2.createdFeature() +SketchLine_9.setName("SketchLine_9") +SketchLine_9.result().setName("SketchLine_9") +SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchCircle_1.center(), SketchLine_9.result()) +SketchConstraintDistance_3 = Sketch_1.setDistance(SketchAPI_Line(SketchLine_9).startPoint(), SketchCircle_1.center(), 80, True) +SketchMultiRotation_2 = Sketch_1.addRotation([SketchCircle_1.results()[1]], SketchAPI_Line(SketchLine_9).startPoint(), 360, 8, True) +[SketchCircle_2, SketchCircle_3, SketchCircle_4, SketchCircle_5, SketchCircle_6, SketchCircle_7, SketchCircle_8] = SketchMultiRotation_2.rotated() +model.do() +Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), 50, 0) +Compound_1_objects = [model.selection("COMPSOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_1_2"), model.selection("SOLID", "Extrusion_1_3"), model.selection("SOLID", "Extrusion_1_4"), model.selection("SOLID", "Extrusion_1_5"), model.selection("SOLID", "Extrusion_1_6"), model.selection("SOLID", "Extrusion_1_7"), model.selection("SOLID", "Extrusion_1_8"), model.selection("SOLID", "Extrusion_1_9")] +Compound_1 = model.addCompound(Part_1_doc, Compound_1_objects) +Union_1_objects = [model.selection("SOLID", "Compound_1_1_1_1"), model.selection("SOLID", "Compound_1_1_1_2"), model.selection("SOLID", "Compound_1_1_1_3")] +Union_1 = model.addUnion(Part_1_doc, Union_1_objects, 20190506) + +model.testHaveNamingSubshapes(Union_1, model, Part_1_doc) + +model.end() + +from GeomAPI import GeomAPI_Shape + +model.testNbResults(Union_1, 1) +model.testNbSubResults(Union_1, [9]) +model.testNbSubShapes(Union_1, GeomAPI_Shape.SOLID, [15]) +model.testNbSubShapes(Union_1, GeomAPI_Shape.FACE, [70]) +model.testNbSubShapes(Union_1, GeomAPI_Shape.EDGE, [224]) +model.testNbSubShapes(Union_1, GeomAPI_Shape.VERTEX, [448]) +model.testResultsVolumes(Union_1, [649101.433981]) + +assert(model.checkPythonDump()) -- 2.39.2