]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Merge remote-tracking branch 'remotes/origin/HigherLevelObjectsHistory'
authorazv <azv@opencascade.com>
Tue, 26 Feb 2019 12:38:17 +0000 (15:38 +0300)
committerazv <azv@opencascade.com>
Tue, 26 Feb 2019 12:38:17 +0000 (15:38 +0300)
# Conflicts:
# env.sh
# src/FeaturesPlugin/CMakeLists.txt
# src/SketchPlugin/Test/TestUpdateSketch.py

97 files changed:
doc/gui/conf.py.in
src/BuildPlugin/BuildPlugin_CompSolid.cpp
src/BuildPlugin/BuildPlugin_CompSolid.h
src/BuildPlugin/BuildPlugin_Compound.cpp
src/BuildPlugin/BuildPlugin_Edge.cpp
src/BuildPlugin/BuildPlugin_Face.cpp
src/BuildPlugin/BuildPlugin_Face.h
src/BuildPlugin/BuildPlugin_Shape.cpp [new file with mode: 0644]
src/BuildPlugin/BuildPlugin_Shape.h [new file with mode: 0644]
src/BuildPlugin/BuildPlugin_Shell.cpp
src/BuildPlugin/BuildPlugin_Shell.h
src/BuildPlugin/BuildPlugin_Solid.cpp
src/BuildPlugin/BuildPlugin_Solid.h
src/BuildPlugin/BuildPlugin_Validators.cpp
src/BuildPlugin/CMakeLists.txt
src/BuildPlugin/Test/TestCompound_History.py [new file with mode: 0644]
src/CollectionPlugin/CMakeLists.txt
src/CollectionPlugin/Test/TestGroupMove.py [deleted file]
src/CollectionPlugin/Test/TestGroupMove01.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove02.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove03.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove04.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove05.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove06.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove07.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove08.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove09.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove10.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove11.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove12.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove13.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove14.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove15.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove16.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove17.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove18.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove19.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove2.py [deleted file]
src/CollectionPlugin/Test/TestGroupMove3.py [deleted file]
src/FeaturesPlugin/CMakeLists.txt
src/FeaturesPlugin/FeaturesPlugin_BooleanCommon.cpp
src/FeaturesPlugin/FeaturesPlugin_BooleanCut.cpp
src/FeaturesPlugin/FeaturesPlugin_BooleanFill.cpp
src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp
src/FeaturesPlugin/FeaturesPlugin_BooleanSmash.cpp
src/FeaturesPlugin/FeaturesPlugin_Fillet.cpp
src/FeaturesPlugin/FeaturesPlugin_FusionFaces.cpp
src/FeaturesPlugin/FeaturesPlugin_Intersection.cpp
src/FeaturesPlugin/FeaturesPlugin_MultiRotation.cpp
src/FeaturesPlugin/FeaturesPlugin_MultiRotation.h
src/FeaturesPlugin/FeaturesPlugin_MultiTranslation.cpp
src/FeaturesPlugin/FeaturesPlugin_MultiTranslation.h
src/FeaturesPlugin/FeaturesPlugin_Partition.cpp
src/FeaturesPlugin/FeaturesPlugin_Placement.cpp
src/FeaturesPlugin/FeaturesPlugin_Rotation.cpp
src/FeaturesPlugin/FeaturesPlugin_Scale.cpp
src/FeaturesPlugin/FeaturesPlugin_Symmetry.cpp
src/FeaturesPlugin/FeaturesPlugin_Tools.cpp
src/FeaturesPlugin/FeaturesPlugin_Tools.h
src/FeaturesPlugin/FeaturesPlugin_Translation.cpp
src/FeaturesPlugin/Test/Test1876.py [new file with mode: 0644]
src/FeaturesPlugin/Test/Test1942.py
src/FeaturesPlugin/Test/Test2636.py [new file with mode: 0644]
src/FeaturesPlugin/Test/Test2738.py [new file with mode: 0644]
src/FeaturesPlugin/Test/Test2826.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestBooleanCommon_SolidsHistory.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestBooleanCut_SolidsHistory.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestBooleanFuse_SolidsHistory.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestBooleanSmash_SolidsHistory.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillet_History.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestPartition_SolidsHistory.py [new file with mode: 0644]
src/GeomAPI/GeomAPI_Shape.cpp
src/GeomAPI/GeomAPI_Shape.h
src/GeomAlgoAPI/GeomAlgoAPI.i
src/GeomAlgoAPI/GeomAlgoAPI_Boolean.cpp
src/GeomAlgoAPI/GeomAlgoAPI_Boolean.h
src/GeomAlgoAPI/GeomAlgoAPI_MakeVolume.cpp
src/GeomAlgoAPI/GeomAlgoAPI_MakeVolume.h
src/GeomAlgoAPI/GeomAlgoAPI_Sewing.cpp
src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h
src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp
src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.h
src/GeomAlgoAPI/GeomAlgoAPI_UnifySameDomain.cpp
src/Model/Model_AttributeSelection.cpp
src/Model/Model_AttributeSelection.h
src/Model/Model_AttributeString.h
src/Model/Model_BodyBuilder.cpp
src/Model/Model_BodyBuilder.h
src/Model/Model_ResultBody.cpp
src/Model/Model_ResultBody.h
src/Model/Model_ResultConstruction.cpp
src/Model/Model_Update.cpp
src/ModelAPI/ModelAPI_BodyBuilder.h
src/ModelAPI/ModelAPI_ResultBody.cpp
src/ModelAPI/ModelAPI_ResultBody.h
src/ModelAPI/Test/Test2358_2.py
src/SketchPlugin/Test/TestMovementComplex.py

index ed3e6fd5b6636b7c7a27bccaf935020c80c5d11e..b02b59b3f3e5686d86b1aa25dad80846082246ff 100644 (file)
@@ -61,9 +61,9 @@ html_show_copyright = False
 # built documents.
 #
 # The short X.Y version.
-version = u'3.0.0'
+version = u'9.2.0'
 # The full version, including alpha/beta/rc tags.
-release = u'3.0.0'
+release = u'9.2.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
index 9034b1a7eafd5181ffdbcda09ef9671db188c998..c45eeb23eb3f4e396f98154ea26d8d8775e27daf 100644 (file)
@@ -32,25 +32,3 @@ void BuildPlugin_CompSolid::initAttributes()
 {
   data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
 }
-
-//=================================================================================================
-void BuildPlugin_CompSolid::execute()
-{
-  // all the needed checkings are in validator, so, here just make and store result
-  ListOfShape anOriginalShapes;
-  AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
-  for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
-    AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
-    GeomShapePtr aShape = aSelection->value();
-    if (!aShape.get())
-      aShape = aSelection->context()->shape();
-    anOriginalShapes.push_back(aShape);
-  }
-  std::shared_ptr<GeomAlgoAPI_MakeVolume> anAlgo(
-    new GeomAlgoAPI_MakeVolume(anOriginalShapes, false));
-  GeomShapePtr aVolumeRes = anAlgo->shape();
-
-  // check and process result of volume maker
-  GeomShapePtr aResShape = getSingleSubshape(aVolumeRes);
-  storeResult(anOriginalShapes, aResShape, anAlgo);
-}
index 335d6f8ebdc79b686818fe45d63418d593d09977..bf6b9c5dc742e32a93db5bfc65bd8c36532d289e 100644 (file)
@@ -55,9 +55,6 @@ public:
 
   /// Request for initialization of data model of the feature: adding all attributes.
   BUILDPLUGIN_EXPORT virtual void initAttributes();
-
-  /// Creates a new part document if needed.
-  BUILDPLUGIN_EXPORT virtual void execute();
 };
 
 #endif
index c2c6f756c1729bebd9cbd70fdda211c2e6e6bc75..7aa9a81641d78c6c47d0f58ae41f17c78968e6d5 100644 (file)
@@ -75,7 +75,7 @@ void BuildPlugin_Compound::execute()
   int anIndexToRemove = 0;
   if (aCopyCompound) {
     ResultBodyPtr aResultBody = document()->createBody(data(), anIndexToRemove++);
-    aResultBody->store(aCopyCompound);
+    aResultBody->storeModified(anOriginalShapes, aCopyCompound, aCopyAlgo);
     aResultBody->loadModifiedShapes(aCopyAlgo, aCompound, GeomAPI_Shape::VERTEX);
     aResultBody->loadModifiedShapes(aCopyAlgo, aCompound, GeomAPI_Shape::EDGE);
     aResultBody->loadModifiedShapes(aCopyAlgo, aCompound, GeomAPI_Shape::FACE);
index 30460c159e937b65f3fd53d2b939f78bd0cf7e55..c7928d083dcad5eb5bb818763d8baaf65148a8f2 100644 (file)
@@ -86,7 +86,10 @@ void BuildPlugin_Edge::execute()
 
     // Store result.
     ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
-    aResultBody->storeModified(aShape, aCopyAlgo->shape());
+
+    ListOfShape aBaseShapes;
+    aBaseShapes.push_back(aShape);
+    aResultBody->storeModified(aBaseShapes, aCopyAlgo->shape(), aCopyAlgo);
     aResultBody->loadModifiedShapes(aCopyAlgo, aShape, GeomAPI_Shape::VERTEX);
 
     setResult(aResultBody, aResultIndex);
index e4f43c6013fb731d36b0a8f8596a0bca3abf29c3..022865abdd3682773a3b4a0a1cee2e70858ea434 100644 (file)
@@ -27,6 +27,7 @@
 #include <GeomAPI_Pln.h>
 #include <GeomAPI_ShapeExplorer.h>
 
+#include <GeomAlgoAPI_MakeShapeList.h>
 #include <GeomAlgoAPI_ShapeTools.h>
 #include <GeomAlgoAPI_SketchBuilder.h>
 #include <GeomAlgoAPI_Copy.h>
@@ -59,6 +60,9 @@ void BuildPlugin_Face::execute()
   // Collect base shapes.
   ListOfShape anEdges;
   ListOfShape anOriginalFaces;
+  ListOfShape aContexts;
+  getOriginalShapesAndContexts(BASE_OBJECTS_ID(), anOriginalFaces, aContexts);
+  anOriginalFaces.clear();
   std::list< std::shared_ptr<GeomAPI_Dir> > aListOfNormals;
   for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
     AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
@@ -87,8 +91,10 @@ void BuildPlugin_Face::execute()
 
   // Build faces by edges.
   ListOfShape aFaces;
+  GeomMakeShapePtr aFaceBuilder;
   if (!anEdges.empty())
-    buildFacesByEdges(anEdges, aListOfNormals, aFaces);
+    buildFacesByEdges(anEdges, aListOfNormals, aFaces, aFaceBuilder);
+  int aNbFacesFromEdges = (int)aFaces.size();
 
   // Add faces selected by user.
   aFaces.insert(aFaces.end(), anOriginalFaces.begin(), anOriginalFaces.end());
@@ -96,22 +102,20 @@ void BuildPlugin_Face::execute()
   // Store result.
   int anIndex = 0;
   for(ListOfShape::const_iterator anIt = aFaces.cbegin(); anIt != aFaces.cend(); ++anIt) {
-    ResultBodyPtr aResultBody = document()->createBody(data(), anIndex);
-    GeomShapePtr aShape = *anIt;
-    GeomAlgoAPI_Copy aCopy(aShape);
-    aShape = aCopy.shape();
-    aResultBody->store(aShape);
-
-    // Store edges.
-    int anEdgeIndex = 1;
-    for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
-      GeomShapePtr anEdge = anExp.current();
-      aResultBody->generated(anEdge, "Edge_" + std::to_string((long long)anEdgeIndex));
-      ++anEdgeIndex;
-    }
+    std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList);
+    if (anIndex < aNbFacesFromEdges)
+      aMakeShapeList->appendAlgo(aFaceBuilder);
 
-    setResult(aResultBody, anIndex);
-    ++anIndex;
+    GeomShapePtr aShape = *anIt;
+    GeomMakeShapePtr aCopy(new GeomAlgoAPI_Copy(aShape));
+    aMakeShapeList->appendAlgo(aCopy);
+
+    ListOfShape aBaseShapes;
+    if (anIndex < aNbFacesFromEdges)
+      aBaseShapes = anEdges;
+    else
+      aBaseShapes.push_back(aShape);
+    storeResult(aMakeShapeList, aBaseShapes, aContexts, aCopy->shape(), anIndex++);
   }
 
   removeResults(anIndex);
@@ -120,7 +124,8 @@ void BuildPlugin_Face::execute()
 void BuildPlugin_Face::buildFacesByEdges(
     const ListOfShape& theEdges,
     const std::list< std::shared_ptr<GeomAPI_Dir> >& theNormals,
-    ListOfShape& theFaces) const
+    ListOfShape& theFaces,
+    std::shared_ptr<GeomAlgoAPI_MakeShape>& theBuilderAlgo) const
 {
   // Get plane.
   std::shared_ptr<GeomAPI_Pln> aPln = GeomAlgoAPI_ShapeTools::findPlane(theEdges);
@@ -136,8 +141,10 @@ void BuildPlugin_Face::buildFacesByEdges(
   }
 
   // Get faces.
-  GeomAlgoAPI_SketchBuilder::createFaces(aPln->location(), aPln->xDirection(),
-                                         aPln->direction(), theEdges, theFaces);
+  std::shared_ptr<GeomAlgoAPI_SketchBuilder> aSketchBuilder(
+      new GeomAlgoAPI_SketchBuilder(aPln, theEdges));
+  theFaces = aSketchBuilder->faces();
+  theBuilderAlgo = aSketchBuilder;
 
   // Get wires from faces.
   ListOfShape aWires;
index 90cc1933350af57a58b91987c2450f5dcd7723a8..1545de1a9b936e0834c99ee303f70ded4edd14f1 100644 (file)
 #define BuildPlugin_Face_H_
 
 #include "BuildPlugin.h"
-
-#include <ModelAPI_Feature.h>
+#include "BuildPlugin_Shape.h"
 
 class GeomAPI_Dir;
 class GeomAPI_Shape;
+class GeomAlgoAPI_MakeShape;
 
 /// \class BuildPlugin_Face
 /// \ingroup Plugins
 /// \brief Feature for creation of face from sketch edges or existing wires.
-class BuildPlugin_Face: public ModelAPI_Feature
+class BuildPlugin_Face: public BuildPlugin_Shape
 {
 public:
   /// Use plugin manager for features creation
@@ -67,7 +67,8 @@ private:
   /// Create faces basing on the list of edges
   void buildFacesByEdges(const std::list< std::shared_ptr<GeomAPI_Shape> >& theEdges,
                          const std::list< std::shared_ptr<GeomAPI_Dir> >& theNormals,
-                         std::list< std::shared_ptr<GeomAPI_Shape> >& theFaces) const;
+                         std::list< std::shared_ptr<GeomAPI_Shape> >& theFaces,
+                         std::shared_ptr<GeomAlgoAPI_MakeShape>& theBuilderAlgo) const;
 };
 
 #endif
diff --git a/src/BuildPlugin/BuildPlugin_Shape.cpp b/src/BuildPlugin/BuildPlugin_Shape.cpp
new file mode 100644 (file)
index 0000000..60c273c
--- /dev/null
@@ -0,0 +1,78 @@
+// 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>
+//
+
+#include "BuildPlugin_Shape.h"
+
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_ResultBody.h>
+
+#include <GeomAlgoAPI_MakeShape.h>
+
+#include <GeomAPI_PlanarEdges.h>
+
+
+//=================================================================================================
+void BuildPlugin_Shape::storeResult(const GeomMakeShapePtr& theAlgorithm,
+                                    const ListOfShape& theOriginalShapes,
+                                    const ListOfShape& theOriginalSolids,
+                                    const GeomShapePtr& theResultShape,
+                                    const int theResultIndex)
+{
+  ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
+  aResultBody->storeModified(theOriginalSolids, theResultShape, theAlgorithm);
+
+  for (ListOfShape::const_iterator anIt = theOriginalShapes.cbegin();
+       anIt != theOriginalShapes.cend();
+       ++anIt)
+  {
+    GeomShapePtr aShape = *anIt;
+    aResultBody->loadModifiedShapes(theAlgorithm, aShape, GeomAPI_Shape::VERTEX);
+    aResultBody->loadModifiedShapes(theAlgorithm, aShape, GeomAPI_Shape::EDGE);
+    aResultBody->loadModifiedShapes(theAlgorithm, aShape, GeomAPI_Shape::FACE);
+  }
+  setResult(aResultBody, theResultIndex);
+}
+
+//=================================================================================================
+void BuildPlugin_Shape::getOriginalShapesAndContexts(const std::string& theSelectionListID,
+                                                     ListOfShape& theShapes,
+                                                     ListOfShape& theContexts)
+{
+  std::set<GeomShapePtr, GeomAPI_Shape::Comparator> aContexts;
+
+  AttributeSelectionListPtr aSelectionList = selectionList(theSelectionListID);
+  for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
+    AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
+    GeomShapePtr aShape = aSelection->value();
+    GeomShapePtr aContext = aSelection->context()->shape();
+    if (!aShape.get())
+      aShape = aContext;
+    theShapes.push_back(aShape);
+
+    // do not collect sketch faces, because they are stored as compounds
+    // and then are treated as modified by the algorithm
+    if (!std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aContext).get())
+      aContexts.insert(aContext);
+  }
+
+  std::set<GeomShapePtr, GeomAPI_Shape::Comparator>::const_iterator anIt = aContexts.begin();
+  for (; anIt != aContexts.end(); ++anIt)
+    theContexts.push_back(*anIt);
+}
diff --git a/src/BuildPlugin/BuildPlugin_Shape.h b/src/BuildPlugin/BuildPlugin_Shape.h
new file mode 100644 (file)
index 0000000..e858ca1
--- /dev/null
@@ -0,0 +1,51 @@
+// 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>
+//
+
+#ifndef BuildPlugin_Shape_H_
+#define BuildPlugin_Shape_H_
+
+#include "BuildPlugin.h"
+
+#include <GeomAPI_Shape.h>
+
+#include <ModelAPI_Feature.h>
+
+class GeomAlgoAPI_MakeShape;
+
+/// \class BuildPlugin_Shape
+/// \ingroup Plugins
+/// \brief Base class containing common methods for shape creating operations.
+class BuildPlugin_Shape: public ModelAPI_Feature
+{
+protected:
+  /// Obtain list of selected shapes and their contexts
+  void getOriginalShapesAndContexts(const std::string& theSelectionListID,
+                                    ListOfShape& theShapes,
+                                    ListOfShape& theContexts);
+
+  /// Store result of algorithm
+  void storeResult(const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgorithm,
+                   const ListOfShape& theOriginalShapes,
+                   const ListOfShape& theOriginalContexts,
+                   const GeomShapePtr& theResultShape,
+                   const int theResultIndex = 0);
+};
+
+#endif
index ed71dcb0cc7aa443453628c2398466113a26c842..7f1010307502ee73fa57b18556aa824de3880354 100644 (file)
@@ -45,15 +45,8 @@ void BuildPlugin_Shell::execute()
   AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
 
   // Collect base shapes.
-  ListOfShape aShapes;
-  for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
-    AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
-    GeomShapePtr aShape = aSelection->value();
-    if(!aShape.get()) {
-      aShape = aSelection->context()->shape();
-    }
-    aShapes.push_back(aShape);
-  }
+  ListOfShape aShapes, aContexts;
+  getOriginalShapesAndContexts(BASE_OBJECTS_ID(), aShapes, aContexts);
 
   // Sew faces.
   GeomMakeShapePtr aSewingAlgo(new GeomAlgoAPI_Sewing(aShapes));
@@ -70,35 +63,7 @@ void BuildPlugin_Shell::execute()
   int anIndex = 0;
   for(GeomAPI_ShapeExplorer anExp(aResult, GeomAPI_Shape::SHELL); anExp.more(); anExp.next()) {
     GeomShapePtr aShell = anExp.current();
-    ResultBodyPtr aResultBody = document()->createBody(data(), anIndex);
-    aResultBody->store(aShell);
-    for(ListOfShape::const_iterator anIt = aShapes.cbegin(); anIt != aShapes.cend(); ++anIt) {
-      for (GeomAPI_ShapeExplorer aFaceExp(*anIt, GeomAPI_Shape::FACE);
-           aFaceExp.more();
-           aFaceExp.next())
-      {
-        GeomShapePtr aFace = aFaceExp.current();
-        ListOfShape aHistory;
-        aSewingAlgo->modified(aFace, aHistory);
-        for (ListOfShape::const_iterator aHistoryIt = aHistory.cbegin();
-             aHistoryIt != aHistory.cend();
-             ++aHistoryIt)
-        {
-          GeomShapePtr aHistoryShape = *aHistoryIt;
-          if (aShell->isSubShape(aHistoryShape, false)) {
-            aResultBody->loadModifiedShapes(aSewingAlgo,
-                                            aFace,
-                                            GeomAPI_Shape::EDGE);
-            aResultBody->loadModifiedShapes(aSewingAlgo,
-                                            aFace,
-                                            GeomAPI_Shape::FACE);
-            break;
-          }
-        }
-      }
-    }
-    setResult(aResultBody, anIndex);
-    ++anIndex;
+    storeResult(aSewingAlgo, aShapes, aContexts, aShell, anIndex++);
   }
 
   removeResults(anIndex);
index a89b5fbf04f6840ca931a9a0cd014ec982c0a0cc..514aa349e54b988769bf2ebecfd675d534d83067 100644 (file)
 #define BuildPlugin_Shell_H_
 
 #include "BuildPlugin.h"
-
-#include <ModelAPI_Feature.h>
+#include "BuildPlugin_Shape.h"
 
 /// \class BuildPlugin_Shell
 /// \ingroup Plugins
 /// \brief Feature for creation of shell from faces and shells.
-class BuildPlugin_Shell: public ModelAPI_Feature
+class BuildPlugin_Shell: public BuildPlugin_Shape
 {
 public:
   /// Use plugin manager for features creation
index 00d9a473a6af37608f39c4a26f0b18ee0121d321..215be1683a9f934717560d3b5f1f7324a84481ba 100644 (file)
@@ -22,6 +22,7 @@
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_ResultBody.h>
 
+#include <GeomAPI_ShapeExplorer.h>
 #include <GeomAPI_ShapeIterator.h>
 
 #include <GeomAlgoAPI_MakeVolume.h>
@@ -41,38 +42,15 @@ void BuildPlugin_Solid::initAttributes()
 void BuildPlugin_Solid::execute()
 {
   // all the needed checkings are in validator, so, here just make and store result
-  ListOfShape anOriginalShapes;
-  AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
-  for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
-    AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
-    GeomShapePtr aShape = aSelection->value();
-    if (!aShape.get())
-      aShape = aSelection->context()->shape();
-    anOriginalShapes.push_back(aShape);
-  }
+  ListOfShape anOriginalFaces;
+  ListOfShape anOriginalSolids;
+  getOriginalShapesAndContexts(BASE_OBJECTS_ID(), anOriginalFaces, anOriginalSolids);
+
   std::shared_ptr<GeomAlgoAPI_MakeVolume> anAlgo(
-    new GeomAlgoAPI_MakeVolume(anOriginalShapes, false));
+    new GeomAlgoAPI_MakeVolume(anOriginalFaces, false));
   // check and process result of volume maker
   GeomShapePtr aResShape = getSingleSubshape(anAlgo->shape());
-  storeResult(anOriginalShapes, aResShape, anAlgo);
-}
-
-void BuildPlugin_Solid::storeResult(const ListOfShape& theOriginalShapes,
-                                    const GeomShapePtr& theResultShape,
-                                    const GeomMakeShapePtr& theAlgorithm)
-{
-  ResultBodyPtr aResultBody = document()->createBody(data());
-  aResultBody->store(theResultShape);
-
-  // Store faces
-  for (ListOfShape::const_iterator anIt = theOriginalShapes.cbegin();
-       anIt != theOriginalShapes.cend();
-       ++anIt)
-  {
-    GeomShapePtr aShape = *anIt;
-    aResultBody->loadModifiedShapes(theAlgorithm, aShape, GeomAPI_Shape::FACE);
-  }
-  setResult(aResultBody);
+  storeResult(anAlgo, anOriginalFaces, anOriginalSolids, aResShape);
 }
 
 GeomShapePtr BuildPlugin_Solid::getSingleSubshape(const GeomShapePtr& theCompound)
index 3c323ee025590890e70e2bdde802e5e0d3607e8c..f364b94b0f93b7224632c39fbbd6a542ea7d8e69 100644 (file)
 #define BuildPlugin_Solid_H_
 
 #include "BuildPlugin.h"
-
-#include <GeomAPI_Shape.h>
-#include <ModelAPI_Feature.h>
-
-class GeomAlgoAPI_MakeShape;
+#include "BuildPlugin_Shape.h"
 
 /// \class BuildPlugin_Solid
 /// \ingroup Plugins
 /// \brief Feature for creation of solid from faces or shells.
-class BuildPlugin_Solid: public ModelAPI_Feature
+class BuildPlugin_Solid: public BuildPlugin_Shape
 {
 public:
   /// Use plugin manager for features creation
@@ -64,11 +60,6 @@ public:
   BUILDPLUGIN_EXPORT virtual void execute();
 
 protected:
-  /// Store result of algorithm
-  void storeResult(const ListOfShape& theOriginalShapes,
-                   const GeomShapePtr& theResultShape,
-                   const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgorithm);
-
   /// Explode compound to get single shape
   GeomShapePtr getSingleSubshape(const GeomShapePtr& theCompound);
 };
index 7dbc38e9d76f1a90a384b76631f7bb4378a08d49..4c7c8a4fc8afbbceb1fb1f1b6a1820c95730cc1f 100644 (file)
@@ -246,9 +246,8 @@ bool BuildPlugin_ValidatorBaseForFace::isValid(const std::shared_ptr<ModelAPI_Fe
     }
 
     // Check that selected objects have closed contours.
-    ListOfShape aFaces;
-    GeomAlgoAPI_SketchBuilder::createFaces(aPln->location(), aPln->xDirection(),
-                                           aPln->direction(), anEdges, aFaces);
+    GeomAlgoAPI_SketchBuilder aBuilder(aPln, anEdges);
+    const ListOfShape& aFaces = aBuilder.faces();
     if(aFaces.empty()) {
       theError = "Selected objects do not generate closed contour.";
       return false;
index 5d24b41255b2891b253ac8dc7f4b43857eb71822..f22f6598bbc9d5a385958abcfa4c4ca2c253a770 100644 (file)
@@ -31,6 +31,7 @@ INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/Events
 SET(PROJECT_HEADERS
     BuildPlugin.h
     BuildPlugin_Plugin.h
+    BuildPlugin_Shape.h
     BuildPlugin_Vertex.h
     BuildPlugin_Edge.h
     BuildPlugin_Wire.h
@@ -48,6 +49,7 @@ SET(PROJECT_HEADERS
 
 SET(PROJECT_SOURCES
     BuildPlugin_Plugin.cpp
+    BuildPlugin_Shape.cpp
     BuildPlugin_Vertex.cpp
     BuildPlugin_Edge.cpp
     BuildPlugin_Wire.cpp
@@ -119,6 +121,7 @@ ADD_UNIT_TESTS(TestVertex.py
                TestCompSolid.py
                TestCompound.py
                TestCompound_ErrorMsg.py
+               TestCompound_History.py
                TestSubShapes.py
                TestSubShapes_ErrorMsg.py
                TestFilling.py
diff --git a/src/BuildPlugin/Test/TestCompound_History.py b/src/BuildPlugin/Test/TestCompound_History.py
new file mode 100644 (file)
index 0000000..a0b494b
--- /dev/null
@@ -0,0 +1,73 @@
+## 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 the history of compound works correctly after movement of groups after this compound feature
+
+# -*- coding: utf-8 -*-
+
+from salome.shaper import model
+from ModelAPI import *
+from GeomAPI import *
+
+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"))
+SketchPoint_1 = Sketch_1.addPoint(-19.03078817733991, 40.92241379310347)
+SketchLine_1 = Sketch_1.addLine(-0.7463054187192111, 38.55911330049261, -18.03571428571429, 28.48399014778325)
+SketchCircle_1 = Sketch_1.addCircle(-2.238916256157633, 23.13546798029557, 5.523556488740459)
+model.do()
+Vertex_1 = model.addVertex(Part_1_doc, [model.selection("VERTEX", "Sketch_1/SketchPoint_1")])
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_1/SketchLine_1")])
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection(), 10, 0)
+Group_1_objects = [model.selection("VERTEX", "Vertex_1_1"), model.selection("VERTEX", "Edge_1_1/Modified_Vertex&Sketch_1/SketchLine_1_EndVertex"), model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]")]
+Group_1 = model.addGroup(Part_1_doc, Group_1_objects)
+Group_2 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Edge_1_1"), model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]")])
+Group_3 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")])
+Compound_1_objects = [model.selection("VERTEX", "Vertex_1_1"), model.selection("EDGE", "Edge_1_1"), model.selection("SOLID", "Extrusion_1_1")]
+Compound_1 = model.addCompound(Part_1_doc, Compound_1_objects)
+model.do()
+# move groups after the compound
+Part_1_doc.moveFeature(Group_1.feature(), Compound_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+Part_1_doc.moveFeature(Group_3.feature(), Group_2.feature())
+model.end()
+
+# check groups are correct
+aFactory = ModelAPI_Session.get().validators()
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 3)
+assert(aFactory.validate(Group_1.feature()))
+for i in range(3):
+  assert(Group_1.groupList().value(i).value().shapeType() == GeomAPI_Shape.VERTEX)
+
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 2)
+assert(aFactory.validate(Group_2.feature()))
+for i in range(2):
+  assert(Group_2.groupList().value(i).value().shapeType() == GeomAPI_Shape.EDGE)
+
+selectionList = Group_3.feature().selectionList("group_list")
+assert(selectionList.size() == 1)
+assert(aFactory.validate(Group_3.feature()))
+assert(Group_3.groupList().value(0).value().shapeType() == GeomAPI_Shape.SOLID)
+
+assert(model.checkPythonDump())
index ea7505203d7167b561924fc47f487040fab5a523..1ed8befc4f43f3d7a83bd2e8bccfb80c1d671b2b 100644 (file)
@@ -34,7 +34,7 @@ SET(PROJECT_HEADERS
     CollectionPlugin_Field.h
     CollectionPlugin_WidgetCreator.h
     CollectionPlugin_WidgetField.h
-       CollectionPlugin_Validators.h
+    CollectionPlugin_Validators.h
 )
 
 SET(PROJECT_MOC_HEADERS
@@ -47,7 +47,7 @@ SET(PROJECT_SOURCES
     CollectionPlugin_Field.cpp
     CollectionPlugin_WidgetCreator.cpp
     CollectionPlugin_WidgetField.cpp
-       CollectionPlugin_Validators.cpp
+    CollectionPlugin_Validators.cpp
 )
 
 SET(XML_RESOURCES
@@ -107,8 +107,24 @@ ADD_UNIT_TESTS(
                TestGroup2.py
                TestField.py
                TestGroup1799.py
-               TestGroupMove.py
-               TestGroupMove2.py
-               TestGroupMove3.py
+               TestGroupMove01.py
+               TestGroupMove02.py
+               TestGroupMove03.py
+               TestGroupMove04.py
+               TestGroupMove05.py
+               TestGroupMove06.py
+               TestGroupMove07.py
+               TestGroupMove08.py
+               TestGroupMove09.py
+               TestGroupMove10.py
+               TestGroupMove11.py
+               TestGroupMove12.py
+               TestGroupMove13.py
+               TestGroupMove14.py
+               TestGroupMove15.py
+               TestGroupMove16.py
+               TestGroupMove17.py
+               TestGroupMove18.py
+               TestGroupMove19.py
                TestGroupShareTopology.py
 )
diff --git a/src/CollectionPlugin/Test/TestGroupMove.py b/src/CollectionPlugin/Test/TestGroupMove.py
deleted file mode 100644 (file)
index fb3768c..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-# 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
-#
-
-# 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/TestGroupMove01.py b/src/CollectionPlugin/Test/TestGroupMove01.py
new file mode 100644 (file)
index 0000000..fb3768c
--- /dev/null
@@ -0,0 +1,49 @@
+# 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
+#
+
+# 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/TestGroupMove02.py b/src/CollectionPlugin/Test/TestGroupMove02.py
new file mode 100644 (file)
index 0000000..e764e5c
--- /dev/null
@@ -0,0 +1,44 @@
+# 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
+#
+
+# Test that removed vertex, selected in the group makes empty group => invalid one
+
+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() == 0)
+assert(aFactory.validate(Group_1.feature()) == False)
diff --git a/src/CollectionPlugin/Test/TestGroupMove03.py b/src/CollectionPlugin/Test/TestGroupMove03.py
new file mode 100644 (file)
index 0000000..495bd4b
--- /dev/null
@@ -0,0 +1,86 @@
+# 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
+#
+
+# Test that partition divides cylinder into 4 faces, there is no edges in a group moved to the end
+# Based on the CEA report mail 04.12.2018, page 2
+
+from SketchAPI import *
+
+from ModelAPI import *
+from GeomAPI 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("XOZ"))
+SketchArc_1 = Sketch_1.addArc(-1.103476974288834e-12, 24.99999999999979, 24.49489742783218, 30, 0, 50, False)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.result())
+SketchLine_2 = Sketch_1.addLine(0, 50, -10, 50)
+SketchLine_2.setAuxiliary(True)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_2.result())
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchArc_1.results()[1], SketchLine_2.result())
+SketchLine_3 = Sketch_1.addLine(24.49489742783218, 30, 24.49489742783218, 5)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(24.49489742783218, 5, 34.49489742783218, 5)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(34.49489742783218, 5, 34.49489742783218, 0)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_6 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.result())
+SketchLine_7 = Sketch_1.addLine(34.49489742783218, 0, 0, 0)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_7.endPoint())
+SketchLine_8 = Sketch_1.addLine(0, 50, 0, 0)
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_8.endPoint())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_4.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_5.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_4.result(), 10)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_5.result(), 5)
+SketchConstraintLength_3 = Sketch_1.setLength(SketchLine_3.result(), 25)
+SketchConstraintLength_4 = Sketch_1.setLength(SketchLine_8.result(), 50)
+SketchConstraintLength_5 = Sketch_1.setLength(SketchLine_2.result(), 10)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], 25)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchArc_1_2r-SketchLine_8f-SketchLine_7r-SketchLine_5r-SketchLine_4r-SketchLine_3r")], model.selection("EDGE", "PartSet/OZ"), 360, 0)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Revolution_1_1/Generated_Face&Sketch_1/SketchLine_3")])
+Partition_1_objects = [model.selection("SOLID", "Revolution_1_1"), model.selection("FACE", "PartSet/XOZ"), model.selection("FACE", "PartSet/YOZ")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects)
+model.do()
+
+# move group
+Part_1_doc.moveFeature(Group_1.feature(), Partition_1.feature())
+model.end()
+
+# Check group: result must be four faces
+aFactory = ModelAPI_Session.get().validators()
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 4)
+assert(aFactory.validate(Group_1.feature()))
+for i in range(4):
+  assert(Group_1.groupList().value(i).value().shapeType() == GeomAPI_Shape.FACE)
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupMove04.py b/src/CollectionPlugin/Test/TestGroupMove04.py
new file mode 100644 (file)
index 0000000..4755468
--- /dev/null
@@ -0,0 +1,64 @@
+## 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 of deep nested results history. Cylinders divided to two by cut, then each divided to
+# two by partition by plane, then resulting compsolids are collected in compound.
+# Checking that group on initial extrusion moved to the end contains the corresponding
+# results, but divided.
+
+from salome.shaper import model
+from ModelAPI import *
+
+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(-4.602216748768477, 10.94581280788177, 9.660420057801511)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2r")], model.selection(), 10, 0)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")])
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/YOZ"), 1, True)
+Sketch_2 = model.addSketch(Part_1_doc, model.standardPlane("XOY"))
+SketchCircle_2 = Sketch_2.addCircle(-5.643073116097736, 11.91382008305256, 15.03576198961618)
+model.do()
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchCircle_2_2r")], model.selection(), 2, -4)
+Cut_1 = model.addCut(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], [model.selection("SOLID", "Extrusion_2_1")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("COMPOUND", "Cut_1_1"), model.selection("FACE", "Plane_1")])
+Compound_1 = model.addCompound(Part_1_doc, [model.selection("COMPSOLID", "Partition_1_1"), model.selection("COMPSOLID", "Partition_1_2")])
+model.do()
+# move groups to the end
+Part_1_doc.moveFeature(Group_1.feature(), Compound_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+model.end()
+
+aFactory = ModelAPI_Session.get().validators()
+# check group 1: cylindical face is divided to 6 (because of seam edge)
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 6)
+assert(aFactory.validate(Group_1.feature()))
+
+# check group 2: solid is divided to 4 solids
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 4)
+assert(aFactory.validate(Group_2.feature()))
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupMove05.py b/src/CollectionPlugin/Test/TestGroupMove05.py
new file mode 100644 (file)
index 0000000..400fdab
--- /dev/null
@@ -0,0 +1,103 @@
+## 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 of deep nested results history.
+# Faces and edges of a box has been collected to groups. After that, the box has been copied.
+# Check that groups moved to the end contain corresponding results.
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Box_1_1")])
+Group_2_objects = [model.selection("FACE", "Box_1_1/Back"), model.selection("FACE", "Box_1_1/Top"), model.selection("FACE", "Box_1_1/Right"), model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Bottom"), model.selection("FACE", "Box_1_1/Front")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Group_3_objects = [model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Right]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Right]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+LinearCopy_1 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 15, 2)
+model.do()
+# move groups to the end
+Part_1_doc.moveFeature(Group_1.feature(), LinearCopy_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+Part_1_doc.moveFeature(Group_3.feature(), Group_2.feature())
+model.end()
+
+from ModelAPI import *
+
+aFactory = ModelAPI_Session.get().validators()
+# check group 1: all solids in compound should be selected
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 2)
+assert(aFactory.validate(Group_1.feature()))
+# check group 2: number of faces is multiplied twice than original
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 12)
+assert(aFactory.validate(Group_2.feature()))
+# check group 3: number of edges is multiplied twice than original
+selectionList = Group_3.feature().selectionList("group_list")
+assert(selectionList.size() == 24)
+assert(aFactory.validate(Group_3.feature()))
+
+model.begin()
+LinearCopy_2 = model.addMultiTranslation(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_1_1")], model.selection("EDGE", "PartSet/OY"), 15, 2, model.selection("EDGE", "PartSet/OZ"), 15, 2)
+# move groups to the end
+Part_1_doc.moveFeature(Group_1.feature(), LinearCopy_2.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+Part_1_doc.moveFeature(Group_3.feature(), Group_2.feature())
+model.end()
+
+# check group 1: all solids in compound should be selected
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 8)
+assert(aFactory.validate(Group_1.feature()))
+# check group 2: number of faces is multiplied twice than original
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 48)
+assert(aFactory.validate(Group_2.feature()))
+# check group 3: number of edges is multiplied twice than original
+selectionList = Group_3.feature().selectionList("group_list")
+assert(selectionList.size() == 96)
+assert(aFactory.validate(Group_3.feature()))
+
+model.begin()
+AngularCopy_1 = model.addMultiRotation(Part_1_doc, [model.selection("SOLID", "LinearCopy_2_1_1_1"), model.selection("SOLID", "LinearCopy_2_1_1_2")], model.selection("EDGE", "PartSet/OZ"), 2)
+# move groups to the end
+Part_1_doc.moveFeature(Group_1.feature(), AngularCopy_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+Part_1_doc.moveFeature(Group_3.feature(), Group_2.feature())
+model.end()
+
+# check group 1: all solids in compound should be selected
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 4)
+assert(aFactory.validate(Group_1.feature()))
+# check group 2: number of faces is multiplied twice than original
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 24)
+assert(aFactory.validate(Group_2.feature()))
+# check group 3: number of edges is multiplied twice than original
+selectionList = Group_3.feature().selectionList("group_list")
+assert(selectionList.size() == 48)
+assert(aFactory.validate(Group_3.feature()))
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupMove06.py b/src/CollectionPlugin/Test/TestGroupMove06.py
new file mode 100644 (file)
index 0000000..5229e0c
--- /dev/null
@@ -0,0 +1,128 @@
+## 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 of deep nested results history.
+# Copied boxes are involved to Fill operation.
+# Check the groups of initial boxes moved to the end contain the corresponding
+# results, but divided.
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Axis_4 = model.addAxis(Part_1_doc, model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Left][Box_1_1/Bottom]"), model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Right][Box_1_1/Top]"))
+LinearCopy_1 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "Axis_1"), 10, 2)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("SOLID", "LinearCopy_1_1_1")])
+Group_2_objects = [model.selection("FACE", "LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Back"), model.selection("FACE", "LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Top"), model.selection("FACE", "LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Right"), model.selection("FACE", "LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Left"), model.selection("FACE", "LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Bottom"), model.selection("FACE", "LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Front")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Group_3_objects = [model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Bottom]"), model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Right]"), model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Left]"), model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Top]"), model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Right][LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Bottom]"), model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Left][LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Top]"), model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Left][LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Bottom]"), model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Right][LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Top]"), model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Bottom]"), model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Left]"), model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Right]"), model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Top]")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+Group_4 = model.addGroup(Part_1_doc, [model.selection("SOLID", "LinearCopy_1_1_2")])
+Group_5_objects = [model.selection("FACE", "LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Back"), model.selection("FACE", "LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Top"), model.selection("FACE", "LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Right"), model.selection("FACE", "LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Left"), model.selection("FACE", "LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Bottom"), model.selection("FACE", "LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Front")]
+Group_5 = model.addGroup(Part_1_doc, Group_5_objects)
+Group_6_objects = [model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Back][LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Bottom]"), model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Back][LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Right]"), model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Back][LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Left]"), model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Back][LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Top]"), model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Right][LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Bottom]"), model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Left][LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Top]"), model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Left][LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Bottom]"), model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Right][LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Top]"), model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Front][LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Bottom]"), model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Front][LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Left]"), model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Front][LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Right]"), model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Front][LinearCopy_1_1_2/MF:Translated_Face&Box_1_1/Top]")]
+Group_6 = model.addGroup(Part_1_doc, Group_6_objects)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Left"), model.selection("FACE", "LinearCopy_1_1_1/MF:Translated_Face&Box_1_1/Right"))
+Fill_1 = model.addFill(Part_1_doc, [model.selection("SOLID", "LinearCopy_1_1_1")], [model.selection("SOLID", "LinearCopy_1_1_2"), model.selection("FACE", "Plane_1")])
+model.do()
+# move groups to the end
+Part_1_doc.moveFeature(Group_1.feature(), Fill_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+Part_1_doc.moveFeature(Group_3.feature(), Group_2.feature())
+Part_1_doc.moveFeature(Group_4.feature(), Group_3.feature())
+Part_1_doc.moveFeature(Group_5.feature(), Group_4.feature())
+Part_1_doc.moveFeature(Group_6.feature(), Group_5.feature())
+model.end()
+
+from ModelAPI import *
+
+aFactory = ModelAPI_Session.get().validators()
+
+# groups related to original box should be split
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 3)
+assert(aFactory.validate(Group_1.feature()))
+
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 13)
+assert(aFactory.validate(Group_2.feature()))
+
+selectionList = Group_3.feature().selectionList("group_list")
+assert(selectionList.size() == 19)
+assert(aFactory.validate(Group_3.feature()))
+
+# groups related to the copied box should contain only the elements connected with the original box
+selectionList = Group_4.feature().selectionList("group_list")
+assert(selectionList.size() == 1)
+assert(aFactory.validate(Group_4.feature()))
+
+selectionList = Group_5.feature().selectionList("group_list")
+assert(selectionList.size() == 3)
+assert(aFactory.validate(Group_5.feature()))
+
+selectionList = Group_6.feature().selectionList("group_list")
+assert(selectionList.size() == 3)
+assert(aFactory.validate(Group_6.feature()))
+
+
+model.begin()
+Filling_1 = model.addFilling(Part_1_doc, [model.selection("EDGE", "Fill_1_1_2/Generated_Edge&Plane_1/Plane_1&Box_1_1/Top"), model.selection("EDGE", "[Fill_1_1_2/Modified_Face&Box_1_1/Right][(Fill_1_1_2/Modified_Face&Box_1_1/Right)(Fill_1_1_2/Modified_Face&Plane_1/Plane_1)(Fill_1_1_2/Modified_Face&Box_1_1/Front)(Fill_1_1_2/Modified_Face&Box_1_1/Top)2(Fill_1_1_2/Modified_Face&Box_1_1/Left)2]")])
+Fill_2 = model.addFill(Part_1_doc, [model.selection("SOLID", "Fill_1_1_2")], [model.selection("FACE", "Filling_1_1")])
+model.do()
+# move groups to the end once again
+Part_1_doc.moveFeature(Group_1.feature(), Fill_2.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+Part_1_doc.moveFeature(Group_3.feature(), Group_2.feature())
+Part_1_doc.moveFeature(Group_4.feature(), Group_3.feature())
+Part_1_doc.moveFeature(Group_5.feature(), Group_4.feature())
+Part_1_doc.moveFeature(Group_6.feature(), Group_5.feature())
+model.end()
+
+# groups related to original box should be split
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 4)
+assert(aFactory.validate(Group_1.feature()))
+
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 16)
+assert(aFactory.validate(Group_2.feature()))
+
+selectionList = Group_3.feature().selectionList("group_list")
+# one of edges should disappear, due to its belonging to the face of the filling
+assert(selectionList.size() == 18)
+assert(aFactory.validate(Group_3.feature()))
+
+# groups related to the copied box should be split correspondingly
+selectionList = Group_4.feature().selectionList("group_list")
+assert(selectionList.size() == 1)
+assert(aFactory.validate(Group_4.feature()))
+
+selectionList = Group_5.feature().selectionList("group_list")
+assert(selectionList.size() == 6)
+assert(aFactory.validate(Group_5.feature()))
+
+selectionList = Group_6.feature().selectionList("group_list")
+assert(selectionList.size() == 5)
+assert(aFactory.validate(Group_6.feature()))
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupMove07.py b/src/CollectionPlugin/Test/TestGroupMove07.py
new file mode 100644 (file)
index 0000000..04c84e2
--- /dev/null
@@ -0,0 +1,83 @@
+## 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 of deep nested results history.
+# Faces and edges of a box has been collected to groups. After that, the box has been symmetried.
+# Check that groups moved to the end contain corresponding results.
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Box_1_1")])
+Group_2_objects = [model.selection("FACE", "Box_1_1/Back"), model.selection("FACE", "Box_1_1/Top"), model.selection("FACE", "Box_1_1/Right"), model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Bottom"), model.selection("FACE", "Box_1_1/Front")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Group_3_objects = [model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Right]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Right]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+Symmetry_1 = model.addSymmetry(Part_1_doc, [model.selection("SOLID", "Box_1_1")], model.selection("FACE", "Box_1_1/Left"), False)
+model.do()
+# move groups to the end
+Part_1_doc.moveFeature(Group_1.feature(), Symmetry_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+Part_1_doc.moveFeature(Group_3.feature(), Group_2.feature())
+model.end()
+
+from ModelAPI import *
+
+aFactory = ModelAPI_Session.get().validators()
+# check group 1: solids should be selected
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 1)
+assert(aFactory.validate(Group_1.feature()))
+# check group 2: number of faces is the same
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 6)
+assert(aFactory.validate(Group_2.feature()))
+# check group 3: number of edges is the same
+selectionList = Group_3.feature().selectionList("group_list")
+assert(selectionList.size() == 12)
+assert(aFactory.validate(Group_3.feature()))
+
+model.begin()
+Symmetry_2 = model.addSymmetry(Part_1_doc, [model.selection("SOLID", "Symmetry_1_1")], model.selection("VERTEX", "[Symmetry_1_1/MF:Symmetried_Face&Box_1_1/Front][Symmetry_1_1/MF:Symmetried_Face&Box_1_1/Left][Symmetry_1_1/MF:Symmetried_Face&Box_1_1/Bottom]"), True)
+model.do()
+# move groups to the end
+Part_1_doc.moveFeature(Group_1.feature(), Symmetry_2.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+Part_1_doc.moveFeature(Group_3.feature(), Group_2.feature())
+model.end()
+
+# check group 1: all solids in compound should be selected
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 2)
+assert(aFactory.validate(Group_1.feature()))
+# check group 2: number of faces is multiplied twice than original
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 12)
+assert(aFactory.validate(Group_2.feature()))
+# check group 3: number of edges is multiplied twice than original
+selectionList = Group_3.feature().selectionList("group_list")
+assert(selectionList.size() == 24)
+assert(aFactory.validate(Group_3.feature()))
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupMove08.py b/src/CollectionPlugin/Test/TestGroupMove08.py
new file mode 100644 (file)
index 0000000..91fbcc3
--- /dev/null
@@ -0,0 +1,128 @@
+## 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 of deep nested results history. Fillet operation.
+# Check the groups of initial solids moved to the end contain the corresponding
+# results, but divided.
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Box_1_1")])
+Group_2_objects = [model.selection("FACE", "Box_1_1/Back"), model.selection("FACE", "Box_1_1/Top"), model.selection("FACE", "Box_1_1/Right"), model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Bottom"), model.selection("FACE", "Box_1_1/Front")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Group_3_objects = [model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Right]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Right]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Left][Box_1_1/Top]"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Group_4 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")])
+Group_5_objects = [model.selection("FACE", "Cylinder_1_1/Face_1"), model.selection("FACE", "Cylinder_1_1/Face_2"), model.selection("FACE", "Cylinder_1_1/Face_3")]
+Group_5 = model.addGroup(Part_1_doc, Group_5_objects)
+Group_6_objects = [model.selection("EDGE", "[Cylinder_1_1/Face_1][Cylinder_1_1/Face_2]"), model.selection("EDGE", "[Cylinder_1_1/Face_1][Cylinder_1_1/Face_3]"), model.selection("EDGE", "([Cylinder_1_1/Face_1][Cylinder_1_1/Face_2])([Cylinder_1_1/Face_1][Cylinder_1_1/Face_3])")]
+Group_6 = model.addGroup(Part_1_doc, Group_6_objects)
+Fillet_1 = model.addFillet(Part_1_doc, [model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]")], 2)
+model.do()
+# move groups to the end
+Part_1_doc.moveFeature(Group_1.feature(), Fillet_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+Part_1_doc.moveFeature(Group_3.feature(), Group_2.feature())
+model.end()
+
+from ModelAPI import *
+
+aFactory = ModelAPI_Session.get().validators()
+
+# groups related to original box should be split
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 1)
+assert(aFactory.validate(Group_1.feature()))
+
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 6)
+assert(aFactory.validate(Group_2.feature()))
+
+selectionList = Group_3.feature().selectionList("group_list")
+assert(selectionList.size() == 11)
+assert(aFactory.validate(Group_3.feature()))
+
+model.begin()
+Fillet_2 = model.addFillet(Part_1_doc, [model.selection("FACE", "Cylinder_1_1/Face_2")], 2)
+model.do()
+# move groups to the end
+Part_1_doc.moveFeature(Group_4.feature(), Fillet_2.feature())
+Part_1_doc.moveFeature(Group_5.feature(), Group_4.feature())
+Part_1_doc.moveFeature(Group_6.feature(), Group_5.feature())
+model.end()
+
+# groups related to original cylinder should be split
+selectionList = Group_4.feature().selectionList("group_list")
+assert(selectionList.size() == 1)
+assert(aFactory.validate(Group_4.feature()))
+
+selectionList = Group_5.feature().selectionList("group_list")
+assert(selectionList.size() == 3)
+assert(aFactory.validate(Group_5.feature()))
+
+selectionList = Group_6.feature().selectionList("group_list")
+assert(selectionList.size() == 2) # edge selected for the fillet become removed
+assert(aFactory.validate(Group_6.feature()))
+
+model.begin()
+Fillet_3 = model.addFillet(Part_1_doc, [model.selection("EDGE", "[Fillet_1_1/MF:Fillet_Face&Box_1_1/Front][Fillet_1_1/MF:Fillet_Face&Box_1_1/Left]")], 1, 2)
+model.do()
+# move groups to the end
+Part_1_doc.moveFeature(Group_1.feature(), Fillet_3.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+Part_1_doc.moveFeature(Group_3.feature(), Group_2.feature())
+Part_1_doc.moveFeature(Group_4.feature(), Group_3.feature())
+Part_1_doc.moveFeature(Group_5.feature(), Group_4.feature())
+Part_1_doc.moveFeature(Group_6.feature(), Group_5.feature())
+model.end()
+
+# groups related to original box should be split
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 1)
+assert(aFactory.validate(Group_1.feature()))
+
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 6)
+assert(aFactory.validate(Group_2.feature()))
+
+selectionList = Group_3.feature().selectionList("group_list")
+assert(selectionList.size() == 9)
+assert(aFactory.validate(Group_3.feature()))
+
+# groups related to original cylinder should stay untouched
+selectionList = Group_4.feature().selectionList("group_list")
+assert(selectionList.size() == 1)
+assert(aFactory.validate(Group_4.feature()))
+
+selectionList = Group_5.feature().selectionList("group_list")
+assert(selectionList.size() == 3)
+assert(aFactory.validate(Group_5.feature()))
+
+selectionList = Group_6.feature().selectionList("group_list")
+assert(selectionList.size() == 2)
+assert(aFactory.validate(Group_6.feature()))
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupMove09.py b/src/CollectionPlugin/Test/TestGroupMove09.py
new file mode 100644 (file)
index 0000000..f8b3383
--- /dev/null
@@ -0,0 +1,75 @@
+## 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 of deep nested results history. FuseFaces operation.
+# Check the groups of initial solids moved to the end contain the corresponding
+# results, but merged faces.
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1"), model.selection("SOLID", "Box_1_1")])
+Union_1_objects = [model.selection("SOLID", "Partition_1_1_1"), model.selection("SOLID", "Partition_1_1_2"), model.selection("SOLID", "Partition_1_1_3")]
+Union_1 = model.addUnion(Part_1_doc, Union_1_objects)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Union_1_1")])
+Group_2_objects = [model.selection("FACE", "Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_1"), model.selection("FACE", "Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_2"), model.selection("FACE", "Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_3"), model.selection("FACE", "Partition_1_1_2/Modified_Face&Box_1_1/Bottom&Cylinder_1_1/Face_3"), model.selection("FACE", "Partition_1_1_2/Modified_Face&Box_1_1/Top&Cylinder_1_1/Face_2"), model.selection("FACE", "Partition_1_1_3/Modified_Face&Box_1_1/Back"), model.selection("FACE", "Partition_1_1_3/Modified_Face&Box_1_1/Bottom"), model.selection("FACE", "Partition_1_1_3/Modified_Face&Box_1_1/Top"), model.selection("FACE", "Box_1_1/Right"), model.selection("FACE", "Partition_1_1_3/Modified_Face&Box_1_1/Left"), model.selection("FACE", "Box_1_1/Front")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Group_3_objects = [model.selection("EDGE", "[Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_1][Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_3]"), model.selection("EDGE", "[Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_2][Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_1]"), model.selection("EDGE", "([Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_1][Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_3])(Partition_1_1_3/Generated_Edge&Box_1_1/Back&Cylinder_1_1/Face_1)([Partition_1_1_3/Modified_Face&Box_1_1/Back][Partition_1_1_3/Modified_Face&Box_1_1/Bottom])([Partition_1_1_3/Modified_Face&Box_1_1/Bottom][Partition_1_1_2/Modified_Face&Box_1_1/Bottom&Cylinder_1_1/Face_3])_Union_1_1"), model.selection("EDGE", "[Partition_1_1_3/Modified_Face&Box_1_1/Back][Partition_1_1_3/Modified_Face&Box_1_1/Bottom]"), model.selection("EDGE", "[Partition_1_1_3/Modified_Face&Box_1_1/Back][Box_1_1/Right]"), model.selection("EDGE", "Partition_1_1_3/Generated_Edge&Box_1_1/Back&Cylinder_1_1/Face_1"), model.selection("EDGE", "([Partition_1_1_2/Modified_Face&Box_1_1/Top&Cylinder_1_1/Face_2][Partition_1_1_3/Modified_Face&Box_1_1/Top])([Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_2][Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_1])([Partition_1_1_3/Modified_Face&Box_1_1/Top][Partition_1_1_3/Modified_Face&Box_1_1/Back])(Partition_1_1_3/Generated_Edge&Box_1_1/Back&Cylinder_1_1/Face_1)_Union_1_1"), model.selection("EDGE", "[Partition_1_1_3/Modified_Face&Box_1_1/Top][Partition_1_1_3/Modified_Face&Box_1_1/Back]"), model.selection("EDGE", "([Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_1][Partition_1_1_3/Modified_Face&Box_1_1/Left])([Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_1][Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_3])([Partition_1_1_3/Modified_Face&Box_1_1/Left][Partition_1_1_3/Modified_Face&Box_1_1/Bottom])([Partition_1_1_3/Modified_Face&Box_1_1/Bottom][Partition_1_1_2/Modified_Face&Box_1_1/Bottom&Cylinder_1_1/Face_3])_Union_1_1"), model.selection("EDGE", "[Partition_1_1_3/Modified_Face&Box_1_1/Bottom][Partition_1_1_2/Modified_Face&Box_1_1/Bottom&Cylinder_1_1/Face_3]"), model.selection("EDGE", "[Partition_1_1_2/Modified_Face&Box_1_1/Top&Cylinder_1_1/Face_2][Partition_1_1_3/Modified_Face&Box_1_1/Top]"), model.selection("EDGE", "([Partition_1_1_2/Modified_Face&Box_1_1/Top&Cylinder_1_1/Face_2][Partition_1_1_3/Modified_Face&Box_1_1/Top])([Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_2][Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_1])([Partition_1_1_3/Modified_Face&Box_1_1/Top][Partition_1_1_3/Modified_Face&Box_1_1/Left])([Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_1][Partition_1_1_3/Modified_Face&Box_1_1/Left])_Union_1_1"), model.selection("EDGE", "[Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_1][Partition_1_1_3/Modified_Face&Box_1_1/Left]"), model.selection("EDGE", "[Partition_1_1_3/Modified_Face&Box_1_1/Top][Box_1_1/Right]"), model.selection("EDGE", "[Box_1_1/Right][Partition_1_1_3/Modified_Face&Box_1_1/Bottom]"), model.selection("EDGE", "[Partition_1_1_3/Modified_Face&Box_1_1/Left][Partition_1_1_3/Modified_Face&Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Partition_1_1_3/Modified_Face&Box_1_1/Left]"), model.selection("EDGE", "[Partition_1_1_3/Modified_Face&Box_1_1/Top][Partition_1_1_3/Modified_Face&Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Front][Partition_1_1_3/Modified_Face&Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Front]"), model.selection("EDGE", "[Partition_1_1_3/Modified_Face&Box_1_1/Top][Box_1_1/Front]")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+Group_4_objects = [model.selection("VERTEX", "[Partition_1_1_3/Modified_Face&Box_1_1/Top][Box_1_1/Front][Partition_1_1_3/Modified_Face&Box_1_1/Left]"), model.selection("VERTEX", "[Partition_1_1_2/Modified_Face&Box_1_1/Top&Cylinder_1_1/Face_2][Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_2][Partition_1_1_3/Modified_Face&Box_1_1/Top][Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_1][Partition_1_1_3/Modified_Face&Box_1_1/Left]"), model.selection("VERTEX", "[Box_1_1/Front][Partition_1_1_3/Modified_Face&Box_1_1/Left][Partition_1_1_3/Modified_Face&Box_1_1/Bottom]"), model.selection("VERTEX", "[_weak_name_10_Union_1_1]e[_weak_name_4_Union_1_1]e"), model.selection("VERTEX", "[Partition_1_1_3/Modified_Face&Box_1_1/Top][Box_1_1/Right][Box_1_1/Front]"), model.selection("VERTEX", "[Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_1][Partition_1_1_3/Modified_Face&Box_1_1/Left][Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_3][Partition_1_1_3/Modified_Face&Box_1_1/Bottom][Partition_1_1_2/Modified_Face&Box_1_1/Bottom&Cylinder_1_1/Face_3]"), model.selection("VERTEX", "[Partition_1_1_2/Modified_Face&Box_1_1/Top&Cylinder_1_1/Face_2][Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_2][Partition_1_1_3/Modified_Face&Box_1_1/Top][Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_1][Partition_1_1_3/Modified_Face&Box_1_1/Back]"), model.selection("VERTEX", "[Box_1_1/Right][Box_1_1/Front][Partition_1_1_3/Modified_Face&Box_1_1/Bottom]"), model.selection("VERTEX", "[_weak_name_3_Union_1_1]e[_weak_name_9_Union_1_1]e"), model.selection("VERTEX", "[Partition_1_1_3/Modified_Face&Box_1_1/Top][Partition_1_1_3/Modified_Face&Box_1_1/Back][Box_1_1/Right]"), model.selection("VERTEX", "[Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_1][Partition_1_1_3/Modified_Face&Box_1_1/Back][Partition_1_1_1/Modified_Face&Cylinder_1_1/Face_3][Partition_1_1_3/Modified_Face&Box_1_1/Bottom][Partition_1_1_2/Modified_Face&Box_1_1/Bottom&Cylinder_1_1/Face_3]"), model.selection("VERTEX", "[Partition_1_1_3/Modified_Face&Box_1_1/Back][Box_1_1/Right][Partition_1_1_3/Modified_Face&Box_1_1/Bottom]")]
+Group_4 = model.addGroup(Part_1_doc, Group_4_objects)
+FusionFaces_1 = model.addFusionFaces(Part_1_doc, model.selection("SOLID", "Union_1_1"))
+model.do()
+# move groups to the end
+Part_1_doc.moveFeature(Group_1.feature(), FusionFaces_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+Part_1_doc.moveFeature(Group_3.feature(), Group_2.feature())
+Part_1_doc.moveFeature(Group_4.feature(), Group_3.feature())
+model.end()
+
+from ModelAPI import *
+
+aFactory = ModelAPI_Session.get().validators()
+
+# number of solids should be the same
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 1)
+assert(aFactory.validate(Group_1.feature()))
+
+# same-plane faces should be merged
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 11)
+assert(aFactory.validate(Group_2.feature()))
+
+# shared edges of merged faces should be deleted
+selectionList = Group_3.feature().selectionList("group_list")
+assert(selectionList.size() == 15)
+assert(aFactory.validate(Group_3.feature()))
+
+selectionList = Group_4.feature().selectionList("group_list")
+assert(selectionList.size() == 10)
+assert(aFactory.validate(Group_4.feature()))
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupMove10.py b/src/CollectionPlugin/Test/TestGroupMove10.py
new file mode 100644 (file)
index 0000000..ee973fd
--- /dev/null
@@ -0,0 +1,71 @@
+## 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>
+##
+
+from salome.shaper import model
+from ModelAPI import *
+
+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(-8, 20, 25)
+SketchLine_1 = Sketch_1.addLine(40, 32, -5, 32)
+SketchLine_2 = Sketch_1.addLine(-5, 32, -5, 5)
+SketchLine_3 = Sketch_1.addLine(-5, 5, 40, 5)
+SketchLine_4 = Sketch_1.addLine(40, 5, 40, 32)
+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())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), 10, 0)
+Group_1_objects = [model.selection("SOLID", "Extrusion_1_1_2"), model.selection("SOLID", "Extrusion_1_1_1"), model.selection("SOLID", "Extrusion_1_1_3")]
+Group_1 = model.addGroup(Part_1_doc, Group_1_objects)
+# to create groups of faces, edges and vertices
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+model.do()
+Remove_SubShapes_1 = model.addRemoveSubShapes(Part_1_doc, model.selection("COMPSOLID", "Extrusion_1_1"))
+Remove_SubShapes_1.setSubShapesToRemove([model.selection("SOLID", "Extrusion_1_1_2"), model.selection("SOLID", "Extrusion_1_1_3")])
+model.do()
+# move groups to the end
+LastFeature = Remove_SubShapes_1.feature()
+for i in range(Part_1_doc.size("Groups")):
+  GroupFeature = Part_1_doc.feature(objectToResult(Part_1_doc.object("Groups", 0))) # move always the very first group
+  Part_1_doc.moveFeature(GroupFeature, LastFeature)
+  LastFeature = GroupFeature
+model.end()
+
+aFactory = ModelAPI_Session.get().validators()
+
+# Check groups
+a = 0
+num_in_groups = [1, 10, 15, 7]
+for i in range(Part_1_doc.size("Groups")):
+  GroupFeature = Part_1_doc.feature(objectToResult(Part_1_doc.object("Groups", i)))
+  assert(aFactory.validate(GroupFeature))
+  assert(GroupFeature.selectionList("group_list").size() == num_in_groups[a])
+  a = a + 1
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupMove11.py b/src/CollectionPlugin/Test/TestGroupMove11.py
new file mode 100644 (file)
index 0000000..76186a6
--- /dev/null
@@ -0,0 +1,72 @@
+## 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 of deep nested results history. Scale operation.
+# Check the groups of initial solids moved to the end contain the corresponding results.
+
+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(-15, 30, 30)
+SketchCircle_2 = Sketch_1.addCircle(15, 25, 25)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), 10, 0)
+Group_1_objects = [model.selection("SOLID", "Extrusion_1_1_3"), model.selection("SOLID", "Extrusion_1_1_1"), model.selection("SOLID", "Extrusion_1_1_2")]
+Group_1 = model.addGroup(Part_1_doc, Group_1_objects)
+Group_2_objects = [model.selection("FACE", "Extrusion_1_1_3/Generated_Face&Sketch_1/SketchCircle_2_2"), model.selection("FACE", "Extrusion_1_1_3/Generated_Face&Sketch_1/SketchCircle_1_2"), model.selection("FACE", "Extrusion_1_1_3/From_Face"), model.selection("FACE", "Extrusion_1_1_3/To_Face"), model.selection("FACE", "Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_1"), model.selection("FACE", "Extrusion_1_1_1/To_Face"), model.selection("FACE", "Extrusion_1_1_1/From_Face"), model.selection("FACE", "Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_2_2"), model.selection("FACE", "Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_2"), model.selection("FACE", "Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_2_2&weak_name_1"), model.selection("FACE", "Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_1"), model.selection("FACE", "Extrusion_1_1_2/From_Face"), model.selection("FACE", "Extrusion_1_1_2/To_Face"), model.selection("FACE", "Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_2"), model.selection("FACE", "Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_2_2&weak_name_2")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Group_3_objects = [model.selection("EDGE", "[Extrusion_1_1_3/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1_3/Generated_Face&Sketch_1/SketchCircle_2_2][weak_name_1]"), model.selection("EDGE", "[Extrusion_1_1_3/Generated_Face&Sketch_1/SketchCircle_2_2][Extrusion_1_1_3/From_Face]"), model.selection("EDGE", "[Extrusion_1_1_3/Generated_Face&Sketch_1/SketchCircle_2_2][Extrusion_1_1_3/To_Face]"), model.selection("EDGE", "[Extrusion_1_1_3/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1_3/From_Face]"), model.selection("EDGE", "[Extrusion_1_1_3/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1_3/To_Face]"), model.selection("EDGE", "[Extrusion_1_1_3/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1_3/Generated_Face&Sketch_1/SketchCircle_2_2][weak_name_2]"), model.selection("EDGE", "[Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_1][Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_2_2]"), model.selection("EDGE", "[Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_1][Extrusion_1_1_1/From_Face]"), model.selection("EDGE", "[Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_1][Extrusion_1_1_1/To_Face]"), model.selection("EDGE", "[Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_2_2][Extrusion_1_1_1/From_Face]"), model.selection("EDGE", "[Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_1][Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_2]"), model.selection("EDGE", "[Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_2_2][Extrusion_1_1_1/To_Face]"), model.selection("EDGE", "[Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_2][Extrusion_1_1_1/To_Face]"), model.selection("EDGE", "[Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_2][Extrusion_1_1_1/From_Face]"), model.selection("EDGE", "[Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_2][Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_2_2]"), model.selection("EDGE", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_1][Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_2_2&weak_name_1]"), model.selection("EDGE", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_2_2&weak_name_1][Extrusion_1_1_2/From_Face]"), model.selection("EDGE", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_2_2&weak_name_1][Extrusion_1_1_2/To_Face]"), model.selection("EDGE", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_1][Extrusion_1_1_2/To_Face]"), model.selection("EDGE", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_1][Extrusion_1_1_2/From_Face]"), model.selection("EDGE", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_1][Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_2]"), model.selection("EDGE", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_2][Extrusion_1_1_2/To_Face]"), model.selection("EDGE", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_2][Extrusion_1_1_2/From_Face]"), model.selection("EDGE", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_2_2&weak_name_2][Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_2]"), model.selection("EDGE", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_2_2&weak_name_2][Extrusion_1_1_2/To_Face]"), model.selection("EDGE", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_2_2&weak_name_2][Extrusion_1_1_2/From_Face]"), model.selection("EDGE", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_2_2&weak_name_1][Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_2_2&weak_name_2]")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+Group_4_objects = [model.selection("VERTEX", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_2_2&weak_name_1][Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_2_2&weak_name_2][Extrusion_1_1_2/To_Face]"), model.selection("VERTEX", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_2_2&weak_name_1][Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_2_2&weak_name_2][Extrusion_1_1_2/From_Face]"), model.selection("VERTEX", "[Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_1][Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_2_2][Extrusion_1_1_1/To_Face]"), model.selection("VERTEX", "[_weak_name_5_Extrusion_1_1_3]e[_weak_name_2_Extrusion_1_1_3]e[_weak_name_4_Extrusion_1_1_3]e"), model.selection("VERTEX", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_1][Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_2_2&weak_name_1][Extrusion_1_1_2/To_Face]"), model.selection("VERTEX", "[_weak_name_5_Extrusion_1_1_3]e[_weak_name_1_Extrusion_1_1_3]e[_weak_name_3_Extrusion_1_1_3]e"), model.selection("VERTEX", "[Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_1][Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_2_2][Extrusion_1_1_1/From_Face]"), model.selection("VERTEX", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_1][Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_2_2&weak_name_1][Extrusion_1_1_2/From_Face]"), model.selection("VERTEX", "[Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_1][Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_2][Extrusion_1_1_1/To_Face]"), model.selection("VERTEX", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_1][Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_2][Extrusion_1_1_2/To_Face]"), model.selection("VERTEX", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_1][Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_2][Extrusion_1_1_2/From_Face]"), model.selection("VERTEX", "[Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_1][Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_2][Extrusion_1_1_1/From_Face]"), model.selection("VERTEX", "[_weak_name_6_Extrusion_1_1_3]e[_weak_name_2_Extrusion_1_1_3]e[_weak_name_4_Extrusion_1_1_3]e"), model.selection("VERTEX", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_2_2&weak_name_2][Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_2][Extrusion_1_1_2/To_Face]"), model.selection("VERTEX", "[Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_2][Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_2_2][Extrusion_1_1_1/To_Face]"), model.selection("VERTEX", "[_weak_name_6_Extrusion_1_1_3]e[_weak_name_1_Extrusion_1_1_3]e[_weak_name_3_Extrusion_1_1_3]e"), model.selection("VERTEX", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_2_2&weak_name_2][Extrusion_1_1_2/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_2][Extrusion_1_1_2/From_Face]"), model.selection("VERTEX", "[Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_1_2&weak_name_2][Extrusion_1_1_1/Generated_Face&Sketch_1/SketchCircle_2_2][Extrusion_1_1_1/From_Face]")]
+Group_4 = model.addGroup(Part_1_doc, Group_4_objects)
+Scale_1 = model.addScale(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1_1")] , model.selection("VERTEX", "PartSet/Origin"), 2)
+model.do()
+# move groups to the end
+Part_1_doc.moveFeature(Group_1.feature(), Scale_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+Part_1_doc.moveFeature(Group_3.feature(), Group_2.feature())
+Part_1_doc.moveFeature(Group_4.feature(), Group_3.feature())
+model.end()
+
+from ModelAPI import *
+
+aFactory = ModelAPI_Session.get().validators()
+
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 1)
+assert(aFactory.validate(Group_1.feature()))
+
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 5)
+assert(aFactory.validate(Group_2.feature()))
+
+selectionList = Group_3.feature().selectionList("group_list")
+assert(selectionList.size() == 9)
+assert(aFactory.validate(Group_3.feature()))
+
+selectionList = Group_4.feature().selectionList("group_list")
+assert(selectionList.size() == 6)
+assert(aFactory.validate(Group_4.feature()))
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupMove12.py b/src/CollectionPlugin/Test/TestGroupMove12.py
new file mode 100644 (file)
index 0000000..e7c2f54
--- /dev/null
@@ -0,0 +1,81 @@
+## 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 of deep nested results history. Translation operation.
+# Check the groups of initial boxes moved to the end contain the corresponding
+# results, but divided.
+
+from salome.shaper import model
+from ModelAPI import *
+
+aFactory = ModelAPI_Session.get().validators()
+
+def moveGroupsAndVerify(thePart, theLastFeature, theRefNumInGroups):
+    # move groups to the end
+    model.begin()
+    LastFeature = theLastFeature
+    for i in range(thePart.size("Groups")):
+        GroupFeature = thePart.feature(objectToResult(thePart.object("Groups", 0))) # move always the very first group
+        Part_1_doc.moveFeature(GroupFeature, LastFeature)
+        LastFeature = GroupFeature
+    model.end()
+
+    a = 0
+    for i in range(thePart.size("Groups")):
+        GroupFeature = thePart.feature(objectToResult(thePart.object("Groups", i)))
+        assert(aFactory.validate(GroupFeature))
+        assert(GroupFeature.selectionList("group_list").size() == theRefNumInGroups[a])
+        a = a + 1
+
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Partition_1_1_3"), model.selection("SOLID", "Partition_1_1_1")])
+Group_2_objects = [model.selection("FACE", "Partition_1_1_4/Modified_Face&Box_1_1/Front"), model.selection("FACE", "Partition_1_1_4/Modified_Face&Box_1_1/Top"), model.selection("FACE", "Partition_1_1_2/Modified_Face&Box_1_1/Top"), model.selection("FACE", "Partition_1_1_2/Modified_Face&Box_1_1/Right")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Group_3_objects = [model.selection("EDGE", "[Partition_1_1_3/Modified_Face&Box_1_1/Top][Partition_1_1_3/Modified_Face&Box_1_1/Front]"), model.selection("EDGE", "[Partition_1_1_3/Modified_Face&Box_1_1/Top][Partition_1_1_3/Modified_Face&Box_1_1/Left]"), model.selection("EDGE", "Partition_1_1_1/Generated_Edge&Plane_2/Plane_2&Box_1_1/Top"), model.selection("EDGE", "[Partition_1_1_1/Modified_Face&Box_1_1/Top][Partition_1_1_1/Modified_Face&Box_1_1/Left]"), model.selection("EDGE", "[Partition_1_1_1/Modified_Face&Box_1_1/Back][Partition_1_1_1/Modified_Face&Box_1_1/Top]"), model.selection("EDGE", "Partition_1_1_2/Generated_Edge&Plane_1/Plane_1&Box_1_1/Top"), model.selection("EDGE", "Partition_1_1_3/Generated_Edge&Plane_1/Plane_1&Box_1_1/Top"), model.selection("EDGE", "[Partition_1_1_4/Modified_Face&Box_1_1/Top][Partition_1_1_4/Modified_Face&Box_1_1/Front]"), model.selection("EDGE", "[Partition_1_1_4/Modified_Face&Box_1_1/Top][Partition_1_1_4/Modified_Face&Box_1_1/Right]"), model.selection("EDGE", "Partition_1_1_2/Generated_Edge&Plane_2/Plane_2&Box_1_1/Top"), model.selection("EDGE", "[Partition_1_1_2/Modified_Face&Box_1_1/Back][Partition_1_1_2/Modified_Face&Box_1_1/Top]"), model.selection("EDGE", "[Partition_1_1_2/Modified_Face&Box_1_1/Top][Partition_1_1_2/Modified_Face&Box_1_1/Right]")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+Group_4_objects = [model.selection("VERTEX", "[Partition_1_1_3/Modified_Face&Box_1_1/Front][Partition_1_1_3/Modified_Face&Box_1_1/Left][Partition_1_1_3/Modified_Face&Box_1_1/Bottom]"), model.selection("VERTEX", "Partition_1_1_4/Generated_Vertex&Plane_1/Plane_1&weak_name_1"), model.selection("VERTEX", "[Partition_1_1_4/Modified_Face&Box_1_1/Front][Partition_1_1_4/Modified_Face&Box_1_1/Bottom][Partition_1_1_4/Modified_Face&Box_1_1/Right]"), model.selection("VERTEX", "Partition_1_1_1/Generated_Vertex&Plane_2/Plane_2&weak_name_1"), model.selection("VERTEX", "[Partition_1_1_2/Modified_Face&Box_1_1/Bottom][Partition_1_1_2/Modified_Face&Plane_1/Plane_1][Partition_1_1_2/Modified_Face&Plane_2/Plane_2]"), model.selection("VERTEX", "Partition_1_1_2/Generated_Vertex&Plane_2/Plane_2&weak_name_1"), model.selection("VERTEX", "[Partition_1_1_1/Modified_Face&Box_1_1/Back][Partition_1_1_1/Modified_Face&Box_1_1/Bottom][Partition_1_1_1/Modified_Face&Box_1_1/Left]"), model.selection("VERTEX", "Partition_1_1_2/Generated_Vertex&Plane_1/Plane_1&weak_name_1"), model.selection("VERTEX", "[Partition_1_1_2/Modified_Face&Box_1_1/Back][Partition_1_1_2/Modified_Face&Box_1_1/Right][Partition_1_1_2/Modified_Face&Box_1_1/Bottom]")]
+Group_4 = model.addGroup(Part_1_doc, Group_4_objects)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Partition_1_1")], model.selection("EDGE", "PartSet/OX"), 20)
+model.do()
+model.end()
+
+num_in_groups = [2, 4, 12, 9]
+moveGroupsAndVerify(Part_1_doc, Translation_1.feature(), num_in_groups)
+
+model.begin()
+Translation_2 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Translation_1_1")], 10, 10, 0)
+model.end()
+moveGroupsAndVerify(Part_1_doc, Translation_2.feature(), num_in_groups)
+
+model.begin()
+Translation_3 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Translation_2_1")], model.selection("VERTEX", "[Translation_2_1_1/MF:Translated_Face&Box_1_1/Back][Translation_2_1_1/MF:Translated_Face&Box_1_1/Bottom][Translation_2_1_1/MF:Translated_Face&Box_1_1/Left]"), model.selection("VERTEX", "PartSet/Origin"))
+model.end()
+moveGroupsAndVerify(Part_1_doc, Translation_3.feature(), num_in_groups)
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupMove13.py b/src/CollectionPlugin/Test/TestGroupMove13.py
new file mode 100644 (file)
index 0000000..9bcb491
--- /dev/null
@@ -0,0 +1,75 @@
+## 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 of deep nested results history. Rotation operation.
+# Check the groups of initial boxes moved to the end contain the corresponding
+# results, but divided.
+
+from salome.shaper import model
+from ModelAPI import *
+
+aFactory = ModelAPI_Session.get().validators()
+
+def moveGroupsAndVerify(thePart, theLastFeature, theRefNumInGroups):
+    # move groups to the end
+    model.begin()
+    LastFeature = theLastFeature
+    for i in range(thePart.size("Groups")):
+        GroupFeature = thePart.feature(objectToResult(thePart.object("Groups", 0))) # move always the very first group
+        Part_1_doc.moveFeature(GroupFeature, LastFeature)
+        LastFeature = GroupFeature
+    model.end()
+
+    a = 0
+    for i in range(thePart.size("Groups")):
+        GroupFeature = thePart.feature(objectToResult(thePart.object("Groups", i)))
+        assert(aFactory.validate(GroupFeature))
+        assert(GroupFeature.selectionList("group_list").size() == theRefNumInGroups[a])
+        a = a + 1
+
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Partition_1_1_3"), model.selection("SOLID", "Partition_1_1_1")])
+Group_2_objects = [model.selection("FACE", "Partition_1_1_4/Modified_Face&Box_1_1/Front"), model.selection("FACE", "Partition_1_1_4/Modified_Face&Box_1_1/Top"), model.selection("FACE", "Partition_1_1_2/Modified_Face&Box_1_1/Top"), model.selection("FACE", "Partition_1_1_2/Modified_Face&Box_1_1/Right")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Group_3_objects = [model.selection("EDGE", "[Partition_1_1_3/Modified_Face&Box_1_1/Top][Partition_1_1_3/Modified_Face&Box_1_1/Front]"), model.selection("EDGE", "[Partition_1_1_3/Modified_Face&Box_1_1/Top][Partition_1_1_3/Modified_Face&Box_1_1/Left]"), model.selection("EDGE", "Partition_1_1_1/Generated_Edge&Plane_2/Plane_2&Box_1_1/Top"), model.selection("EDGE", "[Partition_1_1_1/Modified_Face&Box_1_1/Top][Partition_1_1_1/Modified_Face&Box_1_1/Left]"), model.selection("EDGE", "[Partition_1_1_1/Modified_Face&Box_1_1/Back][Partition_1_1_1/Modified_Face&Box_1_1/Top]"), model.selection("EDGE", "Partition_1_1_2/Generated_Edge&Plane_1/Plane_1&Box_1_1/Top"), model.selection("EDGE", "Partition_1_1_3/Generated_Edge&Plane_1/Plane_1&Box_1_1/Top"), model.selection("EDGE", "[Partition_1_1_4/Modified_Face&Box_1_1/Top][Partition_1_1_4/Modified_Face&Box_1_1/Front]"), model.selection("EDGE", "[Partition_1_1_4/Modified_Face&Box_1_1/Top][Partition_1_1_4/Modified_Face&Box_1_1/Right]"), model.selection("EDGE", "Partition_1_1_2/Generated_Edge&Plane_2/Plane_2&Box_1_1/Top"), model.selection("EDGE", "[Partition_1_1_2/Modified_Face&Box_1_1/Back][Partition_1_1_2/Modified_Face&Box_1_1/Top]"), model.selection("EDGE", "[Partition_1_1_2/Modified_Face&Box_1_1/Top][Partition_1_1_2/Modified_Face&Box_1_1/Right]")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+Group_4_objects = [model.selection("VERTEX", "[Partition_1_1_3/Modified_Face&Box_1_1/Front][Partition_1_1_3/Modified_Face&Box_1_1/Left][Partition_1_1_3/Modified_Face&Box_1_1/Bottom]"), model.selection("VERTEX", "Partition_1_1_4/Generated_Vertex&Plane_1/Plane_1&weak_name_1"), model.selection("VERTEX", "[Partition_1_1_4/Modified_Face&Box_1_1/Front][Partition_1_1_4/Modified_Face&Box_1_1/Bottom][Partition_1_1_4/Modified_Face&Box_1_1/Right]"), model.selection("VERTEX", "Partition_1_1_1/Generated_Vertex&Plane_2/Plane_2&weak_name_1"), model.selection("VERTEX", "[Partition_1_1_2/Modified_Face&Box_1_1/Bottom][Partition_1_1_2/Modified_Face&Plane_1/Plane_1][Partition_1_1_2/Modified_Face&Plane_2/Plane_2]"), model.selection("VERTEX", "Partition_1_1_2/Generated_Vertex&Plane_2/Plane_2&weak_name_1"), model.selection("VERTEX", "[Partition_1_1_1/Modified_Face&Box_1_1/Back][Partition_1_1_1/Modified_Face&Box_1_1/Bottom][Partition_1_1_1/Modified_Face&Box_1_1/Left]"), model.selection("VERTEX", "Partition_1_1_2/Generated_Vertex&Plane_1/Plane_1&weak_name_1"), model.selection("VERTEX", "[Partition_1_1_2/Modified_Face&Box_1_1/Back][Partition_1_1_2/Modified_Face&Box_1_1/Right][Partition_1_1_2/Modified_Face&Box_1_1/Bottom]")]
+Group_4 = model.addGroup(Part_1_doc, Group_4_objects)
+Rotation_1 = model.addRotation(Part_1_doc, [model.selection("COMPSOLID", "Partition_1_1")], model.selection("EDGE", "PartSet/OX"), 45)
+model.end()
+
+num_in_groups = [2, 4, 12, 9]
+moveGroupsAndVerify(Part_1_doc, Rotation_1.feature(), num_in_groups)
+
+model.begin()
+Rotation_2 = model.addRotation(Part_1_doc, [model.selection("COMPSOLID", "Rotation_1_1")], model.selection("VERTEX", "[Rotation_1_1_3/MF:Rotated_Face&Box_1_1/Top][Rotation_1_1_3/MF:Rotated_Face&Box_1_1/Front][Rotation_1_1_3/MF:Rotated_Face&Box_1_1/Left]"), model.selection("VERTEX", "[Rotation_1_1_4/MF:Rotated_Face&Box_1_1/Front][Rotation_1_1_4/MF:Rotated_Face&Box_1_1/Bottom][Rotation_1_1_4/MF:Rotated_Face&Box_1_1/Right]"), model.selection("VERTEX", "[Rotation_1_1_2/MF:Rotated_Face&Box_1_1/Back][Rotation_1_1_2/MF:Rotated_Face&Box_1_1/Right][Rotation_1_1_2/MF:Rotated_Face&Box_1_1/Bottom]"))
+model.end()
+moveGroupsAndVerify(Part_1_doc, Rotation_2.feature(), num_in_groups)
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupMove14.py b/src/CollectionPlugin/Test/TestGroupMove14.py
new file mode 100644 (file)
index 0000000..8bc4d00
--- /dev/null
@@ -0,0 +1,75 @@
+## 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 of deep nested results history. Scale operation.
+# Check the groups of initial boxes moved to the end contain the corresponding
+# results, but divided.
+
+from salome.shaper import model
+from ModelAPI import *
+
+aFactory = ModelAPI_Session.get().validators()
+
+def moveGroupsAndVerify(thePart, theLastFeature, theRefNumInGroups):
+    # move groups to the end
+    model.begin()
+    LastFeature = theLastFeature
+    for i in range(thePart.size("Groups")):
+        GroupFeature = thePart.feature(objectToResult(thePart.object("Groups", 0))) # move always the very first group
+        Part_1_doc.moveFeature(GroupFeature, LastFeature)
+        LastFeature = GroupFeature
+    model.end()
+
+    a = 0
+    for i in range(thePart.size("Groups")):
+        GroupFeature = thePart.feature(objectToResult(thePart.object("Groups", i)))
+        assert(aFactory.validate(GroupFeature))
+        assert(GroupFeature.selectionList("group_list").size() == theRefNumInGroups[a])
+        a = a + 1
+
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Partition_1_1_3"), model.selection("SOLID", "Partition_1_1_1")])
+Group_2_objects = [model.selection("FACE", "Partition_1_1_4/Modified_Face&Box_1_1/Front"), model.selection("FACE", "Partition_1_1_4/Modified_Face&Box_1_1/Top"), model.selection("FACE", "Partition_1_1_2/Modified_Face&Box_1_1/Top"), model.selection("FACE", "Partition_1_1_2/Modified_Face&Box_1_1/Right")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Group_3_objects = [model.selection("EDGE", "[Partition_1_1_3/Modified_Face&Box_1_1/Top][Partition_1_1_3/Modified_Face&Box_1_1/Front]"), model.selection("EDGE", "[Partition_1_1_3/Modified_Face&Box_1_1/Top][Partition_1_1_3/Modified_Face&Box_1_1/Left]"), model.selection("EDGE", "Partition_1_1_1/Generated_Edge&Plane_2/Plane_2&Box_1_1/Top"), model.selection("EDGE", "[Partition_1_1_1/Modified_Face&Box_1_1/Top][Partition_1_1_1/Modified_Face&Box_1_1/Left]"), model.selection("EDGE", "[Partition_1_1_1/Modified_Face&Box_1_1/Back][Partition_1_1_1/Modified_Face&Box_1_1/Top]"), model.selection("EDGE", "Partition_1_1_2/Generated_Edge&Plane_1/Plane_1&Box_1_1/Top"), model.selection("EDGE", "Partition_1_1_3/Generated_Edge&Plane_1/Plane_1&Box_1_1/Top"), model.selection("EDGE", "[Partition_1_1_4/Modified_Face&Box_1_1/Top][Partition_1_1_4/Modified_Face&Box_1_1/Front]"), model.selection("EDGE", "[Partition_1_1_4/Modified_Face&Box_1_1/Top][Partition_1_1_4/Modified_Face&Box_1_1/Right]"), model.selection("EDGE", "Partition_1_1_2/Generated_Edge&Plane_2/Plane_2&Box_1_1/Top"), model.selection("EDGE", "[Partition_1_1_2/Modified_Face&Box_1_1/Back][Partition_1_1_2/Modified_Face&Box_1_1/Top]"), model.selection("EDGE", "[Partition_1_1_2/Modified_Face&Box_1_1/Top][Partition_1_1_2/Modified_Face&Box_1_1/Right]")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+Group_4_objects = [model.selection("VERTEX", "[Partition_1_1_3/Modified_Face&Box_1_1/Front][Partition_1_1_3/Modified_Face&Box_1_1/Left][Partition_1_1_3/Modified_Face&Box_1_1/Bottom]"), model.selection("VERTEX", "Partition_1_1_4/Generated_Vertex&Plane_1/Plane_1&weak_name_1"), model.selection("VERTEX", "[Partition_1_1_4/Modified_Face&Box_1_1/Front][Partition_1_1_4/Modified_Face&Box_1_1/Bottom][Partition_1_1_4/Modified_Face&Box_1_1/Right]"), model.selection("VERTEX", "Partition_1_1_1/Generated_Vertex&Plane_2/Plane_2&weak_name_1"), model.selection("VERTEX", "[Partition_1_1_2/Modified_Face&Box_1_1/Bottom][Partition_1_1_2/Modified_Face&Plane_1/Plane_1][Partition_1_1_2/Modified_Face&Plane_2/Plane_2]"), model.selection("VERTEX", "Partition_1_1_2/Generated_Vertex&Plane_2/Plane_2&weak_name_1"), model.selection("VERTEX", "[Partition_1_1_1/Modified_Face&Box_1_1/Back][Partition_1_1_1/Modified_Face&Box_1_1/Bottom][Partition_1_1_1/Modified_Face&Box_1_1/Left]"), model.selection("VERTEX", "Partition_1_1_2/Generated_Vertex&Plane_1/Plane_1&weak_name_1"), model.selection("VERTEX", "[Partition_1_1_2/Modified_Face&Box_1_1/Back][Partition_1_1_2/Modified_Face&Box_1_1/Right][Partition_1_1_2/Modified_Face&Box_1_1/Bottom]")]
+Group_4 = model.addGroup(Part_1_doc, Group_4_objects)
+Scale_1 = model.addScale(Part_1_doc, [model.selection("COMPSOLID", "Partition_1_1")] , model.selection("VERTEX", "PartSet/Origin"), 2)
+model.end()
+
+num_in_groups = [2, 4, 12, 9]
+moveGroupsAndVerify(Part_1_doc, Scale_1.feature(), num_in_groups)
+
+model.begin()
+Scale_2 = model.addScale(Part_1_doc, [model.selection("COMPSOLID", "Scale_1_1")] , model.selection("VERTEX", "PartSet/Origin"), 1 , 2, 3)
+model.end()
+moveGroupsAndVerify(Part_1_doc, Scale_2.feature(), num_in_groups)
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupMove15.py b/src/CollectionPlugin/Test/TestGroupMove15.py
new file mode 100644 (file)
index 0000000..eab7390
--- /dev/null
@@ -0,0 +1,71 @@
+## 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 of deep nested results history. Placement operation.
+# Check the groups of initial boxes moved to the end contain the corresponding
+# results, but divided.
+
+from salome.shaper import model
+from ModelAPI import *
+
+aFactory = ModelAPI_Session.get().validators()
+
+def moveGroupsAndVerify(thePart, theLastFeature, theRefNumInGroups):
+    # move groups to the end
+    model.begin()
+    LastFeature = theLastFeature
+    for i in range(thePart.size("Groups")):
+        GroupFeature = thePart.feature(objectToResult(thePart.object("Groups", 0))) # move always the very first group
+        Part_1_doc.moveFeature(GroupFeature, LastFeature)
+        LastFeature = GroupFeature
+    model.end()
+
+    a = 0
+    for i in range(thePart.size("Groups")):
+        GroupFeature = thePart.feature(objectToResult(thePart.object("Groups", i)))
+        assert(aFactory.validate(GroupFeature))
+        assert(GroupFeature.selectionList("group_list").size() == theRefNumInGroups[a])
+        a = a + 1
+
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Back"), model.selection("FACE", "Box_1_1/Front"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Partition_1_1_3"), model.selection("SOLID", "Partition_1_1_1")])
+Group_2_objects = [model.selection("FACE", "Partition_1_1_4/Modified_Face&Box_1_1/Front"), model.selection("FACE", "Partition_1_1_4/Modified_Face&Box_1_1/Top"), model.selection("FACE", "Partition_1_1_2/Modified_Face&Box_1_1/Top"), model.selection("FACE", "Partition_1_1_2/Modified_Face&Box_1_1/Right")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Group_3_objects = [model.selection("EDGE", "[Partition_1_1_3/Modified_Face&Box_1_1/Top][Partition_1_1_3/Modified_Face&Box_1_1/Front]"), model.selection("EDGE", "[Partition_1_1_3/Modified_Face&Box_1_1/Top][Partition_1_1_3/Modified_Face&Box_1_1/Left]"), model.selection("EDGE", "Partition_1_1_1/Generated_Edge&Plane_2/Plane_2&Box_1_1/Top"), model.selection("EDGE", "[Partition_1_1_1/Modified_Face&Box_1_1/Top][Partition_1_1_1/Modified_Face&Box_1_1/Left]"), model.selection("EDGE", "[Partition_1_1_1/Modified_Face&Box_1_1/Back][Partition_1_1_1/Modified_Face&Box_1_1/Top]"), model.selection("EDGE", "Partition_1_1_2/Generated_Edge&Plane_1/Plane_1&Box_1_1/Top"), model.selection("EDGE", "Partition_1_1_3/Generated_Edge&Plane_1/Plane_1&Box_1_1/Top"), model.selection("EDGE", "[Partition_1_1_4/Modified_Face&Box_1_1/Top][Partition_1_1_4/Modified_Face&Box_1_1/Front]"), model.selection("EDGE", "[Partition_1_1_4/Modified_Face&Box_1_1/Top][Partition_1_1_4/Modified_Face&Box_1_1/Right]"), model.selection("EDGE", "Partition_1_1_2/Generated_Edge&Plane_2/Plane_2&Box_1_1/Top"), model.selection("EDGE", "[Partition_1_1_2/Modified_Face&Box_1_1/Back][Partition_1_1_2/Modified_Face&Box_1_1/Top]"), model.selection("EDGE", "[Partition_1_1_2/Modified_Face&Box_1_1/Top][Partition_1_1_2/Modified_Face&Box_1_1/Right]")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+Group_4_objects = [model.selection("VERTEX", "[Partition_1_1_3/Modified_Face&Box_1_1/Front][Partition_1_1_3/Modified_Face&Box_1_1/Left][Partition_1_1_3/Modified_Face&Box_1_1/Bottom]"), model.selection("VERTEX", "Partition_1_1_4/Generated_Vertex&Plane_1/Plane_1&weak_name_1"), model.selection("VERTEX", "[Partition_1_1_4/Modified_Face&Box_1_1/Front][Partition_1_1_4/Modified_Face&Box_1_1/Bottom][Partition_1_1_4/Modified_Face&Box_1_1/Right]"), model.selection("VERTEX", "Partition_1_1_1/Generated_Vertex&Plane_2/Plane_2&weak_name_1"), model.selection("VERTEX", "[Partition_1_1_2/Modified_Face&Box_1_1/Bottom][Partition_1_1_2/Modified_Face&Plane_1/Plane_1][Partition_1_1_2/Modified_Face&Plane_2/Plane_2]"), model.selection("VERTEX", "Partition_1_1_2/Generated_Vertex&Plane_2/Plane_2&weak_name_1"), model.selection("VERTEX", "[Partition_1_1_1/Modified_Face&Box_1_1/Back][Partition_1_1_1/Modified_Face&Box_1_1/Bottom][Partition_1_1_1/Modified_Face&Box_1_1/Left]"), model.selection("VERTEX", "Partition_1_1_2/Generated_Vertex&Plane_1/Plane_1&weak_name_1"), model.selection("VERTEX", "[Partition_1_1_2/Modified_Face&Box_1_1/Back][Partition_1_1_2/Modified_Face&Box_1_1/Right][Partition_1_1_2/Modified_Face&Box_1_1/Bottom]")]
+Group_4 = model.addGroup(Part_1_doc, Group_4_objects)
+Placement_1 = model.addPlacement(Part_1_doc, [model.selection("COMPSOLID", "Partition_1_1")], model.selection("FACE", "Partition_1_1_4/Modified_Face&Box_1_1/Bottom"), model.selection("FACE", "Partition_1_1_1/Modified_Face&Box_1_1/Top"), False, True)
+model.do()
+model.end()
+
+num_in_groups = [2, 4, 12, 9]
+moveGroupsAndVerify(Part_1_doc, Placement_1.feature(), num_in_groups)
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupMove16.py b/src/CollectionPlugin/Test/TestGroupMove16.py
new file mode 100644 (file)
index 0000000..ced352d
--- /dev/null
@@ -0,0 +1,70 @@
+## 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 of deep nested results history. Compsolid operation.
+# Check the initial groups moved to the end contain the corresponding results.
+
+from salome.shaper import model
+from ModelAPI import *
+
+aFactory = ModelAPI_Session.get().validators()
+
+def moveGroupsAndVerify(thePart, theLastFeature, theRefNumInGroups):
+    # move groups to the end
+    model.begin()
+    LastFeature = theLastFeature
+    for i in range(thePart.size("Groups")):
+        GroupFeature = thePart.feature(objectToResult(thePart.object("Groups", 0))) # move always the very first group
+        Part_1_doc.moveFeature(GroupFeature, LastFeature)
+        LastFeature = GroupFeature
+    model.end()
+
+    a = 0
+    for i in range(thePart.size("Groups")):
+        GroupFeature = thePart.feature(objectToResult(thePart.object("Groups", i)))
+        assert(aFactory.validate(GroupFeature))
+        assert(GroupFeature.selectionList("group_list").size() == theRefNumInGroups[a])
+        a = a + 1
+
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Box_1_1")])
+Group_2_objects = [model.selection("FACE", "Box_1_1/Back"), model.selection("FACE", "Box_1_1/Top"), model.selection("FACE", "Box_1_1/Right"), model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Bottom"), model.selection("FACE", "Box_1_1/Front")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Group_3_objects = [model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Right]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Right]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+Group_4_objects = [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/Top]"), model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Left][Box_1_1/Bottom]"), model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Right][Box_1_1/Top]"), model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Left][Box_1_1/Bottom]"), model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Right][Box_1_1/Bottom]"), model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Right][Box_1_1/Top]"), model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Right][Box_1_1/Bottom]")]
+Group_4 = model.addGroup(Part_1_doc, Group_4_objects)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Bottom"), model.selection("FACE", "Box_1_1/Top"))
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchCircle_1 = Sketch_1.addCircle(3.528942405489753, -5.938455554641368, 11.4411217503133)
+model.do()
+CompSolid_1 = model.addCompSolid(Part_1_doc, [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2r")])
+model.do()
+model.end()
+
+num_in_groups = [2, 10, 16, 8]
+moveGroupsAndVerify(Part_1_doc, CompSolid_1.feature(), num_in_groups)
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupMove17.py b/src/CollectionPlugin/Test/TestGroupMove17.py
new file mode 100644 (file)
index 0000000..673f10f
--- /dev/null
@@ -0,0 +1,71 @@
+## 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 of deep nested results history. Solid operation.
+# Check the initial groups moved to the end contain the corresponding results.
+
+from salome.shaper import model
+from ModelAPI import *
+
+aFactory = ModelAPI_Session.get().validators()
+
+def moveGroupsAndVerify(thePart, theLastFeature, theRefNumInGroups):
+    # move groups to the end
+    model.begin()
+    LastFeature = theLastFeature
+    for i in range(thePart.size("Groups")):
+        GroupFeature = thePart.feature(objectToResult(thePart.object("Groups", 0))) # move always the very first group
+        Part_1_doc.moveFeature(GroupFeature, LastFeature)
+        LastFeature = GroupFeature
+    model.end()
+
+    a = 0
+    for i in range(thePart.size("Groups")):
+        GroupFeature = thePart.feature(objectToResult(thePart.object("Groups", i)))
+        assert(aFactory.validate(GroupFeature))
+        assert(GroupFeature.selectionList("group_list").size() == theRefNumInGroups[a])
+        a = a + 1
+
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Box_1_1")])
+Group_2_objects = [model.selection("FACE", "Box_1_1/Back"), model.selection("FACE", "Box_1_1/Top"), model.selection("FACE", "Box_1_1/Right"), model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Bottom"), model.selection("FACE", "Box_1_1/Front")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Group_3_objects = [model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Right]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Right]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+Group_4_objects = [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/Top]"), model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Left][Box_1_1/Bottom]"), model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Right][Box_1_1/Top]"), model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Left][Box_1_1/Bottom]"), model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Right][Box_1_1/Bottom]"), model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Right][Box_1_1/Top]"), model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Right][Box_1_1/Bottom]")]
+Group_4 = model.addGroup(Part_1_doc, Group_4_objects)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Bottom"), model.selection("FACE", "Box_1_1/Top"))
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchCircle_1 = Sketch_1.addCircle(3.528942405489753, -5.938455554641368, 11.4411217503133)
+model.do()
+Solid_1_objects = [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2r"), model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Bottom"), model.selection("FACE", "Box_1_1/Back"), model.selection("FACE", "Box_1_1/Right")]
+Solid_1 = model.addSolid(Part_1_doc, Solid_1_objects)
+model.do()
+model.end()
+
+num_in_groups = [1, 5, 8, 4]
+moveGroupsAndVerify(Part_1_doc, Solid_1.feature(), num_in_groups)
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupMove18.py b/src/CollectionPlugin/Test/TestGroupMove18.py
new file mode 100644 (file)
index 0000000..889fa54
--- /dev/null
@@ -0,0 +1,70 @@
+## 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 of deep nested results history. Shell operation.
+# Check the initial groups moved to the end contain the corresponding results.
+
+from salome.shaper import model
+from ModelAPI import *
+
+aFactory = ModelAPI_Session.get().validators()
+
+def moveGroupsAndVerify(thePart, theLastFeature, theRefNumInGroups):
+    # move groups to the end
+    model.begin()
+    LastFeature = theLastFeature
+    for i in range(thePart.size("Groups")):
+        GroupFeature = thePart.feature(objectToResult(thePart.object("Groups", 0))) # move always the very first group
+        Part_1_doc.moveFeature(GroupFeature, LastFeature)
+        LastFeature = GroupFeature
+    model.end()
+
+    a = 0
+    for i in range(thePart.size("Groups")):
+        GroupFeature = thePart.feature(objectToResult(thePart.object("Groups", i)))
+        assert(aFactory.validate(GroupFeature))
+        assert(GroupFeature.selectionList("group_list").size() == theRefNumInGroups[a])
+        a = a + 1
+
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1_objects = [model.selection("FACE", "Box_1_1/Back"), model.selection("FACE", "Box_1_1/Top"), model.selection("FACE", "Box_1_1/Right"), model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Bottom"), model.selection("FACE", "Box_1_1/Front")]
+Group_1 = model.addGroup(Part_1_doc, Group_1_objects)
+Group_2_objects = [model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Right]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Right]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Group_3_objects = [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/Top]"), model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Right][Box_1_1/Top]"), model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Left][Box_1_1/Bottom]"), model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Right][Box_1_1/Top]"), model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Left][Box_1_1/Bottom]"), model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Right][Box_1_1/Bottom]"), model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Right][Box_1_1/Bottom]")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects)
+Shell_1_objects = [model.selection("FACE", "Partition_1_1_1/Modified_Face&Box_1_1/Back"), model.selection("FACE", "Partition_1_1_1/Modified_Face&Box_1_1/Left"), model.selection("FACE", "Partition_1_1_1/Modified_Face&Box_1_1/Top"), model.selection("FACE", "Partition_1_1_2/Modified_Face&Box_1_1/Back"), model.selection("FACE", "Partition_1_1_4/Modified_Face&Box_1_1/Front"), model.selection("FACE", "Partition_1_1_4/Modified_Face&Box_1_1/Right")]
+Shell_1 = model.addShell(Part_1_doc, Shell_1_objects)
+model.do()
+model.end()
+
+num_in_groups = [6, 13, 6]
+moveGroupsAndVerify(Part_1_doc, Shell_1.feature(), num_in_groups)
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupMove19.py b/src/CollectionPlugin/Test/TestGroupMove19.py
new file mode 100644 (file)
index 0000000..dfb176f
--- /dev/null
@@ -0,0 +1,79 @@
+## 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 of deep nested results history. Shell operation.
+# Check the initial groups moved to the end contain the corresponding results.
+
+from salome.shaper import model
+from ModelAPI import *
+
+aFactory = ModelAPI_Session.get().validators()
+
+def moveGroupsAndVerify(thePart, theLastFeature, theRefNumInGroups):
+    # move groups to the end
+    model.begin()
+    LastFeature = theLastFeature
+    for i in range(thePart.size("Groups")):
+        GroupFeature = thePart.feature(objectToResult(thePart.object("Groups", 0))) # move always the very first group
+        Part_1_doc.moveFeature(GroupFeature, LastFeature)
+        LastFeature = GroupFeature
+    model.end()
+
+    a = 0
+    for i in range(thePart.size("Groups")):
+        GroupFeature = thePart.feature(objectToResult(thePart.object("Groups", i)))
+        assert(aFactory.validate(GroupFeature))
+        assert(GroupFeature.selectionList("group_list").size() == theRefNumInGroups[a])
+        a = a + 1
+
+
+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(37.25033050129738, -29.31988879634488, -32.3129114537045, -29.31988879634488)
+SketchLine_2 = Sketch_1.addLine(-32.3129114537045, -29.31988879634488, -32.3129114537045, 42.23870159689701)
+SketchLine_3 = Sketch_1.addLine(-32.3129114537045, 42.23870159689701, 37.25033050129738, 42.23870159689701)
+SketchLine_4 = Sketch_1.addLine(37.25033050129738, 42.23870159689701, 37.25033050129738, -29.31988879634488)
+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())
+model.do()
+Edge_1_objects = [model.selection("EDGE", "Sketch_1/SketchLine_1"), model.selection("EDGE", "Sketch_1/SketchLine_4"), model.selection("EDGE", "Sketch_1/SketchLine_2"), model.selection("EDGE", "Sketch_1/SketchLine_3")]
+Edge_1 = model.addEdge(Part_1_doc, Edge_1_objects)
+Group_1_objects = [model.selection("EDGE", "Edge_1_1"), model.selection("EDGE", "Edge_1_3"), model.selection("EDGE", "Edge_1_4"), model.selection("EDGE", "Edge_1_2")]
+Group_1 = model.addGroup(Part_1_doc, Group_1_objects)
+Group_2_objects = [model.selection("VERTEX", "Edge_1_1/Modified_Vertex&Sketch_1/SketchLine_1_StartVertex"), model.selection("VERTEX", "Edge_1_2/Modified_Vertex&Sketch_1/SketchLine_4_EndVertex"), model.selection("VERTEX", "Edge_1_1/Modified_Vertex&Sketch_1/SketchLine_1_EndVertex"), model.selection("VERTEX", "Edge_1_3/Modified_Vertex&Sketch_1/SketchLine_2_StartVertex"), model.selection("VERTEX", "Edge_1_4/Modified_Vertex&Sketch_1/SketchLine_3_EndVertex"), model.selection("VERTEX", "Edge_1_2/Modified_Vertex&Sketch_1/SketchLine_4_StartVertex"), model.selection("VERTEX", "Edge_1_3/Modified_Vertex&Sketch_1/SketchLine_2_EndVertex"), model.selection("VERTEX", "Edge_1_4/Modified_Vertex&Sketch_1/SketchLine_3_StartVertex")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Face_1_objects = [model.selection("EDGE", "Edge_1_1"), model.selection("EDGE", "Edge_1_2"), model.selection("EDGE", "Edge_1_3"), model.selection("EDGE", "Edge_1_4")]
+Face_1 = model.addFace(Part_1_doc, Face_1_objects)
+model.do()
+model.end()
+
+num_in_groups = [4, 8]
+moveGroupsAndVerify(Part_1_doc, Face_1.feature(), num_in_groups)
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupMove2.py b/src/CollectionPlugin/Test/TestGroupMove2.py
deleted file mode 100644 (file)
index 03091ea..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-# 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
-#
-
-# 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/CollectionPlugin/Test/TestGroupMove3.py b/src/CollectionPlugin/Test/TestGroupMove3.py
deleted file mode 100644 (file)
index 495bd4b..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-# 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
-#
-
-# Test that partition divides cylinder into 4 faces, there is no edges in a group moved to the end
-# Based on the CEA report mail 04.12.2018, page 2
-
-from SketchAPI import *
-
-from ModelAPI import *
-from GeomAPI 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("XOZ"))
-SketchArc_1 = Sketch_1.addArc(-1.103476974288834e-12, 24.99999999999979, 24.49489742783218, 30, 0, 50, False)
-SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
-SketchLine_1 = SketchProjection_1.createdFeature()
-SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.result())
-SketchLine_2 = Sketch_1.addLine(0, 50, -10, 50)
-SketchLine_2.setAuxiliary(True)
-SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_2.startPoint())
-SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_2.result())
-SketchConstraintTangent_1 = Sketch_1.setTangent(SketchArc_1.results()[1], SketchLine_2.result())
-SketchLine_3 = Sketch_1.addLine(24.49489742783218, 30, 24.49489742783218, 5)
-SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_3.startPoint())
-SketchLine_4 = Sketch_1.addLine(24.49489742783218, 5, 34.49489742783218, 5)
-SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
-SketchLine_5 = Sketch_1.addLine(34.49489742783218, 5, 34.49489742783218, 0)
-SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
-SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False)
-SketchLine_6 = SketchProjection_2.createdFeature()
-SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.result())
-SketchLine_7 = Sketch_1.addLine(34.49489742783218, 0, 0, 0)
-SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_7.startPoint())
-SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_7.endPoint())
-SketchLine_8 = Sketch_1.addLine(0, 50, 0, 0)
-SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_8.startPoint())
-SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_8.endPoint())
-SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_4.result())
-SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_3.result())
-SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_5.result())
-SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_4.result(), 10)
-SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_5.result(), 5)
-SketchConstraintLength_3 = Sketch_1.setLength(SketchLine_3.result(), 25)
-SketchConstraintLength_4 = Sketch_1.setLength(SketchLine_8.result(), 50)
-SketchConstraintLength_5 = Sketch_1.setLength(SketchLine_2.result(), 10)
-SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], 25)
-model.do()
-Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchArc_1_2r-SketchLine_8f-SketchLine_7r-SketchLine_5r-SketchLine_4r-SketchLine_3r")], model.selection("EDGE", "PartSet/OZ"), 360, 0)
-Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Revolution_1_1/Generated_Face&Sketch_1/SketchLine_3")])
-Partition_1_objects = [model.selection("SOLID", "Revolution_1_1"), model.selection("FACE", "PartSet/XOZ"), model.selection("FACE", "PartSet/YOZ")]
-Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects)
-model.do()
-
-# move group
-Part_1_doc.moveFeature(Group_1.feature(), Partition_1.feature())
-model.end()
-
-# Check group: result must be four faces
-aFactory = ModelAPI_Session.get().validators()
-selectionList = Group_1.feature().selectionList("group_list")
-assert(selectionList.size() == 4)
-assert(aFactory.validate(Group_1.feature()))
-for i in range(4):
-  assert(Group_1.groupList().value(i).value().shapeType() == GeomAPI_Shape.FACE)
-
-assert(model.checkPythonDump())
index 2c7b1e2bb4c57c73f182bddafbd6ce51668a19ab..70a5a6fcd2e79b629aedc4ce6ead5c6d42e7179e 100644 (file)
@@ -356,10 +356,12 @@ ADD_UNIT_TESTS(TestExtrusion.py
                TestBooleanCut_WireCompound_WireCompound.py
                TestBooleanCut_Compound_Solid.py
                TestBooleanCut_ErrorMsg.py
+               TestBooleanCut_SolidsHistory.py
                TestBooleanSmash_Face_Face.py
                TestBooleanSmash_SubSolid_Solid.py
                TestBooleanSmash_CompSolid_Solid.py
                TestBooleanSmash_ErrorMsg.py
+               TestBooleanSmash_SolidsHistory.py
                TestBooleanFuse_SimpleMode.py
                TestBooleanFuse_RemoveEdges.py
                TestBooleanFuse_ErrorMsg.py
@@ -389,6 +391,7 @@ ADD_UNIT_TESTS(TestExtrusion.py
                TestBooleanCommon_CompSolidCompound_Shell.py
                TestBooleanCommon_CompSolidCompound_CompSolidCompound.py
                TestBooleanCommon_ErrorMsg.py
+               TestBooleanCommon_SolidsHistory.py
                Test2596.py
                Test2592.py
                Test2588.py
@@ -412,6 +415,7 @@ ADD_UNIT_TESTS(TestExtrusion.py
                TestPartitionSubCompsolidWithPlane4.py
                TestPartitionSubCompsolidWithPlane5.py
                TestPartitionArgsUpdate.py
+               TestPartition_SolidsHistory.py
                TestBooleanFuse_Vertex_Vertex.py
                TestBooleanFuse_VertexCompound_VertexCompound.py
                TestBooleanFuse_Edge_Edge.py
@@ -427,13 +431,17 @@ ADD_UNIT_TESTS(TestExtrusion.py
                TestBooleanFuse_CompSolid_Face.py
                TestBooleanFuse_CompSolid_CompSolid.py
                TestBooleanFuse_CompSolidCompound_CompSolidCompound.py
+               TestBooleanFuse_SolidsHistory.py
                TestFillet.py
                TestFillet1.py
                TestFillet_ErrorMsg.py
+               TestFillet_History.py
                TestScale1.py
                TestScale2.py
                Test1816.py
+               Test1876.py
                Test2631.py
+               Test2636.py
                Test2650.py
                Test2681.py
                Test2686.py
@@ -445,6 +453,8 @@ ADD_UNIT_TESTS(TestExtrusion.py
                Test2692.py
                Test2617.py
                Test2729.py
+               Test2738.py
                Test2751.py
+               Test2826.py
                Test2854.py
 )
index 26deb15c0be7c0ae8f0b0df986d60be934da7c89..eb23d0bab2fe563e12263c35936482224cba2bec 100644 (file)
@@ -157,13 +157,14 @@ void FeaturesPlugin_BooleanCommon::execute()
       std::shared_ptr<ModelAPI_ResultBody> aResultBody =
         document()->createBody(data(), aResultIndex);
 
-      GeomShapePtr aBaseShape = anObjects.front();
-      anObjects.pop_front();
+      ListOfShape anEmptyTools;
       FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
-                                               aBaseShape,
                                                anObjects,
+                                               anEmptyTools,
                                                aMakeShapeList,
                                                aShape);
+      GeomShapePtr aBaseShape = anObjects.front();
+      anObjects.pop_front();
       setResult(aResultBody, aResultIndex);
       aResultIndex++;
 
@@ -221,9 +222,10 @@ void FeaturesPlugin_BooleanCommon::execute()
       if (aShapeIt.more() || aResShape->shapeType() == GeomAPI_Shape::VERTEX) {
         std::shared_ptr<ModelAPI_ResultBody> aResultBody =
           document()->createBody(data(), aResultIndex);
-
+        ListOfShape anObjectList;
+        anObjectList.push_back(anObject);
         FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
-                                                 anObject,
+                                                 anObjectList,
                                                  aTools,
                                                  aMakeShapeList,
                                                  aResShape);
@@ -303,8 +305,10 @@ void FeaturesPlugin_BooleanCommon::execute()
         std::shared_ptr<ModelAPI_ResultBody> aResultBody =
           document()->createBody(data(), aResultIndex);
 
+        ListOfShape aCompSolidList;
+        aCompSolidList.push_back(aCompSolid);
         FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
-                                                 aCompSolid,
+                                                 aCompSolidList,
                                                  aTools,
                                                  aMakeShapeList,
                                                  aResultShape);
@@ -387,8 +391,10 @@ void FeaturesPlugin_BooleanCommon::execute()
         std::shared_ptr<ModelAPI_ResultBody> aResultBody =
           document()->createBody(data(), aResultIndex);
 
+        ListOfShape aCompoundList;
+        aCompoundList.push_back(aCompound);
         FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
-                                                 aCompound,
+                                                 aCompoundList,
                                                  aTools,
                                                  aMakeShapeList,
                                                  aResultShape);
index 784ef8f2b711287d51f949e6b1e19420df58a1b7..04b9020ba0858e837393e6d29b78b4487b60a4ad 100644 (file)
@@ -132,8 +132,10 @@ void FeaturesPlugin_BooleanCut::execute()
       std::shared_ptr<ModelAPI_ResultBody> aResultBody =
         document()->createBody(data(), aResultIndex);
 
+      ListOfShape anObjectList;
+      anObjectList.push_back(anObject);
       FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
-                                               anObject,
+                                               anObjectList,
                                                aTools,
                                                aMakeShapeList,
                                                aResShape);
@@ -213,8 +215,10 @@ void FeaturesPlugin_BooleanCut::execute()
       std::shared_ptr<ModelAPI_ResultBody> aResultBody =
         document()->createBody(data(), aResultIndex);
 
+      ListOfShape anObjectList;
+      anObjectList.push_back(aCompSolid);
       FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
-                                               aCompSolid,
+                                               anObjectList,
                                                aTools,
                                                aMakeShapeList,
                                                aResultShape);
@@ -295,8 +299,10 @@ void FeaturesPlugin_BooleanCut::execute()
       std::shared_ptr<ModelAPI_ResultBody> aResultBody =
         document()->createBody(data(), aResultIndex);
 
+      ListOfShape anObjectList;
+      anObjectList.push_back(aCompound);
       FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
-                                               aCompound,
+                                               anObjectList,
                                                aTools,
                                                aMakeShapeList,
                                                aResultShape);
index 1fecf3926810c3549faa81ee3bb7bc149c784a3f..92d513e5c521252197ea3dedfccc1ab0418426a3 100644 (file)
 //
 
 #include "FeaturesPlugin_BooleanFill.h"
+#include "FeaturesPlugin_Tools.h"
 
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_Tools.h>
 
 #include <GeomAlgoAPI_Boolean.h>
+#include <GeomAlgoAPI_CompoundBuilder.h>
 #include <GeomAlgoAPI_MakeShapeCustom.h>
 #include <GeomAlgoAPI_MakeShapeList.h>
 #include <GeomAlgoAPI_Partition.h>
@@ -105,6 +107,9 @@ void FeaturesPlugin_BooleanFill::execute()
     return;
   }
 
+  std::vector<FeaturesPlugin_Tools::ResultBaseAlgo> aResultBaseAlgoList;
+  ListOfShape aResultShapesList;
+
   // For solids cut each object with all tools.
   for(ListOfShape::iterator
       anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end(); anObjectsIt++) {
@@ -160,12 +165,23 @@ void FeaturesPlugin_BooleanFill::execute()
     std::shared_ptr<ModelAPI_ResultBody> aResultBody =
         document()->createBody(data(), aResultIndex);
 
+    // tools should be added to the list to fulfill the correct history of modification
+    aListWithObject.insert(aListWithObject.end(), aTools.begin(), aTools.end());
+
     ListOfShape aUsedTools = aTools;
     aUsedTools.insert(aUsedTools.end(), aPlanes.begin(), aPlanes.end());
 
-    loadNamingDS(aResultBody, anObject, aUsedTools, aResShape, aMakeShapeList);
+    FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, aListWithObject, aUsedTools,
+                                             aMakeShapeList, aResShape);
     setResult(aResultBody, aResultIndex);
     aResultIndex++;
+
+    FeaturesPlugin_Tools::ResultBaseAlgo aRBA;
+    aRBA.resultBody = aResultBody;
+    aRBA.baseShape = anObject;
+    aRBA.makeShape = aMakeShapeList;
+    aResultBaseAlgoList.push_back(aRBA);
+    aResultShapesList.push_back(aResShape);
   }
 
   // Compsolids handling
@@ -245,15 +261,29 @@ void FeaturesPlugin_BooleanFill::execute()
     ListOfShape aUsedTools = aTools;
     aUsedTools.insert(aUsedTools.end(), aPlanes.begin(), aPlanes.end());
 
-    loadNamingDS(aResultBody,
-                  aCompSolid,
-                  aUsedTools,
-                  aResultShape,
-                  aMakeShapeList);
+    ListOfShape aBaseShapes;
+    aBaseShapes.push_back(aCompSolid);
+    // tools should be added to the list to fulfill the correct history of modification
+    aBaseShapes.insert(aBaseShapes.end(), aTools.begin(), aTools.end());
+
+    FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, aBaseShapes, aUsedTools,
+                                             aMakeShapeList, aResultShape);
     setResult(aResultBody, aResultIndex);
     aResultIndex++;
+
+    FeaturesPlugin_Tools::ResultBaseAlgo aRBA;
+    aRBA.resultBody = aResultBody;
+    aRBA.baseShape = aCompSolid;
+    aRBA.makeShape = aMakeShapeList;
+    aResultBaseAlgoList.push_back(aRBA);
+    aResultShapesList.push_back(aResultShape);
   }
 
+  // Store deleted shapes after all results has been proceeded. This is to avoid issue when in one
+  // result shape has been deleted, but in another it was modified or stayed.
+  GeomShapePtr aResultShapesCompound = GeomAlgoAPI_CompoundBuilder::compound(aResultShapesList);
+  FeaturesPlugin_Tools::loadDeletedShapes(aResultBaseAlgoList, aTools, aResultShapesCompound);
+
   // remove the rest results if there were produced in the previous pass
   removeResults(aResultIndex);
 }
index 6c3f272110da56800631912596a97415b1b8ca7b..176e8b6fe9eecbfb5e28d458ed58bc7f1c3aec0a 100644 (file)
@@ -270,20 +270,19 @@ void FeaturesPlugin_BooleanFuse::execute()
 
   int aResultIndex = 0;
 
-  GeomShapePtr aBackShape = anOriginalShapes.back();
-  anOriginalShapes.pop_back();
   ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
 
+  ListOfShape anEmptyTools;
   FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
-                                           aBackShape,
                                            anOriginalShapes,
+                                           anEmptyTools,
                                            aMakeShapeList,
                                            aShape);
   setResult(aResultBody, aResultIndex);
   aResultIndex++;
 
   FeaturesPlugin_Tools::loadDeletedShapes(aResultBody,
-                                          aBackShape,
+                                          GeomShapePtr(),
                                           anOriginalShapes,
                                           aMakeShapeList,
                                           aShape);
index 46d7b202135bac4e0faad5a5d5dad2a0edeca944..9c8bb1e578bffda2db38ab2ccc6990304361f277 100644 (file)
@@ -212,12 +212,10 @@ void FeaturesPlugin_BooleanSmash::execute()
     aMakeShapeList->appendAlgo(aFillerAlgo);
   }
 
-  std::shared_ptr<GeomAPI_Shape> aFrontShape = anOriginalShapes.front();
-  anOriginalShapes.pop_front();
   std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
 
   FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
-                                           aFrontShape,
+                                           anOriginalShapes,
                                            anOriginalShapes,
                                            aMakeShapeList,
                                            aShape);
@@ -226,7 +224,7 @@ void FeaturesPlugin_BooleanSmash::execute()
   aResultIndex++;
 
   FeaturesPlugin_Tools::loadDeletedShapes(aResultBody,
-                                          aFrontShape,
+                                          GeomShapePtr(),
                                           anOriginalShapes,
                                           aMakeShapeList,
                                           aShape);
index 89c07b94e8542c55dc5031fa4a9925416617523b..8dcd2fae4e5383a3ebe1aa74ecf7d24b1c2a7114 100644 (file)
@@ -18,6 +18,7 @@
 //
 
 #include "FeaturesPlugin_Fillet.h"
+#include "FeaturesPlugin_Tools.h"
 
 #include <ModelAPI_Data.h>
 #include <ModelAPI_AttributeDouble.h>
@@ -28,6 +29,7 @@
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_Validator.h>
 
+#include <GeomAlgoAPI_CompoundBuilder.h>
 #include <GeomAlgoAPI_Fillet.h>
 #include <GeomAlgoAPI_MakeShapeList.h>
 #include <GeomAlgoAPI_Tools.h>
@@ -61,7 +63,7 @@ static ListOfShape selectEdges(const ListOfShape& theShapes)
   return anEdges;
 }
 
-// If theShape is a compound of single shape, return it
+// If theShape is a compound of a single sub-shape, return this sub-shape
 static GeomShapePtr unwrapCompound(const GeomShapePtr& theShape)
 {
   GeomShapePtr aShape = theShape;
@@ -101,9 +103,9 @@ void FeaturesPlugin_Fillet::execute()
   if (!aCreationMethod)
     return;
 
-  GeomAPI_DataMapOfShapeMapOfShapes aSolidsAndSubs;
+  std::list<std::pair<GeomShapePtr, ListOfShape> > aSolidsAndSubs;
 
-  // getting objects and sort them accroding to parent solids
+  // getting objects and sort them according to parent solids
   AttributeSelectionListPtr anObjectsSelList = selectionList(OBJECT_LIST_ID());
   for (int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); ++anObjectsIndex) {
     AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex);
@@ -125,12 +127,26 @@ void FeaturesPlugin_Fillet::execute()
     if (!aParent)
       return;
 
+    // searching this parent is already in the list aSolidsAndSubs
+    std::list<std::pair<GeomShapePtr, ListOfShape> >::iterator aSearch = aSolidsAndSubs.begin();
+    ListOfShape* aFound;
+    for(; aSearch != aSolidsAndSubs.end(); aSearch++) {
+      if (aSearch->first->isSame(aParent)) {
+        aFound = &(aSearch->second);
+        break;
+      }
+    }
+    if (aSearch == aSolidsAndSubs.end()) { // not found, so, add a new one
+      aSolidsAndSubs.push_back(std::pair<GeomShapePtr, ListOfShape>(aParent, ListOfShape()));
+      aFound = &(aSolidsAndSubs.back().second);
+    }
+
     ListOfShape anEdgesAndVertices;
     collectSubs(anObject, anEdgesAndVertices, GeomAPI_Shape::EDGE);
     collectSubs(anObject, anEdgesAndVertices, GeomAPI_Shape::VERTEX);
     for (ListOfShape::iterator aEIt = anEdgesAndVertices.begin();
          aEIt != anEdgesAndVertices.end(); ++aEIt)
-      aSolidsAndSubs.add(aParent, *aEIt);
+      aFound->push_back(*aEIt);
   }
 
   bool isFixedRadius = true;
@@ -149,10 +165,13 @@ void FeaturesPlugin_Fillet::execute()
   int aResultIndex = 0;
   std::string anError;
 
-  GeomAPI_DataMapOfShapeMapOfShapes::iterator anIt = aSolidsAndSubs.begin();
+  std::vector<FeaturesPlugin_Tools::ResultBaseAlgo> aResultBaseAlgoList;
+  ListOfShape anOriginalShapesList, aResultShapesList;
+
+  std::list<std::pair<GeomShapePtr, ListOfShape> >::iterator anIt = aSolidsAndSubs.begin();
   for (; anIt != aSolidsAndSubs.end(); ++anIt) {
-    GeomShapePtr aSolid = anIt.first();
-    ListOfShape aFilletEdgesAndVertices = anIt.second();
+    GeomShapePtr aSolid = anIt->first;
+    ListOfShape aFilletEdgesAndVertices = anIt->second;
 
     ListOfShape aFilletEdges = selectEdges(aFilletEdgesAndVertices);
     if (isFixedRadius)
@@ -169,43 +188,37 @@ void FeaturesPlugin_Fillet::execute()
     std::shared_ptr<ModelAPI_ResultBody> aResultBody =
         document()->createBody(data(), aResultIndex);
 
-    loadNamingDS(aResultBody, aSolid, aResult, aFilletBuilder);
+    ListOfShape aBaseShapes;
+    aBaseShapes.push_back(aSolid);
+    FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, aBaseShapes, ListOfShape(),
+                                             aFilletBuilder, aResult, "Fillet");
+
     setResult(aResultBody, aResultIndex);
     aResultIndex++;
-  }
-  removeResults(aResultIndex);
-}
 
-void FeaturesPlugin_Fillet::loadNamingDS(
-    std::shared_ptr<ModelAPI_ResultBody> theResultBody,
-    const std::shared_ptr<GeomAPI_Shape> theBaseShape,
-    const std::shared_ptr<GeomAPI_Shape> theResultShape,
-    const std::shared_ptr<GeomAlgoAPI_MakeShape>& theMakeShape)
-{
-  //load result
-  if(theBaseShape->isEqual(theResultShape)) {
-    theResultBody->store(theResultShape, false);
-    return;
+    FeaturesPlugin_Tools::ResultBaseAlgo aRBA;
+    aRBA.resultBody = aResultBody;
+    aRBA.baseShape = aSolid;
+    aRBA.makeShape = aFilletBuilder;
+    aResultBaseAlgoList.push_back(aRBA);
+    aResultShapesList.push_back(aResult);
+    anOriginalShapesList.push_back(aSolid);
+
+    const std::string aFilletFaceName = "Fillet";
+    ListOfShape::iterator aSelectedBase = aFilletEdges.begin();
+    for(; aSelectedBase != aFilletEdges.end(); aSelectedBase++) {
+      GeomShapePtr aBase = *aSelectedBase;
+      // Store new faces generated from edges and vertices
+      aResultBody->loadGeneratedShapes(
+        aFilletBuilder, aBase, GeomAPI_Shape::EDGE, aFilletFaceName, true);
+    }
   }
 
-  theResultBody->storeModified(theBaseShape, theResultShape);
+  // Store deleted shapes after all results has been proceeded. This is to avoid issue when in one
+  // result shape has been deleted, but in another it was modified or stayed.
+  GeomShapePtr aResultShapesCompound = GeomAlgoAPI_CompoundBuilder::compound(aResultShapesList);
+  FeaturesPlugin_Tools::loadDeletedShapes(aResultBaseAlgoList,
+      anOriginalShapesList, aResultShapesCompound);
 
-  const std::string aFilletFaceName = "Fillet_Face";
-
-  // Store modified faces
-  theResultBody->loadModifiedShapes(theMakeShape, theBaseShape, GeomAPI_Shape::FACE);
-
-  // Store new faces generated from edges and vertices
-  theResultBody->loadGeneratedShapes(theMakeShape,
-                                     theBaseShape,
-                                     GeomAPI_Shape::EDGE,
-                                     aFilletFaceName);
-  theResultBody->loadGeneratedShapes(theMakeShape,
-                                     theBaseShape,
-                                     GeomAPI_Shape::VERTEX,
-                                     aFilletFaceName);
-
-  // Deleted shapes
-  theResultBody->loadDeletedShapes(theMakeShape, theBaseShape, GeomAPI_Shape::EDGE);
-  theResultBody->loadDeletedShapes(theMakeShape, theBaseShape, GeomAPI_Shape::FACE);
+  removeResults(aResultIndex);
 }
index c7a9f62c2c31fd519ecfbab4ac141b9280d260ee..7a1e75453a33877c9aa406ae976cf3b5d017f293 100644 (file)
@@ -18,6 +18,7 @@
 //
 
 #include "FeaturesPlugin_FusionFaces.h"
+#include "FeaturesPlugin_Tools.h"
 
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_AttributeString.h>
@@ -69,13 +70,10 @@ void FeaturesPlugin_FusionFaces::execute()
   // Store result
   GeomShapePtr aResultShape = anAlgo->shape();
   ResultBodyPtr aResultBody = document()->createBody(data());
-  if (aResultShape->isEqual(aBaseShape)) {
-    aResultBody->store(aResultShape);
-  } else {
-    aResultBody->storeModified(aBaseShape, aResultShape);
 
-    aResultBody->loadModifiedShapes(anAlgo, aBaseShape, GeomAPI_Shape::EDGE);
-    aResultBody->loadModifiedShapes(anAlgo, aBaseShape, GeomAPI_Shape::FACE);
-  }
+  ListOfShape aBaseShapesList;
+  aBaseShapesList.push_back(aBaseShape);
+  FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, aBaseShapesList, ListOfShape(),
+                                           anAlgo, aResultShape);
   setResult(aResultBody);
 }
index 9d6e6ebe910b1af07269333b0b8e165502d55c0d..1fa9079247f632a9cf86732de0a28b271bfada7e 100644 (file)
@@ -82,7 +82,6 @@ void FeaturesPlugin_Intersection::execute()
   setResult(aResultBody, aResultIndex);
   aResultIndex++;
 
-
   // remove the rest results if there were produced in the previous pass
   removeResults(aResultIndex);
 }
@@ -99,7 +98,7 @@ void FeaturesPlugin_Intersection::loadNamingDS(ResultBodyPtr theResultBody,
     return;
   }
 
-  theResultBody->storeModified(theObjects.front(), aResultShape);
+  theResultBody->storeModified(theObjects, aResultShape, theMakeShape);
 
   const int aShapeTypesNb = 3;
   const GeomAPI_Shape::ShapeType aShapeTypes[aShapeTypesNb] = {GeomAPI_Shape::VERTEX,
index cc60873c417bf5ad5f8684314124d5018375eba7..64286a9d7e6d8b70f52cbdfca3d2debc18a95d97 100644 (file)
 // Author:      Clarisse Genrault (CEA)
 
 #include <FeaturesPlugin_MultiRotation.h>
+#include <FeaturesPlugin_Tools.h>
 
 #include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_MakeShapeList.h>
 #include <GeomAlgoAPI_ShapeTools.h>
 #include <GeomAlgoAPI_Tools.h>
 #include <GeomAlgoAPI_Translation.h>
@@ -193,7 +195,8 @@ void FeaturesPlugin_MultiRotation::performRotation1D()
     } else {
       std::string anError;
       ListOfShape aListOfShape;
-      std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > aListOfRotationAlgo;
+      std::shared_ptr<GeomAlgoAPI_MakeShapeList>
+          aListOfRotationAlgo(new GeomAlgoAPI_MakeShapeList);
 
       for (int i=0; i<nbCopies; i++) {
         std::shared_ptr<GeomAlgoAPI_Rotation> aRotationnAlgo(
@@ -212,13 +215,16 @@ void FeaturesPlugin_MultiRotation::performRotation1D()
           break;
         }
         aListOfShape.push_back(aRotationnAlgo->shape());
-        aListOfRotationAlgo.push_back(aRotationnAlgo);
+        aListOfRotationAlgo->appendAlgo(aRotationnAlgo);
       }
       std::shared_ptr<GeomAPI_Shape> aCompound =
         GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
-      aResultBody->storeModified(aBaseShape, aCompound);
-      loadNamingDS(aListOfRotationAlgo, aResultBody, aBaseShape);
+
+      ListOfShape aBaseShapes;
+      aBaseShapes.push_back(aBaseShape);
+      FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, aBaseShapes, ListOfShape(),
+                                               aListOfRotationAlgo, aCompound, "Rotated");
 
       setResult(aResultBody, aResultIndex);
     }
@@ -458,22 +464,3 @@ void FeaturesPlugin_MultiRotation::loadNamingDS3(
   }
 }
 #endif
-
-//=================================================================================================
-void FeaturesPlugin_MultiRotation::loadNamingDS(
-    std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > theListOfRotationAlgo,
-    std::shared_ptr<ModelAPI_ResultBody> theResultBody,
-    std::shared_ptr<GeomAPI_Shape> theBaseShape)
-{
-  for (std::list<std::shared_ptr<GeomAlgoAPI_Rotation> >::const_iterator anIt =
-    theListOfRotationAlgo.begin(); anIt != theListOfRotationAlgo.cend(); ++anIt) {
-    // naming of faces
-    theResultBody->loadModifiedShapes(*anIt, theBaseShape, GeomAPI_Shape::FACE, "Rotated_Face");
-
-    // naming of edges
-    theResultBody->loadModifiedShapes(*anIt, theBaseShape, GeomAPI_Shape::EDGE, "Rotated_Edge");
-
-    // naming of vertex
-    theResultBody->loadModifiedShapes(*anIt, theBaseShape, GeomAPI_Shape::VERTEX, "Rotated_Vertex");
-  }
-}
index 477d6b62fc622bf2dcfde37ebc73fff6e7d8f271..f7dc3dc8d304ce105ca0011301e3959ab38b90e8 100644 (file)
@@ -135,10 +135,6 @@ private:
                     std::shared_ptr<ModelAPI_ResultBody> theResultBody,
                     std::shared_ptr<GeomAPI_Shape> theBaseShape, int nb);
 #endif
-
-  void loadNamingDS(std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > theListOfRotationAlgo,
-                    std::shared_ptr<ModelAPI_ResultBody> theResultBody,
-                    std::shared_ptr<GeomAPI_Shape> theBaseShape);
 };
 
 #endif // FEATURESPLUGIN_MULTIROTATION_H_
index d8b241228f20a30495e04fc426c57282ab7afb3f..b9af9671352fd044aa1e628b1af8dad648aa5916 100644 (file)
 //
 
 #include <FeaturesPlugin_MultiTranslation.h>
+#include <FeaturesPlugin_Tools.h>
 
 #include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_MakeShapeList.h>
 #include <GeomAlgoAPI_Tools.h>
 
 #include <GeomAPI_Ax1.h>
@@ -171,7 +173,8 @@ void FeaturesPlugin_MultiTranslation::performOneDirection()
     } else {
       std::string anError;
       ListOfShape aListOfShape;
-      std::list<std::shared_ptr<GeomAlgoAPI_Translation> > aListOfTranslationAlgo;
+      std::shared_ptr<GeomAlgoAPI_MakeShapeList>
+          aListOfTranslationAlgo(new GeomAlgoAPI_MakeShapeList);
 
       for (int i=0; i<nbCopies; i++) {
         std::shared_ptr<GeomAlgoAPI_Translation> aTranslationAlgo(
@@ -191,13 +194,16 @@ void FeaturesPlugin_MultiTranslation::performOneDirection()
           break;
         }
         aListOfShape.push_back(aTranslationAlgo->shape());
-        aListOfTranslationAlgo.push_back(aTranslationAlgo);
+        aListOfTranslationAlgo->appendAlgo(aTranslationAlgo);
       }
       std::shared_ptr<GeomAPI_Shape> aCompound =
         GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
-      aResultBody->storeModified(aBaseShape, aCompound);
-      loadNamingDS(aListOfTranslationAlgo, aResultBody, aBaseShape);
+
+      ListOfShape aBaseShapes;
+      aBaseShapes.push_back(aBaseShape);
+      FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, aBaseShapes, ListOfShape(),
+                                               aListOfTranslationAlgo, aCompound, "Translated");
 
       setResult(aResultBody, aResultIndex);
     }
@@ -360,7 +366,8 @@ void FeaturesPlugin_MultiTranslation::performTwoDirection()
     } else {
       std::string anError;
       ListOfShape aListOfShape;
-      std::list<std::shared_ptr<GeomAlgoAPI_Translation> > aListOfTranslationAlgo;
+      std::shared_ptr<GeomAlgoAPI_MakeShapeList>
+          aListOfTranslationAlgo(new GeomAlgoAPI_MakeShapeList);
 
       for (int j=0; j<aSecondNbCopies; j++) {
         for (int i=0; i<aFirstNbCopies; i++) {
@@ -384,14 +391,18 @@ void FeaturesPlugin_MultiTranslation::performTwoDirection()
             break;
           }
           aListOfShape.push_back(aTranslationAlgo->shape());
-          aListOfTranslationAlgo.push_back(aTranslationAlgo);
+          aListOfTranslationAlgo->appendAlgo(aTranslationAlgo);
         }
       }
       std::shared_ptr<GeomAPI_Shape> aCompound =
         GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
-      aResultBody->storeModified(aBaseShape, aCompound);
-      loadNamingDS(aListOfTranslationAlgo, aResultBody, aBaseShape);
+
+      ListOfShape aBaseShapes;
+      aBaseShapes.push_back(aBaseShape);
+      FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, aBaseShapes, ListOfShape(),
+                                               aListOfTranslationAlgo, aCompound, "Translated");
+
       setResult(aResultBody, aResultIndex);
     }
     aResultIndex++;
@@ -400,31 +411,3 @@ void FeaturesPlugin_MultiTranslation::performTwoDirection()
   // Remove the rest results if there were produced in the previous pass.
   removeResults(aResultIndex);
 }
-
-//=================================================================================================
-void FeaturesPlugin_MultiTranslation::loadNamingDS(
-    std::list<std::shared_ptr<GeomAlgoAPI_Translation> > theListOfTranslationAlgo,
-    std::shared_ptr<ModelAPI_ResultBody> theResultBody,
-    std::shared_ptr<GeomAPI_Shape> theBaseShape)
-{
-  for (std::list<std::shared_ptr<GeomAlgoAPI_Translation> >::const_iterator anIt =
-    theListOfTranslationAlgo.begin(); anIt != theListOfTranslationAlgo.cend(); ++anIt) {
-    // naming of faces
-    theResultBody->loadModifiedShapes(*anIt,
-                                      theBaseShape,
-                                      GeomAPI_Shape::FACE,
-                                      "Translated_Face");
-
-    // naming of edges
-    theResultBody->loadModifiedShapes(*anIt,
-                                      theBaseShape,
-                                      GeomAPI_Shape::EDGE,
-                                      "Translated_Edge");
-
-    // naming of vertex
-    theResultBody->loadModifiedShapes(*anIt,
-                                      theBaseShape,
-                                      GeomAPI_Shape::VERTEX,
-                                      "Translated_Vertex");
-  }
-}
index 9c0dfe3840b5f4610cfe03c01a37edc46b40b156..9571ed3d218c91228b58167d2eadd62c5f625b32 100644 (file)
@@ -119,10 +119,6 @@ private:
 
   /// Perform the multi translation in two directions.
   void performTwoDirection();
-
-  void loadNamingDS(std::list<std::shared_ptr<GeomAlgoAPI_Translation> > theListOfTranslationAlgo,
-                    std::shared_ptr<ModelAPI_ResultBody> theResultBody,
-                    std::shared_ptr<GeomAPI_Shape> theBaseShape);
 };
 
 #endif // FEATURESPLUGIN_MULTITRANSLATION_H_
\ No newline at end of file
index a97985ea40bfff5fb88c3db2600a1a1893ea36f2..f572664a2cc85c8fa5e71914c0c62a06ee39613c 100644 (file)
@@ -171,37 +171,20 @@ void FeaturesPlugin_Partition::storeResult(
   const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
   const int theIndex)
 {
-  // Find base. The most complicated is the real modified object (#1799 if box is partitioned by
-  // two planes the box is the base, not planes, independently on the order in the list).
-  GeomShapePtr aBaseShape;
-  for(ListOfShape::const_iterator anIt = theObjects.cbegin(); anIt != theObjects.cend(); ++anIt) {
-    GeomShapePtr anObjectShape = *anIt;
-    GeomShapePtr aCandidate =
-      findBase(anObjectShape, theResultShape, GeomAPI_Shape::VERTEX, theMakeShape);
-    if(!aCandidate.get()) {
-      aCandidate = findBase(anObjectShape, theResultShape, GeomAPI_Shape::EDGE, theMakeShape);
-    }
-    if (!aCandidate.get())
-      aCandidate = findBase(anObjectShape, theResultShape, GeomAPI_Shape::FACE, theMakeShape);
-
-    if(aCandidate.get()) {
-      if (!aBaseShape.get() || aBaseShape->shapeType() > aCandidate->shapeType()) {
-        aBaseShape = aCandidate;
-      }
-    }
-  }
-
   // Create result body.
   ResultBodyPtr aResultBody = document()->createBody(data(), theIndex);
 
-  // Store modified shape.
-  if(!aBaseShape.get() || aBaseShape->isEqual(theResultShape)) {
-    aResultBody->store(theResultShape, false);
-    setResult(aResultBody, theIndex);
-    return;
+  // if result is same as one of the base object, no modification was performed
+  for(ListOfShape::const_iterator anObj = theObjects.cbegin(); anObj != theObjects.cend(); ++anObj)
+  {
+    if (anObj->get() && (*anObj)->isSame(theResultShape)) {
+      aResultBody->store(theResultShape, false);
+      setResult(aResultBody, theIndex);
+      return;
+    }
   }
 
-  aResultBody->storeModified(aBaseShape, theResultShape);
+  aResultBody->storeModified(theObjects, theResultShape, theMakeShape);
 
   std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = theMakeShape->mapOfSubShapes();
   theObjects.insert(theObjects.end(), thePlanes.begin(), thePlanes.end());
@@ -221,38 +204,6 @@ void FeaturesPlugin_Partition::storeResult(
 
 //=================     Auxiliary functions     ===================================================
 
-GeomShapePtr findBase(const GeomShapePtr theObjectShape,
-                      const GeomShapePtr theResultShape,
-                      const GeomAPI_Shape::ShapeType theShapeType,
-                      const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
-{
-  GeomShapePtr aBaseShape;
-  std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = theMakeShape->mapOfSubShapes();
-  for(GeomAPI_ShapeExplorer anObjectSubShapesExp(theObjectShape, theShapeType);
-      anObjectSubShapesExp.more();
-      anObjectSubShapesExp.next()) {
-    GeomShapePtr anObjectSubShape = anObjectSubShapesExp.current();
-    ListOfShape aModifiedShapes;
-    theMakeShape->modified(anObjectSubShape, aModifiedShapes);
-    for(ListOfShape::const_iterator
-        aModIt = aModifiedShapes.cbegin(); aModIt != aModifiedShapes.cend(); ++aModIt) {
-      GeomShapePtr aModShape = *aModIt;
-      if(aMapOfSubShapes->isBound(aModShape)) {
-        aModShape = aMapOfSubShapes->find(aModShape);
-      }
-      if(theResultShape->isSubShape(aModShape)) {
-        aBaseShape = theObjectShape;
-        break;
-      }
-    }
-    if(aBaseShape.get()) {
-      break;
-    }
-  }
-
-  return aBaseShape;
-}
-
 static CompsolidSubs::iterator findOrAdd(CompsolidSubs& theList, const GeomShapePtr& theCompsolid)
 {
   CompsolidSubs::iterator aFound = theList.begin();
index eda3bed26c80d22e277ad3267c4d1252c410f62f..0acf3a84e07c22da2d7d80bc2c0757fde884230a 100644 (file)
@@ -166,8 +166,11 @@ void FeaturesPlugin_Placement::execute()
 
       //LoadNamingDS
       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
-      aResultBody->storeModified(aBaseShape, aTransformAlgo->shape());
-      FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, aBaseShape, aTransformAlgo, "Placed");
+
+      ListOfShape aShapes;
+      aShapes.push_back(aBaseShape);
+      FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, aShapes, ListOfShape(),
+                                               aTransformAlgo, aTransformAlgo->shape(), "Placed");
       setResult(aResultBody, aResultIndex);
     }
     aResultIndex++;
index bfe4ad1a84cd4774838c4f04c6ef29200bd91b2a..7ef1d86b8827fb58468b62ca83b4628ffa0e2124 100644 (file)
@@ -172,8 +172,15 @@ void FeaturesPlugin_Rotation::performTranslationByAxisAndAngle()
       }
 
       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
-      aResultBody->storeModified(aBaseShape, aRotationAlgo->shape());
-      FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, aBaseShape, aRotationAlgo, "Rotated");
+
+      ListOfShape aShapes;
+      aShapes.push_back(aBaseShape);
+      FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
+                                               aShapes,
+                                               ListOfShape(),
+                                               aRotationAlgo,
+                                               aRotationAlgo->shape(),
+                                               "Rotated");
       setResult(aResultBody, aResultIndex);
     }
     aResultIndex++;
@@ -271,8 +278,15 @@ void FeaturesPlugin_Rotation::performTranslationByThreePoints()
       }
 
       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
-      aResultBody->storeModified(aBaseShape, aRotationAlgo->shape());
-      FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, aBaseShape, aRotationAlgo, "Rotated");
+
+      ListOfShape aShapes;
+      aShapes.push_back(aBaseShape);
+      FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
+                                               aShapes,
+                                               ListOfShape(),
+                                               aRotationAlgo,
+                                               aRotationAlgo->shape(),
+                                               "Rotated");
       setResult(aResultBody, aResultIndex);
     }
     aResultIndex++;
index b1fba3444802d05a0386bd57670a608e9adc0d9b..bdb4cdd52fde517cc999053ac555b78368b7d3f9 100644 (file)
@@ -137,8 +137,15 @@ void FeaturesPlugin_Scale::performScaleByFactor()
     }
 
     ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
-    aResultBody->storeModified(aBaseShape, aScaleAlgo->shape());
-    FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, aBaseShape, aScaleAlgo, "Scaled");
+
+    ListOfShape aShapes;
+    aShapes.push_back(aBaseShape);
+    FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
+                                             aShapes,
+                                             ListOfShape(),
+                                             aScaleAlgo,
+                                             aScaleAlgo->shape(),
+                                             "Scaled");
     setResult(aResultBody, aResultIndex);
     aResultIndex++;
   }
@@ -215,8 +222,15 @@ void FeaturesPlugin_Scale::performScaleByDimensions()
     }
 
     ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
-    aResultBody->storeModified(aBaseShape, aScaleAlgo->shape());
-    FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, aBaseShape, aScaleAlgo, "Scaled");
+
+    ListOfShape aShapes;
+    aShapes.push_back(aBaseShape);
+    FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
+                                             aShapes,
+                                             ListOfShape(),
+                                             aScaleAlgo,
+                                             aScaleAlgo->shape(),
+                                             "Scaled");
     setResult(aResultBody, aResultIndex);
     aResultIndex++;
   }
index a243e55f30b0137cf373080a386e9d27a515da81..38b50f39391e0d19cd01cf266d4ef525c52f57e2 100644 (file)
@@ -369,8 +369,12 @@ void FeaturesPlugin_Symmetry::buildResult(
 
   // Store and name the result.
   ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
-  aResultBody->storeModified(theBaseShape, aCompound);
-  FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, theBaseShape, anAlgoList, "Symmetried");
+
+  ListOfShape aBaseShapes;
+  aBaseShapes.push_back(theBaseShape);
+  FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, aBaseShapes, ListOfShape(),
+                                           anAlgoList, aCompound, "Symmetried");
+
   setResult(aResultBody, theResultIndex);
 }
 
index b484349d08f2f8809b0fd83faf07b42639b9ce5e..ed96231b4387dc1307117285b224ef157b3e3f5d 100644 (file)
 
 //==================================================================================================
 void FeaturesPlugin_Tools::loadModifiedShapes(ResultBodyPtr theResultBody,
-                                              const GeomShapePtr theBaseShape,
+                                              const ListOfShape& theBaseShapes,
                                               const ListOfShape& theTools,
                                               const GeomMakeShapePtr& theMakeShape,
-                                              const GeomShapePtr theResultShape)
+                                              const GeomShapePtr theResultShape,
+                                              const std::string& theNamePrefix)
 {
-  if (theBaseShape->isEqual(theResultShape)) {
-    theResultBody->store(theResultShape, false);
-    return;
-  }
+  theResultBody->storeModified(theBaseShapes, theResultShape, theMakeShape);
 
-  theResultBody->storeModified(theBaseShape, theResultShape);
+  ListOfShape aShapes = theBaseShapes;
+  ListOfShape::const_iterator aToolIter = theTools.cbegin();
+  for(; aToolIter != theTools.cend(); aToolIter++)
+    aShapes.push_back(*aToolIter);
 
-  ListOfShape aShapes = theTools;
-  aShapes.push_front(theBaseShape);
+  std::string aVertexName, anEdgeName, aFaceName;
+  if (!theNamePrefix.empty()) {
+    aVertexName = theNamePrefix + "_Vertex";
+    anEdgeName = theNamePrefix + "_Edge";
+    aFaceName = theNamePrefix + "_Face";
+  }
 
   for (ListOfShape::const_iterator anIter = aShapes.begin(); anIter != aShapes.end(); ++anIter)
   {
-    theResultBody->loadModifiedShapes(theMakeShape, *anIter, GeomAPI_Shape::VERTEX);
-    theResultBody->loadModifiedShapes(theMakeShape, *anIter, GeomAPI_Shape::EDGE);
-    theResultBody->loadModifiedShapes(theMakeShape, *anIter, GeomAPI_Shape::FACE);
+    theResultBody->loadModifiedShapes(theMakeShape, *anIter, GeomAPI_Shape::VERTEX, aVertexName);
+    theResultBody->loadModifiedShapes(theMakeShape, *anIter, GeomAPI_Shape::EDGE, anEdgeName);
+    theResultBody->loadModifiedShapes(theMakeShape, *anIter, GeomAPI_Shape::FACE, aFaceName);
   }
 }
 
 //==================================================================================================
 void FeaturesPlugin_Tools::loadModifiedShapes(ResultBodyPtr theResultBody,
-                                              const GeomShapePtr theBaseShape,
+                                              const GeomShapePtr& theBaseShape,
                                               const GeomMakeShapePtr& theMakeShape,
                                               const std::string theName)
 {
@@ -97,7 +102,8 @@ void FeaturesPlugin_Tools::loadDeletedShapes(ResultBodyPtr theResultBody,
   const GeomShapePtr theResultShapesCompound)
 {
   ListOfShape aShapes = theTools;
-  aShapes.push_front(theBaseShape);
+  if (theBaseShape.get())
+    aShapes.push_front(theBaseShape);
 
   for (ListOfShape::const_iterator anIter = aShapes.begin(); anIter != aShapes.end(); anIter++)
   {
index 395079bb57399ca4476c2e6c5a333cfdfba76213..dd04de569f511a3517ccc12b7604ac69afe31ea3 100644 (file)
@@ -35,16 +35,16 @@ public:
 
 public:
   static void loadModifiedShapes(ResultBodyPtr theResultBody,
-                                 const GeomShapePtr theBaseShape,
+                                 const ListOfShape& theBaseShapes,
                                  const ListOfShape& theTools,
                                  const GeomMakeShapePtr& theMakeShape,
-                                 const GeomShapePtr theResultShape);
+                                 const GeomShapePtr theResultShape,
+                                 const std::string& theNamePrefix = "");
 
   static void loadModifiedShapes(ResultBodyPtr theResultBody,
-                                 const GeomShapePtr theBaseShape,
+                                 const GeomShapePtr& theBaseShape,
                                  const GeomMakeShapePtr& theMakeShape,
                                  const std::string theName);
-
     /// Stores deleted shapes.
   static void loadDeletedShapes(ResultBodyPtr theResultBody,
                                 const GeomShapePtr theBaseShape,
index 4e6d57073988c87869413f9f5be6af989a447ae3..eff54dc689f759480f280cca2cc47ef3a11f5a39 100644 (file)
@@ -184,10 +184,14 @@ void FeaturesPlugin_Translation::performTranslationByAxisAndDistance()
       }
 
       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
-      aResultBody->storeModified(aBaseShape, aTranslationAlgo->shape());
+
+      ListOfShape aShapes;
+      aShapes.push_back(aBaseShape);
       FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
-                                               aBaseShape,
+                                               aShapes,
+                                               ListOfShape(),
                                                aTranslationAlgo,
+                                               aTranslationAlgo->shape(),
                                                "Translated");
       setResult(aResultBody, aResultIndex);
     }
@@ -260,10 +264,14 @@ void FeaturesPlugin_Translation::performTranslationByDimensions()
       }
 
       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
-      aResultBody->storeModified(aBaseShape, aTranslationAlgo->shape());
+
+      ListOfShape aShapes;
+      aShapes.push_back(aBaseShape);
       FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
-                                               aBaseShape,
+                                               aShapes,
+                                               ListOfShape(),
                                                aTranslationAlgo,
+                                               aTranslationAlgo->shape(),
                                                "Translated");
       setResult(aResultBody, aResultIndex);
     }
@@ -349,10 +357,14 @@ void FeaturesPlugin_Translation::performTranslationByTwoPoints()
       }
 
       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
-      aResultBody->storeModified(aBaseShape, aTranslationAlgo->shape());
+
+      ListOfShape aShapes;
+      aShapes.push_back(aBaseShape);
       FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
-                                               aBaseShape,
+                                               aShapes,
+                                               ListOfShape(),
                                                aTranslationAlgo,
+                                               aTranslationAlgo->shape(),
                                                "Translated");
       setResult(aResultBody, aResultIndex);
     }
diff --git a/src/FeaturesPlugin/Test/Test1876.py b/src/FeaturesPlugin/Test/Test1876.py
new file mode 100644 (file)
index 0000000..47709b5
--- /dev/null
@@ -0,0 +1,72 @@
+## 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>
+##
+
+from salome.shaper import model
+from ModelAPI import *
+
+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(396.8373493975904, 115.9638554216867, -225.1506024096385, 115.9638554216867)
+SketchLine_2 = Sketch_1.addLine(-225.1506024096385, 115.9638554216867, -225.1506024096385, -149.0963855421687)
+SketchLine_3 = Sketch_1.addLine(-225.1506024096385, -149.0963855421687, 396.8373493975904, -149.0963855421687)
+SketchLine_4 = Sketch_1.addLine(396.8373493975904, -149.0963855421687, 396.8373493975904, 115.9638554216867)
+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())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_2.addCircle(-348.644578313253, 155.1204819277109, 207.6894050099908)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f")], model.selection(), 100, 0)
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchCircle_1_2r")], model.selection(), 100, 0)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Extrusion_2_1")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_2_1")])
+model.end()
+
+# move groups
+model.begin()
+Part_1_doc.moveFeature(Group_1.feature(), Partition_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+model.end()
+
+# check each group contain two results: one is related to original body only, another - common part
+
+aFactory = ModelAPI_Session.get().validators()
+assert(aFactory.validate(Group_1.feature()))
+assert(aFactory.validate(Group_2.feature()))
+aList1 = Group_1.feature().selectionList("group_list")
+aList2 = Group_2.feature().selectionList("group_list")
+assert(aList1.size() == 2)
+assert(aList2.size() == 2)
+assert(aList1.value(0).value().shapeTypeStr() == "SOLID")
+assert(aList1.value(1).value().shapeTypeStr() == "SOLID")
+assert(aList2.value(0).value().shapeTypeStr() == "SOLID")
+assert(aList2.value(1).value().shapeTypeStr() == "SOLID")
+assert(aList1.value(0).value().isSame(aList2.value(0).value()) or aList1.value(1).value().isSame(aList2.value(0).value()) or
+aList1.value(0).value().isSame(aList2.value(1).value()) or aList1.value(1).value().isSame(aList2.value(1).value()))
index cef3c5768d09e373b9cb3077ebca7f6944a972bd..d11aaaca1731cd0dd7e2e6c711c59981d9357cf2 100644 (file)
@@ -183,7 +183,19 @@ Plane_5 = model.addPlane(Part_1_doc, model.selection("EDGE", "PartSet/Axis_4"),
 Face_1_objects = [model.selection("EDGE", "Sketch_1/SketchArc_2_2"), model.selection("EDGE", "Sketch_1/SketchLine_4"), model.selection("EDGE", "Sketch_1/SketchLine_5"), model.selection("EDGE", "Sketch_1/SketchLine_6"), model.selection("EDGE", "Sketch_1/SketchLine_7"), model.selection("EDGE", "Sketch_1/SketchLine_8"), model.selection("EDGE", "Sketch_1/SketchLine_1"), model.selection("EDGE", "Sketch_1/SketchLine_2")]
 Face_1 = model.addFace(Part_1_doc, Face_1_objects)
 Intersection_1 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Recover_1_1"), model.selection("FACE", "Face_1_1")])
-Group_1_objects = [model.selection("VERTEX", "[Intersection_1_1_3/Intersection_1_1_3&Face_1_1/Edge_3][weak_name_2]"), model.selection("VERTEX", "[Intersection_1_1_1/Intersection_1_1_1][weak_name_2]"), model.selection("VERTEX", "[Intersection_1_1_9/Intersection_1_1_9&Face_1_1/Edge_7][weak_name_1]"), model.selection("VERTEX", "[Intersection_1_1_7/Intersection_1_1_7&Face_1_1/Edge_5][weak_name_2]"), model.selection("VERTEX", "[Intersection_1_1_4/Intersection_1_1_4][weak_name_2]"), model.selection("VERTEX", "[Intersection_1_1_1/Intersection_1_1_1][weak_name_1]"), model.selection("VERTEX", "[Intersection_1_1_2/Intersection_1_1_2&Face_1_1/Edge_2][weak_name_1]"), model.selection("VERTEX", "[Intersection_1_1_4/Intersection_1_1_4][weak_name_1]"), model.selection("VERTEX", "[Intersection_1_1_6/Intersection_1_1_6&Face_1_1/Edge_4][weak_name_2]"), model.selection("VERTEX", "[Intersection_1_1_10/Intersection_1_1_10&Face_1_1/Edge_8][weak_name_1]"), model.selection("VERTEX", "[Intersection_1_1_8/Intersection_1_1_8&Face_1_1/Edge_6][weak_name_1]")]
+Group_1_objects = [
+model.selection("VERTEX", "[Intersection_1_1_3/Intersection_1_1_3&Face_1_1/Edge_3][weak_name_2]"),
+model.selection("VERTEX", "[Intersection_1_1_1/Intersection_1_1_1][weak_name_2]"),
+model.selection("VERTEX", "[Intersection_1_1_9/Intersection_1_1_9&Face_1_1/Edge_7][weak_name_1]"),
+model.selection("VERTEX", "[Intersection_1_1_7/Intersection_1_1_7&Face_1_1/Edge_5][weak_name_2]"),
+model.selection("VERTEX", "[Intersection_1_1_4/Intersection_1_1_4][weak_name_2]"),
+model.selection("VERTEX", "[Intersection_1_1_1/Intersection_1_1_1][weak_name_1]"),
+model.selection("VERTEX", "[Intersection_1_1_2/Intersection_1_1_2&Face_1_1/Edge_2][weak_name_1]"),
+model.selection("VERTEX", "[Intersection_1_1_4/Intersection_1_1_4][weak_name_1]"),
+model.selection("VERTEX", "[Intersection_1_1_6/Intersection_1_1_6&Face_1_1/Edge_4][weak_name_2]"),
+model.selection("VERTEX", "[Intersection_1_1_10/Intersection_1_1_10&Face_1_1/Edge_8][weak_name_1]"),
+model.selection("VERTEX", "[Intersection_1_1_8/Intersection_1_1_8&Face_1_1/Edge_6][weak_name_1]")]
+
 Group_1 = model.addGroup(Part_1_doc, Group_1_objects)
 Group_2_objects = [model.selection("EDGE", "Intersection_1_1_7"), model.selection("EDGE", "Intersection_1_1_6"), model.selection("EDGE", "Intersection_1_1_3"), model.selection("EDGE", "Intersection_1_1_11"), model.selection("EDGE", "Intersection_1_1_5"), model.selection("EDGE", "Intersection_1_1_1"), model.selection("EDGE", "Intersection_1_1_4"), model.selection("EDGE", "Intersection_1_1_2"), model.selection("EDGE", "Intersection_1_1_10"), model.selection("EDGE", "Intersection_1_1_9"), model.selection("EDGE", "Intersection_1_1_8")]
 Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
diff --git a/src/FeaturesPlugin/Test/Test2636.py b/src/FeaturesPlugin/Test/Test2636.py
new file mode 100644 (file)
index 0000000..8ad1eea
--- /dev/null
@@ -0,0 +1,437 @@
+## Copyright (C) 2019-20xx  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+model.addParameter(partSet, "epsilon", "0.1")
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchLine_1.setName("SketchLine_2")
+SketchLine_1.result().setName("SketchLine_2")
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_2 = SketchProjection_2.createdFeature()
+SketchLine_2.setName("SketchLine_3")
+SketchLine_2.result().setName("SketchLine_3")
+SketchLine_3 = Sketch_1.addLine(0, 0, 0, -21)
+SketchLine_3.setName("SketchLine_4")
+SketchLine_3.result().setName("SketchLine_4")
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(0, -21, 54, -21)
+SketchLine_4.setName("SketchLine_5")
+SketchLine_4.result().setName("SketchLine_5")
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(54, -21, 57, -18)
+SketchLine_5.setName("SketchLine_6")
+SketchLine_5.result().setName("SketchLine_6")
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_3.result())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_4.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_3.result(), "42/2")
+SketchConstraintAngle_1 = Sketch_1.setAngleComplementary(SketchLine_4.result(), SketchLine_5.result(), 45)
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_5.endPoint(), SketchLine_3.endPoint(), 57)
+SketchLine_6 = Sketch_1.addLine(57, -18, 159.1, -18)
+SketchLine_6.setName("SketchLine_7")
+SketchLine_6.result().setName("SketchLine_7")
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_6.result())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchLine_5.endPoint(), SketchLine_1.result(), "36/2", True)
+SketchLine_7 = Sketch_1.addLine(162.1, -21, 162.1, -31.5)
+SketchLine_7.setName("SketchLine_8")
+SketchLine_7.result().setName("SketchLine_8")
+SketchLine_8 = Sketch_1.addLine(162.1, -31.5, 204.1, -31.5)
+SketchLine_8.setName("SketchLine_9")
+SketchLine_8.result().setName("SketchLine_9")
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchLine_9 = Sketch_1.addLine(204.1, -31.5, 204.1, -21)
+SketchLine_9.setName("SketchLine_10")
+SketchLine_9.result().setName("SketchLine_10")
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchLine_10 = Sketch_1.addLine(204.1, -21, 181.1, -21)
+SketchLine_10.setName("SketchLine_11")
+SketchLine_10.result().setName("SketchLine_11")
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint())
+SketchLine_11 = Sketch_1.addLine(181.1, -21, 168.9756443470179, 0)
+SketchLine_11.setName("SketchLine_12")
+SketchLine_11.result().setName("SketchLine_12")
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint())
+SketchLine_12 = Sketch_1.addLine(168.9756443470179, 0, 0, 0)
+SketchLine_12.setName("SketchLine_13")
+SketchLine_12.result().setName("SketchLine_13")
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_11.endPoint(), SketchLine_12.startPoint())
+SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_12.endPoint())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_12.result())
+SketchConstraintHorizontal_4 = Sketch_1.setHorizontal(SketchLine_10.result())
+SketchConstraintHorizontal_5 = Sketch_1.setHorizontal(SketchLine_8.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_7.result())
+SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_9.result())
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_12.startPoint(), SketchLine_8.endPoint(), "63/2")
+SketchConstraintDistanceVertical_2 = Sketch_1.setVerticalDistance(SketchLine_12.startPoint(), SketchLine_10.startPoint(), "42/2")
+SketchConstraintAngle_2 = Sketch_1.setAngleComplementary(SketchLine_12.result(), SketchLine_11.result(), 60)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_10.result(), 23)
+SketchConstraintLength_3 = Sketch_1.setLength(SketchLine_8.result(), 42)
+SketchLine_13 = Sketch_1.addLine(54, -21, 54, 0)
+SketchLine_13.setName("SketchLine_14")
+SketchLine_13.result().setName("SketchLine_14")
+SketchConstraintCoincidence_11 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_13.startPoint())
+SketchConstraintCoincidence_12 = Sketch_1.setCoincident(SketchLine_13.endPoint(), SketchLine_1.result())
+SketchLine_14 = Sketch_1.addLine(57, -18, 57, 0)
+SketchLine_14.setName("SketchLine_15")
+SketchLine_14.result().setName("SketchLine_15")
+SketchConstraintCoincidence_13 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_14.startPoint())
+SketchConstraintCoincidence_14 = Sketch_1.setCoincident(SketchLine_14.endPoint(), SketchLine_1.result())
+SketchConstraintVertical_4 = Sketch_1.setVertical(SketchLine_14.result())
+SketchConstraintVertical_5 = Sketch_1.setVertical(SketchLine_13.result())
+SketchLine_15 = Sketch_1.addLine(181.1, -21, 181.1, -31.5)
+SketchLine_15.setName("SketchLine_18")
+SketchLine_15.result().setName("SketchLine_18")
+SketchConstraintCoincidence_15 = Sketch_1.setCoincident(SketchLine_10.endPoint(), SketchLine_15.startPoint())
+SketchConstraintCoincidence_16 = Sketch_1.setCoincident(SketchLine_15.endPoint(), SketchLine_8.result())
+SketchConstraintVertical_6 = Sketch_1.setVertical(SketchLine_15.result())
+SketchArc_1 = Sketch_1.addArc(159.1, -21, 162.1, -21, 159.1, -18, False)
+SketchPoint_1 = Sketch_1.addPoint(162.1, -18)
+SketchPoint_1.setName("SketchPoint_2")
+SketchPoint_1.result().setName("SketchPoint_2")
+SketchPoint_1.setAuxiliary(True)
+SketchConstraintCoincidence_17 = Sketch_1.setCoincident(SketchPoint_1.coordinates(), SketchLine_6.result())
+SketchConstraintCoincidence_18 = Sketch_1.setCoincident(SketchPoint_1.coordinates(), SketchLine_7.result())
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchLine_6.startPoint(), SketchPoint_1.coordinates(), "105+epsilon", False)
+SketchConstraintCoincidence_19 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_20 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_6.endPoint())
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchArc_1.results()[1], SketchLine_6.result())
+SketchConstraintTangent_2 = Sketch_1.setTangent(SketchArc_1.results()[1], SketchLine_7.result())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], 3)
+SketchLine_16 = Sketch_1.addLine(162.1, -21, 181.1, -21)
+SketchLine_16.setName("SketchLine_36")
+SketchLine_16.result().setName("SketchLine_36")
+SketchConstraintCoincidence_21 = Sketch_1.setCoincident(SketchLine_16.endPoint(), SketchLine_11.result())
+SketchConstraintCoincidence_22 = Sketch_1.setCoincident(SketchLine_16.startPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_23 = Sketch_1.setCoincident(SketchLine_16.endPoint(), SketchLine_15.startPoint())
+SketchLine_17 = Sketch_1.addLine(159.1, -18, 159.1, 0)
+SketchLine_17.setName("SketchLine_35")
+SketchLine_17.result().setName("SketchLine_35")
+SketchConstraintCoincidence_24 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_17.startPoint())
+SketchConstraintCoincidence_25 = Sketch_1.setCoincident(SketchLine_17.endPoint(), SketchLine_12.result())
+SketchConstraintVertical_7 = Sketch_1.setVertical(SketchLine_17.result())
+SketchLine_18 = Sketch_1.addLine(159.1, -18, 175.3264973081038, -11)
+SketchLine_18.setName("SketchLine_37")
+SketchLine_18.result().setName("SketchLine_37")
+SketchConstraintCoincidence_26 = Sketch_1.setCoincident(SketchLine_18.endPoint(), SketchLine_11.result())
+SketchConstraintCoincidence_27 = Sketch_1.setCoincident(SketchLine_18.startPoint(), SketchLine_6.endPoint())
+SketchLine_19 = Sketch_1.addLine(168.9756443470179, 0, 168.9756443470179, -5)
+SketchLine_19.setName("SketchLine_38")
+SketchLine_19.result().setName("SketchLine_38")
+SketchLine_19.setAuxiliary(True)
+SketchConstraintCoincidence_28 = Sketch_1.setCoincident(SketchLine_11.endPoint(), SketchLine_19.startPoint())
+SketchConstraintVertical_8 = Sketch_1.setVertical(SketchLine_19.result())
+SketchConstraintLength_4 = Sketch_1.setLength(SketchLine_19.result(), 5)
+SketchConstraintDistanceVertical_3 = Sketch_1.setVerticalDistance(SketchLine_18.endPoint(), SketchLine_12.startPoint(), 11)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection("EDGE", "Sketch_1/SketchLine_13"), 360, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Revolution_1_1_1/Generated_Face&Sketch_1/SketchLine_4"))
+SketchPoint_2 = Sketch_2.addPoint(0, 0)
+SketchPoint_2.setName("SketchPoint_3")
+SketchPoint_2.result().setName("SketchPoint_3")
+SketchProjection_3 = Sketch_2.addProjection(model.selection("VERTEX", "[Revolution_1_1_1/Generated_Face&Sketch_1/SketchLine_4][Revolution_1_1_1/Generated_Face&Sketch_1/SketchLine_5]__cc"), False)
+SketchProjection_3.setName("SketchProjection_4")
+SketchProjection_3.result().setName("SketchProjection_4")
+SketchPoint_3 = SketchProjection_3.createdFeature()
+SketchPoint_3.setName("SketchPoint_4")
+SketchPoint_3.result().setName("SketchPoint_4")
+SketchConstraintCoincidence_29 = Sketch_2.setCoincident(SketchPoint_2.coordinates(), SketchPoint_3.result())
+model.do()
+Sketch_2.setName("Sketch_3")
+Sketch_2.result().setName("Sketch_3")
+model.do()
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Sketch_3 = model.addSketch(Part_2_doc, model.defaultPlane("XOY"))
+SketchProjection_4 = Sketch_3.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_20 = SketchProjection_4.createdFeature()
+SketchLine_20.setName("SketchLine_2")
+SketchLine_20.result().setName("SketchLine_2")
+SketchProjection_5 = Sketch_3.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_21 = SketchProjection_5.createdFeature()
+SketchLine_21.setName("SketchLine_3")
+SketchLine_21.result().setName("SketchLine_3")
+SketchLine_22 = Sketch_3.addLine(0, 0, 0, -21)
+SketchLine_22.setName("SketchLine_4")
+SketchLine_22.result().setName("SketchLine_4")
+SketchConstraintCoincidence_30 = Sketch_3.setCoincident(SketchAPI_Line(SketchLine_20).startPoint(), SketchLine_22.startPoint())
+SketchLine_23 = Sketch_3.addLine(0, -21, 54, -21)
+SketchLine_23.setName("SketchLine_5")
+SketchLine_23.result().setName("SketchLine_5")
+SketchConstraintCoincidence_31 = Sketch_3.setCoincident(SketchLine_22.endPoint(), SketchLine_23.startPoint())
+SketchLine_24 = Sketch_3.addLine(54, -21, 57, -18)
+SketchLine_24.setName("SketchLine_6")
+SketchLine_24.result().setName("SketchLine_6")
+SketchConstraintCoincidence_32 = Sketch_3.setCoincident(SketchLine_23.endPoint(), SketchLine_24.startPoint())
+SketchConstraintVertical_9 = Sketch_3.setVertical(SketchLine_22.result())
+SketchConstraintHorizontal_6 = Sketch_3.setHorizontal(SketchLine_23.result())
+SketchConstraintLength_5 = Sketch_3.setLength(SketchLine_22.result(), "42/2")
+SketchConstraintAngle_3 = Sketch_3.setAngleComplementary(SketchLine_23.result(), SketchLine_24.result(), 45)
+SketchConstraintDistanceHorizontal_2 = Sketch_3.setHorizontalDistance(SketchLine_24.endPoint(), SketchLine_22.endPoint(), 57)
+SketchLine_25 = Sketch_3.addLine(57, -18, 159.1, -18)
+SketchLine_25.setName("SketchLine_7")
+SketchLine_25.result().setName("SketchLine_7")
+SketchConstraintCoincidence_33 = Sketch_3.setCoincident(SketchLine_24.endPoint(), SketchLine_25.startPoint())
+SketchConstraintHorizontal_7 = Sketch_3.setHorizontal(SketchLine_25.result())
+SketchConstraintDistance_3 = Sketch_3.setDistance(SketchLine_24.endPoint(), SketchLine_20.result(), "36/2", True)
+SketchLine_26 = Sketch_3.addLine(162.1, -21, 162.1, -31.5)
+SketchLine_26.setName("SketchLine_8")
+SketchLine_26.result().setName("SketchLine_8")
+SketchLine_27 = Sketch_3.addLine(162.1, -31.5, 204.1, -31.5)
+SketchLine_27.setName("SketchLine_9")
+SketchLine_27.result().setName("SketchLine_9")
+SketchConstraintCoincidence_34 = Sketch_3.setCoincident(SketchLine_26.endPoint(), SketchLine_27.startPoint())
+SketchLine_28 = Sketch_3.addLine(204.1, -31.5, 204.1, -21)
+SketchLine_28.setName("SketchLine_10")
+SketchLine_28.result().setName("SketchLine_10")
+SketchConstraintCoincidence_35 = Sketch_3.setCoincident(SketchLine_27.endPoint(), SketchLine_28.startPoint())
+SketchLine_29 = Sketch_3.addLine(204.1, -21, 181.1, -21)
+SketchLine_29.setName("SketchLine_11")
+SketchLine_29.result().setName("SketchLine_11")
+SketchConstraintCoincidence_36 = Sketch_3.setCoincident(SketchLine_28.endPoint(), SketchLine_29.startPoint())
+SketchLine_30 = Sketch_3.addLine(181.1, -21, 168.9756443470179, 0)
+SketchLine_30.setName("SketchLine_12")
+SketchLine_30.result().setName("SketchLine_12")
+SketchConstraintCoincidence_37 = Sketch_3.setCoincident(SketchLine_29.endPoint(), SketchLine_30.startPoint())
+SketchLine_31 = Sketch_3.addLine(168.9756443470179, 0, 0, 0)
+SketchLine_31.setName("SketchLine_13")
+SketchLine_31.result().setName("SketchLine_13")
+SketchConstraintCoincidence_38 = Sketch_3.setCoincident(SketchLine_30.endPoint(), SketchLine_31.startPoint())
+SketchConstraintCoincidence_39 = Sketch_3.setCoincident(SketchAPI_Line(SketchLine_20).startPoint(), SketchLine_31.endPoint())
+SketchConstraintHorizontal_8 = Sketch_3.setHorizontal(SketchLine_31.result())
+SketchConstraintHorizontal_9 = Sketch_3.setHorizontal(SketchLine_29.result())
+SketchConstraintHorizontal_10 = Sketch_3.setHorizontal(SketchLine_27.result())
+SketchConstraintVertical_10 = Sketch_3.setVertical(SketchLine_26.result())
+SketchConstraintVertical_11 = Sketch_3.setVertical(SketchLine_28.result())
+SketchConstraintDistanceVertical_4 = Sketch_3.setVerticalDistance(SketchLine_31.startPoint(), SketchLine_27.endPoint(), "63/2")
+SketchConstraintDistanceVertical_5 = Sketch_3.setVerticalDistance(SketchLine_31.startPoint(), SketchLine_29.startPoint(), "42/2")
+SketchConstraintAngle_4 = Sketch_3.setAngleComplementary(SketchLine_31.result(), SketchLine_30.result(), 60)
+SketchConstraintLength_6 = Sketch_3.setLength(SketchLine_29.result(), 23)
+SketchConstraintLength_7 = Sketch_3.setLength(SketchLine_27.result(), 42)
+SketchLine_32 = Sketch_3.addLine(54, -21, 54, 0)
+SketchLine_32.setName("SketchLine_14")
+SketchLine_32.result().setName("SketchLine_14")
+SketchConstraintCoincidence_40 = Sketch_3.setCoincident(SketchLine_23.endPoint(), SketchLine_32.startPoint())
+SketchConstraintCoincidence_41 = Sketch_3.setCoincident(SketchLine_32.endPoint(), SketchLine_20.result())
+SketchLine_33 = Sketch_3.addLine(57, -18, 57, 0)
+SketchLine_33.setName("SketchLine_15")
+SketchLine_33.result().setName("SketchLine_15")
+SketchConstraintCoincidence_42 = Sketch_3.setCoincident(SketchLine_24.endPoint(), SketchLine_33.startPoint())
+SketchConstraintCoincidence_43 = Sketch_3.setCoincident(SketchLine_33.endPoint(), SketchLine_20.result())
+SketchConstraintVertical_12 = Sketch_3.setVertical(SketchLine_33.result())
+SketchConstraintVertical_13 = Sketch_3.setVertical(SketchLine_32.result())
+SketchLine_34 = Sketch_3.addLine(181.1, -21, 181.1, -31.5)
+SketchLine_34.setName("SketchLine_18")
+SketchLine_34.result().setName("SketchLine_18")
+SketchConstraintCoincidence_44 = Sketch_3.setCoincident(SketchLine_29.endPoint(), SketchLine_34.startPoint())
+SketchConstraintCoincidence_45 = Sketch_3.setCoincident(SketchLine_34.endPoint(), SketchLine_27.result())
+SketchConstraintVertical_14 = Sketch_3.setVertical(SketchLine_34.result())
+SketchArc_2 = Sketch_3.addArc(159.1, -21, 162.1, -21, 159.1, -18, False)
+SketchPoint_4 = Sketch_3.addPoint(162.1, -18)
+SketchPoint_4.setName("SketchPoint_2")
+SketchPoint_4.result().setName("SketchPoint_2")
+SketchPoint_4.setAuxiliary(True)
+SketchConstraintCoincidence_46 = Sketch_3.setCoincident(SketchPoint_4.coordinates(), SketchLine_25.result())
+SketchConstraintCoincidence_47 = Sketch_3.setCoincident(SketchPoint_4.coordinates(), SketchLine_26.result())
+SketchConstraintDistance_4 = Sketch_3.setDistance(SketchLine_25.startPoint(), SketchPoint_4.coordinates(), "105+epsilon", False)
+SketchConstraintCoincidence_48 = Sketch_3.setCoincident(SketchArc_2.startPoint(), SketchLine_26.startPoint())
+SketchConstraintCoincidence_49 = Sketch_3.setCoincident(SketchArc_2.endPoint(), SketchLine_25.endPoint())
+SketchConstraintTangent_3 = Sketch_3.setTangent(SketchArc_2.results()[1], SketchLine_25.result())
+SketchConstraintTangent_4 = Sketch_3.setTangent(SketchArc_2.results()[1], SketchLine_26.result())
+SketchConstraintRadius_2 = Sketch_3.setRadius(SketchArc_2.results()[1], 3)
+SketchLine_35 = Sketch_3.addLine(162.1, -21, 181.1, -21)
+SketchLine_35.setName("SketchLine_36")
+SketchLine_35.result().setName("SketchLine_36")
+SketchConstraintCoincidence_50 = Sketch_3.setCoincident(SketchLine_35.endPoint(), SketchLine_30.result())
+SketchConstraintCoincidence_51 = Sketch_3.setCoincident(SketchLine_35.startPoint(), SketchLine_26.startPoint())
+SketchConstraintCoincidence_52 = Sketch_3.setCoincident(SketchLine_35.endPoint(), SketchLine_34.startPoint())
+SketchLine_36 = Sketch_3.addLine(159.1, -18, 159.1, 0)
+SketchLine_36.setName("SketchLine_35")
+SketchLine_36.result().setName("SketchLine_35")
+SketchConstraintCoincidence_53 = Sketch_3.setCoincident(SketchLine_25.endPoint(), SketchLine_36.startPoint())
+SketchConstraintCoincidence_54 = Sketch_3.setCoincident(SketchLine_36.endPoint(), SketchLine_31.result())
+SketchConstraintVertical_15 = Sketch_3.setVertical(SketchLine_36.result())
+SketchLine_37 = Sketch_3.addLine(159.1, -18, 175.3264973081038, -11)
+SketchLine_37.setName("SketchLine_37")
+SketchLine_37.result().setName("SketchLine_37")
+SketchConstraintCoincidence_55 = Sketch_3.setCoincident(SketchLine_37.endPoint(), SketchLine_30.result())
+SketchConstraintCoincidence_56 = Sketch_3.setCoincident(SketchLine_37.startPoint(), SketchLine_25.endPoint())
+SketchLine_38 = Sketch_3.addLine(168.9756443470179, 0, 168.9756443470179, -5)
+SketchLine_38.setName("SketchLine_38")
+SketchLine_38.result().setName("SketchLine_38")
+SketchLine_38.setAuxiliary(True)
+SketchConstraintCoincidence_57 = Sketch_3.setCoincident(SketchLine_30.endPoint(), SketchLine_38.startPoint())
+SketchConstraintVertical_16 = Sketch_3.setVertical(SketchLine_38.result())
+SketchConstraintLength_8 = Sketch_3.setLength(SketchLine_38.result(), 5)
+SketchConstraintDistanceVertical_6 = Sketch_3.setVerticalDistance(SketchLine_37.endPoint(), SketchLine_31.startPoint(), 11)
+model.do()
+Revolution_2 = model.addRevolution(Part_2_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection("EDGE", "Sketch_1/SketchLine_13"), 360, 0)
+Sketch_4 = model.addSketch(Part_2_doc, model.selection("FACE", "Revolution_1_1_1/Generated_Face&Sketch_1/SketchLine_4"))
+SketchLine_39 = Sketch_4.addLine(50, 0, -50, 0)
+SketchLine_39.setName("SketchLine_19")
+SketchLine_39.result().setName("SketchLine_19")
+SketchConstraintHorizontal_11 = Sketch_4.setHorizontal(SketchLine_39.result())
+SketchProjection_6 = Sketch_4.addProjection(model.selection("VERTEX", "[Revolution_1_1_1/Generated_Face&Sketch_1/SketchLine_4][Revolution_1_1_1/Generated_Face&Sketch_1/SketchLine_5]__cc"), False)
+SketchPoint_5 = SketchProjection_6.createdFeature()
+SketchPoint_5.setName("SketchPoint_1")
+SketchPoint_5.result().setName("SketchPoint_1")
+SketchConstraintLength_9 = Sketch_4.setLength(SketchLine_39.result(), 100)
+SketchLine_40 = Sketch_4.addLine(0, -50, 0, 50)
+SketchLine_40.setName("SketchLine_20")
+SketchLine_40.result().setName("SketchLine_20")
+SketchProjection_7 = Sketch_4.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_41 = SketchProjection_7.createdFeature()
+SketchLine_41.setName("SketchLine_21")
+SketchLine_41.result().setName("SketchLine_21")
+SketchConstraintCoincidence_58 = Sketch_4.setCoincident(SketchLine_40.startPoint(), SketchLine_41.result())
+SketchConstraintVertical_17 = Sketch_4.setVertical(SketchLine_40.result())
+SketchConstraintLength_10 = Sketch_4.setLength(SketchLine_40.result(), 100)
+SketchCircle_1 = Sketch_4.addCircle(0, 0, 7)
+SketchCircle_1.setAuxiliary(True)
+SketchConstraintCoincidence_59 = Sketch_4.setCoincident(SketchAPI_Point(SketchPoint_5).coordinates(), SketchCircle_1.center())
+SketchConstraintRadius_3 = Sketch_4.setRadius(SketchCircle_1.results()[1], 7)
+SketchLine_42 = Sketch_4.addLine(0, 0, -4.949747468305834, -4.949747468305832)
+SketchLine_42.setName("SketchLine_22")
+SketchLine_42.result().setName("SketchLine_22")
+SketchLine_42.setAuxiliary(True)
+SketchConstraintCoincidence_60 = Sketch_4.setCoincident(SketchAPI_Point(SketchPoint_5).coordinates(), SketchLine_42.startPoint())
+SketchConstraintCoincidence_61 = Sketch_4.setCoincident(SketchLine_42.endPoint(), SketchCircle_1.results()[1])
+SketchConstraintAngle_5 = Sketch_4.setAngleComplementary(SketchLine_42.result(), SketchLine_39.result(), 45)
+SketchLine_43 = Sketch_4.addLine(0, -7, -4.949747468305834, -4.949747468305832)
+SketchLine_43.setName("SketchLine_23")
+SketchLine_43.result().setName("SketchLine_23")
+SketchConstraintCoincidence_62 = Sketch_4.setCoincident(SketchLine_43.startPoint(), SketchLine_41.result())
+SketchConstraintCoincidence_63 = Sketch_4.setCoincident(SketchLine_42.endPoint(), SketchLine_43.endPoint())
+SketchLine_44 = Sketch_4.addLine(-4.949747468305834, -4.949747468305832, -7, 0)
+SketchLine_44.setName("SketchLine_24")
+SketchLine_44.result().setName("SketchLine_24")
+SketchConstraintCoincidence_64 = Sketch_4.setCoincident(SketchLine_42.endPoint(), SketchLine_44.startPoint())
+SketchConstraintCoincidence_65 = Sketch_4.setCoincident(SketchLine_44.endPoint(), SketchLine_39.result())
+SketchLine_45 = Sketch_4.addLine(-4.949747468305834, -4.949747468305832, -33.23401871576774, -33.23401871576773)
+SketchLine_45.setName("SketchLine_25")
+SketchLine_45.result().setName("SketchLine_25")
+SketchConstraintCoincidence_66 = Sketch_4.setCoincident(SketchLine_42.endPoint(), SketchLine_45.startPoint())
+SketchConstraintCollinear_1 = Sketch_4.setCollinear(SketchLine_45.result(), SketchLine_42.result())
+SketchConstraintCoincidence_67 = Sketch_4.setCoincident(SketchLine_43.startPoint(), SketchCircle_1.results()[1])
+SketchConstraintCoincidence_68 = Sketch_4.setCoincident(SketchLine_44.endPoint(), SketchCircle_1.results()[1])
+SketchConstraintLength_11 = Sketch_4.setLength(SketchLine_45.result(), 40)
+SketchMultiRotation_1_objects = [SketchLine_43.result(), SketchLine_45.result(), SketchLine_44.result()]
+SketchMultiRotation_1 = Sketch_4.addRotation(SketchMultiRotation_1_objects, SketchAPI_Line(SketchLine_41).startPoint(), 90, 4)
+[SketchLine_46, SketchLine_47, SketchLine_48, SketchLine_49, SketchLine_50, SketchLine_51, SketchLine_52, SketchLine_53, SketchLine_54] = SketchMultiRotation_1.rotated()
+SketchLine_54.setName("SketchLine_34")
+SketchLine_54.result().setName("SketchLine_34")
+SketchLine_53.setName("SketchLine_33")
+SketchLine_53.result().setName("SketchLine_33")
+SketchLine_52.setName("SketchLine_28")
+SketchLine_52.result().setName("SketchLine_28")
+SketchLine_51.setName("SketchLine_32")
+SketchLine_51.result().setName("SketchLine_32")
+SketchLine_50.setName("SketchLine_31")
+SketchLine_50.result().setName("SketchLine_31")
+SketchLine_49.setName("SketchLine_27")
+SketchLine_49.result().setName("SketchLine_27")
+SketchLine_48.setName("SketchLine_30")
+SketchLine_48.result().setName("SketchLine_30")
+SketchLine_47.setName("SketchLine_29")
+SketchLine_47.result().setName("SketchLine_29")
+SketchLine_46.setName("SketchLine_26")
+SketchLine_46.result().setName("SketchLine_26")
+model.do()
+Edge_1_objects = [model.selection("EDGE", "Sketch_2/SketchLine_27"), model.selection("EDGE", "Sketch_2/SketchLine_26"), model.selection("EDGE", "Sketch_2/SketchLine_28"), model.selection("EDGE", "Sketch_2/SketchLine_19"), model.selection("EDGE", "Sketch_2/SketchLine_25"), model.selection("EDGE", "Sketch_2/SketchLine_23"), model.selection("EDGE", "Sketch_2/SketchLine_24"), model.selection("EDGE", "Sketch_2/SketchLine_30"), model.selection("EDGE", "Sketch_2/SketchLine_34"), model.selection("EDGE", "Sketch_2/SketchLine_29"), model.selection("EDGE", "Sketch_2/SketchLine_33"), model.selection("EDGE", "Sketch_2/SketchLine_31"), model.selection("EDGE", "Sketch_2/SketchLine_20"), model.selection("EDGE", "Sketch_2/SketchLine_32")]
+Edge_1 = model.addEdge(Part_2_doc, Edge_1_objects)
+Extrusion_1_objects = [model.selection("EDGE", "Edge_1_1"), model.selection("EDGE", "Edge_1_2"), model.selection("EDGE", "Edge_1_3"), model.selection("EDGE", "Edge_1_4"), model.selection("EDGE", "Edge_1_5"), model.selection("EDGE", "Edge_1_6"), model.selection("EDGE", "Edge_1_7"), model.selection("EDGE", "Edge_1_8"), model.selection("EDGE", "Edge_1_9"), model.selection("EDGE", "Edge_1_10"), model.selection("EDGE", "Edge_1_11"), model.selection("EDGE", "Edge_1_12"), model.selection("EDGE", "Edge_1_13"), model.selection("EDGE", "Edge_1_14")]
+Extrusion_1 = model.addExtrusion(Part_2_doc, Extrusion_1_objects, model.selection("EDGE", "PartSet/OX"), 300, 0)
+Fill_1_objects_2 = [model.selection("FACE", "Extrusion_1_1"), model.selection("FACE", "Extrusion_1_2"), model.selection("FACE", "Extrusion_1_3"), model.selection("FACE", "Extrusion_1_4"), model.selection("FACE", "Extrusion_1_5"), model.selection("FACE", "Extrusion_1_6"), model.selection("FACE", "Extrusion_1_7"), model.selection("FACE", "Extrusion_1_8"), model.selection("FACE", "Extrusion_1_9"), model.selection("FACE", "Extrusion_1_10"), model.selection("FACE", "Extrusion_1_11"), model.selection("FACE", "Extrusion_1_12"), model.selection("FACE", "Extrusion_1_13"), model.selection("FACE", "Extrusion_1_14")]
+Fill_1 = model.addFill(Part_2_doc, [model.selection("COMPSOLID", "Revolution_1_1")], Fill_1_objects_2)
+Group_1_objects = [model.selection("SOLID", "Fill_1_1_25"), model.selection("SOLID", "Fill_1_1_28"), model.selection("SOLID", "Fill_1_1_26"), model.selection("SOLID", "Fill_1_1_27"), model.selection("SOLID", "Fill_1_1_31"), model.selection("SOLID", "Fill_1_1_35"), model.selection("SOLID", "Fill_1_1_36"), model.selection("SOLID", "Fill_1_1_32"), model.selection("SOLID", "Fill_1_1_34"), model.selection("SOLID", "Fill_1_1_30"), model.selection("SOLID", "Fill_1_1_33"), model.selection("SOLID", "Fill_1_1_29")]
+Group_1 = model.addGroup(Part_2_doc, Group_1_objects)
+Group_1.setName("CORPS")
+Group_1.result().setName("CORPS")
+Group_2_objects = [model.selection("SOLID", "Fill_1_1_41"), model.selection("SOLID", "Fill_1_1_49"), model.selection("SOLID", "Fill_1_1_69"), model.selection("SOLID", "Fill_1_1_71"), model.selection("SOLID", "Fill_1_1_51"), model.selection("SOLID", "Fill_1_1_43"), model.selection("SOLID", "Fill_1_1_44"), model.selection("SOLID", "Fill_1_1_67"), model.selection("SOLID", "Fill_1_1_39"), model.selection("SOLID", "Fill_1_1_47"), model.selection("SOLID", "Fill_1_1_45"), model.selection("SOLID", "Fill_1_1_37"), model.selection("SOLID", "Fill_1_1_65"), model.selection("SOLID", "Fill_1_1_66"), model.selection("SOLID", "Fill_1_1_38"), model.selection("SOLID", "Fill_1_1_46"), model.selection("SOLID", "Fill_1_1_48"), model.selection("SOLID", "Fill_1_1_40"), model.selection("SOLID", "Fill_1_1_68"), model.selection("SOLID", "Fill_1_1_42"), model.selection("SOLID", "Fill_1_1_70"), model.selection("SOLID", "Fill_1_1_50"), model.selection("SOLID", "Fill_1_1_52"), model.selection("SOLID", "Fill_1_1_72"), model.selection("SOLID", "Fill_1_1_63"), model.selection("SOLID", "Fill_1_1_64"), model.selection("SOLID", "Fill_1_1_61"), model.selection("SOLID", "Fill_1_1_62"), model.selection("SOLID", "Fill_1_1_58"), model.selection("SOLID", "Fill_1_1_57"), model.selection("SOLID", "Fill_1_1_54"), model.selection("SOLID", "Fill_1_1_53"), model.selection("SOLID", "Fill_1_1_55"), model.selection("SOLID", "Fill_1_1_56"), model.selection("SOLID", "Fill_1_1_60"), model.selection("SOLID", "Fill_1_1_59")]
+Group_2 = model.addGroup(Part_2_doc, Group_2_objects)
+Group_2.setName("TETE")
+Group_2.result().setName("TETE")
+Group_3_objects = [model.selection("SOLID", "Fill_1_1_2"), model.selection("SOLID", "Fill_1_1_1"), model.selection("SOLID", "Fill_1_1_5"), model.selection("SOLID", "Fill_1_1_9"), model.selection("SOLID", "Fill_1_1_13"), model.selection("SOLID", "Fill_1_1_14"), model.selection("SOLID", "Fill_1_1_15"), model.selection("SOLID", "Fill_1_1_19"), model.selection("SOLID", "Fill_1_1_11"), model.selection("SOLID", "Fill_1_1_12"), model.selection("SOLID", "Fill_1_1_24"), model.selection("SOLID", "Fill_1_1_23"), model.selection("SOLID", "Fill_1_1_16"), model.selection("SOLID", "Fill_1_1_8"), model.selection("SOLID", "Fill_1_1_20"), model.selection("SOLID", "Fill_1_1_4"), model.selection("SOLID", "Fill_1_1_3"), model.selection("SOLID", "Fill_1_1_7"), model.selection("SOLID", "Fill_1_1_10"), model.selection("SOLID", "Fill_1_1_6")]
+Group_3 = model.addGroup(Part_2_doc, Group_3_objects)
+Group_3.setName("PIED")
+Group_3.result().setName("PIED")
+Group_4 = model.addGroup(Part_2_doc, [model.selection("EDGE", "Fill_1_1_36/Generated_Edge&Sketch_2/SketchLine_31&Sketch_1/SketchLine_7")])
+Group_4.setName("corps_hauteur")
+Group_4.result().setName("corps_hauteur")
+Group_5 = model.addGroup(Part_2_doc, [model.selection("EDGE", "Fill_1_1_11/Generated_Edge&Sketch_2/SketchLine_31&Sketch_1/SketchLine_5")])
+Group_5.setName("pied_hauteur")
+Group_5.result().setName("pied_hauteur")
+Group_6 = model.addGroup(Part_2_doc, [model.selection("EDGE", "Fill_1_1_24/Generated_Edge&Sketch_2/SketchLine_31&Sketch_1/SketchLine_6")])
+Group_6.setName("chanfrein")
+Group_6.result().setName("chanfrein")
+Group_7 = model.addGroup(Part_2_doc, [model.selection("EDGE", "Fill_1_1_72/Generated_Edge&Sketch_2/SketchLine_31&Sketch_1/SketchArc_1_2")])
+Group_7.setName("filet")
+Group_7.result().setName("filet")
+Group_8 = model.addGroup(Part_2_doc, [model.selection("EDGE", "Fill_1_1_42/Generated_Edge&Sketch_2/SketchLine_31&Sketch_1/SketchLine_9")])
+Group_8.setName("tete_bas")
+Group_8.result().setName("tete_bas")
+Group_9_objects = [model.selection("FACE", "Fill_1_1_12/Modified_Face&Sketch_1/SketchLine_5"), model.selection("FACE", "Fill_1_1_11/Modified_Face&Sketch_1/SketchLine_5"), model.selection("FACE", "Fill_1_1_9/Modified_Face&Sketch_1/SketchLine_5"), model.selection("FACE", "Fill_1_1_8/Modified_Face&Sketch_1/SketchLine_5"), model.selection("FACE", "Fill_1_1_4/Modified_Face&Sketch_1/SketchLine_5"), model.selection("FACE", "Fill_1_1_1/Modified_Face&Sketch_1/SketchLine_5"), model.selection("FACE", "Fill_1_1_2/Modified_Face&Sketch_1/SketchLine_5"), model.selection("FACE", "Fill_1_1_5/Modified_Face&Sketch_1/SketchLine_5")]
+Group_9 = model.addGroup(Part_2_doc, Group_9_objects)
+Group_9.setName("ADH_PIEDS")
+Group_9.result().setName("ADH_PIEDS")
+Group_10_objects = [model.selection("FACE", "Fill_1_1_13/Modified_Face&Sketch_1/SketchLine_6"), model.selection("FACE", "Fill_1_1_14/Modified_Face&Sketch_1/SketchLine_6"), model.selection("FACE", "Fill_1_1_25/Modified_Face&Sketch_1/SketchLine_7"), model.selection("FACE", "Fill_1_1_26/Modified_Face&Sketch_1/SketchLine_7"), model.selection("FACE", "Fill_1_1_15/Modified_Face&Sketch_1/SketchLine_6"), model.selection("FACE", "Fill_1_1_27/Modified_Face&Sketch_1/SketchLine_7"), model.selection("FACE", "Fill_1_1_19/Modified_Face&Sketch_1/SketchLine_6"), model.selection("FACE", "Fill_1_1_31/Modified_Face&Sketch_1/SketchLine_7"), model.selection("FACE", "Fill_1_1_23/Modified_Face&Sketch_1/SketchLine_6"), model.selection("FACE", "Fill_1_1_35/Modified_Face&Sketch_1/SketchLine_7"), model.selection("FACE", "Fill_1_1_24/Modified_Face&Sketch_1/SketchLine_6"), model.selection("FACE", "Fill_1_1_36/Modified_Face&Sketch_1/SketchLine_7"), model.selection("FACE", "Fill_1_1_32/Modified_Face&Sketch_1/SketchLine_7"), model.selection("FACE", "Fill_1_1_20/Modified_Face&Sketch_1/SketchLine_6"), model.selection("FACE", "Fill_1_1_16/Modified_Face&Sketch_1/SketchLine_6"), model.selection("FACE", "Fill_1_1_28/Modified_Face&Sketch_1/SketchLine_7"), model.selection("FACE", "Fill_1_1_70/Modified_Face&Sketch_1/SketchArc_1_2"), model.selection("FACE", "Fill_1_1_42/Modified_Face&Sketch_1/SketchLine_8"), model.selection("FACE", "Fill_1_1_68/Modified_Face&Sketch_1/SketchArc_1_2"), model.selection("FACE", "Fill_1_1_40/Modified_Face&Sketch_1/SketchLine_8"), model.selection("FACE", "Fill_1_1_66/Modified_Face&Sketch_1/SketchArc_1_2"), model.selection("FACE", "Fill_1_1_38/Modified_Face&Sketch_1/SketchLine_8"), model.selection("FACE", "Fill_1_1_37/Modified_Face&Sketch_1/SketchLine_8"), model.selection("FACE", "Fill_1_1_65/Modified_Face&Sketch_1/SketchArc_1_2"), model.selection("FACE", "Fill_1_1_39/Modified_Face&Sketch_1/SketchLine_8"), model.selection("FACE", "Fill_1_1_67/Modified_Face&Sketch_1/SketchArc_1_2"), model.selection("FACE", "Fill_1_1_69/Modified_Face&Sketch_1/SketchArc_1_2"), model.selection("FACE", "Fill_1_1_41/Modified_Face&Sketch_1/SketchLine_8"), model.selection("FACE", "Fill_1_1_43/Modified_Face&Sketch_1/SketchLine_8"), model.selection("FACE", "Fill_1_1_71/Modified_Face&Sketch_1/SketchArc_1_2"), model.selection("FACE", "Fill_1_1_44/Modified_Face&Sketch_1/SketchLine_8"), model.selection("FACE", "Fill_1_1_72/Modified_Face&Sketch_1/SketchArc_1_2"), model.selection("FACE", "Fill_1_1_52/Modified_Face&Sketch_1/SketchLine_9"), model.selection("FACE", "Fill_1_1_44/Modified_Face&Sketch_1/SketchLine_9"), model.selection("FACE", "Fill_1_1_43/Modified_Face&Sketch_1/SketchLine_9"), model.selection("FACE", "Fill_1_1_51/Modified_Face&Sketch_1/SketchLine_9"), model.selection("FACE", "Fill_1_1_50/Modified_Face&Sketch_1/SketchLine_9"), model.selection("FACE", "Fill_1_1_42/Modified_Face&Sketch_1/SketchLine_9"), model.selection("FACE", "Fill_1_1_40/Modified_Face&Sketch_1/SketchLine_9"), model.selection("FACE", "Fill_1_1_48/Modified_Face&Sketch_1/SketchLine_9"), model.selection("FACE", "Fill_1_1_46/Modified_Face&Sketch_1/SketchLine_9"), model.selection("FACE", "Fill_1_1_38/Modified_Face&Sketch_1/SketchLine_9"), model.selection("FACE", "Fill_1_1_37/Modified_Face&Sketch_1/SketchLine_9"), model.selection("FACE", "Fill_1_1_45/Modified_Face&Sketch_1/SketchLine_9"), model.selection("FACE", "Fill_1_1_39/Modified_Face&Sketch_1/SketchLine_9"), model.selection("FACE", "Fill_1_1_47/Modified_Face&Sketch_1/SketchLine_9"), model.selection("FACE", "Fill_1_1_49/Modified_Face&Sketch_1/SketchLine_9"), model.selection("FACE", "Fill_1_1_41/Modified_Face&Sketch_1/SketchLine_9")]
+Group_10 = model.addGroup(Part_2_doc, Group_10_objects)
+Group_10.setName("CONTACT_VIS")
+Group_10.result().setName("CONTACT_VIS")
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("COMPSOLID", "Fill_1_1")], 0, 100, 0)
+AngularCopy_1 = model.addMultiRotation(Part_2_doc, [model.selection("COMPSOLID", "Translation_1_1")], model.selection("EDGE", "PartSet/OX"), 4)
+model.do()
+
+# move groups to the end
+Part_2_doc.moveFeature(Group_1.feature(), AngularCopy_1.feature())
+Part_2_doc.moveFeature(Group_2.feature(), Group_1.feature())
+Part_2_doc.moveFeature(Group_3.feature(), Group_2.feature())
+Part_2_doc.moveFeature(Group_4.feature(), Group_3.feature())
+Part_2_doc.moveFeature(Group_5.feature(), Group_4.feature())
+Part_2_doc.moveFeature(Group_6.feature(), Group_5.feature())
+Part_2_doc.moveFeature(Group_7.feature(), Group_6.feature())
+Part_2_doc.moveFeature(Group_8.feature(), Group_7.feature())
+Part_2_doc.moveFeature(Group_9.feature(), Group_8.feature())
+Part_2_doc.moveFeature(Group_10.feature(), Group_9.feature())
+model.end()
+
+from ModelAPI import *
+
+aFactory = ModelAPI_Session.get().validators()
+
+# Check groups
+a = 0
+num_in_groups = [48, 144, 80, 4, 4, 4, 4, 4, 32, 192]
+for i in range(Part_2_doc.size("Groups")):
+  GroupFeature = Part_2_doc.feature(objectToResult(Part_2_doc.object("Groups", i)))
+  assert(aFactory.validate(GroupFeature))
+  assert(GroupFeature.selectionList("group_list").size() == num_in_groups[a])
+  a = a + 1
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/Test2738.py b/src/FeaturesPlugin/Test/Test2738.py
new file mode 100644 (file)
index 0000000..d8f8da2
--- /dev/null
@@ -0,0 +1,75 @@
+## 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>
+##
+
+# -*- coding: utf-8 -*-
+
+from salome.shaper import model
+from GeomAlgoAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "d", "8")
+model.addParameter(Part_1_doc, "nb", "3")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_1.addCircle(-34.12026714434272, 28.71281409244911, 1.619211673722419)
+SketchCircle_2 = Sketch_1.addCircle(-34.12026714434272, 28.71281409244911, 3.180589706721861)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchCircle_1.center(), SketchCircle_2.center())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("WIRE_2", (-35.73947881806514, 28.71281409244911, 0))], model.selection(), 2, -1)
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", (-37.30085685106458, 28.71281409244911, 0))], model.selection(), 5, 0)
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("COMPOUND", "all-in-Extrusion_1"), model.selection("COMPOUND", "all-in-Extrusion_2")])
+Group_1 = model.addGroup(Part_1_doc, [model.selection("SOLID", (-34.12026714434272, 28.71281409244911, 1.5))])
+Group_1.setName("Group_dechets")
+Group_1.result().setName("Group_dechets")
+Group_2 = model.addGroup(Part_1_doc, [model.selection("SOLID", (-34.12026714434272, 28.71281409244911, 2.35984679315518))])
+Group_2.setName("Group_colis")
+Group_2.result().setName("Group_colis")
+LinearCopy_1 = model.addMultiTranslation(Part_1_doc, [model.selection("COMPSOLID", (-34.12026714434272, 28.71281409244911, 2.5))], model.selection("EDGE", "PartSet/OX"), "d", "nb", model.selection("EDGE", "PartSet/OY"), "d", "nb")
+model.do()
+# move groups to the end
+Part_1_doc.moveFeature(Group_1.feature(), LinearCopy_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+model.end()
+
+from ModelAPI import *
+aFactory = ModelAPI_Session.get().validators()
+
+# number of solids should be multiplyed by linear copy
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 9)
+assert(aFactory.validate(Group_1.feature()))
+# checkthat solids in the first group are small, like the origin
+for i in range(9):
+  delta = GeomAlgoAPI_ShapeTools_volume(selectionList.value(i).value()) - 8.236773528312948
+  assert(fabs(delta) < 1.e-5)
+
+# same-plane faces should be merged
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 9)
+assert(aFactory.validate(Group_2.feature()))
+
+# checkthat solids in the secong group are big, like the origin
+for i in range(9):
+  delta = GeomAlgoAPI_ShapeTools_volume(selectionList.value(i).value()) - 150.66735294710597
+  assert(fabs(delta) < 1.e-5)
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/Test2826.py b/src/FeaturesPlugin/Test/Test2826.py
new file mode 100644 (file)
index 0000000..dc1cdd0
--- /dev/null
@@ -0,0 +1,463 @@
+## 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>
+##
+
+# -*- coding: utf-8 -*-
+
+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("XOZ"))
+SketchLine_1 = Sketch_1.addLine(6.188, 9.025, 6.188, -3.45)
+SketchLine_2 = Sketch_1.addLine(6.188, -3.45, 0, -3.45)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(0, -3.45, 0, -6.449999999999999)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(0, -6.449999999999999, 7.782, -6.45)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(7.782, -6.45, 7.782, -3.45)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_1.addLine(7.782, -3.45, 6.538, -3.45)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchLine_7 = Sketch_1.addLine(6.538, -3.45, 6.538, -2.4)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchLine_8 = Sketch_1.addLine(6.538, -2.4, 6.375999999999999, -2.25)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchLine_9 = Sketch_1.addLine(6.375999999999999, -2.25, 6.375999999999999, 9.025)
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchLine_10 = Sketch_1.addLine(6.375999999999999, 9.025, 6.188, 9.025)
+SketchLine_10.setAuxiliary(True)
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint())
+SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_10.endPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_10.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_2.result())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_6.result())
+SketchConstraintHorizontal_4 = Sketch_1.setHorizontal(SketchLine_4.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_5.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_3.result())
+SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_1.result())
+SketchConstraintVertical_4 = Sketch_1.setVertical(SketchLine_9.result())
+SketchConstraintVertical_5 = Sketch_1.setVertical(SketchLine_7.result())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_11 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_11 = Sketch_1.setCoincident(SketchLine_3.startPoint(), SketchLine_11.result())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Line(SketchLine_11).startPoint(), SketchLine_2.result(), 3.45, True)
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_3.result(), 3)
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_12 = SketchProjection_2.createdFeature()
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchLine_1.startPoint(), SketchLine_12.result(), 9.025, True)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_10.result(), 0.188)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_8.endPoint(), SketchLine_7.endPoint(), 0.15)
+SketchConstraintCoincidence_12 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_2.result())
+SketchConstraintDistance_3 = Sketch_1.setDistance(SketchLine_6.endPoint(), SketchLine_1.result(), 0.35, True)
+SketchConstraintDistance_4 = Sketch_1.setDistance(SketchLine_8.endPoint(), SketchLine_12.result(), 2.25, True)
+SketchConstraintDistance_5 = Sketch_1.setDistance(SketchLine_2.startPoint(), SketchLine_11.result(), 6.188, True)
+SketchLine_13 = Sketch_1.addLine(7.032, -4.050000000000001, 5.532, -4.050000000000001)
+SketchLine_14 = Sketch_1.addLine(5.532, -4.050000000000001, 5.532, -5.850000000000001)
+SketchLine_15 = Sketch_1.addLine(5.532, -5.850000000000001, 7.032, -5.850000000000001)
+SketchLine_16 = Sketch_1.addLine(7.032, -5.850000000000001, 7.032, -4.050000000000001)
+SketchConstraintCoincidence_13 = Sketch_1.setCoincident(SketchLine_16.endPoint(), SketchLine_13.startPoint())
+SketchConstraintCoincidence_14 = Sketch_1.setCoincident(SketchLine_13.endPoint(), SketchLine_14.startPoint())
+SketchConstraintCoincidence_15 = Sketch_1.setCoincident(SketchLine_14.endPoint(), SketchLine_15.startPoint())
+SketchConstraintCoincidence_16 = Sketch_1.setCoincident(SketchLine_15.endPoint(), SketchLine_16.startPoint())
+SketchConstraintHorizontal_5 = Sketch_1.setHorizontal(SketchLine_13.result())
+SketchConstraintVertical_6 = Sketch_1.setVertical(SketchLine_14.result())
+SketchConstraintHorizontal_6 = Sketch_1.setHorizontal(SketchLine_15.result())
+SketchConstraintVertical_7 = Sketch_1.setVertical(SketchLine_16.result())
+SketchLine_17 = Sketch_1.addLine(6.282, 9.025000000000013, 6.282, -4.050000000000002)
+SketchLine_17.setAuxiliary(True)
+SketchConstraintCoincidence_17 = Sketch_1.setCoincident(SketchLine_17.startPoint(), SketchLine_10.result())
+SketchConstraintCoincidence_18 = Sketch_1.setCoincident(SketchLine_17.endPoint(), SketchLine_13.result())
+SketchConstraintVertical_8 = Sketch_1.setVertical(SketchLine_17.result())
+SketchConstraintMiddle_1 = Sketch_1.setMiddlePoint(SketchLine_17.startPoint(), SketchLine_10.result())
+SketchConstraintMiddle_2 = Sketch_1.setMiddlePoint(SketchLine_17.endPoint(), SketchLine_13.result())
+SketchConstraintLength_3 = Sketch_1.setLength(SketchLine_13.result(), 1.5)
+SketchConstraintLength_4 = Sketch_1.setLength(SketchLine_16.result(), 1.8)
+SketchConstraintDistance_6 = Sketch_1.setDistance(SketchLine_17.endPoint(), SketchLine_5.result(), 1.5, True)
+SketchConstraintDistance_7 = Sketch_1.setDistance(SketchLine_14.startPoint(), SketchLine_2.result(), 0.6, True)
+SketchLine_18 = Sketch_1.addLine(6.375999999999999, 9.025, 6.537999999999999, 9.186999999999999)
+SketchConstraintCoincidence_19 = Sketch_1.setCoincident(SketchLine_9.endPoint(), SketchLine_18.startPoint())
+SketchLine_19 = Sketch_1.addLine(6.537999999999999, 9.186999999999999, 6.537999999999999, 10.256)
+SketchConstraintCoincidence_20 = Sketch_1.setCoincident(SketchLine_18.endPoint(), SketchLine_19.startPoint())
+SketchLine_20 = Sketch_1.addLine(6.537999999999999, 10.256, 6.188, 10.256)
+SketchConstraintCoincidence_21 = Sketch_1.setCoincident(SketchLine_19.endPoint(), SketchLine_20.startPoint())
+SketchLine_21 = Sketch_1.addLine(6.188, 10.256, 4.938, 10.97786688777512)
+SketchConstraintCoincidence_22 = Sketch_1.setCoincident(SketchLine_20.endPoint(), SketchLine_21.startPoint())
+SketchLine_22 = Sketch_1.addLine(6.188, 9.025, 6.082, 9.532)
+SketchConstraintCoincidence_23 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_22.startPoint())
+SketchArc_1 = Sketch_1.addArc(4.793854309433998, 9.262673655435936, 6.082, 9.532, 5.676829966640704, 10.23848613167324, False)
+SketchConstraintCoincidence_24 = Sketch_1.setCoincident(SketchLine_22.endPoint(), SketchArc_1.startPoint())
+SketchLine_23 = Sketch_1.addLine(5.676829966640704, 10.23848613167324, 5.417460848824595, 10.45671600291324)
+SketchConstraintCoincidence_25 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_23.startPoint())
+SketchLine_24 = Sketch_1.addLine(5.417460848824595, 10.45671600291324, 5.143396378647488, 10.65615482129427)
+SketchConstraintCoincidence_26 = Sketch_1.setCoincident(SketchLine_23.endPoint(), SketchLine_24.startPoint())
+SketchLine_25 = Sketch_1.addLine(5.143396378647488, 10.65615482129427, 4.856000000000001, 10.83583872155447)
+SketchConstraintCoincidence_27 = Sketch_1.setCoincident(SketchLine_24.endPoint(), SketchLine_25.startPoint())
+SketchArc_2 = Sketch_1.addArc(0, 2.425, 4.856000000000001, 10.83583872155447, 0, 12.137, False)
+SketchConstraintCoincidence_28 = Sketch_1.setCoincident(SketchLine_25.endPoint(), SketchArc_2.startPoint())
+SketchArc_3 = Sketch_1.addArc(0, 2.425, 4.938, 10.97786688777512, 0, 12.301, False)
+SketchConstraintCoincidence_29 = Sketch_1.setCoincident(SketchLine_21.endPoint(), SketchArc_3.startPoint())
+SketchConstraintCoincidence_30 = Sketch_1.setCoincident(SketchArc_3.center(), SketchArc_2.center())
+SketchConstraintCoincidence_31 = Sketch_1.setCoincident(SketchArc_2.center(), SketchLine_11.result())
+SketchArc_4 = Sketch_1.addArc(0, 2.425, 0, 12.219, 6.538, 9.717255618119815, True)
+SketchArc_4.setAuxiliary(True)
+SketchConstraintCoincidence_32 = Sketch_1.setCoincident(SketchArc_2.center(), SketchArc_4.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_4.results()[1], 9.794)
+SketchLine_26 = Sketch_1.addLine(0, 12.301, 0, 12.137)
+SketchConstraintCoincidence_33 = Sketch_1.setCoincident(SketchArc_3.endPoint(), SketchLine_26.startPoint())
+SketchConstraintCoincidence_34 = Sketch_1.setCoincident(SketchArc_2.endPoint(), SketchLine_26.endPoint())
+SketchConstraintCoincidence_35 = Sketch_1.setCoincident(SketchLine_26.startPoint(), SketchLine_11.result())
+SketchConstraintCoincidence_36 = Sketch_1.setCoincident(SketchLine_26.endPoint(), SketchArc_2.endPoint())
+SketchConstraintCoincidence_37 = Sketch_1.setCoincident(SketchLine_11.result(), SketchLine_26.endPoint())
+SketchConstraintCoincidence_38 = Sketch_1.setCoincident(SketchArc_4.startPoint(), SketchLine_26.result())
+SketchConstraintMiddle_3 = Sketch_1.setMiddlePoint(SketchArc_4.startPoint(), SketchLine_26.result())
+SketchConstraintDistance_8 = Sketch_1.setDistance(SketchLine_26.startPoint(), SketchArc_4.startPoint(), 0.082, True)
+SketchConstraintHorizontal_7 = Sketch_1.setHorizontal(SketchLine_20.result())
+SketchConstraintVertical_9 = Sketch_1.setVertical(SketchLine_19.result())
+SketchConstraintDistance_9 = Sketch_1.setDistance(SketchArc_3.center(), SketchLine_12.result(), 2.425, True)
+SketchLine_27 = Sketch_1.addLine(4.856000000000001, 10.83583872155447, 0, 2.425)
+SketchLine_27.setAuxiliary(True)
+SketchConstraintCoincidence_39 = Sketch_1.setCoincident(SketchLine_25.endPoint(), SketchLine_27.startPoint())
+SketchConstraintCoincidence_40 = Sketch_1.setCoincident(SketchArc_2.center(), SketchLine_27.endPoint())
+SketchLine_28 = Sketch_1.addLine(5.143396378647488, 10.65615482129427, 0, 2.425)
+SketchLine_28.setAuxiliary(True)
+SketchConstraintCoincidence_41 = Sketch_1.setCoincident(SketchLine_24.endPoint(), SketchLine_28.startPoint())
+SketchConstraintCoincidence_42 = Sketch_1.setCoincident(SketchArc_2.center(), SketchLine_28.endPoint())
+SketchLine_29 = Sketch_1.addLine(0, 2.425, 5.417460848824595, 10.45671600291324)
+SketchLine_29.setAuxiliary(True)
+SketchConstraintCoincidence_43 = Sketch_1.setCoincident(SketchArc_2.center(), SketchLine_29.startPoint())
+SketchConstraintCoincidence_44 = Sketch_1.setCoincident(SketchLine_23.endPoint(), SketchLine_29.endPoint())
+SketchLine_30 = Sketch_1.addLine(5.676829966640704, 10.23848613167324, 0, 2.425)
+SketchLine_30.setAuxiliary(True)
+SketchConstraintCoincidence_45 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_30.startPoint())
+SketchConstraintCoincidence_46 = Sketch_1.setCoincident(SketchArc_2.center(), SketchLine_30.endPoint())
+SketchConstraintAngle_1 = Sketch_1.setAngle(SketchLine_27.result(), SketchLine_11.result(), 29.99999999999999)
+SketchConstraintAngle_2 = Sketch_1.setAngle(SketchLine_28.result(), SketchLine_11.result(), 32.00000000000001)
+SketchConstraintAngle_3 = Sketch_1.setAngle(SketchLine_29.result(), SketchLine_11.result(), 34.00000000000001)
+SketchConstraintAngle_4 = Sketch_1.setAngle(SketchLine_30.result(), SketchLine_11.result(), 36.00000000000001)
+SketchConstraintAngle_5 = Sketch_1.setAngleComplementary(SketchLine_18.result(), SketchLine_10.result(), 44.99999999999972)
+SketchConstraintLength_5 = Sketch_1.setLength(SketchLine_20.result(), 0.35)
+SketchConstraintDistance_10 = Sketch_1.setDistance(SketchLine_20.startPoint(), SketchLine_12.result(), 10.256, True)
+SketchConstraintDistance_10.setName("SketchConstraintDistance_13")
+SketchConstraintDistance_11 = Sketch_1.setDistance(SketchLine_22.endPoint(), SketchLine_1.result(), 0.106, True)
+SketchConstraintDistance_11.setName("SketchConstraintDistance_14")
+SketchConstraintDistance_12 = Sketch_1.setDistance(SketchLine_22.endPoint(), SketchLine_12.result(), 9.532, True)
+SketchConstraintDistance_12.setName("SketchConstraintDistance_15")
+SketchLine_31 = Sketch_1.addLine(4.856000000000001, 10.83583872155447, 4.938, 10.97786688777512)
+SketchLine_31.setAuxiliary(True)
+SketchConstraintCoincidence_47 = Sketch_1.setCoincident(SketchLine_25.endPoint(), SketchLine_31.startPoint())
+SketchConstraintCoincidence_47.setName("SketchConstraintCoincidence_48")
+SketchConstraintCoincidence_48 = Sketch_1.setCoincident(SketchLine_21.endPoint(), SketchLine_31.endPoint())
+SketchConstraintCoincidence_48.setName("SketchConstraintCoincidence_49")
+SketchConstraintCollinear_1 = Sketch_1.setCollinear(SketchLine_31.result(), SketchLine_27.result())
+SketchConstraintCoincidence_49 = Sketch_1.setCoincident(SketchArc_4.endPoint(), SketchLine_19.result())
+SketchConstraintCoincidence_49.setName("SketchConstraintCoincidence_50")
+SketchConstraintRadius_2 = Sketch_1.setRadius(SketchArc_1.results()[1], 1.316)
+SketchLine_32 = Sketch_1.addLine(5.143396378647488, 10.65615482129427, 5.236653048654413, 10.80539669036974)
+SketchLine_32.setAuxiliary(True)
+SketchConstraintCoincidence_50 = Sketch_1.setCoincident(SketchLine_24.endPoint(), SketchLine_32.startPoint())
+SketchConstraintCoincidence_50.setName("SketchConstraintCoincidence_51")
+SketchConstraintCoincidence_51 = Sketch_1.setCoincident(SketchLine_32.endPoint(), SketchLine_21.result())
+SketchConstraintCoincidence_51.setName("SketchConstraintCoincidence_52")
+SketchLine_33 = Sketch_1.addLine(5.417460848824595, 10.45671600291324, 5.536033128724348, 10.63250663704018)
+SketchLine_33.setAuxiliary(True)
+SketchConstraintCoincidence_52 = Sketch_1.setCoincident(SketchLine_23.endPoint(), SketchLine_33.startPoint())
+SketchConstraintCoincidence_52.setName("SketchConstraintCoincidence_53")
+SketchConstraintCoincidence_53 = Sketch_1.setCoincident(SketchLine_33.endPoint(), SketchLine_21.result())
+SketchConstraintCoincidence_53.setName("SketchConstraintCoincidence_54")
+SketchLine_34 = Sketch_1.addLine(5.676829966640704, 10.23848613167324, 5.836876630976977, 10.4587714668974)
+SketchLine_34.setAuxiliary(True)
+SketchConstraintCoincidence_54 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_34.startPoint())
+SketchConstraintCoincidence_54.setName("SketchConstraintCoincidence_55")
+SketchConstraintCoincidence_55 = Sketch_1.setCoincident(SketchLine_34.endPoint(), SketchLine_21.result())
+SketchConstraintCoincidence_55.setName("SketchConstraintCoincidence_56")
+SketchConstraintCollinear_2 = Sketch_1.setCollinear(SketchLine_32.result(), SketchLine_28.result())
+SketchConstraintCollinear_3 = Sketch_1.setCollinear(SketchLine_33.result(), SketchLine_29.result())
+SketchConstraintCollinear_4 = Sketch_1.setCollinear(SketchLine_34.result(), SketchLine_30.result())
+SketchPoint_1 = Sketch_1.addPoint(5.190029273900029, 10.73078305375602)
+SketchConstraintCoincidence_56 = Sketch_1.setCoincident(SketchPoint_1.coordinates(), SketchArc_4.results()[1])
+SketchConstraintCoincidence_56.setName("SketchConstraintCoincidence_57")
+SketchConstraintCoincidence_57 = Sketch_1.setCoincident(SketchPoint_1.coordinates(), SketchLine_32.result())
+SketchConstraintCoincidence_57.setName("SketchConstraintCoincidence_58")
+SketchConstraintDistance_13 = Sketch_1.setDistance(SketchLine_25.startPoint(), SketchPoint_1.coordinates(), 0.08799999999999999, True)
+SketchConstraintDistance_13.setName("SketchConstraintDistance_16")
+SketchPoint_2 = Sketch_1.addPoint(5.476735296592504, 10.54459398560407)
+SketchConstraintCoincidence_58 = Sketch_1.setCoincident(SketchPoint_2.coordinates(), SketchArc_4.results()[1])
+SketchConstraintCoincidence_58.setName("SketchConstraintCoincidence_59")
+SketchConstraintCoincidence_59 = Sketch_1.setCoincident(SketchLine_33.result(), SketchPoint_2.coordinates())
+SketchConstraintCoincidence_59.setName("SketchConstraintCoincidence_60")
+SketchConstraintDistance_14 = Sketch_1.setDistance(SketchLine_24.startPoint(), SketchPoint_2.coordinates(), 0.106, True)
+SketchConstraintDistance_14.setName("SketchConstraintDistance_17")
+SketchPoint_3 = Sketch_1.addPoint(5.756768760952494, 10.34851244290823)
+SketchConstraintCoincidence_60 = Sketch_1.setCoincident(SketchPoint_3.coordinates(), SketchArc_4.results()[1])
+SketchConstraintCoincidence_60.setName("SketchConstraintCoincidence_61")
+SketchConstraintCoincidence_61 = Sketch_1.setCoincident(SketchPoint_3.coordinates(), SketchLine_34.result())
+SketchConstraintCoincidence_61.setName("SketchConstraintCoincidence_62")
+SketchConstraintDistance_15 = Sketch_1.setDistance(SketchArc_1.endPoint(), SketchPoint_3.coordinates(), 0.136, True)
+SketchConstraintDistance_15.setName("SketchConstraintDistance_18")
+SketchConstraintCoincidence_62 = Sketch_1.setCoincident(SketchLine_21.startPoint(), SketchLine_1.result())
+SketchConstraintCoincidence_62.setName("SketchConstraintCoincidence_63")
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_6f-SketchLine_7f-SketchLine_8f-SketchLine_9f-SketchLine_18f-SketchLine_19f-SketchLine_20f-SketchLine_21f-SketchArc_3_2f-SketchLine_26f-SketchArc_2_2r-SketchLine_25r-SketchLine_24r-SketchLine_23r-SketchArc_1_2r-SketchLine_22r-SketchLine_16r-SketchLine_15r-SketchLine_14r-SketchLine_13r")], model.selection("EDGE", "PartSet/OZ"), 360, 0)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Revolution_1_1/Generated_Face&Sketch_1/SketchLine_4")])
+Group_1.setName("Base")
+Group_1.result().setName("Base")
+Group_2_objects = [model.selection("FACE", "Revolution_1_1/Generated_Face&Sketch_1/SketchLine_2"), model.selection("FACE", "Revolution_1_1/Generated_Face&Sketch_1/SketchLine_1"), model.selection("FACE", "Revolution_1_1/Generated_Face&Sketch_1/SketchLine_24"), model.selection("FACE", "Revolution_1_1/Generated_Face&Sketch_1/SketchArc_2_2"), model.selection("FACE", "Revolution_1_1/Generated_Face&Sketch_1/SketchLine_25"), model.selection("FACE", "Revolution_1_1/Generated_Face&Sketch_1/SketchLine_23"), model.selection("FACE", "Revolution_1_1/Generated_Face&Sketch_1/SketchLine_22"), model.selection("FACE", "Revolution_1_1/Generated_Face&Sketch_1/SketchArc_1_2")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Group_2.setName("Faces_int")
+Group_2.result().setName("Faces_int")
+Group_3_objects = [model.selection("FACE", "Revolution_1_1/Generated_Face&Sketch_1/SketchLine_16"), model.selection("FACE", "Revolution_1_1/Generated_Face&Sketch_1/SketchLine_13"), model.selection("FACE", "Revolution_1_1/Generated_Face&Sketch_1/SketchLine_14"), model.selection("FACE", "Revolution_1_1/Generated_Face&Sketch_1/SketchLine_15")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+Group_3.setName("Faces_gallerie")
+Group_3.result().setName("Faces_gallerie")
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_35 = Sketch_2.addLine(3.397674805046317, 12.11397308570391, 3.082152448528626, 11.21424138021434)
+SketchLine_36 = Sketch_2.addLine(3.241000000000001, 12.09482302308413, 3.241000000000001, 11.06850194037818)
+SketchLine_36.setAuxiliary(True)
+SketchConstraintVertical_10 = Sketch_2.setVertical(SketchLine_36.result())
+SketchPoint_4 = Sketch_2.addPoint(3.241, 11.66720509403099)
+SketchConstraintCoincidence_63 = Sketch_2.setCoincident(SketchPoint_4.coordinates(), SketchLine_35.result())
+SketchConstraintCoincidence_63.setName("SketchConstraintCoincidence_64")
+SketchConstraintCoincidence_64 = Sketch_2.setCoincident(SketchLine_36.result(), SketchPoint_4.coordinates())
+SketchConstraintCoincidence_64.setName("SketchConstraintCoincidence_65")
+SketchProjection_3 = Sketch_2.addProjection(model.selection("EDGE", "Sketch_1/SketchArc_4_2"), False)
+SketchArc_5 = SketchProjection_3.createdFeature()
+SketchConstraintCoincidence_65 = Sketch_2.setCoincident(SketchPoint_4.coordinates(), SketchArc_5.results()[1])
+SketchConstraintCoincidence_65.setName("SketchConstraintCoincidence_66")
+SketchConstraintAngle_6 = Sketch_2.setAngleComplementary(SketchLine_35.result(), SketchLine_36.result(), 160.675)
+SketchProjection_4 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_37 = SketchProjection_4.createdFeature()
+SketchConstraintDistance_16 = Sketch_2.setDistance(SketchPoint_4.coordinates(), SketchLine_37.result(), 3.241, True)
+SketchConstraintDistance_16.setName("SketchConstraintDistance_19")
+SketchLine_38 = Sketch_2.addLine(3.911629569238839, 11.53981731861503, 3.828898026216406, 11.30390315670624)
+SketchLine_39 = Sketch_2.addLine(3.828898026216406, 11.30390315670624, 4.057270795192212, 11.20218846558286)
+SketchConstraintCoincidence_66 = Sketch_2.setCoincident(SketchLine_38.endPoint(), SketchLine_39.startPoint())
+SketchConstraintCoincidence_66.setName("SketchConstraintCoincidence_67")
+SketchLine_40 = Sketch_2.addLine(4.057270795192212, 11.20218846558286, 4.140002338214646, 11.43810262749166)
+SketchLine_40.setAuxiliary(True)
+SketchConstraintCoincidence_67 = Sketch_2.setCoincident(SketchLine_39.endPoint(), SketchLine_40.startPoint())
+SketchConstraintCoincidence_67.setName("SketchConstraintCoincidence_68")
+SketchLine_41 = Sketch_2.addLine(4.140002338214646, 11.43810262749166, 3.911629569238839, 11.53981731861503)
+SketchConstraintCoincidence_68 = Sketch_2.setCoincident(SketchLine_40.endPoint(), SketchLine_41.startPoint())
+SketchConstraintCoincidence_68.setName("SketchConstraintCoincidence_69")
+SketchConstraintCoincidence_69 = Sketch_2.setCoincident(SketchLine_38.startPoint(), SketchLine_41.endPoint())
+SketchConstraintCoincidence_69.setName("SketchConstraintCoincidence_70")
+SketchLine_42 = Sketch_2.addLine(4.057270795192212, 11.20218846558286, 4.410949215071502, 11.07754130426779)
+SketchConstraintCoincidence_70 = Sketch_2.setCoincident(SketchLine_39.endPoint(), SketchLine_42.startPoint())
+SketchConstraintCoincidence_70.setName("SketchConstraintCoincidence_71")
+SketchProjection_5 = Sketch_2.addProjection(model.selection("EDGE", "Sketch_1/SketchArc_2_2"), False)
+SketchArc_6 = SketchProjection_5.createdFeature()
+SketchConstraintCoincidence_71 = Sketch_2.setCoincident(SketchLine_42.endPoint(), SketchArc_6.results()[1])
+SketchConstraintCoincidence_71.setName("SketchConstraintCoincidence_72")
+SketchLine_43 = Sketch_2.addLine(4.410949215071502, 11.07754130426779, 4.465704943014801, 11.23368068225505)
+SketchConstraintCoincidence_72 = Sketch_2.setCoincident(SketchLine_42.endPoint(), SketchLine_43.startPoint())
+SketchConstraintCoincidence_72.setName("SketchConstraintCoincidence_73")
+SketchProjection_6 = Sketch_2.addProjection(model.selection("EDGE", "Sketch_1/SketchArc_3_2"), False)
+SketchArc_7 = SketchProjection_6.createdFeature()
+SketchConstraintCoincidence_73 = Sketch_2.setCoincident(SketchLine_43.endPoint(), SketchArc_7.results()[1])
+SketchConstraintCoincidence_73.setName("SketchConstraintCoincidence_74")
+SketchLine_44 = Sketch_2.addLine(4.465704943014801, 11.23368068225505, 4.140002338214646, 11.43810262749166)
+SketchConstraintCoincidence_74 = Sketch_2.setCoincident(SketchLine_43.endPoint(), SketchLine_44.startPoint())
+SketchConstraintCoincidence_74.setName("SketchConstraintCoincidence_75")
+SketchConstraintCoincidence_75 = Sketch_2.setCoincident(SketchLine_40.endPoint(), SketchLine_44.endPoint())
+SketchConstraintCoincidence_75.setName("SketchConstraintCoincidence_76")
+SketchConstraintParallel_1 = Sketch_2.setParallel(SketchLine_38.result(), SketchLine_35.result())
+SketchConstraintParallel_2 = Sketch_2.setParallel(SketchLine_40.result(), SketchLine_38.result())
+SketchConstraintParallel_3 = Sketch_2.setParallel(SketchLine_43.result(), SketchLine_40.result())
+SketchConstraintLength_6 = Sketch_2.setLength(SketchLine_40.result(), 0.25)
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_40.result(), SketchLine_38.result())
+SketchPoint_5 = Sketch_2.addPoint(3.87026379772762, 11.42186023766063)
+SketchConstraintCoincidence_76 = Sketch_2.setCoincident(SketchPoint_5.coordinates(), SketchLine_38.result())
+SketchConstraintCoincidence_76.setName("SketchConstraintCoincidence_77")
+SketchConstraintMiddle_4 = Sketch_2.setMiddlePoint(SketchPoint_5.coordinates(), SketchLine_38.result())
+SketchConstraintCoincidence_77 = Sketch_2.setCoincident(SketchPoint_5.coordinates(), SketchArc_5.results()[1])
+SketchConstraintCoincidence_77.setName("SketchConstraintCoincidence_78")
+SketchPoint_6 = Sketch_2.addPoint(4.09863656670343, 11.32014554653726)
+SketchConstraintCoincidence_78 = Sketch_2.setCoincident(SketchPoint_6.coordinates(), SketchLine_40.result())
+SketchConstraintCoincidence_78.setName("SketchConstraintCoincidence_79")
+SketchConstraintCoincidence_79 = Sketch_2.setCoincident(SketchPoint_6.coordinates(), SketchArc_5.results()[1])
+SketchConstraintCoincidence_79.setName("SketchConstraintCoincidence_80")
+SketchConstraintMiddle_5 = Sketch_2.setMiddlePoint(SketchPoint_6.coordinates(), SketchLine_40.result())
+SketchConstraintLength_7 = Sketch_2.setLength(SketchLine_41.result(), 0.25)
+SketchConstraintDistance_17 = Sketch_2.setDistance(SketchLine_38.startPoint(), SketchLine_35.result(), "1.35/2", True)
+SketchConstraintDistance_17.setName("SketchConstraintDistance_20")
+SketchConstraintDistance_18 = Sketch_2.setDistance(SketchLine_41.startPoint(), SketchLine_43.result(), 0.375, True)
+SketchConstraintDistance_18.setName("SketchConstraintDistance_21")
+SketchLine_45 = Sketch_2.addLine(3.911629569238839, 11.53981731861503, 3.397674805046317, 12.11397308570391)
+SketchConstraintCoincidence_80 = Sketch_2.setCoincident(SketchLine_38.startPoint(), SketchLine_45.startPoint())
+SketchConstraintCoincidence_80.setName("SketchConstraintCoincidence_81")
+SketchConstraintCoincidence_81 = Sketch_2.setCoincident(SketchLine_35.startPoint(), SketchLine_45.endPoint())
+SketchConstraintCoincidence_81.setName("SketchConstraintCoincidence_82")
+SketchLine_46 = Sketch_2.addLine(3.082152448528626, 11.21424138021434, 3.828898026216406, 11.30390315670624)
+SketchConstraintCoincidence_82 = Sketch_2.setCoincident(SketchLine_35.endPoint(), SketchLine_46.startPoint())
+SketchConstraintCoincidence_82.setName("SketchConstraintCoincidence_83")
+SketchConstraintCoincidence_83 = Sketch_2.setCoincident(SketchLine_38.endPoint(), SketchLine_46.endPoint())
+SketchConstraintCoincidence_83.setName("SketchConstraintCoincidence_84")
+model.do()
+Revolution_2 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_35r-SketchLine_46f-SketchLine_38r-SketchLine_45f")], model.selection("EDGE", "Sketch_2/SketchLine_35"), 360, 0)
+AngularCopy_1 = model.addMultiRotation(Part_1_doc, [model.selection("SOLID", "Revolution_2_1")], model.selection("EDGE", "PartSet/OZ"), 2)
+Cut_1 = model.addCut(Part_1_doc, [model.selection("SOLID", "Revolution_1_1")], [model.selection("COMPOUND", "AngularCopy_1_1")])
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOY"), 3.6, False)
+Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchProjection_7 = Sketch_3.addProjection(model.selection("EDGE", "[Revolution_1_1/Generated_Face&Sketch_1/SketchLine_9][Revolution_1_1/Generated_Face&Sketch_1/SketchLine_8]"), True)
+SketchCircle_1 = SketchProjection_7.createdFeature()
+SketchProjection_8 = Sketch_3.addProjection(model.selection("EDGE", "[Revolution_1_1/Generated_Face&Sketch_1/SketchLine_1][Revolution_1_1/Generated_Face&Sketch_1/SketchLine_2]"), True)
+SketchCircle_2 = SketchProjection_8.createdFeature()
+SketchLine_47 = Sketch_3.addLine(6.067916611160706, -1.958, 6.166614630411087, -1.958)
+SketchConstraintCoincidence_84 = Sketch_3.setCoincident(SketchLine_47.startPoint(), SketchCircle_1.results()[1])
+SketchConstraintCoincidence_84.setName("SketchConstraintCoincidence_85")
+SketchArc_8 = Sketch_3.addArc(0, 0, 6.166614630411087, -1.958, 6.47, 0, False)
+SketchConstraintCoincidence_85 = Sketch_3.setCoincident(SketchLine_47.endPoint(), SketchArc_8.startPoint())
+SketchConstraintCoincidence_85.setName("SketchConstraintCoincidence_87")
+SketchConstraintHorizontal_8 = Sketch_3.setHorizontal(SketchLine_47.result())
+SketchProjection_9 = Sketch_3.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_48 = SketchProjection_9.createdFeature()
+SketchLine_48.setName("SketchLine_49")
+SketchLine_48.result().setName("SketchLine_49")
+SketchConstraintDistance_19 = Sketch_3.setDistance(SketchLine_47.endPoint(), SketchLine_48.result(), 1.958, True)
+SketchConstraintDistance_19.setName("SketchConstraintDistance_23")
+SketchLine_49 = Sketch_3.addLine(5.870057921349673, -1.957999999999988, 5.858998207885032, -1.675999999999991)
+SketchLine_49.setName("SketchLine_50")
+SketchLine_49.result().setName("SketchLine_50")
+SketchConstraintCoincidence_86 = Sketch_3.setCoincident(SketchLine_49.startPoint(), SketchCircle_2.results()[1])
+SketchConstraintCoincidence_86.setName("SketchConstraintCoincidence_89")
+SketchConstraintCoincidence_87 = Sketch_3.setCoincident(SketchArc_8.endPoint(), SketchLine_48.result())
+SketchConstraintCoincidence_87.setName("SketchConstraintCoincidence_88")
+SketchArc_9 = Sketch_3.addArc(0, 0, 5.858998207885032, -1.675999999999991, 6.093999999999999, 0, False)
+SketchConstraintCoincidence_88 = Sketch_3.setCoincident(SketchLine_49.endPoint(), SketchArc_9.startPoint())
+SketchConstraintCoincidence_88.setName("SketchConstraintCoincidence_90")
+SketchConstraintCoincidence_89 = Sketch_3.setCoincident(SketchLine_48.result(), SketchArc_9.endPoint())
+SketchConstraintCoincidence_89.setName("SketchConstraintCoincidence_91")
+SketchConstraintCoincidence_90 = Sketch_3.setCoincident(SketchArc_9.center(), SketchAPI_Line(SketchLine_48).startPoint())
+SketchConstraintCoincidence_90.setName("SketchConstraintCoincidence_92")
+SketchConstraintCoincidence_91 = Sketch_3.setCoincident(SketchArc_8.result(), SketchAPI_Line(SketchLine_48).startPoint())
+SketchConstraintCoincidence_91.setName("SketchConstraintCoincidence_93")
+SketchPoint_7 = Sketch_3.addPoint(6.188, 0)
+SketchConstraintCoincidence_92 = Sketch_3.setCoincident(SketchPoint_7.coordinates(), SketchCircle_2.results()[1])
+SketchConstraintCoincidence_92.setName("SketchConstraintCoincidence_94")
+SketchConstraintCoincidence_93 = Sketch_3.setCoincident(SketchPoint_7.coordinates(), SketchLine_48.result())
+SketchConstraintCoincidence_93.setName("SketchConstraintCoincidence_95")
+SketchPoint_8 = Sketch_3.addPoint(6.375999999999999, 0)
+SketchConstraintCoincidence_94 = Sketch_3.setCoincident(SketchPoint_8.coordinates(), SketchCircle_1.results()[1])
+SketchConstraintCoincidence_94.setName("SketchConstraintCoincidence_96")
+SketchConstraintCoincidence_95 = Sketch_3.setCoincident(SketchPoint_8.coordinates(), SketchLine_48.result())
+SketchConstraintCoincidence_95.setName("SketchConstraintCoincidence_97")
+SketchConstraintDistance_20 = Sketch_3.setDistance(SketchPoint_8.coordinates(), SketchArc_8.endPoint(), 0.094, True)
+SketchConstraintDistance_20.setName("SketchConstraintDistance_22")
+SketchConstraintDistance_21 = Sketch_3.setDistance(SketchArc_9.endPoint(), SketchPoint_7.coordinates(), 0.094, True)
+SketchConstraintDistance_21.setName("SketchConstraintDistance_24")
+SketchConstraintDistance_22 = Sketch_3.setDistance(SketchArc_9.startPoint(), SketchLine_47.result(), 0.282, True)
+SketchConstraintDistance_22.setName("SketchConstraintDistance_25")
+SketchConstraintCoincidence_96 = Sketch_3.setCoincident(SketchLine_49.startPoint(), SketchLine_47.result())
+SketchConstraintCoincidence_96.setName("SketchConstraintCoincidence_98")
+SketchConstraintMirror_1_objects = [SketchArc_9.results()[1], SketchLine_49.result(), SketchLine_47.result(), SketchArc_8.results()[1]]
+SketchConstraintMirror_1 = Sketch_3.addMirror(SketchLine_48.result(), SketchConstraintMirror_1_objects)
+[SketchArc_10, SketchLine_50, SketchLine_51, SketchArc_11] = SketchConstraintMirror_1.mirrored()
+SketchLine_51.setName("SketchLine_52")
+SketchLine_51.result().setName("SketchLine_52")
+SketchLine_50.setName("SketchLine_51")
+SketchLine_50.result().setName("SketchLine_51")
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchProjection_8f-SketchProjection_8f-SketchLine_51f-SketchArc_10_2r-SketchArc_9_2r-SketchLine_50r"), model.selection("FACE", "Sketch_3/Face-SketchProjection_7r-SketchLine_47f-SketchArc_8_2f-SketchArc_11_2f-SketchLine_52r-SketchProjection_7r")], model.selection(), 0, 4.2)
+Sketch_4 = model.addSketch(Part_1_doc, model.standardPlane("YOZ"))
+SketchLine_52 = Sketch_4.addLine(0.75, 2.1, -0.75, 2.1)
+SketchLine_52.setName("SketchLine_53")
+SketchLine_52.result().setName("SketchLine_53")
+SketchLine_53 = Sketch_4.addLine(-0.75, 2.1, -0.75, 0.3)
+SketchLine_53.setName("SketchLine_54")
+SketchLine_53.result().setName("SketchLine_54")
+SketchLine_54 = Sketch_4.addLine(-0.75, 0.3, 0.75, 0.3)
+SketchLine_54.setName("SketchLine_55")
+SketchLine_54.result().setName("SketchLine_55")
+SketchLine_55 = Sketch_4.addLine(0.75, 0.3, 0.75, 2.1)
+SketchLine_55.setName("SketchLine_56")
+SketchLine_55.result().setName("SketchLine_56")
+SketchConstraintCoincidence_97 = Sketch_4.setCoincident(SketchLine_55.endPoint(), SketchLine_52.startPoint())
+SketchConstraintCoincidence_97.setName("SketchConstraintCoincidence_99")
+SketchConstraintCoincidence_98 = Sketch_4.setCoincident(SketchLine_52.endPoint(), SketchLine_53.startPoint())
+SketchConstraintCoincidence_98.setName("SketchConstraintCoincidence_100")
+SketchConstraintCoincidence_99 = Sketch_4.setCoincident(SketchLine_53.endPoint(), SketchLine_54.startPoint())
+SketchConstraintCoincidence_99.setName("SketchConstraintCoincidence_101")
+SketchConstraintCoincidence_100 = Sketch_4.setCoincident(SketchLine_54.endPoint(), SketchLine_55.startPoint())
+SketchConstraintCoincidence_100.setName("SketchConstraintCoincidence_102")
+SketchConstraintHorizontal_9 = Sketch_4.setHorizontal(SketchLine_52.result())
+SketchConstraintVertical_11 = Sketch_4.setVertical(SketchLine_53.result())
+SketchConstraintHorizontal_10 = Sketch_4.setHorizontal(SketchLine_54.result())
+SketchConstraintVertical_12 = Sketch_4.setVertical(SketchLine_55.result())
+SketchProjection_10 = Sketch_4.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_56 = SketchProjection_10.createdFeature()
+SketchLine_56.setName("SketchLine_57")
+SketchLine_56.result().setName("SketchLine_57")
+SketchConstraintDistance_23 = Sketch_4.setDistance(SketchLine_52.startPoint(), SketchLine_56.result(), 2.1, True)
+SketchConstraintDistance_23.setName("SketchConstraintDistance_26")
+SketchConstraintDistance_24 = Sketch_4.setDistance(SketchLine_54.endPoint(), SketchLine_56.result(), 0.3, True)
+SketchConstraintDistance_24.setName("SketchConstraintDistance_27")
+SketchPoint_9 = Sketch_4.addPoint(0, 2.1)
+SketchConstraintCoincidence_101 = Sketch_4.setCoincident(SketchPoint_9.coordinates(), SketchLine_52.result())
+SketchConstraintCoincidence_101.setName("SketchConstraintCoincidence_103")
+SketchProjection_11 = Sketch_4.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_57 = SketchProjection_11.createdFeature()
+SketchLine_57.setName("SketchLine_58")
+SketchLine_57.result().setName("SketchLine_58")
+SketchConstraintCoincidence_102 = Sketch_4.setCoincident(SketchPoint_9.coordinates(), SketchLine_57.result())
+SketchConstraintCoincidence_102.setName("SketchConstraintCoincidence_104")
+SketchConstraintMiddle_6 = Sketch_4.setMiddlePoint(SketchPoint_9.coordinates(), SketchLine_52.result())
+SketchConstraintDistance_25 = Sketch_4.setDistance(SketchPoint_9.coordinates(), SketchLine_52.startPoint(), 0.75, True)
+SketchConstraintDistance_25.setName("SketchConstraintDistance_28")
+model.do()
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_4/Face-SketchLine_53r-SketchLine_54f-SketchLine_55f-SketchLine_56f")], model.selection(), 10, 0)
+Rotation_1_objects = [model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_1_2"), model.selection("SOLID", "Extrusion_2_1")]
+Rotation_1 = model.addRotation(Part_1_doc, Rotation_1_objects, model.selection("EDGE", "PartSet/OZ"), -90)
+Cut_2_objects_1 = [model.selection("SOLID", "Cut_1_1"), model.selection("SOLID", "Rotation_1_1"), model.selection("SOLID", "Rotation_1_2")]
+Cut_2 = model.addCut(Part_1_doc, Cut_2_objects_1, [model.selection("SOLID", "Rotation_1_3")])
+Fuse_2_objects_1 = [model.selection("SOLID", "Cut_2_1"), model.selection("SOLID", "Cut_2_2"), model.selection("SOLID", "Cut_2_3")]
+Fuse_2 = model.addFuse(Part_1_doc, Fuse_2_objects_1, True)
+model.do()
+# move groups to the end
+Part_1_doc.moveFeature(Group_1.feature(), Fuse_2.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+Part_1_doc.moveFeature(Group_3.feature(), Group_2.feature())
+model.end()
+
+# check groups are correct
+from ModelAPI import *
+from GeomAPI import *
+aFactory = ModelAPI_Session.get().validators()
+
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 1)
+assert(aFactory.validate(Group_1.feature()))
+assert(Group_1.groupList().value(0).value().shapeType() == GeomAPI_Shape.FACE)
+
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 8)
+assert(aFactory.validate(Group_2.feature()))
+for i in range(8):
+  assert(Group_2.groupList().value(i).value().shapeType() == GeomAPI_Shape.FACE)
+
+selectionList = Group_3.feature().selectionList("group_list")
+assert(selectionList.size() == 4)
+assert(aFactory.validate(Group_3.feature()))
+for i in range(4):
+  assert(Group_3.groupList().value(i).value().shapeType() == GeomAPI_Shape.FACE)
diff --git a/src/FeaturesPlugin/Test/TestBooleanCommon_SolidsHistory.py b/src/FeaturesPlugin/Test/TestBooleanCommon_SolidsHistory.py
new file mode 100644 (file)
index 0000000..5fd15d8
--- /dev/null
@@ -0,0 +1,132 @@
+## 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 the history of Common operation works correctly after movement of groups after this Common feature
+
+# -*- coding: utf-8 -*-
+
+from salome.shaper import model
+from ModelAPI import *
+from GeomAPI import *
+from SketchAPI import *
+
+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, 5, 7.071067811865464)
+SketchCircle_2 = Sketch_1.addCircle(0, 10, 7.071067811865464)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchCircle_1.center(), SketchCircle_2.results()[1])
+SketchCircle_3 = Sketch_1.addCircle(-5, 5, 7.071067811865464)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchCircle_2.center(), SketchCircle_3.results()[1])
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchCircle_3.center(), SketchCircle_2.results()[1])
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchCircle_1.results()[1], SketchCircle_2.center())
+SketchCircle_4 = Sketch_1.addCircle(0, 0, 7.071067811865464)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchCircle_4.center(), SketchCircle_3.results()[1])
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchCircle_4.results()[1], SketchCircle_3.center())
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchCircle_4.results()[1], SketchCircle_1.center())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchCircle_1.center(), SketchCircle_3.center(), 10, True)
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchCircle_2.center(), SketchCircle_4.center(), 10, True)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchCircle_4.center(), SketchAPI_Point(SketchPoint_1).coordinates())
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_1 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchCircle_2.center(), SketchLine_1.result())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_2 = Sketch_2.addLine(-5, 5, 0, 0)
+SketchProjection_3 = Sketch_2.addProjection(model.selection("VERTEX", "Sketch_1/SketchCircle_3_2__cc"), False)
+SketchPoint_2 = SketchProjection_3.createdFeature()
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_2.startPoint(), SketchPoint_2.result())
+SketchProjection_4 = Sketch_2.addProjection(model.selection("VERTEX", "Sketch_1/SketchCircle_4_2__cc"), False)
+SketchPoint_3 = SketchProjection_4.createdFeature()
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchPoint_3.result())
+SketchLine_3 = Sketch_2.addLine(0, 0, 5, 5)
+SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchProjection_5 = Sketch_2.addProjection(model.selection("VERTEX", "Sketch_1/SketchCircle_1_2__cc"), False)
+SketchPoint_4 = SketchProjection_5.createdFeature()
+SketchConstraintCoincidence_13 = Sketch_2.setCoincident(SketchLine_3.endPoint(), SketchPoint_4.result())
+SketchLine_4 = Sketch_2.addLine(-5, 5, 5, 5)
+SketchConstraintCoincidence_14 = Sketch_2.setCoincident(SketchLine_2.startPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_15 = Sketch_2.setCoincident(SketchLine_3.endPoint(), SketchLine_4.endPoint())
+SketchArc_1 = Sketch_2.addArc(-1.474514954580286e-16, 5, -5, 5, 5, 5, True)
+SketchConstraintCoincidence_16 = Sketch_2.setCoincident(SketchLine_4.result(), SketchArc_1.center())
+SketchConstraintCoincidence_17 = Sketch_2.setCoincident(SketchLine_2.startPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_18 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchArc_1.endPoint())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1")], model.selection(), 10, 0)
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_2")], model.selection(), 5, 5)
+Group_1_objects = [model.selection("SOLID", "Extrusion_1_1_13"), model.selection("SOLID", "Extrusion_1_1_10"), model.selection("SOLID", "Extrusion_1_1_7"), model.selection("SOLID", "Extrusion_1_1_9"), model.selection("SOLID", "Extrusion_1_1_1"), model.selection("SOLID", "Extrusion_1_1_5"), model.selection("SOLID", "Extrusion_1_1_4"), model.selection("SOLID", "Extrusion_1_1_12"), model.selection("SOLID", "Extrusion_1_1_11"), model.selection("SOLID", "Extrusion_1_1_8"), model.selection("SOLID", "Extrusion_1_1_3"), model.selection("SOLID", "Extrusion_1_1_6"), model.selection("SOLID", "Extrusion_1_1_2")]
+Group_1 = model.addGroup(Part_1_doc, Group_1_objects)
+Group_2 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Extrusion_2_1_2"), model.selection("SOLID", "Extrusion_2_1_1")])
+Group_3_objects = [model.selection("FACE", "Extrusion_1_1_7/From_Face"), model.selection("FACE", "Extrusion_1_1_1/From_Face"), model.selection("FACE", "Extrusion_1_1_9/From_Face"), model.selection("FACE", "Extrusion_1_1_12/From_Face"), model.selection("FACE", "Extrusion_1_1_4/From_Face"), model.selection("FACE", "Extrusion_1_1_5/From_Face"), model.selection("FACE", "Extrusion_1_1_8/From_Face"), model.selection("FACE", "Extrusion_1_1_11/From_Face"), model.selection("FACE", "Extrusion_1_1_6/From_Face"), model.selection("FACE", "Extrusion_1_1_2/From_Face"), model.selection("FACE", "Extrusion_1_1_3/From_Face"), model.selection("FACE", "Extrusion_1_1_10/From_Face")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+Group_4_objects = [model.selection("FACE", "Extrusion_2_1_2/Generated_Face&Sketch_2/SketchLine_4"), model.selection("FACE", "Extrusion_2_1_2/Generated_Face&Sketch_2/SketchArc_1_2"), model.selection("FACE", "Extrusion_2_1_2/From_Face"), model.selection("FACE", "Extrusion_2_1_2/To_Face"), model.selection("FACE", "Extrusion_2_1_1/Generated_Face&Sketch_2/SketchLine_2"), model.selection("FACE", "Extrusion_2_1_1/To_Face"), model.selection("FACE", "Extrusion_2_1_1/From_Face"), model.selection("FACE", "Extrusion_2_1_1/Generated_Face&Sketch_2/SketchLine_4"), model.selection("FACE", "Extrusion_2_1_1/Generated_Face&Sketch_2/SketchLine_3")]
+Group_4 = model.addGroup(Part_1_doc, Group_4_objects)
+Common_1 = model.addCommon(Part_1_doc, [model.selection("COMPSOLID", "Extrusion_1_1"), model.selection("COMPSOLID", "Extrusion_2_1")])
+Common_1.result().subResult(0).setColor(254, 254, 127)
+Common_1.result().subResult(1).setColor(204, 102, 204)
+Common_1.result().subResult(2).setColor(51, 102, 102)
+Common_1.result().subResult(3).setColor(0, 153, 0)
+Common_1.result().subResult(4).setColor(254, 0, 0)
+Common_1.result().subResult(5).setColor(204, 0, 204)
+Common_1.result().subResult(6).setColor(102, 0, 0)
+Common_1.result().subResult(7).setColor(0, 0, 153)
+Common_1.result().subResult(8).setColor(0, 0, 204)
+Common_1.result().subResult(9).setColor(0, 0, 204)
+Common_1.result().subResult(10).setColor(0, 153, 0)
+Common_1.result().subResult(11).setColor(127, 127, 254)
+model.do()
+# move groups after the Common
+Part_1_doc.moveFeature(Group_1.feature(), Common_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+Part_1_doc.moveFeature(Group_3.feature(), Group_2.feature())
+Part_1_doc.moveFeature(Group_4.feature(), Group_3.feature())
+model.end()
+
+# check groups are correct
+aFactory = ModelAPI_Session.get().validators()
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 12)
+assert(aFactory.validate(Group_1.feature()))
+for i in range(12):
+  assert(Group_1.groupList().value(i).value().shapeType() == GeomAPI_Shape.SOLID)
+
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 12)
+assert(aFactory.validate(Group_2.feature()))
+for i in range(12):
+  assert(Group_2.groupList().value(i).value().shapeType() == GeomAPI_Shape.SOLID)
+
+selectionList = Group_3.feature().selectionList("group_list")
+assert(selectionList.size() == 12)
+assert(aFactory.validate(Group_3.feature()))
+for i in range(12):
+  assert(Group_3.groupList().value(i).value().shapeType() == GeomAPI_Shape.FACE)
+
+selectionList = Group_4.feature().selectionList("group_list")
+assert(selectionList.size() == 22)
+assert(aFactory.validate(Group_4.feature()))
+for i in range(22):
+  assert(Group_4.groupList().value(i).value().shapeType() == GeomAPI_Shape.FACE)
+
+assert(model.checkPythonDump(model.ModelHighAPI.CHECK_NAMING))
diff --git a/src/FeaturesPlugin/Test/TestBooleanCut_SolidsHistory.py b/src/FeaturesPlugin/Test/TestBooleanCut_SolidsHistory.py
new file mode 100644 (file)
index 0000000..5fc9567
--- /dev/null
@@ -0,0 +1,77 @@
+## 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 the history of Cut operation works correctly after movement of groups after this Cut feature:
+# cut tools are deleted, cut objects are correctly transformed to and divided if needed
+
+# -*- coding: utf-8 -*-
+
+from salome.shaper import model
+from ModelAPI import *
+from GeomAPI import *
+
+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(-10.57884322822754, 25.90966115484096, 9.63424990252037)
+SketchLine_1 = Sketch_1.addLine(-18.29572175958338, 20.14177099321736, -2.288684850537554, 30.81802598002054)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchCircle_1.results()[1])
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchCircle_1.results()[1])
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_2 = Sketch_2.addLine(7.424373233594292, 20.04016872303595, -10.19950738916256, 28.60837438423646)
+SketchLine_3 = Sketch_2.addLine(-10.19950738916256, 28.60837438423646, 10.7835313495703, 29.11992811073657)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_2.addLine(10.7835313495703, 29.11992811073657, 7.424373233594292, 20.04016872303595)
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_2.startPoint(), SketchLine_4.endPoint())
+SketchLine_5 = Sketch_2.addLine(-10.19950738916256, 28.60837438423646, 9.111243103183778, 24.59975538297626)
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_4.result())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1"), model.selection("COMPOUND", "all-in-Sketch_2")], model.selection(), 10, 0)
+Group_1_objects = [model.selection("SOLID", "Extrusion_1_1_2"), model.selection("SOLID", "Extrusion_1_1_1"), model.selection("SOLID", "Extrusion_1_2_2"), model.selection("SOLID", "Extrusion_1_2_1")]
+Group_1 = model.addGroup(Part_1_doc, Group_1_objects)
+Group_2_objects = [model.selection("FACE", "Extrusion_1_1_2/Generated_Face&Sketch_1/SketchLine_1"), model.selection("FACE", "Extrusion_1_1_2/To_Face"), model.selection("FACE", "Extrusion_1_2_2/To_Face")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Cut_1 = model.addCut(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1_2")], [model.selection("SOLID", "Extrusion_1_2_2")])
+model.do()
+# move groups after the Cut
+Part_1_doc.moveFeature(Group_1.feature(), Cut_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+model.end()
+
+# check groups are correct
+aFactory = ModelAPI_Session.get().validators()
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 2)
+assert(aFactory.validate(Group_1.feature()))
+for i in range(2):
+  assert(Group_1.groupList().value(i).value().shapeType() == GeomAPI_Shape.SOLID)
+
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 3)
+assert(aFactory.validate(Group_2.feature()))
+for i in range(3):
+  assert(Group_2.groupList().value(i).value().shapeType() == GeomAPI_Shape.FACE)
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestBooleanFuse_SolidsHistory.py b/src/FeaturesPlugin/Test/TestBooleanFuse_SolidsHistory.py
new file mode 100644 (file)
index 0000000..b966d42
--- /dev/null
@@ -0,0 +1,81 @@
+## 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>
+##
+
+# -*- coding: utf-8 -*-
+
+from salome.shaper import model
+from ModelAPI import *
+from GeomAPI import *
+
+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(-9.826354679802961, 29.97660098522167, -30.22536945812809, 29.97660098522167)
+SketchLine_2 = Sketch_1.addLine(-30.22536945812809, 29.97660098522167, -30.22536945812809, 11.69211822660099)
+SketchLine_3 = Sketch_1.addLine(-30.22536945812809, 11.69211822660099, -9.826354679802961, 11.69211822660099)
+SketchLine_4 = Sketch_1.addLine(-9.826354679802961, 11.69211822660099, -9.826354679802961, 29.97660098522167)
+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())
+SketchLine_5 = Sketch_1.addLine(-30.22536945812809, 11.69211822660099, -9.826354679802961, 29.97660098522167)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_5.endPoint())
+SketchCircle_1 = Sketch_1.addCircle(9.328817733990148, 6.841133004926101, 8.342093824373531)
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_2 = Sketch_2.addCircle(-5.846059113300496, 9.453201970443347, 11.01344978196573)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1")], model.selection(), 10, 0)
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_2")], model.selection(), 11, 1)
+Group_1_objects = [model.selection("SOLID", "Extrusion_1_2_1"), model.selection("SOLID", "Extrusion_1_2_2"), model.selection("SOLID", "Extrusion_2_1"), model.selection("SOLID", "Extrusion_1_1")]
+Group_1 = model.addGroup(Part_1_doc, Group_1_objects)
+Group_2_objects = [model.selection("FACE", "Extrusion_1_2_1/To_Face"), model.selection("FACE", "Extrusion_1_2_2/To_Face"), model.selection("FACE", "Extrusion_2_1/To_Face"), model.selection("FACE", "Extrusion_1_1/To_Face")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Fuse_1_objects_1 = [model.selection("SOLID", "Extrusion_1_2_2"), model.selection("SOLID", "Extrusion_2_1"), model.selection("SOLID", "Extrusion_1_1")]
+Fuse_1 = model.addFuse(Part_1_doc, Fuse_1_objects_1)
+model.do()
+# move group
+Part_1_doc.moveFeature(Group_1.feature(), Fuse_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+model.end()
+
+# Check group 1: 3 solids
+aFactory = ModelAPI_Session.get().validators()
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 3)
+assert(aFactory.validate(Group_1.feature()))
+for i in range(3):
+  assert(Group_1.groupList().value(i).value().shapeType() == GeomAPI_Shape.SOLID)
+
+# Check group 2: 3 faces
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 3)
+assert(aFactory.validate(Group_2.feature()))
+for i in range(3):
+  assert(Group_2.groupList().value(i).value().shapeType() == GeomAPI_Shape.FACE)
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestBooleanSmash_SolidsHistory.py b/src/FeaturesPlugin/Test/TestBooleanSmash_SolidsHistory.py
new file mode 100644 (file)
index 0000000..44354bf
--- /dev/null
@@ -0,0 +1,122 @@
+## 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 the history of Smash operation works correctly after movement of groups after this Smash feature
+
+# -*- coding: utf-8 -*-
+
+from salome.shaper import model
+from ModelAPI import *
+from GeomAPI import *
+
+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(26.49384236453203, 25.42805779478775, -23.25985221674878, 25.42805779478775)
+SketchLine_2 = Sketch_1.addLine(-23.25985221674878, 25.42805779478775, -23.25985221674878, -22.79086009461325)
+SketchLine_3 = Sketch_1.addLine(-23.25985221674878, -22.79086009461325, 26.49384236453203, -22.79086009461325)
+SketchLine_4 = Sketch_1.addLine(26.49384236453203, -22.79086009461325, 26.49384236453203, 25.42805779478775)
+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())
+SketchLine_5 = Sketch_1.addLine(-23.25985221674878, -22.79086009461325, -4.602216748768477, 25.42805779478775)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_1.result())
+SketchLine_6 = Sketch_1.addLine(-4.602216748768477, 25.42805779478775, 8.458128078817737, -22.79086009461324)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_3.result())
+SketchLine_7 = Sketch_1.addLine(8.458128078817737, -22.79086009461324, 26.49384236453203, 25.42805779478775)
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_7.endPoint())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_8 = Sketch_2.addLine(38.18596059113301, 15.79679802955666, -30.91800131851275, 15.79679802955666)
+SketchLine_9 = Sketch_2.addLine(-30.91800131851275, 15.79679802955666, -30.91800131851275, -10.07512315270936)
+SketchLine_10 = Sketch_2.addLine(-30.91800131851275, -10.07512315270936, 38.18596059113301, -10.07512315270936)
+SketchLine_11 = Sketch_2.addLine(38.18596059113301, -10.07512315270936, 38.18596059113301, 15.79679802955666)
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_11.endPoint(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchConstraintCoincidence_13 = Sketch_2.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint())
+SketchConstraintCoincidence_14 = Sketch_2.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint())
+SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_8.result())
+SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_9.result())
+SketchConstraintHorizontal_4 = Sketch_2.setHorizontal(SketchLine_10.result())
+SketchConstraintVertical_4 = Sketch_2.setVertical(SketchLine_11.result())
+SketchLine_12 = Sketch_2.addLine(38.18596059113301, 15.79679802955666, -30.91800131851275, 1.368226600985215)
+SketchConstraintCoincidence_15 = Sketch_2.setCoincident(SketchLine_8.startPoint(), SketchLine_12.startPoint())
+SketchConstraintCoincidence_16 = Sketch_2.setCoincident(SketchLine_12.endPoint(), SketchLine_9.result())
+SketchLine_13 = Sketch_2.addLine(-30.91800131851275, 1.368226600985215, 38.18596059113301, -10.07512315270936)
+SketchConstraintCoincidence_17 = Sketch_2.setCoincident(SketchLine_12.endPoint(), SketchLine_13.startPoint())
+SketchConstraintCoincidence_18 = Sketch_2.setCoincident(SketchLine_10.endPoint(), SketchLine_13.endPoint())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1")], model.selection(), 10, 0)
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_2")], model.selection(), 5, 5)
+Group_1_objects = [model.selection("SOLID", "Extrusion_1_1_1"), model.selection("SOLID", "Extrusion_1_1_4"), model.selection("SOLID", "Extrusion_1_1_2"), model.selection("SOLID", "Extrusion_1_1_3")]
+Group_1 = model.addGroup(Part_1_doc, Group_1_objects)
+Group_2_objects = [model.selection("SOLID", "Extrusion_2_1_2"), model.selection("SOLID", "Extrusion_2_1_3"), model.selection("SOLID", "Extrusion_2_1_1")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Group_3_objects = [model.selection("FACE", "Extrusion_1_1_4/From_Face"), model.selection("FACE", "Extrusion_1_1_2/From_Face"), model.selection("FACE", "Extrusion_1_1_4/Generated_Face&Sketch_1/SketchLine_3"), model.selection("FACE", "Extrusion_1_1_2/Generated_Face&Sketch_1/SketchLine_1"), model.selection("FACE", "Extrusion_1_1_4/To_Face"), model.selection("FACE", "Extrusion_1_1_2/To_Face")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+Group_4_objects = [model.selection("FACE", "Extrusion_2_1_2/To_Face"), model.selection("FACE", "Extrusion_2_1_3/To_Face"), model.selection("FACE", "Extrusion_2_1_1/To_Face")]
+Group_4 = model.addGroup(Part_1_doc, Group_4_objects)
+Smash_1_objects_1 = [model.selection("SOLID", "Extrusion_1_1_1"), model.selection("SOLID", "Extrusion_1_1_4"), model.selection("SOLID", "Extrusion_1_1_2")]
+Smash_1 = model.addSmash(Part_1_doc, Smash_1_objects_1, [model.selection("SOLID", "Extrusion_2_1_1"), model.selection("SOLID", "Extrusion_2_1_2")])
+model.do()
+# move groups after the Smash
+Part_1_doc.moveFeature(Group_1.feature(), Smash_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+Part_1_doc.moveFeature(Group_3.feature(), Group_2.feature())
+Part_1_doc.moveFeature(Group_4.feature(), Group_3.feature())
+model.end()
+
+# check groups are correct
+aFactory = ModelAPI_Session.get().validators()
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 4)
+assert(aFactory.validate(Group_1.feature()))
+for i in range(4):
+  assert(Group_1.groupList().value(i).value().shapeType() == GeomAPI_Shape.SOLID)
+
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 2)
+assert(aFactory.validate(Group_2.feature()))
+for i in range(2):
+  assert(Group_2.groupList().value(i).value().shapeType() == GeomAPI_Shape.SOLID)
+
+selectionList = Group_3.feature().selectionList("group_list")
+assert(selectionList.size() == 10)
+assert(aFactory.validate(Group_3.feature()))
+for i in range(10):
+  assert(Group_3.groupList().value(i).value().shapeType() == GeomAPI_Shape.FACE)
+
+selectionList = Group_4.feature().selectionList("group_list")
+assert(selectionList.size() == 10)
+assert(aFactory.validate(Group_4.feature()))
+for i in range(10):
+  assert(Group_4.groupList().value(i).value().shapeType() == GeomAPI_Shape.FACE)
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillet_History.py b/src/FeaturesPlugin/Test/TestFillet_History.py
new file mode 100644 (file)
index 0000000..45f17b0
--- /dev/null
@@ -0,0 +1,83 @@
+## 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 the history of Fillet operation works correctly after movement of groups after this Fillet feature:
+# Faces are modified, edges that were used for fillet are removed
+
+# -*- coding: utf-8 -*-
+
+from salome.shaper import model
+from ModelAPI import *
+from GeomAPI import *
+from SketchAPI import *
+
+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(23.0955987576144, 26.85924638608351, -23.50862068965518, 26.85924638608351)
+SketchLine_2 = Sketch_1.addLine(-23.50862068965518, 26.85924638608351, -23.50862068965518, -11.11713209726581)
+SketchLine_3 = Sketch_1.addLine(-23.50862068965518, -11.11713209726581, 23.0955987576144, -11.11713209726581)
+SketchLine_4 = Sketch_1.addLine(23.0955987576144, -11.11713209726581, 23.0955987576144, 26.85924638608351)
+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_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_3.setName("SketchConstraintCoincidence_4")
+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())
+SketchLine_5 = Sketch_1.addLine(2.024890803123894, -11.11713209726581, 23.0955987576144, 26.85924638608351)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_5.endPoint())
+SketchConstraintCoincidence_4.setName("SketchConstraintCoincidence_6")
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.startPoint(), SketchLine_3.result())
+SketchConstraintCoincidence_5.setName("SketchConstraintCoincidence_5")
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_6.setName("SketchConstraintCoincidence_7")
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_3f-SketchLine_4f-SketchLine_5r"), model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_5f")], model.selection(), 10, 0)
+Group_1_objects = [model.selection("FACE", "Extrusion_1_1_2/Generated_Face&Sketch_1/SketchLine_2"), model.selection("FACE", "Extrusion_1_1_2/To_Face"), model.selection("FACE", "Extrusion_1_1_2/Generated_Face&Sketch_1/SketchLine_3")]
+Group_1 = model.addGroup(Part_1_doc, Group_1_objects)
+Group_2_objects = [model.selection("EDGE", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchLine_2][Extrusion_1_1_2/Generated_Face&Sketch_1/SketchLine_3]"), model.selection("EDGE", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchLine_2][Extrusion_1_1_2/To_Face]"), model.selection("EDGE", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchLine_1][Extrusion_1_1_2/Generated_Face&Sketch_1/SketchLine_2]"), model.selection("EDGE", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchLine_5][Extrusion_1_1_2/To_Face]")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Fillet_1_objects = [model.selection("EDGE", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchLine_2][Extrusion_1_1_2/To_Face]"), model.selection("EDGE", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchLine_1][Extrusion_1_1_2/Generated_Face&Sketch_1/SketchLine_2]"), model.selection("EDGE", "[Extrusion_1_1_2/Generated_Face&Sketch_1/SketchLine_2][Extrusion_1_1_2/From_Face]")]
+Fillet_1 = model.addFillet(Part_1_doc, Fillet_1_objects, 2)
+model.do()
+# move groups after the Fillet
+Part_1_doc.moveFeature(Group_1.feature(), Fillet_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+model.end()
+
+# check groups are correct
+aFactory = ModelAPI_Session.get().validators()
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 3)
+assert(aFactory.validate(Group_1.feature()))
+for i in range(3):
+  assert(Group_1.groupList().value(i).value().shapeType() == GeomAPI_Shape.FACE)
+
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 2)
+assert(aFactory.validate(Group_2.feature()))
+for i in range(2):
+  assert(Group_2.groupList().value(i).value().shapeType() == GeomAPI_Shape.EDGE)
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestPartition_SolidsHistory.py b/src/FeaturesPlugin/Test/TestPartition_SolidsHistory.py
new file mode 100644 (file)
index 0000000..ea7a2da
--- /dev/null
@@ -0,0 +1,91 @@
+## 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 partition of solid works correctly after movement of groups after this partition
+
+# -*- coding: utf-8 -*-
+
+from salome.shaper import model
+from ModelAPI import *
+from GeomAPI import *
+
+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(-16.04556650246306, 45.15147783251232, -31.59359605911331, 45.15147783251232)
+SketchLine_2 = Sketch_1.addLine(-31.59359605911331, 45.15147783251232, -31.59359605911331, 29.10591133004927)
+SketchLine_3 = Sketch_1.addLine(-31.59359605911331, 29.10591133004927, -16.04556650246306, 29.10591133004927)
+SketchLine_4 = Sketch_1.addLine(-16.04556650246306, 29.10591133004927, -16.04556650246306, 45.15147783251232)
+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())
+SketchLine_5 = Sketch_1.addLine(12.4384236453202, 13.06034482758621, -5.846059113300496, 13.06034482758621)
+SketchLine_6 = Sketch_1.addLine(-5.846059113300496, 13.06034482758621, -5.846059113300496, -6.965517241379309)
+SketchLine_7 = Sketch_1.addLine(-5.846059113300496, -6.965517241379309, 12.4384236453202, -6.965517241379309)
+SketchLine_8 = Sketch_1.addLine(12.4384236453202, -6.965517241379309, 12.4384236453202, 13.06034482758621)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_6.result())
+SketchConstraintHorizontal_4 = Sketch_1.setHorizontal(SketchLine_7.result())
+SketchConstraintVertical_4 = Sketch_1.setVertical(SketchLine_8.result())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_2.addCircle(-10.81448298196523, 20.3003568426161, 15.58088381891068)
+SketchLine_9 = Sketch_2.addLine(-19.86849367207068, 32.98061042849822, 0.2083042015703297, 9.288449501673265)
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_9.startPoint(), SketchCircle_1.results()[1])
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_9.endPoint(), SketchCircle_1.results()[1])
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1"), model.selection("COMPOUND", "Sketch_2")], model.selection(), 10, 0)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_1_3_2")])
+Group_2_objects = [model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_4"), model.selection("FACE", "Extrusion_1_3_2/Generated_Face&Sketch_2/SketchCircle_1_2"), model.selection("FACE", "Extrusion_1_3_1/Generated_Face&Sketch_2/SketchCircle_1_2&weak_name_1"), model.selection("FACE", "Extrusion_1_2/To_Face")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Partition_1_objects = [model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_1_2"), model.selection("COMPSOLID", "Extrusion_1_3")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects)
+model.do()
+# move groups after the partitiion
+Part_1_doc.moveFeature(Group_1.feature(), Partition_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+model.end()
+
+# check groups are correct
+aFactory = ModelAPI_Session.get().validators()
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 5)
+assert(aFactory.validate(Group_1.feature()))
+for i in range(5):
+  assert(Group_1.groupList().value(i).value().shapeType() == GeomAPI_Shape.SOLID)
+
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 10)
+assert(aFactory.validate(Group_2.feature()))
+for i in range(10):
+  assert(Group_2.groupList().value(i).value().shapeType() == GeomAPI_Shape.FACE)
+
+assert(model.checkPythonDump())
index ed1f347aa3c1118dbc5d83b9ec177d764bcfbfc9..7036f55378ede29acbbcf26dc3c9ae31e06c9320 100644 (file)
@@ -688,3 +688,9 @@ bool GeomAPI_Shape::isSelfIntersected(const int theLevelOfCheck) const
 
   return false;
 }
+
+bool GeomAPI_Shape::Comparator::operator()(const std::shared_ptr<GeomAPI_Shape>& theShape1,
+                                           const std::shared_ptr<GeomAPI_Shape>& theShape2) const
+{
+  return theShape1->impl<TopoDS_Shape>().TShape() < theShape2->impl<TopoDS_Shape>().TShape();
+}
index b15da00b26f321a753a80ca26510ec5040f9006c..cf3222bca246fc178d895d381812016bebdc9121 100644 (file)
@@ -218,6 +218,16 @@ public:
   /// 8 - V/V, V/E, E/E, V/F, E/F, F/F, V/S, E/S and F/S;<br>
   /// 9 - V/V, V/E, E/E, V/F, E/F, F/F, V/S, E/S, F/S and S/S - all interferences (Default value)
   GEOMAPI_EXPORT bool isSelfIntersected(const int theLevelOfCheck = 9) const;
+
+public:
+  class Comparator
+  {
+  public:
+    /// Return \c true if the address of the first shape is less than the address of the second
+    GEOMAPI_EXPORT
+    bool operator ()(const std::shared_ptr<GeomAPI_Shape>& theShape1,
+                     const std::shared_ptr<GeomAPI_Shape>& theShape2) const;
+  };
 };
 
 //! Pointer on list of shapes
index e5625c5c6c7d006be804d98d8b4207ff4657fa79..d1c014e1b6d0783a541d7fc46f32425296787b87 100644 (file)
@@ -49,6 +49,7 @@
 %shared_ptr(GeomAlgoAPI_Revolution)
 %shared_ptr(GeomAlgoAPI_Rotation)
 %shared_ptr(GeomAlgoAPI_Sewing)
+%shared_ptr(GeomAlgoAPI_SketchBuilder)
 %shared_ptr(GeomAlgoAPI_ShapeBuilder)
 %shared_ptr(GeomAlgoAPI_Translation)
 %shared_ptr(GeomAlgoAPI_Transform)
index 051c9266805fd9e87adc45ce3e61b48989999404..1f5dc4cfe6add343fde014c402defcb3d3bb6864 100644 (file)
@@ -24,6 +24,8 @@
 
 #include <BOPAlgo_BOP.hxx>
 #include <TopTools_ListOfShape.hxx>
+#include <TopoDS_Iterator.hxx>
+#include <TopExp_Explorer.hxx>
 
 //=================================================================================================
 GeomAlgoAPI_Boolean::GeomAlgoAPI_Boolean(const GeomShapePtr theObject,
@@ -128,3 +130,86 @@ void GeomAlgoAPI_Boolean::build(const ListOfShape& theObjects,
   this->setShape(aShape);
   this->setDone(true);
 }
+
+static bool isHistoryType(TopAbs_ShapeEnum theType) {
+  return theType == TopAbs_VERTEX || theType == TopAbs_EDGE ||
+         theType == TopAbs_FACE || theType == TopAbs_SOLID;
+}
+
+/// searches the corresponding result for theOld
+static void searchResult(const TopoDS_Shape& theOld, const TopoDS_Shape& theResult,
+  BOPAlgo_BOP* theBuilder, TopTools_MapOfShape& theNews)
+{
+  if (theResult.ShapeType() == theOld.ShapeType()) { // check some sub-shape produces a sub-result
+    if (theOld.IsSame(theResult)) {
+      theNews.Add(theResult);
+      return;
+    }
+    // searching for new result by sub-shapes of aSubType type
+    TopAbs_ShapeEnum aSubType = TopAbs_ShapeEnum(int(theOld.ShapeType()) + 1);
+    while(aSubType < TopAbs_VERTEX && !isHistoryType(aSubType))
+      aSubType = TopAbs_ShapeEnum(int(aSubType) + 1);
+    if (aSubType == TopAbs_SHAPE)
+      return;
+    TopTools_MapOfShape aResSubs;
+    for(TopExp_Explorer aResExp(theResult, aSubType); aResExp.More(); aResExp.Next())
+      aResSubs.Add(aResExp.Current());
+    for(TopExp_Explorer anExp(theOld, aSubType); anExp.More(); anExp.Next()) {
+      const TopTools_ListOfShape& aNewSubs = theBuilder->Modified(anExp.Current());
+      // searching for this new sub in theResult
+      for(TopTools_ListIteratorOfListOfShape aNewSub(aNewSubs); aNewSub.More(); aNewSub.Next()) {
+        if (aResSubs.Contains(aNewSub.Value())) {
+          theNews.Add(theResult);
+          return;
+        }
+      }
+    }
+  } else if (theResult.ShapeType() < theOld.ShapeType()) { // recursive search among sub-shapes
+    for(TopoDS_Iterator aSubResults(theResult); aSubResults.More(); aSubResults.Next()) {
+      searchResult(theOld, aSubResults.Value(), theBuilder, theNews);
+    }
+  }
+}
+
+// check the shape is on the higher level of compound or compsolid
+bool isInComp(const TopoDS_Shape& theComp, const TopoDS_Shape& theShape) {
+  if (theComp.ShapeType() == TopAbs_COMPOUND || theComp.ShapeType() == TopAbs_COMPSOLID) {
+    for(TopoDS_Iterator anIter(theComp); anIter.More(); anIter.Next()) {
+      if (isInComp(anIter.Value(), theShape))
+        return true;
+    }
+  } else return theShape.IsSame(theComp);
+  return false;
+}
+
+//=================================================================================================
+/// make arguments of Fuse produce result shapes with "modified" evolution
+void GeomAlgoAPI_Boolean::modified(const GeomShapePtr theOldShape, ListOfShape& theNewShapes)
+{
+  BOPAlgo_BOP* aBuilder = this->implPtr<BOPAlgo_BOP>();
+  if (aBuilder->Operation() == BOPAlgo_FUSE) { // only for fuse and when old is and argument
+    TopoDS_Shape anOld = theOldShape->impl<TopoDS_Shape>();
+    bool isOldComp = anOld.ShapeType() == TopAbs_COMPOUND || anOld.ShapeType() == TopAbs_COMPSOLID;
+    bool aFound = false;
+    TopTools_ListIteratorOfListOfShape anIter(aBuilder->Arguments());
+    for(; !aFound && anIter.More(); anIter.Next())
+      aFound = anOld.IsSame(anIter.Value()) || (!isOldComp && isInComp(anIter.Value(), anOld));
+    for(anIter.Initialize(aBuilder->Tools()); !aFound && anIter.More(); anIter.Next())
+      aFound = anOld.IsSame(anIter.Value()) || (!isOldComp && isInComp(anIter.Value(), anOld));
+    if (aFound) {
+      TopoDS_Shape aResult = aBuilder->Shape();
+      TopTools_MapOfShape aNewsMap;
+      searchResult(anOld, aResult, aBuilder, aNewsMap);
+      if (!aNewsMap.IsEmpty()) {
+        for(TopTools_MapIteratorOfMapOfShape aNewsIter(aNewsMap); aNewsIter.More(); aNewsIter.Next())
+        {
+          GeomShapePtr aShape(new GeomAPI_Shape);
+          aShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aNewsIter.Value()));
+          theNewShapes.push_back(aShape);
+        }
+        return;
+      }
+    }
+  }
+  GeomAlgoAPI_MakeShape::modified(theOldShape, theNewShapes); // default behavior
+}
index fc946cc187ad933ac92077cdea05be0407345771..d5a08376c3d3163fec204e9ca730396703e9788a 100644 (file)
@@ -56,6 +56,10 @@ public:
                                          const ListOfShape& theTools,
                                          const OperationType theOperationType);
 
+  /// Redefinition of the generic method for the Fuse problem: OCCT 30481
+  GEOMALGOAPI_EXPORT virtual void modified(const GeomShapePtr theOldShape,
+    ListOfShape& theNewShapes);
+
 private:
   /// Builds resulting shape.
   void build(const ListOfShape& theObjects,
index 2b1c8b12498d0384fdd9f8f89fbd708c096e7a4f..c09e24f98020f7f8d6f12aabfabc8ff00c5127d6 100644 (file)
@@ -19,6 +19,8 @@
 
 #include "GeomAlgoAPI_MakeVolume.h"
 
+#include <GeomAPI_ShapeExplorer.h>
+
 #include <GeomAlgoAPI_ShapeTools.h>
 
 #include <BOPAlgo_MakerVolume.hxx>
@@ -90,3 +92,32 @@ void GeomAlgoAPI_MakeVolume::build(const ListOfShape& theFaces)
   this->setShape(aShape);
   this->setDone(true);
 }
+
+//=================================================================================================
+void GeomAlgoAPI_MakeVolume::modified(const GeomShapePtr theOldShape,
+                                      ListOfShape& theNewShapes)
+{
+  if (theOldShape->shapeType() == GeomAPI_Shape::SOLID) {
+    ListOfShape aNewShapes;
+    // collect faces and parent shapes, if it is not done yet
+    if (!isNewShapesCollected(theOldShape, GeomAPI_Shape::FACE))
+      collectNewShapes(theOldShape, GeomAPI_Shape::FACE);
+
+    for (GeomAPI_ShapeExplorer anIt(shape(), GeomAPI_Shape::SOLID); anIt.more(); anIt.next()) {
+      for (GeomAPI_ShapeExplorer anExp(anIt.current(), GeomAPI_Shape::FACE);
+           anExp.more(); anExp.next()) {
+        GeomShapePtr anOldShapesCompound =
+            oldShapesForNew(theOldShape, anExp.current(), GeomAPI_Shape::FACE);
+        if (!anOldShapesCompound->isNull()) {
+          aNewShapes.push_back(anIt.current());
+          break;
+        }
+      }
+    }
+
+    if (!aNewShapes.empty())
+      theNewShapes = aNewShapes;
+  }
+  else
+    GeomAlgoAPI_MakeShape::modified(theOldShape, theNewShapes);
+}
index f6af7a2f9b614e339b151ab821c076aca01566cb..c478d9808a003c739cd0e619612eb47b54f0eef4 100644 (file)
@@ -43,6 +43,12 @@ public:
   GEOMALGOAPI_EXPORT GeomAlgoAPI_MakeVolume(const ListOfShape& theFaces,
     const bool theAvoidInternal);
 
+  /// \return the list of shapes modified from the shape \a theShape.
+  /// \param[in] theOldShape base shape.
+  /// \param[out] theNewShapes shapes modified from \a theShape. Does not cleared!
+  GEOMALGOAPI_EXPORT virtual void modified(const GeomShapePtr theOldShape,
+                                           ListOfShape& theNewShapes);
+
 private:
   /// Builds resulting shape.
   void build(const ListOfShape& theFaces);
index cbf2a75f5f8856b58e2fd01916cda7ae40e9b761..264c6bd30367566b8e8d401cf51d0cbaef9c7f38 100644 (file)
@@ -79,6 +79,30 @@ void GeomAlgoAPI_Sewing::build(const ListOfShape& theShapes)
 }
 
 //==================================================================================================
+#include <GeomAPI_ShapeExplorer.h>
+#include <GeomAPI_ShapeIterator.h>
+
+typedef std::map<GeomShapePtr, ListOfShape, GeomAPI_Shape::Comparator> MapFaceSolid;
+static void facesBelongingToSolids(const GeomShapePtr& theShape,
+                                   MapFaceSolid& theShapeRelations)
+{
+  for (GeomAPI_ShapeExplorer aSolidExp(theShape, GeomAPI_Shape::SHELL);
+       aSolidExp.more(); aSolidExp.next()) {
+    GeomShapePtr aSolid = aSolidExp.current();
+    for (GeomAPI_ShapeExplorer aFaceExp(aSolid, GeomAPI_Shape::FACE);
+         aFaceExp.more(); aFaceExp.next())
+      theShapeRelations[aFaceExp.current()].push_back(aSolid);
+  }
+}
+
+static bool isShapeInList(const GeomShapePtr& theShape, const ListOfShape& theList)
+{
+  for (ListOfShape::const_iterator anIt = theList.begin(); anIt != theList.end(); ++anIt)
+    if (theShape->isEqual(*anIt))
+      return true;
+  return false;
+}
+
 void GeomAlgoAPI_Sewing::modified(const std::shared_ptr<GeomAPI_Shape> theShape,
                                   ListOfShape& theHistory)
 {
@@ -100,4 +124,21 @@ void GeomAlgoAPI_Sewing::modified(const std::shared_ptr<GeomAPI_Shape> theShape,
     aGeomShape->setImpl(new TopoDS_Shape(anExp.Current()));
     theHistory.push_back(aGeomShape);
   }
+
+  if (theShape->shapeType() < GeomAPI_Shape::FACE) {
+    ListOfShape aNewShapes;
+    // collect faces and parent shapes, if it is not done yet
+    if (!isNewShapesCollected(theShape, GeomAPI_Shape::FACE))
+      collectNewShapes(theShape, GeomAPI_Shape::FACE);
+
+    for (GeomAPI_ShapeIterator anIt(shape()); anIt.more(); anIt.next()) {
+      GeomShapePtr anOldShapesCompound =
+          oldShapesForNew(theShape, anIt.current(), GeomAPI_Shape::FACE);
+      if (!anOldShapesCompound->isNull())
+        aNewShapes.push_back(anIt.current());
+    }
+
+    if (!aNewShapes.empty())
+      theHistory = aNewShapes;
+  }
 }
index 810b2aaf56fde9c60472c5c9095a4c757717cad9..4127ccf2cd7261b6acd0e892faac8f362ef7e0a1 100644 (file)
@@ -51,7 +51,7 @@ public:
   /// \return the total area of the faces of the current shape or 0.0 if it can be computed.
   GEOMALGOAPI_EXPORT static double area(const std::shared_ptr<GeomAPI_Shape> theShape);
 
-  /// \return the centre of mass of the current face.
+  /// \return the center of mass of the current face.
   /// The coordinates returned for the center of mass
   /// are expressed in the absolute Cartesian coordinate system.
   /// (This function works only for surfaces).
@@ -91,7 +91,7 @@ public:
   /// \brief Enlarges or reduces plane to fit bounding box.
   /// \return plane that fits to bounding box.
   /// \param[in] thePlane base plane.
-  /// \param[in] thePoints bounding box points (shoud be eight).
+  /// \param[in] thePoints bounding box points (should be eight).
   GEOMALGOAPI_EXPORT static std::shared_ptr<GeomAPI_Face> fitPlaneToBox(
     const std::shared_ptr<GeomAPI_Shape> thePlane,
     const std::list<std::shared_ptr<GeomAPI_Pnt> >& thePoints);
@@ -116,10 +116,10 @@ public:
 
   /// \brief Return a plane for list of shapes if they are all planar.
   /// \param[in] theShapes shapes to find plane.
-  /// \return plane where all shapes lie or empty ptr if they not planar.
+  /// \return plane where all shapes lie or empty pointer if they not planar.
   GEOMALGOAPI_EXPORT static std::shared_ptr<GeomAPI_Pln> findPlane(const ListOfShape& theShapes);
 
-  /// \brief Checks that vertex/edge is inside face or vertext inside wire.
+  /// \brief Checks that vertex/edge is inside face or vertex inside wire.
   /// \param[in] theSubShape shape that should be inside.
   /// \param[in] theBaseShape base shape.
   /// \return true if edge inside the face.
@@ -149,7 +149,7 @@ public:
                    std::pair<std::list<std::shared_ptr<GeomDataAPI_Point2D> >,
                              std::list<std::shared_ptr<ModelAPI_Object> > > > PointToRefsMap;
   /// \brief Performs the split of the shape by points.
-  /// \param[in] theBaseShape shape that should be splitted.
+  /// \param[in] theBaseShape shape that should be divided.
   /// \param[in] thePoints container of points to split
   /// \param[out] theShapes container of shapes after split
   GEOMALGOAPI_EXPORT static void splitShape(const std::shared_ptr<GeomAPI_Shape>& theBaseShape,
@@ -157,7 +157,7 @@ public:
                                       std::set<std::shared_ptr<GeomAPI_Shape> >& theShapes);
 
   /// \brief Performs the split of the shape by points.
-  /// \param[in] theBaseShape shape that should be splitted.
+  /// \param[in] theBaseShape shape that should be divided.
   /// \param[in] thePoints container of points to split
   /// \param[out] theShapes container of shapes after split
   GEOMALGOAPI_EXPORT static void splitShape_p(const std::shared_ptr<GeomAPI_Shape>& theBaseShape,
@@ -169,7 +169,7 @@ public:
                                     const std::set<std::shared_ptr<GeomAPI_Shape> >& theShapes);
 
 #ifdef FEATURE_MULTIROTATION_TWO_DIRECTIONS
-  /// \brief Returns a dir from a shape and an axis.
+  /// \brief Returns a direction from a shape and an axis.
   /// \param[in] theBaseShape shape whose center of mass serves as the starting point of the dir.
   /// \param[in] theAxis axis that serves as a direction for the dir
   /// \return dir that builds from center of mass of the base shape and the axis
@@ -178,7 +178,7 @@ public:
                                     const std::shared_ptr<GeomAPI_Ax1> theAxis);
 #endif
 
-  /// \brief Reapproximate a wire to build a single edge
+  /// \brief Re-approximate a wire to build a single edge
   GEOMALGOAPI_EXPORT static std::shared_ptr<GeomAPI_Edge> wireToEdge(
       const std::shared_ptr<GeomAPI_Wire>& theWire);
 
index fc8846c8b0a3d9638c1e848cc5bc011e7d002e97..cd4db1dad6e388b6bc7fe89ee2b85f5f25909098 100644 (file)
@@ -20,6 +20,8 @@
 #include <GeomAlgoAPI_SketchBuilder.h>
 #include <GeomAPI_PlanarEdges.h>
 
+#include <GeomAPI_Pln.h>
+
 #include <BOPAlgo_Builder.hxx>
 #include <BRep_Builder.hxx>
 #include <BRepTools_WireExplorer.hxx>
@@ -198,14 +200,15 @@ static void sortFaces(TopTools_ListOfShape& theAreas,
   }
 }
 
-void GeomAlgoAPI_SketchBuilder::createFaces(
+void GeomAlgoAPI_SketchBuilder::build(
     const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
     const std::shared_ptr<GeomAPI_Dir>& theDirX,
     const std::shared_ptr<GeomAPI_Dir>& theNorm,
-    const std::list<std::shared_ptr<GeomAPI_Shape> >& theFeatures,
-    std::list<std::shared_ptr<GeomAPI_Shape> >& theResultFaces)
+    const std::list<std::shared_ptr<GeomAPI_Shape> >& theEdges)
 {
-  if (theFeatures.empty())
+  myResultFaces.clear();
+  setDone(false);
+  if (theEdges.empty())
     return;
 
   BRep_Builder aBuilder;
@@ -215,24 +218,31 @@ void GeomAlgoAPI_SketchBuilder::createFaces(
   aBuilder.MakeFace(aPlnFace, aPlane, Precision::Confusion());
 
   // Use General Fuse algorithm to prepare all subfaces, bounded by given list of edges
-  BOPAlgo_Builder aBB;
-  aBB.AddArgument(aPlnFace);
+  BOPAlgo_Builder* aBB = new BOPAlgo_Builder;
+  aBB->AddArgument(aPlnFace);
+
+  setImpl(aBB);
+  setBuilderType(OCCT_BOPAlgo_Builder);
 
   NCollection_List<TopoDS_Shape> anEdges;
   NCollection_List<TopoDS_Shape>::Iterator aShapeIt;
-  std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator aFeatIt = theFeatures.begin();
-  for (; aFeatIt != theFeatures.end(); aFeatIt++) {
+  std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator aFeatIt = theEdges.begin();
+  for (; aFeatIt != theEdges.end(); aFeatIt++) {
     std::shared_ptr<GeomAPI_Shape> aShape(*aFeatIt);
     const TopoDS_Edge& anEdge = aShape->impl<TopoDS_Edge>();
     if (anEdge.ShapeType() == TopAbs_EDGE)
-      aBB.AddArgument(anEdge);
+      aBB->AddArgument(anEdge);
   }
-  aBB.Perform();
-  if (aBB.HasErrors())
+  aBB->Perform();
+  if (aBB->HasErrors())
     return;
+
+  TopoDS_Compound aResult;
+  aBuilder.MakeCompound(aResult);
+
   // Collect faces
-  TopTools_ListOfShape anAreas = aBB.Modified(aPlnFace);
-  sortFaces(anAreas, theFeatures); // sort faces by the edges in them
+  TopTools_ListOfShape anAreas = aBB->Modified(aPlnFace);
+  sortFaces(anAreas, theEdges); // sort faces by the edges in them
   TopTools_ListIteratorOfListOfShape anIt(anAreas);
   for (; anIt.More(); anIt.Next()) {
     TopoDS_Face aFace = TopoDS::Face(anIt.Value());
@@ -252,7 +262,7 @@ void GeomAlgoAPI_SketchBuilder::createFaces(
 
       // to make faces equal on different platforms, we will find
       // a vertex lying on an edge with the lowest index in the list of initial edges
-      TopoDS_Vertex aStartVertex = findStartVertex(aWire, aFace, theFeatures);
+      TopoDS_Vertex aStartVertex = findStartVertex(aWire, aFace, theEdges);
 
       TopoDS_Wire aNewWire;
       aBuilder.MakeWire(aNewWire);
@@ -288,30 +298,43 @@ void GeomAlgoAPI_SketchBuilder::createFaces(
     }
 
     // store face
-    aFace = aNewFace;
+    aBuilder.Add(aResult, aNewFace);
     std::shared_ptr<GeomAPI_Shape> aResFace(new GeomAPI_Shape);
     aResFace->setImpl(new TopoDS_Face(aFace));
-    theResultFaces.push_back(aResFace);
+    myResultFaces.push_back(aResFace);
   }
+
+  // update results
+  GeomShapePtr aResShape(new GeomAPI_Shape);
+  aResShape->setImpl(new TopoDS_Shape(aResult));
+  setShape(aResShape);
+  setDone(true);
 }
 
-void GeomAlgoAPI_SketchBuilder::createFaces(const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
-                                            const std::shared_ptr<GeomAPI_Dir>& theDirX,
-                                            const std::shared_ptr<GeomAPI_Dir>& theNorm,
-                                            const std::shared_ptr<GeomAPI_Shape>& theWire,
-                                std::list<std::shared_ptr<GeomAPI_Shape> >& theResultFaces)
+GeomAlgoAPI_SketchBuilder::GeomAlgoAPI_SketchBuilder(
+  const std::shared_ptr<GeomAPI_Pln>& thePlane,
+  const std::list<std::shared_ptr<GeomAPI_Shape> >& theEdges)
+{
+  build(thePlane->location(), thePlane->xDirection(), thePlane->direction(), theEdges);
+}
+
+GeomAlgoAPI_SketchBuilder::GeomAlgoAPI_SketchBuilder(
+    const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
+    const std::shared_ptr<GeomAPI_Dir>& theDirX,
+    const std::shared_ptr<GeomAPI_Dir>& theNorm,
+    const std::shared_ptr<GeomAPI_Shape>& theWire)
 {
   std::shared_ptr<GeomAPI_PlanarEdges> aWire =
     std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(theWire);
   if(aWire) {
     // Filter wires, return only faces.
-    createFaces(theOrigin, theDirX, theNorm, aWire->getEdges(), theResultFaces);
+    build(theOrigin, theDirX, theNorm, aWire->getEdges());
   } else { // it may be only one circle
     std::shared_ptr<GeomAPI_Edge> anEdge = std::dynamic_pointer_cast<GeomAPI_Edge>(theWire);
     if (anEdge) {
       std::list<std::shared_ptr<GeomAPI_Shape> > aList;
       aList.push_back(anEdge);
-      createFaces(theOrigin, theDirX, theNorm, aList, theResultFaces);
+      build(theOrigin, theDirX, theNorm, aList);
     }
   }
 }
index f7c1477ae6ac98c43fc9ffd9807d65655e1e7425..fe29d89be27d1190411e5381b2c14907fb6f3e39 100644 (file)
 #define GeomAlgoAPI_SketchBuilder_H_
 
 #include <GeomAlgoAPI.h>
+#include <GeomAlgoAPI_MakeShape.h>
 
 #include <memory>
 #include <list>
 
-#include <GeomAPI_Dir.h>
-#include <GeomAPI_Pnt.h>
-#include <GeomAPI_Shape.h>
+class GeomAPI_Dir;
+class GeomAPI_Pln;
+class GeomAPI_Pnt;
+class GeomAPI_Shape;
 
 /** \class GeomAlgoAPI_SketchBuilder
  *  \ingroup DataAlgo
  *  \brief Creates planar faces based on the list of Sketch features
  */
-class GEOMALGOAPI_EXPORT GeomAlgoAPI_SketchBuilder
+class GeomAlgoAPI_SketchBuilder : public GeomAlgoAPI_MakeShape
 {
- public:
-  /** \brief Creates list of faces based on the features of the sketch
-   *  \param[in]  theOrigin      origin point of the sketch
-   *  \param[in]  theDirX        x-direction of the sketch
-   *  \param[in]  theNorm        normal of the sketch
-   *  \param[in]  theFeatures    initial features of the sketch
-   *  \param[out] theResultFaces faces based on closed wires
+public:
+  /** \brief Creates list of faces based on the edges of the sketch
+   *  \param[in]  thePlane  plane of the sketch
+   *  \param[in]  theEdges  initial edges of the sketch
    *
    *  The algorithm searches all loops of edges surrounding lesser areas.
    */
-  static void createFaces(const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
-                          const std::shared_ptr<GeomAPI_Dir>& theDirX,
-                          const std::shared_ptr<GeomAPI_Dir>& theNorm,
-                          const std::list<std::shared_ptr<GeomAPI_Shape> >& theFeatures,
-                          std::list<std::shared_ptr<GeomAPI_Shape> >& theResultFaces);
+  GEOMALGOAPI_EXPORT
+  GeomAlgoAPI_SketchBuilder(const std::shared_ptr<GeomAPI_Pln>& thePlane,
+                            const std::list<std::shared_ptr<GeomAPI_Shape> >& theEdges);
 
   /** \brief Creates list of faces and unclosed wires on basis of the features of the sketch
    *  \param[in]  theOrigin      origin point of the sketch
    *  \param[in]  theDirX        x-direction of the sketch
    *  \param[in]  theNorm        normal of the sketch
    *  \param[in]  theWire        a wire which contains all edges
-   *  \param[out] theResultFaces faces based on closed wires
    *
    *  The algorithm searches all loops of edges surrounding lesser areas.
    */
-  static void createFaces(const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
-                          const std::shared_ptr<GeomAPI_Dir>& theDirX,
-                          const std::shared_ptr<GeomAPI_Dir>& theNorm,
-                          const std::shared_ptr<GeomAPI_Shape>& theWire,
-                          std::list<std::shared_ptr<GeomAPI_Shape> >& theResultFaces);
+  GEOMALGOAPI_EXPORT
+  GeomAlgoAPI_SketchBuilder(const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
+                            const std::shared_ptr<GeomAPI_Dir>& theDirX,
+                            const std::shared_ptr<GeomAPI_Dir>& theNorm,
+                            const std::shared_ptr<GeomAPI_Shape>& theWire);
+
+  /// Return list of created faces
+  GEOMALGOAPI_EXPORT const std::list<std::shared_ptr<GeomAPI_Shape> >& faces() const
+  { return myResultFaces; }
+
+private:
+  void build(const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
+             const std::shared_ptr<GeomAPI_Dir>& theDirX,
+             const std::shared_ptr<GeomAPI_Dir>& theNorm,
+             const std::list<std::shared_ptr<GeomAPI_Shape> >& theEdges);
+
+private:
+  std::list<std::shared_ptr<GeomAPI_Shape> > myResultFaces;
 };
 
 #endif
index d087d0715af32adb3f10201ce0f8287c9ae216da..320c30d8fd31b8b7ab81c1093c22f938b416873a 100644 (file)
@@ -112,6 +112,8 @@ void GeomAlgoAPI_UnifySameDomain::modified(const std::shared_ptr<GeomAPI_Shape>
   const ShapeUpgrade_UnifySameDomain& aUnifyAlgo = this->impl<ShapeUpgrade_UnifySameDomain>();
 
   for (int aIsModified = 0; aIsModified <= 1; aIsModified++) {
+    if (!aUnifyAlgo.History()->IsSupportedType(aShape)) // to avoid crash in BRepTools_History
+      continue;
     const TopTools_ListOfShape& aMList = aIsModified ?
       aUnifyAlgo.History()->Modified(aShape) : aUnifyAlgo.History()->Generated(aShape);
     for (TopTools_ListIteratorOfListOfShape aModified(aMList); aModified.More(); aModified.Next()) {
index 053443ac730ee00d6b2636fa56f7a3f56c595c04..92be8663dbc26432cf9469ff69e52055c14d0e7e 100644 (file)
@@ -1085,9 +1085,10 @@ void Model_AttributeSelection::computeValues(
   if (aWasWholeContext) {
     theValShape = theOldContext->shape()->impl<TopoDS_Shape>();
   }
+  TopAbs_ShapeEnum aValType = theValShape.ShapeType();
   TopoDS_Shape aNewContShape = theNewContext->shape()->impl<TopoDS_Shape>();
   // if a new value is unchanged in the new context, do nothing: value is correct
-  TopExp_Explorer aSubExp(aNewContShape, theValShape.ShapeType());
+  TopExp_Explorer aSubExp(aNewContShape, aValType);
   for(; aSubExp.More(); aSubExp.Next()) {
     if (aSubExp.Current().IsSame(theValShape)) {
       theShapes.Append(theValShape);
@@ -1132,17 +1133,15 @@ void Model_AttributeSelection::computeValues(
                 return;
               }
               // don't add edges generated from faces
-              if (aPairIter.NewShape().ShapeType() <= theValShape.ShapeType())
+              if (aPairIter.NewShape().ShapeType() <= aValType)
                 theShapes.Append(aPairIter.NewShape());
             }
           } else if (!aPairIter.OldShape().IsNull()) { // search shape that contains this sub
-            TopExp_Explorer anExp(aPairIter.OldShape(), theValShape.ShapeType());
+            TopExp_Explorer anExp(aPairIter.OldShape(), aValType);
             for(; anExp.More(); anExp.Next()) {
               if (anExp.Current().IsSame(theValShape)) { // found a new container
-                if (aPairIter.NewShape().IsNull()) {// value was removed
-                  theShapes.Clear();
-                  return;
-                }
+                if (aPairIter.NewShape().IsNull()) // skip removed high-level shape
+                  continue;
                 aNewToOld.Bind(aPairIter.NewShape(), aPairIter.OldShape());
                 anOlds.Add(aPairIter.OldShape());
                 break;
@@ -1154,11 +1153,37 @@ void Model_AttributeSelection::computeValues(
     }
   }
   if (aToFindPart == 2 && !aNewToOld.IsEmpty()) {
+    // also iterate the whole old shape to find not-modified shapes that contain this old
+    TopoDS_Shape anOldContShape = theOldContext->shape()->impl<TopoDS_Shape>();
+    NCollection_Map<TopAbs_ShapeEnum> aNewTypes; // types of shapes to iterate
+    TopTools_DataMapOfShapeShape::Iterator aNewTypeIter(aNewToOld);
+    for(; aNewTypeIter.More(); aNewTypeIter.Next()) {
+      if (aNewTypeIter.Key().ShapeType() != aValType)
+        aNewTypes.Add(aNewTypeIter.Key().ShapeType());
+    }
+    NCollection_Map<TopAbs_ShapeEnum>::Iterator aTypeIter(aNewTypes);
+    for(; aTypeIter.More(); aTypeIter.Next()) {
+      for(TopExp_Explorer anExp(anOldContShape, aTypeIter.Value()); anExp.More(); anExp.Next()) {
+        TopoDS_Shape anOld = anExp.Current();
+        if (aNewToOld.IsBound(anOld) || anOlds.Contains(anOld)) // this was modified
+          continue;
+        TopExp_Explorer aValExp(anOld, aValType);
+        for(; aValExp.More(); aValExp.Next()) {
+          const TopoDS_Shape& anUnchanged = aValExp.Current();
+          if (anUnchanged.IsSame(theValShape)) {
+            aNewToOld.Bind(anOld, anOld);
+            anOlds.Add(anOld);
+            break;
+          }
+        }
+      }
+    }
+
     // map of sub-shapes -> number of occurrences 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());
+      TopExp_Explorer aSubExp(aContIter.Key(), aValType);
       for(; aSubExp.More(); aSubExp.Next()) {
         if (!aSubs.IsBound(aSubExp.Current())) {
           aSubs.Bind(aSubExp.Current(), TopTools_MapOfShape());
@@ -1173,12 +1198,51 @@ void Model_AttributeSelection::computeValues(
       aSubsIter(aSubs);
     for(; aSubsIter.More(); aSubsIter.Next()) {
       if (aSubsIter.Value().Size() == aCountInOld) {
-        theShapes.Append(aSubsIter.Key());
+        TopoDS_Shape anOld = aSubsIter.Key();
+        // check this exists in the new shape
+        TopExp_Explorer aNew(aNewContShape, anOld.ShapeType());
+        for (; aNew.More(); aNew.Next()) {
+          if (aNew.Current().IsSame(anOld))
+            break;
+        }
+        if (aNew.More())
+          theShapes.Append(anOld);
       }
     }
   }
   if (theShapes.IsEmpty()) { // nothing was changed
-    theShapes.Append(aWasWholeContext ? TopoDS_Shape() : theValShape);
+    if (aWasWholeContext)
+      theShapes.Append(TopoDS_Shape());
+    else { // if theValShape exists in new context, add it without changes, otherwise - nothing
+      for (TopExp_Explorer aNew(aNewContShape, aValType); aNew.More(); aNew.Next()){
+        if (aNew.Current().IsSame(theValShape)) {
+          theShapes.Append(theValShape);
+          break;
+        }
+      }
+    }
+  } else if (theShapes.Size() > 1) {
+    // check it is possible to remove extra sub-shapes:
+    // keep only shapes with the same number of containers if possible
+    TopAbs_ShapeEnum anAncType = TopAbs_FACE;
+    if (aValType == TopAbs_VERTEX)
+      anAncType = TopAbs_EDGE;
+    TopoDS_Shape anOldContext = theOldContext->shape()->impl<TopoDS_Shape>();
+    TopTools_IndexedDataMapOfShapeListOfShape anOldMap;
+    TopExp::MapShapesAndUniqueAncestors(anOldContext, aValType,  anAncType, anOldMap);
+    if (anOldMap.Contains(theValShape)) {
+      int aNumInOld = anOldMap.FindFromKey(theValShape).Extent();
+      TopTools_IndexedDataMapOfShapeListOfShape aNewMap;
+      TopExp::MapShapesAndUniqueAncestors(aNewContShape, aValType,  anAncType, aNewMap);
+      TopTools_ListOfShape aNewResults;
+      for(TopTools_ListOfShape::Iterator aNewSubs(theShapes); aNewSubs.More(); aNewSubs.Next()) {
+        TopoDS_Shape aCand = aNewSubs.Value();
+        if (aNewMap.Contains(aCand) && aNewMap.FindFromKey(aCand).Extent() == aNumInOld)
+          aNewResults.Append(aCand);
+      }
+      if (!aNewResults.IsEmpty() && aNewResults.Size() < theShapes.Size())
+        theShapes = aNewResults;
+    }
   }
 }
 
@@ -1188,7 +1252,6 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr<Model_Document>
   std::list<ResultPtr>& theResults, TopTools_ListOfShape& theValShapes)
 {
   std::set<ResultPtr> aResults; // to avoid duplicates, new context, null if deleted
-  TopTools_ListOfShape aResContShapes;
   // iterate context and shape, but also if it is sub-shape of main shape, check also it
   TopTools_ListOfShape aContextList;
   aContextList.Append(theContShape);
@@ -1225,7 +1288,6 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr<Model_Document>
       aModifIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNewNS);
       if (aNewNS->Evolution() == TNaming_MODIFY || aNewNS->Evolution() == TNaming_GENERATED) {
         aResults.insert(aModifierObj);
-        aResContShapes.Append(aModifierObj->shape()->impl<TopoDS_Shape>());
       } else if (aNewNS->Evolution() == TNaming_DELETE) { // a shape was deleted => result is empty
         aResults.insert(ResultPtr());
       } else { // not-processed modification => don't support it
@@ -1233,8 +1295,58 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr<Model_Document>
       }
     }
   }
-  if (aResults.empty())
+  // if there exist context composite and sub-result(s), leave only sub(s)
+  for(std::set<ResultPtr>::iterator aResIter = aResults.begin(); aResIter != aResults.end();) {
+    ResultPtr aParent = ModelAPI_Tools::bodyOwner(*aResIter);
+    for(; aParent.get(); aParent = ModelAPI_Tools::bodyOwner(aParent))
+      if (aResults.count(aParent))
+        break;
+    if (aParent.get()) { // erase from set, so, restart iteration
+      aResults.erase(aParent);
+      aResIter = aResults.begin();
+    } else aResIter++;
+  }
+
+  if (aResults.empty()) {
+    // check the context become concealed by operation which is earlier than this selection
+    std::list<ResultPtr> allRes;
+    ResultPtr aRoot = ModelAPI_Tools::bodyOwner(theContext, true);
+    if (!aRoot.get())
+      aRoot = theContext;
+    ResultBodyPtr aRootBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aRoot);
+    if (aRootBody.get()) {
+      ModelAPI_Tools::allSubs(aRootBody, allRes);
+      allRes.push_back(aRootBody);
+    } else
+      allRes.push_back(aRoot);
+
+    FeaturePtr aThisFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
+    for (std::list<ResultPtr>::iterator aSub = allRes.begin(); aSub != allRes.end(); aSub++) {
+      ResultPtr aResCont = *aSub;
+      const std::set<AttributePtr>& aRefs = aResCont->data()->refsToMe();
+      std::set<AttributePtr>::const_iterator aRef = aRefs.begin();
+      for (; aRef != aRefs.end(); aRef++) {
+        if (!aRef->get() || !(*aRef)->owner().get())
+          continue;
+        // concealed attribute only
+        FeaturePtr aRefFeat = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRef)->owner());
+        if (aRefFeat == aThisFeature)
+          continue;
+        if (!ModelAPI_Session::get()->validators()->isConcealed(
+          aRefFeat->getKind(), (*aRef)->id()))
+          continue;
+        if (theDoc->isLaterByDep(aThisFeature, aRefFeat)) {
+          // for extrusion cut in python script the nested sketch reference may be concealed before
+          // it is nested, so, check this composite feature is valid
+          static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
+          // need to be validated to update the "Apply" state if not previewed
+          if (aFactory->validate(aRefFeat))
+            return true; // feature conceals result, return true, so the context will be removed
+        }
+      }
+    }
     return false; // no modifications found, must stay the same
+  }
   // iterate all results to find further modifications
   std::set<ResultPtr>::iterator aResIter = aResults.begin();
   for(; aResIter != aResults.end(); aResIter++) {
@@ -1271,7 +1383,7 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr<Model_Document>
   return true; // theResults must be empty: everything is deleted
 }
 
-void Model_AttributeSelection::updateInHistory()
+void Model_AttributeSelection::updateInHistory(bool& theRemove)
 {
   ResultPtr aContext = std::dynamic_pointer_cast<ModelAPI_Result>(myRef.value());
   // only bodies and parts may be modified later in the history, don't do anything otherwise
@@ -1344,17 +1456,36 @@ void Model_AttributeSelection::updateInHistory()
   TopTools_ListOfShape aValShapes;
   if (searchNewContext(aDoc, aNewCShape, aContext, aValShape, aContLab, aNewContexts, aValShapes))
   {
+    std::set<ResultPtr> allContexts, aSkippedContext;
+    std::list<ResultPtr>::iterator aNewContext = aNewContexts.begin();
+    for(; aNewContext != aNewContexts.end(); aNewContext++)
+      allContexts.insert(*aNewContext);
+
+    // if there exist context composite and sub-result(s), leave only sub(s)
+    std::set<ResultPtr>::iterator aResIter = allContexts.begin();
+    for(; aResIter != allContexts.end(); aResIter++) {
+      ResultPtr aParent = ModelAPI_Tools::bodyOwner(*aResIter);
+      for(; aParent.get(); aParent = ModelAPI_Tools::bodyOwner(aParent))
+        if (allContexts.count(aParent))
+          aSkippedContext.insert(aParent);
+    }
+
     GeomAPI_Shape::ShapeType aListShapeType = GeomAPI_Shape::SHAPE;
     if (myParent) {
-      if (myParent->selectionType() == "VERTEX") aListShapeType = GeomAPI_Shape::VERTEX;
-      else if (myParent->selectionType() == "EDGE") aListShapeType = GeomAPI_Shape::EDGE;
-      else if (myParent->selectionType() == "FACE") aListShapeType = GeomAPI_Shape::FACE;
+      if (myParent->selectionType() == "VERTEX" || myParent->selectionType() == "Vertices")
+        aListShapeType = GeomAPI_Shape::VERTEX;
+      else if (myParent->selectionType() == "EDGE" || myParent->selectionType() == "Edges")
+        aListShapeType = GeomAPI_Shape::EDGE;
+      else if (myParent->selectionType() == "FACE" || myParent->selectionType() == "Faces")
+        aListShapeType = GeomAPI_Shape::FACE;
     }
 
     std::list<ResultPtr>::iterator aNewCont = aNewContexts.begin();
     TopTools_ListIteratorOfListOfShape aNewValues(aValShapes);
     bool aFirst = true; // first is set to this, next are appended to parent
     for(; aNewCont != aNewContexts.end(); aNewCont++, aNewValues.Next()) {
+      if (aSkippedContext.count(*aNewCont))
+        continue;
 
       GeomShapePtr aValueShape;
       if (!aNewValues.Value().IsNull()) {
@@ -1372,81 +1503,23 @@ void Model_AttributeSelection::updateInHistory()
         continue;
       }
 
-      ResultPtr aSetContext;
       if (aFirst) {
         setValue(*aNewCont, aValueShape);
-        aSetContext = context();
+        aFirst = false;
       } else if (myParent) {
-        myParent->append(*aNewCont, aValueShape);
-        aSetContext = myParent->value(myParent->size() - 1)->context();
-      }
-
-      // #2826 : error if context is concealed by new context where the value is not presented
-      if (aSetContext.get()) {
-        bool anError = false;
-        std::list<ResultPtr> allRes;
-        ResultPtr aCompContext;
-        ResultBodyPtr aCompBody = ModelAPI_Tools::bodyOwner(aSetContext, true);
-        if (aCompBody.get()) {
-          ModelAPI_Tools::allSubs(aCompBody, allRes);
-          allRes.push_back(aCompBody);
-          aCompContext = aCompBody;
-        }
-        if (allRes.empty())
-          allRes.push_back(aSetContext);
-
-        std::list<ResultPtr>::iterator aSub = allRes.begin();
-        for (; !anError && aSub != allRes.end(); aSub++) {
-          ResultPtr aResCont = *aSub;
-          ResultBodyPtr aResBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResCont);
-          const std::set<AttributePtr>& aRefs = aResCont->data()->refsToMe();
-          std::set<AttributePtr>::const_iterator aRef = aRefs.begin();
-          for (; aRef != aRefs.end(); aRef++) {
-            if (!aRef->get() || !(*aRef)->owner().get())
-              continue;
-            // concealed attribute only
-            FeaturePtr aRefFeat = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRef)->owner());
-            if (!aRefFeat.get())
-              continue;
-            if (!ModelAPI_Session::get()->validators()->isConcealed(
-              aRefFeat->getKind(), (*aRef)->id()))
-              continue;
-            // check the found feature is older than this attribute
-            if (aRefFeat == aThisFeature || aDoc->isLaterByDep(aRefFeat, aThisFeature))
-              continue;
-            // check the found feature don't have the value-shape
-            GeomShapePtr aValue = aFirst ? value() : myParent->value(myParent->size() - 1)->value();
-            if (aValue.get()) {
-              std::list<ResultPtr>::const_iterator aRefResults = aRefFeat->results().cbegin();
-              for(; aRefResults != aRefFeat->results().cend(); aRefResults++) {
-                if ((*aRefResults)->shape().get() &&
-                    !(*aRefResults)->shape()->isSubShape(aValue, false)) { // set error
-                  ResultPtr anEmptyContext;
-                  std::shared_ptr<GeomAPI_Shape> anEmptyShape;
-                  if (aFirst) {
-                    setValue(anEmptyContext, anEmptyShape); // nullify the selection
-                  } else {
-                    myParent->value(myParent->size() - 1)->setValue(anEmptyContext, anEmptyShape);
-                  }
-                  Events_InfoMessage("Model_AttributeSelection",
-                    "Selection of sub-shape of already modified result").send();
-                  anError = true;
-                  break;
-                }
-              }
-              if (anError)
-                break;
-            }
-          }
-        }
+        if (!myParent->isInList(*aNewCont, aValueShape)) // avoid addition of duplicates
+          myParent->append(*aNewCont, aValueShape);
       }
-      aFirst = false;
     }
     if (aFirst) { // nothing was added, all results were deleted
-      ResultPtr anEmptyContext;
-      std::shared_ptr<GeomAPI_Shape> anEmptyShape;
-      setValue(anEmptyContext, anEmptyShape); // nullify the selection
-      return;
+      if (myParent) {
+        theRemove = true;
+      } else {
+        ResultPtr anEmptyContext;
+        std::shared_ptr<GeomAPI_Shape> anEmptyShape;
+        setValue(anEmptyContext, anEmptyShape); // nullify the selection
+        return;
+      }
     }
   }
 }
index 25d852c695f92ca292c9f23e53a8162d0e9537ba..1896caa017f435687409907b388f0ac42a6c2d06 100644 (file)
@@ -121,7 +121,8 @@ public:
 
   /// Updates the arguments of selection if something was affected by creation
   /// or reorder of features upper in the history line (issue #1757)
-  MODEL_EXPORT virtual void updateInHistory();
+  /// Returns theRemove true if this attribute must be removed (become deleted)
+  MODEL_EXPORT virtual void updateInHistory(bool& theRemove);
 
   // Implementation of the name generator method from the Selector package
   // This method returns the context name by the label of the sub-selected shape
index 7b2dfb6f8cd5abcc17c93fd5dca8ad46d702590c..2ab3b1cff4a3c553e434bb9d3fb2138a1358f9c6 100644 (file)
@@ -49,7 +49,7 @@ class Model_AttributeString : public ModelAPI_AttributeString
   MODEL_EXPORT virtual std::wstring valueW();
 
  protected:
-  /// Initializes attibutes
+  /// Initializes attributes
   Model_AttributeString(TDF_Label& theLabel);
   /// Reinitializes the internal state of the attribute (may be needed on undo/redo, abort, etc)
   virtual void reinit();
index 913a773ada5efb0f960d9b934ebbe458f4193cc9..5c89b7cc31fa069cdcfb89defed73961c4f32af1 100644 (file)
@@ -119,6 +119,53 @@ Model_BodyBuilder::Model_BodyBuilder(ModelAPI_Object* theOwner)
 {
 }
 
+/// Checks that shape is presented in the tree with not-selection evolution
+/// In theOriginalLabel it returns label where NS of old sub-shape is stored
+static bool isShapeInTree(const TDF_Label& theAccess1, const TDF_Label& theAccess2,
+  TopoDS_Shape theShape, TDF_Label& theOriginalLabel)
+{
+  bool aResult = TNaming_Tool::HasLabel(theAccess1, theShape);
+  if (aResult) { //check evolution and a label of this shape
+    for(TNaming_SameShapeIterator aShapes(theShape, theAccess1); aShapes.More(); aShapes.Next())
+    {
+      static Handle(TNaming_NamedShape) aNS;
+      if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+        if (aNS->Evolution() != TNaming_SELECTED) {
+          theOriginalLabel = aNS->Label();
+          return true;
+        }
+      }
+    }
+  }
+  if (!theAccess2.IsNull()) {
+    static const TDF_Label anEmpty;
+    return isShapeInTree(theAccess2, anEmpty, theShape, theOriginalLabel);
+  }
+  return false;
+}
+
+/// Stores entry to the external label in the entries list at this label
+static void storeExternalReference(const TDF_Label& theExternal, const TDF_Label theThis)
+{
+  // store information about the external document reference to restore old shape on open
+  if (!theExternal.IsNull() && !theExternal.Root().IsEqual(theThis.Root())) {
+    Handle(TDataStd_ExtStringList) anEntries;
+    if (!theThis.FindAttribute(kEXTERNAL_SHAPE_REF, anEntries)) {
+      anEntries = TDataStd_ExtStringList::Set(theThis, kEXTERNAL_SHAPE_REF);
+    }
+    TCollection_AsciiString anEntry;
+    TDF_Tool::Entry(theExternal, anEntry);
+    // check it already contains this entry
+    TDataStd_ListOfExtendedString::Iterator anIter(anEntries->List());
+    for(; anIter.More(); anIter.Next())
+      if (anIter.Value() == anEntry)
+        break;
+    if (!anIter.More()) {
+      anEntries->Append(anEntry);
+    }
+  }
+}
+
 void Model_BodyBuilder::store(const GeomShapePtr& theShape,
                               const bool theIsStoreSameShapes)
 {
@@ -165,15 +212,15 @@ void Model_BodyBuilder::store(const GeomShapePtr& theShape,
 }
 
 void Model_BodyBuilder::storeGenerated(const GeomShapePtr& theFromShape,
-  const GeomShapePtr& theToShape)
+  const GeomShapePtr& theToShape, const bool theIsCleanStored)
 {
   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
   if (aData) {
     TDF_Label aShapeLab = aData->shapeLab();
     // clean builders
-    clean();
-    // store the new shape as primitive
-    TNaming_Builder aBuilder(aShapeLab);
+    if (theIsCleanStored)
+      clean();
+    TNaming_Builder* aBuilder = builder(0);
     if (!theFromShape || !theToShape)
       return;  // bad shape
     TopoDS_Shape aShapeBasis = theFromShape->impl<TopoDS_Shape>();
@@ -182,22 +229,70 @@ void Model_BodyBuilder::storeGenerated(const GeomShapePtr& theFromShape,
     TopoDS_Shape aShapeNew = theToShape->impl<TopoDS_Shape>();
     if (aShapeNew.IsNull())
       return;  // null shape inside
-    aBuilder.Generated(aShapeBasis, aShapeNew);
+
+    // There is no sense to write history if old shape does not exist in the document.
+    TDF_Label anAccess2 = std::dynamic_pointer_cast<Model_Document>(
+      ModelAPI_Session::get()->moduleDocument())->generalLabel();
+    TDF_Label anOriginalLabel;
+    if (!isShapeInTree(aData->shapeLab(), anAccess2, aShapeBasis, anOriginalLabel)) {
+      if (aBuilder->NamedShape()->Get().IsNull()) { // store as primitive if alone anyway
+        aBuilder->Generated(aShapeNew);
+      }
+    } else {
+      if (aBuilder->NamedShape()->Evolution() == TNaming_PRIMITIVE) { // erase primitive before
+        myBuilders.erase(0);
+        aBuilder = builder(0);
+      }
+
+      aBuilder->Generated(aShapeBasis, aShapeNew);
+      // store information about the external document reference to restore old shape on open
+      storeExternalReference(anOriginalLabel, aBuilder->NamedShape()->Label());
+    }
+
     // register name
-    if(!aBuilder.NamedShape()->IsEmpty()) {
+    if(!aBuilder->NamedShape()->IsEmpty()) {
       Handle(TDataStd_Name) anAttr;
-      if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
+      if(aBuilder->NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
         std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
         if(!aName.empty()) {
           std::shared_ptr<Model_Document> aDoc =
             std::dynamic_pointer_cast<Model_Document>(document());
-          aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName);
+          aDoc->addNamingName(aBuilder->NamedShape()->Label(), aName);
         }
       }
     }
   }
 }
 
+void Model_BodyBuilder::storeGenerated(const std::list<GeomShapePtr>& theFromShapes,
+  const GeomShapePtr& theToShape, const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
+{
+  bool aStored = false;
+  std::list<GeomShapePtr>::const_iterator anOldIter = theFromShapes.cbegin();
+  for (; anOldIter != theFromShapes.cend(); anOldIter++) {
+    bool aStore = (*anOldIter)->isCompound() || (*anOldIter)->isShell() || (*anOldIter)->isWire();
+    if (!aStore) {
+      ListOfShape aNews; // check this old really generates theToShape
+      theMakeShape->generated(*anOldIter, aNews);
+      ListOfShape::iterator aNewIter = aNews.begin();
+      for (; aNewIter != aNews.end(); aNewIter++) {
+        if (theToShape->isSame(*aNewIter))
+          break;
+      }
+      aStore = aNewIter != aNews.end();
+    }
+    if (aStore) {
+      storeGenerated(*anOldIter, theToShape, !aStored);
+      TNaming_Builder* aBuilder = builder(0);
+      aStored = !aBuilder->NamedShape()->IsEmpty();
+    }
+  }
+  if (!aStored) { // store as PRIMITIVE, but clean in any way
+    store(theToShape);
+    return;
+  }
+}
+
 TNaming_Builder* Model_BodyBuilder::builder(const int theTag)
 {
   std::map<int, TNaming_Builder*>::iterator aFind = myBuilders.find(theTag);
@@ -218,7 +313,6 @@ void Model_BodyBuilder::storeModified(const GeomShapePtr& theOldShape,
   if (aData) {
     // clean builders
     if (theIsCleanStored) clean();
-    // store the new shape as primitive
     TNaming_Builder* aBuilder = builder(0);
     if (!theOldShape || !theNewShape)
       return;  // bad shape
@@ -228,10 +322,29 @@ void Model_BodyBuilder::storeModified(const GeomShapePtr& theOldShape,
     TopoDS_Shape aShapeNew = theNewShape->impl<TopoDS_Shape>();
     if (aShapeNew.IsNull())
       return;  // null shape inside
-    aBuilder->Modify(aShapeOld, aShapeNew);
+
+    // There is no sense to write history if old shape does not exist in the document.
+    TDF_Label anAccess2 = std::dynamic_pointer_cast<Model_Document>(
+      ModelAPI_Session::get()->moduleDocument())->generalLabel();
+    TDF_Label anOriginalLabel;
+    if (!isShapeInTree(aData->shapeLab(), anAccess2, aShapeOld, anOriginalLabel)) {
+      if (aBuilder->NamedShape()->Get().IsNull()) { // store as primitive if alone anyway
+        aBuilder->Generated(aShapeNew);
+      }
+    } else {
+      if (aBuilder->NamedShape()->Evolution() == TNaming_PRIMITIVE) { // erase primitive before
+        myBuilders.erase(0);
+        aBuilder = builder(0);
+      }
+
+      aBuilder->Modify(aShapeOld, aShapeNew);
+      // store information about the external document reference to restore old shape on open
+      storeExternalReference(anOriginalLabel, aBuilder->NamedShape()->Label());
+    }
+
     if(!aBuilder->NamedShape()->IsEmpty()) {
       Handle(TDataStd_Name) anAttr;
-      if(aBuilder->NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
+      if(aBuilder->NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(), anAttr)) {
         std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
         if(!aName.empty()) {
           std::shared_ptr<Model_Document> aDoc =
@@ -243,6 +356,36 @@ void Model_BodyBuilder::storeModified(const GeomShapePtr& theOldShape,
   }
 }
 
+void Model_BodyBuilder::storeModified(const std::list<GeomShapePtr>& theOldShapes,
+  const GeomShapePtr& theNewShape, const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
+{
+  bool aStored = false;
+  std::list<GeomShapePtr>::const_iterator anOldIter = theOldShapes.cbegin();
+  for(; anOldIter != theOldShapes.cend(); anOldIter++) {
+    // compounds may cause crash if call "modified"
+    bool aStore = (*anOldIter)->isCompound() || (*anOldIter)->isShell() || (*anOldIter)->isWire();
+    if (!aStore) {
+      ListOfShape aNews; // check this old really modifies theNewShape
+      theMakeShape->modified(*anOldIter, aNews);
+      ListOfShape::iterator aNewIter = aNews.begin();
+      for(; aNewIter != aNews.end(); aNewIter++) {
+        if (theNewShape->isSame(*aNewIter))
+          break;
+      }
+      aStore = aNewIter != aNews.end();
+    }
+    if (aStore) {
+      storeModified(*anOldIter, theNewShape, !aStored);
+      TNaming_Builder* aBuilder = builder(0);
+      aStored = !aBuilder->NamedShape()->IsEmpty();
+    }
+  }
+  if (!aStored) { // store as PRIMITIVE, but clean in any way
+    store(theNewShape);
+    return;
+  }
+}
+
 void Model_BodyBuilder::clean()
 {
   TDF_Label aLab = std::dynamic_pointer_cast<Model_Data>(data())->shapeLab();
@@ -430,53 +573,6 @@ static void keepTopLevelShapes(ListOfShape& theShapes,
   }
 }
 
-/// Checks that shape is presented in the tree with not-selection evolution
-/// In theOriginalLabel it returns label where NS of old sub-shape is stored
-static bool isShapeInTree(const TDF_Label& theAccess1, const TDF_Label& theAccess2,
-  TopoDS_Shape theShape, TDF_Label& theOriginalLabel)
-{
-  bool aResult = TNaming_Tool::HasLabel(theAccess1, theShape);
-  if (aResult) { //check evolution and a label of this shape
-    for(TNaming_SameShapeIterator aShapes(theShape, theAccess1); aShapes.More(); aShapes.Next())
-    {
-      static Handle(TNaming_NamedShape) aNS;
-      if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
-        if (aNS->Evolution() != TNaming_SELECTED) {
-          theOriginalLabel = aNS->Label();
-          return true;
-        }
-      }
-    }
-  }
-  if (!theAccess2.IsNull()) {
-    static const TDF_Label anEmpty;
-    return isShapeInTree(theAccess2, anEmpty, theShape, theOriginalLabel);
-  }
-  return false;
-}
-
-/// Stores entry to the external label in the entries list at this label
-static void storeExternalReference(const TDF_Label& theExternal, const TDF_Label theThis)
-{
-  // store information about the external document reference to restore old shape on open
-  if (!theExternal.IsNull() && !theExternal.Root().IsEqual(theThis.Root())) {
-    Handle(TDataStd_ExtStringList) anEntries;
-    if (!theThis.FindAttribute(kEXTERNAL_SHAPE_REF, anEntries)) {
-      anEntries = TDataStd_ExtStringList::Set(theThis, kEXTERNAL_SHAPE_REF);
-    }
-    TCollection_AsciiString anEntry;
-    TDF_Tool::Entry(theExternal, anEntry);
-    // check it already contains this entry
-    TDataStd_ListOfExtendedString::Iterator anIter(anEntries->List());
-    for(; anIter.More(); anIter.Next())
-      if (anIter.Value() == anEntry)
-        break;
-    if (!anIter.More()) {
-      anEntries->Append(anEntry);
-    }
-  }
-}
-
 void Model_BodyBuilder::loadModifiedShapes(const GeomMakeShapePtr& theAlgo,
                                            const GeomShapePtr& theOldShape,
                                            const GeomAPI_Shape::ShapeType theShapeTypeToExplore,
@@ -527,44 +623,18 @@ void Model_BodyBuilder::loadModifiedShapes(const GeomMakeShapePtr& theAlgo,
 
       bool aNewShapeIsSameAsOldShape = anOldSubShape->isSame(aNewShape);
       bool aNewShapeIsNotInResultShape = !aResultShape->isSubShape(aNewShape, false);
-      if (aNewShapeIsSameAsOldShape
-          || aNewShapeIsNotInResultShape)
-      {
+      if (aNewShapeIsSameAsOldShape || aNewShapeIsNotInResultShape)
         continue;
-      }
 
-      TNaming_Builder* aBuilder;
-      if (aResultShape->isSame(aNewShape)) {
-        // keep the modification evolution on the root level (2241 - history propagation issue)
-        aBuilder = builder(0);
-        TDF_Label aShapeLab = aBuilder->NamedShape()->Label();
-        Handle(TDF_Reference) aRef;
-        if (aShapeLab.FindAttribute(TDF_Reference::GetID(), aRef)) {
-          // Store only in case if it does not have reference.
-          continue;
-        }
+      if (aResultShape->isSame(aNewShape))
+        continue; // it is stored on the root level (2241 - history propagation issue)
 
-        // Check if new shape was already stored.
-        if (isAlreadyStored(aBuilder, anOldSubShape_, aNewShape_)) continue;
-
-        if (!aBuilder->NamedShape().IsNull() &&
-            ((isGenerated && aBuilder->NamedShape()->Evolution() != TNaming_GENERATED)
-              || (!isGenerated && aBuilder->NamedShape()->Evolution() != TNaming_MODIFY)))
-        {
-          myBuilders.erase(0); // clear old builder to avoid different evolutions crash
-          aBuilder = builder(0);
-        }
-      } else {
-        int aTag = isGenerated ? getGenerationTag(aNewShape_)
-                               : getModificationTag(aNewShape_);
-        aBuilder = builder(aTag);
-
-        // Check if new shape was already stored.
-        if (isAlreadyStored(aBuilder, anOldSubShape_, aNewShape_)) continue;
-
-        buildName(aTag, theName);
-      }
+      int aTag = isGenerated ? getGenerationTag(aNewShape_) : getModificationTag(aNewShape_);
+      TNaming_Builder*aBuilder = builder(aTag);
+      if (isAlreadyStored(aBuilder, anOldSubShape_, aNewShape_))
+        continue; // new shape was already stored.
 
+      buildName(aTag, theName);
       isGenerated ? aBuilder->Generated(anOldSubShape_, aNewShape_)
                   : aBuilder->Modify(anOldSubShape_, aNewShape_);
       // store information about the external document reference to restore old shape on open
@@ -576,7 +646,8 @@ void Model_BodyBuilder::loadModifiedShapes(const GeomMakeShapePtr& theAlgo,
 void Model_BodyBuilder::loadGeneratedShapes(const GeomMakeShapePtr& theAlgo,
                                             const GeomShapePtr& theOldShape,
                                             const GeomAPI_Shape::ShapeType theShapeTypeToExplore,
-                                            const std::string& theName)
+                                            const std::string& theName,
+                                            const bool theSaveOldIfNotInTree)
 {
   GeomShapePtr aResultShape = shape();
   TopTools_MapOfShape anAlreadyProcessedShapes;
@@ -597,7 +668,11 @@ void Model_BodyBuilder::loadGeneratedShapes(const GeomMakeShapePtr& theAlgo,
     bool anOldSubShapeNotInTree =
       !isShapeInTree(aData->shapeLab(), anAccess2, anOldSubShape_, anOriginalLabel);
     if (anOldSubShapeAlreadyProcessed || anOldSubShapeNotInTree) {
-      continue;
+      if (theSaveOldIfNotInTree) {
+        std::string aSelectionName = theName + "Selected";
+        generated(anOldSubShape, aSelectionName, false);
+      } else
+        continue;
     }
 
     // Get new shapes.
@@ -619,6 +694,9 @@ void Model_BodyBuilder::loadGeneratedShapes(const GeomMakeShapePtr& theAlgo,
         continue;
       }
 
+      if (aResultShape->isSame(aNewShape))
+        continue; // it is stored on the root level
+
       TopAbs_ShapeEnum aNewShapeType = aNewShape_.ShapeType();
       if (aNewShapeType == TopAbs_WIRE || aNewShapeType == TopAbs_SHELL) {
         // TODO: This is a workaround. New shape should be only edge or face.
@@ -631,25 +709,6 @@ void Model_BodyBuilder::loadGeneratedShapes(const GeomMakeShapePtr& theAlgo,
           storeExternalReference(anOriginalLabel, builder(aTag)->NamedShape()->Label());
         }
         buildName(aTag, theName);
-      } if (aResultShape->isSame(aNewShape)) {
-        // keep the generation evolution on the root level (2397 - for intersection feature)
-        TNaming_Builder* aBuilder = builder(0);
-        TDF_Label aShapeLab = aBuilder->NamedShape()->Label();
-        Handle(TDF_Reference) aRef;
-        if (aShapeLab.FindAttribute(TDF_Reference::GetID(), aRef)) {
-          // Store only in case if it does not have reference.
-          continue;
-        }
-
-        // Check if new shape was already stored.
-        if (isAlreadyStored(aBuilder, anOldSubShape_, aNewShape_)) continue;
-
-        if (!aBuilder->NamedShape().IsNull() &&
-            aBuilder->NamedShape()->Evolution() != TNaming_GENERATED) {
-          myBuilders.erase(0); // clear old builder to avoid different evolutions crash
-          aBuilder = builder(0);
-        }
-        aBuilder->Generated(anOldSubShape_, aNewShape_);
       } else {
         int aTag = getGenerationTag(aNewShape_);
         if (aTag == INVALID_TAG) return;
index 3819141009aecadbb48339a7dbbe207f72e560f6..08e79790b890d04982205f1cb2d3e92525954744 100644 (file)
@@ -41,21 +41,34 @@ class Model_BodyBuilder : public ModelAPI_BodyBuilder
 public:
   /// Stores the shape (called by the execution method).
   MODEL_EXPORT virtual void store(const GeomShapePtr& theShape,
-                                  const bool theIsStoreSameShapes = true);
+                                  const bool theIsStoreSameShapes = true) override;
 
   /// Stores the generated shape (called by the execution method).
   MODEL_EXPORT virtual void storeGenerated(const GeomShapePtr& theFromShape,
-                                           const GeomShapePtr& theToShape);
+                                           const GeomShapePtr& theToShape,
+                                           const bool theIsCleanStored = true) override;
+
+  /// Stores the root generated shapes (called by the execution method).
+  MODEL_EXPORT virtual void storeGenerated(const std::list<GeomShapePtr>& theFromShapes,
+    const GeomShapePtr& theToShape,
+    const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape) override;
 
   /// Stores the modified shape (called by the execution method).
   /// \param theOldShape shape that produces result
   /// \param theNewShape resulting shape
-  /// \param theDecomposeSolidsTag tag for starting of solids sub-elements placement in case
-  ///          theNewShape is compound of solids, if zero it is not used
+  /// \param theIsCleanStored erases all previous data structure of this body if true
   MODEL_EXPORT virtual void storeModified(const GeomShapePtr& theOldShape,
                                           const GeomShapePtr& theNewShape,
                                           const bool theIsCleanStored = true) override;
 
+  /// Stores the root modified shape (called by the execution method).
+  /// \param theOldShapes all shapes that produce result
+  /// \param theNewShape resulting shape
+  /// \param theIsCleanStored erases all previous data structure of this body if true
+  MODEL_EXPORT virtual void storeModified(const std::list<GeomShapePtr>& theOldShapes,
+    const GeomShapePtr& theNewShape,
+    const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape) override;
+
   /// Returns the shape-result produced by this feature
   MODEL_EXPORT virtual GeomShapePtr shape();
 
@@ -98,7 +111,8 @@ public:
   virtual void loadGeneratedShapes(const GeomMakeShapePtr& theAlgo,
                                    const GeomShapePtr& theOldShape,
                                    const GeomAPI_Shape::ShapeType theShapeTypeToExplore,
-                                   const std::string& theName = "") override;
+                                   const std::string& theName = "",
+                                   const bool theSaveOldIfNotInTree = false) override;
 
   /// Loads shapes of the first level (to be used during shape import)
   MODEL_EXPORT virtual void loadFirstLevel(GeomShapePtr theShape,
index 7f1659411d0b1c4a8460e896ab42d0a65ad122ae..4f442842e795195bbbd0763b7e8d3c2986ae9523 100644 (file)
 #include <ModelAPI_Tools.h>
 #include <Model_Data.h>
 #include <Events_Loop.h>
+#include <GeomAPI_ShapeIterator.h>
+#include <GeomAPI_ShapeExplorer.h>
 
 #include <TopoDS_Shape.hxx>
 #include <TopExp_Explorer.hxx>
+#include <TopTools_MapOfShape.hxx>
 #include <TDataStd_UAttribute.hxx>
 
 // if this attribute exists, the shape is connected topology
@@ -74,7 +77,8 @@ bool Model_ResultBody::generated(const GeomShapePtr& theNewShape,
 void Model_ResultBody::loadGeneratedShapes(const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgo,
                                            const GeomShapePtr& theOldShape,
                                            const GeomAPI_Shape::ShapeType theShapeTypeToExplore,
-                                           const std::string& theName)
+                                           const std::string& theName,
+                                           const bool theSaveOldIfNotInTree)
 {
   if (mySubs.size()) { // consists of subs
     for (std::vector<ResultBodyPtr>::const_iterator aSubIter = mySubs.cbegin();
@@ -82,10 +86,12 @@ void Model_ResultBody::loadGeneratedShapes(const std::shared_ptr<GeomAlgoAPI_Mak
          ++aSubIter)
     {
       const ResultBodyPtr& aSub = *aSubIter;
-      aSub->loadGeneratedShapes(theAlgo, theOldShape, theShapeTypeToExplore, theName);
+      aSub->loadGeneratedShapes(
+        theAlgo, theOldShape, theShapeTypeToExplore, theName, theSaveOldIfNotInTree);
     }
   } else { // do for this directly
-    myBuilder->loadGeneratedShapes(theAlgo, theOldShape, theShapeTypeToExplore, theName);
+    myBuilder->loadGeneratedShapes(
+      theAlgo, theOldShape, theShapeTypeToExplore, theName, theSaveOldIfNotInTree);
   }
 }
 
@@ -94,31 +100,12 @@ void Model_ResultBody::loadModifiedShapes(const std::shared_ptr<GeomAlgoAPI_Make
                                           const GeomAPI_Shape::ShapeType theShapeTypeToExplore,
                                           const std::string& theName)
 {
-  if (/*theSplitInSubs &&*/ mySubs.size()) { // consists of subs
+  if (mySubs.size()) { // consists of subs
     // optimization of getting of new shapes for specific sub-result
     if (!theAlgo->isNewShapesCollected(theOldShape, theShapeTypeToExplore))
       theAlgo->collectNewShapes(theOldShape, theShapeTypeToExplore);
     std::vector<ResultBodyPtr>::const_iterator aSubIter = mySubs.cbegin();
     for(; aSubIter != mySubs.cend(); aSubIter++) {
-      // check that sub-shape was also created as modification of ShapeIn
-      /* to find when it is needed later to enable: to store modification of sub-bodies not only as primitives
-      GeomShapePtr aSubGeomShape = (*aSubIter)->shape();
-      if (!theIsStoreAsGenerated && aSubGeomShape.get() && !aSubGeomShape->isNull()) {
-        TopoDS_Shape aSubShape = aSubGeomShape->impl<TopoDS_Shape>();
-        TopoDS_Shape aWholeIn = theShapeIn->impl<TopoDS_Shape>();
-        for(TopExp_Explorer anExp(aWholeIn, aSubShape.ShapeType()); anExp.More(); anExp.Next()) {
-          ListOfShape aHistory;
-          std::shared_ptr<GeomAPI_Shape> aSubIn(new GeomAPI_Shape());
-          aSubIn->setImpl((new TopoDS_Shape(anExp.Current())));
-          theMS->modified(aSubIn, aHistory);
-          std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator anIt = aHistory.begin();
-          for (; anIt != aHistory.end(); anIt++) {
-            if ((*anIt)->isSame(aSubGeomShape)) {
-              (*aSubIter)->storeModified(aSubIn, aSubGeomShape, -2); // -2 is to avoid clearing
-            }
-          }
-        }
-      }*/
       (*aSubIter)->loadModifiedShapes(theAlgo, theOldShape, theShapeTypeToExplore, theName);
     }
   } else { // do for this directly
@@ -272,7 +259,14 @@ void Model_ResultBody::updateSubs(const std::shared_ptr<GeomAPI_Shape>& theThisS
       }
       GeomShapePtr anOldSubShape = aSub->shape();
       if (!aShape->isEqual(anOldSubShape)) {
-        aSub->store(aShape, false);
+        if (myAlgo.get()) {
+          std::list<GeomShapePtr> anOldForSub;
+          computeOldForSub(aShape, myOlds, anOldForSub);
+          myIsGenerated ? aSub->storeGenerated(anOldForSub, aShape, myAlgo) :
+            aSub->storeModified(anOldForSub, aShape, myAlgo);
+        } else {
+          aSub->store(aShape, false);
+        }
         aECreator->sendUpdated(aSub, EVENT_DISP);
         aECreator->sendUpdated(aSub, EVENT_UPD);
       }
@@ -310,6 +304,23 @@ void Model_ResultBody::updateSubs(const std::shared_ptr<GeomAPI_Shape>& theThisS
   }
 }
 
+void Model_ResultBody::updateSubs(
+  const GeomShapePtr& theThisShape, const std::list<GeomShapePtr>& theOlds,
+  const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape, const bool isGenerated)
+{
+  myAlgo = theMakeShape;
+  myOlds = theOlds;
+  myIsGenerated = isGenerated;
+  // to avoid changing of "isDisabled" flag in the "updateSubs" cycle
+  isDisabled();
+
+  updateSubs(theThisShape, true);
+  myAlgo.reset();
+  myOlds.clear();
+  myHistoryCash.Clear();
+}
+
+
 bool Model_ResultBody::isConnectedTopology()
 {
   TDF_Label aDataLab = std::dynamic_pointer_cast<Model_Data>(data())->label();
@@ -338,3 +349,88 @@ void Model_ResultBody::cleanCash()
     aSub->cleanCash();
   }
 }
+
+// adds to the theSubSubs map all sub-shapes of theSub if it is compound of compsolid
+static void collectSubs(
+  const GeomShapePtr theSub, TopTools_MapOfShape& theSubSubs, const bool theOneLevelMore)
+{
+  if (theSub->isNull())
+    return;
+  if (theSubSubs.Add(theSub->impl<TopoDS_Shape>()))  {
+    bool aIsComp = theSub->isCompound() || theSub->isCompSolid();
+    if (aIsComp) {
+      for(GeomAPI_ShapeIterator anIter(theSub); anIter.more(); anIter.next())
+        collectSubs(anIter.current(), theSubSubs, theOneLevelMore);
+    } else if (theOneLevelMore) {
+      GeomAPI_Shape::ShapeType aSubType = GeomAPI_Shape::ShapeType(int(theSub->shapeType()) + 1);
+      if (aSubType == GeomAPI_Shape::SHAPE)
+        return;
+      if (aSubType == GeomAPI_Shape::SHELL)
+        aSubType = GeomAPI_Shape::FACE;
+      if (aSubType == GeomAPI_Shape::WIRE)
+        aSubType = GeomAPI_Shape::EDGE;
+
+      for(GeomAPI_ShapeExplorer anExp(theSub, aSubType); anExp.more(); anExp.next()) {
+        collectSubs(anExp.current(), theSubSubs, false);
+      }
+    }
+  }
+}
+
+void Model_ResultBody::computeOldForSub(const GeomShapePtr& theSub,
+  const std::list<GeomShapePtr>& theAllOlds, std::list<GeomShapePtr>& theOldForSub)
+{
+  // the old can be also used for sub-shape of theSub; collect all subs of compound or compsolid
+  TopTools_MapOfShape aSubSubs;
+  collectSubs(theSub, aSubSubs, false);
+
+  std::list<GeomShapePtr>::const_iterator aRootOlds = theAllOlds.cbegin();
+  for (; aRootOlds != theAllOlds.cend(); aRootOlds++) {
+    // use sub-shapes of olds too if they are compounds or compsolids
+    TopTools_MapOfShape anOldSubs;
+    // iterate one level more (for intersection of solids this is face)
+    collectSubs(*aRootOlds, anOldSubs, true);
+    for (TopTools_MapOfShape::Iterator anOldIter(anOldSubs); anOldIter.More(); anOldIter.Next()) {
+      TopoDS_Shape anOldShape = anOldIter.Value();
+      if (anOldShape.ShapeType() == TopAbs_COMPOUND || anOldShape.ShapeType() == TopAbs_SHELL ||
+          anOldShape.ShapeType() == TopAbs_WIRE)
+        continue; // container old-shapes are not supported by the history, may cause crash
+      GeomShapePtr anOldSub(new GeomAPI_Shape);
+      anOldSub->setImpl<TopoDS_Shape>(new TopoDS_Shape(anOldShape));
+
+      ListOfShape aNews;
+      if (myHistoryCash.IsBound(anOldShape)) {
+        const TopTools_ListOfShape& aList = myHistoryCash.Find(anOldShape);
+        for(TopTools_ListIteratorOfListOfShape anIter(aList); anIter.More(); anIter.Next()) {
+          GeomShapePtr aShape(new GeomAPI_Shape);
+          aShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(anIter.Value()));
+          aNews.push_back(aShape);
+        }
+      } else {
+        myIsGenerated ? myAlgo->generated(anOldSub, aNews) : myAlgo->modified(anOldSub, aNews);
+        // MakeShape may return alone old shape if there is no history information for this input
+        if (aNews.size() == 1 && aNews.front()->isEqual(anOldSub))
+          aNews.clear();
+        // store result in the history
+        TopTools_ListOfShape aList;
+        for (ListOfShape::iterator aNewIter = aNews.begin(); aNewIter != aNews.end(); aNewIter++) {
+          aList.Append((*aNewIter)->impl<TopoDS_Shape>());
+        }
+        myHistoryCash.Bind(anOldShape, aList);
+      }
+
+      for (ListOfShape::iterator aNewIter = aNews.begin(); aNewIter != aNews.end(); aNewIter++) {
+        if (aSubSubs.Contains((*aNewIter)->impl<TopoDS_Shape>())) {
+          // check list already contains this sub
+          std::list<GeomShapePtr>::iterator aResIter = theOldForSub.begin();
+          for(; aResIter != theOldForSub.end(); aResIter++)
+            if ((*aResIter)->isSame(anOldSub))
+              break;
+          if (aResIter == theOldForSub.end())
+            theOldForSub.push_back(anOldSub); // found old used for new theSubShape creation
+          break;
+        }
+      }
+    }
+  }
+}
index 19a3bb9874bc696eb113590d961a75e985deac33..8abd4408965588dccb07a882fdb07258f53156ca 100644 (file)
@@ -25,6 +25,8 @@
 #include <vector>
 #include <map>
 
+#include <TopTools_DataMapOfShapeListOfShape.hxx>
+
 /**\class Model_ResultBody
 * \ingroup DataModel
 * \brief The body (shape) result of a feature.
@@ -42,6 +44,14 @@ class Model_ResultBody : public ModelAPI_ResultBody
   std::map<ObjectPtr, int> mySubsMap;
   /// Keeps the last state of the concealment flag in order to update it when needed.
   bool myLastConcealed;
+  /// History information for update subs
+  std::shared_ptr<GeomAlgoAPI_MakeShape> myAlgo;
+  /// All old shapes used for the root result construction
+  std::list<GeomShapePtr> myOlds;
+  /// Information about the kind of the history information: modified or generated
+  bool myIsGenerated;
+  /// Map from old shape to list of new shapes, cash for computeOldForSub method
+  TopTools_DataMapOfShapeListOfShape myHistoryCash;
 
 public:
 
@@ -58,7 +68,8 @@ public:
   virtual void loadGeneratedShapes(const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgo,
                                    const GeomShapePtr& theOldShape,
                                    const GeomAPI_Shape::ShapeType theShapeTypeToExplore,
-                                   const std::string& theName = "") override;
+                                   const std::string& theName = "",
+                                   const bool theSaveOldIfNotInTree = false) override;
 
   /// load modified shapes for sub-objects
   MODEL_EXPORT
@@ -108,9 +119,18 @@ protected:
   void updateSubs(const std::shared_ptr<GeomAPI_Shape>& theThisShape,
                   const bool theShapeChanged = true);
 
+  /// Updates the sub-bodies in accordance to the algorithm history information
+  void updateSubs(
+    const GeomShapePtr& theThisShape, const std::list<GeomShapePtr>& theOlds,
+    const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape, const bool isGenerated);
+
   // Checks the state of children and parents to send events of creation/erase when needed
   void updateConcealment();
 
+  /// Adds to theOldForSub only old shapes that where used for theSub creation
+  void computeOldForSub(const GeomShapePtr& theSub,
+    const std::list<GeomShapePtr>& theAllOlds, std::list<GeomShapePtr>& theOldForSub);
+
   friend class Model_Objects;
 };
 
index c2c425cdcb9c28c09b6f66811fe14ae6f848aa12..041e8f226d34a769e6e4ccf23110d04d99a55ace 100644 (file)
@@ -291,12 +291,12 @@ void Model_ResultConstruction::storeShape(std::shared_ptr<GeomAPI_Shape> theShap
         }
       }
 
-      std::list<std::shared_ptr<GeomAPI_Shape> > aFaces;
-      GeomAlgoAPI_SketchBuilder::createFaces(aWirePtr->origin(), aWirePtr->dirX(),
-        aWirePtr->norm(), aWirePtr, aFaces);
+      GeomAlgoAPI_SketchBuilder aSketchBuilder(aWirePtr->origin(), aWirePtr->dirX(),
+                                               aWirePtr->norm(), aWirePtr);
+      const ListOfShape& aFaces = aSketchBuilder.faces();
       // order is important to store faces in the same order if sketch is created from scratch
       NCollection_IndexedDataMap<TopoDS_Face, TColStd_ListOfInteger> aNewIndices; // edges indices
-      std::list<std::shared_ptr<GeomAPI_Shape> >::iterator aFIter = aFaces.begin();
+      std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator aFIter = aFaces.begin();
       for (; aFIter != aFaces.end(); aFIter++) {
         std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(*aFIter));
         // put them to a label, trying to keep the same faces on the same labels
index 98d13b066b410deb6d813c01e22827520efa7214..f86c3076b240ecde193a2eb4955552fbbed23100 100644 (file)
@@ -1068,19 +1068,27 @@ void Model_Update::updateSelection(const std::set<std::shared_ptr<ModelAPI_Objec
     for (; aRefsIter != aRefs.end(); aRefsIter++) {
       std::shared_ptr<Model_AttributeSelection> aSel =
         std::dynamic_pointer_cast<Model_AttributeSelection>(*aRefsIter);
-      aSel->updateInHistory();
+      bool aRemove = false;
+      aSel->updateInHistory(aRemove);
     }
     // update the selection list attributes if any
     aRefs = (*anObj)->data()->attributes(ModelAPI_AttributeSelectionList::typeId());
     for (aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) {
+      std::set<int> aRemoveSet;
       std::shared_ptr<ModelAPI_AttributeSelectionList> aSel =
         std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*aRefsIter);
       for(int a = aSel->size() - 1; a >= 0; a--) {
         std::shared_ptr<Model_AttributeSelection> aSelAttr =
           std::dynamic_pointer_cast<Model_AttributeSelection>(aSel->value(a));
-        if (aSelAttr.get())
-          aSelAttr->updateInHistory();
+        if (aSelAttr.get()) {
+          bool theRemove = false;
+          aSelAttr->updateInHistory(theRemove);
+          if (theRemove) {
+            aRemoveSet.insert(a);
+          }
+        }
       }
+      aSel->remove(aRemoveSet);
     }
   }
 }
index 3cbdf43e0ddbfc158d2f09ddf52fadf5bc888742..ecf3137338df10ba16e832437dc7af0c6aad6a9c 100644 (file)
@@ -46,13 +46,22 @@ public:
 
   /// Stores the generated shape (called by the execution method).
   virtual void storeGenerated(const GeomShapePtr& theFromShape,
-                              const GeomShapePtr& theToShape) = 0;
+                              const GeomShapePtr& theToShape,
+                              const bool theIsCleanStored = true) = 0;
+
+  /// Stores the root generated shapes (called by the execution method).
+  virtual void storeGenerated(const std::list<GeomShapePtr>& theFromShapes,
+    const GeomShapePtr& theToShape, const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape) = 0;
 
   /// Stores the modified shape (called by the execution method).
   virtual void storeModified(const GeomShapePtr& theOldShape,
                              const GeomShapePtr& theNewShape,
                              const bool theIsCleanStored = true) = 0;
 
+  /// Stores the root modified shapes (called by the execution method).
+  virtual void storeModified(const std::list<GeomShapePtr>& theOldShapes,
+    const GeomShapePtr& theNewShape, const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)=0;
+
   /// Returns the shape-result produced by this feature
   virtual GeomShapePtr shape() = 0;
 
@@ -91,7 +100,8 @@ public:
   virtual void loadGeneratedShapes(const GeomMakeShapePtr& theAlgo,
                                    const GeomShapePtr& theOldShape,
                                    const GeomAPI_Shape::ShapeType theShapeTypeToExplore,
-                                   const std::string& theName = "") = 0;
+                                   const std::string& theName = "",
+                                   const bool theSaveOldIfNotInTree = false) = 0;
 
   /// load shapes of the first level (to be used during shape import)
   virtual void loadFirstLevel(GeomShapePtr theShape,
index 0f02272be6f08d7b471504093a3547e9d0828f61..603aaac4df93d98a740c804eefbafa7a4928d40d 100644 (file)
@@ -66,6 +66,21 @@ void ModelAPI_ResultBody::storeGenerated(const GeomShapePtr& theFromShape,
   updateSubs(theToShape);
 }
 
+void ModelAPI_ResultBody::storeGenerated(
+  const std::list<GeomShapePtr>& theFromShapes, const GeomShapePtr& theToShape,
+  const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
+{
+  myBuilder->storeGenerated(theFromShapes, theToShape, theMakeShape);
+  myConnect = ConnectionNotComputed;
+
+  static Events_Loop* aLoop = Events_Loop::loop();
+  static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
+  aECreator->sendUpdated(data()->owner(), aRedispEvent);
+
+  updateSubs(theToShape, theFromShapes, theMakeShape, true);
+}
+
 void ModelAPI_ResultBody::storeModified(const GeomShapePtr& theOldShape,
                                         const GeomShapePtr& theNewShape,
                                         const bool theIsCleanStored)
@@ -81,6 +96,21 @@ void ModelAPI_ResultBody::storeModified(const GeomShapePtr& theOldShape,
   updateSubs(theNewShape);
 }
 
+void ModelAPI_ResultBody::storeModified(
+  const std::list<GeomShapePtr>& theOldShapes, const GeomShapePtr& theNewShape,
+  const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
+{
+  myBuilder->storeModified(theOldShapes, theNewShape, theMakeShape);
+  myConnect = ConnectionNotComputed;
+
+  static Events_Loop* aLoop = Events_Loop::loop();
+  static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
+  aECreator->sendUpdated(data()->owner(), aRedispEvent);
+
+  updateSubs(theNewShape, theOldShapes, theMakeShape, false);
+}
+
 GeomShapePtr ModelAPI_ResultBody::shape()
 {
   return myBuilder->shape();
index 0304b86c5e07efe9a8ce44a9168447c9de0f047a..0991119bd56c931ed13a666172efc1fe8e2ed15d 100644 (file)
@@ -101,11 +101,21 @@ public:
   MODELAPI_EXPORT virtual void storeGenerated(const GeomShapePtr& theFromShape,
                                               const GeomShapePtr& theToShape);
 
+  /// Stores the root modified shapes (called by the execution method).
+  MODELAPI_EXPORT virtual void storeGenerated(
+    const std::list<GeomShapePtr>& theFromShapes, const GeomShapePtr& theToShape,
+    const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape);
+
   /// Stores the modified shape (called by the execution method).
   MODELAPI_EXPORT virtual void storeModified(const GeomShapePtr& theOldShape,
                                              const GeomShapePtr& theNewShape,
                                              const bool theIsCleanStored = true);
 
+  /// Stores the root modified shapes (called by the execution method).
+  MODELAPI_EXPORT virtual void storeModified(
+    const std::list<GeomShapePtr>& theOldShapes, const GeomShapePtr& theNewShape,
+    const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape);
+
   /// Returns the shape-result produced by this feature
   MODELAPI_EXPORT virtual GeomShapePtr shape();
 
@@ -147,7 +157,8 @@ public:
   virtual void loadGeneratedShapes(const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgo,
                                    const GeomShapePtr& theOldShape,
                                    const GeomAPI_Shape::ShapeType theShapeTypeToExplore,
-                                   const std::string& theName = "") = 0;
+                                   const std::string& theName = "",
+                                   const bool theSaveOldIfNotInTree = false) = 0;
 
   /// load shapes of the first level (to be used during shape import)
   MODELAPI_EXPORT virtual void loadFirstLevel(GeomShapePtr theShape,
@@ -164,6 +175,11 @@ public:
   MODELAPI_EXPORT virtual void updateSubs(const GeomShapePtr& theThisShape,
     const bool theShapeChanged = true) = 0;
 
+  /// Updates the sub-bodies in accordance to the algorithm history information
+  MODELAPI_EXPORT virtual void updateSubs(
+    const GeomShapePtr& theThisShape, const std::list<GeomShapePtr>& theOlds,
+    const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape, const bool isGenerated) = 0;
+
   /// Cleans cash related to the already stored elements
   MODELAPI_EXPORT virtual void cleanCash() = 0;
 
index d374315b1dd70c5bdd9c6414f0bafda0ebd3218e..526a6f627d2418f0f26aafb1ce753cd93d2ccee2 100644 (file)
@@ -110,10 +110,15 @@ Sketch_3.result().setName("Sketch_4")
 ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_4")], model.selection(), "h", 0, [model.selection("SOLID", "ExtrusionCut_1_1")])
 Fillet_1_objects = [model.selection("EDGE", "[ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/To_Face][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)(ExtrusionCut_2_1/Modified_Face&Sketch_3/SketchLine_12)(ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/To_Face)]"), model.selection("EDGE", "[(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)(ExtrusionCut_2_1/Modified_Face&Sketch_3/SketchLine_12)(ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/To_Face)][ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/To_Face]"), model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_2][ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/To_Face]"), model.selection("EDGE", "[ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/From_Face][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_2]"), model.selection("EDGE", "[(ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/From_Face)(ExtrusionCut_2_1/Modified_Face&Sketch_3/SketchLine_9)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)][ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/From_Face]"), model.selection("EDGE", "[ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/From_Face][(ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/From_Face)(ExtrusionCut_2_1/Modified_Face&Sketch_3/SketchLine_9)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)]"), model.selection("EDGE", "[ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/From_Face][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3]"), model.selection("EDGE", "[ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/From_Face][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1]"), model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3][ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/To_Face]"), model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/To_Face]"), model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)(ExtrusionCut_2_1/Modified_Face&Sketch_3/SketchLine_12)(ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/To_Face)]"), model.selection("EDGE", "[(ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/From_Face)(ExtrusionCut_2_1/Modified_Face&Sketch_3/SketchLine_9)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3]"), model.selection("EDGE", "[(ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/From_Face)(ExtrusionCut_2_1/Modified_Face&Sketch_3/SketchLine_9)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1]"), model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)(ExtrusionCut_2_1/Modified_Face&Sketch_3/SketchLine_12)(ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/To_Face)]"), model.selection("EDGE", "[(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)(ExtrusionCut_2_1/Modified_Face&Sketch_3/SketchLine_12)(ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/To_Face)][ExtrusionCut_2_1/Generated_Face&Sketch_4/SketchLine_16&weak_name_2]"), model.selection("EDGE", "[(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)(ExtrusionCut_2_1/Modified_Face&Sketch_3/SketchLine_12)(ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/To_Face)][ExtrusionCut_2_1/Generated_Face&Sketch_4/SketchLine_18&weak_name_2]")]
 Fillet_1 = model.addFillet(Part_1_doc, Fillet_1_objects, 2)
-Group_1_objects = [model.selection("FACE", "Fillet_1_1/Modified_Face&Sketch_1/SketchLine_4&weak_name_1"), model.selection("FACE", "Fillet_1_1/Modified_Face&Sketch_1/SketchLine_4&weak_name_4"), model.selection("FACE", "Fillet_1_1/Modified_Face&Sketch_1/SketchLine_4&weak_name_2"), model.selection("FACE", "Fillet_1_1/Modified_Face&Sketch_1/SketchLine_4&weak_name_3")]
+Group_1_objects = [
+model.selection("FACE", "(Fillet_1_1/GF:Fillet&Fillet_1_1/FilletSelected_14)(Fillet_1_1/MF:Fillet_Face&Sketch_3/SketchLine_12)(Fillet_1_1/GF:Fillet&Fillet_1_1/FilletSelected_15)(Fillet_1_1/GF:Fillet&Fillet_1_1/FilletSelected_1)"),
+model.selection("FACE", "(Fillet_1_1/MF:Fillet_Face&Sketch_3/SketchLine_12)(Fillet_1_1/GF:Fillet&Fillet_1_1/FilletSelected_11)(Fillet_1_1/GF:Fillet&Fillet_1_1/FilletSelected_16)(Fillet_1_1/GF:Fillet&Fillet_1_1/FilletSelected_2)"),
+model.selection("FACE", "(Fillet_1_1/MF:Fillet_Face&Sketch_3/SketchLine_9)(Fillet_1_1/GF:Fillet&Fillet_1_1/FilletSelected_13)(Fillet_1_1/GF:Fillet&Fillet_1_1/FilletSelected_6)"),
+model.selection("FACE", "(Fillet_1_1/GF:Fillet&Fillet_1_1/FilletSelected_5)(Fillet_1_1/MF:Fillet_Face&Sketch_3/SketchLine_9)(Fillet_1_1/GF:Fillet&Fillet_1_1/FilletSelected_12)")
+]
 Group_1 = model.addGroup(Part_1_doc, Group_1_objects)
-Group_2 = model.addGroup(Part_1_doc, [model.selection("EDGE", "[(Fillet_1_1/Modified_Face&Sketch_1/SketchLine_3)(Fillet_1_1/Modified_Face&Extrusion_1_1/To_Face)][Fillet_1_1/Modified_Face&Extrusion_1_1/To_Face]"), model.selection("EDGE", "[Fillet_1_1/Modified_Face&Sketch_1/SketchLine_3][(Fillet_1_1/Modified_Face&Sketch_1/SketchLine_3)(Fillet_1_1/Modified_Face&Extrusion_1_1/To_Face)]")])
-Group_3 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "[Fillet_1_1/Modified_Face&Sketch_3/SketchLine_9][ExtrusionCut_1_1/Generated_Face&Sketch_3/SketchLine_13][Fillet_1_1/Modified_Face&Sketch_1/SketchLine_3]"), model.selection("VERTEX", "[ExtrusionCut_1_1/Generated_Face&Sketch_3/SketchLine_13][Fillet_1_1/Modified_Face&Sketch_1/SketchLine_3][Fillet_1_1/Modified_Face&Sketch_3/SketchLine_12]")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("EDGE", "[Fillet_1_1/GF:Fillet&Fillet_1_1/FilletSelected_9][Fillet_1_1/MF:Fillet_Face&Extrusion_1_1/To_Face]"), model.selection("EDGE", "[Fillet_1_1/MF:Fillet_Face&Sketch_1/SketchLine_3][Fillet_1_1/GF:Fillet&Fillet_1_1/FilletSelected_9]")])
+Group_3 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "[Fillet_1_1/MF:Fillet_Face&Sketch_3/SketchLine_9][ExtrusionCut_1_1/Generated_Face&Sketch_3/SketchLine_13][Fillet_1_1/MF:Fillet_Face&Sketch_1/SketchLine_3]"), model.selection("VERTEX", "[ExtrusionCut_1_1/Generated_Face&Sketch_3/SketchLine_13][Fillet_1_1/MF:Fillet_Face&Sketch_1/SketchLine_3][Fillet_1_1/MF:Fillet_Face&Sketch_3/SketchLine_12]")])
 model.do()
 
 Folder_1 = model.addFolder(Part_1_doc, Sketch_3, ExtrusionCut_2)
index 2b42d20ccb2b607876c1d1073701b06524dea35d..9b40f1c3ae3294438a4935a9b446223949147a90 100644 (file)
@@ -339,9 +339,9 @@ model.do()
 Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_9r-SketchLine_8r-SketchLine_7r-SketchLine_6r-SketchLine_14f-SketchLine_16r-SketchArc_3_2r-SketchLine_15f-SketchLine_13r-SketchArc_2_2r-SketchCircle_2_2r")], model.selection(), -165, 155)
 Boolean_1 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], [model.selection("SOLID", "Extrusion_2_1")])
 
-Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "(Fuse_1_1/Modified_Face&Extrusion_1_1/To_Face)(Extrusion_1_1/Generated_Face&Sketch_1/SketchArc_1_2)(Fuse_1_1/Modified_Face&Sketch_1/SketchLine_5&Sketch_2/SketchLine_7)"))
+Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "(Fuse_1_1/Modified_Face&Extrusion_1_1/To_Face)(Extrusion_1_1/Generated_Face&Sketch_1/SketchArc_1_2)(Fuse_1_1/Modified_Face&Sketch_2/SketchLine_7&Sketch_1/SketchLine_5)"))
 SketchLine_17 = Sketch_3.addLine(145, 0, 165, 0)
-SketchProjection_2 = Sketch_3.addProjection(model.selection("VERTEX", "[Fuse_1_1/Modified_Face&Extrusion_1_1/From_Face&Sketch_2/SketchLine_6][Fuse_1_1/Modified_Face&Sketch_1/SketchLine_1&Extrusion_2_1/To_Face][Fuse_1_1/Modified_Face&Sketch_1/SketchLine_5&Sketch_2/SketchLine_7]"))
+SketchProjection_2 = Sketch_3.addProjection(model.selection("VERTEX", "[Fuse_1_1/Modified_Face&Sketch_2/SketchLine_6&Extrusion_1_1/From_Face][Fuse_1_1/Modified_Face&Extrusion_2_1/To_Face&Sketch_1/SketchLine_1][Fuse_1_1/Modified_Face&Sketch_2/SketchLine_7&Sketch_1/SketchLine_5]"))
 SketchPoint_2 = SketchProjection_2.createdFeature()
 SketchConstraintCoincidence_23 = Sketch_3.setCoincident(SketchLine_17.endPoint(), SketchAPI_Point(SketchPoint_2).result())
 SketchLine_18 = Sketch_3.addLine(165, 0, 165, -20)
@@ -364,12 +364,12 @@ SketchArc_5 = Sketch_3.addArc(145, -20, 155, -20, 145, -10, False)
 SketchConstraintCoincidence_31 = Sketch_3.setCoincident(SketchLine_19.endPoint(), SketchArc_5.center())
 SketchConstraintCoincidence_32 = Sketch_3.setCoincident(SketchLine_20.result(), SketchArc_5.endPoint())
 SketchConstraintCoincidence_33 = Sketch_3.setCoincident(SketchArc_5.startPoint(), SketchLine_19.result())
-SketchLine_21 = Sketch_3.addLine(model.selection("EDGE", "[Fuse_1_1/Modified_Face&Extrusion_2_1/From_Face][(Fuse_1_1/Modified_Face&Extrusion_2_1/From_Face)(Extrusion_2_1/Generated_Face&Sketch_2/SketchLine_8)(Fuse_1_1/Modified_Face&Sketch_1/SketchLine_5&Sketch_2/SketchLine_7)]"))
+SketchLine_21 = Sketch_3.addLine(model.selection("EDGE", "[Fuse_1_1/Modified_Face&Extrusion_2_1/From_Face][(Fuse_1_1/Modified_Face&Extrusion_2_1/From_Face)(Extrusion_2_1/Generated_Face&Sketch_2/SketchLine_8)(Fuse_1_1/Modified_Face&Sketch_2/SketchLine_7&Sketch_1/SketchLine_5)]"))
 SketchConstraintTangent_5 = Sketch_3.setTangent(SketchArc_5.results()[1], SketchLine_21.result())
 model.do()
 
-ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchArc_4_2r-SketchLine_18r-SketchLine_17r")], model.selection(), model.selection("FACE", "Fuse_1_1/Modified_Face&Sketch_1/SketchLine_2&Sketch_2/SketchLine_9"), 0, model.selection(), 0, [model.selection("SOLID", "Fuse_1_1")])
-ExtrusionFuse_1 = model.addExtrusionFuse(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchArc_4_2f-SketchLine_20r-SketchArc_5_2r-SketchLine_19r")], model.selection(), model.selection("FACE", "(Fuse_1_1/Modified_Face&Extrusion_2_1/From_Face)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2&Sketch_2/SketchLine_9)(ExtrusionCut_1_1/Generated_Face&Sketch_3/SketchArc_4_2)(ExtrusionCut_1_1/Modified_Face&Extrusion_2_1/To_Face)(Extrusion_2_1/Generated_Face&Sketch_2/SketchLine_8)"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_1_1")])
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchArc_4_2r-SketchLine_18r-SketchLine_17r")], model.selection(), model.selection("FACE", "Fuse_1_1/Modified_Face&Sketch_2/SketchLine_9&Sketch_1/SketchLine_2"), 0, model.selection(), 0, [model.selection("SOLID", "Fuse_1_1")])
+ExtrusionFuse_1 = model.addExtrusionFuse(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchArc_4_2f-SketchLine_20r-SketchArc_5_2r-SketchLine_19r")], model.selection(), model.selection("FACE", "(Fuse_1_1/Modified_Face&Extrusion_2_1/From_Face)(ExtrusionCut_1_1/Modified_Face&Sketch_2/SketchLine_9&Sketch_1/SketchLine_2)(ExtrusionCut_1_1/Generated_Face&Sketch_3/SketchArc_4_2)(ExtrusionCut_1_1/Modified_Face&Extrusion_2_1/To_Face)(Extrusion_2_1/Generated_Face&Sketch_2/SketchLine_8)"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_1_1")])
 model.do()
 
 model.end()