]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Issue #2192 : change the naming principles of compsolid in case of Partition to make...
authormpv <mpv@opencascade.com>
Wed, 5 Jul 2017 10:58:36 +0000 (13:58 +0300)
committermpv <mpv@opencascade.com>
Wed, 5 Jul 2017 10:58:36 +0000 (13:58 +0300)
Makes some old studies and python files with Partition sub-shapes selection invalid.

12 files changed:
src/CollectionPlugin/CMakeLists.txt
src/CollectionPlugin/Test/TestGroup1799.py
src/CollectionPlugin/Test/TestGroupMove.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove2.py [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_Partition.cpp
src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.cpp
src/FeaturesPlugin/Test/Test2038.py
src/FeaturesPlugin/Test/Test2194.py
src/Model/Model_AttributeSelection.cpp
src/Model/Model_AttributeSelection.h
src/Model/Model_ResultCompSolid.cpp
src/Model/Model_ResultCompSolid.h

index 9725d50914bfed85d4dec490d3684ccab2397b90..4bc29cccb3d764fdde6a7ec498d4bb01ddeddbe8 100644 (file)
@@ -105,4 +105,6 @@ ADD_UNIT_TESTS(
                TestGroup.py
                TestField.py
                TestGroup1799.py
+               TestGroupMove.py
+               TestGroupMove2.py
 )
index c959182daeea34e2380093e165a14c454d1d72a1..8a767c0e71af344d0b444ca9e8bb0825b40dea20 100644 (file)
@@ -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 (file)
index 0000000..dd1e0c1
--- /dev/null
@@ -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<mailto: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 (file)
index 0000000..0f06d1d
--- /dev/null
@@ -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<mailto: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)
index a6ab995680ad1db03a72421d6f99ac8cc6a0a400..c2a78a62e875b86251d84eb3aba83bcd63f7976d 100755 (executable)
@@ -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);
   }
 
index 51d64cba431065a2446b5c271d56cd71e788e6a5..dbf4fc1ed059b17d9d6b768ebb3cfb0040376267 100644 (file)
 #include <ModelAPI_Validator.h>
 
 #include <GeomAPI_ShapeIterator.h>
+#include <GeomAPI_ShapeExplorer.h>
 
 #include <GeomAlgoAPI_Copy.h>
 #include <GeomAlgoAPI_ShapeBuilder.h>
 #include <GeomAlgoAPI_ShapeTools.h>
+#include <GeomAlgoAPI_MakeShapeCustom.h>
+
 
 //==================================================================================================
 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);
index f5371bbf5b7bcfe5926ef512354cf537de7fac81..0dd252ec94bd839404042450f88c3aded5603282 100644 (file)
@@ -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()
index 8cfc171ffc5155faf4978764766757e088bb3f92..0fd8972afe8e1e90847cd185387af26e1728219f 100644 (file)
@@ -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()
 
index 7348703eeb17c95499f749f23305f4cee53a7d7b..1e8aca1927a429aca3eb9b1037ccccc75d11becf 100644 (file)
@@ -47,6 +47,8 @@
 #include <TDataStd_UAttribute.hxx>
 #include <TDataStd_Name.hxx>
 #include <TopTools_ListOfShape.hxx>
+#include <TopTools_DataMapOfShapeShape.hxx>
+#include <TopTools_MapOfShape.hxx>
 #include <TopExp_Explorer.hxx>
 #include <BRep_Tool.hxx>
 #include <TopoDS.hxx>
@@ -54,6 +56,7 @@
 #include <TDF_ChildIterator.hxx>
 #include <TDF_ChildIDIterator.hxx>
 #include <TopoDS_Iterator.hxx>
+#include <TDF_ChildIDIterator.hxx>
 
 //#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>();
