]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Merge remote-tracking branch 'remotes/origin/Dev_2.8.0' into Dev_2.8.0
authorazv <azv@opencascade.com>
Thu, 21 Sep 2017 12:05:25 +0000 (15:05 +0300)
committerazv <azv@opencascade.com>
Thu, 21 Sep 2017 12:05:25 +0000 (15:05 +0300)
112 files changed:
CMakeCommon/FindTInspector.cmake
CMakeLists.txt
env.sh
src/CollectionPlugin/CMakeLists.txt
src/CollectionPlugin/Test/TestGroup1799.py
src/CollectionPlugin/Test/TestGroupMove.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupMove2.py [new file with mode: 0644]
src/ExchangePlugin/export_widget.xml
src/FeaturesPlugin/CMakeLists.txt
src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp
src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp
src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp
src/FeaturesPlugin/FeaturesPlugin_Partition.cpp
src/FeaturesPlugin/FeaturesPlugin_Pipe.cpp
src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.cpp
src/FeaturesPlugin/FeaturesPlugin_Tools.cpp
src/FeaturesPlugin/Test/Test2038.py
src/FeaturesPlugin/Test/Test2172.py [new file with mode: 0644]
src/FeaturesPlugin/Test/Test2194.py [new file with mode: 0644]
src/FeaturesPlugin/Test/Test2197_1.py [new file with mode: 0644]
src/FeaturesPlugin/Test/Test2197_2.py [new file with mode: 0644]
src/FeaturesPlugin/Test/Test2197_3.py [new file with mode: 0644]
src/FeaturesPlugin/Test/Test2197_4.py [new file with mode: 0644]
src/FeaturesPlugin/Test/Test2215.py [new file with mode: 0644]
src/FeaturesPlugin/Test/Test2222.py [new file with mode: 0644]
src/FeaturesPlugin/Test/Test2231.py [new file with mode: 0644]
src/FeaturesPlugin/Test/Test2233.py [new file with mode: 0644]
src/FeaturesPlugin/Test/Test2240.py [new file with mode: 0644]
src/FeaturesPlugin/Test/Test2246.py [new file with mode: 0644]
src/FeaturesPlugin/Test/Test2248.py [new file with mode: 0644]
src/FeaturesPlugin/Test/Test2251.py [new file with mode: 0644]
src/FeaturesPlugin/partition_widget.xml
src/GeomAPI/GeomAPI_Edge.cpp
src/GeomAPI/GeomAPI_Edge.h
src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp
src/GeomAlgoAPI/GeomAlgoAPI_MakeShapeList.cpp
src/GeomAlgoAPI/GeomAlgoAPI_Partition.cpp
src/GeomAlgoAPI/GeomAlgoAPI_Pipe.cpp
src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp
src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp
src/GeomValidators/GeomValidators_Positive.cpp
src/Model/Model_Application.cpp
src/Model/Model_Application.h
src/Model/Model_AttributeSelection.cpp
src/Model/Model_AttributeSelection.h
src/Model/Model_AttributeSelectionList.cpp
src/Model/Model_BodyBuilder.cpp
src/Model/Model_BodyBuilder.h
src/Model/Model_Data.cpp
src/Model/Model_Document.cpp
src/Model/Model_Document.h
src/Model/Model_ResultCompSolid.cpp
src/Model/Model_ResultCompSolid.h
src/Model/Model_ResultConstruction.cpp
src/Model/Model_ResultPart.cpp
src/Model/Model_ResultPart.h
src/Model/Model_SelectionNaming.cpp
src/Model/Model_Session.cpp
src/Model/Model_Session.h
src/ModelAPI/CMakeLists.txt
src/ModelAPI/ModelAPI_ResultBody.cpp
src/ModelAPI/ModelAPI_ResultBody.h
src/ModelAPI/ModelAPI_Session.h
src/ModelAPI/Test/Test2228.py [new file with mode: 0644]
src/ModelAPI/Test/Test2241.py [new file with mode: 0644]
src/ModelAPI/Test/Test2252.py [new file with mode: 0644]
src/ModuleBase/ModuleBase_IWorkshop.h
src/ModuleBase/ModuleBase_ModelWidget.cpp
src/ModuleBase/ModuleBase_ResultPrs.cpp
src/ModuleBase/ModuleBase_ResultPrs.h
src/ModuleBase/ModuleBase_WidgetEditor.cpp
src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp
src/ModuleBase/ModuleBase_WidgetMultiSelector.h
src/PartSet/PartSet_Module.cpp
src/PartSet/PartSet_Validators.cpp
src/PartSet/PartSet_Validators.h
src/PartSet/PartSet_WidgetPoint2d.cpp
src/PartSet/PartSet_WidgetSketchLabel.cpp
src/PartSetPlugin/PartSetPlugin_Part.cpp
src/PythonAPI/model/tests/tests.py
src/SHAPERGUI/CMakeLists.txt
src/SHAPERGUI/SHAPERGUI_SalomeViewer.cpp
src/SketchPlugin/CMakeLists.txt
src/SketchPlugin/SketchPlugin_ConstraintLength.cpp
src/SketchPlugin/SketchPlugin_Fillet.cpp
src/SketchPlugin/SketchPlugin_MacroArc.cpp
src/SketchPlugin/SketchPlugin_MacroCircle.cpp
src/SketchPlugin/SketchPlugin_Tools.cpp
src/SketchPlugin/SketchPlugin_Tools.h
src/SketchPlugin/SketchPlugin_Validators.cpp
src/SketchPlugin/Test/Test2229.py [new file with mode: 0644]
src/SketchPlugin/Test/Test2239.py [new file with mode: 0644]
src/SketchPlugin/plugin-Sketch.xml
src/SketchSolver/PlaneGCSSolver/CMakeLists.txt
src/SketchSolver/SketchSolver_ConstraintMovement.cpp
src/SketchSolver/SketchSolver_Manager.cpp
src/XGUI/XGUI_ContextMenuMgr.cpp
src/XGUI/XGUI_Displayer.cpp
src/XGUI/XGUI_MenuMgr.cpp
src/XGUI/XGUI_ModuleConnector.cpp
src/XGUI/XGUI_ModuleConnector.h
src/XGUI/XGUI_OperationMgr.cpp
src/XGUI/XGUI_OperationMgr.h
src/XGUI/XGUI_Tools.cpp
src/XGUI/XGUI_Workshop.cpp
src/XGUI/XGUI_Workshop.h
src/XGUI/XGUI_WorkshopListener.cpp
src/XGUI/XGUI_WorkshopListener.h
test.API/SHAPER/CMakeLists.txt
test.API/SHAPER/Transformations/TestTranslation_1.py
test.API/SHAPER/Transformations/TestTranslation_2.py
test.models/piece_12.py

index 0b2ba217bf48e57fa63c955d6c294dc6f5d5aa3c..82e2a4655c541787d1aa355af18fbb32024524ab 100644 (file)
@@ -30,6 +30,9 @@ IF(EXISTS ${TINSPECTOR_ROOT_DIR})
     FIND_LIBRARY(TKTreeModel TKTreeModel "${TINSPECTOR_LIB_DIR}")
     SET(TKTreeModel ${TKTreeModel})
 
+    FIND_LIBRARY(TKVInspector TKVInspector "${TINSPECTOR_LIB_DIR}")
+    SET(TKVInspector ${TKVInspector})
+
   ENDIF(TKTInspector)
 
 ENDIF(EXISTS ${TINSPECTOR_ROOT_DIR})
index 4b7dbabeabf7d707c856d629ad5350fa8df24c89..9475e015fe68cab8df6632a56ae29290d4d584e9 100644 (file)
@@ -27,7 +27,7 @@ IF(WIN32)
   CMAKE_POLICY(SET CMP0020 OLD) # disable automatic linking to qtmain.lib
 ENDIF(WIN32)
 
-SET (SHAPER_Version 2.7.1)
+SET (SHAPER_Version 2.7.2)
 
 SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeCommon" ${CMAKE_MODULE_PATH})
 
@@ -82,6 +82,9 @@ ELSE(${HAVE_SALOME})
     SET(SHAPER_INSTALL_TUI_DOC doc CACHE INTERNAL "" FORCE)
 ENDIF(${HAVE_SALOME})
 
+# Sketcher: Change radius of circular edges while dragging a point on the edge
+SET(SKETCHER_CHANGE_RADIUS_WHEN_MOVE FALSE)
+
 ADD_SUBDIRECTORY (src/Config)
 ADD_SUBDIRECTORY (src/Events)
 ADD_SUBDIRECTORY (src/Model)
diff --git a/env.sh b/env.sh
index 4591db57a68eb17db53c1724cd09bff706d89179..05bfb11452bf30cdb2b0ed2bfec876e1a5c6c4d7 100644 (file)
--- a/env.sh
+++ b/env.sh
@@ -11,7 +11,6 @@ export AUT_DIR=$(pwd)
 export TOOLS_DIR=$(pwd)
 
 export HOME_OLD=$HOME
-
 source /dn46/SALOME/series8x/current-2017-07-11/start.sh
 export HOME=$HOME_OLD
 
index 9725d50914bfed85d4dec490d3684ccab2397b90..4bc29cccb3d764fdde6a7ec498d4bb01ddeddbe8 100644 (file)
@@ -105,4 +105,6 @@ ADD_UNIT_TESTS(
                TestGroup.py
                TestField.py
                TestGroup1799.py
+               TestGroupMove.py
+               TestGroupMove2.py
 )
index c959182daeea34e2380093e165a14c454d1d72a1..8a767c0e71af344d0b444ca9e8bb0825b40dea20 100644 (file)
@@ -119,8 +119,8 @@ Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Extrusion_1_1/To_
 Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_12"), 150, True)
 Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_7"), 150, True)
 Partition_1 = model.addPartition(Part_1_doc, [model.selection("FACE", "Plane_1"), model.selection("COMPSOLID", "Extrusion_1_1"), model.selection("FACE", "Plane_2")])
-Plane_6 = model.addPlane(Part_1_doc, model.selection("FACE", "Partition_1_1/Modified_Face_1_2_1"), 110, True)
-Plane_7 = model.addPlane(Part_1_doc, model.selection("FACE", "Partition_1_1/Modified_Face_1_9_1"), 380, True)
+Plane_6 = model.addPlane(Part_1_doc, model.selection("FACE", "Partition_1_1_7/Modified_Face_1_3"), 110, True)
+Plane_7 = model.addPlane(Part_1_doc, model.selection("FACE", "Partition_1_1_5/Modified_Face_1_3"), 380, True)
 Partition_2 = model.addPartition(Part_1_doc, [model.selection("FACE", "Plane_3"), model.selection("COMPSOLID", "Partition_1_1"), model.selection("FACE", "Plane_4")])
 model.do()
 
diff --git a/src/CollectionPlugin/Test/TestGroupMove.py b/src/CollectionPlugin/Test/TestGroupMove.py
new file mode 100644 (file)
index 0000000..dd1e0c1
--- /dev/null
@@ -0,0 +1,50 @@
+## Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+# Test that box partitioned is splitted: group with edge becomes 2 edges group,
+# group with not-touched vertex keeps this vertex.
+
+from salome.shaper import model
+from ModelAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 20, 10, 10)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Back"), 10, True)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Box_1_1/Left&Box_1_1/Top")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "Box_1_1/Back&Box_1_1/Left&Box_1_1/Top")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1")])
+model.do()
+# move groups
+Part_1_doc.moveFeature(Group_1.feature(), Partition_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+model.end()
+
+# Check groups
+aFactory = ModelAPI_Session.get().validators()
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 2)
+assert(aFactory.validate(Group_1.feature()))
+
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 1)
+assert(aFactory.validate(Group_2.feature()))
diff --git a/src/CollectionPlugin/Test/TestGroupMove2.py b/src/CollectionPlugin/Test/TestGroupMove2.py
new file mode 100644 (file)
index 0000000..0f06d1d
--- /dev/null
@@ -0,0 +1,45 @@
+## Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+# Test that removed vertex, selected in the group makes group with one invalid element (empty shape)
+
+from salome.shaper import model
+from ModelAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 20)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("VERTEX", "Box_1_1/Back&Box_1_1/Right&Box_1_1/Top"), model.selection("VERTEX", "Box_1_1/Front&Box_1_1/Left&Box_1_1/Top"), model.selection("VERTEX", "Box_1_1/Back&Box_1_1/Left&Box_1_1/Bottom"))
+Group_1 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "Box_1_1/Back&Box_1_1/Left&Box_1_1/Top")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1")])
+Remove_SubShapes_1 = model.addRemoveSubShapes(Part_1_doc, model.selection("COMPSOLID", "Partition_1_1"))
+Remove_SubShapes_1.setSubShapesToKeep([model.selection("SOLID", "Partition_1_1_2")])
+model.do()
+# move group
+Part_1_doc.moveFeature(Group_1.feature(), Remove_SubShapes_1.feature())
+model.end()
+
+# Check group
+aFactory = ModelAPI_Session.get().validators()
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 1)
+assert(aFactory.validate(Group_1.feature()) == False)
index ef66f277b398b328b945f7588950b701bfb9ac28..330187a1c7d74295c005d8d93ec869bb954ae709 100644 (file)
@@ -27,7 +27,7 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
                             title="Export file"
                             path="">
         <validator id="ExchangePlugin_ExportFormat"
-                   parameters="BREP|BRP:BREP,STEP|STP:STEP,IGES|IGS:IGES-5.1,IGES|IGS:IGES-5.3" />
+                   parameters="brep|brp:BREP,step|stp:STEP,iges|igs:IGES-5.1,iges|igs:IGES-5.3" />
       </export_file_selector>
       <multi_selector id="selection_list"
                       tooltip="Select a set of objects"
@@ -41,7 +41,7 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
                             title="Export file"
                             path="">
         <validator id="ExchangePlugin_ExportFormat"
-                   parameters="XAO:XAO" />
+                   parameters="xao:XAO" />
       </export_file_selector>
       <stringvalue id="xao_author"
                    label="Author"
index 987de3a17ba3d467139aa4aa76addb97bcd03af4..94ec4f78c0078de437949bf82ea57bb709326c10 100644 (file)
@@ -167,4 +167,18 @@ ADD_UNIT_TESTS(TestExtrusion.py
                Test2023.py
                Test2046.py
                Test2038.py
+               Test2172.py
+               Test2194.py
+               Test2197_1.py
+               Test2197_2.py
+               Test2197_3.py
+               Test2197_4.py
+               Test2215.py
+               Test2222.py
+               Test2233.py
+               Test2231.py
+               Test2240.py
+               Test2246.py
+               Test2248.py
+               Test2251.py
 )
index 66425edc023677a806ac5a36335c76ffca4b2dc8..b51d76b60079f828e22d108873850259b1bce324 100644 (file)
@@ -101,7 +101,8 @@ void FeaturesPlugin_Boolean::execute()
     }
     ResultPtr aContext = anObjectAttr->context();
     ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
-    if(aResCompSolidPtr.get()) {
+    if(aResCompSolidPtr.get()
+        && aResCompSolidPtr->shape()->shapeType() == GeomAPI_Shape::COMPSOLID) {
       std::shared_ptr<GeomAPI_Shape> aContextShape = aResCompSolidPtr->shape();
       std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
         anIt = aCompSolidsObjects.begin();
@@ -629,7 +630,7 @@ void FeaturesPlugin_Boolean::loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> t
 {
   //load result
   if(theBaseShape->isEqual(theResultShape)) {
-    theResultBody->store(theResultShape);
+    theResultBody->store(theResultShape, false);
   } else {
     const int aModifyTag = 1;
     const int aDeletedTag = 2;
@@ -644,7 +645,7 @@ void FeaturesPlugin_Boolean::loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> t
     const std::string aModFName = "Modified_Face";
 
     theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE,
-                                               aModifyTag, aModName, theMapOfShapes);
+      aModifyTag, aModName, theMapOfShapes, false, false, true);
     theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape,
                                      GeomAPI_Shape::FACE, aDeletedTag);
 
@@ -665,7 +666,7 @@ void FeaturesPlugin_Boolean::loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> t
       }
       theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter,
         aName == aModEName ? GeomAPI_Shape::EDGE : GeomAPI_Shape::FACE,
-        aTag, aName, theMapOfShapes);
+        aTag, aName, theMapOfShapes, false, false, true);
       theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, aDeletedTag);
     }
   }
index ebc6420e776c57e55bf0922a96283d9510731653..6f200a6c7329c8c4e6518ec89be640e2729ff48d 100644 (file)
@@ -389,7 +389,7 @@ void FeaturesPlugin_CompositeBoolean::storeModificationHistory(ResultBodyPtr the
     }
     theResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), *anIt,
       (*anIt)->shapeType() == GeomAPI_Shape::EDGE ?
-      GeomAPI_Shape::EDGE : GeomAPI_Shape::FACE, aTag, aName, *aMap.get());
+      GeomAPI_Shape::EDGE : GeomAPI_Shape::FACE, aTag, aName, *aMap.get(), false, false, true);
     theResultBody->loadDeletedShapes(theMakeShape.get(), *anIt, GeomAPI_Shape::FACE, aDelTag);
   }
 }
index 4d81b553b9fabe7a8f1f831e8d49dd8a8caabe1a..adde95a0b22668d6cf0d1cf82976265096529ca3 100644 (file)
@@ -335,6 +335,110 @@ void FeaturesPlugin_CompositeSketch::storeGenerationHistory(ResultBodyPtr theRes
                                                 theTag++, aGenName + "Face",
                                                 *aMapOfSubShapes.get());
   }
+  // issue #2197: make naming of edges generated from vertices
+  if (aShapeTypeToExplode == GeomAPI_Shape::EDGE) {
+    GeomAPI_DataMapOfShapeShape aFacesFromFromEdges;
+    GeomAPI_ShapeExplorer anEdgeExp(theBaseShape, GeomAPI_Shape::EDGE);
+    for(; anEdgeExp.more(); anEdgeExp.next()) {
+      ListOfShape aGenerated;
+      theMakeShape->generated(anEdgeExp.current(), aGenerated);
+      ListOfShape::iterator aGenIter = aGenerated.begin();
+      for(; aGenIter != aGenerated.end(); aGenIter++) {
+        GeomShapePtr aGen = *aGenIter;
+        if (aGen.get() && !aGen->isNull()) {
+          if ((*aGenIter)->shapeType() == GeomAPI_Shape::FACE) { // normal case
+            aFacesFromFromEdges.bind(aGen, anEdgeExp.current());
+          }
+        }
+      }
+    }
+
+    // closed revolution of 1-3 faces can not distinguish lateral and base edges
+    if (aFacesFromFromEdges.size() <= 3) {
+      bool isClosed = false; // lateral edges are closed (in full revolution)
+      GeomAPI_DataMapOfShapeShape anEdgesFromVertices;
+      GeomAPI_ShapeExplorer aVertExp(theBaseShape, GeomAPI_Shape::VERTEX);
+      for(int anIndex = 1; aVertExp.more(); aVertExp.next()) {
+        ListOfShape aGenerated;
+        theMakeShape->generated(aVertExp.current(), aGenerated);
+        ListOfShape::iterator aGenIter = aGenerated.begin();
+        for(; aGenIter != aGenerated.end(); aGenIter++) {
+          std::shared_ptr<GeomAPI_Shape> aGenerated = *aGenIter;
+          if (anEdgesFromVertices.isBound(aGenerated)) // already here
+            continue;
+          std::ostringstream aStream;
+          aStream<<"Lateral_Edge_"<<anIndex++;
+          theResultBody->generated(aGenerated, aStream.str(), theTag++);
+
+          anEdgesFromVertices.bind(aGenerated, aVertExp.current());
+          std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aGenerated));
+          isClosed = isClosed || anEdge->isClosed();
+        }
+      }
+      if (isClosed) {
+        GeomAPI_ShapeExplorer anEdgesExp(theMakeShape->shape(), GeomAPI_Shape::EDGE);
+        for(int anIndex = 1; anEdgesExp.more(); anEdgesExp.next()) {
+          if (!anEdgesFromVertices.isBound(anEdgesExp.current())) {
+            // found a base edge
+            std::ostringstream aStream;
+            aStream<<"Base_Edge_"<<anIndex++;
+            theResultBody->generated(anEdgesExp.current(), aStream.str(), theTag++);
+            // only one orientation is needed
+            anEdgesFromVertices.bind(anEdgesExp.current(), anEdgesExp.current());
+          }
+        }
+      } else if (aFacesFromFromEdges.size() == 1) { // 2233: sphere created by the revolution:
+        // vertices at degenerated edges will have the same name
+        GeomAPI_DataMapOfShapeShape aVertices;
+        GeomAPI_ShapeExplorer aVertExp(theMakeShape->shape(), GeomAPI_Shape::VERTEX);
+        for(int anIndex = 1; aVertExp.more(); aVertExp.next()) {
+          if (!aVertices.isBound(aVertExp.current())) {
+            // found a base edge
+            std::ostringstream aStream;
+            aStream<<"Vertex_"<<anIndex++;
+            theResultBody->generated(aVertExp.current(), aStream.str(), theTag++);
+            // only one orientation is needed
+            aVertices.bind(aVertExp.current(), aVertExp.current());
+          }
+        }
+      }
+    } else { // issue #2197, test case 4 : edges that produce fully-revolved face,
+      // but contain only 2 edges (on apex of revolution)
+      GeomAPI_ShapeExplorer anEdgeExp(theBaseShape, GeomAPI_Shape::EDGE);
+      for(int anIndex = 1; anEdgeExp.more(); anEdgeExp.next()) {
+        ListOfShape aGenerated;
+        theMakeShape->generated(anEdgeExp.current(), aGenerated);
+        ListOfShape::iterator aGenIter = aGenerated.begin();
+        for(; aGenIter != aGenerated.end(); aGenIter++) {
+          GeomShapePtr aGen = (*aGenIter);
+          if (aGen.get() && !aGen->isNull()) {
+            GeomAPI_ShapeExplorer aFaceEdgeExp(aGen, GeomAPI_Shape::EDGE);
+            int aNumEdges = 0;
+            int aNumClosed = 0;
+            GeomShapePtr aNotClosedEdge;
+            GeomAPI_DataMapOfShapeShape alreadyIterated;
+            for(; aFaceEdgeExp.more(); aFaceEdgeExp.next()) {
+              std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aFaceEdgeExp.current()));
+              if (anEdge->isDegenerated() || alreadyIterated.isBound(anEdge))
+                continue;
+              alreadyIterated.bind(anEdge, anEdge);
+              aNumEdges++;
+              if (anEdge->isClosed()) {
+                aNumClosed++;
+              } else {
+                aNotClosedEdge = anEdge;
+              }
+            }
+            if (aNumEdges == 2 && aNumClosed == 1) {
+              std::ostringstream aStream;
+              aStream<<"Base_Edge_"<<anIndex++;
+              theResultBody->generated(aNotClosedEdge, aStream.str(), theTag++);
+            }
+          }
+        }
+      }
+    }
+  }
 
   std::shared_ptr<GeomAlgoAPI_MakeSweep> aMakeSweep =
     std::dynamic_pointer_cast<GeomAlgoAPI_MakeSweep>(theMakeShape);
index a6ab995680ad1db03a72421d6f99ac8cc6a0a400..afb763fc614e09bd5a30eb49f3ba37afc0a40ac4 100755 (executable)
@@ -170,7 +170,7 @@ void FeaturesPlugin_Partition::storeResult(
 
   // Store modified shape.
   if(!aBaseShape.get() || aBaseShape->isEqual(theResultShape)) {
-    aResultBody->store(theResultShape);
+    aResultBody->store(theResultShape, false);
     setResult(aResultBody, theIndex);
     return;
   }
@@ -189,14 +189,11 @@ void FeaturesPlugin_Partition::storeResult(
   for(ListOfShape::const_iterator anIt = theObjects.cbegin(); anIt != theObjects.cend(); ++anIt) {
     GeomShapePtr aShape = *anIt;
     std::string aModEdgeName = aModName + "_Edge_" + std::to_string((long long)anIndex);
-    std::string aModFaceName = aModName + "_Face_" + std::to_string((long long)anIndex++);
     aResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::EDGE,
-                                             aModTag, aModEdgeName, *aMapOfSubShapes.get(), true);
-    aModTag += 10000;
+      aModTag, aModEdgeName, *aMapOfSubShapes.get(), false, true, true);
+    std::string aModFaceName = aModName + "_Face_" + std::to_string((long long)anIndex++);
     aResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::FACE,
-                                             aModTag, aModFaceName, *aMapOfSubShapes.get(), true);
-    aModTag += 10000;
-    aResultBody->loadDeletedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::EDGE, aDelTag);
+      aModTag + 1, aModFaceName, *aMapOfSubShapes.get(), false, true, true);
     aResultBody->loadDeletedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::FACE, aDelTag);
   }
 
index a386d8dc56f53fe16c7bc9c8e6388eeb7866ab45..ca72a5aeb951bc15b49bf129cd14b79e5e0e3508 100644 (file)
@@ -342,9 +342,6 @@ void FeaturesPlugin_Pipe::storeResult(const std::shared_ptr<GeomAPI_Shape> theBa
                                            aGenTag++, aGenName + "Face", *aMapOfSubShapes.get());
   }
 
-  aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, aShapeTypeToExplode,
-                                            aGenTag++, aGenName, *aMapOfSubShapes.get());
-
   // Store from shapes.
   int aFromTag = aGenTag;
   storeShapes(aResultBody, aBaseShapeType, aMapOfSubShapes,
index 51d64cba431065a2446b5c271d56cd71e788e6a5..53d02ab83e183e643c45c03357965aea72d51dc1 100644 (file)
 #include <ModelAPI_Validator.h>
 
 #include <GeomAPI_ShapeIterator.h>
+#include <GeomAPI_ShapeExplorer.h>
 
 #include <GeomAlgoAPI_Copy.h>
 #include <GeomAlgoAPI_ShapeBuilder.h>
 #include <GeomAlgoAPI_ShapeTools.h>
+#include <GeomAlgoAPI_MakeShapeCustom.h>
+
 
 //==================================================================================================
 FeaturesPlugin_RemoveSubShapes::FeaturesPlugin_RemoveSubShapes()
@@ -130,18 +133,48 @@ void FeaturesPlugin_RemoveSubShapes::execute()
     aResultShape = anAttrSelectionInList->value();
   }
 
+  // find all removed shapes
+  GeomAlgoAPI_MakeShapeCustom aDeletedSubs;
+  std::set<GeomAPI_Shape::ShapeType> aTypes; // types that where removed
+  aTypes.insert(GeomAPI_Shape::FACE);
+  for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) {
+    if (!anIt.current().get() || anIt.current()->isNull())
+      continue;
+    int anIndex;
+    for(anIndex = 0; anIndex < aSubsNb; ++anIndex) {
+      AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
+      GeomShapePtr aLeftShape = anAttrSelectionInList->value();
+      if (anIt.current()->isEqual(aLeftShape)) {
+        break; // found in a left-list
+      }
+    }
+    if (anIndex == aSubsNb) { // not found in left
+      aDeletedSubs.addDeleted(anIt.current());
+      aTypes.insert(anIt.current()->shapeType());
+      if (anIt.current()->shapeType() != GeomAPI_Shape::FACE) {
+        GeomAPI_ShapeExplorer aFaces(anIt.current(), GeomAPI_Shape::FACE);
+        for(; aFaces.more(); aFaces.next())
+          aDeletedSubs.addDeleted(aFaces.current());
+      }
+    }
+  }
+
+
   GeomAlgoAPI_Copy aCopy(aResultShape);
   aResultShape = aCopy.shape();
 
   // Store result.
   ResultBodyPtr aResultBody = document()->createBody(data());
   aResultBody->storeModified(aBaseShape, aResultShape, 1);
+  std::set<GeomAPI_Shape::ShapeType>::iterator aTypeIter = aTypes.begin();
+  for(; aTypeIter != aTypes.end(); aTypeIter++)
+    aResultBody->loadDeletedShapes(&aDeletedSubs, aBaseShape, *aTypeIter, 1);
   aResultBody->loadAndOrientModifiedShapes(&aCopy,
                                            aBaseShape,
                                            GeomAPI_Shape::FACE,
-                                           10000,
+                                           2,
                                            "Modified_Face",
                                            *aCopy.mapOfSubShapes().get(),
-                                           true);
+                                           true, false, true);
   setResult(aResultBody);
 }
