From: mpv Date: Wed, 5 Jul 2017 10:58:36 +0000 (+0300) Subject: Issue #2192 : change the naming principles of compsolid in case of Partition to make... X-Git-Tag: V_2.7.2RC~22 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=f3af7540eb79629e249c042f590478eb3623f12c;p=modules%2Fshaper.git Issue #2192 : change the naming principles of compsolid in case of Partition to make the OCCT naming algorithm works and works much faster (without many FILTERBYNEIGHBOURS algorithms implementation) in case of Planes made on vertices on Partition-compsolid. Makes some old studies and python files with Partition sub-shapes selection invalid. --- diff --git a/src/CollectionPlugin/CMakeLists.txt b/src/CollectionPlugin/CMakeLists.txt index 9725d5091..4bc29cccb 100644 --- a/src/CollectionPlugin/CMakeLists.txt +++ b/src/CollectionPlugin/CMakeLists.txt @@ -105,4 +105,6 @@ ADD_UNIT_TESTS( TestGroup.py TestField.py TestGroup1799.py + TestGroupMove.py + TestGroupMove2.py ) diff --git a/src/CollectionPlugin/Test/TestGroup1799.py b/src/CollectionPlugin/Test/TestGroup1799.py index c959182da..8a767c0e7 100644 --- a/src/CollectionPlugin/Test/TestGroup1799.py +++ b/src/CollectionPlugin/Test/TestGroup1799.py @@ -119,8 +119,8 @@ Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Extrusion_1_1/To_ Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_12"), 150, True) Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_7"), 150, True) Partition_1 = model.addPartition(Part_1_doc, [model.selection("FACE", "Plane_1"), model.selection("COMPSOLID", "Extrusion_1_1"), model.selection("FACE", "Plane_2")]) -Plane_6 = model.addPlane(Part_1_doc, model.selection("FACE", "Partition_1_1/Modified_Face_1_2_1"), 110, True) -Plane_7 = model.addPlane(Part_1_doc, model.selection("FACE", "Partition_1_1/Modified_Face_1_9_1"), 380, True) +Plane_6 = model.addPlane(Part_1_doc, model.selection("FACE", "Partition_1_1_7/Modified_Face_1_3"), 110, True) +Plane_7 = model.addPlane(Part_1_doc, model.selection("FACE", "Partition_1_1_5/Modified_Face_1_3"), 380, True) Partition_2 = model.addPartition(Part_1_doc, [model.selection("FACE", "Plane_3"), model.selection("COMPSOLID", "Partition_1_1"), model.selection("FACE", "Plane_4")]) model.do() diff --git a/src/CollectionPlugin/Test/TestGroupMove.py b/src/CollectionPlugin/Test/TestGroupMove.py new file mode 100644 index 000000000..dd1e0c17f --- /dev/null +++ b/src/CollectionPlugin/Test/TestGroupMove.py @@ -0,0 +1,50 @@ +## 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 +## + +# Test that box partitioned is splitted: group with edge becomes 2 edges group, +# group with not-touched vertex keeps this vertex. + +from salome.shaper import model +from ModelAPI import * + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Box_1 = model.addBox(Part_1_doc, 20, 10, 10) +Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Back"), 10, True) +Group_1 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Box_1_1/Left&Box_1_1/Top")]) +Group_2 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "Box_1_1/Back&Box_1_1/Left&Box_1_1/Top")]) +Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1")]) +model.do() +# move groups +Part_1_doc.moveFeature(Group_1.feature(), Partition_1.feature()) +Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature()) +model.end() + +# Check groups +aFactory = ModelAPI_Session.get().validators() +selectionList = Group_1.feature().selectionList("group_list") +assert(selectionList.size() == 2) +assert(aFactory.validate(Group_1.feature())) + +selectionList = Group_2.feature().selectionList("group_list") +assert(selectionList.size() == 1) +assert(aFactory.validate(Group_2.feature())) diff --git a/src/CollectionPlugin/Test/TestGroupMove2.py b/src/CollectionPlugin/Test/TestGroupMove2.py new file mode 100644 index 000000000..0f06d1dfd --- /dev/null +++ b/src/CollectionPlugin/Test/TestGroupMove2.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 +## + +# Test that removed vertex, selected in the group makes group with one invalid element (empty shape) + +from salome.shaper import model +from ModelAPI import * + +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, 20) +Plane_4 = model.addPlane(Part_1_doc, model.selection("VERTEX", "Box_1_1/Back&Box_1_1/Right&Box_1_1/Top"), model.selection("VERTEX", "Box_1_1/Front&Box_1_1/Left&Box_1_1/Top"), model.selection("VERTEX", "Box_1_1/Back&Box_1_1/Left&Box_1_1/Bottom")) +Group_1 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "Box_1_1/Back&Box_1_1/Left&Box_1_1/Top")]) +Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1")]) +Remove_SubShapes_1 = model.addRemoveSubShapes(Part_1_doc, model.selection("COMPSOLID", "Partition_1_1")) +Remove_SubShapes_1.setSubShapesToKeep([model.selection("SOLID", "Partition_1_1_2")]) +model.do() +# move group +Part_1_doc.moveFeature(Group_1.feature(), Remove_SubShapes_1.feature()) +model.end() + +# Check group +aFactory = ModelAPI_Session.get().validators() +selectionList = Group_1.feature().selectionList("group_list") +assert(selectionList.size() == 1) +assert(aFactory.validate(Group_1.feature()) == False) diff --git a/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp b/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp index a6ab99568..c2a78a62e 100755 --- a/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp @@ -189,14 +189,11 @@ void FeaturesPlugin_Partition::storeResult( for(ListOfShape::const_iterator anIt = theObjects.cbegin(); anIt != theObjects.cend(); ++anIt) { GeomShapePtr aShape = *anIt; std::string aModEdgeName = aModName + "_Edge_" + std::to_string((long long)anIndex); - std::string aModFaceName = aModName + "_Face_" + std::to_string((long long)anIndex++); aResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::EDGE, - aModTag, aModEdgeName, *aMapOfSubShapes.get(), true); - aModTag += 10000; + aModTag, aModEdgeName, *aMapOfSubShapes.get(), false, false); + std::string aModFaceName = aModName + "_Face_" + std::to_string((long long)anIndex++); aResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::FACE, - aModTag, aModFaceName, *aMapOfSubShapes.get(), true); - aModTag += 10000; - aResultBody->loadDeletedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::EDGE, aDelTag); + aModTag + 1, aModFaceName, *aMapOfSubShapes.get(), false, true); aResultBody->loadDeletedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::FACE, aDelTag); } diff --git a/src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.cpp b/src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.cpp index 51d64cba4..dbf4fc1ed 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.cpp @@ -28,10 +28,13 @@ #include #include +#include #include #include #include +#include + //================================================================================================== FeaturesPlugin_RemoveSubShapes::FeaturesPlugin_RemoveSubShapes() @@ -130,16 +133,38 @@ void FeaturesPlugin_RemoveSubShapes::execute() aResultShape = anAttrSelectionInList->value(); } + // find all removed shapes + GeomAlgoAPI_MakeShapeCustom aDeletedSubs; + for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) { + if (!anIt.current().get() || anIt.current()->isNull()) + continue; + int anIndex; + for(anIndex = 0; anIndex < aSubsNb; ++anIndex) { + AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex); + GeomShapePtr aLeftShape = anAttrSelectionInList->value(); + if (anIt.current()->isEqual(aLeftShape)) { + break; // found in a left-list + } + } + if (anIndex == aSubsNb) { // not found in left + GeomAPI_ShapeExplorer aFaces(anIt.current(), GeomAPI_Shape::FACE); + for(; aFaces.more(); aFaces.next()) + aDeletedSubs.addDeleted(aFaces.current()); + } + } + + GeomAlgoAPI_Copy aCopy(aResultShape); aResultShape = aCopy.shape(); // Store result. ResultBodyPtr aResultBody = document()->createBody(data()); aResultBody->storeModified(aBaseShape, aResultShape, 1); + aResultBody->loadDeletedShapes(&aDeletedSubs, aBaseShape, GeomAPI_Shape::FACE, 1); aResultBody->loadAndOrientModifiedShapes(&aCopy, aBaseShape, GeomAPI_Shape::FACE, - 10000, + 2, "Modified_Face", *aCopy.mapOfSubShapes().get(), true); diff --git a/src/FeaturesPlugin/Test/Test2038.py b/src/FeaturesPlugin/Test/Test2038.py index f5371bbf5..0dd252ec9 100644 --- a/src/FeaturesPlugin/Test/Test2038.py +++ b/src/FeaturesPlugin/Test/Test2038.py @@ -42,8 +42,9 @@ Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/ Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], model.selection("EDGE", "PartSet/OX"), 50) Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Translation_1_1"), model.selection("SOLID", "Extrusion_2_1")]) Translation_2 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Partition_1_1")], model.selection("EDGE", "PartSet/OZ"), 50) -Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Translation_2_1/Translated_Face_24"), model.selection("FACE", "Translation_2_1/Translated_Face_13"), model.selection("FACE", "Translation_2_1/Translated_Face_16"), model.selection("FACE", "Translation_2_1/Translated_Face_12"), model.selection("FACE", "Translation_2_1/Translated_Face_9"), model.selection("FACE", "Translation_2_1/Translated_Face_10"), model.selection("FACE", "Translation_2_1/Translated_Face_11"), model.selection("FACE", "Translation_2_1/Translated_Face_25"), model.selection("FACE", "Translation_2_1/Translated_Face_20"), model.selection("FACE", "Translation_2_1/Translated_Face_19"), model.selection("FACE", "Translation_2_1/Translated_Face_18"), model.selection("FACE", "Translation_2_1/Translated_Face_27"), model.selection("FACE", "Translation_2_1/Translated_Face_17"), model.selection("FACE", "Translation_2_1/Translated_Face_31"), model.selection("FACE", "Translation_2_1/Translated_Face_32"), model.selection("FACE", "Translation_2_1/Translated_Face_30"), model.selection("FACE", "Translation_2_1/Translated_Face_28"), model.selection("FACE", "Translation_2_1/Translated_Face_29"), model.selection("FACE", "Translation_2_1/Translated_Face_8"), model.selection("FACE", "Translation_2_1/Translated_Face_22"), model.selection("FACE", "Translation_2_1/Translated_Face_7"), model.selection("FACE", "Translation_2_1/Translated_Face_6"), model.selection("FACE", "Translation_2_1/Translated_Face_5"), model.selection("FACE", "Translation_2_1/Translated_Face_3"), model.selection("FACE", "Translation_2_1/Translated_Face_1"), model.selection("FACE", "Translation_2_1/Translated_Face_2"), model.selection("FACE", "Translation_2_1/Translated_Face_21"), model.selection("FACE", "Translation_2_1/Translated_Face_4"), model.selection("FACE", "Translation_2_1/Translated_Face_25"), model.selection("FACE", "Translation_2_1/Translated_Face_27"), model.selection("FACE", "Translation_2_1/Translated_Face_21"), model.selection("FACE", "Translation_2_1/Translated_Face_22"), model.selection("FACE", "Translation_2_1/Translated_Face_26"), model.selection("FACE", "Translation_2_1/Translated_Face_23"), model.selection("FACE", "Translation_2_1/Translated_Face_30"), model.selection("FACE", "Translation_2_1/Translated_Face_23"), model.selection("FACE", "Translation_2_1/Translated_Face_14"), model.selection("FACE", "Translation_2_1/Translated_Face_15")]) -model.do() +#Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Translation_2_1/Translated_Face_24"), model.selection("FACE", "Translation_2_1/Translated_Face_13"), model.selection("FACE", "Translation_2_1/Translated_Face_16"), model.selection("FACE", "Translation_2_1/Translated_Face_12"), model.selection("FACE", "Translation_2_1/Translated_Face_9"), model.selection("FACE", "Translation_2_1/Translated_Face_10"), model.selection("FACE", "Translation_2_1/Translated_Face_11"), model.selection("FACE", "Translation_2_1/Translated_Face_25"), model.selection("FACE", "Translation_2_1/Translated_Face_20"), model.selection("FACE", "Translation_2_1/Translated_Face_19"), model.selection("FACE", "Translation_2_1/Translated_Face_18"), model.selection("FACE", "Translation_2_1/Translated_Face_27"), model.selection("FACE", "Translation_2_1/Translated_Face_17"), model.selection("FACE", "Translation_2_1/Translated_Face_31"), model.selection("FACE", "Translation_2_1/Translated_Face_32"), model.selection("FACE", "Translation_2_1/Translated_Face_30"), model.selection("FACE", "Translation_2_1/Translated_Face_28"), model.selection("FACE", "Translation_2_1/Translated_Face_29"), model.selection("FACE", "Translation_2_1/Translated_Face_8"), model.selection("FACE", "Translation_2_1/Translated_Face_22"), model.selection("FACE", "Translation_2_1/Translated_Face_7"), model.selection("FACE", "Translation_2_1/Translated_Face_6"), model.selection("FACE", "Translation_2_1/Translated_Face_5"), model.selection("FACE", "Translation_2_1/Translated_Face_3"), model.selection("FACE", "Translation_2_1/Translated_Face_1"), model.selection("FACE", "Translation_2_1/Translated_Face_2"), model.selection("FACE", "Translation_2_1/Translated_Face_21"), model.selection("FACE", "Translation_2_1/Translated_Face_4"), model.selection("FACE", "Translation_2_1/Translated_Face_25"), model.selection("FACE", "Translation_2_1/Translated_Face_27"), model.selection("FACE", "Translation_2_1/Translated_Face_21"), model.selection("FACE", "Translation_2_1/Translated_Face_22"), model.selection("FACE", "Translation_2_1/Translated_Face_26"), model.selection("FACE", "Translation_2_1/Translated_Face_23"), model.selection("FACE", "Translation_2_1/Translated_Face_30"), model.selection("FACE", "Translation_2_1/Translated_Face_23"), model.selection("FACE", "Translation_2_1/Translated_Face_14"), model.selection("FACE", "Translation_2_1/Translated_Face_15")]) +Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Translation_2_1_6/Translated_Face_1"), model.selection("FACE", "Translation_2_1_5/Translated_Face_1"), model.selection("FACE", "Translation_2_1_5/Translated_Face_4"), model.selection("FACE", "Translation_2_1_4/Translated_Face_4"), model.selection("FACE", "Translation_2_1_5/Translated_Face_3"), model.selection("FACE", "Translation_2_1_5/Translated_Face_2"), model.selection("FACE", "Translation_2_1_5/Translated_Face_5"), model.selection("FACE", "Translation_2_1_7/Translated_Face_5"), model.selection("FACE", "Translation_2_1_6/Translated_Face_5"), model.selection("FACE", "Translation_2_1_4/Translated_Face_1"), model.selection("FACE", "Translation_2_1_2/Translated_Face_2"), model.selection("FACE", "Translation_2_1_5/Translated_Face_5"), model.selection("FACE", "Translation_2_1_2/Translated_Face_1"), model.selection("FACE", "Translation_2_1_4/Translated_Face_5"), model.selection("FACE", "Translation_2_1_2/Translated_Face_3"), model.selection("FACE", "Translation_2_1_3/Translated_Face_5"), model.selection("FACE", "Translation_2_1_1/Translated_Face_3"), model.selection("FACE", "Translation_2_1_4/Translated_Face_2"), model.selection("FACE", "Translation_2_1_2/Translated_Face_3"), model.selection("FACE", "Translation_2_1_1/Translated_Face_4"), model.selection("FACE", "Translation_2_1_1/Translated_Face_1"), model.selection("FACE", "Translation_2_1_1/Translated_Face_2"), model.selection("FACE", "Translation_2_1_3/Translated_Face_4"), model.selection("FACE", "Translation_2_1_4/Translated_Face_3"), model.selection("FACE", "Translation_2_1_3/Translated_Face_5"), model.selection("FACE", "Translation_2_1_3/Translated_Face_2"), model.selection("FACE", "Translation_2_1_3/Translated_Face_3"), model.selection("FACE", "Translation_2_1_3/Translated_Face_1"), model.selection("FACE", "Translation_2_1_7/Translated_Face_3"), model.selection("FACE", "Translation_2_1_7/Translated_Face_5"), model.selection("FACE", "Translation_2_1_7/Translated_Face_4"), model.selection("FACE", "Translation_2_1_7/Translated_Face_1"), model.selection("FACE", "Translation_2_1_7/Translated_Face_2"), model.selection("FACE", "Translation_2_1_6/Translated_Face_4"), model.selection("FACE", "Translation_2_1_4/Translated_Face_5"), model.selection("FACE", "Translation_2_1_6/Translated_Face_5"), model.selection("FACE", "Translation_2_1_6/Translated_Face_2"), model.selection("FACE", "Translation_2_1_6/Translated_Face_3")]) + model.end() groupFeature = Group_1.feature() diff --git a/src/FeaturesPlugin/Test/Test2194.py b/src/FeaturesPlugin/Test/Test2194.py index 8cfc171ff..0fd8972af 100644 --- a/src/FeaturesPlugin/Test/Test2194.py +++ b/src/FeaturesPlugin/Test/Test2194.py @@ -34,7 +34,7 @@ SketchCircle_3 = Sketch_2.addCircle(-41.97827733564338, 89.35676702647821, 6.102 model.do() Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchCircle_2_2f"), model.selection("FACE", "Sketch_2/Face-SketchCircle_3_2f")], model.selection(), 10, 0) Boolean_1 = model.addSmash(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], [model.selection("SOLID", "Extrusion_2_1"), model.selection("SOLID", "Extrusion_2_2")]) -Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Extrusion_2_2/To_Face_1"), model.selection("FACE", "Extrusion_2_2/From_Face_1"), model.selection("FACE", "Extrusion_2_2/Generated_Face_1"), model.selection("FACE", "Extrusion_2_1/From_Face_1"), model.selection("FACE", "Boolean_1_1/Modified_3"), model.selection("FACE", "Extrusion_1_1/From_Face_1"), model.selection("FACE", "Extrusion_1_1/Generated_Face_1"), model.selection("FACE", "Extrusion_2_2/From_Face_1"), model.selection("FACE", "Extrusion_2_1/Generated_Face_1"), model.selection("FACE", "Extrusion_2_1/From_Face_1"), model.selection("FACE", "Extrusion_2_1/To_Face_1")]) +Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Extrusion_2_2/To_Face_1"), model.selection("FACE", "Extrusion_2_2/From_Face_1"), model.selection("FACE", "Extrusion_2_2/Generated_Face_1"), model.selection("FACE", "Extrusion_2_1/From_Face_1"), model.selection("FACE", "Boolean_1_1_1/Modified_1"), model.selection("FACE", "Extrusion_1_1/From_Face_1"), model.selection("FACE", "Extrusion_1_1/Generated_Face_1"), model.selection("FACE", "Extrusion_2_2/From_Face_1"), model.selection("FACE", "Extrusion_2_1/Generated_Face_1"), model.selection("FACE", "Extrusion_2_1/From_Face_1"), model.selection("FACE", "Extrusion_2_1/To_Face_1")]) model.do() model.end() diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index 7348703ee..1e8aca192 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -47,6 +47,8 @@ #include #include #include +#include +#include #include #include #include @@ -54,6 +56,7 @@ #include #include #include +#include //#define DEB_NAMING 1 #ifdef DEB_NAMING @@ -772,6 +775,178 @@ std::string Model_AttributeSelection::contextName(const ResultPtr& theContext) c return aResult; } +void Model_AttributeSelection::computeValues( + ResultPtr theOldContext, ResultPtr theNewContext, TopoDS_Shape theValShape, + TopTools_ListOfShape& theShapes) +{ + TopoDS_Shape anOldContShape = theOldContext->shape()->impl(); + TopoDS_Shape aNewContShape = theNewContext->shape()->impl(); + if (anOldContShape.IsSame(theValShape)) { // full context shape substituted by new full context + theShapes.Append(aNewContShape); + return; + } + if (theValShape.IsNull()) { + theShapes.Append(theValShape); + return; + } + // if a new value is unchanged in the new context, do nothing: value is correct + TopExp_Explorer aSubExp(aNewContShape, theValShape.ShapeType()); + for(; aSubExp.More(); aSubExp.Next()) { + if (aSubExp.Current().IsSame(theValShape)) { + theShapes.Append(theValShape); + return; + } + } + // if new context becomes compsolid, the resulting sub may be in sub-solids + std::list aNewToIterate; + aNewToIterate.push_back(theNewContext); + ResultCompSolidPtr aComp = std::dynamic_pointer_cast(theNewContext); + if (aComp.get()) { + for(int a = 0; a < aComp->numberOfSubs(); a++) + aNewToIterate.push_back(aComp->subResult(a, false)); + } + + // first iteration: searching for the whole shape appearance (like face of the box) + // second iteration: searching for sub-shapes that contain the sub (like vertex on faces) + int aToFindPart = 0; + TopTools_DataMapOfShapeShape aNewToOld; // map from new containers to old containers (with val) + TopTools_MapOfShape anOlds; // to know how many olds produced new containers + for(; aToFindPart != 2 && theShapes.IsEmpty(); aToFindPart++) { + std::list::iterator aNewContIter = aNewToIterate.begin(); + for(; aNewContIter != aNewToIterate.end(); aNewContIter++) { + std::shared_ptr aNewData = + std::dynamic_pointer_cast((*aNewContIter)->data()); + TDF_Label aNewLab = aNewData->label(); + // searching for produced sub-shape fully on some label + TDF_ChildIDIterator aNSIter(aNewLab, TNaming_NamedShape::GetID(), Standard_True); + for(; aNSIter.More(); aNSIter.Next()) { + Handle(TNaming_NamedShape) aNS = Handle(TNaming_NamedShape)::DownCast(aNSIter.Value()); + for(TNaming_Iterator aPairIter(aNS); aPairIter.More(); aPairIter.Next()) { + if (aToFindPart == 0) { // search shape is fully inside + if (aPairIter.OldShape().IsSame(theValShape)) { + if (aPairIter.NewShape().IsNull()) {// value was removed + theShapes.Clear(); + return; + } + theShapes.Append(aPairIter.NewShape()); + } + } else if (!aPairIter.OldShape().IsNull()) { // search shape that contains this sub + TopExp_Explorer anExp(aPairIter.OldShape(), theValShape.ShapeType()); + for(; anExp.More(); anExp.Next()) { + if (anExp.Current().IsSame(theValShape)) { // found a new container + if (aPairIter.NewShape().IsNull()) {// value was removed + theShapes.Clear(); + return; + } + aNewToOld.Bind(aPairIter.NewShape(), aPairIter.OldShape()); + anOlds.Add(aPairIter.OldShape()); + break; + } + } + } + } + } + } + } + if (aToFindPart == 2 && !aNewToOld.IsEmpty()) { + // map of sub-shapes -> number of occurences of these shapes in containers + NCollection_DataMap aSubs; + TopTools_DataMapOfShapeShape::Iterator aContIter(aNewToOld); + for(; aContIter.More(); aContIter.Next()) { + TopExp_Explorer aSubExp(aContIter.Key(), theValShape.ShapeType()); + for(; aSubExp.More(); aSubExp.Next()) { + if (!aSubs.IsBound(aSubExp.Current())) { + aSubs.Bind(aSubExp.Current(), TopTools_MapOfShape()); + } + // store old to know how many olds produced this shape + aSubs.ChangeFind(aSubExp.Current()).Add(aContIter.Value()); + } + } + // if sub is appeared same times in containers as the number of old shapes that contain it + int aCountInOld = anOlds.Size(); + NCollection_DataMap::Iterator + aSubsIter(aSubs); + for(; aSubsIter.More(); aSubsIter.Next()) { + if (aSubsIter.Value().Size() == aCountInOld) { + theShapes.Append(aSubsIter.Key()); + } + } + } + if (theShapes.IsEmpty()) // nothing was changed + theShapes.Append(theValShape); +} + +bool Model_AttributeSelection::searchNewContext(std::shared_ptr theDoc, + const TopoDS_Shape theContShape, ResultPtr theContext, TopoDS_Shape theValShape, + TDF_Label theAccessLabel, + std::list& theResults, TopTools_ListOfShape& theValShapes) +{ + std::set aResults; // to avoid duplicates + TopTools_ListOfShape aResContShapes; + TNaming_SameShapeIterator aModifIter(theContShape, theAccessLabel); + for(; aModifIter.More(); aModifIter.Next()) { + ResultPtr aModifierObj = std::dynamic_pointer_cast + (theDoc->objects()->object(aModifIter.Label().Father())); + if (!aModifierObj.get()) + break; + FeaturePtr aModifierFeat = theDoc->feature(aModifierObj); + if (!aModifierFeat.get()) + break; + FeaturePtr aThisFeature = std::dynamic_pointer_cast(owner()); + if (aModifierFeat == aThisFeature || theDoc->objects()->isLater(aModifierFeat, aThisFeature)) + continue; // the modifier feature is later than this, so, should not be used + FeaturePtr aCurrentModifierFeat = theDoc->feature(theContext); + if (aCurrentModifierFeat == aModifierFeat || + theDoc->objects()->isLater(aCurrentModifierFeat, aModifierFeat)) + continue; // the current modifier is later than the found, so, useless + Handle(TNaming_NamedShape) aNewNS; + aModifIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNewNS); + if (aNewNS->Evolution() == TNaming_MODIFY || aNewNS->Evolution() == TNaming_GENERATED) { + aResults.insert(aModifierObj); + TNaming_Iterator aPairIter(aNewNS); + aResContShapes.Append(aPairIter.NewShape()); + } else if (aNewNS->Evolution() == TNaming_DELETE) { // a shape was deleted => result is empty + aResults.insert(ResultPtr()); + aResContShapes.Append(TopoDS_Shape()); + } else { // not-precessed modification => don't support it + continue; + } + } + if (aResults.empty()) + return false; // no modifications found, must stay the same + // iterate all results to find futher modifications + std::set::iterator aResIter = aResults.begin(); + TopTools_ListOfShape::Iterator aResShapes(aResContShapes); + for(; aResIter != aResults.end(); aResIter++, aResShapes.Next()) { + if (aResIter->get() != NULL) { + // compute new values by two contextes: the old and the new + TopTools_ListOfShape aValShapes; + computeValues(theContext, *aResIter, theValShape, aValShapes); + + TopTools_ListIteratorOfListOfShape aNewVal(aValShapes); + for(; aNewVal.More(); aNewVal.Next()) { + std::list aNewRes; + TopTools_ListOfShape aNewUpdatedVal; + if (searchNewContext(theDoc, aResShapes.Value(), *aResIter, aNewVal.Value(), + theAccessLabel, aNewRes, aNewUpdatedVal)) + { + // appeand new results instead of the current ones + std::list::iterator aNewIter = aNewRes.begin(); + TopTools_ListIteratorOfListOfShape aNewUpdVal(aNewUpdatedVal); + for(; aNewIter != aNewRes.end(); aNewIter++, aNewUpdVal.Next()) { + theResults.push_back(*aNewIter); + theValShapes.Append(aNewUpdVal.Value()); + } + } else { // the current result is good + theResults.push_back(*aResIter); + theValShapes.Append(aNewVal.Value()); + } + } + } + } + return true; // theResults must be empty: everything is deleted +} + void Model_AttributeSelection::updateInHistory() { ResultPtr aContext = std::dynamic_pointer_cast(myRef.value()); @@ -795,66 +970,50 @@ void Model_AttributeSelection::updateInHistory() TNaming_Iterator aPairIter(aContNS); if (!aPairIter.More()) return; - TopoDS_Shape aNewShape = aPairIter.NewShape(); + TopoDS_Shape aNewCShape = aPairIter.NewShape(); bool anIterate = true; // trying to update also the sub-shape selected GeomShapePtr aSubShape = value(); if (aSubShape.get() && aSubShape->isEqual(aContext->shape())) aSubShape.reset(); - - while(anIterate) { - anIterate = false; - TNaming_SameShapeIterator aModifIter(aNewShape, aContLab); - for(; aModifIter.More(); aModifIter.Next()) { - ResultPtr aModifierObj = std::dynamic_pointer_cast - (aDoc->objects()->object(aModifIter.Label().Father())); - if (!aModifierObj.get()) - break; - FeaturePtr aModifierFeat = aDoc->feature(aModifierObj); - if (!aModifierFeat.get()) - break; - if (aModifierFeat == aThisFeature || aDoc->objects()->isLater(aModifierFeat, aThisFeature)) - continue; // the modifier feature is later than this, so, should not be used - if (aCurrentModifierFeat == aModifierFeat || - aDoc->objects()->isLater(aCurrentModifierFeat, aModifierFeat)) - continue; // the current modifier is later than the found, so, useless - Handle(TNaming_NamedShape) aNewNS; - aModifIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNewNS); - if (aNewNS->Evolution() == TNaming_MODIFY || aNewNS->Evolution() == TNaming_GENERATED) { - aModifierResFound = aModifierObj; - aCurrentModifierFeat = aModifierFeat; - TNaming_Iterator aPairIter(aNewNS); - aNewShape = aPairIter.NewShape(); - anIterate = true; - break; - } else if (aNewNS->Evolution() == TNaming_DELETE) { // a shape was deleted => result is null - ResultPtr anEmptyContext; - std::shared_ptr anEmptyShape; - setValue(anEmptyContext, anEmptyShape); // nullify the selection - return; - } else { // not-precessed modification => don't support it - continue; - } - } + TopoDS_Shape aValShape; + if (aSubShape.get()) { + aValShape = aSubShape->impl(); } - if (aModifierResFound.get()) { + + std::list aNewContexts; + TopTools_ListOfShape aValShapes; + if (searchNewContext(aDoc, aNewCShape, aContext, aValShape, aContLab, aNewContexts, aValShapes)) + { // update scope to reset to a new one myScope.Clear(); - myRef.setValue(aModifierResFound); - // if context shape type is changed to more complicated and this context is selected, split - if (myParent &&!aSubShape.get() && aModifierResFound->shape().get() && aContext->shape().get()) - { - TopoDS_Shape anOldShape = aContext->shape()->impl(); - TopoDS_Shape aNewShape = aModifierResFound->shape()->impl(); - if (!anOldShape.IsNull() && !aNewShape.IsNull() && - anOldShape.ShapeType() != aNewShape.ShapeType() && - (aNewShape.ShapeType() == TopAbs_COMPOUND || aNewShape.ShapeType() == TopAbs_COMPSOLID)) { - // prepare for split in "update" - TDF_Label aSelLab = selectionLabel(); - split(aContext, aNewShape, anOldShape.ShapeType()); + + std::list::iterator aNewCont = aNewContexts.begin(); + TopTools_ListIteratorOfListOfShape aNewValues(aValShapes); + if (aNewCont == aNewContexts.end()) { // all results were deleted + ResultPtr anEmptyContext; + std::shared_ptr anEmptyShape; + setValue(anEmptyContext, anEmptyShape); // nullify the selection + return; + } + + GeomShapePtr aValueShape; + if (!aNewValues.Value().IsNull()) { + aValueShape = std::make_shared(); + aValueShape->setImpl(new TopoDS_Shape(aNewValues.Value())); + } + setValue(*aNewCont, aValueShape); + // if there are more than one result, put them by "append" into "parent" list + if (myParent) { + for(aNewCont++, aNewValues.Next(); aNewCont != aNewContexts.end(); aNewCont++, aNewValues.Next()) { + GeomShapePtr aValueShape; + if (!aNewValues.Value().IsNull()) { + aValueShape = std::make_shared(); + aValueShape->setImpl(new TopoDS_Shape(aNewValues.Value())); + } + myParent->append(*aNewCont, aValueShape); } } - update(); // it must recompute a new sub-shape automatically } } diff --git a/src/Model/Model_AttributeSelection.h b/src/Model/Model_AttributeSelection.h index c75766a73..c2a65b535 100644 --- a/src/Model/Model_AttributeSelection.h +++ b/src/Model/Model_AttributeSelection.h @@ -26,6 +26,7 @@ #include #include #include +#include class Model_AttributeSelectionList; @@ -135,6 +136,16 @@ protected: /// Splits theNewShape into sub-shapes of theType type (for the list parent of this attribute) void split(ResultPtr theContext, TopoDS_Shape theNewShape, TopAbs_ShapeEnum theType); + /// When group position is updated, searches the new context and new values + bool searchNewContext(std::shared_ptr theDoc, const TopoDS_Shape theContShape, + ResultPtr theContext, TopoDS_Shape theValShape, TDF_Label theAccessLabel, + std::list& theResults, TopTools_ListOfShape& theValShapes); + + /// computes theShapes list - shapes that were generated/modified/deleted the theValShape + /// during creation from new to old context + void computeValues(ResultPtr theOldContext, ResultPtr theNewContext, TopoDS_Shape theValShape, + TopTools_ListOfShape& theShapes); + friend class Model_Data; friend class Model_AttributeSelectionList; }; diff --git a/src/Model/Model_ResultCompSolid.cpp b/src/Model/Model_ResultCompSolid.cpp index 0ba7c79b7..e97a541bb 100755 --- a/src/Model/Model_ResultCompSolid.cpp +++ b/src/Model/Model_ResultCompSolid.cpp @@ -65,6 +65,27 @@ void Model_ResultCompSolid::storeModified(const std::shared_ptr& updateSubs(theNewShape); } +void Model_ResultCompSolid::loadAndOrientModifiedShapes (GeomAlgoAPI_MakeShape* theMS, + std::shared_ptr theShapeIn, const int theKindOfShape, const int theTag, + const std::string& theName, GeomAPI_DataMapOfShapeShape& theSubShapes, + const bool theIsStoreSeparate, + const bool theIsStoreAsGenerated) +{ + if (mySubs.size()) { // consists of subs + std::vector >::const_iterator aSubIter = mySubs.cbegin(); + for(; aSubIter != mySubs.cend(); aSubIter++) { + (*aSubIter)->loadAndOrientModifiedShapes( + theMS, theShapeIn, theKindOfShape, theTag, theName, theSubShapes, theIsStoreSeparate, + theIsStoreAsGenerated); + } + } else { // do for this directly + ModelAPI_ResultCompSolid::loadAndOrientModifiedShapes( + theMS, theShapeIn, theKindOfShape, theTag, theName, theSubShapes, theIsStoreSeparate, + theIsStoreAsGenerated); + } +} + + int Model_ResultCompSolid::numberOfSubs(bool forTree) const { return int(mySubs.size()); diff --git a/src/Model/Model_ResultCompSolid.h b/src/Model/Model_ResultCompSolid.h index 9715f0155..69d813565 100755 --- a/src/Model/Model_ResultCompSolid.h +++ b/src/Model/Model_ResultCompSolid.h @@ -57,6 +57,14 @@ public: MODEL_EXPORT virtual void storeModified(const std::shared_ptr& theOldShape, const std::shared_ptr& theNewShape, const int theDecomposeSolidsTag = 0); + /// load and orient modified shapes for sub-objects + MODEL_EXPORT virtual void loadAndOrientModifiedShapes (GeomAlgoAPI_MakeShape* theMS, + std::shared_ptr theShapeIn, const int theKindOfShape, const int theTag, + const std::string& theName, GeomAPI_DataMapOfShapeShape& theSubShapes, + const bool theIsStoreSeparate = false, + const bool theIsStoreAsGenerated = false); + + /// Returns the number of sub-elements MODEL_EXPORT virtual int numberOfSubs(bool forTree = false) const;