+  TopoDS_Shape aNewContShape = theNewContext->shape()->impl<TopoDS_Shape>();
+  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<ResultPtr> aNewToIterate;
+  aNewToIterate.push_back(theNewContext);
+  ResultCompSolidPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(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<ResultPtr>::iterator aNewContIter = aNewToIterate.begin();
+    for(; aNewContIter != aNewToIterate.end(); aNewContIter++) {
+      std::shared_ptr<Model_Data> aNewData =
+        std::dynamic_pointer_cast<Model_Data>((*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<TopoDS_Shape, TopTools_MapOfShape, TopTools_ShapeMapHasher> 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<TopoDS_Shape, TopTools_MapOfShape, TopTools_ShapeMapHasher>::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<Model_Document> theDoc,
+  const TopoDS_Shape theContShape, ResultPtr theContext, TopoDS_Shape theValShape,
+  TDF_Label theAccessLabel,
+  std::list<ResultPtr>& theResults, TopTools_ListOfShape& theValShapes)
+{
+  std::set<ResultPtr> aResults; // to avoid duplicates
+  TopTools_ListOfShape aResContShapes;
+  TNaming_SameShapeIterator aModifIter(theContShape, theAccessLabel);
+  for(; aModifIter.More(); aModifIter.Next()) {
+    ResultPtr aModifierObj = std::dynamic_pointer_cast<ModelAPI_Result>
+      (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<ModelAPI_Feature>(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<ResultPtr>::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<ResultPtr> 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<ResultPtr>::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<ModelAPI_Result>(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<ModelAPI_Result>
-        (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<GeomAPI_Shape> 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<TopoDS_Shape>();
   }
-  if (aModifierResFound.get()) {
+
+  std::list<ResultPtr> 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>();
-      TopoDS_Shape aNewShape = aModifierResFound->shape()->impl<TopoDS_Shape>();
-      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<ResultPtr>::iterator aNewCont = aNewContexts.begin();
+    TopTools_ListIteratorOfListOfShape aNewValues(aValShapes);
+    if (aNewCont == aNewContexts.end()) { // all results were deleted
+      ResultPtr anEmptyContext;
+      std::shared_ptr<GeomAPI_Shape> anEmptyShape;
+      setValue(anEmptyContext, anEmptyShape); // nullify the selection
+      return;
+    }
+
+    GeomShapePtr aValueShape;
+    if (!aNewValues.Value().IsNull()) {
+      aValueShape = std::make_shared<GeomAPI_Shape>();
+      aValueShape->setImpl<TopoDS_Shape>(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<GeomAPI_Shape>();
+          aValueShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aNewValues.Value()));
+        }
+        myParent->append(*aNewCont, aValueShape);
       }
     }
-    update(); // it must recompute a new sub-shape automatically
   }
 }
 
index c75766a73d02a81ededb201522fd8e5f09caad06..c2a65b535e31cb6f868d62b9b6e16608ff590787 100644 (file)
@@ -26,6 +26,7 @@
 #include <ModelAPI_AttributeSelection.h>
 #include <TDF_LabelMap.hxx>
 #include <TopoDS_Shape.hxx>
+#include <TopTools_ListOfShape.hxx>
 
 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<Model_Document> theDoc, const TopoDS_Shape theContShape,
+                        ResultPtr theContext, TopoDS_Shape theValShape, TDF_Label theAccessLabel,
+                        std::list<ResultPtr>& 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;
 };
index 0ba7c79b7a5656a317f0b72a98c4661d5576b3fc..e97a541bb4f24fff552e5d35cedb3d1783bf0cd6 100755 (executable)
@@ -65,6 +65,27 @@ void Model_ResultCompSolid::storeModified(const std::shared_ptr<GeomAPI_Shape>&
   updateSubs(theNewShape);
 }
 
+void Model_ResultCompSolid::loadAndOrientModifiedShapes (GeomAlgoAPI_MakeShape* theMS,
+    std::shared_ptr<GeomAPI_Shape>  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<std::shared_ptr<ModelAPI_ResultBody> >::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());
index 9715f01556030fc8cad967ac1d68f4549b30fd3d..69d81356591e5e7e9ac6415c1264c79d81009e3d 100755 (executable)
@@ -57,6 +57,14 @@ public:
   MODEL_EXPORT virtual void storeModified(const std::shared_ptr<GeomAPI_Shape>& theOldShape,
     const std::shared_ptr<GeomAPI_Shape>& theNewShape, const int theDecomposeSolidsTag = 0);
 
+  /// load and orient modified shapes for sub-objects
+  MODEL_EXPORT virtual void loadAndOrientModifiedShapes (GeomAlgoAPI_MakeShape* theMS,
+    std::shared_ptr<GeomAPI_Shape>  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;