index f885bce03b7603d0f1fc99cf29b5dfdb745bf1b7..07709d1ed7fa2a2056346f9e0f0c28ebed31b07e 100644 (file)
@@ -54,10 +54,6 @@ void FeaturesPlugin_Tools::storeModifiedShapes(GeomAlgoAPI_MakeShape& theAlgo,
       theResultBody->loadAndOrientModifiedShapes(&theAlgo,
                                 theBaseShape, GeomAPI_Shape::FACE,
                                 theFaceTag, theName + "_Face", theSubShapes, false, true);
-      if (theBaseShape->shapeType() == GeomAPI_Shape::COMPSOLID
-          || theBaseShape->shapeType() == GeomAPI_Shape::SOLID) {
-        break;
-      }
     }
     case GeomAPI_Shape::FACE:
     case GeomAPI_Shape::WIRE: {
index f5371bbf5b7bcfe5926ef512354cf537de7fac81..8a98df7e97ba911ace53474ea0d8a316dee7599d 100644 (file)
@@ -43,7 +43,8 @@ Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Extr
 Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Translation_1_1"), model.selection("SOLID", "Extrusion_2_1")])
 Translation_2 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Partition_1_1")], model.selection("EDGE", "PartSet/OZ"), 50)
 Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Translation_2_1/Translated_Face_24"), model.selection("FACE", "Translation_2_1/Translated_Face_13"), model.selection("FACE", "Translation_2_1/Translated_Face_16"), model.selection("FACE", "Translation_2_1/Translated_Face_12"), model.selection("FACE", "Translation_2_1/Translated_Face_9"), model.selection("FACE", "Translation_2_1/Translated_Face_10"), model.selection("FACE", "Translation_2_1/Translated_Face_11"), model.selection("FACE", "Translation_2_1/Translated_Face_25"), model.selection("FACE", "Translation_2_1/Translated_Face_20"), model.selection("FACE", "Translation_2_1/Translated_Face_19"), model.selection("FACE", "Translation_2_1/Translated_Face_18"), model.selection("FACE", "Translation_2_1/Translated_Face_27"), model.selection("FACE", "Translation_2_1/Translated_Face_17"), model.selection("FACE", "Translation_2_1/Translated_Face_31"), model.selection("FACE", "Translation_2_1/Translated_Face_32"), model.selection("FACE", "Translation_2_1/Translated_Face_30"), model.selection("FACE", "Translation_2_1/Translated_Face_28"), model.selection("FACE", "Translation_2_1/Translated_Face_29"), model.selection("FACE", "Translation_2_1/Translated_Face_8"), model.selection("FACE", "Translation_2_1/Translated_Face_22"), model.selection("FACE", "Translation_2_1/Translated_Face_7"), model.selection("FACE", "Translation_2_1/Translated_Face_6"), model.selection("FACE", "Translation_2_1/Translated_Face_5"), model.selection("FACE", "Translation_2_1/Translated_Face_3"), model.selection("FACE", "Translation_2_1/Translated_Face_1"), model.selection("FACE", "Translation_2_1/Translated_Face_2"), model.selection("FACE", "Translation_2_1/Translated_Face_21"), model.selection("FACE", "Translation_2_1/Translated_Face_4"), model.selection("FACE", "Translation_2_1/Translated_Face_25"), model.selection("FACE", "Translation_2_1/Translated_Face_27"), model.selection("FACE", "Translation_2_1/Translated_Face_21"), model.selection("FACE", "Translation_2_1/Translated_Face_22"), model.selection("FACE", "Translation_2_1/Translated_Face_26"), model.selection("FACE", "Translation_2_1/Translated_Face_23"), model.selection("FACE", "Translation_2_1/Translated_Face_30"), model.selection("FACE", "Translation_2_1/Translated_Face_23"), model.selection("FACE", "Translation_2_1/Translated_Face_14"), model.selection("FACE", "Translation_2_1/Translated_Face_15")])
-model.do()
+#Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Translation_2_1_6/Translated_Face_1"), model.selection("FACE", "Translation_2_1_5/Translated_Face_1"), model.selection("FACE", "Translation_2_1_5/Translated_Face_4"), model.selection("FACE", "Translation_2_1_4/Translated_Face_4"), model.selection("FACE", "Translation_2_1_5/Translated_Face_3"), model.selection("FACE", "Translation_2_1_5/Translated_Face_2"), model.selection("FACE", "Translation_2_1_5/Translated_Face_5"), model.selection("FACE", "Translation_2_1_7/Translated_Face_5"), model.selection("FACE", "Translation_2_1_6/Translated_Face_5"), model.selection("FACE", "Translation_2_1_4/Translated_Face_1"), model.selection("FACE", "Translation_2_1_2/Translated_Face_2"), model.selection("FACE", "Translation_2_1_5/Translated_Face_5"), model.selection("FACE", "Translation_2_1_2/Translated_Face_1"), model.selection("FACE", "Translation_2_1_4/Translated_Face_5"), model.selection("FACE", "Translation_2_1_2/Translated_Face_3"), model.selection("FACE", "Translation_2_1_3/Translated_Face_5"), model.selection("FACE", "Translation_2_1_1/Translated_Face_3"), model.selection("FACE", "Translation_2_1_4/Translated_Face_2"), model.selection("FACE", "Translation_2_1_2/Translated_Face_3"), model.selection("FACE", "Translation_2_1_1/Translated_Face_4"), model.selection("FACE", "Translation_2_1_1/Translated_Face_1"), model.selection("FACE", "Translation_2_1_1/Translated_Face_2"), model.selection("FACE", "Translation_2_1_3/Translated_Face_4"), model.selection("FACE", "Translation_2_1_4/Translated_Face_3"), model.selection("FACE", "Translation_2_1_3/Translated_Face_5"), model.selection("FACE", "Translation_2_1_3/Translated_Face_2"), model.selection("FACE", "Translation_2_1_3/Translated_Face_3"), model.selection("FACE", "Translation_2_1_3/Translated_Face_1"), model.selection("FACE", "Translation_2_1_7/Translated_Face_3"), model.selection("FACE", "Translation_2_1_7/Translated_Face_5"), model.selection("FACE", "Translation_2_1_7/Translated_Face_4"), model.selection("FACE", "Translation_2_1_7/Translated_Face_1"), model.selection("FACE", "Translation_2_1_7/Translated_Face_2"), model.selection("FACE", "Translation_2_1_6/Translated_Face_4"), model.selection("FACE", "Translation_2_1_4/Translated_Face_5"), model.selection("FACE", "Translation_2_1_6/Translated_Face_5"), model.selection("FACE", "Translation_2_1_6/Translated_Face_2"), model.selection("FACE", "Translation_2_1_6/Translated_Face_3")])
+
 model.end()
 
 groupFeature = Group_1.feature()
diff --git a/src/FeaturesPlugin/Test/Test2172.py b/src/FeaturesPlugin/Test/Test2172.py
new file mode 100644 (file)
index 0000000..65c4dac
--- /dev/null
@@ -0,0 +1,89 @@
+## 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
+
+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(-85.62958302127123, 51.64856737222455, 159.4430553521271, 401.6485673722245)
+SketchLine_2 = Sketch_1.addLine(159.4430553521271, 401.6485673722245, 909.4430553521272, 401.6485673722245)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(909.4430553521272, 401.6485673722245, 909.4430553521272, -98.35143262777548)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(909.4430553521272, -98.35143262777548, 551.916977573864, -398.3514326277755)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(551.916977573864, -398.3514326277755, -18.08302242613596, -398.3514326277755)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_1.addLine(-18.08302242613596, -398.3514326277755, -18.08302242613596, -98.35143262777552)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchArc_1 = Sketch_1.addArc(0, -7.626897158721915e-023, -85.62958302127123, 51.64856737222455, -18.08302242613596, -98.35143262777552, False)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchArc_1.endPoint())
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchArc_1.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_6.result())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], 100)
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_2.result(), 750)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_3.result(), 500)
+SketchConstraintLength_3 = Sketch_1.setLength(SketchLine_5.result(), 570)
+SketchConstraintAngle_1 = Sketch_1.setAngleBackward(SketchLine_5.result(), SketchLine_4.result(), 139.9999999999999)
+SketchConstraintAngle_2 = Sketch_1.setAngle(SketchLine_1.result(), SketchLine_2.result(), 124.9999999999987)
+SketchConstraintLength_4 = Sketch_1.setLength(SketchLine_6.result(), 300)
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchArc_1.startPoint(), SketchLine_2.result(), 350)
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchLine_4.startPoint(), SketchLine_5.result(), 300)
+SketchPoint_1 = Sketch_1.addPoint(model.selection("VERTEX", "PartSet/Origin"))
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchArc_1.center(), SketchPoint_1.coordinates())
+SketchCircle_1 = Sketch_1.addCircle(623.3624504738834, 247.4315530304268, 75)
+SketchCircle_2 = Sketch_1.addCircle(267.9975824521076, 55.86558171402226, 100)
+SketchLine_7 = Sketch_1.addLine(-18.08302242613596, -98.35143262777552, 356.0223839531057, 103.3169707422677)
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchLine_8 = Sketch_1.addLine(557.3438493481349, 211.8430112592427, 909.4430553521272, 401.6485673722245)
+SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_8.endPoint())
+SketchConstraintCoincidence_11 = Sketch_1.setCoincident(SketchCircle_2.center(), SketchLine_7.result())
+SketchConstraintCoincidence_12 = Sketch_1.setCoincident(SketchCircle_1.center(), SketchLine_7.result())
+SketchConstraintRadius_2 = Sketch_1.setRadius(SketchCircle_2.results()[1], 100)
+SketchConstraintRadius_3 = Sketch_1.setRadius(SketchCircle_1.results()[1], 75)
+SketchPoint_2 = Sketch_1.addPoint(557.3438493481349, 211.8430112592427)
+SketchConstraintCoincidence_13 = Sketch_1.setCoincident(SketchPoint_2.coordinates(), SketchLine_8.startPoint())
+SketchConstraintCollinear_1 = Sketch_1.setCollinear(SketchLine_7.result(), SketchLine_8.result())
+SketchConstraintCoincidence_14 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchCircle_2.results()[1])
+SketchConstraintDistance_3 = Sketch_1.setDistance(SketchCircle_2.center(), SketchLine_6.endPoint(), 325)
+SketchConstraintCoincidence_15 = Sketch_1.setCoincident(SketchPoint_2.coordinates(), SketchCircle_1.results()[1])
+SketchConstraintDistance_4 = Sketch_1.setDistance(SketchCircle_1.center(), SketchLine_2.endPoint(), 325)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f-SketchLine_8f")], model.selection("EDGE", "PartSet/OZ"), 360, 0)
+Revolution_2 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_2_2f-SketchLine_7r")], model.selection("EDGE", "PartSet/OZ"), 360, 0)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Revolution_1_1/Lateral_Edge_1"), model.selection("EDGE", "Revolution_1_1/Lateral_Edge_2"), model.selection("EDGE", "Revolution_1_1/Base_Edge_1"), model.selection("EDGE", "Revolution_1_1/Base_Edge_2"), model.selection("EDGE", "Revolution_2_1/Lateral_Edge_1"), model.selection("EDGE", "Revolution_2_1/Lateral_Edge_2"), model.selection("EDGE", "Revolution_2_1/Lateral_Edge_3"), model.selection("EDGE", "Revolution_2_1/Base_Edge_2"), model.selection("EDGE", "Revolution_2_1/Base_Edge_3"), model.selection("EDGE", "Revolution_2_1/Base_Edge_1")])
+model.end()
+
+# check that resulting group selection is valid
+from ModelAPI import *
+aFactory = ModelAPI_Session.get().validators()
+assert(aFactory.validate(Group_1.feature()))
+assert(Group_1.groupList().size() == 10)
+for a in range(10):
+  assert(Group_1.groupList().value(a).value().shapeTypeStr() == "EDGE")
+  assert(len(Group_1.groupList().value(a).namingName()) > 0)
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/Test2194.py b/src/FeaturesPlugin/Test/Test2194.py
new file mode 100644 (file)
index 0000000..0fd8972
--- /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>
+##
+
+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("YOZ"))
+SketchCircle_1 = Sketch_1.addCircle(-79.57211859899775, 93.0358363165245, 69.46562387481423)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection(), 10, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face_1"))
+SketchCircle_2 = Sketch_2.addCircle(-111.8968837135755, 98.96901887198163, 6.57145775571253)
+SketchCircle_3 = Sketch_2.addCircle(-41.97827733564338, 89.35676702647821, 6.102067916018811)
+model.do()
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchCircle_2_2f"), model.selection("FACE", "Sketch_2/Face-SketchCircle_3_2f")], model.selection(), 10, 0)
+Boolean_1 = model.addSmash(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], [model.selection("SOLID", "Extrusion_2_1"), model.selection("SOLID", "Extrusion_2_2")])
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Extrusion_2_2/To_Face_1"), model.selection("FACE", "Extrusion_2_2/From_Face_1"), model.selection("FACE", "Extrusion_2_2/Generated_Face_1"), model.selection("FACE", "Extrusion_2_1/From_Face_1"), model.selection("FACE", "Boolean_1_1_1/Modified_1"), model.selection("FACE", "Extrusion_1_1/From_Face_1"), model.selection("FACE", "Extrusion_1_1/Generated_Face_1"), model.selection("FACE", "Extrusion_2_2/From_Face_1"), model.selection("FACE", "Extrusion_2_1/Generated_Face_1"), model.selection("FACE", "Extrusion_2_1/From_Face_1"), model.selection("FACE", "Extrusion_2_1/To_Face_1")])
+model.do()
+model.end()
+
+groupFeature = Group_1.feature()
+groupSelectionList = groupFeature.selectionList("group_list")
+assert(groupSelectionList.size() == 11)
+for index in range(0, groupSelectionList.size()):
+  attrSelection = groupSelectionList.value(index)
+  shape = attrSelection.value()
+  name = attrSelection.namingName()
+  assert(shape.isFace())
+  assert(name != ""), "Empty shape name"
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/Test2197_1.py b/src/FeaturesPlugin/Test/Test2197_1.py
new file mode 100644 (file)
index 0000000..e157deb
--- /dev/null
@@ -0,0 +1,45 @@
+## Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+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("YOZ"))
+SketchCircle_1 = Sketch_1.addCircle(-150, 79, -50, 79)
+SketchCircle_2 = Sketch_1.addCircle(-155, 278, -10, 278)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f-SketchCircle_2_2f")], model.selection("EDGE", "PartSet/OZ"), 360, 0)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Revolution_1_1/Base_Edge_1"), model.selection("EDGE", "Revolution_1_1/Base_Edge_2"), model.selection("EDGE", "Revolution_1_1/Base_Edge_3")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Revolution_1_1/Lateral_Edge_1"), model.selection("EDGE", "Revolution_1_1/Lateral_Edge_2"), model.selection("EDGE", "Revolution_1_1/Lateral_Edge_3")])
+model.end()
+
+# check that resulting group selection is valid
+from ModelAPI import *
+aFactory = ModelAPI_Session.get().validators()
+for aGroupIter in [Group_1, Group_2]:
+  assert(aFactory.validate(aGroupIter.feature()))
+  assert(aGroupIter.groupList().size() == 3)
+  for a in range(3):
+    assert(aGroupIter.groupList().value(a).value().shapeTypeStr() == "EDGE")
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/Test2197_2.py b/src/FeaturesPlugin/Test/Test2197_2.py
new file mode 100644 (file)
index 0000000..c32cd44
--- /dev/null
@@ -0,0 +1,48 @@
+## 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
+
+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("YOZ"))
+SketchCircle_1 = Sketch_1.addCircle(-150, 80, 100)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchCircle_1_2")])
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Face_1_1")], model.selection("EDGE", "PartSet/OZ"), 360, 0)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Revolution_1_1/Base_Edge_1")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Revolution_1_1/Lateral_Edge_1")])
+Group_3 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "Revolution_1_1/Lateral_Edge_1&Revolution_1_1/Base_Edge_1")])
+model.end()
+
+# check that resulting group selection is valid
+from ModelAPI import *
+aFactory = ModelAPI_Session.get().validators()
+for aGroupIter in [Group_1, Group_2, Group_3]:
+  assert(aFactory.validate(aGroupIter.feature()))
+  assert(aGroupIter.groupList().size() == 1)
+  if aGroupIter == Group_3:
+    assert(aGroupIter.groupList().value(0).value().shapeTypeStr() == "VERTEX")
+  else:
+    assert(aGroupIter.groupList().value(0).value().shapeTypeStr() == "EDGE")
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/Test2197_3.py b/src/FeaturesPlugin/Test/Test2197_3.py
new file mode 100644 (file)
index 0000000..e07e3e1
--- /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>
+##
+
+# revolution of 3-edges contour (4th is used as axis of rotation) is checking for naming of edges
+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(138, 47, 265, 35)
+SketchLine_2 = Sketch_1.addLine(265, 35, 248, 186)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(248, 186, 138, 234)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(138, 234, 138, 47)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_4.endPoint())
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchLine_2f-SketchLine_3f-SketchLine_4f")], model.selection("EDGE", "Sketch_1/Edge-SketchLine_4"), 360, 0)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Revolution_1_1/Lateral_Edge_4"), model.selection("EDGE", "Revolution_1_1/Base_Edge_2"), model.selection("EDGE", "Revolution_1_1/Lateral_Edge_2"), model.selection("EDGE", "Revolution_1_1/Base_Edge_1"), model.selection("EDGE", "Revolution_1_1/Base_Edge_3")])
+model.end()
+
+# check that resulting group selection is valid
+from ModelAPI import *
+aFactory = ModelAPI_Session.get().validators()
+assert(aFactory.validate(Group_1.feature()))
+assert(Group_1.groupList().size() == 5)
+for a in range(5):
+  assert(Group_1.groupList().value(a).value().shapeTypeStr() == "EDGE")
+  assert(len(Group_1.groupList().value(a).namingName()) > 0)
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/Test2197_4.py b/src/FeaturesPlugin/Test/Test2197_4.py
new file mode 100644 (file)
index 0000000..9ebe471
--- /dev/null
@@ -0,0 +1,67 @@
+## 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>
+##
+
+# revolution of 4-edges contour (5th is used as axis of rotation) is checking for naming of edges
+
+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(138.1074168797953, 47.3145780051151, 265.9846547314579, 35.80562659846547)
+SketchLine_2 = Sketch_1.addLine(248.0818414322251, 186.7007672634271, 138.1074168797954, 234.0153452685422)
+SketchLine_2.setName("SketchLine_3")
+SketchLine_2.result().setName("SketchLine_3")
+SketchLine_3 = Sketch_1.addLine(138.1074168797954, 234.0153452685422, 138.1074168797953, 47.3145780051151)
+SketchLine_3.setName("SketchLine_4")
+SketchLine_3.result().setName("SketchLine_4")
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_1.setName("SketchConstraintCoincidence_3")
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintCoincidence_2.setName("SketchConstraintCoincidence_4")
+SketchLine_4 = Sketch_1.addLine(248.0818414322251, 186.7007672634271, 215.8394027534853, 111.2328618876045)
+SketchLine_4.setName("SketchLine_5")
+SketchLine_4.result().setName("SketchLine_5")
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.startPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_3.setName("SketchConstraintCoincidence_5")
+SketchLine_5 = Sketch_1.addLine(215.8394027534853, 111.2328618876045, 265.9846547314579, 35.80562659846547)
+SketchLine_5.setName("SketchLine_6")
+SketchLine_5.result().setName("SketchLine_6")
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_4.setName("SketchConstraintCoincidence_6")
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_5.endPoint())
+SketchConstraintCoincidence_5.setName("SketchConstraintCoincidence_7")
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchLine_3f-SketchLine_4f-SketchLine_5r-SketchLine_6r")], model.selection("EDGE", "Sketch_1/Edge-SketchLine_4"), 360, 0)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Revolution_1_1/Generated_Face_5&Revolution_1_1/Generated_Face_1"), model.selection("EDGE", "Revolution_1_1/Generated_Face_2&Revolution_1_1/Generated_Face_1"), model.selection("EDGE", "Revolution_1_1/Generated_Face_3&Revolution_1_1/Generated_Face_2"), model.selection("EDGE", "Revolution_1_1/Base_Edge_2"), model.selection("EDGE", "Revolution_1_1/Base_Edge_1"), model.selection("EDGE", "Revolution_1_1/Generated_Face_1"), model.selection("EDGE", "Revolution_1_1/Generated_Face_2")])
+model.end()
+
+# check that resulting group selection is valid
+from ModelAPI import *
+aFactory = ModelAPI_Session.get().validators()
+assert(aFactory.validate(Group_1.feature()))
+assert(Group_1.groupList().size() == 7)
+for a in range(7):
+  assert(Group_1.groupList().value(a).value().shapeTypeStr() == "EDGE")
+  assert(len(Group_1.groupList().value(a).namingName()) > 0)
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/Test2215.py b/src/FeaturesPlugin/Test/Test2215.py
new file mode 100644 (file)
index 0000000..6c2b3f9
--- /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>
+##
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0, 0, 0, 50)
+SketchLine_2 = Sketch_1.addLine(0, 50, 50, 50)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(50, 50, 50, 0)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(50, 0, 0, 0)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintRigid_1 = Sketch_1.setFixed(SketchLine_1.startPoint())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_1.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_4.result(), 50)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_1.result(), 50)
+SketchConstraintParallel_1 = Sketch_1.setParallel(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintParallel_2 = Sketch_1.setParallel(SketchLine_2.result(), SketchLine_4.result())
+SketchConstraintPerpendicular_1 = Sketch_1.setPerpendicular(SketchLine_1.result(), SketchLine_4.result())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r")], model.selection(), 50, 0)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Extrusion_1_1/From_Face_1"), 25, True)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchLine_5 = Sketch_2.addLine(84.67753244325934, -72.65003691291119, -28.95543815719345, -72.65003691291119)
+SketchLine_6 = Sketch_2.addLine(-28.95543815719345, -72.65003691291119, -28.95543815719345, 10.01640181835304)
+SketchLine_7 = Sketch_2.addLine(-28.95543815719345, 10.01640181835304, 84.67753244325934, 10.01640181835304)
+SketchLine_8 = Sketch_2.addLine(84.67753244325934, 10.01640181835304, 84.67753244325934, -72.65003691291119)
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintHorizontal_1 = Sketch_2.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_2 = Sketch_2.setVertical(SketchLine_6.result())
+SketchConstraintHorizontal_2 = Sketch_2.setHorizontal(SketchLine_7.result())
+SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_8.result())
+model.do()
+Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_6"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_8"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_5"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_7")])
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Wire_1_1")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1"), model.selection("FACE", "Face_1_1")])
+Sketch_3 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_9 = Sketch_3.addLine(0, 0, 0, 10)
+SketchLine_10 = Sketch_3.addLine(0, 10, 10, 10)
+SketchConstraintCoincidence_9 = Sketch_3.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint())
+SketchLine_11 = Sketch_3.addLine(10, 10, 10, 0)
+SketchConstraintCoincidence_10 = Sketch_3.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint())
+SketchLine_12 = Sketch_3.addLine(10, 0, 0, 0)
+SketchConstraintCoincidence_11 = Sketch_3.setCoincident(SketchLine_11.endPoint(), SketchLine_12.startPoint())
+SketchConstraintCoincidence_12 = Sketch_3.setCoincident(SketchLine_12.endPoint(), SketchLine_9.startPoint())
+SketchConstraintRigid_2 = Sketch_3.setFixed(SketchLine_9.startPoint())
+SketchConstraintVertical_4 = Sketch_3.setVertical(SketchLine_9.result())
+SketchConstraintLength_3 = Sketch_3.setLength(SketchLine_12.result(), 10)
+SketchConstraintLength_4 = Sketch_3.setLength(SketchLine_9.result(), 10)
+SketchConstraintParallel_3 = Sketch_3.setParallel(SketchLine_9.result(), SketchLine_11.result())
+SketchConstraintParallel_4 = Sketch_3.setParallel(SketchLine_10.result(), SketchLine_12.result())
+SketchConstraintPerpendicular_2 = Sketch_3.setPerpendicular(SketchLine_9.result(), SketchLine_12.result())
+model.do()
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_9r-SketchLine_10r-SketchLine_11r-SketchLine_12r")], model.selection(), 50, 0)
+Boolean_1 = model.addCut(Part_1_doc, [model.selection("COMPSOLID", "Partition_1_1_1")], [model.selection("SOLID", "Extrusion_2_1")])
+model.do()
+model.end()
diff --git a/src/FeaturesPlugin/Test/Test2222.py b/src/FeaturesPlugin/Test/Test2222.py
new file mode 100644 (file)
index 0000000..ccbab14
--- /dev/null
@@ -0,0 +1,57 @@
+## 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>
+##
+
+# check that fac partitioned by plane has correctly named modified edges
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(173, 265, -254, 265)
+SketchLine_2 = Sketch_1.addLine(-254, 265, -254, 118)
+SketchLine_3 = Sketch_1.addLine(-254, 118, 173, 118)
+SketchLine_4 = Sketch_1.addLine(173, 118, 173, 265)
+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()
+Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_3"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_4")])
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/YOZ"), 1, False)
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("FACE", "Plane_1")])
+Group_1 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Partition_1_1_2/Modified_Edge_1_1")])
+model.end()
+
+# check that resulting group selection is valid
+from ModelAPI import *
+aFactory = ModelAPI_Session.get().validators()
+assert(aFactory.validate(Group_1.feature()))
+assert(Group_1.groupList().size() == 1)
+assert(Group_1.groupList().value(0).value().shapeTypeStr() == "EDGE")
+assert(len(Group_1.groupList().value(0).namingName()) > 0)
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/Test2231.py b/src/FeaturesPlugin/Test/Test2231.py
new file mode 100644 (file)
index 0000000..f51ba4f
--- /dev/null
@@ -0,0 +1,80 @@
+## 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
+
+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(306.7092651757188, 0, 0, 0)
+SketchPoint_1 = Sketch_1.addPoint(model.selection("VERTEX", "PartSet/Origin"))
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchPoint_1.result())
+SketchLine_2 = Sketch_1.addLine(0, 0, 0, 127.7955271565495)
+SketchLine_3 = Sketch_1.addLine(0, 127.7955271565495, 306.7092651757188, 127.7955271565495)
+SketchLine_4 = Sketch_1.addLine(306.7092651757188, 127.7955271565495, 306.7092651757188, 0)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_5 = 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(0, 127.7955271565495, -349.8402555910542, 127.7955271565495)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_1.addLine(-349.8402555910542, 127.7955271565495, -349.8402555910542, 0)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchLine_7 = Sketch_1.addLine(-349.8402555910542, 0, 0, 0)
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_7.endPoint())
+SketchLine_8 = Sketch_1.addLine(0, 0, 0, -164.5367412140575)
+SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_8.startPoint())
+SketchLine_9 = Sketch_1.addLine(0, -164.5367412140575, -349.8402555910542, -164.5367412140575)
+SketchConstraintCoincidence_11 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchLine_10 = Sketch_1.addLine(-349.8402555910542, -164.5367412140575, -349.8402555910542, 0)
+SketchConstraintCoincidence_12 = Sketch_1.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint())
+SketchConstraintCoincidence_13 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_10.endPoint())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_7.result())
+SketchConstraintHorizontal_4 = Sketch_1.setHorizontal(SketchLine_5.result())
+SketchConstraintHorizontal_5 = Sketch_1.setHorizontal(SketchLine_9.result())
+SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_6.result())
+SketchConstraintVertical_4 = Sketch_1.setVertical(SketchLine_10.result())
+SketchConstraintVertical_5 = Sketch_1.setVertical(SketchLine_8.result())
+SketchLine_11 = Sketch_1.addLine(527.1565495207667, -78.27476038338659, 81.46964856230041, -78.27476038338659)
+SketchLine_12 = Sketch_1.addLine(81.46964856230041, -78.27476038338659, 81.46964856230041, -285.9424920127795)
+SketchLine_13 = Sketch_1.addLine(81.46964856230041, -285.9424920127795, 527.1565495207667, -285.9424920127795)
+SketchLine_14 = Sketch_1.addLine(527.1565495207667, -285.9424920127795, 527.1565495207667, -78.27476038338659)
+SketchConstraintCoincidence_14 = Sketch_1.setCoincident(SketchLine_14.endPoint(), SketchLine_11.startPoint())
+SketchConstraintCoincidence_15 = Sketch_1.setCoincident(SketchLine_11.endPoint(), SketchLine_12.startPoint())
+SketchConstraintCoincidence_16 = Sketch_1.setCoincident(SketchLine_12.endPoint(), SketchLine_13.startPoint())
+SketchConstraintCoincidence_17 = Sketch_1.setCoincident(SketchLine_13.endPoint(), SketchLine_14.startPoint())
+SketchConstraintHorizontal_6 = Sketch_1.setHorizontal(SketchLine_11.result())
+SketchConstraintVertical_6 = Sketch_1.setVertical(SketchLine_12.result())
+SketchConstraintHorizontal_7 = Sketch_1.setHorizontal(SketchLine_13.result())
+SketchConstraintVertical_7 = Sketch_1.setVertical(SketchLine_14.result())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_2f-SketchLine_5f-SketchLine_6f-SketchLine_7f"), model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r"), model.selection("FACE", "Sketch_1/Face-SketchLine_7r-SketchLine_8r-SketchLine_9r-SketchLine_10r"), model.selection("FACE", "Sketch_1/Face-SketchLine_11f-SketchLine_12f-SketchLine_13f-SketchLine_14f")], model.selection(), 10, 0)
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1"), model.selection("COMPSOLID", "Extrusion_1_2")])
+model.do()
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/Test2233.py b/src/FeaturesPlugin/Test/Test2233.py
new file mode 100644 (file)
index 0000000..5c6d5f2
--- /dev/null
@@ -0,0 +1,54 @@
+## 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>
+##
+
+# check that revolution that produces a sphere has correctly named 2 vertices with different names
+
+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("YOZ"))
+SketchPoint_1 = Sketch_1.addPoint(model.selection("VERTEX", "PartSet/Origin"))
+SketchLine_1 = Sketch_1.addLine(model.selection("EDGE", "PartSet/OZ"))
+SketchArc_1 = Sketch_1.addArc(0, 0, 0, 50, 0, -50, True)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchArc_1.center())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.result(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.result())
+SketchLine_2 = Sketch_1.addLine(0, 50, 0, -50)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchArc_1.endPoint())
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchArc_1_2f-SketchLine_2f")], model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), 360, 0)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "Revolution_1_1/Vertex_1"), model.selection("VERTEX", "Revolution_1_1/Vertex_2")])
+model.end()
+
+# check that resulting group selection is valid and names are different
+from ModelAPI import *
+aFactory = ModelAPI_Session.get().validators()
+assert(aFactory.validate(Group_1.feature()))
+assert(Group_1.groupList().size() == 2)
+assert(Group_1.groupList().value(0).value().shapeTypeStr() == "VERTEX")
+assert(len(Group_1.groupList().value(0).namingName()) > 0)
+assert(Group_1.groupList().value(1).value().shapeTypeStr() == "VERTEX")
+assert(Group_1.groupList().value(0).namingName() != Group_1.groupList().value(1).namingName())
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/Test2240.py b/src/FeaturesPlugin/Test/Test2240.py
new file mode 100644 (file)
index 0000000..5317ea2
--- /dev/null
@@ -0,0 +1,151 @@
+## 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
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "length_assemblage", "10")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0, 60, 10, 60)
+SketchLine_2 = Sketch_1.addLine(model.selection("EDGE", "PartSet/OY"))
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_2.result())
+SketchLine_3 = Sketch_1.addLine(10, 60, 10, 40)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(10, 40, 20, 40)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(20, 40, 20, 20)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_1.addLine(20, 20, 30, 20)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchLine_7 = Sketch_1.addLine(30, 20, 30, 0)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchLine_8 = Sketch_1.addLine(model.selection("EDGE", "PartSet/OX"))
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_8.result())
+SketchLine_9 = Sketch_1.addLine(30, 0, 81.26217508737108, 0)
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_9.startPoint())
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_9.endPoint(), SketchLine_8.result())
+SketchLine_10 = Sketch_1.addLine(0, 60, 0, 81.26217508737108)
+SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_10.startPoint())
+SketchConstraintCoincidence_11 = Sketch_1.setCoincident(SketchLine_10.endPoint(), SketchLine_2.result())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_4.result())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_6.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_5.result())
+SketchArc_1 = Sketch_1.addArc(4.151438510550382e-034, -3.089278765476956e-034, 81.26217508737108, 0, 0, 81.26217508737108, False)
+SketchConstraintCoincidence_12 = Sketch_1.setCoincident(SketchLine_2.startPoint(), SketchArc_1.center())
+SketchConstraintCoincidence_13 = Sketch_1.setCoincident(SketchLine_9.endPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_14 = Sketch_1.setCoincident(SketchLine_2.result(), SketchArc_1.endPoint())
+SketchConstraintCoincidence_15 = Sketch_1.setCoincident(SketchLine_10.endPoint(), SketchArc_1.endPoint())
+SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_7.result())
+SketchArc_2 = Sketch_1.addArc(4.151438510550382e-034, -3.089278765476956e-034, 76.26217508737108, 0, 0, 76.26217508737108, False)
+SketchConstraintCoincidence_16 = Sketch_1.setCoincident(SketchLine_2.startPoint(), SketchArc_2.center())
+SketchConstraintCoincidence_16.setName("SketchConstraintCoincidence_23")
+SketchConstraintCoincidence_17 = Sketch_1.setCoincident(SketchLine_9.result(), SketchArc_2.startPoint())
+SketchConstraintCoincidence_17.setName("SketchConstraintCoincidence_24")
+SketchConstraintCoincidence_18 = Sketch_1.setCoincident(SketchLine_10.result(), SketchArc_2.endPoint())
+SketchConstraintCoincidence_18.setName("SketchConstraintCoincidence_25")
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchArc_1.endPoint(), SketchArc_2.endPoint(), 5)
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_7.result(), "2*length_assemblage")
+SketchConstraintLength_1.setName("SketchConstraintLength_2")
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_6.result(), "length_assemblage")
+SketchConstraintLength_2.setName("SketchConstraintLength_3")
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_5.result(), SketchLine_7.result())
+SketchConstraintEqual_1.setName("SketchConstraintEqual_2")
+SketchConstraintEqual_2 = Sketch_1.setEqual(SketchLine_6.result(), SketchLine_4.result())
+SketchConstraintEqual_2.setName("SketchConstraintEqual_3")
+SketchConstraintEqual_3 = Sketch_1.setEqual(SketchLine_5.result(), SketchLine_3.result())
+SketchConstraintEqual_3.setName("SketchConstraintEqual_4")
+SketchConstraintEqual_4 = Sketch_1.setEqual(SketchLine_4.result(), SketchLine_1.result())
+SketchConstraintEqual_4.setName("SketchConstraintEqual_5")
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_2.addCircle(9.082839147404137, 71.32948234489588, 2.005056553640547)
+SketchCircle_2 = Sketch_2.addCircle(20.11065019242717, 63.7102674410618, 2.268462537186828)
+SketchCircle_3 = Sketch_2.addCircle(26.52683116407693, 51.67992811921848, 2.727171758268866)
+SketchCircle_4 = Sketch_2.addCircle(38.35666483055617, 58.29661474623231, 3.007584830460834)
+SketchCircle_5 = Sketch_2.addCircle(33.94554041254697, 44.0607132153844, 3.054011155390377)
+SketchCircle_6 = Sketch_2.addCircle(48.58245325412298, 42.45666797247195, 2.346858526438435)
+SketchCircle_7 = Sketch_2.addCircle(38.95818179664835, 31.42885692744893, 3.547307159201095)
+SketchCircle_8 = Sketch_2.addCircle(63.82088306179116, 27.41874382016783, 4.536925074373651)
+SketchCircle_9 = Sketch_2.addCircle(50.18649849703544, 28.4212720969881, 4.820482891521984)
+SketchCircle_10 = Sketch_2.addCircle(49.58498153094326, 15.18789884296047, 2.552020354335177)
+SketchCircle_11 = Sketch_2.addCircle(66.22695092615982, 10.77677442495125, 4.536925074373645)
+SketchCircle_12 = Sketch_2.addCircle(50.98852111849166, 6.165144351577979, 3.547307159201085)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_1f-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_6f-SketchLine_7f-SketchLine_9f-SketchLine_10r-SketchArc_2_2f")])
+Face_2 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_9f-SketchLine_10r-SketchArc_1_2f-SketchArc_2_2r")])
+Face_3 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchCircle_1_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_2_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_3_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_4_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_5_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_6_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_7_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_9_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_8_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_10_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_12_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_11_2")])
+Face_4 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchCircle_1_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_2_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_3_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_4_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_5_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_7_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_6_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_9_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_8_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_10_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_12_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_11_2"), model.selection("WIRE", "Sketch_1/Wire-SketchLine_1f-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_6f-SketchLine_7f-SketchLine_9f-SketchLine_10r-SketchArc_2_2f")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("FACE", "Face_2_1"), model.selection("FACE", "Face_3_1"), model.selection("FACE", "Face_3_2"), model.selection("FACE", "Face_3_3"), model.selection("FACE", "Face_3_4"), model.selection("FACE", "Face_3_5"), model.selection("FACE", "Face_3_6"), model.selection("FACE", "Face_3_7"), model.selection("FACE", "Face_3_8"), model.selection("FACE", "Face_3_9"), model.selection("FACE", "Face_3_10"), model.selection("FACE", "Face_3_11"), model.selection("FACE", "Face_3_12"), model.selection("FACE", "Face_4_1")])
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Face_2_1"), model.selection("FACE", "Face_3_7"), model.selection("FACE", "Face_3_5"), model.selection("FACE", "Face_3_3"), model.selection("FACE", "Face_3_4"), model.selection("FACE", "Face_3_1"), model.selection("FACE", "Face_3_2"), model.selection("FACE", "Face_3_6"), model.selection("FACE", "Face_3_11"), model.selection("FACE", "Face_3_10"), model.selection("FACE", "Face_3_8"), model.selection("FACE", "Face_3_9"), model.selection("FACE", "Face_3_12")])
+Group_1.result().setName("eau")
+Group_1.result().setColor(0, 170, 255)
+Group_2 = model.addGroup(Part_1_doc, [model.selection("FACE", "Face_4_1")])
+Group_2.result().setName("acier")
+Group_2.result().setColor(170, 85, 0)
+Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "PartSet/XOY"))
+SketchLine_11 = Sketch_3.addLine(40, 0, 30, 0)
+SketchPoint_1 = Sketch_3.addPoint(model.selection("VERTEX", "Partition_1_1_1/Modified_Edge_15_6&Partition_1_1_1/Modified_Edge_15_5"))
+SketchConstraintCoincidence_19 = Sketch_3.setCoincident(SketchLine_11.endPoint(), SketchPoint_1.result())
+SketchLine_12 = Sketch_3.addLine(30, 0, 30, 10)
+SketchLine_13 = Sketch_3.addLine(30, 10, 40, 10)
+SketchLine_14 = Sketch_3.addLine(40, 10, 40, 0)
+SketchConstraintCoincidence_20 = Sketch_3.setCoincident(SketchLine_14.endPoint(), SketchLine_11.startPoint())
+SketchConstraintCoincidence_21 = Sketch_3.setCoincident(SketchLine_11.endPoint(), SketchLine_12.startPoint())
+SketchConstraintCoincidence_22 = Sketch_3.setCoincident(SketchLine_12.endPoint(), SketchLine_13.startPoint())
+SketchConstraintCoincidence_23 = Sketch_3.setCoincident(SketchLine_13.endPoint(), SketchLine_14.startPoint())
+SketchConstraintCoincidence_23.setName("SketchConstraintCoincidence_26")
+SketchConstraintHorizontal_4 = Sketch_3.setHorizontal(SketchLine_11.result())
+SketchConstraintVertical_4 = Sketch_3.setVertical(SketchLine_12.result())
+SketchConstraintHorizontal_5 = Sketch_3.setHorizontal(SketchLine_13.result())
+SketchConstraintVertical_5 = Sketch_3.setVertical(SketchLine_14.result())
+SketchConstraintLength_3 = Sketch_3.setLength(SketchLine_13.result(), "length_assemblage")
+SketchConstraintLength_3.setName("SketchConstraintLength_1")
+SketchConstraintEqual_5 = Sketch_3.setEqual(SketchLine_13.result(), SketchLine_14.result())
+SketchConstraintEqual_5.setName("SketchConstraintEqual_1")
+model.do()
+Face_5 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_3/Wire-SketchLine_11r-SketchLine_12r-SketchLine_13r-SketchLine_14r")])
+MultiTranslation_1 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Face_5_1")], model.selection("EDGE", "Sketch_1/Edge-SketchLine_9"), "length_assemblage", 4, model.selection("EDGE", "PartSet/OY"), "length_assemblage", 2)
+Recover_1 = model.addRecover(Part_1_doc, MultiTranslation_1, [Face_5.result()])
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("FACE", "Recover_1_1")], model.selection("VERTEX", "Sketch_3/Vertex-SketchPoint_1-SketchLine_12s-SketchLine_11e"), model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_6s-SketchLine_5e"))
+MultiTranslation_2 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Translation_1_1")], model.selection("EDGE", "PartSet/OX"), "length_assemblage", 4, model.selection("EDGE", "PartSet/OY"), "length_assemblage", 2)
+Recover_2 = model.addRecover(Part_1_doc, MultiTranslation_1, [Face_5.result()])
+Translation_2 = model.addTranslation(Part_1_doc, [model.selection("FACE", "Recover_2_1")], model.selection("VERTEX", "Sketch_3/Vertex-SketchPoint_1-SketchLine_12s-SketchLine_11e"), model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_4s-SketchLine_3e"))
+MultiTranslation_3 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Translation_2_1")], model.selection("EDGE", "PartSet/OX"), "length_assemblage", 4)
+Recover_3 = model.addRecover(Part_1_doc, MultiTranslation_1, [Face_5.result()])
+Translation_3 = model.addTranslation(Part_1_doc, [model.selection("FACE", "Recover_3_1")], model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_9s-SketchLine_7e"), model.selection("VERTEX", "MultiTranslation_3_1/Translated_Edge_1_4&MultiTranslation_3_1/Translated_Edge_1_1"))
+MultiTranslation_4 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Translation_3_1")], model.selection("EDGE", "PartSet/OX"), "length_assemblage", 3)
+Recover_4 = model.addRecover(Part_1_doc, MultiTranslation_1, [Face_5.result()])
+Translation_4 = model.addTranslation(Part_1_doc, [model.selection("FACE", "Recover_4_1")], model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_9s-SketchLine_7e"), model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_1s-SketchLine_10s"))
+MultiTranslation_5 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Translation_4_1")], model.selection("EDGE", "PartSet/OX"), "length_assemblage", 2)
+Partition_2 = model.addPartition(Part_1_doc, [model.selection("COMPOUND", "Partition_1_1"), model.selection("COMPOUND", "MultiTranslation_1_1"), model.selection("COMPOUND", "MultiTranslation_2_1"), model.selection("COMPOUND", "MultiTranslation_3_1"), model.selection("COMPOUND", "MultiTranslation_4_1"), model.selection("COMPOUND", "MultiTranslation_5_1")])
+model.end()
+
+# check that partition constructed correctly
+from ModelAPI import *
+aFactory = ModelAPI_Session.get().validators()
+assert(aFactory.validate(Partition_2.feature()))
+assert(Partition_2.feature().results().size() == 1)
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/Test2246.py b/src/FeaturesPlugin/Test/Test2246.py
new file mode 100644 (file)
index 0000000..c178e45
--- /dev/null
@@ -0,0 +1,55 @@
+## 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>
+##
+
+# check that revolution that produces a sphere has correctly named 2 vertices with different names
+
+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("YOZ"))
+SketchPoint_1 = Sketch_1.addPoint(model.selection("VERTEX", "PartSet/Origin"))
+SketchLine_1 = Sketch_1.addLine(model.selection("EDGE", "PartSet/OZ"))
+SketchArc_1 = Sketch_1.addArc(0, 0, 0, 62, 0, -62, False)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchArc_1.center())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.result(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.result())
+SketchLine_2 = Sketch_1.addLine(0, -62, 0, 62)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_2.endPoint())
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchArc_1_2f-SketchLine_2f")], model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), 360, 0)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Revolution_1_1")], model.selection("EDGE", "PartSet/OY"), 150)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "Translation_1_1/Translated_Vertex_1"), model.selection("VERTEX", "Translation_1_1/Translated_Vertex_2")])
+model.end()
+
+# check that resulting group selection is valid, names exist and different
+from ModelAPI import *
+aFactory = ModelAPI_Session.get().validators()
+assert(aFactory.validate(Group_1.feature()))
+assert(Group_1.groupList().size() == 2)
+assert(Group_1.groupList().value(0).value().shapeTypeStr() == "VERTEX")
+assert(len(Group_1.groupList().value(0).namingName()) > 0)
+assert(Group_1.groupList().value(1).value().shapeTypeStr() == "VERTEX")
+assert(Group_1.groupList().value(0).namingName() != Group_1.groupList().value(1).namingName())
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/Test2248.py b/src/FeaturesPlugin/Test/Test2248.py
new file mode 100644 (file)
index 0000000..89f15dd
--- /dev/null
@@ -0,0 +1,63 @@
+## 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>
+##
+
+# check that extrusion of sketch with intersected edges produces well-named edges
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(394.1014919414247, 282.461820162796, -355.0948596332293, 282.461820162796)
+SketchLine_2 = Sketch_1.addLine(-355.0948596332293, 282.461820162796, -355.0948596332293, -224.6243998437472)
+SketchLine_3 = Sketch_1.addLine(-355.0948596332293, -224.6243998437472, 394.1014919414247, -224.6243998437472)
+SketchLine_4 = Sketch_1.addLine(394.1014919414247, -224.6243998437472, 394.1014919414247, 282.461820162796)
+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())
+SketchArc_1 = Sketch_1.addArc(-7.174842024158346, 282.461820162796, -355.0948596332293, 282.461820162796, 143.9210226543769, -30.9362945892586, False)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_2.startPoint(), SketchArc_1.startPoint())
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchLine_2.result(), SketchArc_1.results()[1])
+SketchArc_2 = Sketch_1.addArc(394.1014919414247, 441.436567364073, 394.1014919414247, -224.6243998437472, -125.0902346435239, 24.21101315681109, True)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchArc_2.startPoint())
+SketchConstraintTangent_2 = Sketch_1.setTangent(SketchLine_3.result(), SketchArc_2.results()[1])
+SketchCircle_1 = Sketch_1.addCircle(-13.45056286489504, 169.4770920976776, 150.6703210346195)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), 10, 0)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/To_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/From_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/To_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/From_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_10&Extrusion_1_1/To_Face_3"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_10&Extrusion_1_1/From_Face_3"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/To_Face_3"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/From_Face_3"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_10"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_9&Extrusion_1_1/Generated_Face_10"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_9&Extrusion_1_1/To_Face_3"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_9&Extrusion_1_1/From_Face_3"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_9"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/To_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/From_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/From_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/To_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_5"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/Generated_Face_6"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_6&Extrusion_1_1/From_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_6&Extrusion_1_1/To_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&Extrusion_1_1/From_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_6&Extrusion_1_1/Generated_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_11&Extrusion_1_1/Generated_Face_5"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_11&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_11&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_11&Extrusion_1_1/Generated_Face_10"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_6&Extrusion_1_1/Generated_Face_5"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_10&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_10&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_6&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_6&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_7&Extrusion_1_1/Generated_Face_6"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_7&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_7&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_10&Extrusion_1_1/Generated_Face_9"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_9&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_9&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_9&Extrusion_1_1/Generated_Face_8"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_8&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_8&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_8&Extrusion_1_1/Generated_Face_7")])
+model.end()
+
+# check that resulting group selection is valid
+from ModelAPI import *
+aFactory = ModelAPI_Session.get().validators()
+assert(aFactory.validate(Group_1.feature()))
+assert(Group_1.groupList().size() == 46)
+for a in range(46):
+  assert(Group_1.groupList().value(a).value().shapeTypeStr() == "EDGE")
+  assert(len(Group_1.groupList().value(a).namingName()) > 0)
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/Test2251.py b/src/FeaturesPlugin/Test/Test2251.py
new file mode 100644 (file)
index 0000000..c269496
--- /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>
+##
+
+# check that extrusion of sketch with intersected edges produces well-named faces
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(500.0000311770457, 317.8294573643411, -308.1395348837211, 317.8294573643411)
+SketchLine_2 = Sketch_1.addLine(-308.1395348837211, 317.8294573643411, -308.1395348837211, -263.9724263224183)
+SketchLine_3 = Sketch_1.addLine(-308.1395348837211, -263.9724263224183, 500.0000311770457, -263.9724263224183)
+SketchLine_4 = Sketch_1.addLine(500.0000311770457, -263.9724263224183, 500.0000311770457, 317.8294573643411)
+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())
+SketchCircle_1 = Sketch_1.addCircle(-118.2170542635659, 222.8682170542636, 141.685090902591)
+SketchCircle_2 = Sketch_1.addCircle(294.5736434108529, -40.69767441860468, 113.2187726277406)
+SketchArc_1 = Sketch_1.addArc(500.0000311770867, -335287.7996679137, 500.0000311770457, -263.9724263224183, -639.534183538502, -265.9104108427558, True)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchArc_1.startPoint())
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchLine_3.result(), SketchArc_1.results()[1])
+SketchArc_2 = Sketch_1.addArc(-638.1195022375863, -681.8252609710054, -639.534183538502, -265.9104108427558, -316.014851248167, -418.6983758160058, True)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchArc_2.startPoint())
+SketchConstraintTangent_2 = Sketch_1.setTangent(SketchArc_1.results()[1], SketchArc_2.results()[1])
+SketchArc_3 = Sketch_1.addArc(-167.5780303038277, -297.4405230733651, -316.014851248167, -418.6983758160058, -17.4411870157839, -178.2940378070349, False)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchArc_2.endPoint(), SketchArc_3.startPoint())
+SketchConstraintTangent_3 = Sketch_1.setTangent(SketchArc_2.results()[1], SketchArc_3.results()[1])
+SketchArc_4 = Sketch_1.addArc(-301.8048538198685, -403.9610406236078, -17.4411870157839, -178.2940378070349, -637.5573748460384, -265.908384788777, False)
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchArc_3.endPoint(), SketchArc_4.startPoint())
+SketchConstraintTangent_4 = Sketch_1.setTangent(SketchArc_3.results()[1], SketchArc_4.results()[1])
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchArc_2.results()[1], SketchArc_4.endPoint())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), 100, 0)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Extrusion_1_1/Generated_Face_19"), model.selection("FACE", "Extrusion_1_1/Generated_Face_18"), model.selection("FACE", "Extrusion_1_1/Generated_Face_16"), model.selection("FACE", "Extrusion_1_1/Generated_Face_15"), model.selection("FACE", "Extrusion_1_1/Generated_Face_15"), model.selection("FACE", "Extrusion_1_1/Generated_Face_5"), model.selection("FACE", "Extrusion_1_1/Generated_Face_4"), model.selection("FACE", "Extrusion_1_1/From_Face_3"), model.selection("FACE", "Extrusion_1_1/Generated_Face_3"), model.selection("FACE", "Extrusion_1_1/To_Face_3"), model.selection("FACE", "Extrusion_1_1/Generated_Face_19"), model.selection("FACE", "Extrusion_1_1/Generated_Face_4"), model.selection("FACE", "Extrusion_1_1/From_Face_4"), model.selection("FACE", "Extrusion_1_1/To_Face_4"), model.selection("FACE", "Extrusion_1_1/Generated_Face_8"), model.selection("FACE", "Extrusion_1_1/Generated_Face_3"), model.selection("FACE", "Extrusion_1_1/Generated_Face_9"), model.selection("FACE", "Extrusion_1_1/From_Face_6"), model.selection("FACE", "Extrusion_1_1/Generated_Face_13"), model.selection("FACE", "Extrusion_1_1/To_Face_6"), model.selection("FACE", "Extrusion_1_1/Generated_Face_1"), model.selection("FACE", "Extrusion_1_1/Generated_Face_12"), model.selection("FACE", "Extrusion_1_1/To_Face_5"), model.selection("FACE", "Extrusion_1_1/Generated_Face_2"), model.selection("FACE", "Extrusion_1_1/From_Face_5"), model.selection("FACE", "Extrusion_1_1/Generated_Face_1"), model.selection("FACE", "Extrusion_1_1/Generated_Face_8"), model.selection("FACE", "Extrusion_1_1/Generated_Face_9"), model.selection("FACE", "Extrusion_1_1/Generated_Face_13"), model.selection("FACE", "Extrusion_1_1/Generated_Face_7"), model.selection("FACE", "Extrusion_1_1/Generated_Face_14"), model.selection("FACE", "Extrusion_1_1/Generated_Face_12"), model.selection("FACE", "Extrusion_1_1/Generated_Face_18"), model.selection("FACE", "Extrusion_1_1/From_Face_2"), model.selection("FACE", "Extrusion_1_1/Generated_Face_11"), model.selection("FACE", "Extrusion_1_1/Generated_Face_6"), model.selection("FACE", "Extrusion_1_1/To_Face_2"), model.selection("FACE", "Extrusion_1_1/Generated_Face_10"), model.selection("FACE", "Extrusion_1_1/Generated_Face_6"), model.selection("FACE", "Extrusion_1_1/To_Face_7"), model.selection("FACE", "Extrusion_1_1/From_Face_7"), model.selection("FACE", "Extrusion_1_1/Generated_Face_17"), model.selection("FACE", "Extrusion_1_1/From_Face_1"), model.selection("FACE", "Extrusion_1_1/To_Face_1")])
+model.end()
+
+# check that resulting group selection is valid
+from ModelAPI import *
+aFactory = ModelAPI_Session.get().validators()
+assert(aFactory.validate(Group_1.feature()))
+assert(Group_1.groupList().size() == 44)
+for a in range(44):
+  assert(Group_1.groupList().value(a).value().shapeTypeStr() == "FACE")
+  assert(len(Group_1.groupList().value(a).namingName()) > 0)
+
+assert(model.checkPythonDump())
index 4963d4252afc81e539a0d557d4aed88784dbc9bf..05dec480ee480c649e3f2e28b7d05fcec1cd080a 100755 (executable)
@@ -28,5 +28,5 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
     clear_in_neutral_point="false">
     <validator id="FeaturesPlugin_ValidatorPartitionSelection" parameters="Plane"/>
   </multi_selector>
