From 01ae9016b46b78b931d74e9f5da99c64ce892830 Mon Sep 17 00:00:00 2001 From: dbv Date: Wed, 29 Nov 2017 19:36:59 +0300 Subject: [PATCH] =?utf8?q?Issue=20#2308:=201.1.2.4=20Faces=20in=20?= =?utf8?q?=E2=80=9CUnion=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Now Union allows to select faces with shared edges. Only results and sub-results allowed for selection. --- src/FeaturesPlugin/CMakeLists.txt | 1 + src/FeaturesPlugin/FeaturesPlugin_Union.cpp | 42 ++++--- .../FeaturesPlugin_Validators.cpp | 33 +++++- src/FeaturesPlugin/Test/TestUnionFaces.py | 45 ++++++++ src/FeaturesPlugin/union_widget.xml | 2 +- src/GeomAlgoAPI/CMakeLists.txt | 2 + .../GeomAlgoAPI_UnifySameDomain.cpp | 106 ++++++++++++++++++ src/GeomAlgoAPI/GeomAlgoAPI_UnifySameDomain.h | 49 ++++++++ 8 files changed, 260 insertions(+), 20 deletions(-) create mode 100644 src/FeaturesPlugin/Test/TestUnionFaces.py create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_UnifySameDomain.cpp create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_UnifySameDomain.h diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index 81552dd4c..d527286bb 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -161,6 +161,7 @@ ADD_UNIT_TESTS(TestExtrusion.py TestSerialBoolean.py TestIntersection.py TestUnion.py + TestUnionFaces.py TestRemoveSubShapes.py TestRemoveSubShapes2.py TestPipe.py diff --git a/src/FeaturesPlugin/FeaturesPlugin_Union.cpp b/src/FeaturesPlugin/FeaturesPlugin_Union.cpp index 2b3188ddc..66bef610c 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Union.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Union.cpp @@ -23,8 +23,10 @@ #include #include #include +#include #include +#include #include #include @@ -87,7 +89,7 @@ void FeaturesPlugin_Union::execute() anObjects.insert(anObjects.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()) { + 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++) { @@ -107,31 +109,36 @@ void FeaturesPlugin_Union::execute() } // Fuse objects. + std::shared_ptr anAlgo; ListOfShape aTools; - aTools.splice(aTools.begin(), anObjects, anObjects.begin()); - std::shared_ptr aFuseAlgo(new GeomAlgoAPI_Boolean(anObjects, - aTools, - GeomAlgoAPI_Boolean::BOOL_FUSE)); + if (anObjects.front()->shapeType() == GeomAPI_Shape::SOLID) { + aTools.splice(aTools.begin(), anObjects, anObjects.begin()); + anAlgo.reset(new GeomAlgoAPI_Boolean(anObjects, + aTools, + GeomAlgoAPI_Boolean::BOOL_FUSE)); + } else { + anAlgo.reset(new GeomAlgoAPI_UnifySameDomain(anObjects)); + } // Checking that the algorithm worked properly. GeomAlgoAPI_MakeShapeList aMakeShapeList; GeomAPI_DataMapOfShapeShape aMapOfShapes; - if(!aFuseAlgo->isDone()) { + if(!anAlgo->isDone()) { setError("Error: Boolean algorithm failed."); return; } - if(aFuseAlgo->shape()->isNull()) { + if(anAlgo->shape()->isNull()) { setError("Error: Resulting shape is Null."); return; } - if(!aFuseAlgo->isValid()) { + if(!anAlgo->isValid()) { setError("Error: Resulting shape is not valid."); return; } - GeomShapePtr aShape = aFuseAlgo->shape(); - aMakeShapeList.appendAlgo(aFuseAlgo); - aMapOfShapes.merge(aFuseAlgo->mapOfSubShapes()); + GeomShapePtr aShape = anAlgo->shape(); + aMakeShapeList.appendAlgo(anAlgo); + aMapOfShapes.merge(anAlgo->mapOfSubShapes()); // Store original shapes for naming. anObjects.splice(anObjects.begin(), aTools); @@ -161,18 +168,21 @@ void FeaturesPlugin_Union::execute() } // Store result and naming. - const int aModifyTag = 1; - const int aDeletedTag = 2; - /// sub solids will be placed at labels 3, 4, etc. if result is compound of solids - const int aSubsolidsTag = 3; + const int aModifyEdgeTag = 1; + const int aModifyFaceTag = 2; + const int aDeletedTag = 3; + /// sub solids will be placed at labels 4, 5 etc. if result is compound of solids + const int aSubsolidsTag = 4; const std::string aModName = "Modified"; std::shared_ptr aResultBody = document()->createBody(data()); aResultBody->storeModified(anObjects.front(), aShape, aSubsolidsTag); for(ListOfShape::const_iterator anIter = anObjects.begin(); anIter != anObjects.end(); ++anIter) { + aResultBody->loadAndOrientModifiedShapes(&aMakeShapeList, *anIter, GeomAPI_Shape::EDGE, + aModifyEdgeTag, aModName, aMapOfShapes); aResultBody->loadAndOrientModifiedShapes(&aMakeShapeList, *anIter, GeomAPI_Shape::FACE, - aModifyTag, aModName, aMapOfShapes); + aModifyFaceTag, aModName, aMapOfShapes); aResultBody->loadDeletedShapes(&aMakeShapeList, *anIter, GeomAPI_Shape::FACE, aDeletedTag); } diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp index ddcdfacf2..853037100 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp @@ -845,11 +845,28 @@ bool FeaturesPlugin_ValidatorUnionSelection::isValid(const AttributePtr& theAttr for(int anIndex = 0; anIndex < aBaseObjectsAttrList->size(); ++anIndex) { bool isSameFound = false; AttributeSelectionPtr anAttrSelectionInList = aBaseObjectsAttrList->value(anIndex); + ResultPtr aContext = anAttrSelectionInList->context(); + + ResultConstructionPtr aConstruction = + std::dynamic_pointer_cast(aContext); + if(aConstruction.get()) { + theError = "Error: Result construction not allowed for selection."; + return false; + } + + GeomShapePtr aShape = anAttrSelectionInList->value(); + GeomShapePtr aContextShape = aContext->shape(); + if (aShape.get() && aContextShape.get() && !aContextShape->isEqual(aShape)) { + theError = "Error: Local selection not allowed."; + return false; + } + ResultCompSolidPtr aResult = - std::dynamic_pointer_cast(anAttrSelectionInList->context()); + std::dynamic_pointer_cast(aContext); if(!aResult.get()) { continue; } + if(aResult->numberOfSubs() > 0) { theError = "Error: Whole compsolids not allowed for selection."; return false; @@ -882,17 +899,27 @@ bool FeaturesPlugin_ValidatorUnionArguments::isValid( } // Get all shapes. + GeomAPI_Shape::ShapeType aType = GeomAPI_Shape::COMPSOLID; ListOfShape aBaseShapesList; for(int anIndex = 0; anIndex < aBaseObejctsAttrList->size(); ++anIndex) { AttributeSelectionPtr anAttrSelectionInList = aBaseObejctsAttrList->value(anIndex); GeomShapePtr aShape = anAttrSelectionInList->value(); + if (!aShape.get()) { + continue; + } aBaseShapesList.push_back(aShape); + aType = aShape->shapeType() == GeomAPI_Shape::FACE ? GeomAPI_Shape::SHELL : + GeomAPI_Shape::COMPSOLID; } - // Make componud and find connected. + // Make compound and find connected. GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseShapesList); ListOfShape aCombined, aFree; - GeomAlgoAPI_ShapeTools::combineShapes(aCompound, GeomAPI_Shape::COMPSOLID, aCombined, aFree); + GeomAlgoAPI_ShapeTools::combineShapes( + aCompound, + aType, + aCombined, + aFree); if(aFree.size() > 0 || aCombined.size() > 1) { theError = "Error: Not all shapes have shared topology."; diff --git a/src/FeaturesPlugin/Test/TestUnionFaces.py b/src/FeaturesPlugin/Test/TestUnionFaces.py new file mode 100644 index 000000000..3bbd55f83 --- /dev/null +++ b/src/FeaturesPlugin/Test/TestUnionFaces.py @@ -0,0 +1,45 @@ +## Copyright (C) 2014-2017 CEA/DEN, EDF R&D +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## +## See http:##www.salome-platform.org/ or +## email : webmaster.salome@opencascade.com +## + +from salome.shaper import model + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchCircle_1 = Sketch_1.addCircle(-5.197255574614073, 0.1732418524871273, 67.586529314451) +model.do() +Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchCircle_1_2")]) +Partition_1 = model.addPartition(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("FACE", "PartSet/YOZ"), model.selection("FACE", "PartSet/XOZ")]) +Union_1 = model.addUnion(Part_1_doc, [model.selection("FACE", "Partition_1_1_3"), model.selection("FACE", "Partition_1_1_4")]) +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/union_widget.xml b/src/FeaturesPlugin/union_widget.xml index 1de6e9a6e..2d14a54bd 100644 --- a/src/FeaturesPlugin/union_widget.xml +++ b/src/FeaturesPlugin/union_widget.xml @@ -23,7 +23,7 @@ email : webmaster.salome@opencascade.com diff --git a/src/GeomAlgoAPI/CMakeLists.txt b/src/GeomAlgoAPI/CMakeLists.txt index 78ca7b9d6..aa563452b 100644 --- a/src/GeomAlgoAPI/CMakeLists.txt +++ b/src/GeomAlgoAPI/CMakeLists.txt @@ -73,6 +73,7 @@ SET(PROJECT_HEADERS GeomAlgoAPI_Symmetry.h GeomAlgoAPI_Scale.h GeomAlgoAPI_Circ2dBuilder.h + GeomAlgoAPI_UnifySameDomain.h ) SET(PROJECT_SOURCES @@ -124,6 +125,7 @@ SET(PROJECT_SOURCES GeomAlgoAPI_Symmetry.cpp GeomAlgoAPI_Scale.cpp GeomAlgoAPI_Circ2dBuilder.cpp + GeomAlgoAPI_UnifySameDomain.cpp ) SET(PROJECT_LIBRARIES diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_UnifySameDomain.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_UnifySameDomain.cpp new file mode 100644 index 000000000..8e8238aaf --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_UnifySameDomain.cpp @@ -0,0 +1,106 @@ +// 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 "GeomAlgoAPI_UnifySameDomain.h" + +#include +#include + +#include +#include +#include + +//================================================================================================== +GeomAlgoAPI_UnifySameDomain::GeomAlgoAPI_UnifySameDomain(const ListOfShape& theShapes) +{ + build(theShapes); +} + +void GeomAlgoAPI_UnifySameDomain::build(const ListOfShape& theShapes) +{ + if(theShapes.empty()) { + return; + } + + // Make compound. + GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(theShapes); + ListOfShape aCombined, aFree; + GeomAlgoAPI_ShapeTools::combineShapes( + aCompound, + GeomAPI_Shape::SHELL, + aCombined, + aFree); + + if(aFree.size() > 0 || aCombined.size() > 1) { + return; + } + + const TopoDS_Shape& aShell = aCombined.front()->impl(); + + ShapeUpgrade_UnifySameDomain* aUnifyAlgo = new ShapeUpgrade_UnifySameDomain(); + this->setImpl(aUnifyAlgo); + + aUnifyAlgo->Initialize(aShell); + aUnifyAlgo->UnifyFacesAndEdges(); + aUnifyAlgo->Build(); + + TopoDS_Shape aResult = aUnifyAlgo->Shape(); + if (aResult.IsNull()) { + return; + } + + if (aResult.ShapeType() == TopAbs_SHELL) { + int aNb = 0; + TopoDS_Iterator anIt(aResult); + for (; anIt.More(); anIt.Next()) { + ++aNb; + } + + if (aNb == 1) { + anIt.Initialize(aResult); + aResult = anIt.Value(); + } + } + + std::shared_ptr aShape(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(aResult)); + this->setShape(aShape); + this->setDone(true); +} + +//================================================================================================== +void GeomAlgoAPI_UnifySameDomain::modified(const std::shared_ptr theShape, + ListOfShape& theHistory) +{ + if(!theShape.get()) { + return; + } + + const TopoDS_Shape& aShape = theShape->impl(); + const ShapeUpgrade_UnifySameDomain& aUnifyAlgo = this->impl(); + + TopoDS_Shape aModifiedShape = aUnifyAlgo.Generated(aShape); + + for(TopExp_Explorer anExp(aModifiedShape, aShape.ShapeType()); anExp.More(); anExp.Next()) { + GeomShapePtr aGeomShape(new GeomAPI_Shape()); + aGeomShape->setImpl(new TopoDS_Shape(anExp.Current())); + theHistory.push_back(aGeomShape); + } +} diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_UnifySameDomain.h b/src/GeomAlgoAPI/GeomAlgoAPI_UnifySameDomain.h new file mode 100644 index 000000000..a18366672 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_UnifySameDomain.h @@ -0,0 +1,49 @@ +// 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 +// + +#ifndef GeomAlgoAPI_UnifySameDomain_H_ +#define GeomAlgoAPI_UnifySameDomain_H_ + +#include "GeomAlgoAPI.h" +#include "GeomAlgoAPI_MakeShape.h" + +#include + +/// \class GeomAlgoAPI_UnifySameDomain +/// \ingroup DataAlgo +/// \brief This tool tries to unify faces and edges of the shape which lies on the same geometry. +class GeomAlgoAPI_UnifySameDomain: public GeomAlgoAPI_MakeShape +{ +public: + /// Constructor. + GEOMALGOAPI_EXPORT GeomAlgoAPI_UnifySameDomain(const ListOfShape& theShapes); + + /// \return the list of shapes modified from the shape \a theShape. + /// \param[in] theShape base shape. + /// \param[out] theHistory modified shapes. + GEOMALGOAPI_EXPORT virtual void modified(const std::shared_ptr theShape, + ListOfShape& theHistory); + +private: + /// Builds resulting shape. + void build(const ListOfShape& theShapes); +}; + +#endif -- 2.39.2