-  <validator id="GeomValidators_MinObjectsSelected" parameters="base_objects,2"/>
+  <validator id="GeomValidators_MinObjectsSelected" parameters="base_objects,1"/>
 </source>
index 37862ec309ced4a18bf32af4bea3fad5be49e409..5e72160c5af8b0ce65abf43ac988ae4c9c455325 100644 (file)
@@ -286,3 +286,25 @@ double GeomAPI_Edge::length() const
   Adaptor3d_Curve* anAdaptor3d = &aBRepAdaptor;
   return GCPnts_AbscissaPoint::Length(*anAdaptor3d);
 }
+
+bool GeomAPI_Edge::isClosed() const
+{
+  const TopoDS_Shape& aShape = const_cast<GeomAPI_Edge*>(this)->impl<TopoDS_Shape>();
+  if (aShape.IsNull())
+    return false;
+  double aFirst, aLast;
+  Handle(Geom_Curve) aCurve = BRep_Tool::Curve((const TopoDS_Edge&)aShape, aFirst, aLast);
+  if (aCurve.IsNull() || !aCurve->IsPeriodic())
+    return false;
+  aLast += aLast > aFirst ? -aCurve->Period() : aCurve->Period();;
+
+  return fabs(aFirst - aLast) < 1.e-9;
+}
+
+bool GeomAPI_Edge::isDegenerated() const
+{
+  const TopoDS_Shape& aShape = const_cast<GeomAPI_Edge*>(this)->impl<TopoDS_Shape>();
+  if (aShape.IsNull() || aShape.ShapeType() != TopAbs_EDGE)
+    return false;
+  return BRep_Tool::Degenerated(TopoDS::Edge(aShape));
+}
index 59b36c04207fe3d9b0685942fb42aac4b0a0989f..ce0f7b559d18e0f1b9d830af6e6d3d5d94879970 100644 (file)
@@ -96,6 +96,14 @@ public:
   /// Returns edge length.
   GEOMAPI_EXPORT
   double length() const;
+
+  /// Returns true if the edge is closed (like full circle)
+  GEOMAPI_EXPORT
+  bool isClosed() const;
+
+  /// Returns true if the edge is degenerated (has no 3D curve)
+  GEOMAPI_EXPORT
+  bool isDegenerated() const;
 };
 
 //! Pointer on attribute object
index 2e9c9c18ea45bb286d617a6fe91391e09babce54..d6ba70d19919110cfe07087731d15cd75995457f 100644 (file)
 //
 
 #include <GeomAlgoAPI_EdgeBuilder.h>
-
-#include <Bnd_Box.hxx>
-#include <BRep_Tool.hxx>
-#include <BRepBndLib.hxx>
+#include <gp_Pln.hxx>
 #include <BRepBuilderAPI_MakeEdge.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS.hxx>
+#include <BRep_Tool.hxx>
+#include <Geom_Plane.hxx>
+#include <Geom_CylindricalSurface.hxx>
+#include <Geom_RectangularTrimmedSurface.hxx>
+
 #include <gp_Ax2.hxx>
 #include <gp_Circ.hxx>
 #include <gp_Elips.hxx>
-#include <gp_Pln.hxx>
-#include <Geom_CylindricalSurface.hxx>
-#include <Geom_Plane.hxx>
-#include <Geom_RectangularTrimmedSurface.hxx>
-#include <TopoDS.hxx>
-#include <TopoDS_Edge.hxx>
-#include <TopoDS_Face.hxx>
+#include <Bnd_Box.hxx>
+#include <BRepBndLib.hxx>
 
 std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_EdgeBuilder::line(
     std::shared_ptr<GeomAPI_Pnt> theStart, std::shared_ptr<GeomAPI_Pnt> theEnd)
@@ -199,7 +199,7 @@ std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_EdgeBuilder::lineCircleArc(
 
   /// OCCT creates an edge on a circle with empty radius, but visualization
   /// is not able to process it
-  if (theCenter->isEqual(theStartPoint))
+  if (theCenter->isEqual(theStartPoint) || theCenter->isEqual(theEndPoint))
     return aRes;
 
   double aRadius = theCenter->distance(theStartPoint);
index fa5f9f098ae634b8e63e6d0a060a5b131b33d948..7cf3b3fb44c74768de6adb32fa4162565cc9fe33 100644 (file)
@@ -123,9 +123,9 @@ void GeomAlgoAPI_MakeShapeList::result(const std::shared_ptr<GeomAPI_Shape> theS
       aBuilderIt != myListOfMakeShape.end(); aBuilderIt++) {
     std::shared_ptr<GeomAlgoAPI_MakeShape> aMakeShape = *aBuilderIt;
     NCollection_Map<TopoDS_Shape> aTempShapes;
-    bool hasResults = false;
     for(NCollection_Map<TopoDS_Shape>::Iterator
         aShapeIt(anAlgoShapes); aShapeIt.More(); aShapeIt.Next()) {
+      bool hasResults = false;
       std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape);
       aShape->setImpl(new TopoDS_Shape(aShapeIt.Value()));
       ListOfShape aGeneratedShapes;
index 409988692ed200944bff497b5b447887760b8911..cd880734a65e4c56d03250784d6417e39b525aa8 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <TopExp_Explorer.hxx>
 #include <TopoDS_Builder.hxx>
+#include <TopTools_MapOfShape.hxx>
 
 //=================================================================================================
 std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_Partition::make(const ListOfShape& theObjects,
@@ -46,6 +47,21 @@ GeomAlgoAPI_Partition::GeomAlgoAPI_Partition(const ListOfShape& theObjects,
   build(theObjects, theTools);
 }
 
+static void prepareShapes(const TopoDS_Shape&   theShape,
+                           TopTools_ListOfShape& theSimpleList)
+{
+  if (theShape.ShapeType() != TopAbs_COMPOUND) {
+      theSimpleList.Append(theShape);
+    return;
+  }
+
+  // explode compound on simple shapes to allow their intersections
+  TopoDS_Iterator It (theShape, Standard_True, Standard_True);
+  for (; It.More(); It.Next()) {
+    TopoDS_Shape curSh = It.Value();
+    prepareShapes(curSh, theSimpleList);
+  }
+}
 
 //=================================================================================================
 void GeomAlgoAPI_Partition::build(const ListOfShape& theObjects,
@@ -60,11 +76,21 @@ void GeomAlgoAPI_Partition::build(const ListOfShape& theObjects,
   this->setImpl(anOperation);
   this->setBuilderType(OCCT_BOPAlgo_Builder);
 
+  TopTools_MapOfShape ShapesMap;
   // Getting objects.
-  for (ListOfShape::const_iterator
+  for(ListOfShape::const_iterator
        anObjectsIt = theObjects.begin(); anObjectsIt != theObjects.end(); anObjectsIt++) {
     const TopoDS_Shape& aShape = (*anObjectsIt)->impl<TopoDS_Shape>();
-    anOperation->AddArgument(aShape);
+    // #2240: decompose compounds to get the valid result
+    TopTools_ListOfShape aSimpleShapes;
+    prepareShapes(aShape, aSimpleShapes);
+    TopTools_ListIteratorOfListOfShape aSimpleIter(aSimpleShapes);
+    for (; aSimpleIter.More(); aSimpleIter.Next()) {
+      const TopoDS_Shape& aSimpleSh = aSimpleIter.Value();
+      if (ShapesMap.Add(aSimpleSh)) {
+        anOperation->AddArgument(aSimpleSh);
+      }
+    }
   }
 
   // Getting tools.
index fb5f6e8b8016dbb7f76821cce0e8d193b9f9d7df..236f8e944d0efdc87925cc54a9a697170d8d55bb 100644 (file)
@@ -214,49 +214,66 @@ void GeomAlgoAPI_Pipe::build(const ListOfShape& theBaseShapes,
   }
 
   // Making pipe.
-  BRepOffsetAPI_MakePipeShell* aPipeBuilder = new BRepOffsetAPI_MakePipeShell(aPathWire);
-  if(!aPipeBuilder) {
-    return;
-  }
+  Standard_Boolean isDone = Standard_False;
   bool anIsSolidNeeded = false;
-  ListOfShape::const_iterator aBaseIt = theBaseShapes.cbegin();
-  ListOfShape::const_iterator aLocIt = theLocations.cbegin();
-  while(aBaseIt != theBaseShapes.cend()) {
-    GeomShapePtr aBase = *aBaseIt;
-    TopoDS_Shape aBaseShape;
-    TopAbs_ShapeEnum aBaseShapeType;
-    if(!getBase(aBaseShape, aBaseShapeType, aBase)) {
-      delete aPipeBuilder;
+  BRepOffsetAPI_MakePipeShell* aPipeBuilder;
+  for(int i = 0; i < 2; ++i) {
+    aPipeBuilder = new BRepOffsetAPI_MakePipeShell(aPathWire);
+    if(!aPipeBuilder) {
       return;
     }
-    ++aBaseIt;
-    if(aBaseShapeType == TopAbs_FACE) {
-      anIsSolidNeeded = true;
-    }
-
-    if(aHasLocations) {
-      GeomShapePtr aLocation = *aLocIt;
-      if(!aLocation.get() || aLocation->shapeType() != GeomAPI_Shape::VERTEX) {
+    ListOfShape::const_iterator aBaseIt = theBaseShapes.cbegin();
+    ListOfShape::const_iterator aLocIt = theLocations.cbegin();
+    while(aBaseIt != theBaseShapes.cend()) {
+      GeomShapePtr aBase = *aBaseIt;
+      TopoDS_Shape aBaseShape;
+      TopAbs_ShapeEnum aBaseShapeType;
+      if(!getBase(aBaseShape, aBaseShapeType, aBase)) {
         delete aPipeBuilder;
         return;
       }
-      TopoDS_Vertex aLocationVertex = aLocation->impl<TopoDS_Vertex>();
-      ++aLocIt;
-      aPipeBuilder->Add(aBaseShape, aLocationVertex);
-    } else {
-      aPipeBuilder->Add(aBaseShape);
+      ++aBaseIt;
+      if(aBaseShapeType == TopAbs_FACE) {
+        anIsSolidNeeded = true;
+      }
+
+      if(aHasLocations) {
+        GeomShapePtr aLocation = *aLocIt;
+        if(!aLocation.get() || aLocation->shapeType() != GeomAPI_Shape::VERTEX) {
+          delete aPipeBuilder;
+          return;
+        }
+        TopoDS_Vertex aLocationVertex = aLocation->impl<TopoDS_Vertex>();
+        ++aLocIt;
+        aPipeBuilder->Add(aBaseShape, aLocationVertex);
+      } else {
+        aPipeBuilder->Add(aBaseShape);
+      }
+    }
+
+    if(aPipeBuilder->IsReady() == Standard_False) {
+      delete aPipeBuilder;
+      return;
+    }
+
+    if (i == 1) {
+       // Try to use Descrete Trihedron mode.
+      aPipeBuilder->SetDiscreteMode();
+    }
+    aPipeBuilder->Build();
+    isDone = aPipeBuilder->IsDone();
+
+    if (isDone) {
+      break;
     }
-  }
 
-  if(aPipeBuilder->IsReady() == Standard_False) {
     delete aPipeBuilder;
-    return;
   }
 
-  if(!buildPipe(aPipeBuilder)) {
-    delete aPipeBuilder;
+  if (!isDone) {
     return;
   }
+
   this->initialize(aPipeBuilder);
 
   // Checking result.
index cdf421e6f89f5caf3896813c560b13bdc21fac05..7fcdc7a0e9ecbddcc8eae633ddc8f3498cecf3f7 100644 (file)
@@ -321,49 +321,85 @@ std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::groupSharedTopology(
   NCollection_List<TopoDS_Shape> anUngroupedShapes, aStillUngroupedShapes;
   addSimpleShapeToList(anInShape, anUngroupedShapes);
 
-  NCollection_Vector<NCollection_List<TopoDS_Shape>> aGroups;
-  while(!anUngroupedShapes.IsEmpty()) {
-    NCollection_List<TopoDS_Shape> aGroupedShapes;
-    aGroupedShapes.Append(anUngroupedShapes.First());
-    anUngroupedShapes.RemoveFirst();
-    for(NCollection_List<TopoDS_Shape>::Iterator aGroupIt(aGroupedShapes);
+  // Iterate over all shapes and find shapes with shared vertices.
+  TopTools_ListOfShape aMapOrder;
+  BOPCol_DataMapOfShapeListOfShape aVertexShapesMap;
+  for(NCollection_List<TopoDS_Shape>::Iterator aShapesIt(anUngroupedShapes);
+      aShapesIt.More();
+      aShapesIt.Next()) {
+    const TopoDS_Shape& aShape = aShapesIt.Value();
+    for(TopExp_Explorer aShapeExp(aShape, TopAbs_VERTEX);
+        aShapeExp.More();
+        aShapeExp.Next()) {
+      const TopoDS_Shape& aVertex = aShapeExp.Current();
+      if (!aVertexShapesMap.IsBound(aVertex)) {
+        NCollection_List<TopoDS_Shape> aList;
+        aList.Append(aShape);
+        aMapOrder.Append(aVertex);
+        aVertexShapesMap.Bind(aVertex, aList);
+      } else {
+        if(!aVertexShapesMap.ChangeFind(aVertex).Contains(aShape)) {
+          aVertexShapesMap.ChangeFind(aVertex).Append(aShape);
+        }
+      }
+    }
+  }
+
+  // Iterate over the map and group shapes.
+  NCollection_Vector<TopTools_ListOfShape> aGroups;
+  while (!aMapOrder.IsEmpty()) {
+    // Get first group of shapes in map, and then unbind it.
+    const TopoDS_Shape& aKey = aMapOrder.First();
+    TopTools_ListOfShape aGroupedShapes = aVertexShapesMap.Find(aKey);
+    aVertexShapesMap.UnBind(aKey);
+    aMapOrder.Remove(aKey);
+    // Iterate over shapes in this group and add to it shapes from groups in map.
+    for(TopTools_ListOfShape::Iterator aGroupIt(aGroupedShapes);
         aGroupIt.More(); aGroupIt.Next()) {
       const TopoDS_Shape& aGroupedShape = aGroupIt.Value();
-      for(TopExp_Explorer aGroupShapeExp(aGroupedShape, TopAbs_VERTEX);
-          aGroupShapeExp.More();
-          aGroupShapeExp.Next()) {
-        // Find all shapes which have same vertex.
-        aStillUngroupedShapes.Clear();
-        const TopoDS_Shape& aVertex1 = aGroupShapeExp.Current();
-        for(NCollection_List<TopoDS_Shape>::Iterator anUngroupedIt(anUngroupedShapes);
-            anUngroupedIt.More();
-            anUngroupedIt.Next()) {
-          const TopoDS_Shape& anUngroupedShape = anUngroupedIt.Value();
-          bool isAdded = false;
-          for(TopExp_Explorer anUgroupedShapeExp(anUngroupedShape, TopAbs_VERTEX);
-              anUgroupedShapeExp.More();
-              anUgroupedShapeExp.Next()) {
-            const TopoDS_Shape& aVertex2 = anUgroupedShapeExp.Current();
-            if(aVertex1.IsSame(aVertex2)) {
-              aGroupedShapes.Append(anUngroupedShape);
-              isAdded = true;
-              break;
-            }
-          }
-          if(!isAdded) {
-            aStillUngroupedShapes.Append(anUngroupedShape);
-          }
+      TopTools_ListOfShape aKeysToUnbind;
+      for(TopTools_ListOfShape::Iterator aKeysIt(aMapOrder);
+          aKeysIt.More();
+          aKeysIt.Next()) {
+        const TopTools_ListOfShape& aGroupInMap = aVertexShapesMap(aKeysIt.Value());
+        if(!aGroupInMap.Contains(aGroupedShape)) {
+          // Group in map does not containt shape from our group, so go to the next group in map.
+          continue;
         }
-        anUngroupedShapes = aStillUngroupedShapes;
-        if(anUngroupedShapes.IsEmpty()) {
-          break;
+        // Iterate over shape in group in map, and add new shapes into our group.
+        for(TopTools_ListOfShape::Iterator aGroupInMapIt(aGroupInMap);
+            aGroupInMapIt.More();
+            aGroupInMapIt.Next()) {
+          const TopoDS_Shape& aShape = aGroupInMapIt.Value();
+          if (!aGroupedShapes.Contains(aShape)) {
+            aGroupedShapes.Append(aShape);
+          }
         }
+        // Save key to unbind from this map.
+        aKeysToUnbind.Append(aKeysIt.Value());
       }
-      if(anUngroupedShapes.IsEmpty()) {
-        break;
+      // Unbind groups from map that we added to our group.
+      for(TopTools_ListOfShape::Iterator aKeysIt(aKeysToUnbind);
+          aKeysIt.More();
+          aKeysIt.Next()) {
+        aVertexShapesMap.UnBind(aKeysIt.Value());
+        aMapOrder.Remove(aKeysIt.Value());
+      }
+    }
+    // Sort shapes.
+    TopTools_ListOfShape aSortedGroup;
+    for(int aST = TopAbs_COMPOUND; aST <= TopAbs_SHAPE; ++aST) {
+      TopTools_ListOfShape::Iterator anIt(aGroupedShapes);
+      while (anIt.More()) {
+        if(anIt.Value().ShapeType() == aST) {
+          aSortedGroup.Append(anIt.Value());
+          aGroupedShapes.Remove(anIt);
+        } else {
+          anIt.Next();
+        }
       }
     }
-    aGroups.Append(aGroupedShapes);
+    aGroups.Append(aSortedGroup);
   }
 
   TopoDS_Compound aCompound;
index eca84e8a22695d6f98df02f0bc6cccee9b7a0c4c..c4bf9d6f38d37039a245433249aeb4b5a9997624 100644 (file)
 #include <TopoDS.hxx>
 #include <TopoDS_Edge.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <GProp_GProps.hxx>
+#include <BRepGProp.hxx>
 
 #include <list>
 #include <cmath>
-
+#include <algorithm>
 
 static TopoDS_Vertex findStartVertex(const TopoDS_Shape& theShape)
 {
@@ -100,6 +102,92 @@ static TopoDS_Vertex findStartVertex(const TopoDS_Shape& theShape,
   return findStartVertex(theShape);
 }
 
+// returns true if the first shape must be located earlier than the second
+bool isFirst(const TopoDS_Shape& theFirst, const TopoDS_Shape& theSecond,
+  NCollection_DataMap<TopoDS_Shape, NCollection_Array1<int> >& theAreaToIndex,
+  const NCollection_DataMap<Handle(Geom_Curve), int>& theCurveToIndex)
+{
+  // fill theAreaToIndex for both shapes if needed
+  for(int aShapeNum = 1; aShapeNum <= 2; aShapeNum++) {
+    TopoDS_Shape aShape = aShapeNum == 1 ? theFirst : theSecond;
+    if (!theAreaToIndex.IsBound(aShape)) { // fill the list of curve indices
+      NCollection_List<int> aNewList;
+      TopExp_Explorer anEdgesExp(aShape, TopAbs_EDGE);
+      for(; anEdgesExp.More(); anEdgesExp.Next()) {
+        double aFirst, aLast;
+        Handle(Geom_Curve) aCurve = BRep_Tool::Curve(
+          TopoDS::Edge(anEdgesExp.Current()), aFirst, aLast);
+        if (aCurve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
+          aCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve)->BasisCurve();
+        if (theCurveToIndex.IsBound(aCurve)) {
+          aNewList.Append(theCurveToIndex.Find(aCurve));
+        }
+      }
+      NCollection_Array1<int> aNewArray(1, aNewList.Extent());
+      NCollection_List<int>::Iterator aListIter(aNewList);
+      for(int anIndex = 1; aListIter.More(); aListIter.Next(), anIndex++) {
+        aNewArray.SetValue(anIndex, aListIter.Value());
+      }
+      std::sort(aNewArray.begin(), aNewArray.end());
+      theAreaToIndex.Bind(aShape, aNewArray);
+    }
+  }
+  // compare lists of indices one by one to find chich list indices are lower
+  NCollection_Array1<int>::Iterator aFirstList(theAreaToIndex.ChangeFind(theFirst));
+  NCollection_Array1<int>::Iterator aSecondList(theAreaToIndex.ChangeFind(theSecond));
+  for(; aFirstList.More() && aSecondList.More(); aFirstList.Next(), aSecondList.Next()) {
+    if (aFirstList.Value() < aSecondList.Value()) return true;
+    if (aFirstList.Value() > aSecondList.Value()) return false;
+  }
+  // if faces are identical by curves names (circle splitted by line in seam-point), use parameters
+  if (!aFirstList.More() && !aSecondList.More()) {
+    GProp_GProps aGProps;
+    BRepGProp::SurfaceProperties(theFirst, aGProps);
+    gp_Pnt aCentre1 = aGProps.CentreOfMass();
+    BRepGProp::SurfaceProperties(theSecond, aGProps);
+    gp_Pnt aCentre2 = aGProps.CentreOfMass();
+    return aCentre1.X() + aCentre1.Y() + aCentre1.Z() < aCentre2.X() + aCentre2.Y() + aCentre2.Z();
+  }
+  // if in first list there is no elements left, it is the first
+  return !aFirstList.More();
+}
+
+// sorts faces (in theAreas list) to make persistent order: by initial shapes edges
+static void sortFaces(TopTools_ListOfShape& theAreas,
+  const std::list<std::shared_ptr<GeomAPI_Shape> >& theInitialShapes)
+{
+  // collect indices of all edges to operate them quickly
+  NCollection_DataMap<Handle(Geom_Curve), int> aCurveToIndex; // curve -> index in initial shapes
+  std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator aFeatIt = theInitialShapes.begin();
+  for (int anIndex = 0; aFeatIt != theInitialShapes.end(); aFeatIt++) {
+    std::shared_ptr<GeomAPI_Shape> aShape(*aFeatIt);
+    const TopoDS_Edge& anEdge = aShape->impl<TopoDS_Edge>();
+    if (anEdge.ShapeType() != TopAbs_EDGE)
+      continue;
+
+    double aFirst, aLast;
+    Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
+    if (aCurve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
+      aCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve)->BasisCurve();
+    if (!aCurveToIndex.IsBound(aCurve))
+      aCurveToIndex.Bind(aCurve, anIndex++);
+  }
+  // map from area to the most first indices of curves (to compare) in it
+  NCollection_DataMap<TopoDS_Shape, NCollection_Array1<int> > anAreaToIndex;
+  // sort areas
+  TopTools_ListOfShape::Iterator anArea1(theAreas);
+  for(; anArea1.More(); anArea1.Next()) {
+    TopTools_ListOfShape::Iterator anArea2 = anArea1;
+    for(anArea2.Next(); anArea2.More(); anArea2.Next()) {
+      if (!isFirst(anArea1.Value(), anArea2.Value(), anAreaToIndex, aCurveToIndex)) { // exchange
+        TopoDS_Shape aTmp = anArea1.Value();
+        anArea1.ChangeValue() = anArea2.Value();
+        anArea2.ChangeValue() = aTmp;
+      }
+    }
+  }
+}
+
 void GeomAlgoAPI_SketchBuilder::createFaces(
     const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
     const std::shared_ptr<GeomAPI_Dir>& theDirX,
@@ -134,7 +222,8 @@ void GeomAlgoAPI_SketchBuilder::createFaces(
     return;
 
   // Collect faces
-  const TopTools_ListOfShape& anAreas = aBB.Modified(aPlnFace);
+  TopTools_ListOfShape anAreas = aBB.Modified(aPlnFace);
+  sortFaces(anAreas, theFeatures); // sort faces by the edges in them
   TopTools_ListIteratorOfListOfShape anIt(anAreas);
   for (; anIt.More(); anIt.Next()) {
     TopoDS_Face aFace = TopoDS::Face(anIt.Value());
index 446470df27ad40ec1f1dce6dea58e1dbb5fac4be..139239be9aaac39a943194ec5d31c6f98d171eec 100644 (file)
@@ -48,7 +48,6 @@ bool GeomValidators_Positive::isValid(const AttributePtr& theAttribute,
   double aMinValue = 1.e-5;
   if(theArguments.size() == 1) {
     std::list<std::string>::const_iterator anIt = theArguments.begin();
-    char *aErr;
     double aValue = Config_PropManager::stringToDouble((*anIt).c_str());
     if(aValue != 0) {
       // very probably ok
index ed730d1c8578812e38c508d1cd45f5bc3522bca5..a5688b66e5e7f1150ec8bec91434ae16c32cc82c 100644 (file)
@@ -136,9 +136,10 @@ void Model_Application::setLoadByDemand(std::string theID, const int theDocID)
 }
 
 //=======================================================================
-bool Model_Application::isLoadByDemand(std::string theID)
+bool Model_Application::isLoadByDemand(std::string theID, const int theDocIndex)
 {
-  return myLoadedByDemand.find(theID) != myLoadedByDemand.end();
+  return myLoadedByDemand.find(theID) != myLoadedByDemand.end() &&
+    myLoadedByDemand[theID] == theDocIndex;
 }
 
 //=======================================================================
index 8f5526c0de45c2fb7c904253dcba98591a746247..6ec3c8df938bf137bf8346f71fdc1d8d770166ec 100644 (file)
@@ -76,7 +76,7 @@ public:
   //! Defines that specified document must be loaded by demand
   void setLoadByDemand(std::string theID, const int theDocID);
   //! Returns true if specified document must be loaded by demand
-  bool isLoadByDemand(std::string theID);
+  bool isLoadByDemand(std::string theID, const int theDocIndex);
   //! Closes and removes the documents that are not loaded by demand and
   //! not in the given list
   void removeUselessDocuments(std::list<std::shared_ptr<ModelAPI_Document> > theUsedDocs);
index 63614449c11b40b2bd277cceb1e42c5908310cbe..344ee30ee36009e59b2dea139d2c2b92d3b907ac 100644 (file)
@@ -49,6 +49,8 @@
 #include <TDataStd_UAttribute.hxx>
 #include <TDataStd_Name.hxx>
 #include <TopTools_ListOfShape.hxx>
+#include <TopTools_DataMapOfShapeShape.hxx>
+#include <TopTools_MapOfShape.hxx>
 #include <TopExp_Explorer.hxx>
 #include <BRep_Tool.hxx>
 #include <TopoDS.hxx>
@@ -56,6 +58,7 @@
 #include <TDF_ChildIterator.hxx>
 #include <TDF_ChildIDIterator.hxx>
 #include <TopoDS_Iterator.hxx>
+#include <TDF_ChildIDIterator.hxx>
 #include <Geom_Circle.hxx>
 #include <Geom_Ellipse.hxx>
 #include <BRep_Builder.hxx>
@@ -274,7 +277,7 @@ std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::internalValue(CenterTyp
     if (aSelLab.IsAttribute(kPART_REF_ID)) {
       ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(context());
       if (!aPart.get() || !aPart->isActivated())
-        return aResult; // postponed naming needed
+        return std::shared_ptr<GeomAPI_Shape>(); // postponed naming needed
       Handle(TDataStd_Integer) anIndex;
       if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) {
         if (anIndex->Get()) { // special selection attribute was created, use it
@@ -287,8 +290,8 @@ std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::internalValue(CenterTyp
             if (aPartEnd != std::string::npos && aPartEnd != aSubShapeName.rfind('/')) {
               std::string aNameInPart = aSubShapeName.substr(aPartEnd + 1);
               int anIndex;
-              std::string aTypeStr; // to reuse already existing selection the type is not needed
-              return aPart->shapeInPart(aNameInPart, aTypeStr, anIndex);
+              std::string aType; // to reuse already existing selection the type is not needed
+              return aPart->shapeInPart(aNameInPart, aType, anIndex);
             }
           }
         }
@@ -300,7 +303,6 @@ std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::internalValue(CenterTyp
       TopoDS_Shape aSelShape = aSelection->Get();
       aResult = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape);
       aResult->setImpl(new TopoDS_Shape(aSelShape));
-      return aResult;
     } else { // for simple construction element: just shape of this construction element
       std::shared_ptr<Model_ResultConstruction> aConstr =
         std::dynamic_pointer_cast<Model_ResultConstruction>(context());
@@ -314,7 +316,7 @@ std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::internalValue(CenterTyp
       }
     }
   }
-  return aResult; // empty case
+  return aResult;
 }
 
 bool Model_AttributeSelection::isInvalid()
@@ -812,7 +814,7 @@ void Model_AttributeSelection::selectSubShape(
           Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(aConShape, selectionLabel());
           if (!aNS.IsNull()) {
             aNS = TNaming_Tool::CurrentNamedShape(aNS);
-            if (!aNS.IsNull()) {
+            if (!aNS.IsNull() && scope().Contains(aNS->Label())) { // scope check is for 2228
               TDF_Label aLab = aNS->Label();
               while(aLab.Depth() != 7 && aLab.Depth() > 5)
                 aLab = aLab.Father();
@@ -929,21 +931,240 @@ std::string Model_AttributeSelection::contextName(const ResultPtr& theContext) c
   return aResult;
 }
 
+void Model_AttributeSelection::computeValues(
+  ResultPtr theOldContext, ResultPtr theNewContext, TopoDS_Shape theValShape,
+  TopTools_ListOfShape& theShapes)
+{
+  bool aWasWholeContext = theValShape.IsNull();
+  if (aWasWholeContext) {
+    //theShapes.Append(theValShape);
+    //return;
+    theValShape = theOldContext->shape()->impl<TopoDS_Shape>();
+  }
+  //TopoDS_Shape anOldContShape = theOldContext->shape()->impl<TopoDS_Shape>();
+  TopoDS_Shape aNewContShape = theNewContext->shape()->impl<TopoDS_Shape>();
+  //if (anOldContShape.IsSame(theValShape)) { // full context shape substituted by new full context
+    //theShapes.Append(aNewContShape);
+    //return;
+  //}
+  // if a new value is unchanged in the new context, do nothing: value is correct
+  TopExp_Explorer aSubExp(aNewContShape, theValShape.ShapeType());
+  for(; aSubExp.More(); aSubExp.Next()) {
+    if (aSubExp.Current().IsSame(theValShape)) {
+      theShapes.Append(theValShape);
+      return;
+    }
+  }
+  // if new context becomes compsolid, the resulting sub may be in sub-solids
+  std::list<ResultPtr> aNewToIterate;
+  aNewToIterate.push_back(theNewContext);
+  ResultCompSolidPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theNewContext);
+  if (aComp.get()) {
+    for(int a = 0; a < aComp->numberOfSubs(); a++)
+      aNewToIterate.push_back(aComp->subResult(a, false));
+  }
+
+  // first iteration: searching for the whole shape appearance (like face of the box)
+  // second iteration: searching for sub-shapes that contain the sub (like vertex on faces)
+  int aToFindPart = 0;
+  TopTools_DataMapOfShapeShape aNewToOld; // map from new containers to old containers (with val)
+  TopTools_MapOfShape anOlds; // to know how many olds produced new containers
+  for(; aToFindPart != 2 && theShapes.IsEmpty(); aToFindPart++) {
+    std::list<ResultPtr>::iterator aNewContIter = aNewToIterate.begin();
+    for(; aNewContIter != aNewToIterate.end(); aNewContIter++) {
+      std::shared_ptr<Model_Data> aNewData =
+        std::dynamic_pointer_cast<Model_Data>((*aNewContIter)->data());
+      TDF_Label aNewLab = aNewData->label();
+      // searching for produced sub-shape fully on some label
+      TDF_ChildIDIterator aNSIter(aNewLab, TNaming_NamedShape::GetID(), Standard_True);
+      for(; aNSIter.More(); aNSIter.Next()) {
+        Handle(TNaming_NamedShape) aNS = Handle(TNaming_NamedShape)::DownCast(aNSIter.Value());
+        for(TNaming_Iterator aPairIter(aNS); aPairIter.More(); aPairIter.Next()) {
+          if (aToFindPart == 0) { // search shape is fully inside
+            if (aPairIter.OldShape().IsSame(theValShape)) {
+              if (aPairIter.NewShape().IsNull()) {// value was removed
+                theShapes.Clear();
+                return;
+              }
+              theShapes.Append(aPairIter.NewShape());
+            }
+          } else if (!aPairIter.OldShape().IsNull()) { // search shape that contains this sub
+            TopExp_Explorer anExp(aPairIter.OldShape(), theValShape.ShapeType());
+            for(; anExp.More(); anExp.Next()) {
+              if (anExp.Current().IsSame(theValShape)) { // found a new container
+                if (aPairIter.NewShape().IsNull()) {// value was removed
+                  theShapes.Clear();
+                  return;
+                }
+                aNewToOld.Bind(aPairIter.NewShape(), aPairIter.OldShape());
+                anOlds.Add(aPairIter.OldShape());
+                break;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  if (aToFindPart == 2 && !aNewToOld.IsEmpty()) {
+    // map of sub-shapes -> number of occurences of these shapes in containers
+    NCollection_DataMap<TopoDS_Shape, TopTools_MapOfShape, TopTools_ShapeMapHasher> aSubs;
+    TopTools_DataMapOfShapeShape::Iterator aContIter(aNewToOld);
+    for(; aContIter.More(); aContIter.Next()) {
+      TopExp_Explorer aSubExp(aContIter.Key(), theValShape.ShapeType());
+      for(; aSubExp.More(); aSubExp.Next()) {
+        if (!aSubs.IsBound(aSubExp.Current())) {
+          aSubs.Bind(aSubExp.Current(), TopTools_MapOfShape());
+        }
+        // store old to know how many olds produced this shape
+        aSubs.ChangeFind(aSubExp.Current()).Add(aContIter.Value());
+      }
+    }
+    // if sub is appeared same times in containers as the number of old shapes that contain it
+    int aCountInOld = anOlds.Size();
+    NCollection_DataMap<TopoDS_Shape, TopTools_MapOfShape, TopTools_ShapeMapHasher>::Iterator
+      aSubsIter(aSubs);
+    for(; aSubsIter.More(); aSubsIter.Next()) {
+      if (aSubsIter.Value().Size() == aCountInOld) {
+        theShapes.Append(aSubsIter.Key());
+      }
+    }
+  }
+  if (theShapes.IsEmpty()) { // nothing was changed
+    theShapes.Append(aWasWholeContext ? TopoDS_Shape() : theValShape);
+  }
+}
+
+bool Model_AttributeSelection::searchNewContext(std::shared_ptr<Model_Document> theDoc,
+  const TopoDS_Shape theContShape, ResultPtr theContext, TopoDS_Shape theValShape,
+  TDF_Label theAccessLabel,
+  std::list<ResultPtr>& theResults, TopTools_ListOfShape& theValShapes)
+{
+  std::set<ResultPtr> aResults; // to avoid duplicates, new context, null if deleted
+  TopTools_ListOfShape aResContShapes;
+  TNaming_SameShapeIterator aModifIter(theContShape, theAccessLabel);
+  for(; aModifIter.More(); aModifIter.Next()) {
+    TDF_Label anObjLab = aModifIter.Label().Father();
+    ResultPtr aModifierObj = std::dynamic_pointer_cast<ModelAPI_Result>
+      (theDoc->objects()->object(anObjLab));
+    if (!aModifierObj.get()) {
+      // #2241: shape may be sub-element of new object, not main (shell created from faces)
+      if (!anObjLab.IsRoot())
+        aModifierObj = std::dynamic_pointer_cast<ModelAPI_Result>
+        (theDoc->objects()->object(anObjLab.Father()));
+      if (!aModifierObj.get())
+        continue;
+    }
+    FeaturePtr aModifierFeat = theDoc->feature(aModifierObj);
+    if (!aModifierFeat.get())
+      continue;
+    FeaturePtr aThisFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
+    if (aModifierFeat == aThisFeature || theDoc->objects()->isLater(aModifierFeat, aThisFeature))
+      continue; // the modifier feature is later than this, so, should not be used
+    FeaturePtr aCurrentModifierFeat = theDoc->feature(theContext);
+    if (aCurrentModifierFeat == aModifierFeat ||
+      theDoc->objects()->isLater(aCurrentModifierFeat, aModifierFeat))
+      continue; // the current modifier is later than the found, so, useless
+    Handle(TNaming_NamedShape) aNewNS;
+    aModifIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNewNS);
+    if (aNewNS->Evolution() == TNaming_MODIFY || aNewNS->Evolution() == TNaming_GENERATED) {
+      aResults.insert(aModifierObj);
+      //TNaming_Iterator aPairIter(aNewNS);
+      //aResContShapes.Append(aPairIter.NewShape());
+      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-precessed modification => don't support it
+      continue;
+    }
+  }
+  if (aResults.empty())
+    return false; // no modifications found, must stay the same
+  // iterate all results to find futher modifications
+  std::set<ResultPtr>::iterator aResIter = aResults.begin();
+  for(; aResIter != aResults.end(); aResIter++) {
+    if (aResIter->get() != NULL) {
+      // compute new values by two contextes: the old and the new
+      TopTools_ListOfShape aValShapes;
+      computeValues(theContext, *aResIter, theValShape, aValShapes);
+
+      TopTools_ListIteratorOfListOfShape aNewVal(aValShapes);
+      for(; aNewVal.More(); aNewVal.Next()) {
+        std::list<ResultPtr> aNewRes;
+        TopTools_ListOfShape aNewUpdatedVal;
+        TopoDS_Shape aNewValSh = aNewVal.Value();
+        TopoDS_Shape aNewContShape = (*aResIter)->shape()->impl<TopoDS_Shape>();
+        if (theValShape.IsNull() && aNewContShape.IsSame(aNewValSh))
+          aNewValSh.Nullify();
+        if (searchNewContext(theDoc, aNewContShape, *aResIter, aNewValSh,
+                             theAccessLabel, aNewRes, aNewUpdatedVal))
+        {
+          // appeand new results instead of the current ones
+          std::list<ResultPtr>::iterator aNewIter = aNewRes.begin();
+          TopTools_ListIteratorOfListOfShape aNewUpdVal(aNewUpdatedVal);
+          for(; aNewIter != aNewRes.end(); aNewIter++, aNewUpdVal.Next()) {
+            theResults.push_back(*aNewIter);
+            theValShapes.Append(aNewUpdVal.Value());
+          }
+        } else { // the current result is good
+          theResults.push_back(*aResIter);
+          theValShapes.Append(aNewValSh);
+        }
+      }
+    }
+  }
+  return true; // theResults must be empty: everything is deleted
+}
+
 void Model_AttributeSelection::updateInHistory()
 {
   ResultPtr aContext = std::dynamic_pointer_cast<ModelAPI_Result>(myRef.value());
-  // only bodies may be modified later in the history, don't do anything otherwise
-  if (!aContext.get() || aContext->groupName() != ModelAPI_ResultBody::group())
+  // only bodies and parts may be modified later in the history, don't do anything otherwise
+  if (!aContext.get() || (aContext->groupName() != ModelAPI_ResultBody::group() &&
+      aContext->groupName() != ModelAPI_ResultPart::group()))
     return;
+  std::shared_ptr<Model_Document> aDoc =
+    std::dynamic_pointer_cast<Model_Document>(aContext->document());
   std::shared_ptr<Model_Data> aContData = std::dynamic_pointer_cast<Model_Data>(aContext->data());
   if (!aContData.get() || !aContData->isValid())
     return;
   TDF_Label aContLab = aContData->label(); // named shape where the selected context is located
   Handle(TNaming_NamedShape) aContNS;
-  if (!aContLab.FindAttribute(TNaming_NamedShape::GetID(), aContNS))
+  if (!aContLab.FindAttribute(TNaming_NamedShape::GetID(), aContNS)) {
+    bool aFoundNewContext = true;
+    ResultPtr aNewContext = aContext;
+    while(aFoundNewContext) {
+      aFoundNewContext = false;
+      // parts have no shape in result, so, trace references using the Part info
+      if (aNewContext->groupName() == ModelAPI_ResultPart::group()) {
+        ResultPartPtr aPartContext = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aNewContext);
+        if (aPartContext.get()) { // searching for the up to date references to the referenced cont
+          const std::set<AttributePtr>& aRefs = aPartContext->data()->refsToMe();
+          std::set<AttributePtr>::const_iterator aRef = aRefs.begin();
+          for(; aRef != aRefs.end(); aRef++) {
+            // to avoid detection of part changes by local selection only
+            AttributeSelectionPtr aSel =
+              std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*aRef);
+            if (aSel.get() && !aSel->value()->isSame(aSel->context()->shape()))
+              continue;
+
+            FeaturePtr aRefFeat = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRef)->owner());
+            if (aRefFeat.get() && aRefFeat != owner()) {
+              FeaturePtr aThisFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
+              if (aDoc->objects()->isLater(aThisFeature, aRefFeat)) { // found better feature
+                aFoundNewContext = true;
+                aNewContext = aRefFeat->firstResult();
+              }
+            }
+          }
+        }
+      }
+    }
+    if (aNewContext != aContext) {
+      setValue(aNewContext, value());
+    }
     return;
-  std::shared_ptr<Model_Document> aDoc =
-    std::dynamic_pointer_cast<Model_Document>(aContext->document());
+  }
   FeaturePtr aThisFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
   FeaturePtr aCurrentModifierFeat = aDoc->feature(aContext);
   // iterate the context shape modifications in order to find a feature that is upper in history
@@ -952,66 +1173,51 @@ void Model_AttributeSelection::updateInHistory()
   TNaming_Iterator aPairIter(aContNS);
   if (!aPairIter.More())
     return;
-  TopoDS_Shape aNewShape = aPairIter.NewShape();
+  TopoDS_Shape aNewCShape = aPairIter.NewShape();
   bool anIterate = true;
   // trying to update also the sub-shape selected
   GeomShapePtr aSubShape = value();
   if (aSubShape.get() && aSubShape->isEqual(aContext->shape()))
     aSubShape.reset();
-
-  while(anIterate) {
-    anIterate = false;
-    TNaming_SameShapeIterator aModifIter(aNewShape, aContLab);
-    for(; aModifIter.More(); aModifIter.Next()) {
-      ResultPtr aModifierObj = std::dynamic_pointer_cast<ModelAPI_Result>
-        (aDoc->objects()->object(aModifIter.Label().Father()));
-      if (!aModifierObj.get())
-        break;
-      FeaturePtr aModifierFeat = aDoc->feature(aModifierObj);
-      if (!aModifierFeat.get())
-        break;
-      if (aModifierFeat == aThisFeature || aDoc->objects()->isLater(aModifierFeat, aThisFeature))
-        continue; // the modifier feature is later than this, so, should not be used
-      if (aCurrentModifierFeat == aModifierFeat ||
-        aDoc->objects()->isLater(aCurrentModifierFeat, aModifierFeat))
-        continue; // the current modifier is later than the found, so, useless
-      Handle(TNaming_NamedShape) aNewNS;
-      aModifIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNewNS);
-      if (aNewNS->Evolution() == TNaming_MODIFY || aNewNS->Evolution() == TNaming_GENERATED) {
-        aModifierResFound = aModifierObj;
-        aCurrentModifierFeat = aModifierFeat;
-        TNaming_Iterator aPairIter(aNewNS);
-        aNewShape = aPairIter.NewShape();
-        anIterate = true;
-        break;
-      } else if (aNewNS->Evolution() == TNaming_DELETE) { // a shape was deleted => result is null
-        ResultPtr anEmptyContext;
-        std::shared_ptr<GeomAPI_Shape> anEmptyShape;
-        setValue(anEmptyContext, anEmptyShape); // nullify the selection
-        return;
-      } else { // not-precessed modification => don't support it
-        continue;
-      }
-    }
+  TopoDS_Shape aValShape;
+  if (aSubShape.get()) {
+    aValShape = aSubShape->impl<TopoDS_Shape>();
   }
-  if (aModifierResFound.get()) {
+
+  std::list<ResultPtr> aNewContexts;
+  TopTools_ListOfShape aValShapes;
+  if (searchNewContext(aDoc, aNewCShape, aContext, aValShape, aContLab, aNewContexts, aValShapes))
+  {
     // update scope to reset to a new one
     myScope.Clear();
-    myRef.setValue(aModifierResFound);
-    // if context shape type is changed to more complicated and this context is selected, split
-    if (myParent &&!aSubShape.get() && aModifierResFound->shape().get() && aContext->shape().get())
-    {
-      TopoDS_Shape anOldShape = aContext->shape()->impl<TopoDS_Shape>();
-      TopoDS_Shape aNewShape = aModifierResFound->shape()->impl<TopoDS_Shape>();
-      if (!anOldShape.IsNull() && !aNewShape.IsNull() &&
-        anOldShape.ShapeType() != aNewShape.ShapeType() &&
-        (aNewShape.ShapeType() == TopAbs_COMPOUND || aNewShape.ShapeType() == TopAbs_COMPSOLID)) {
-        // prepare for split in "update"
-        TDF_Label aSelLab = selectionLabel();
-        split(aContext, aNewShape, anOldShape.ShapeType());
+
+    std::list<ResultPtr>::iterator aNewCont = aNewContexts.begin();
+    TopTools_ListIteratorOfListOfShape aNewValues(aValShapes);
+    if (aNewCont == aNewContexts.end()) { // all results were deleted
+      ResultPtr anEmptyContext;
+      std::shared_ptr<GeomAPI_Shape> anEmptyShape;
+      setValue(anEmptyContext, anEmptyShape); // nullify the selection
+      return;
+    }
+
+    GeomShapePtr aValueShape;
+    if (!aNewValues.Value().IsNull()) {
+      aValueShape = std::make_shared<GeomAPI_Shape>();
+      aValueShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aNewValues.Value()));
+    }
+    setValue(*aNewCont, aValueShape);
+    // if there are more than one result, put them by "append" into "parent" list
+    if (myParent) {
+      for(aNewCont++, aNewValues.Next(); aNewCont != aNewContexts.end();
+          aNewCont++, aNewValues.Next()) {
+        GeomShapePtr aValueShape;
+        if (!aNewValues.Value().IsNull()) {
+          aValueShape = std::make_shared<GeomAPI_Shape>();
+          aValueShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aNewValues.Value()));
+        }
+        myParent->append(*aNewCont, aValueShape);
       }
     }
-    update(); // it must recompute a new sub-shape automatically
   }
 }
 
index 12a0003ffb3f8b13495cf66601704f2a7a482f71..5011bdce420ccde489bded88f141932b5fdaa673 100644 (file)
 #include <ModelAPI_AttributeSelection.h>
 #include <TDF_LabelMap.hxx>
 #include <TopoDS_Shape.hxx>
+#include <TopTools_ListOfShape.hxx>
 
 class Model_AttributeSelectionList;
+class Model_Document;
 
 /**\class Model_AttributeSelection
  * \ingroup DataModel
@@ -151,6 +153,16 @@ protected:
   /// Splits theNewShape into sub-shapes of theType type (for the list parent of this attribute)
   void split(ResultPtr theContext, TopoDS_Shape theNewShape, TopAbs_ShapeEnum theType);
 
+  /// When group position is updated, searches the new context and new values
+  bool searchNewContext(std::shared_ptr<Model_Document> theDoc, const TopoDS_Shape theContShape,
+                        ResultPtr theContext, TopoDS_Shape theValShape, TDF_Label theAccessLabel,
+                        std::list<ResultPtr>& theResults, TopTools_ListOfShape& theValShapes);
+
+  /// computes theShapes list - shapes that were generated/modified/deleted the theValShape
+  /// during creation from new to old context
+  void computeValues(ResultPtr theOldContext, ResultPtr theNewContext, TopoDS_Shape theValShape,
+    TopTools_ListOfShape& theShapes);
+
   friend class Model_Data;
   friend class Model_AttributeSelectionList;
 };
index e091a6e9e6fa09505864ebea062e9e3bc702d11e..5207a112024deb535b0e860b5e072f7b7dea05e5 100644 (file)
@@ -237,7 +237,7 @@ bool Model_AttributeSelectionList::isInList(const ResultPtr& theContext,
       std::list<std::shared_ptr<GeomAPI_Shape> >::iterator aShapes = aContext->second.begin();
       for(; aShapes != aContext->second.end(); aShapes++) {
         if (!theSubShape.get()) {
-          if (!aShapes->get())
+          if (!aShapes->get() || (*aShapes)->isSame(aContext->first->shape()))
             return true;
         } else {
           // we need to call here isSame instead of isEqual to do not check shapes orientation
@@ -254,13 +254,13 @@ bool Model_AttributeSelectionList::isInList(const ResultPtr& theContext,
     if (anAttr.get()) {
       if (anAttr->context() == theContext) { // contexts are equal, so, check that values are also
         std::shared_ptr<GeomAPI_Shape> aValue = anAttr->value();
-        if (!aValue.get()) {
-          if (!theSubShape.get()) { // both are null
+        if (!theSubShape.get()) {
+          if (!aValue.get() || aValue->isSame(theContext->shape())) { // both are null
             return true;
           }
         } else {
           // we need to call here isSame instead of isEqual to do not check shapes orientation
-          if (aValue->isSame(theSubShape)) // shapes are equal
+          if (theSubShape->isSame(aValue)) // shapes are equal
             return true;
         }
       }
index 383661d8642f75678ef6a7f92a55015e398f3455..39fbea9b63c86f22653ac4c03ae89021e1ab1416 100755 (executable)
@@ -31,6 +31,7 @@
 #include <TopoDS.hxx>
 #include <TopoDS_Face.hxx>
 #include <TDF_ChildIterator.hxx>
+#include <TDF_ChildIDIterator.hxx>
 #include <TDF_Reference.hxx>
 #include <TopTools_MapOfShape.hxx>
 #include <TopExp_Explorer.hxx>
@@ -251,9 +252,18 @@ void  Model_BodyBuilder::storeWithoutNaming(const std::shared_ptr<GeomAPI_Shape>
 
 void Model_BodyBuilder::clean()
 {
-  std::vector<TNaming_Builder*>::iterator aBuilder = myBuilders.begin();
-  for(; aBuilder != myBuilders.end(); aBuilder++)
-    delete *aBuilder;
+  TDF_Label aLab = std::dynamic_pointer_cast<Model_Data>(data())->shapeLab();
+  if (aLab.IsNull())
+    return;
+  std::map<int, TNaming_Builder*>::iterator aBuilder = myBuilders.begin();
+  for(; aBuilder != myBuilders.end(); aBuilder++) {
+    delete aBuilder->second;
+    // clear also shapes on cleaned sub-labels (#2241)
+    Handle(TNaming_NamedShape) aNS;
+    if (aLab.FindChild(aBuilder->first).FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+      aNS->Clear();
+    }
+  }
   myBuilders.clear();
 }
 
@@ -264,17 +274,13 @@ Model_BodyBuilder::~Model_BodyBuilder()
 
 TNaming_Builder* Model_BodyBuilder::builder(const int theTag)
 {
-  if (myBuilders.size() <= (unsigned int)theTag) {
-    myBuilders.insert(myBuilders.end(), theTag - myBuilders.size() + 1, NULL);
-  }
-  if (!myBuilders[theTag]) {
+  std::map<int, TNaming_Builder*>::iterator aFind = myBuilders.find(theTag);
+  if (aFind == myBuilders.end()) {
     std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
     myBuilders[theTag] = new TNaming_Builder(aData->shapeLab().FindChild(theTag));
-    //TCollection_AsciiString entry;//
-    //TDF_Tool::Entry(aData->shapeLab().FindChild(theTag), entry);
-    //cout << "Label = " <<entry.ToCString() <<endl;
+    aFind = myBuilders.find(theTag);
   }
-  return myBuilders[theTag];
+  return aFind->second;
 }
 
 void Model_BodyBuilder::buildName(const int theTag, const std::string& theName)
@@ -377,6 +383,8 @@ void Model_BodyBuilder::loadAndOrientModifiedShapes (
   for (; aShapeExplorer.More(); aShapeExplorer.Next ()) {
     const TopoDS_Shape& aRoot = aShapeExplorer.Current ();
     if (!aView.Add(aRoot)) continue;
+    if (TNaming_Tool::NamedShape(aRoot, builder(theTag)->NamedShape()->Label()).IsNull())
+      continue; // there is no sence to write history is old shape does not persented in document
     ListOfShape aList;
     std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
     aRShape->setImpl((new TopoDS_Shape(aRoot)));
@@ -431,6 +439,8 @@ void Model_BodyBuilder::loadAndOrientGeneratedShapes (
   for (; aShapeExplorer.More(); aShapeExplorer.Next ()) {
     const TopoDS_Shape& aRoot = aShapeExplorer.Current ();
     if (!aView.Add(aRoot)) continue;
+    if (TNaming_Tool::NamedShape(aRoot, builder(theTag)->NamedShape()->Label()).IsNull())
+      continue; // there is no sence to write history is old shape does not persented in document
     ListOfShape aList;
     std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
     aRShape->setImpl((new TopoDS_Shape(aRoot)));
index f295e0864b469ade49d94a93fbe306f439486177..983c03a7564f5f7564d0e9a48c8641d721a1589a 100755 (executable)
@@ -36,9 +36,9 @@ class TNaming_Builder;
  */
 class Model_BodyBuilder : public ModelAPI_BodyBuilder
 {
-  /// builders that tores the naming history: one per label to allow store several shapes to one
+  /// builders that store the naming history: one per label to allow store several shapes to one
   /// label; index in vector corresponds to the label tag
-  std::vector<TNaming_Builder*> myBuilders;
+  std::map<int, TNaming_Builder*> myBuilders;
 public:
   /// Stores the shape (called by the execution method).
   MODEL_EXPORT virtual void store(const std::shared_ptr<GeomAPI_Shape>& theShape,
index 7bfa1c237ceed03f19f6bbf5548889ec7f714c4a..867614ca3fb39f5668446b30e6af1b83ef37a38a 100644 (file)
@@ -307,7 +307,14 @@ void Model_Data::sendAttributeUpdated(ModelAPI_Attribute* theAttr)
   if (theAttr->isArgument()) {
     if (mySendAttributeUpdated) {
       if (myObject) {
-        myObject->attributeChanged(theAttr->id());
+        try {
+            myObject->attributeChanged(theAttr->id());
+        } catch(...) {
+          if (owner().get() && owner()->data().get() && owner()->data()->isValid()) {
+            Events_InfoMessage("Model_Data",
+              "%1 has failed during the update").arg(owner()->data()->name()).send();
+          }
+        }
         static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
         ModelAPI_EventCreator::get()->sendUpdated(myObject, anEvent);
       }
@@ -339,7 +346,14 @@ bool Model_Data::blockSendAttributeUpdated(const bool theBlock, const bool theSe
         myWasChangedButBlocked.clear();
         std::list<ModelAPI_Attribute*>::iterator aChangedIter = aWasChangedButBlocked.begin();
         for(; aChangedIter != aWasChangedButBlocked.end(); aChangedIter++) {
-          myObject->attributeChanged((*aChangedIter)->id());
+          try {
+            myObject->attributeChanged((*aChangedIter)->id());
+          } catch(...) {
+            if (owner().get() && owner()->data().get() && owner()->data()->isValid()) {
+              Events_InfoMessage("Model_Data",
+                "%1 has failed during the update").arg(owner()->data()->name()).send();
+            }
+          }
         }
         static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
         ModelAPI_EventCreator::get()->sendUpdated(myObject, anEvent);
index c6d7dda35baa7ce1647ba3a60d10e83fa8c74880..03959c2ff7ea4eecc838ee652f242609828701e4 100755 (executable)
@@ -1308,7 +1308,7 @@ TDF_Label Model_Document::findNamingName(std::string theName)
       // If not found child label with the exact sub-name, then try to find compound with
       // such sub-name without suffix.
       Standard_Integer aSuffixPos = aSubName.SearchFromEnd('_');
-      if (aSuffixPos != -1) {
+      if (aSuffixPos != -1 && aSuffixPos != aSubName.Length()) {
         TCollection_ExtendedString anIndexStr = aSubName.Split(aSuffixPos);
         aSubName.Remove(aSuffixPos);
         aNamesIter.Initialize(aFind->second, TDataStd_Name::GetID(), Standard_True);
index 84a2706bef71f08657427aa90039cdfffbc93a83..67e48301e9fca54d78df0138c05b2875d51de8c8 100644 (file)
@@ -150,7 +150,7 @@ class Model_Document : public ModelAPI_Document
 
   //! Sets the current feature: all features below will be disabled, new features
   //! will be appended after this one.
-  //! \param theCurrent the selected feature as current: blow it everythin become disabled
+  //! \param theCurrent the selected feature as current: below it everything becomes disabled
   //! \param theVisible use visible features only: flag is true for Object Browser functionality
   MODEL_EXPORT virtual void setCurrentFeature(std::shared_ptr<ModelAPI_Feature> theCurrent,
     const bool theVisible);
index 0ba7c79b7a5656a317f0b72a98c4661d5576b3fc..231c0b6ed33290d915c5cfecb54ecccf1c1ed401 100755 (executable)
@@ -65,6 +65,28 @@ void Model_ResultCompSolid::storeModified(const std::shared_ptr<GeomAPI_Shape>&
   updateSubs(theNewShape);
 }
 
+void Model_ResultCompSolid::loadAndOrientModifiedShapes(GeomAlgoAPI_MakeShape* theMS,
+    std::shared_ptr<GeomAPI_Shape>  theShapeIn, const int  theKindOfShape, const int  theTag,
+    const std::string& theName, GeomAPI_DataMapOfShapeShape& theSubShapes,
+    const bool theIsStoreSeparate,
+    const bool theIsStoreAsGenerated,
+    const bool theSplitInSubs)
+{
+  if (theSplitInSubs && mySubs.size()) { // consists of subs
+    std::vector<std::shared_ptr<ModelAPI_ResultBody> >::const_iterator aSubIter = mySubs.cbegin();
+    for(; aSubIter != mySubs.cend(); aSubIter++) {
+      (*aSubIter)->loadAndOrientModifiedShapes(
+        theMS, theShapeIn, theKindOfShape, theTag, theName, theSubShapes, theIsStoreSeparate,
+        theIsStoreAsGenerated);
+    }
+  } else { // do for this directly
+    ModelAPI_ResultCompSolid::loadAndOrientModifiedShapes(
+    theMS, theShapeIn, theKindOfShape, theTag, theName, theSubShapes, theIsStoreSeparate,
+    theIsStoreAsGenerated);
+  }
+}
+
+
 int Model_ResultCompSolid::numberOfSubs(bool forTree) const
 {
   return int(mySubs.size());
@@ -215,7 +237,8 @@ void Model_ResultCompSolid::updateSubs(const std::shared_ptr<GeomAPI_Shape>& the
   } else if (!mySubs.empty()) { // erase all subs
     while(!mySubs.empty()) {
       ResultBodyPtr anErased = *(mySubs.rbegin());
-      anErased->setDisabled(anErased, true);
+      if (anErased->data()->isValid())
+        anErased->setDisabled(anErased, true);
       mySubs.pop_back();
     }
     // redisplay this because result with and without subs are displayed differently
index 9715f01556030fc8cad967ac1d68f4549b30fd3d..7fcf5cc59bae616da02259d634912179528e381b 100755 (executable)
@@ -57,6 +57,15 @@ public:
   MODEL_EXPORT virtual void storeModified(const std::shared_ptr<GeomAPI_Shape>& theOldShape,
     const std::shared_ptr<GeomAPI_Shape>& theNewShape, const int theDecomposeSolidsTag = 0);
 
+  /// load and orient modified shapes for sub-objects
+  MODEL_EXPORT virtual void loadAndOrientModifiedShapes (GeomAlgoAPI_MakeShape* theMS,
+    std::shared_ptr<GeomAPI_Shape>  theShapeIn, const int  theKindOfShape, const int  theTag,
+    const std::string& theName, GeomAPI_DataMapOfShapeShape& theSubShapes,
+    const bool theIsStoreSeparate = false,
+    const bool theIsStoreAsGenerated = false,
+    const bool theSplitInSubs = false);
+
+
   /// Returns the number of sub-elements
   MODEL_EXPORT virtual int numberOfSubs(bool forTree = false) const;
 
index 371d4062b9fdb03649a99f9a2dd729a0f92f024f..4962932bfe818400699161dfd0739184f385f08c 100644 (file)
@@ -413,6 +413,9 @@ int Model_ResultConstruction::select(const std::shared_ptr<GeomAPI_Shape>& theSu
   // iterate and store the result ids of sub-elements and sub-elements to sub-labels
   Handle(TDataStd_IntPackedMap) aRefs = TDataStd_IntPackedMap::Set(aLab);
   const int aSubNum = aComposite->numberOfSubs();
+  // subs are placed one by one  because of #2248): sketch curve may produce several edges
+  int aSubLabId = 1;
+
   for(int a = 0; a < aSubNum; a++) {
     FeaturePtr aSub = aComposite->subFeature(a);
     const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
@@ -442,8 +445,9 @@ int Model_ResultConstruction::select(const std::shared_ptr<GeomAPI_Shape>& theSu
                   Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
                   if (aFaceCurve == aCurve) {
                     TDF_Label aSubLab = aLab.FindChild(anID);
+                    TDF_Label aShapeSubLab = aLab.FindChild(aSubLabId++);
                     std::string aFullNameSub = fullName(aComposite, anEdge);
-                    saveSubName(aSubLab, isSelectionMode, anEdge, aMyDoc, aFullNameSub);
+                    saveSubName(aShapeSubLab, isSelectionMode, anEdge, aMyDoc, aFullNameSub);
 
                     int anOrient = Model_SelectionNaming::edgeOrientation(aSubShape, anEdge);
                     if (anOrient != 0) {
@@ -454,14 +458,12 @@ int Model_ResultConstruction::select(const std::shared_ptr<GeomAPI_Shape>& theSu
                 }
               } else { // put vertices of the selected edge to sub-labels
                 // add edges to sub-label to support naming for edges selection
-                int aTagIndex = anID + kSTART_VERTEX_DELTA;
                 for(TopExp_Explorer anEdgeExp(aSubShape, TopAbs_VERTEX);
-                  anEdgeExp.More();
-                  anEdgeExp.Next(), aTagIndex += kSTART_VERTEX_DELTA) {
+                      anEdgeExp.More(); anEdgeExp.Next()) {
                     TopoDS_Vertex aV = TopoDS::Vertex(anEdgeExp.Current());
-                    TDF_Label aSubLab = aLab.FindChild(aTagIndex);
+                    TDF_Label aShapeSubLab = aLab.FindChild(aSubLabId++);
                     std::string aFullNameSub = fullName(aComposite, aV);
-                    saveSubName(aSubLab, isSelectionMode, aV, aMyDoc, aFullNameSub);
+                    saveSubName(aShapeSubLab, isSelectionMode, aV, aMyDoc, aFullNameSub);
                 }
               }
             }
index c0c20223f6cb4dc599ff755b755e0add240da1a5..ddac1acb2a1099999b4d4ce7e31f281b7e5ac011 100644 (file)
@@ -62,7 +62,7 @@ void Model_ResultPart::initAttributes()
 
 std::shared_ptr<ModelAPI_Document> Model_ResultPart::partDoc()
 {
-  if (myTrsf.get() && baseRef().get()) { // the second condition is to to #2035
+  if (myTrsf.get() && baseRef().get()) { // the second condition is due to #2035
     return baseRef()->partDoc();
   }
   DocumentPtr aRes = data()->document(DOC_REF())->value();
@@ -92,8 +92,8 @@ void Model_ResultPart::activate()
   }
   if (!aDocRef->value().get()) {  // create (or open) a document if it is not yet created
     Handle(Model_Application) anApp = Model_Application::getApplication();
-    if (anApp->isLoadByDemand(data()->name())) {
-      anApp->loadDocument(data()->name(), aDocRef->docId()); // if it is just ne part, load may fail
+    if (anApp->isLoadByDemand(data()->name(), aDocRef->docId())) {
+      anApp->loadDocument(data()->name(), aDocRef->docId()); // if it is just new part, load fails
     } else {
       anApp->createDocument(aDocRef->docId());
     }
@@ -113,7 +113,7 @@ void Model_ResultPart::activate()
 
 std::shared_ptr<ModelAPI_ResultPart> Model_ResultPart::original()
 {
-  if (myTrsf.get() && baseRef().get()) {  // the second condition is to to #2035
+  if (myTrsf.get() && baseRef().get()) {  // the second condition is due to #2035
     return baseRef()->original();
   }
   return std::dynamic_pointer_cast<ModelAPI_ResultPart>(data()->owner());
index a9c8e5ddab3629ac7134e805beaaeee2460e4117..b6a1305115ef082accb27186ce9e4342fec6dd2c 100644 (file)
@@ -53,7 +53,7 @@ class Model_ResultPart : public ModelAPI_ResultPart
   /// Returns the part-document of this result
   MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Document> partDoc();
 
-  /// Returns the original part result: for transfomration features results this is
+  /// Returns the original part result: for transformation features results this is
   /// the original Part feature result
   MODEL_EXPORT virtual std::shared_ptr<ModelAPI_ResultPart> original();
 
index 188ffdb24506112f0c5fec2c94e26a810ebc90ba..5dbe49d9e27abe5e05f0c00b5e61790278819c8f 100644 (file)
@@ -137,6 +137,8 @@ bool isTrivial (const TopTools_ListOfShape& theAncestors, TopTools_IndexedMapOfS
   BB.MakeCompound(aCmp);
   TopTools_ListIteratorOfListOfShape it(theAncestors);
   for(;it.More();it.Next()) {
+    if (theSMap.Contains(it.Value()))
+      continue;
     BB.Add(aCmp, it.Value());
     theSMap.Add(it.Value());
   }
@@ -152,6 +154,57 @@ bool isTrivial (const TopTools_ListOfShape& theAncestors, TopTools_IndexedMapOfS
   return true;
 }
 
+const TopoDS_Shape findCommonShape(
+  const TopAbs_ShapeEnum theType, const TopTools_ListOfShape& theList)
+{
+  if(theList.Extent() < 1) {
+    return TopoDS_Shape();
+  } else if (theList.Extent() == 1) { // check that sub-shape is bounded by this alone shape
+    TopTools_MapOfShape aSubsInShape;
+    TopExp_Explorer anExp(theList.First(), theType);
+    for(; anExp.More(); anExp.Next()) {
+      if (aSubsInShape.Contains(anExp.Current())) { // found duplicate
+        return anExp.Current();
+      }
+      aSubsInShape.Add(anExp.Current());
+    }
+  }
+
+  // Store in maps sub-shapes from each face.
+  std::vector<TopTools_MapOfShape> aVec;
+  for(TopTools_ListIteratorOfListOfShape anIt(theList); anIt.More(); anIt.Next()) {
+    const TopoDS_Shape aFace = anIt.Value();
+    TopTools_MapOfShape aMap;
+    for(TopExp_Explorer anExp(aFace, theType); anExp.More(); anExp.Next()) {
+      const TopoDS_Shape& aSubShape = anExp.Current();
+      aMap.Add(anExp.Current());
+    }
+    aVec.push_back(aMap);
+  }
+
+  // Find sub-shape shared between all faces.
+  TopoDS_Shape aSharedShape;
+  for(TopTools_MapIteratorOfMapOfShape anIt(aVec[0]); anIt.More(); anIt.Next()) {
+    const TopoDS_Shape& aSubShape = anIt.Value();
+    int aSharedNb = 1;
+    for(int anIndex = 1; anIndex < aVec.size(); ++anIndex) {
+      if(aVec[anIndex].Contains(aSubShape)) {
+        ++aSharedNb;
+      }
+    }
+    if(aSharedNb == theList.Extent()) {
+      if(aSharedShape.IsNull()) {
+        aSharedShape = aSubShape;
+      } else {
+        // More than one shape shared between all faces, return null shape in this case.
+        return TopoDS_Shape();
+      }
+    }
+  }
+
+  return aSharedShape;
+}
+
 std::string Model_SelectionNaming::namingName(ResultPtr& theContext,
   std::shared_ptr<GeomAPI_Shape> theSubSh, const std::string& theDefaultName,
   const bool theAnotherDoc)
@@ -216,6 +269,9 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext,
           const TopTools_ListOfShape& anAncestors = aMap.FindFromKey(aSubShape);
           // check that it is not a trivial case (F1 & F2: aNumber = 1)
           isTrivialCase = isTrivial(anAncestors, aSMap);
+          if (!isTrivialCase) { // another try: check that common shape can be processed anyway
+            isTrivialCase = !findCommonShape(TopAbs_EDGE, anAncestors).IsNull();
+          }
         } else
           break;
         TopTools_ListOfShape aListOfNbs;
@@ -440,7 +496,7 @@ const TopoDS_Shape findFaceByName(
 size_t ParseName(const std::string& theSubShapeName,   std::list<std::string>& theList)
 {
   std::string aName = theSubShapeName;
-  std::string aLastName;
+  std::string aLastName = aName;
   size_t n1(0), n2(0); // n1 - start position, n2 - position of the delimiter
   while ((n2 = aName.find('&', n1)) != std::string::npos) {
     const std::string aName1 = aName.substr(n1, n2 - n1); //name of face
@@ -453,48 +509,6 @@ size_t ParseName(const std::string& theSubShapeName,   std::list<std::string>& t
   return theList.size();
 }
 
-const TopoDS_Shape findCommonShape(
-  const TopAbs_ShapeEnum theType, const TopTools_ListOfShape& theList)
-{
-  if(theList.Extent() < 2) {
-    return TopoDS_Shape();
-  }
-
-  // Store in maps sub-shapes from each face.
-  std::vector<TopTools_MapOfShape> aVec;
-  for(TopTools_ListIteratorOfListOfShape anIt(theList); anIt.More(); anIt.Next()) {
-    const TopoDS_Shape aFace = anIt.Value();
-    TopTools_MapOfShape aMap;
-    for(TopExp_Explorer anExp(aFace, theType); anExp.More(); anExp.Next()) {
-      const TopoDS_Shape& aSubShape = anExp.Current();
-      aMap.Add(anExp.Current());
-    }
-    aVec.push_back(aMap);
-  }
-
-  // Find sub-shape shared between all faces.
-  TopoDS_Shape aSharedShape;
-  for(TopTools_MapIteratorOfMapOfShape anIt(aVec[0]); anIt.More(); anIt.Next()) {
-    const TopoDS_Shape& aSubShape = anIt.Value();
-    int aSharedNb = 1;
-    for(int anIndex = 1; anIndex < aVec.size(); ++anIndex) {
-      if(aVec[anIndex].Contains(aSubShape)) {
-        ++aSharedNb;
-      }
-    }
-    if(aSharedNb == theList.Extent()) {
-      if(aSharedShape.IsNull()) {
-        aSharedShape = aSubShape;
-      } else {
-        // More than one shape shared between all faces, return null shape in this case.
-        return TopoDS_Shape();
-      }
-    }
-  }
-
-  return aSharedShape;
-}
-
 std::string getContextName(const std::string& theSubShapeName)
 {
   std::string aName;
@@ -792,11 +806,15 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType,
     return false;
     }
   }
+  if (!aSelection.IsNull() &&
+      aSelection.ShapeType() != aType && aSelection.ShapeType() != TopAbs_COMPOUND)
+      aSelection.Nullify(); // to avoid selection of face instead of edge that is described by face
   // another try to find edge or vertex by faces
   std::list<std::string> aListofNames;
   size_t aN = aSelection.IsNull() ? ParseName(aSubShapeName, aListofNames) : 0;
-  if (aSelection.IsNull() && (aType == TopAbs_EDGE || aType == TopAbs_VERTEX)) {
-    if(aN > 1) {
+  if ((aSelection.IsNull() && (aType == TopAbs_EDGE || aType == TopAbs_VERTEX)) ||
+      (!aSelection.IsNull() && aSelection.ShapeType() != aType)) { // edge by one face as example
+    if(aN >= 1) {
       TopTools_ListOfShape aList;
       std::list<std::string>::iterator it = aListofNames.begin();
       for(; it != aListofNames.end(); it++){
@@ -809,7 +827,7 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType,
   }
   // in case of construction, there is no registered names for all sub-elements,
   // even for the main element; so, trying to find them by name (without "&" intersections)
-  if (aN == 0) {
+  if (aN < 2) {
     size_t aConstrNamePos = aSubShapeName.find("/");
     bool isFullName = aConstrNamePos == std::string::npos;
     std::string aContrName = aContName;
index 072382a6fa0a9fcf98f9e8da1d7ce50515c05cb9..10bd28f205db172f7fe67331aa8bf482d3e7ef34 100644 (file)
@@ -332,9 +332,9 @@ std::list<std::shared_ptr<ModelAPI_Document> > Model_Session::allOpenedDocuments
   return aResult;
 }
 
-bool Model_Session::isLoadByDemand(const std::string theDocID)
+bool Model_Session::isLoadByDemand(const std::string theDocID, const int theDocIndex)
 {
-  return Model_Application::getApplication()->isLoadByDemand(theDocID);
+  return Model_Application::getApplication()->isLoadByDemand(theDocID, theDocIndex);
 }
 
 std::shared_ptr<ModelAPI_Document> Model_Session::copy(
index e980774512121d05f8a5971a4f25810689e1a97d..89b9d548c1d5d1b1416b57dde0ad8ec9b92c1aa6 100644 (file)
@@ -113,7 +113,7 @@ class Model_Session : public ModelAPI_Session, public Events_Listener
   MODEL_EXPORT virtual std::list<std::shared_ptr<ModelAPI_Document> > allOpenedDocuments();
 
   /// Returns true if document is not loaded yet
-  MODEL_EXPORT virtual bool isLoadByDemand(const std::string theDocID);
+  MODEL_EXPORT virtual bool isLoadByDemand(const std::string theDocID, const int theDocIndex);
 
   /// Registers the plugin that creates features.
   /// It is obligatory for each plugin to call this function on loading to be found by
index 0985db34bfca740fd7182a8473c3b8eed7fc44a0..bdd120bff2a31af03547168b7d880cc1b6ef6bc4 100644 (file)
@@ -168,4 +168,7 @@ ADD_UNIT_TESTS(TestConstants.py
                Test1995.py
                Test2170.py
                TestExternalConstruction.py
+               Test2228.py
+               Test2241.py
+               Test2252.py
 )
index c88c0f5a631d20ccfcc56b5620223fd54c4a96c7..4025d17b769b0a4e744586473d1c764982a9026e 100644 (file)
@@ -132,7 +132,8 @@ void ModelAPI_ResultBody::loadAndOrientModifiedShapes (GeomAlgoAPI_MakeShape* th
     std::shared_ptr<GeomAPI_Shape>  theShapeIn, const int  theKindOfShape, const int  theTag,
     const std::string& theName, GeomAPI_DataMapOfShapeShape& theSubShapes,
     const bool theIsStoreSeparate,
-    const bool theIsStoreAsGenerated)
+    const bool theIsStoreAsGenerated,
+    const bool /*theSplitInSubs*/)
 {
   myBuilder->loadAndOrientModifiedShapes(
     theMS, theShapeIn, theKindOfShape, theTag, theName, theSubShapes, theIsStoreSeparate,
index 76a10b0b85bb3a4eaa80c5475835cb91389970ac..98a4b6a290c53f76da28f7e60c94c1f3d8597b3f 100644 (file)
@@ -128,7 +128,8 @@ public:
     std::shared_ptr<GeomAPI_Shape>  theShapeIn, const int  theKindOfShape, const int  theTag,
     const std::string& theName, GeomAPI_DataMapOfShapeShape& theSubShapes,
     const bool theIsStoreSeparate = false,
-    const bool theIsStoreAsGenerated = false);
+    const bool theIsStoreAsGenerated = false,
+    const bool theSplitInSubs = false);
   /// load and orient generated shapes
   MODELAPI_EXPORT virtual void loadAndOrientGeneratedShapes (GeomAlgoAPI_MakeShape* theMS,
     std::shared_ptr<GeomAPI_Shape>  theShapeIn, const int  theKindOfShape,
index 21fe583dba774b6a3d0c5cfe4459d24ccad40d81..7b2d7dd1b3887ba6af2b01a53b91721309aed9e5 100644 (file)
@@ -112,7 +112,7 @@ class MODELAPI_EXPORT ModelAPI_Session
   virtual std::list<std::shared_ptr<ModelAPI_Document> > allOpenedDocuments() = 0;
 
   /// Returns true if document is not loaded yet
-  virtual bool isLoadByDemand(const std::string theDocID) = 0;
+  virtual bool isLoadByDemand(const std::string theDocID, const int theDocIndex) = 0;
 
   /// Copies the document to the new one with the given id
   virtual std::shared_ptr<ModelAPI_Document> copy(
diff --git a/src/ModelAPI/Test/Test2228.py b/src/ModelAPI/Test/Test2228.py
new file mode 100644 (file)
index 0000000..f7da0bf
--- /dev/null
@@ -0,0 +1,76 @@
+## 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
+
+model.begin()
+partSet = model.moduleDocument()
+Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY"))
+SketchPoint_1 = Sketch_1.addPoint(model.selection("VERTEX", "Origin"))
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 0.3529019640553777)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchCircle_2 = Sketch_1.addCircle(0, 0, 0.4492388920251514)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchPoint_1.coordinates(), SketchCircle_2.center())
+model.do()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "PartSet/Sketch_1/Face-SketchCircle_1_2r-SketchCircle_2_2f")], model.selection(), 5, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "PartSet/YOZ"))
+SketchCircle_3 = Sketch_2.addCircle(-0.01730125245914903, 1.175069067120482, 0.2787321880802174)
+SketchCircle_4 = Sketch_2.addCircle(-0.01730125245914903, 1.175069067120482, 0.3197841740766353)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchCircle_3.center(), SketchCircle_4.center())
+model.do()
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2r-SketchCircle_2_2f")], model.selection(), 0, 3)
+Extrusion_3 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "PartSet/Sketch_1/Face-SketchCircle_1_2f")], model.selection(), model.selection("FACE", "Extrusion_1_1/To_Face_1"), 0, model.selection(), 0)
+Boolean_1 = model.addCut(Part_1_doc, [model.selection("SOLID", "Extrusion_2_1")], [model.selection("SOLID", "Extrusion_3_1")])
+Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "PartSet/XOZ"))
+SketchLine_1 = Sketch_3.addLine(-3.362323990279312, -0.5188129046480872, 0.8318943090987101, -0.5188129046480872)
+SketchLine_2 = Sketch_3.addLine(0.8318943090987101, -0.5188129046480872, 0.8318943090987101, 7.155729512171993)
+SketchLine_3 = Sketch_3.addLine(0.8318943090987101, 7.155729512171993, -3.362323990279312, 7.155729512171993)
+SketchLine_4 = Sketch_3.addLine(-3.362323990279312, 7.155729512171993, -3.362323990279312, -0.5188129046480872)
+SketchConstraintCoincidence_4 = Sketch_3.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_5 = Sketch_3.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_6 = Sketch_3.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_7 = Sketch_3.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_3.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_3.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_3.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_3.setVertical(SketchLine_4.result())
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_2"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_3"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_4"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_1")])
+Extrusion_4 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchCircle_2_2f")], model.selection(), model.selection("FACE", "Extrusion_2_1/From_Face_1"), 0, model.selection(), 0)
+Boolean_2 = model.addCut(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], [model.selection("SOLID", "Extrusion_4_1")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Boolean_1_1"), model.selection("SOLID", "Boolean_2_1"), model.selection("FACE", "Face_1_1")])
+Remove_SubShapes_1 = model.addRemoveSubShapes(Part_1_doc, model.selection("COMPOUND", "Partition_1_1"))
+Remove_SubShapes_1.setSubShapesToKeep([model.selection("COMPSOLID", "Partition_1_1_1"), model.selection("FACE", "Partition_1_1_3"), model.selection("FACE", "Partition_1_1_4"), model.selection("FACE", "Partition_1_1_5"), model.selection("FACE", "Partition_1_1_6"), model.selection("FACE", "Partition_1_1_7")])
+model.end()
+
+
+# check that remove sub-shapes contains correct selection
+from ModelAPI import *
+aFactory = ModelAPI_Session.get().validators()
+assert(aFactory.validate(Remove_SubShapes_1.feature()))
+assert(Remove_SubShapes_1.subshapes().size() == 6)
+assert(Remove_SubShapes_1.subshapes().value(0).namingName() == "Partition_1_1_1")
+assert(Remove_SubShapes_1.subshapes().value(1).namingName() == "Partition_1_1_3")
+assert(Remove_SubShapes_1.subshapes().value(2).namingName() == "Partition_1_1_4")
+assert(Remove_SubShapes_1.subshapes().value(3).namingName() == "Partition_1_1_5")
+assert(Remove_SubShapes_1.subshapes().value(4).namingName() == "Partition_1_1_6")
+assert(Remove_SubShapes_1.subshapes().value(5).namingName() == "Partition_1_1_7")
diff --git a/src/ModelAPI/Test/Test2241.py b/src/ModelAPI/Test/Test2241.py
new file mode 100644 (file)
index 0000000..5b5684d
--- /dev/null
@@ -0,0 +1,171 @@
+## 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
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "l", "10")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0, 60, 10, 60)
+SketchLine_2 = Sketch_1.addLine(model.selection("EDGE", "PartSet/OY"))
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_2.result())
+SketchLine_3 = Sketch_1.addLine(10, 60, 10, 40)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(10, 40, 20, 40)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(20, 40, 20, 20)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_1.addLine(20, 20, 30, 20)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchLine_7 = Sketch_1.addLine(30, 20, 30, 0)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchLine_8 = Sketch_1.addLine(model.selection("EDGE", "PartSet/OX"))
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_8.result())
+SketchLine_9 = Sketch_1.addLine(30, 0, 81.26217508737108, 0)
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_9.startPoint())
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_9.endPoint(), SketchLine_8.result())
+SketchLine_10 = Sketch_1.addLine(0, 60, 0, 81.26217508737108)
+SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_10.startPoint())
+SketchConstraintCoincidence_11 = Sketch_1.setCoincident(SketchLine_10.endPoint(), SketchLine_2.result())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_4.result())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_6.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_5.result())
+SketchArc_1 = Sketch_1.addArc(4.151438510550382e-034, -3.089278765476956e-034, 81.26217508737108, 0, 0, 81.26217508737108, False)
+SketchConstraintCoincidence_12 = Sketch_1.setCoincident(SketchLine_2.startPoint(), SketchArc_1.center())
+SketchConstraintCoincidence_13 = Sketch_1.setCoincident(SketchLine_9.endPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_14 = Sketch_1.setCoincident(SketchLine_2.result(), SketchArc_1.endPoint())
+SketchConstraintCoincidence_15 = Sketch_1.setCoincident(SketchLine_10.endPoint(), SketchArc_1.endPoint())
+SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_7.result())
+SketchArc_2 = Sketch_1.addArc(4.151438510550382e-034, -3.089278765476956e-034, 76.26217508737108, 0, 0, 76.26217508737108, False)
+SketchConstraintCoincidence_16 = Sketch_1.setCoincident(SketchLine_2.startPoint(), SketchArc_2.center())
+SketchConstraintCoincidence_16.setName("SketchConstraintCoincidence_23")
+SketchConstraintCoincidence_17 = Sketch_1.setCoincident(SketchLine_9.result(), SketchArc_2.startPoint())
+SketchConstraintCoincidence_17.setName("SketchConstraintCoincidence_24")
+SketchConstraintCoincidence_18 = Sketch_1.setCoincident(SketchLine_10.result(), SketchArc_2.endPoint())
+SketchConstraintCoincidence_18.setName("SketchConstraintCoincidence_25")
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchArc_1.endPoint(), SketchArc_2.endPoint(), 5)
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_7.result(), "2*l")
+SketchConstraintLength_1.setName("SketchConstraintLength_2")
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_6.result(), "l")
+SketchConstraintLength_2.setName("SketchConstraintLength_3")
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_5.result(), SketchLine_7.result())
+SketchConstraintEqual_1.setName("SketchConstraintEqual_2")
+SketchConstraintEqual_2 = Sketch_1.setEqual(SketchLine_6.result(), SketchLine_4.result())
+SketchConstraintEqual_2.setName("SketchConstraintEqual_3")
+SketchConstraintEqual_3 = Sketch_1.setEqual(SketchLine_5.result(), SketchLine_3.result())
+SketchConstraintEqual_3.setName("SketchConstraintEqual_4")
+SketchConstraintEqual_4 = Sketch_1.setEqual(SketchLine_4.result(), SketchLine_1.result())
+SketchConstraintEqual_4.setName("SketchConstraintEqual_5")
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_2.addCircle(9.082839147404137, 71.32948234489588, 2.005056553640547)
+SketchCircle_2 = Sketch_2.addCircle(20.11065019242717, 63.7102674410618, 2.268462537186828)
+SketchCircle_3 = Sketch_2.addCircle(26.52683116407693, 51.67992811921848, 2.727171758268866)
+SketchCircle_4 = Sketch_2.addCircle(38.35666483055617, 58.29661474623231, 3.007584830460834)
+SketchCircle_5 = Sketch_2.addCircle(33.94554041254697, 44.0607132153844, 3.054011155390377)
+SketchCircle_6 = Sketch_2.addCircle(48.58245325412298, 42.45666797247195, 2.346858526438435)
+SketchCircle_7 = Sketch_2.addCircle(38.95818179664835, 31.42885692744893, 3.547307159201095)
+SketchCircle_8 = Sketch_2.addCircle(63.82088306179116, 27.41874382016783, 4.536925074373651)
+SketchCircle_9 = Sketch_2.addCircle(50.18649849703544, 28.4212720969881, 4.820482891521984)
+SketchCircle_10 = Sketch_2.addCircle(49.58498153094326, 15.18789884296047, 2.552020354335177)
+SketchCircle_11 = Sketch_2.addCircle(66.22695092615982, 10.77677442495125, 4.536925074373645)
+SketchCircle_12 = Sketch_2.addCircle(50.98852111849166, 6.165144351577979, 3.547307159201085)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_1f-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_6f-SketchLine_7f-SketchLine_9f-SketchLine_10r-SketchArc_2_2f")])
+Face_2 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_9f-SketchLine_10r-SketchArc_1_2f-SketchArc_2_2r")])
+Face_3 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchCircle_1_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_2_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_3_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_4_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_5_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_6_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_7_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_9_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_8_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_10_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_12_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_11_2")])
+Face_4 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchCircle_1_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_2_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_3_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_4_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_5_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_7_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_6_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_9_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_8_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_10_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_12_2"), model.selection("EDGE", "Sketch_2/Edge-SketchCircle_11_2"), model.selection("WIRE", "Sketch_1/Wire-SketchLine_1f-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_6f-SketchLine_7f-SketchLine_9f-SketchLine_10r-SketchArc_2_2f")])
+Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "PartSet/XOY"))
+SketchLine_11 = Sketch_3.addLine(40, 0, 30, 0)
+SketchPoint_1 = Sketch_3.addPoint(model.selection("VERTEX", "Face_1_1/Edge_4&Face_1_1/Edge_5"))
+SketchConstraintCoincidence_19 = Sketch_3.setCoincident(SketchLine_11.endPoint(), SketchPoint_1.result())
+SketchLine_12 = Sketch_3.addLine(30, 0, 30, 10)
+SketchLine_13 = Sketch_3.addLine(30, 10, 40, 10)
+SketchLine_14 = Sketch_3.addLine(40, 10, 40, 0)
+SketchConstraintCoincidence_20 = Sketch_3.setCoincident(SketchLine_14.endPoint(), SketchLine_11.startPoint())
+SketchConstraintCoincidence_21 = Sketch_3.setCoincident(SketchLine_11.endPoint(), SketchLine_12.startPoint())
+SketchConstraintCoincidence_22 = Sketch_3.setCoincident(SketchLine_12.endPoint(), SketchLine_13.startPoint())
+SketchConstraintCoincidence_23 = Sketch_3.setCoincident(SketchLine_13.endPoint(), SketchLine_14.startPoint())
+SketchConstraintCoincidence_23.setName("SketchConstraintCoincidence_26")
+SketchConstraintHorizontal_4 = Sketch_3.setHorizontal(SketchLine_11.result())
+SketchConstraintVertical_4 = Sketch_3.setVertical(SketchLine_12.result())
+SketchConstraintHorizontal_5 = Sketch_3.setHorizontal(SketchLine_13.result())
+SketchConstraintVertical_5 = Sketch_3.setVertical(SketchLine_14.result())
+SketchConstraintEqual_5 = Sketch_3.setEqual(SketchLine_14.result(), SketchLine_13.result())
+SketchConstraintEqual_5.setName("SketchConstraintEqual_6")
+SketchConstraintLength_3 = Sketch_3.setLength(SketchLine_13.result(), "l")
+SketchConstraintLength_3.setName("SketchConstraintLength_4")
+model.do()
+Face_5 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_3/Wire-SketchLine_11r-SketchLine_12r-SketchLine_13r-SketchLine_14r")])
+MultiTranslation_1 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Face_5_1")], model.selection("EDGE", "PartSet/OX"), "l", 4, model.selection("EDGE", "PartSet/OY"), "l", 2)
+Recover_1 = model.addRecover(Part_1_doc, MultiTranslation_1, [Face_5.result()])
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("FACE", "Recover_1_1")], model.selection("VERTEX", "Face_4_1/Edge_4&Face_4_1/Edge_5"), model.selection("VERTEX", "Face_4_1/Edge_6&Face_4_1/Edge_7"))
+MultiTranslation_2 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Translation_1_1")], model.selection("EDGE", "PartSet/OX"), "l", 4, model.selection("EDGE", "PartSet/OY"), "l", 2)
+Recover_2 = model.addRecover(Part_1_doc, MultiTranslation_1, [Face_5.result()])
+Translation_2 = model.addTranslation(Part_1_doc, [model.selection("FACE", "Recover_2_1")], model.selection("VERTEX", "Face_4_1/Edge_4&Face_4_1/Edge_5"), model.selection("VERTEX", "Face_4_1/Edge_8&Face_4_1/Edge_9"))
+MultiTranslation_3 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Translation_2_1")], model.selection("EDGE", "PartSet/OX"), "l", 4)
+Recover_3 = model.addRecover(Part_1_doc, MultiTranslation_1, [Face_5.result()])
+Translation_3 = model.addTranslation(Part_1_doc, [model.selection("FACE", "Recover_3_1")], model.selection("VERTEX", "Face_4_1/Edge_4&Face_4_1/Edge_5"), model.selection("VERTEX", "MultiTranslation_3_1/Translated_Edge_1_4&MultiTranslation_3_1/Translated_Edge_1_1"))
+MultiTranslation_4 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Translation_3_1")], model.selection("EDGE", "PartSet/OX"), "l", 3)
+Recover_4 = model.addRecover(Part_1_doc, MultiTranslation_1, [Face_5.result()])
+Translation_4 = model.addTranslation(Part_1_doc, [model.selection("FACE", "Recover_4_1")], model.selection("VERTEX", "Face_4_1/Edge_4&Face_4_1/Edge_5"), model.selection("VERTEX", "Face_4_1/Edge_1&Face_4_1/Edge_2"))
+MultiTranslation_5 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Translation_4_1")], model.selection("EDGE", "PartSet/OX"), "l", 2)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "MultiTranslation_4_1_2"), model.selection("FACE", "MultiTranslation_1_1_8"), model.selection("FACE", "MultiTranslation_1_1_4"), model.selection("FACE", "MultiTranslation_1_1_3"), model.selection("FACE", "MultiTranslation_1_1_6"), model.selection("FACE", "MultiTranslation_1_1_2"), model.selection("FACE", "MultiTranslation_1_1_7"), model.selection("FACE", "MultiTranslation_2_1_3"), model.selection("FACE", "MultiTranslation_3_1_4"), model.selection("FACE", "MultiTranslation_2_1_8"), model.selection("FACE", "MultiTranslation_2_1_4"), model.selection("FACE", "MultiTranslation_2_1_7"), model.selection("FACE", "MultiTranslation_4_1_3"), model.selection("FACE", "MultiTranslation_1_1_1"), model.selection("FACE", "MultiTranslation_5_1_2"), model.selection("FACE", "MultiTranslation_4_1_1"), model.selection("FACE", "MultiTranslation_5_1_1"), model.selection("FACE", "MultiTranslation_3_1_3"), model.selection("FACE", "MultiTranslation_3_1_2"), model.selection("FACE", "MultiTranslation_3_1_1"), model.selection("FACE", "MultiTranslation_2_1_6"), model.selection("FACE", "MultiTranslation_2_1_2"), model.selection("FACE", "MultiTranslation_2_1_5"), model.selection("FACE", "MultiTranslation_2_1_1"), model.selection("FACE", "MultiTranslation_1_1_5")])
+Group_1.setName("Group_3")
+Group_1.result().setName("assemblages")
+Group_2 = model.addGroup(Part_1_doc, [model.selection("FACE", "Face_2_1"), model.selection("FACE", "Face_3_7"), model.selection("FACE", "Face_3_5"), model.selection("FACE", "Face_3_3"), model.selection("FACE", "Face_3_4"), model.selection("FACE", "Face_3_1"), model.selection("FACE", "Face_3_2"), model.selection("FACE", "Face_3_6"), model.selection("FACE", "Face_3_11"), model.selection("FACE", "Face_3_10"), model.selection("FACE", "Face_3_8"), model.selection("FACE", "Face_3_9"), model.selection("FACE", "Face_3_12")])
+Group_2.setName("Group_1")
+Group_2.result().setName("eau")
+Group_2.result().setColor(0, 170, 255)
+Group_3 = model.addGroup(Part_1_doc, [model.selection("FACE", "Face_4_1")])
+Group_3.setName("Group_2")
+Group_3.result().setName("acier")
+Group_3.result().setColor(170, 85, 0)
+Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "MultiTranslation_1_1_1"), model.selection("FACE", "MultiTranslation_1_1_2"), model.selection("FACE", "MultiTranslation_1_1_3"), model.selection("FACE", "MultiTranslation_1_1_4"), model.selection("FACE", "MultiTranslation_1_1_5"), model.selection("FACE", "MultiTranslation_1_1_6"), model.selection("FACE", "MultiTranslation_1_1_7"), model.selection("FACE", "MultiTranslation_2_1_4"), model.selection("FACE", "MultiTranslation_2_1_5"), model.selection("FACE", "MultiTranslation_2_1_6"), model.selection("FACE", "MultiTranslation_2_1_7"), model.selection("FACE", "MultiTranslation_2_1_8"), model.selection("FACE", "MultiTranslation_2_1_1"), model.selection("FACE", "MultiTranslation_2_1_2"), model.selection("FACE", "MultiTranslation_2_1_3"), model.selection("FACE", "MultiTranslation_3_1_4"), model.selection("FACE", "MultiTranslation_3_1_3"), model.selection("FACE", "MultiTranslation_3_1_2"), model.selection("FACE", "MultiTranslation_3_1_1"), model.selection("FACE", "MultiTranslation_4_1_1"), model.selection("FACE", "MultiTranslation_4_1_2"), model.selection("FACE", "MultiTranslation_4_1_3"), model.selection("FACE", "MultiTranslation_5_1_1"), model.selection("FACE", "MultiTranslation_5_1_2"), model.selection("FACE", "MultiTranslation_1_1_8")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("FACE", "Face_3_1"), model.selection("FACE", "Face_3_2"), model.selection("FACE", "Face_4_1"), model.selection("FACE", "Face_2_1"), model.selection("FACE", "Face_1_1"), model.selection("FACE", "Face_3_5"), model.selection("FACE", "Face_3_3"), model.selection("FACE", "Face_3_4"), model.selection("FACE", "Face_3_7"), model.selection("FACE", "Face_3_6"), model.selection("FACE", "Face_3_8"), model.selection("FACE", "Face_3_9"), model.selection("FACE", "Face_3_10"), model.selection("FACE", "Face_3_11"), model.selection("FACE", "Face_3_12"), model.selection("SHELL", "Shell_1_1")])
+Remove_SubShapes_1 = model.addRemoveSubShapes(Part_1_doc, model.selection("COMPOUND", "Partition_1_1"))
+Remove_SubShapes_1.setSubShapesToKeep([model.selection("FACE", "Partition_1_1_2"), model.selection("FACE", "Partition_1_1_3"), model.selection("FACE", "Partition_1_1_4"), model.selection("FACE", "Partition_1_1_5"), model.selection("FACE", "Partition_1_1_6"), model.selection("FACE", "Partition_1_1_7"), model.selection("FACE", "Partition_1_1_8"), model.selection("FACE", "Partition_1_1_9"), model.selection("FACE", "Partition_1_1_10"), model.selection("FACE", "Partition_1_1_11"), model.selection("FACE", "Partition_1_1_12"), model.selection("FACE", "Partition_1_1_13"), model.selection("FACE", "Partition_1_1_14"), model.selection("FACE", "Partition_1_1_15"), model.selection("FACE", "Partition_1_1_16"), model.selection("FACE", "Partition_1_1_17"), model.selection("FACE", "Partition_1_1_18"), model.selection("FACE", "Partition_1_1_19"), model.selection("FACE", "Partition_1_1_20"), model.selection("FACE", "Partition_1_1_21"), model.selection("FACE", "Partition_1_1_22"), model.selection("FACE", "Partition_1_1_23"), model.selection("FACE", "Partition_1_1_24"), model.selection("FACE", "Partition_1_1_25"), model.selection("FACE", "Partition_1_1_26"), model.selection("FACE", "Partition_1_1_27"), model.selection("FACE", "Partition_1_1_28"), model.selection("FACE", "Partition_1_1_29"), model.selection("FACE", "Partition_1_1_30"), model.selection("FACE", "Partition_1_1_31"), model.selection("FACE", "Partition_1_1_32"), model.selection("FACE", "Partition_1_1_33"), model.selection("FACE", "Partition_1_1_34"), model.selection("FACE", "Partition_1_1_35"), model.selection("FACE", "Partition_1_1_36"), model.selection("FACE", "Partition_1_1_37"), model.selection("FACE", "Partition_1_1_38"), model.selection("FACE", "Partition_1_1_39"), model.selection("FACE", "Partition_1_1_40"), model.selection("FACE", "Partition_1_1_41"), model.selection("FACE", "Partition_1_1_42"), model.selection("FACE", "Partition_1_1_43"), model.selection("FACE", "Partition_1_1_44"), model.selection("FACE", "Partition_1_1_45"), model.selection("FACE", "Partition_1_1_46"), model.selection("FACE", "Partition_1_1_47"), model.selection("FACE", "Partition_1_1_48"), model.selection("FACE", "Partition_1_1_49"), model.selection("FACE", "Partition_1_1_50"), model.selection("FACE", "Partition_1_1_51"), model.selection("FACE", "Partition_1_1_52"), model.selection("FACE", "Partition_1_1_53"), model.selection("FACE", "Partition_1_1_54"), model.selection("FACE", "Partition_1_1_55"), model.selection("FACE", "Partition_1_1_56"), model.selection("FACE", "Partition_1_1_57")])
+model.end()
+
+# move groups
+model.begin()
+Part_1_doc.moveFeature(Group_1.feature(), Remove_SubShapes_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 that groups 2 and 3 are correct, but Group_1 elements are removed (because shell is removed)
+from ModelAPI import *
+aFactory = ModelAPI_Session.get().validators()
+for Group in [Group_1, Group_2, Group_3]:
+  if Group != Group_1:
+    assert(aFactory.validate(Group.feature()))
+  assert(Group.groupList().size() != 0)
+  for a in range(Group.groupList().size()):
+    if Group == Group_1:
+      assert(len(Group.groupList().value(a).namingName()) == 0)
+    else:
+      assert(Group.groupList().value(a).value().shapeTypeStr() == "FACE")
+      assert(len(Group.groupList().value(a).namingName()) > 0)
diff --git a/src/ModelAPI/Test/Test2252.py b/src/ModelAPI/Test/Test2252.py
new file mode 100644 (file)
index 0000000..3b4306e
--- /dev/null
@@ -0,0 +1,69 @@
+## 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 *
+from GeomAlgoAPI 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(60, 0, 0, 0)
+SketchPoint_1 = Sketch_1.addPoint(model.selection("VERTEX", "PartSet/Origin"))
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchPoint_1.result())
+SketchLine_2 = Sketch_1.addLine(0, 0, 0, 60)
+SketchLine_3 = Sketch_1.addLine(0, 60, 60, 60)
+SketchLine_4 = Sketch_1.addLine(60, 60, 60, 0)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_5 = 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())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_3.result(), 60)
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_3.result(), SketchLine_4.result())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r")], model.selection(), 90, 0)
+model.do()
+aSession = ModelAPI_Session.get()
+aSession.setActiveDocument(partSet, False)
+Translation_1 = model.addTranslation(partSet, [model.selection("COMPOUND", "Part_1/")], model.selection("EDGE", "OX"), 100)
+model.do()
+# move timeline before Translation
+partSet.setCurrentFeature(Part_1.feature(), True)
+Rotation_1 = model.addRotation(partSet, [model.selection("COMPOUND", "Part_1/")], model.selection("EDGE", "OY"), 90)
+model.do()
+# move timeline to the end of history
+partSet.setCurrentFeature(Translation_1.feature(), True)
+model.end()
+
+# check that rotation then translation were applied consequently
+assert(partSet.size("Parts") == 1)
+resShape = modelAPI_Result(partSet.object("Parts", 0)).shape()
+# height of extrusion 90 / 2 + translation 100
+assert(GeomAlgoAPI_ShapeTools_centreOfMass(resShape).x() == 145)
+# rotated
+assert(floor(GeomAlgoAPI_ShapeTools_centreOfMass(resShape).z()) == -30)
+
+assert(model.checkPythonDump())
index ac0e3a561772647f0e991bc17e246f875f13f26c..77d9314d74d6b7d1d6d10096153bbdb97d82186b 100644 (file)
@@ -137,6 +137,9 @@ Q_OBJECT
   /// Returns main window of the application
   virtual QMainWindow* desktop() const = 0;
 
+  /// Returns true if SHIFT is pressed
+  /// \return boolean value
+  virtual bool hasSHIFTPressed() const = 0;
 
 signals:
   /// Signal selection changed.
index 5bf192c975cb0a6c37c7a427e86a3f4ee605ace3..fcba4e0c4b194ca241bfa5dfdd2eee8e9e8897f1 100644 (file)
@@ -413,7 +413,7 @@ void ModuleBase_ModelWidget::moveObject(ObjectPtr theObj)
   qDebug("ModuleBase_ModelWidget::moveObject");
 #endif
 
-  static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+  static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
   ModelAPI_EventCreator::get()->sendUpdated(theObj, anEvent);
   Events_Loop::loop()->flush(anEvent);
 
index e690ce0e533785b09e08867c135498d3eb187e72..0dd37b3550efc2c532da7bdea5a515390075ffdf 100755 (executable)
@@ -105,14 +105,11 @@ void ModuleBase_ResultPrs::Compute(
 }
 
 void ModuleBase_ResultPrs::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
-                                            const Standard_Integer theMode)
+                                            const Standard_Integer aMode)
 {
-  if (appendVertexSelection(aSelection, theMode))
-    return;
-
-  if (theMode > TopAbs_SHAPE) {
+  if (aMode > TopAbs_SHAPE) {
     // In order to avoid using custom selection modes
-    if (theMode == ModuleBase_ResultPrs::Sel_Result) {
+    if (aMode == ModuleBase_ResultPrs::Sel_Result) {
       AIS_Shape::ComputeSelection(aSelection, TopAbs_COMPOUND);
     }
     return;
@@ -120,7 +117,7 @@ void ModuleBase_ResultPrs::ComputeSelection(const Handle(SelectMgr_Selection)& a
 
   // TODO: OCCT issue should be created for the COMPOUND processing
   // before it is fixed, the next workaround in necessary
-  if (theMode == AIS_Shape::SelectionMode(TopAbs_COMPOUND)) {
+  if (aMode == AIS_Shape::SelectionMode(TopAbs_COMPOUND)) {
     const TopoDS_Shape& aShape = Shape();
     TopExp_Explorer aCompExp(aShape, TopAbs_COMPOUND);
     // do not activate in compound mode shapes which do not contain compounds
@@ -128,7 +125,7 @@ void ModuleBase_ResultPrs::ComputeSelection(const Handle(SelectMgr_Selection)& a
       return;
   }
 
-  if (theMode == AIS_Shape::SelectionMode(TopAbs_COMPSOLID)) {
+  if (aMode == AIS_Shape::SelectionMode(TopAbs_COMPSOLID)) {
     // Limit selection area only by actual object (Shape)
     ResultCompSolidPtr aCompSolid = ModelAPI_Tools::compSolidOwner(myResult);
     if (aCompSolid.get()) {
@@ -157,7 +154,7 @@ void ModuleBase_ResultPrs::ComputeSelection(const Handle(SelectMgr_Selection)& a
     }
     //AIS_Shape::ComputeSelection(aSelection, 0);
   }
-  AIS_Shape::ComputeSelection(aSelection, theMode);
+  AIS_Shape::ComputeSelection(aSelection, aMode);
 
   if (myAdditionalSelectionPriority > 0) {
     for (aSelection->Init(); aSelection->More(); aSelection->Next()) {
@@ -169,34 +166,6 @@ void ModuleBase_ResultPrs::ComputeSelection(const Handle(SelectMgr_Selection)& a
   }
 }
 
-bool ModuleBase_ResultPrs::appendVertexSelection(const Handle(SelectMgr_Selection)& aSelection,
-                                                 const Standard_Integer theMode)
-{
-  if (Shape().ShapeType() == TopAbs_VERTEX) {
-    const TopoDS_Shape& aShape = Shape();
-
-    int aPriority = StdSelect_BRepSelectionTool::GetStandardPriority(aShape, TopAbs_VERTEX);
-    double aDeflection = Prs3d::GetDeflection(aShape, myDrawer);
-
-    /// The cause of this method is the last parameter of BRep owner setting into True.
-    /// That means that owner should behave like it comes from decomposition. (In this case, OCCT
-    /// visualizes it in Ring style) OCCT version is 7.0.0 with path for SHAPER module.
-    Handle(StdSelect_BRepOwner) aOwner = new StdSelect_BRepOwner(aShape, aPriority, Standard_True);
-    StdSelect_BRepSelectionTool::ComputeSensitive(aShape, aOwner, aSelection,
-                                                  aDeflection, myDrawer->HLRAngle(), 9, 500);
-
-    for (aSelection->Init(); aSelection->More(); aSelection->Next()) {
-      Handle(SelectMgr_EntityOwner) anOwner =
-        Handle(SelectMgr_EntityOwner)
-        ::DownCast(aSelection->Sensitive()->BaseSensitive()->OwnerId());
-      anOwner->Set(this);
-    }
-    return true;
-  }
-  return false;
-}
-
-/* OBSOLETE
 void ModuleBase_ResultPrs::appendWiresSelection(const Handle(SelectMgr_Selection)& theSelection,
                                                 const TopoDS_Shape& theShape)
 {
@@ -214,7 +183,7 @@ void ModuleBase_ResultPrs::appendWiresSelection(const Handle(SelectMgr_Selection
                                       myDrawer->IsAutoTriangulation());
   } catch ( Standard_Failure ) {
   }
-}*/
+}
 
 void ModuleBase_ResultPrs::HilightSelected(const Handle(PrsMgr_PresentationManager3d)& thePM,
                                            const SelectMgr_SequenceOfOwner& theOwners)
index af70be9e8aa8b24192577816119c9ec05daa5972..6d46e4ef5c7b85cbef8be991b096f676bbb5b105 100644 (file)
@@ -53,9 +53,9 @@ public:
   /// Highlight the presentation with the given color
   /// \param aPM a presentations manager
   /// \param theStyle a style of presentation
-  /// \param theMode a drawing mode
+  /// \param aMode a drawing mode
   virtual void HilightWithColor (const Handle(PrsMgr_PresentationManager3d)& aPM,
-    const Handle(Graphic3d_HighlightStyle)& theStyle, const Standard_Integer theMode = 0)
+    const Handle(Graphic3d_HighlightStyle)& theStyle, const Standard_Integer aMode = 0)
   {
     Selectable()->HilightOwnerWithColor(aPM, theStyle, this);
   }
@@ -119,22 +119,14 @@ protected:
 
   /// Redefinition of virtual function
   Standard_EXPORT virtual void ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
-                                                const Standard_Integer theMode) ;
+    const Standard_Integer aMode) ;
 
 private:
-  /// If the shape of this presentation is Vertex, it appends custom sensitive and owners for it.
-  /// Owner is a usual Brep owner with "isDecomposite" in true. It is necessary to have "Ring"
-  /// highlight/selected marker.
-  /// \param theSelection a current filled selection
-  /// \param theMode a selection mode
-  /// \return true if the owner is created
-  bool appendVertexSelection(const Handle(SelectMgr_Selection)& aSelection,
-                             const Standard_Integer theMode);
   /// Appens sensitive and owners for wires of the given shape into selection
   /// \param theSelection a current filled selection
   /// \param theShape a shape
-  //void appendWiresSelection(const Handle(SelectMgr_Selection)& theSelection,
-  //                          const TopoDS_Shape& theShape);
+  void appendWiresSelection(const Handle(SelectMgr_Selection)& theSelection,
+                            const TopoDS_Shape& theShape);
 
   /// Reference to result object
   ResultPtr myResult;
index 3c4d0604a5778ff1454d17caf0e94ec994955257..a9c27367fe427b41fd6a0b0bcc29de33cfaebb79 100644 (file)
@@ -103,7 +103,7 @@ bool ModuleBase_WidgetEditor::editedValue(double theSpinMinValue, double theSpin
 bool ModuleBase_WidgetEditor::focusTo()
 {
   showPopupEditor();
-  return true;
+  return false;
 }
 
 bool ModuleBase_WidgetEditor::showPopupEditor(const bool theSendSignals)
@@ -111,9 +111,10 @@ bool ModuleBase_WidgetEditor::showPopupEditor(const bool theSendSignals)
   bool isValueAccepted = false;
   // we need to emit the focus in event manually in order to save the widget as an active
   // in the property panel before the mouse leave event happens in the viewer. The module
-  // ask an active widget and change the feature visualization if the widget is not the current one.
-  if (theSendSignals)
-    emitFocusInWidget();
+  // ask an active widget and change the feature visualization if the widget is not the current
+  // one.  Also we need this widget as active to provide call of processEnter() applyed
+  // by operation manager to the current widget. If not, the myEditorDialog will stay opened
+  emitFocusInWidget();
 
   // nds: it seems, that the envents processing is not necessary anymore
   // White while all events will be processed
index 80fb5cd9a6a7b4be46ad649e2dc0444bd6b8cdf2..d144f33821c377a605e3bed8e80daee5059919a8 100755 (executable)
@@ -469,7 +469,6 @@ void ModuleBase_WidgetMultiSelector::updateFocus()
 {
   // Set focus to List control in order to make possible
   // to use Tab key for transfer the focus to next widgets
-  myListControl->setCurrentRow(myListControl->model()->rowCount() - 1);
   ModuleBase_Tools::setFocus(myListControl,
                              "ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()");
 }
@@ -745,7 +744,8 @@ bool ModuleBase_WidgetMultiSelector::removeUnusedAttributeObjects
     AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID());
     for (int i = 0; i < aSelectionListAttr->size(); i++) {
       AttributeSelectionPtr anAttr = aSelectionListAttr->value(i);
-      bool aFound = findInSelection(anAttr->context(), anAttr->value(), aGeomSelection);
+      bool aFound = findInSelection(anAttr->context(), anAttr->value(), aGeomSelection,
+                                    myWorkshop);
       if (!aFound)
         anIndicesToBeRemoved.insert(i);
     }
@@ -757,7 +757,8 @@ bool ModuleBase_WidgetMultiSelector::removeUnusedAttributeObjects
     for (int i = 0; i < aRefListAttr->size(); i++) {
       ObjectPtr anObject = aRefListAttr->object(i);
       if (anObject.get()) {
-        bool aFound = findInSelection(anObject, GeomShapePtr(), aGeomSelection);
+        bool aFound = findInSelection(anObject, GeomShapePtr(), aGeomSelection,
+                                      myWorkshop);
         if (!aFound)
           anIndicesToBeRemoved.insert(i);
       }
@@ -787,7 +788,8 @@ bool ModuleBase_WidgetMultiSelector::removeUnusedAttributeObjects
         aFound = anAttributes.find(anAttribute) != anAttributes.end();
       }
       else {
-        aFound = findInSelection(aRefAttrListAttr->object(i), GeomShapePtr(), aGeomSelection);
+        aFound = findInSelection(aRefAttrListAttr->object(i), GeomShapePtr(), aGeomSelection,
+                                 myWorkshop);
       }
       if (!aFound)
         anIndicesToBeRemoved.insert(i);
@@ -826,11 +828,22 @@ std::map<ObjectPtr, std::set<GeomShapePtr> > ModuleBase_WidgetMultiSelector::con
 }
 
 bool ModuleBase_WidgetMultiSelector::findInSelection(const ObjectPtr& theObject,
-                              const GeomShapePtr& theShape,
-                              const std::map<ObjectPtr, std::set<GeomShapePtr> >& theGeomSelection)
+                              GeomShapePtr theShape,
+                              const std::map<ObjectPtr, std::set<GeomShapePtr> >& theGeomSelection,
+                              ModuleBase_IWorkshop* theWorkshop)
 {
+  // issue #2154: we should not remove from list objects hidden in the viewer if selection
+  // was done with SHIFT button
+  if (theWorkshop->hasSHIFTPressed() && !theObject->isDisplayed())
+    return true;
+
   bool aFound = false;
   GeomShapePtr anEmptyShape(new GeomAPI_Shape());
+  if (theShape.get()) { // treat shape equal to context as null: 2219, keep order of shapes in list
+    const ResultPtr aContext = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
+    if (aContext.get() && aContext->shape()->isEqual(theShape))
+      theShape.reset();
+  }
   GeomShapePtr aShape = theShape.get() ? theShape : anEmptyShape;
   if (theGeomSelection.find(theObject) != theGeomSelection.end()) {// found
     const std::set<GeomShapePtr>& aShapes = theGeomSelection.at(theObject);
index 1716cc307c2d5f88e2958e3dac1e942aea539d93..2e43e575d1f93c0f9382e81a342c513cfb0325c4 100755 (executable)
@@ -184,10 +184,12 @@ protected:
   /// \param theObject a model object, a set of shapes is searched by it
   /// \param theShape a shape to be in the set of the object shapes
   /// \param theGeomSelection a map built on selection
+  /// \param theWorkshop a current workshop
   /// \return boolean result
   static bool findInSelection(const ObjectPtr& theObject,
-                            const GeomShapePtr& theShape,
-                            const std::map<ObjectPtr, std::set<GeomShapePtr> >& theGeomSelection);
+                            GeomShapePtr theShape,
+                            const std::map<ObjectPtr, std::set<GeomShapePtr> >& theGeomSelection,
+                            ModuleBase_IWorkshop* theWorkshop);
 
 protected:
   /// List control
index a9845e2a57c3f542750a8a1681dd008eaf3fea68..5dc11364e32d6cd5496a910e7d54dbd0ecd92df3 100755 (executable)
@@ -255,6 +255,7 @@ void PartSet_Module::registerValidators()
   aFactory->registerValidator("PartSet_CollinearSelection", new PartSet_CollinearSelection);
   aFactory->registerValidator("PartSet_MiddlePointSelection", new PartSet_MiddlePointSelection);
   aFactory->registerValidator("PartSet_DifferentObjects", new PartSet_DifferentObjectsValidator);
+  aFactory->registerValidator("PartSet_DifferentPoints", new PartSet_DifferentPointsValidator);
   aFactory->registerValidator("PartSet_CoincidentAttr", new PartSet_CoincidentAttr);
   aFactory->registerValidator("PartSet_MultyTranslationSelection",
     new PartSet_MultyTranslationSelection);
index 178a4bfd49f2e74ecf0ba7a59b7b014e447f5af1..b2f95ddd3f665a4bc4871e814c7ba1e63996cd8b 100755 (executable)
@@ -33,6 +33,9 @@
 #include <ModuleBase_OperationFeature.h>
 #include <ModuleBase_ViewerPrs.h>
 
+#include <GeomDataAPI_Point2D.h>
+#include <GeomAPI_Pnt2d.h>
+
 #include <Events_InfoMessage.h>
 
 #include <ModelAPI_AttributeRefAttr.h>
@@ -48,6 +51,7 @@
 #include <SketchPlugin_Sketch.h>
 #include <SketchPlugin_ConstraintCoincidence.h>
 #include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Point.h>
 #include <GeomAPI_Edge.h>
 
 #include <list>
@@ -609,6 +613,56 @@ bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute
   return true;
 }
 
+bool PartSet_DifferentPointsValidator::isValid(const AttributePtr& theAttribute,
+                                               const std::list<std::string>& theArguments,
+                                               Events_InfoMessage& theError) const
+{
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
+
+  // the type of validated attributes should be equal, attributes with
+  // different types are not validated
+  // Check RefAttr attributes
+  std::string anAttrType = theAttribute->attributeType();
+  std::list<std::shared_ptr<ModelAPI_Attribute> > anAttrs;
+  if (anAttrType != ModelAPI_AttributeRefAttr::typeId())
+    return true;
+
+  // obtain point of the given attribute
+  AttributePoint2DPtr anAttributePoint = getRefPointAttribute(theAttribute);
+  if (!anAttributePoint.get() || !anAttributePoint->isInitialized())
+    return true;
+
+  // obtain point of the parameter attribute
+  AttributePoint2DPtr anArgumentPoint = getRefPointAttribute
+                                              (aFeature->attribute(theArguments.front()));
+
+  if (!anArgumentPoint.get() || !anArgumentPoint->isInitialized())
+    return true;
+
+  return !anAttributePoint->pnt()->isEqual(anArgumentPoint->pnt());
+}
+
+AttributePoint2DPtr PartSet_DifferentPointsValidator::getRefPointAttribute
+                                                     (const AttributePtr& theAttribute) const
+{
+  AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
+
+  AttributePoint2DPtr aPointAttribute;
+  if (anAttr->isObject()) {
+    ObjectPtr anObject  = anAttr->object();
+    if (anObject.get()) {
+      FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
+      if (aFeature->getKind() == SketchPlugin_Point::ID())
+        aPointAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>
+                                          (aFeature->attribute(SketchPlugin_Point::COORD_ID()));
+    }
+  }
+  else {
+    aPointAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
+  }
+  return aPointAttribute;
+}
+
 bool PartSet_CoincidentAttr::isValid(const AttributePtr& theAttribute,
                                      const std::list<std::string>& theArguments,
                                      Events_InfoMessage& theError) const
index a14456c4a933cbe5b4325184b7c0e3714ecb9b60..039d259ca9536dec339feab3d2f9cfb4b592225d 100644 (file)
@@ -27,6 +27,8 @@
 #include <ModuleBase_ISelection.h>
 #include <ModelAPI_AttributeValidator.h>
 
+class GeomDataAPI_Point2D;
+
 /*
  * Selector validators
  */
@@ -220,6 +222,34 @@ private:
 
 };
 
+/**
+* \ingroup Validators
+* A validator which checks that Point2D selected for feature attributes are different (not the same)
+* It iterates by the feature ModelAPI_AttributeRefAttr attributes, finds GeomDataAPI_Point2D attribute in
+* value or attribute of the attributes and if the point of the given attribute is geometrical equal to
+* a point of another attribute, returns false
+*/
+class PartSet_DifferentPointsValidator : public ModelAPI_AttributeValidator
+{
+ public:
+  //! Returns true if the attribute is good for the feature attribute
+  //! \param theAttribute an attribute
+  //! \param theArguments a list of arguments (names of attributes to check)
+  //! \param theError an output error string
+  virtual bool isValid(const AttributePtr& theAttribute,
+                       const std::list<std::string>& theArguments,
+                       Events_InfoMessage& theError) const;
+private:
+  //! Finds Point2D attribute by reference attribute. It might be:
+  //! - COORD_ID attribute of SketchPlugin_Point if object
+  //! - Attribute casted to point if attribute
+  //! \param theAttribute an attribute
+  //! \return point 2d attribute or NULL
+  std::shared_ptr<GeomDataAPI_Point2D> getRefPointAttribute
+                      (const AttributePtr& theAttribute) const;
+};
+
+
 /**\class PartSet_CoincidentAttr
  * \ingroup Validators
  * \brief Validator to check whether there is a coincident constraint between
index c7dde30bf0c3420ad90d6f24be573fc0a8147186..3d9d933e95e927ce3457820dfc1b48c90fe9e886 100644 (file)
@@ -593,7 +593,6 @@ void PartSet_WidgetPoint2D::mouseReleased(ModuleBase_IViewWindow* theWindow, QMo
   if (!aFirstValue.get() && myPreSelected.get()) {
     aFirstValue = myPreSelected;
   }
-
   // if we have selection and use it
   if (aFirstValue.get() && isValidSelectionCustom(aFirstValue) &&
       aFirstValue->shape().get()) { /// Trihedron Axis may be selected, but shape is empty
index 5464d078f641c9910a53557cee5a8a589a629c20..aa209656b328a61230ef0ff4e5efe3eacce1a881 100644 (file)
@@ -542,9 +542,6 @@ void PartSet_WidgetSketchLabel::activateSelection(bool toActivate)
     QIntList aModes;
     std::shared_ptr<GeomAPI_Pln> aPlane = plane();
     if (aPlane.get()) {
-      //QList<std::shared_ptr<ModuleBase_ViewerPrs>> aEdges = findCircularEdgesInPlane();
-      //foreach(std::shared_ptr<ModuleBase_ViewerPrs> aPrs, aEdges) {
-      //}
       myWorkshop->module()->activeSelectionModes(aModes);
     }
     else {
index 8ec96b44904ef820b1a998f813823f03148b4c47..4eee01130ea56cad1a35f415f88a224171b7bc55 100644 (file)
@@ -42,7 +42,9 @@ void PartSetPlugin_Part::execute()
     setResult(aResult);
     // do not activate part by simple execution if it is not loaded yet: it must be explicitly
     // activated for this
-    if (!ModelAPI_Session::get()->isLoadByDemand(aResult->data()->name())) {
+    std::shared_ptr<ModelAPI_AttributeDocRef> aDocRef =
+      aResult->data()->document(ModelAPI_ResultPart::DOC_REF());
+    if (!ModelAPI_Session::get()->isLoadByDemand(aResult->data()->name(), aDocRef->docId())) {
       // On undo/redo creation of the part result the Object Browser must get creation event
       // earlier that activation of this part event (otherwise the crash is produced)
       // So, send a creation event earlier, without any grouping
index 9b1d6c713a04188c1ef77873ffd035464f68c389..ce6c3933288a6944447620e92cdccd649407128d 100644 (file)
@@ -23,6 +23,9 @@ from GeomAPI import *
 from GeomDataAPI import *
 from ModelAPI import ModelAPI_Feature
 import math
+from salome.shaper.model import sketcher
+
+TOLERANCE = 1.e-7
 
 aShapeTypes = {
   GeomAPI_Shape.SOLID:  "GeomAPI_Shape.SOLID",
@@ -133,6 +136,8 @@ def testHaveNamingFaces(theFeature, theModel, thePartDoc) :
   """ Tests if all faces of result have a name
   :param theFeature: feature to test.
   """
+  # open transaction since all the checking are performed in tests after model.end() call
+  theModel.begin()
   # Get feature result/sub-result
   aResult = theFeature.results()[0].resultSubShapePair()[0]
   # Get result/sub-result shape
@@ -147,6 +152,37 @@ def testHaveNamingFaces(theFeature, theModel, thePartDoc) :
     shapeExplorer.next()
   # Create group with this selection list
   Group_1 = theModel.addGroup(thePartDoc, selectionList)
+  theModel.end()
+
+  # Now you can check that all selected shapes in group have right shape type and name.
+  groupFeature = Group_1.feature()
+  groupSelectionList = groupFeature.selectionList("group_list")
+  assert(groupSelectionList.size() == len(selectionList))
+  for index in range(0, groupSelectionList.size()):
+    attrSelection = groupSelectionList.value(index)
+    shape = attrSelection.value()
+    name = attrSelection.namingName()
+    assert(shape.isFace())
+    assert(name != ""), "String empty"
+
+def testHaveNamingEdges(theFeature, theModel, thePartDoc) :
+  """ Tests if all faces of result have a name
+  :param theFeature: feature to test.
+  """
+  # Get feature result/sub-result
+  aResult = theFeature.results()[0].resultSubShapePair()[0]
+  # Get result/sub-result shape
+  shape = aResult.shape()
+  # Create shape explorer with desired shape type
+  shapeExplorer = GeomAPI_ShapeExplorer(shape, GeomAPI_Shape.EDGE)
+  # Create list, and store selections in it
+  selectionList = []
+  while shapeExplorer.more():
+    selection = theModel.selection(aResult, shapeExplorer.current()) # First argument should be result/sub-result, second is sub-shape on this result/sub-result
+    selectionList.append(selection)
+    shapeExplorer.next()
+  # Create group with this selection list
+  Group_1 = theModel.addGroup(thePartDoc, selectionList)
   theModel.do()
   theModel.end()
 
@@ -159,9 +195,10 @@ def testHaveNamingFaces(theFeature, theModel, thePartDoc) :
     attrSelection = groupSelectionList.value(index)
     shape = attrSelection.value()
     name = attrSelection.namingName()
-    assert(shape.isFace())
+    assert(shape.isEdge())
     assert(name != ""), "String empty"
 
+
 def testNbSubFeatures(theComposite, theKindOfSub, theExpectedCount):
   """ Tests number of sub-features of the given type
   :param theComposite     composite feature to check its subs
@@ -174,3 +211,15 @@ def testNbSubFeatures(theComposite, theKindOfSub, theExpectedCount):
     if aFeature is not None and aFeature.getKind() == theKindOfSub:
        count += 1
   assert (count == theExpectedCount), "Number of sub-features of type {}: {}, expected {}".format(theKindOfSub, count, theExpectedCount)
+
+def assertSketchArc(theArcFeature):
+  """ Tests whether the arc is correctly defined
+  """
+  aCenterPnt = geomDataAPI_Point2D(theArcFeature.attribute("center_point"))
+  aStartPnt = geomDataAPI_Point2D(theArcFeature.attribute("start_point"))
+  aEndPnt = geomDataAPI_Point2D(theArcFeature.attribute("end_point"))
+  aRadius = theArcFeature.real("radius")
+  aDistCS = sketcher.tools.distancePointPoint(aCenterPnt, aStartPnt)
+  aDistCE = sketcher.tools.distancePointPoint(aCenterPnt, aEndPnt)
+  assert math.fabs(aDistCS - aDistCE) < TOLERANCE, "Wrong arc: center-start distance {}, center-end distance {}".format(aDistCS, aDistCE)
+  assert math.fabs(aRadius.value() -aDistCS) < TOLERANCE, "Wrong arc: radius is {0}, expected {1}".format(aRadius.value(), aDistCS)
index f56ba704f451962928fc1951928fb5cfd1e59b59..63887c6b73423f1f27a8ad463da74d1a3f084f36 100644 (file)
@@ -72,6 +72,7 @@ SET(PROJECT_LIBRARIES
     ${OCCViewer}
     ${qtx}
     ${CAS_SHAPE}
+    ${SalomeObject}
 )
 
 ADD_DEFINITIONS( -DSHAPERGUI_EXPORTS ${CAS_DEFINITIONS} )
index dc11d995f7482e637d411d1dd29e428735f45030..37148b5a3b9025ec68fcd0aa1d7d04a55c093ddf 100644 (file)
@@ -27,6 +27,7 @@
 #include <SUIT_ViewManager.h>
 
 #include <QtxActionToolMgr.h>
+#include <SALOME_AISShape.hxx>
 
 #include <SelectMgr_ListIteratorOfListOfFilter.hxx>
 
@@ -374,8 +375,18 @@ void SHAPERGUI_SalomeViewer::fitAll()
 //**********************************************
 void SHAPERGUI_SalomeViewer::eraseAll()
 {
-  SOCC_Viewer* aViewer = dynamic_cast<SOCC_Viewer*>(myView->viewer());
-  aViewer->EraseAll(0);
+  Handle(AIS_InteractiveContext) aContext = AISContext();
+  AIS_ListOfInteractive aList;
+  aContext->DisplayedObjects(aList);
+  AIS_ListIteratorOfListOfInteractive aLIt;
+  Handle(AIS_InteractiveObject) anAISIO;
+  for (aLIt.Initialize(aList); aLIt.More(); aLIt.Next()) {
+    anAISIO = aLIt.Value();
+    Handle(Standard_Type) aType = anAISIO->DynamicType();
+    if (anAISIO->IsKind(STANDARD_TYPE(SALOME_AISShape))) {
+      aContext->Erase(anAISIO, false);
+    }
+  }
 }
 
 //**********************************************
index c22dad503fdf1786aa7951cb8d0cc3daab505cfc..7c89b5e5c2f6270098d37e92824cdda19841089f 100644 (file)
@@ -34,6 +34,7 @@ SET(PROJECT_HEADERS
     SketchPlugin_ConstraintDistanceHorizontal.h
     SketchPlugin_ConstraintDistanceVertical.h
     SketchPlugin_ConstraintEqual.h
+    SketchPlugin_Fillet.h
     SketchPlugin_ConstraintHorizontal.h
     SketchPlugin_ConstraintLength.h
     SketchPlugin_ConstraintMiddle.h
@@ -47,7 +48,6 @@ SET(PROJECT_HEADERS
     SketchPlugin_Ellipse.h
     SketchPlugin_ExternalValidator.h
     SketchPlugin_Feature.h
-    SketchPlugin_Fillet.h
     SketchPlugin_IntersectionPoint.h
     SketchPlugin_Line.h
     SketchPlugin_MacroArc.h
@@ -79,6 +79,7 @@ SET(PROJECT_SOURCES
     SketchPlugin_ConstraintDistanceHorizontal.cpp
     SketchPlugin_ConstraintDistanceVertical.cpp
     SketchPlugin_ConstraintEqual.cpp
+    SketchPlugin_Fillet.cpp
     SketchPlugin_ConstraintHorizontal.cpp
     SketchPlugin_ConstraintLength.cpp
     SketchPlugin_ConstraintMiddle.cpp
@@ -92,7 +93,6 @@ SET(PROJECT_SOURCES
     SketchPlugin_Ellipse.cpp
     SketchPlugin_ExternalValidator.cpp
     SketchPlugin_Feature.cpp
-    SketchPlugin_Fillet.cpp
     SketchPlugin_IntersectionPoint.cpp
     SketchPlugin_Line.cpp
     SketchPlugin_MacroArc.cpp
@@ -212,11 +212,8 @@ ADD_UNIT_TESTS(TestSketchPointLine.py
                TestTrimCircleAndArc01.py
                TestTrimLine01.py
                TestTrimLine02.py
-               TestMovePoint.py
-               TestMoveLine.py
-               TestMoveCircle.py
-               TestMoveArc.py
-               TestMovementComplex.py
+               Test2229.py
+               Test2239.py
                TestDistanceSignedVsUnsigned01.py
                TestDistanceSignedVsUnsigned02.py
                TestDistanceSignedVsUnsigned03.py
@@ -225,3 +222,13 @@ ADD_UNIT_TESTS(TestSketchPointLine.py
                TestSignedDistancePointPoint.py
                TestSignedDistancePointLine.py
 )
+
+if(${SKETCHER_CHANGE_RADIUS_WHEN_MOVE})
+  ADD_UNIT_TESTS(
+               TestMovePoint.py
+               TestMoveLine.py
+               TestMoveCircle.py
+               TestMoveArc.py
+               TestMovementComplex.py
+  )
+endif()
\ No newline at end of file
index 765984cb6f8fe64ad8afe93a017e1f1419333066..504314fbd293b7a98c91b1b684c681d9b2ed0427 100644 (file)
@@ -138,7 +138,6 @@ bool SketchPlugin_ConstraintLength::getPoints(
 {
   if (!sketch())
     return false;
-  std::shared_ptr<GeomAPI_Pln> aPlane = sketch()->plane();
   std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = std::dynamic_pointer_cast<
       ModelAPI_AttributeRefAttr>(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
   if (!anAttr)
index 10a6a781c9cd7ee9b04168b45a5a1dd17afb5b66..36e6714ab563d594961690f23d02bb054de1eeac 100644 (file)
@@ -474,17 +474,19 @@ std::set<FeaturePtr> getCoincides(const FeaturePtr& theConstraintCoincidence)
 
   SketchPlugin_Tools::findCoincidences(theConstraintCoincidence,
                                        SketchPlugin_ConstraintCoincidence::ENTITY_A(),
-                                       aCoincides);
+                                       aCoincides,
+                                       true);
   SketchPlugin_Tools::findCoincidences(theConstraintCoincidence,
                                        SketchPlugin_ConstraintCoincidence::ENTITY_B(),
-                                       aCoincides);
+                                       aCoincides,
+                                       true);
 
   // Remove points from set of coincides.
   std::set<FeaturePtr> aNewSetOfCoincides;
   for(std::set<FeaturePtr>::iterator anIt = aCoincides.begin(); anIt != aCoincides.end(); ++anIt) {
     std::shared_ptr<SketchPlugin_SketchEntity> aSketchEntity =
       std::dynamic_pointer_cast<SketchPlugin_SketchEntity>(*anIt);
-    if(aSketchEntity.get() && aSketchEntity->isCopy()) {
+    if(aSketchEntity.get() && (aSketchEntity->isCopy() || aSketchEntity->isExternal())) {
       continue;
     }
     if((*anIt)->getKind() == SketchPlugin_Line::ID()) {
index 642434753d88f4a5f09967b7875e5a5e800f4f62..cae5ca0f4da4dfbc086b9c61673a22a820ed208b 100644 (file)
@@ -274,22 +274,16 @@ GeomShapePtr SketchPlugin_MacroArc::getArcShape(bool isBound)
 
 AISObjectPtr SketchPlugin_MacroArc::getAISObject(AISObjectPtr thePrevious)
 {
-  if(!myStart.get() || !myEnd.get() || !myCenter.get()) {
+  GeomShapePtr anArcShape = getArcShape();
+  if(!anArcShape.get())
     return AISObjectPtr();
-  }
 
   SketchPlugin_Sketch* aSketch = sketch();
-  if(!aSketch) {
-    return AISObjectPtr();
-  }
-
-  GeomShapePtr anArcShape = getArcShape();
   std::shared_ptr<GeomAPI_Pnt> aCenter = aSketch->to3D(myCenter->x(), myCenter->y());;
   GeomShapePtr aCenterPointShape = GeomAlgoAPI_PointBuilder::vertex(aCenter);
 
-  if(!anArcShape.get() || !aCenterPointShape.get()) {
+  if(!aCenterPointShape.get())
     return AISObjectPtr();
-  }
 
   std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
   aShapes.push_back(anArcShape);
index 7c87681327cbb1a8398b22d461b4de1b1a293c07..2b6829c729a7f62aa6058e1698f71e9dd6e1ad25 100644 (file)
@@ -392,6 +392,7 @@ AISObjectPtr SketchPlugin_MacroCircle::getAISObject(AISObjectPtr thePrevious)
 }
 
 void SketchPlugin_MacroCircle::attributeChanged(const std::string& theID) {
+  double aRadius = 0.0;
   // If circle type switched reset all attributes.
   if(theID == CIRCLE_TYPE()) {
     SketchPlugin_Tools::resetAttribute(this, CENTER_POINT_ID());
index baa48456394c92fa696e92e409f5a1ebd4655c3c..c798ea4a81e073b7807ea8a30257ce966399f6fc 100644 (file)
@@ -104,7 +104,8 @@ std::set<FeaturePtr> findCoincidentConstraints(const FeaturePtr& theFeature)
 
 void findCoincidences(const FeaturePtr theStartCoin,
                       const std::string& theAttr,
-                      std::set<FeaturePtr>& theList)
+                      std::set<FeaturePtr>& theList,
+                      const bool theIsAttrOnly)
 {
   AttributeRefAttrPtr aPnt = theStartCoin->refattr(theAttr);
   if(!aPnt) {
@@ -116,15 +117,19 @@ void findCoincidences(const FeaturePtr theStartCoin,
     if(aOrig.get() == NULL) {
       return;
     }
-    theList.insert(aObj);
+    if(!theIsAttrOnly || !aPnt->isObject()) {
+      theList.insert(aObj);
+    }
     std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(aObj);
     std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
     for (; aCIt != aCoincidences.end(); ++aCIt) {
       FeaturePtr aConstrFeature = *aCIt;
       std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincidencePoint(aConstrFeature);
       if(aPnt.get() && aOrig->isEqual(aPnt)) {
-        findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A(), theList);
-        findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(), theList);
+        findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A(),
+                         theList, theIsAttrOnly);
+        findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(),
+                         theList, theIsAttrOnly);
       }
     }
   }
index e06cc163950cc207f402fc152176bd6c9b20a185..07ea391dfa86ffa0516efd302f4e57d8e9d46ec6 100644 (file)
@@ -46,9 +46,11 @@ std::set<FeaturePtr> findCoincidentConstraints(const FeaturePtr& theFeature);
 /// \param[in] theStartCoin coincidence feature
 /// \param[in] theAttr attribute name
 /// \param[out] theList list of lines
+/// \param[in] theIsAttrOnly if true includes only coincidences with attributes.
 void findCoincidences(const FeaturePtr theStartCoin,
                       const std::string& theAttr,
-                      std::set<FeaturePtr>& theList);
+                      std::set<FeaturePtr>& theList,
+                      const bool theIsAttrOnly = false);
 
 /// Find all features the point is coincident to.
 std::set<FeaturePtr> findFeaturesCoincidentToPoint(const AttributePoint2DPtr& thePoint);
index 714ec64e781f6e130ac9066be7ee8d1fc5753903..ed22a6420b086cae59f833b975ccedc47b0d3e5a 100755 (executable)
@@ -577,18 +577,20 @@ bool SketchPlugin_FilletVertexValidator::isValid(const AttributePtr& theAttribut
   std::set<FeaturePtr> aCoinsides;
   SketchPlugin_Tools::findCoincidences(aConstraintCoincidence,
                                         SketchPlugin_ConstraintCoincidence::ENTITY_A(),
-                                        aCoinsides);
+                                        aCoinsides,
+                                        true);
   SketchPlugin_Tools::findCoincidences(aConstraintCoincidence,
                                         SketchPlugin_ConstraintCoincidence::ENTITY_B(),
-                                        aCoinsides);
+                                        aCoinsides,
+                                        true);
 
-  // Remove points from set of coincides.
+  // Remove points and external lines from set of coincides.
   std::set<FeaturePtr> aNewSetOfCoincides;
   for(std::set<FeaturePtr>::iterator anIt = aCoinsides.begin();
       anIt != aCoinsides.end(); ++anIt) {
     std::shared_ptr<SketchPlugin_SketchEntity> aSketchEntity =
       std::dynamic_pointer_cast<SketchPlugin_SketchEntity>(*anIt);
-    if(aSketchEntity.get() && aSketchEntity->isCopy()) {
+    if(aSketchEntity.get() && (aSketchEntity->isCopy() || aSketchEntity->isExternal())) {
       continue;
     }
     if((*anIt)->getKind() != SketchPlugin_Line::ID() &&
diff --git a/src/SketchPlugin/Test/Test2229.py b/src/SketchPlugin/Test/Test2229.py
new file mode 100644 (file)
index 0000000..da8f65a
--- /dev/null
@@ -0,0 +1,43 @@
+## 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 ModelAPI import *
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "Wall_R", "6.188")
+model.addParameter(Part_1_doc, "Wall_T1", "0.089")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchPoint_1 = Sketch_1.addPoint(0, 2.424999999999997)
+SketchLine_1 = Sketch_1.addLine(model.selection("EDGE", "PartSet/OY"))
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.coordinates(), SketchLine_1.result())
+SketchConstraintRigid_1 = Sketch_1.setFixed(SketchPoint_1.coordinates())
+SketchLine_2 = Sketch_1.addLine(6.277, 3.700188311077954, 6.277, -1.894463229482514)
+SketchLine_2.setAuxiliary(True)
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchPoint_1.coordinates(), SketchLine_2.result(), "Wall_R+Wall_T1")
+model.end()
+
+# check that resulting sketch is valid
+aFactory = ModelAPI_Session.get().validators()
+assert(aFactory.validate(Sketch_1.feature()))
diff --git a/src/SketchPlugin/Test/Test2239.py b/src/SketchPlugin/Test/Test2239.py
new file mode 100644 (file)
index 0000000..30827d0
--- /dev/null
@@ -0,0 +1,92 @@
+## 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>
+##
+
+"""
+    Test2239.py
+    Test case for issue #2239 "Sketch not updated after having changed the parameter of multi-translation to 1"
+"""
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Parameter_N = model.addParameter(Part_1_doc, "N", "5")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(20, 0, 0, 0)
+SketchPoint_1 = Sketch_1.addPoint(model.selection("VERTEX", "PartSet/Origin"))
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchPoint_1.result())
+SketchLine_2 = Sketch_1.addLine(0, 0, 0, 20)
+SketchLine_3 = Sketch_1.addLine(0, 20, 20, 20)
+SketchLine_4 = Sketch_1.addLine(20, 20, 20, 0)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_3.result(), SketchLine_4.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_3.result(), 20)
+SketchLine_5 = Sketch_1.addLine(20, 0, 30, 0)
+SketchLine_5.setAuxiliary(True)
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_5.result())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_5.startPoint(), SketchLine_1.startPoint())
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_5.result(), 10)
+SketchMultiTranslation_1_objects = [SketchLine_1.result(), SketchLine_2.result(), SketchLine_3.result(), SketchLine_4.result()]
+SketchMultiTranslation_1 = Sketch_1.addTranslation(SketchMultiTranslation_1_objects, SketchLine_1.endPoint(), SketchLine_5.endPoint(), "N")
+model.do()
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Sketch_1, 1)
+model.testNbSubShapes(Sketch_1, GeomAPI_Shape.EDGE, [20])
+model.testNbSubShapes(Sketch_1, GeomAPI_Shape.VERTEX, [40])
+
+# check MultiTranslation error
+Parameter_N.setValue(1)
+model.do()
+assert(SketchMultiTranslation_1.feature().error() != "")
+
+
+# check MultiTranslation error disappears
+Parameter_N.setValue(2)
+model.do()
+assert(SketchMultiTranslation_1.feature().error() == "")
+
+model.testNbResults(Sketch_1, 1)
+model.testNbSubShapes(Sketch_1, GeomAPI_Shape.EDGE, [8])
+model.testNbSubShapes(Sketch_1, GeomAPI_Shape.VERTEX, [16])
+
+# check MultiTranslation is still correct
+Parameter_N.setValue(5)
+model.do()
+assert(SketchMultiTranslation_1.feature().error() == "")
+
+model.testNbResults(Sketch_1, 1)
+model.testNbSubShapes(Sketch_1, GeomAPI_Shape.EDGE, [20])
+model.testNbSubShapes(Sketch_1, GeomAPI_Shape.VERTEX, [40])
+
+model.end()
+
+
+assert(model.checkPythonDump())
index a64b6a35337e6bbffd2df7a88601eac9aa721fd1..9bc2d8b7280e738f93b2b82159ff54fb3a920c54 100644 (file)
@@ -570,7 +570,7 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
             label="Total number of objects"
             tooltip="Total number of objects"
             default="2" min="2" use_reset="false">
-          <validator id="GeomValidators_Positive"/>
+          <validator id="GeomValidators_Positive" parameters="1"/>
         </integervalue>
         <validator id="PartSet_MultyTranslationSelection" />
       </feature>
@@ -615,7 +615,7 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
             label="Total number of objects"
             tooltip="Total number of objects"
             default="2" min="2" use_reset="false">
-          <validator id="GeomValidators_Positive"/>
+          <validator id="GeomValidators_Positive" parameters="1"/>
         </integervalue>
         <validator id="PartSet_MultyTranslationSelection" />
       </feature>
@@ -637,6 +637,7 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
           <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
           <validator id="PartSet_DifferentObjects"/>
           <validator id="GeomValidators_ShapeType" parameters="vertex,line"/>
+          <validator id="PartSet_DifferentPoints" parameters="ConstraintEntityB"/>
         </sketch_shape_selector>
         <sketch_shape_selector
           id="ConstraintEntityB"
@@ -647,6 +648,7 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
           <validator id="SketchPlugin_DistanceAttr" parameters="ConstraintEntityA"/>
           <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
           <validator id="GeomValidators_ShapeType" parameters="vertex,line"/>
+          <validator id="PartSet_DifferentPoints" parameters="ConstraintEntityA"/>
         </sketch_shape_selector>
         <sketch-2dpoint_flyout_selector id="ConstraintFlyoutValuePnt"  default="computed" internal="1" obligatory="0"/>
 
index 081f3425c55397d70cd94d9b5470db542acafdd0..722d0ed24b14dec4cbaaf91d8e78323d1aaefab7 100644 (file)
@@ -112,6 +112,10 @@ SET(PROJECT_SOURCES
     ${SKETCHSOLVER_CONSTRAINT_SOURCES}
 )
 
+if(${SKETCHER_CHANGE_RADIUS_WHEN_MOVE})
+  ADD_DEFINITIONS(-DCHANGE_RADIUS_WHILE_MOVE)
+endif()
+
 ADD_LIBRARY(PlaneGCSSolver MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${SKETCHSOLVER_TEXT_RESOURCES})
 TARGET_LINK_LIBRARIES(PlaneGCSSolver ${PROJECT_LIBRARIES} ${SKETCHSOLVER_LIBRARIES})
 INSTALL(TARGETS PlaneGCSSolver DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES})
index 94c6d7af10066fa33f4489933acae9427abbdb76..f5d6df055692edda89410318425c4c0cc87cb211 100644 (file)
@@ -78,12 +78,14 @@ void SketchSolver_ConstraintMovement::process()
 static bool isSimpleMove(FeaturePtr theMovedFeature, AttributePtr theDraggedPoint)
 {
   bool isSimple = true;
+#ifdef CHANGE_RADIUS_WHILE_MOVE
   if (theMovedFeature->getKind() == SketchPlugin_Circle::ID())
     isSimple = (theDraggedPoint.get() != 0);
   else if (theMovedFeature->getKind() == SketchPlugin_Arc::ID()) {
     isSimple = (theDraggedPoint.get() != 0 &&
                 theDraggedPoint->id() == SketchPlugin_Arc::CENTER_ID());
   }
+#endif
   return isSimple;
 }
 
@@ -213,7 +215,11 @@ void SketchSolver_ConstraintMovement::moveTo(
   double aDelta[2] = { theDestinationPoint->x() - myStartPoint->x(),
                        theDestinationPoint->y() - myStartPoint->y() };
 
+#ifdef CHANGE_RADIUS_WHILE_MOVE
   int aMaxSize = mySimpleMove ? (int)myFixedValues.size() : 2;
+#else
+  int aMaxSize = myMovedFeature->getKind() == SketchPlugin_Line::ID() && !myDraggedPoint ? 4 : 2;
+#endif
   for (int i = 0; i < aMaxSize; ++i)
     myFixedValues[i] += aDelta[i % 2];
 }
index 506c8e46d99a9341a1dc2c983eae606e5f88f27c..03a9e38c13a62f97dfd9356742950499c4cbf0f3 100644 (file)
@@ -27,7 +27,6 @@
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Validator.h>
-#include <SketchPlugin_Constraint.h>
 #include <SketchPlugin_Sketch.h>
 
 /// Global constraint manager object
@@ -68,6 +67,8 @@ SketchSolver_Manager::SketchSolver_Manager()
   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_MOVED));
 
+  ////Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_FAILED));
+  ////Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_REPAIRED));
   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SKETCH_PREPARED));
 }
 
@@ -92,6 +93,7 @@ void SketchSolver_Manager::processEvent(
   bool isUpdateFlushed = false;
   bool isMovedEvt = false;
 
+  static const Events_ID aCreatedEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
   static const Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
   static const Events_ID aSketchPreparedEvent = Events_Loop::eventByName(EVENT_SKETCH_PREPARED);
   // sketch is prepared for resolve: all the needed events
@@ -105,23 +107,37 @@ void SketchSolver_Manager::processEvent(
     return;
   myIsComputed = true;
 
-  if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)
-      || theMessage->eventID() == anUpdateEvent) {
+  if (theMessage->eventID() == aCreatedEvent || theMessage->eventID() == anUpdateEvent) {
     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
         std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
-    std::set<ObjectPtr> aFeatures = anUpdateMsg->objects();
 
     isUpdateFlushed = stopSendUpdate();
 
     // update sketch features only
-    std::set<ObjectPtr>::iterator aFeatIter;
-    for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
-      std::shared_ptr<SketchPlugin_Feature> aFeature =
-          std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
-      if (!aFeature || aFeature->isMacro())
-        continue;
-
-      updateFeature(aFeature);
+    const std::set<ObjectPtr>& aFeatures = anUpdateMsg->objects();
+    // try to keep order as features were created if there are several created features: #2229
+    if (theMessage->eventID() == aCreatedEvent && aFeatures.size() > 1) {
+      std::map<int, std::shared_ptr<SketchPlugin_Feature>> anOrderedFeatures;
+      std::set<ObjectPtr>::iterator aFeatIter;
+      for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
+        std::shared_ptr<SketchPlugin_Feature> aFeature =
+            std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
+        if (aFeature && !aFeature->isMacro() && aFeature->data() && aFeature->data()->isValid()) {
+          anOrderedFeatures[aFeature->data()->featureId()] = aFeature;
+        }
+      }
+      std::map<int, std::shared_ptr<SketchPlugin_Feature>>::iterator aFeat;
+      for(aFeat = anOrderedFeatures.begin(); aFeat != anOrderedFeatures.end(); aFeat++) {
+        updateFeature(aFeat->second);
+      }
+    } else { // order is not important
+      std::set<ObjectPtr>::iterator aFeatIter;
+      for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
+        std::shared_ptr<SketchPlugin_Feature> aFeature =
+            std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
+        if (aFeature && !aFeature->isMacro())
+          updateFeature(aFeature);
+      }
     }
 
   } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED)) {
index e7f6c5f55d9ff66a6a2774b6b2f4197d7a85f6b2..d0ee1667c6196630a1f434424ef9febada2dfc60 100644 (file)
@@ -702,7 +702,7 @@ QStringList XGUI_ContextMenuMgr::actionObjectGroups(const QString& theName)
 void XGUI_ContextMenuMgr::onRename()
 {
   QObjectPtrList anObjects = myWorkshop->selector()->selection()->selectedObjects();
-  if (!myWorkshop->operationMgr()->abortAllOperations())
+  if (!myWorkshop->abortAllOperations())
     return;
   // restore selection in case if dialog box was shown
   myWorkshop->objectBrowser()->setObjectsSelected(anObjects);
index b68f63dd656d6f8f2eafa9726c4e3be10a43fe18..b735f2a51accd2ae8fc1a4993f1d90dae80f2b80 100644 (file)
@@ -1541,6 +1541,9 @@ void XGUI_Displayer::AddOrRemoveSelectedShapes(Handle(AIS_InteractiveContext) th
                            const NCollection_DataMap<TopoDS_Shape,
                            NCollection_Map<Handle(AIS_InteractiveObject)>>& theShapesToBeSelected)
 {
+  NCollection_Map<Handle(AIS_InteractiveObject)> aCompsolidPresentations;
+  NCollection_Map<Handle(AIS_InteractiveObject)> aSelectedPresentations;
+
   NCollection_List<Handle(SelectBasics_EntityOwner)> anActiveOwners;
   theContext->MainSelector()->ActiveOwners(anActiveOwners);
   NCollection_List<Handle(SelectBasics_EntityOwner)>::Iterator anOwnersIt (anActiveOwners);
@@ -1564,26 +1567,46 @@ void XGUI_Displayer::AddOrRemoveSelectedShapes(Handle(AIS_InteractiveContext) th
       if (aShape.IsNull())
         continue;
 
+      Handle(ModuleBase_BRepOwner) aCustomOwner = Handle(ModuleBase_BRepOwner)::DownCast(anOwner);
+
       NCollection_DataMap<TopoDS_Shape, NCollection_Map<Handle(AIS_InteractiveObject)> >
                                              ::Iterator aShapeIt(theShapesToBeSelected);
       for (; aShapeIt.More(); aShapeIt.Next()) {
-        if (aShapeIt.Key().IsSame(aShape)) {
-          const TopoDS_Shape& aParameterShape = aShapeIt.Key();
-          // isSame should be used here as it does not check orientation of shapes
-          // despite on isEqual of shapes or IsBound for shape in QMap. Orientation is
-          // different for Edges shapes in model shape and owner even if this is the same shape
-          if (aParameterShape.IsSame(aShape)) {
-            Handle(AIS_InteractiveObject) anOwnerPresentation =
-                              Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable());
-            NCollection_Map<Handle(AIS_InteractiveObject)> aPresentations =
-                                        theShapesToBeSelected.Find(aParameterShape);
-            if (aPresentations.Contains(anOwnerPresentation)) {
-              theContext->AddOrRemoveSelected(anOwner);
-              anOwner->SetSelected (Standard_True);
-            }
+        const TopoDS_Shape& aParameterShape = aShapeIt.Key();
+        // isSame should be used here as it does not check orientation of shapes
+        // despite on isEqual of shapes or IsBound for shape in QMap. Orientation is
+        // different for Edges shapes in model shape and owner even if this is the same shape
+        if (aParameterShape.IsSame(aShape)) {
+          Handle(AIS_InteractiveObject) anOwnerPresentation =
+                            Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable());
+          NCollection_Map<Handle(AIS_InteractiveObject)> aPresentations =
+                                      theShapesToBeSelected.Find(aParameterShape);
+          if (aPresentations.Contains(anOwnerPresentation)) {
+            theContext->AddOrRemoveSelected(anOwner, Standard_False);
+            anOwner->SetSelected (Standard_True);
+            // collect selected presentations to do not select them if compsolid is selected
+            if (!aSelectedPresentations.Contains(anOwnerPresentation))
+              aSelectedPresentations.Add(anOwnerPresentation);
           }
         }
+        else if (!aCustomOwner.IsNull()) { // CompSolid processing #2219
+          // shape of owner is compound, but shape to be selected is compsolid, so
+          // we need to compare shape to AIS presentation of owner(rule of the owner creation)
+          Handle(AIS_Shape) anOwnerPresentation =
+                            Handle(AIS_Shape)::DownCast(anOwner->Selectable());
+          const TopoDS_Shape& aPresentationShape = anOwnerPresentation->Shape();
+          if (aParameterShape.IsSame(anOwnerPresentation->Shape()) &&
+              !aCompsolidPresentations.Contains(anOwnerPresentation))
+            aCompsolidPresentations.Add(anOwnerPresentation);
+        }
       }
     }
   }
+  // select CompSolid presentations if their owners was not selected yet
+  NCollection_Map<Handle(AIS_InteractiveObject)>::Iterator anIt (aCompsolidPresentations);
+  for (; anIt.More(); anIt.Next()) {
+    if (aSelectedPresentations.Contains(anIt.Value()))
+      continue;
+    theContext->AddOrRemoveSelected(anIt.Value(), Standard_False);
+  }
 }
index 73d0447b008c5fc2582677a5377734377c16396b..fdb129faa151144ab62b56f27fda7406159d83d4 100755 (executable)
@@ -99,8 +99,7 @@ void XGUI_MenuMgr::addFeature(const std::shared_ptr<Config_FeatureMessage>& theM
     }
     if (aNestedActions.contains(FEATURE_WHEN_NESTED_ABORT)) {
       QAction* anAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::AbortAll);
-      QObject::connect(anAction, SIGNAL(triggered()),
-                       anOperationMgr, SLOT(onAbortAllOperations()));
+      QObject::connect(anAction, SIGNAL(triggered()), anOperationMgr, SLOT(abortAllOperations()));
       aNestedActList << anAction;
     }
   }
@@ -210,8 +209,7 @@ QAction* XGUI_MenuMgr::buildAction(const std::shared_ptr<Config_FeatureMessage>&
     }
     if (aNestedActions.contains(FEATURE_WHEN_NESTED_ABORT)) {
       QAction* anAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::AbortAll);
-      QObject::connect(anAction, SIGNAL(triggered()),
-                       anOperationMgr, SLOT(onAbortAllOperations()));
+      QObject::connect(anAction, SIGNAL(triggered()), anOperationMgr, SLOT(abortAllOperations()));
       aNestedActList << anAction;
     }
     anAction = aSalomeConnector->addFeatureOfNested(theWchName.c_str(), aFeatureInfo,
index 4e599649fa3eb786a10decc12b93eebe725d5eb1..b832fbb3071833f34b1eb610a7dcef366587b1c3 100644 (file)
@@ -193,6 +193,10 @@ QMainWindow* XGUI_ModuleConnector::desktop() const
   return myWorkshop->desktop();
 }
 
+bool XGUI_ModuleConnector::hasSHIFTPressed() const
+{
+  return myWorkshop->operationMgr()->hasSHIFTPressed();
+}
 
 std::shared_ptr<Config_FeatureMessage> XGUI_ModuleConnector::featureInfo(const QString& theId) const
 {
index 2d0d1473706cf16788361d2ccb859f333b785c33..06536228efd826ec8b0abb1e7cee7310c6260328 100644 (file)
@@ -119,6 +119,9 @@ Q_OBJECT
   /// Return application main window
   virtual QMainWindow* desktop() const;
 
+  /// Returns true if SHIFT is pressed
+  /// \return boolean value
+  virtual bool hasSHIFTPressed() const;
 
   //! Returns workshop
   XGUI_Workshop* workshop() const { return myWorkshop; }
index 02186143c9def04d27e45cbfa4b8ccddc40e49b3..42f892d212103f2d37bebefb575461c1d6c767d5 100644 (file)
@@ -72,18 +72,25 @@ public:
   virtual bool eventFilter(QObject *theObject, QEvent *theEvent)
   {
     bool isAccepted = false;
-    if (myIsActive && theEvent->type() == QEvent::KeyRelease) {
-      QKeyEvent* aKeyEvent = dynamic_cast<QKeyEvent*>(theEvent);
-      if (aKeyEvent) {
-        switch (aKeyEvent->key()) {
-          case Qt::Key_Delete:
-            isAccepted = myOperationMgr->onProcessDelete(theObject);
-          break;
-          default:
-            isAccepted = myOperationMgr->onKeyReleased(theObject, aKeyEvent);
+    if (myIsActive) {
+      if (theEvent->type() == QEvent::KeyRelease) {
+        QKeyEvent* aKeyEvent = dynamic_cast<QKeyEvent*>(theEvent);
+        if (aKeyEvent) {
+          myOperationMgr->setSHIFTPressed(aKeyEvent->modifiers() & Qt::ShiftModifier);
+          switch (aKeyEvent->key()) {
+            case Qt::Key_Delete:
+              isAccepted = myOperationMgr->onProcessDelete(theObject);
             break;
+            default:
+              isAccepted = myOperationMgr->onKeyReleased(theObject, aKeyEvent);
+              break;
+          }
         }
       }
+      else if (theEvent->type() == QEvent::KeyPress) {
+        QKeyEvent* aKeyEvent = dynamic_cast<QKeyEvent*>(theEvent);
+        myOperationMgr->setSHIFTPressed(aKeyEvent->modifiers() & Qt::ShiftModifier);
+      }
     }
     if (!isAccepted)
       isAccepted = QObject::eventFilter(theObject, theEvent);
@@ -97,7 +104,7 @@ private:
 
 XGUI_OperationMgr::XGUI_OperationMgr(QObject* theParent,
                                      ModuleBase_IWorkshop* theWorkshop)
-: QObject(theParent), myWorkshop(theWorkshop)
+: QObject(theParent), myWorkshop(theWorkshop), mySHIFTPressed(false)
 {
   /// we need to install filter to the application in order to react to 'Delete' key button
   /// this key can not be a short cut for a corresponded action because we need to set
@@ -211,12 +218,7 @@ bool XGUI_OperationMgr::startOperation(ModuleBase_Operation* theOperation)
   return isStarted;
 }
 
-void XGUI_OperationMgr::onAbortAllOperations()
-{
-  abortAllOperations();
-}
-
-bool XGUI_OperationMgr::abortAllOperations(const XGUI_MessageKind& theMessageKind)
+bool XGUI_OperationMgr::abortAllOperations()
 {
   bool aResult = true;
   if(!hasOperation())
@@ -224,29 +226,18 @@ bool XGUI_OperationMgr::abortAllOperations(const XGUI_MessageKind& theMessageKin
 
   if (operationsCount() == 1) {
     ModuleBase_Operation* aCurrentOperation = currentOperation();
-    if (canStopOperation(aCurrentOperation, theMessageKind)) {
+    if (canStopOperation(aCurrentOperation)) {
       abortOperation(aCurrentOperation);
     }
     else
       aResult = false;
   }
   else {
-    if (theMessageKind == XGUI_AbortOperationMessage) {
-      aResult = QMessageBox::question(qApp->activeWindow(),
-                                      tr("Abort operation"),
-                                      tr("All active operations will be aborted."),
-                                      QMessageBox::Ok | QMessageBox::Cancel,
-                                      QMessageBox::Cancel) == QMessageBox::Ok;
-    }
-    else if (theMessageKind == XGUI_InformationMessage) {
-      QString aMessage = tr("Please validate all your active operations before saving.");
-      QMessageBox::question(qApp->activeWindow(),
-                            tr("Validate operation"),
-                            aMessage,
-                            QMessageBox::Ok,
-                            QMessageBox::Ok);
-      aResult = false; // do not perform abort
-    }
+    aResult = QMessageBox::question(qApp->activeWindow(),
+                                    tr("Abort operation"),
+                                    tr("All active operations will be aborted."),
+                                    QMessageBox::Ok | QMessageBox::Cancel,
+                                    QMessageBox::Cancel) == QMessageBox::Ok;
     while(aResult && hasOperation()) {
       abortOperation(currentOperation());
     }
@@ -260,7 +251,7 @@ bool XGUI_OperationMgr::commitAllOperations()
   while (hasOperation()) {
     ModuleBase_Operation* anOperation = currentOperation();
     if (XGUI_Tools::workshop(myWorkshop)->errorMgr()->isApplyEnabled()) {
-      anOperationProcessed = commitOperation();
+      anOperationProcessed = onCommitOperation();
     } else {
       abortOperation(anOperation);
       anOperationProcessed = true;
@@ -314,35 +305,33 @@ void XGUI_OperationMgr::updateApplyOfOperations(ModuleBase_Operation* theOperati
   onValidateOperation();
 }
 
-bool XGUI_OperationMgr::canStopOperation(ModuleBase_Operation* theOperation,
-                                         const XGUI_OperationMgr::XGUI_MessageKind& theMessageKind)
+bool XGUI_OperationMgr::canStopOperation(ModuleBase_Operation* theOperation)
 {
   //in case of nested (sketch) operation no confirmation needed
   if (isGrantedOperation(theOperation->id()))
     return true;
   if (theOperation && theOperation->isModified()) {
-    if (theMessageKind == XGUI_AbortOperationMessage) {
-      QString aMessage = tr("%1 operation will be aborted.").arg(theOperation->id());
-      int anAnswer = QMessageBox::question(qApp->activeWindow(),
-                                           tr("Abort operation"),
-                                           aMessage,
-                                           QMessageBox::Ok | QMessageBox::Cancel,
-                                           QMessageBox::Cancel);
-      return anAnswer == QMessageBox::Ok;
-    }
-    else if (theMessageKind == XGUI_InformationMessage) {
-      QString aMessage = tr("Please validate your %1 before saving.").arg(theOperation->id());
-      QMessageBox::question(qApp->activeWindow(),
-                            tr("Validate operation"),
-                            aMessage,
-                            QMessageBox::Ok,
-                            QMessageBox::Ok);
-      return false;
-    }
+    QString aMessage = tr("%1 operation will be aborted.").arg(theOperation->id());
+    int anAnswer = QMessageBox::question(qApp->activeWindow(),
+                                         tr("Abort operation"),
+                                         aMessage,
+                                         QMessageBox::Ok | QMessageBox::Cancel,
+                                         QMessageBox::Cancel);
+    return anAnswer == QMessageBox::Ok;
   }
   return true;
 }
 
+bool XGUI_OperationMgr::commitOperation()
+{
+  //if (hasOperation() && currentOperation()->isValid()) {
+  //  onCommitOperation();
+  //  return true;
+  //}
+  //return false;
+  return onCommitOperation();
+}
+
 void XGUI_OperationMgr::resumeOperation(ModuleBase_Operation* theOperation)
 {
   theOperation->resume();
@@ -440,7 +429,7 @@ void XGUI_OperationMgr::abortOperation(ModuleBase_Operation* theOperation)
   }
 }
 
-bool XGUI_OperationMgr::commitOperation()
+bool XGUI_OperationMgr::onCommitOperation()
 {
   bool isCommitted = false;
   ModuleBase_Operation* anOperation = currentOperation();
index 00d941981479e68337b4ac30d16b61a8d254c81e..3e6f3b099a86378a1d7250d9b24f7ee59adc0c73 100755 (executable)
@@ -48,15 +48,7 @@ class XGUI_ShortCutListener;
 class XGUI_EXPORT XGUI_OperationMgr : public QObject
 {
 Q_OBJECT
-public:
-  /// Enumeration of kind of message that is used when trying to stop the active operation
-  enum XGUI_MessageKind
-  {
-    XGUI_AbortOperationMessage, //< warns and give possibility to abort current operation
-    XGUI_InformationMessage //< ask to apply the current operation before performing something
-  };
-
-public:
+ public:
   /// Constructor
   /// \param theParent the parent
   /// \param theWorkshop a reference to workshop
@@ -95,9 +87,7 @@ public:
   /// Returns true if the operation can be aborted. If the operation is modified,
   /// the warning message box is shown.
   /// \param theOperation an operation which is checked on stop
-  /// \param theMessageKind a kind of message in warning message box
-  bool canStopOperation(ModuleBase_Operation* theOperation,
-                        const XGUI_MessageKind& theMessageKind = XGUI_AbortOperationMessage);
+  bool canStopOperation(ModuleBase_Operation* theOperation);
 
   /// Find and return operation by its Id.
   ModuleBase_Operation* findOperation(const QString& theId) const;
@@ -134,7 +124,16 @@ public:
   /// \param theOperation an aborted operation
   void abortOperation(ModuleBase_Operation* theOperation);
 
-  bool abortAllOperations(const XGUI_MessageKind& theMessageKind = XGUI_AbortOperationMessage);
+  /// Slot that commits the current operation.
+  bool onCommitOperation();
+
+  /// Returns true if SHIFT is pressed
+  /// \param thePressed new boolean state
+  void setSHIFTPressed(const bool thePressed) { mySHIFTPressed = thePressed; }
+
+  /// Returns true if SHIFT is pressed
+  /// \return boolean value
+  bool hasSHIFTPressed() const { return mySHIFTPressed; }
 
 public slots:
   /// Slot that aborts the current operation.
@@ -144,10 +143,7 @@ public slots:
   /// Commit all operations
   bool commitAllOperations();
   /// Abort all operations
-  void onAbortAllOperations();
-
-protected slots:
-
+  bool abortAllOperations();
 
 signals:
   /// Signal about an operation is stopped. It is emitted after the stop() of operation is done.
@@ -251,6 +247,7 @@ private:
   ModuleBase_IWorkshop* myWorkshop;
 
   XGUI_ShortCutListener* myShortCutListener;
+  bool mySHIFTPressed;
 };
 
 #endif
index 32d60c7805dcf49a17c1585c610ce841c1bbf259..0c5fcd7cf7bdc598ff054a3567b8041a4d4731fc 100644 (file)
@@ -169,9 +169,7 @@ bool canRename(const ObjectPtr& theObject, const QString& theName)
 XGUI_Workshop* workshop(ModuleBase_IWorkshop* theWorkshop)
 {
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWorkshop);
-  if (aConnector)
-    return aConnector->workshop();
-  return 0;
+  return aConnector->workshop();
 }
 
 }
index 7ab372d24330ff7cac299451ddc78923c14be230..0ab1b602c030fa1f7308db8e4bdd260aee1a2311 100755 (executable)
@@ -508,7 +508,7 @@ void XGUI_Workshop::onAcceptActionClicked()
                                                     (anOperationMgr->currentOperation());
     if (aFOperation) {
       //if (errorMgr()->canProcessClick(anAction, aFOperation->feature()))
-      myOperationMgr->commitOperation();
+      myOperationMgr->onCommitOperation();
     }
   }
 }
@@ -776,6 +776,12 @@ void XGUI_Workshop::saveDocument(const QString& theName, std::list<std::string>&
   QApplication::restoreOverrideCursor();
 }
 
+//******************************************************
+bool XGUI_Workshop::abortAllOperations()
+{
+  return myOperationMgr->abortAllOperations();
+}
+
 //******************************************************
 void XGUI_Workshop::operationStarted(ModuleBase_Operation* theOperation)
 {
@@ -791,7 +797,7 @@ void XGUI_Workshop::operationStarted(ModuleBase_Operation* theOperation)
 //******************************************************
 void XGUI_Workshop::onOpen()
 {
-  if(!myOperationMgr->abortAllOperations())
+  if(!abortAllOperations())
     return;
   //save current file before close if modified
   SessionPtr aSession = ModelAPI_Session::get();
@@ -921,7 +927,7 @@ void XGUI_Workshop::onTrihedronVisibilityChanged(bool theState)
 //******************************************************
 bool XGUI_Workshop::onSave()
 {
-  if(!myOperationMgr->abortAllOperations(XGUI_OperationMgr::XGUI_InformationMessage))
+  if(!abortAllOperations())
     return false;
   if (myCurrentDir.isEmpty()) {
     return onSaveAs();
@@ -938,7 +944,7 @@ bool XGUI_Workshop::onSave()
 //******************************************************
 bool XGUI_Workshop::onSaveAs()
 {
-  if(!myOperationMgr->abortAllOperations(XGUI_OperationMgr::XGUI_InformationMessage))
+  if(!abortAllOperations())
     return false;
   QFileDialog dialog(desktop());
   dialog.setWindowTitle(tr("Select directory to save files..."));
@@ -1410,6 +1416,9 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked)
           aParameters.Append(aContext);
 
         MyVCallBack = new VInspector_CallBack();
+        MyTCommunicator->RegisterPlugin("TKDFBrowser");
+        MyTCommunicator->RegisterPlugin("TKVInspector");
+        MyTCommunicator->RegisterPlugin("TKShapeView");
         myDisplayer->setCallBack(MyVCallBack);
         #ifndef HAVE_SALOME
         AppElements_Viewer* aViewer = mainWindow()->viewer();
@@ -1469,7 +1478,7 @@ void XGUI_Workshop::deleteObjects()
   }
 
   QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
-  if (!myOperationMgr->abortAllOperations())
+  if (!abortAllOperations())
     return;
 
   bool hasResult = false;
@@ -1536,7 +1545,7 @@ void addRefsToFeature(const FeaturePtr& theFeature,
 //**************************************************************
 void XGUI_Workshop::cleanHistory()
 {
-  if (!myOperationMgr->abortAllOperations())
+  if (!abortAllOperations())
     return;
 
   QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
@@ -1662,7 +1671,7 @@ void XGUI_Workshop::cleanHistory()
 //**************************************************************
 void XGUI_Workshop::moveObjects()
 {
-  if (!myOperationMgr->abortAllOperations())
+  if (!abortAllOperations())
     return;
 
   SessionPtr aMgr = ModelAPI_Session::get();
@@ -1903,7 +1912,7 @@ void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects)
   if (aColor.size() != 3)
     return;
 
-  if (!myOperationMgr->abortAllOperations())
+  if (!abortAllOperations())
   return;
   // 2. show the dialog to change the value
   XGUI_ColorDialog* aDlg = new XGUI_ColorDialog(desktop());
@@ -1993,7 +2002,7 @@ void XGUI_Workshop::changeDeflection(const QObjectPtrList& theObjects)
   if (aDeflection < 0)
     return;
 
-  if (!myOperationMgr->abortAllOperations())
+  if (!abortAllOperations())
   return;
   // 2. show the dialog to change the value
   XGUI_DeflectionDialog* aDlg = new XGUI_DeflectionDialog(desktop());
@@ -2049,6 +2058,9 @@ void XGUI_Workshop::showOnlyObjects(const QObjectPtrList& theList)
     if (module()->canEraseObject(aObj))
       aObj->setDisplayed(false);
   }
+  //Do not use eraseAll if you didn't send Redisplay event:
+  //all objects are erased from viewer, but considered as displayed in displayer
+  // Problem in bug 2218
   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
 #ifdef HAVE_SALOME
     //issue #2159 Hide all incomplete behavior
index e275f8408c154679f69abc3b74e416202ab8ba58..0f0c350fd4cd455a1662df74bce6472c3e2881c8 100755 (executable)
@@ -265,11 +265,20 @@ Q_OBJECT
   */
   void saveDocument(const QString& theName, std::list<std::string>& theFileNames);
 
+  /**
+   * If there is an active (uncommitted) operation shows a prompt to abort it
+   * and performs abortion if user agreed. Returns true if
+   * - operation aborted successfully
+   * - there is no active operation
+   */
+  bool abortAllOperations();
+
   /// Updates workshop state according to the started operation, e.g. visualizes the property panel
   /// and connect to it.
   /// \param theOpertion a started operation
   void operationStarted(ModuleBase_Operation* theOperation);
 
+
   //! Delete features. Delete the referenced features. There can be a question with a list of
   //! referenced objects.
   //! \param theFeatures a list of objects to be deleted
index f5f2626e2d837da64177eb509dd4d95dce32d923..d1b34d181e594d4a0f0742629db393e22c41b380 100755 (executable)
@@ -43,8 +43,6 @@
 #include <ModelAPI_Result.h>
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Data.h>
-#include <ModelAPI_ResultBody.h>
-#include <ModelAPI_ResultGroup.h>
 #include <ModelAPI_ResultCompSolid.h>
 #include <ModelAPI_Tools.h>
 
@@ -254,9 +252,6 @@ void XGUI_WorkshopListener::
 
   XGUI_Workshop* aWorkshop = workshop();
   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
-  //bool aFirstVisualizedBody = false;
-  bool aDoFitAll = false;
-  int aNbOfShownObjects = workshop()->displayer()->objectsCount();
   bool aRedisplayed = false;
   //std::list<ObjectPtr> aHiddenObjects;
   for (aIt = anObjects.begin(); aIt != anObjects.end(); ++aIt) {
@@ -333,8 +328,6 @@ void XGUI_WorkshopListener::
         }
       } else { // display object if the current operation has it
         if (displayObject(aObj)) {
-          aDoFitAll = aDoFitAll || neededFitAll(aObj, aNbOfShownObjects);
-
           aRedisplayed = true;
           // Deactivate object of current operation from selection
           aWorkshop->deactivateActiveObject(aObj, false);
@@ -351,11 +344,7 @@ void XGUI_WorkshopListener::
   if (aRedisplayed || isCustomized) {
     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_EMPTY_AIS_PRESENTATION));
 
-    //VSV FitAll updated viewer by itself
-    if (aDoFitAll)
-      myWorkshop->viewer()->fitAll();
-    else
-      aDisplayer->updateViewer();
+    aDisplayer->updateViewer();
   }
 }
 
@@ -375,9 +364,6 @@ void XGUI_WorkshopListener::
     .arg(anObjects.size()).arg(anInfoStr).toStdString().c_str());
 #endif
 
-  bool aDoFitAll = false;
-  int aNbOfShownObjects = workshop()->displayer()->objectsCount();
-
   //bool aHasPart = false;
   bool aDisplayed = false;
   for (aIt = anObjects.begin(); aIt != anObjects.end(); ++aIt) {
@@ -416,8 +402,6 @@ void XGUI_WorkshopListener::
       if (myWorkshop->module()->canDisplayObject(anObject)) {
         anObject->setDisplayed(true);
         aDisplayed = displayObject(anObject);
-        if (aDisplayed)
-          aDoFitAll = aDoFitAll || neededFitAll(anObject, aNbOfShownObjects);
       } else
         anObject->setDisplayed(false);
     }
@@ -429,11 +413,7 @@ void XGUI_WorkshopListener::
   //  myObjectBrowser->processEvent(theMsg);
   if (aDisplayed) {
     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_EMPTY_AIS_PRESENTATION));
-    //VSV FitAll updated viewer by itself
-    if (aDoFitAll)
-      myWorkshop->viewer()->fitAll();
-    else
-      workshop()->displayer()->updateViewer();
+    workshop()->displayer()->updateViewer();
   }
   //if (aHasPart) { // TODO: Avoid activate last part on loading of document
   //  activateLastPart();
@@ -505,25 +485,6 @@ bool XGUI_WorkshopListener::displayObject(ObjectPtr theObj)
   return aDisplayer->display(theObj, false);
 }
 
-//**************************************************************
-bool XGUI_WorkshopListener::neededFitAll(ObjectPtr theObj, const int theNbOfShownObjects)
-{
-  bool aFirstVisualizedBody = false;
-
-  if (theNbOfShownObjects == 0) {
-    ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObj);
-    if (aResult.get()) {
-      std::string aResultGroupName = aResult->groupName();
-      if (aResultGroupName == ModelAPI_ResultBody::group() ||
-          aResultGroupName == ModelAPI_ResultGroup::group()) {
-        std::shared_ptr<GeomAPI_Shape> aShapePtr = ModelAPI_Tools::shape(aResult);
-        aFirstVisualizedBody = aShapePtr.get() != NULL;
-      }
-    }
-  }
-  return aFirstVisualizedBody;
-}
-
 bool XGUI_WorkshopListener::customizeCurrentObject(const std::set<ObjectPtr>& theObjects,
                                                    bool theForceRedisplay)
 {
index 486d8f88903f36a150cfd084ab09c4e6abb2e336..c338535bdefd2205599700d8bd56ced599f6142e 100755 (executable)
@@ -91,13 +91,6 @@ protected:
   /// \return true if the object is displayed
   bool displayObject(ObjectPtr theObj);
 
-  /// Answer if the viewer needed to be fit all after the object visualization
-  /// The condition is there is not shown objects and the object is a group or body result
-  /// \param theObject a shown object
-  /// \param theNbOfShownObjects a count of already shown objects in the viewer
-  /// \return true if fit all should be done
-  bool neededFitAll(ObjectPtr theObject, const int theNbOfShownObjects);
-
   /// Calls the module method of cusomize object for the feature of the current operation
   /// Perform cusomize if the force redisplay flag is true or the list of objects contains the
   /// current operation feature
index 80c612aac85c6eeff6e926e52992a05859531923..9b1f8cd6c5eebe697bb9af92083507e3956bb26c 100644 (file)
@@ -27,10 +27,19 @@ ADD_UNIT_TESTS_API(
   Primitives/TestAPI_Cylinder.py
   GDML/TestConeSegment.py
   GDML/TestAPI_ConeSegment.py
-  Transformations/TestScale.py
-  Transformations/TestSymmetry.py
-  Transformations/TestTranslation.py
+  Transformations/TestAPI_MultiTranslation.py
+  Transformations/TestAPI_Rotation.py
   Transformations/TestAPI_Scale.py
   Transformations/TestAPI_Symmetry.py
   Transformations/TestAPI_Translation.py
+  Transformations/TestMultiTranslation.py
+  Transformations/TestRotation.py
+  Transformations/TestScale.py
+  Transformations/TestSymmetry.py
+  Transformations/TestTranslation_1.py
+  Transformations/TestTranslation_2.py
+  Transformations/TestTranslation_3.py
+  Transformations/TestTranslation_4.py
+  Transformations/TestTranslation_5.py
+  Transformations/TestTranslation.py
 )
index 0219872b60b7a681477ba3ecfafe614052e34918..5577a9654c1e730857e431af90e86316504abc76 100644 (file)
@@ -188,7 +188,8 @@ Translation_13 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "
 Translation_14 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "MultiTranslation_5_1")], model.selection("EDGE", "PartSet/OZ"), "d")
 Translation_15 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "MultiTranslation_6_1")], model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), 50)
 Translation_16 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "MultiTranslation_7_1")], model.selection("EDGE", "Edge_1_1"), 50)
-Translation_17 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "MultiTranslation_8_1")], model.selection("EDGE", "MultiTranslation_8_1/Translated_Edge_8_8"), 50)
+#Translation_17 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "MultiTranslation_8_1")], model.selection("EDGE", "MultiTranslation_8_1/Translated_Edge_8_8"), 50)
+Translation_17 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "MultiTranslation_8_1")], model.selection("EDGE", "MultiTranslation_8_1/Translated_Face_3_4&MultiTranslation_8_1/Translated_Face_3_1"), 50)
 Translation_18 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "MultiTranslation_9_1")], model.selection("EDGE", "PartSet/Axis_4"), 50)
 Translation_19 = model.addTranslation(partSet, [model.selection("COMPOUND", "Part_2/")], model.selection("EDGE", "OX"), 15)
 Translation_20 = model.addTranslation(partSet, [model.selection("COMPOUND", "Part_3/")], model.selection("EDGE", "OX"), 0)
index e68805e9ad7b3abea1e067a3b94e91096d3117d7..327b8e741ccd25be359cff69b3b91477c2c4889d 100644 (file)
@@ -164,7 +164,7 @@ Translation_41_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "B
 Partition_6 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_30_1"), model.selection("SOLID", "Translation_29_1")])
 Translation_41 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Partition_6_1")], model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), 15)
 
-# Translateion 42
+# Translation 42
 Translation_42_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_31_1")], model.selection("EDGE", "PartSet/OX"), 5)
 Partition_7 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_32_1"), model.selection("SOLID", "Translation_31_1")])
 Translation_42 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Partition_7_1")], model.selection("EDGE", "Edge_1_1"), 15)
@@ -172,7 +172,7 @@ Translation_42 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID",
 # Translation 43
 Translation_43_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_33_1")], model.selection("EDGE", "PartSet/OX"), 5)
 Partition_8 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_34_1"), model.selection("SOLID", "Translation_33_1")])
-Translation_43 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Partition_8_1")], model.selection("EDGE", "Partition_8_1/Modified_Face_1_1_1&Partition_8_1/Modified_Face_1_9_1"), 15)
+Translation_43 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Partition_8_1")], model.selection("EDGE", "Partition_8_1_1/Modified_Face_1_4&Partition_8_1_1/Modified_Face_1_1"), 15)
 
 # Translation 44
 Translation_44_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_35_1")], model.selection("EDGE", "PartSet/OX"), 5)
@@ -181,99 +181,64 @@ Translation_44 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID",
 model.do()
 model.end()
 
-
 # Checks
 from GeomAPI import GeomAPI_Shape
-from GeomAPI import GeomAPI_ShapeExplorer
-
-def testHaveNamingEdges(theFeature, theModel, thePartDoc) :
-  """ Tests if all faces of result have a name
-  :param theFeature: feature to test.
-  """
-  # Get feature result/sub-result
-  aResult = theFeature.results()[0].resultSubShapePair()[0]
-  # Get result/sub-result shape
-  shape = aResult.shape()
-  # Create shape explorer with desired shape type
-  shapeExplorer = GeomAPI_ShapeExplorer(shape, GeomAPI_Shape.EDGE)
-  # Create list, and store selections in it
-  selectionList = []
-  while shapeExplorer.more():
-    selection = theModel.selection(aResult, shapeExplorer.current()) # First argument should be result/sub-result, second is sub-shape on this result/sub-result
-    selectionList.append(selection)
-    shapeExplorer.next()
-  # Create group with this selection list
-  Group_1 = theModel.addGroup(thePartDoc, selectionList)
-  theModel.do()
-  theModel.end()
-
-  # Now you can check that all selected shapes in group have right shape type and name.
-  groupFeature = Group_1.feature()
-  groupSelectionList = groupFeature.selectionList("group_list")
-  theModel.end()
-  assert(groupSelectionList.size() == len(selectionList))
-  for index in range(0, groupSelectionList.size()):
-    attrSelection = groupSelectionList.value(index)
-    shape = attrSelection.value()
-    name = attrSelection.namingName()
-    assert(shape.isEdge())
-    assert(name != ""), "String empty"
 
 # Translation 27
 model.testNbResults(Translation_27, 1)
 model.testNbSubResults(Translation_27, [12])
 model.testNbSubShapes(Translation_27, GeomAPI_Shape.SOLID, [0])
 model.testNbSubShapes(Translation_27, GeomAPI_Shape.EDGE, [12])
-testHaveNamingEdges(Translation_27, model, Part_1_doc)
+model.testHaveNamingEdges(Translation_27, model, Part_1_doc)
 
 # Translation 28
 model.testNbResults(Translation_28, 1)
 model.testNbSubResults(Translation_28, [12])
 model.testNbSubShapes(Translation_28, GeomAPI_Shape.SOLID, [0])
 model.testNbSubShapes(Translation_28, GeomAPI_Shape.EDGE, [12])
-testHaveNamingEdges(Translation_28, model, Part_1_doc)
+model.testHaveNamingEdges(Translation_28, model, Part_1_doc)
 
 # Translation 29
 model.testNbResults(Translation_29, 1)
 model.testNbSubResults(Translation_29, [12])
 model.testNbSubShapes(Translation_29, GeomAPI_Shape.SOLID, [0])
 model.testNbSubShapes(Translation_29, GeomAPI_Shape.EDGE, [12])
-testHaveNamingEdges(Translation_29, model, Part_1_doc)
+model.testHaveNamingEdges(Translation_29, model, Part_1_doc)
 
 # Translation 31
 model.testNbResults(Translation_31, 1)
 model.testNbSubResults(Translation_31, [12])
 model.testNbSubShapes(Translation_31, GeomAPI_Shape.SOLID, [0])
 model.testNbSubShapes(Translation_31, GeomAPI_Shape.EDGE, [12])
-testHaveNamingEdges(Translation_31, model, Part_1_doc)
+model.testHaveNamingEdges(Translation_31, model, Part_1_doc)
 
 # Translation 32
 model.testNbResults(Translation_32, 1)
 model.testNbSubResults(Translation_32, [12])
 model.testNbSubShapes(Translation_32, GeomAPI_Shape.SOLID, [0])
 model.testNbSubShapes(Translation_32, GeomAPI_Shape.EDGE, [12])
-testHaveNamingEdges(Translation_32, model, Part_1_doc)
+model.testHaveNamingEdges(Translation_32, model, Part_1_doc)
 
 # Translation 33
 model.testNbResults(Translation_33, 1)
 model.testNbSubResults(Translation_33, [12])
 model.testNbSubShapes(Translation_33, GeomAPI_Shape.SOLID, [0])
 model.testNbSubShapes(Translation_33, GeomAPI_Shape.EDGE, [12])
-testHaveNamingEdges(Translation_33, model, Part_1_doc)
+model.testHaveNamingEdges(Translation_33, model, Part_1_doc)
 
 # Translation 34
 model.testNbResults(Translation_34, 1)
 model.testNbSubResults(Translation_34, [12])
 model.testNbSubShapes(Translation_34, GeomAPI_Shape.SOLID, [0])
 model.testNbSubShapes(Translation_34, GeomAPI_Shape.EDGE, [12])
-testHaveNamingEdges(Translation_34, model, Part_1_doc)
+model.testHaveNamingEdges(Translation_34, model, Part_1_doc)
 
 # Translation 35
 model.testNbResults(Translation_35, 1)
 model.testNbSubResults(Translation_35, [12])
 model.testNbSubShapes(Translation_35, GeomAPI_Shape.SOLID, [0])
 model.testNbSubShapes(Translation_35, GeomAPI_Shape.EDGE, [12])
-testHaveNamingEdges(Translation_35, model, Part_1_doc)
+model.testHaveNamingEdges(Translation_35, model, Part_1_doc)
 
 # Translation 36
 model.testNbResults(Translation_36, 1)
index 6ffe39aa3b2e95a5ae9bbf16d8d9be43fc70a2ac..372a26a4c88e387f3e115f87be926153e7fb20be 100644 (file)
@@ -434,7 +434,7 @@ Extrusion_3 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_3/
 Boolean_1 = model.addSmash(Part_1_doc, [model.selection("SOLID", "Extrusion_3_1")], [model.selection("SOLID", "ExtrusionCut_4_1")])
 ExtrusionCut_5 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_3/Wire-SketchCircle_8_2f")], model.selection(), 10, 0, [model.selection("SOLID", "Boolean_1_1_1")])
 ExtrusionCut_6 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchCircle_8_2f")], model.selection(), 10, 0, [model.selection("SOLID", "ExtrusionCut_5_1_1")])
-Axis_4 = model.addAxis(Part_1_doc, model.selection("FACE", "ExtrusionCut_6_1/Modfied_1"))
+Axis_4 = model.addAxis(Part_1_doc, model.selection("FACE", "ExtrusionCut_6_1_2/Modfied_1"))
 Sketch_4 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
 SketchProjection_7 = Sketch_4.addProjection(model.selection("EDGE", "PartSet/OY"))
 SketchLine_28 = SketchProjection_7.createdFeature()
@@ -522,7 +522,7 @@ Extrusion_4 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_4/
 Boolean_2 = model.addSmash(Part_1_doc, [model.selection("SOLID", "ExtrusionCut_6_1_1"), model.selection("SOLID", "Extrusion_4_1")], [model.selection("SOLID", "ExtrusionCut_6_1_2")])
 ExtrusionCut_7 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_4/Face-SketchCircle_9_2f")], model.selection(), 0, 10, [model.selection("SOLID", "Boolean_2_1_1")])
 ExtrusionCut_8 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_4/Face-SketchCircle_9_2f")], model.selection(), 0, 10, [model.selection("SOLID", "ExtrusionCut_7_1_1")])
-Sketch_5 = model.addSketch(Part_1_doc, model.selection("FACE", "Boolean_2_1/Modified_1"))
+Sketch_5 = model.addSketch(Part_1_doc, model.selection("FACE", "Boolean_2_1_1/Modified_1"))
 SketchPoint_3 = Sketch_5.addPoint(model.selection("VERTEX", "PartSet/Origin"))
 SketchPoint_3.setName("SketchPoint_2")
 SketchPoint_3.result().setName("SketchPoint_2")