Salome HOME
Merge remote-tracking branch 'remotes/origin/occ/compounds_processing' V9_5_0a1
authorazv <azv@opencascade.com>
Wed, 26 Feb 2020 13:22:38 +0000 (16:22 +0300)
committerazv <azv@opencascade.com>
Wed, 26 Feb 2020 13:22:38 +0000 (16:22 +0300)
# Conflicts:
# src/FeaturesPlugin/CMakeLists.txt

96 files changed:
CMakeLists.txt
build_Salome_deb.bat
doc/gui/Introduction.rst
env.sh
env_Salome.bat
salomeRun_deb.bat
src/CollectionPlugin/CMakeLists.txt
src/CollectionPlugin/Test/Test18739.py [new file with mode: 0644]
src/Config/Config_WidgetAPI.cpp
src/Config/Config_WidgetAPI.h
src/ConnectorAPI/Test/TestShaperStudy1.py [new file with mode: 0644]
src/ConnectorAPI/Test/TestShaperStudy2.py [new file with mode: 0644]
src/ConnectorAPI/Test/TestShaperStudy3.py [new file with mode: 0644]
src/ConnectorAPI/Test/tests.set
src/ConnectorPlugin/CMakeLists.txt
src/ConnectorPlugin/ConnectorPlugin.py
src/ConnectorPlugin/ConnectorPlugin_PublishToStudyFeature.py [new file with mode: 0644]
src/ConnectorPlugin/plugin-Connector.xml
src/ExchangeAPI/ExchangeAPI_Export.cpp
src/ExchangePlugin/CMakeLists.txt
src/ExchangePlugin/ExchangePlugin_Dump.cpp
src/ExchangePlugin/ExchangePlugin_Dump.h
src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp
src/ExchangePlugin/ExchangePlugin_ExportFeature.h
src/ExchangePlugin/ExchangePlugin_Import.cpp [new file with mode: 0644]
src/ExchangePlugin/ExchangePlugin_Import.h [new file with mode: 0644]
src/ExchangePlugin/ExchangePlugin_Plugin.cpp
src/ExchangePlugin/Test/Test18710.py [new file with mode: 0644]
src/ExchangePlugin/plugin-Exchange.xml
src/FeaturesPlugin/CMakeLists.txt
src/FeaturesPlugin/Test/Test2918.py [new file with mode: 0644]
src/FiltersAPI/FiltersAPI_Feature.cpp
src/FiltersPlugin/CMakeLists.txt
src/FiltersPlugin/FiltersPlugin_OnLine.h
src/FiltersPlugin/FiltersPlugin_OnPlane.h
src/FiltersPlugin/FiltersPlugin_OnPlaneSide.h
src/FiltersPlugin/FiltersPlugin_RelativeToSolid.h
src/FiltersPlugin/FiltersPlugin_Selection.cpp
src/FiltersPlugin/FiltersPlugin_Selection.h
src/FiltersPlugin/FiltersPlugin_TopoConnectedFaces.py
src/FiltersPlugin/Test/TestFilter_OnLine_Multi.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_OnPlaneSide_Multi.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_OnPlane_Multi.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_RelativeToSolid_Multi.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Multi.py [new file with mode: 0644]
src/FiltersPlugin/doc/FiltersPlugin.rst
src/GeomAPI/GeomAPI_AISObject.cpp
src/GeomAPI/GeomAPI_Shape.cpp
src/GeomAPI/GeomAPI_Shape.h
src/Model/Model_AttributeSelection.cpp
src/Model/Model_AttributeSelectionList.cpp
src/Model/Model_AttributeSelectionList.h
src/Model/Model_BodyBuilder.cpp
src/Model/Model_Data.cpp
src/Model/Model_FiltersFactory.cpp
src/Model/Model_Objects.cpp
src/Model/Model_ResultBody.cpp
src/Model/Model_ResultPart.cpp
src/ModelAPI/ModelAPI_AttributeSelectionList.h
src/ModelAPI/ModelAPI_Filter.h
src/ModelAPI/ModelAPI_FiltersFeature.h
src/ModelAPI/ModelAPI_Result.cpp
src/ModelAPI/ModelAPI_Result.h
src/ModelAPI/ModelAPI_Tools.cpp
src/ModelAPI/ModelAPI_Tools.h
src/ModelHighAPI/ModelHighAPI_Dumper.cpp
src/ModelHighAPI/ModelHighAPI_Dumper.h
src/ModuleBase/ModuleBase_ResultPrs.cpp
src/ModuleBase/ModuleBase_ResultPrs.h
src/ModuleBase/ModuleBase_WidgetFactory.cpp
src/ModuleBase/ModuleBase_WidgetFactory.h
src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp
src/ModuleBase/ModuleBase_WidgetSelectionFilter.h
src/PartSet/PartSet_OperationPrs.cpp
src/PartSet/PartSet_SketcherMgr.cpp
src/PythonAPI/model/dump/DumpAssistant.py
src/PythonAPI/model/services/__init__.py
src/SHAPERGUI/SHAPERGUI.cpp
src/SHAPERGUI/SHAPERGUI.h
src/SHAPERGUI/SHAPERGUI_DataModel.cpp
src/SketchPlugin/CMakeLists.txt
src/SketchPlugin/SketchPlugin_Validators.cpp
src/SketchPlugin/Test/Test3154.py [new file with mode: 0755]
src/XAO/CMakeLists.txt
src/XGUI/XGUI_ColorDialog.cpp
src/XGUI/XGUI_ContextMenuMgr.cpp
src/XGUI/XGUI_DeflectionDialog.cpp
src/XGUI/XGUI_Displayer.cpp
src/XGUI/XGUI_PropertyDialog.cpp
src/XGUI/XGUI_SalomeConnector.h
src/XGUI/XGUI_ViewerProxy.cpp
src/XGUI/XGUI_Workshop.cpp
src/XGUI/XGUI_Workshop.h
src/XGUI/XGUI_msg_fr.ts
src/XGUI/XGUI_pictures.qrc
src/XGUI/pictures/iso_lines.png [new file with mode: 0644]

index c63a22307b8a5cfe57f62eec4202265d439c847a..1b7e24ed3227ac9502f5785083b7225102043984 100644 (file)
@@ -97,6 +97,7 @@ IF(${HAVE_SALOME})
     SET(SHAPER_INSTALL_BIN lib/salome CACHE INTERNAL "" FORCE)
     SET(SHAPER_INSTALL_PLUGIN_FILES lib/salome CACHE INTERNAL "" FORCE)
     SET(SHAPER_INSTALL_PYTHON_FILES bin/salome CACHE INTERNAL "" FORCE)
+    SET(SHAPER_INSTALL_HEADERS include/salome CACHE INTERNAL "" FORCE)
     SET(SHAPER_INSTALL_RESOURCES share/salome/resources/shaper CACHE INTERNAL "" FORCE)
     SET(SHAPER_INSTALL_QM_RESOURCES share/salome/resources/shaper CACHE INTERNAL "" FORCE)
     SET(SHAPER_INSTALL_XML_RESOURCES share/salome/resources/shaper CACHE INTERNAL "" FORCE)
@@ -108,6 +109,7 @@ IF(${HAVE_SALOME})
 ELSE(${HAVE_SALOME})
     SET(SHAPER_INSTALL_ADDONS addons CACHE INTERNAL "" FORCE)
     SET(SHAPER_INSTALL_BIN bin CACHE INTERNAL "" FORCE)
+    SET(SHAPER_INSTALL_HEADERS include CACHE INTERNAL "" FORCE)
     SET(SHAPER_INSTALL_PLUGIN_FILES plugins CACHE INTERNAL "" FORCE)
     SET(SHAPER_INSTALL_PYTHON_FILES plugins CACHE INTERNAL "" FORCE)
     SET(SHAPER_INSTALL_RESOURCES resources CACHE INTERNAL "" FORCE)
index a65baa442e0369a644a66f8c65a4a0e23a1dd514..985249431aff37db10550c3ed6a8d71beb7c8dcc 100644 (file)
@@ -10,11 +10,11 @@ popd
 @SET SRC_DIR=%ROOT_DIR%\sources
 @SET OCC_LIB_PREFIX=d
 
-call %SRC_DIR%\env_Salome.bat d
+call %SRC_DIR%\env_Salome.bat d comp
 mkdir %ROOT_DIR%\build
 cd %ROOT_DIR%\build
 
 REM Add -DADD_MODELS_TESTS=TRUE to enable test models
-cmake %SRC_DIR% -G "Visual Studio 14 Win64" -DPYTHON_EXECUTABLE=%PYTHONHOME%\python_d.exe -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX:PATH=%ROOT_DIR%\install
+cmake %SRC_DIR% -G "Visual Studio 15 Win64" -DPYTHON_EXECUTABLE=%PYTHONHOME%\python_d.exe -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX:PATH=%ROOT_DIR%\install
 
 start "" %MSVC_EXE% SHAPER.sln
index 0e493c4e7cd4ac6cb2343df93d68a5bb129c7ef8..75e0508bdd6e8105b85d92651dc06a52a8b3ccde 100644 (file)
@@ -627,7 +627,7 @@ Sketch tab defines properties of coordinate planes shown for selection of sketch
 - **Angular tolerance** defines defines an angular tolerance for automatic creation of horizontal and vertical constraints;\r
 - **Default spline weight** defines default weight for B-spline nodes during creation. The default value can be changed by editing of the spline;\r
 - **Cursor for sketch operation** defines a cursor which indicates a launched sketcher sub-operation.\r
-- **Create sketch entities by dragging** defines a style of sketche etities creation. It concerns creation of lines, rectangles, circles, arcs, ellipses, elliptic arcs. If it is switched ON then points of objects has to be defined by mouse press - mouse move - mouse rellease. Otherwise every point of an object has to be defined by mouse click;\r
+- **Create sketch entities by dragging** defines a style of sketch etities creation. It concerns creation of lines, rectangles, circles, arcs, ellipses, elliptic arcs. If it is switched ON then points of objects have to be defined by mouse press - mouse move - mouse release. Otherwise every point of an object has to be defined by mouse click;\r
 \r
    \r
 .. _viewer_preferences:\r
diff --git a/env.sh b/env.sh
index 1b7c6dadab916a1003e722085627c844e3be2174..cdaec7021c072d3b3b43c3534d669b49cae1535e 100644 (file)
--- a/env.sh
+++ b/env.sh
@@ -1,6 +1,6 @@
 #!/bin/bash -x
 
-export SALOME_DIR=/dn46/SALOME/series9x/current-2020-02-03
+export SALOME_DIR=/dn46/SALOME/series9x/current-2020-02-26
 
 # Path to sources
 export SOURCES_DIR=$(pwd)
index 57d9e32f6d3ad673c0ee8cf54677fee9d9556586..83c073b3447c49110cfd279a1778daf80708b1a5 100644 (file)
@@ -16,11 +16,6 @@ if "%SALOME_ROOT_DIR%" == "" (
   set SALOME_ROOT_DIR=%ROOT_DIR%\SALOME
 )
 
-if "%SOLVESPACE_ROOT_DIR%" == "" (
-  SET SOLVESPACE_ROOT_DIR=%SALOME_ROOT_DIR%\PRODUCTS%OCC_LIB_PREFIX%\solvespace-2.1
-)
-SET PATH=%SOLVESPACE_ROOT_DIR%\lib;%PATH%
-
 if "%PLANEGCS_ROOT_DIR%" == "" (
   SET PLANEGCS_ROOT_DIR=%SALOME_ROOT_DIR%\PRODUCTS%OCC_LIB_PREFIX%\planegcs-0.18
 )
@@ -40,7 +35,13 @@ if "%BOOST_ROOT_DIR%" == "" (
 
 cd /d %SALOME_ROOT_DIR%\WORK
 call set_env.bat %1
-call "%PDIR%\env_compile.bat"
+
+if "%2" == run (
+  call "%PDIR%\env_launch.bat"
+) else (
+  call "%PDIR%\env_compile.bat"
+)
+
 cd /d %ROOT_DIR%
 
 @REM -------------------------
@@ -85,19 +86,18 @@ cd /d %ROOT_DIR%
 
 @SET _NO_DEBUG_HEAP=1
 
-if "%VS140COMNTOOLS%" == "" (
-    echo Could not find MS Visual Studio: variable VS140COMNTOOLS is not defined!
-    exit 1
-) else if exist "%VS140COMNTOOLS%\..\IDE\devenv.exe" (
-    set MSVC_EXE="%VS140COMNTOOLS%\..\IDE\devenv.exe"
-) else if exist "%VS140COMNTOOLS%\..\IDE\VCExpress.exe" (
-    set MSVC_EXE="%VS140COMNTOOLS%\..\IDE\VCExpress.exe"
+@SET VC_VERSION_SHORT=15
+for /f "tokens=1,2*" %%a in ('reg query "HKLM\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SxS\VS7" /v "%VC_VERSION_SHORT%.0" 2^>nul') do set "VSPATH=%%c"
+IF NOT EXIST "%VSPATH%\VC\Auxiliary\Build\vcvarsall.bat" GOTO ERROR1
+
+if exist "%VSPATH%\Common7\IDE\devenv.exe"  (
+  SET msvc_exe=devenv
+) else if exist "%VSPATH%\Common7\IDE\VCExpress.exe"  (
+  SET msvc_exe=VCExpress
 ) else (
-    echo "Could not find MS Visual Studio in %VS140COMNTOOLS%\..\IDE"
-    echo Check environment variable VS140COMNTOOLS!
-    exit 1
+  GOTO ERROR1
 )
-call "%VS140COMNTOOLS%..\Tools\vsvars32.bat"
+call "%VSPATH%\VC\Auxiliary\Build\vcvarsall.bat" x64 > NUL
 
 @SET SHAPER_ROOT_DIR=%ROOT_DIR%\install
 @SET PATH=%SHAPER_ROOT_DIR%\lib\salome;%PATH%
@@ -105,3 +105,10 @@ REM @SET PYTHONPATH=%SHAPER_ROOT_DIR%\lib\python2.7\site-packages\salome\salome;
 REM @SET PYTHONPATH=%SHAPER_ROOT_DIR%\bin\salome;%PYTHONPATH%
 
 @SET LightAppConfig=%SHAPER_ROOT_DIR%\share\salome\resources\shaper;%GUI_ROOT_DIR%\share\salome\resources\gui
+
+goto END
+
+:ERROR1
+ECHO "Visual Studio environment file is not found."
+
+:END
index 17e988d5561f14898566f99b13c4ea519d4ab4fa..5534c345ce059291fb2514d36701ddbd1658f51e 100644 (file)
@@ -8,7 +8,7 @@ pushd %PARENT_DIR%
 popd
 
 @SET OCC_LIB_PREFIX=d
-call env_Salome.bat d
+call env_Salome.bat d run
 
 rem Variable which is necessary for launching SALOME
 SET SALOME_PLEASE_SETUP_ENVIRONMENT_AS_BEFORE=1
index 3e3c164639a5c5dd7f448f47b0e40900e8154641..e13a28446d23377c78b62132680e8888db9017dc 100644 (file)
@@ -164,4 +164,5 @@ ADD_UNIT_TESTS(
                TestGroupMoveAndSplit2.py
                TestGroupMoveAndSplit3.py
                Test3114.py
+               Test18739.py
 )
diff --git a/src/CollectionPlugin/Test/Test18739.py b/src/CollectionPlugin/Test/Test18739.py
new file mode 100644 (file)
index 0000000..54b3568
--- /dev/null
@@ -0,0 +1,47 @@
+# Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+# Test of move to the end and split on LinearCopy: check that order in result is correct
+
+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, "d", "8")
+model.addParameter(Part_1_doc, "nb", "3")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_1.addCircle(-34, 28, 1)
+SketchCircle_2 = Sketch_1.addCircle(-34, 28, 3)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchCircle_1.center(), SketchCircle_2.center())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_1/Face-SketchCircle_2_2f-SketchCircle_1_2r_wire_2")], model.selection(), 2, -1)
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_1/Face-SketchCircle_2_2f-SketchCircle_1_2r_wire")], model.selection(), 5, 0)
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("COMPOUND", "all-in-Extrusion_1"), model.selection("COMPOUND", "all-in-Extrusion_2")])
+Group_1 = model.addGroup(Part_1_doc, "Solids", [model.selection("SOLID", "Partition_1_1_1")])
+LinearCopy_1 = model.addMultiTranslation(Part_1_doc, [model.selection("COMPSOLID", "Partition_1_1")], model.selection("EDGE", "PartSet/OX"), "d", "nb", model.selection("EDGE", "PartSet/OY"), "d", "nb")
+model.do()
+Part_1_doc.moveFeature(Group_1.feature(), LinearCopy_1.feature(), True)
+model.end()
+
+for a in range(9):
+  aGroup = Part_1_doc.objectByName("Features", "Group_1_" + str(a + 1))
+  aSelName = aGroup.data().selectionList("group_list").value(0).context().data().name()
+  assert(aSelName == "LinearCopy_1_1_" + str(a + 1) + "_1")
index cc1dfa98629fbcf9116bdee0297b621728861d3b..5ca092bf8f198429b7760371005e9770bc0c5ec1 100644 (file)
 
 #include <string>
 
-Config_WidgetAPI::Config_WidgetAPI(std::string theRawXml)
+Config_WidgetAPI::Config_WidgetAPI(std::string theRawXml, const std::string theAttributePrefix)
 {
   myDoc = xmlParseDoc(BAD_CAST theRawXml.c_str());
   myCurrentNode = xmlDocGetRootElement(myDoc);
   myFeatureId = getProperty(_ID);
+  myAttributePrefix = theAttributePrefix;
 }
 
 Config_WidgetAPI::~Config_WidgetAPI()
@@ -119,7 +120,7 @@ std::string Config_WidgetAPI::featureId() const
 
 std::string Config_WidgetAPI::widgetId() const
 {
-  return getProperty(_ID);
+  return myAttributePrefix + getProperty(_ID);
 }
 
 std::string Config_WidgetAPI::widgetIcon() const
index 055097cb7a2e9f1ea382950e340a0e451e489cee..6ef588bd6cff7cfab417f8bb06e53a744c5e278d 100644 (file)
@@ -78,7 +78,7 @@ class Config_WidgetAPI
   CONFIG_EXPORT bool getBooleanAttribute(const char* theAttributeName, bool theDefault) const;
 
   /// These fields are accessible for ModuleBase_WidgetFactory only
-  CONFIG_EXPORT Config_WidgetAPI(std::string theRawXml);
+  CONFIG_EXPORT Config_WidgetAPI(std::string theRawXml, const std::string theAttributePrefix = "");
   //! Pass to the next (sibling) node of widget's xml definition. If impossible, returns false
   CONFIG_EXPORT bool toNextWidget();
   //! Pass into the child node of widget's xml definition. If impossible, returns false
@@ -90,6 +90,7 @@ class Config_WidgetAPI
   xmlDocPtr myDoc; //!< Pointer to the root of widget's xml definition
   xmlNodePtr myCurrentNode; //!< Pointer to the current node in the widget's xml definition
   std::string myFeatureId;
+  std::string myAttributePrefix; //!< prefix that must be added to the attribute name
 
   friend class ModuleBase_WidgetFactory;
 };
diff --git a/src/ConnectorAPI/Test/TestShaperStudy1.py b/src/ConnectorAPI/Test/TestShaperStudy1.py
new file mode 100644 (file)
index 0000000..870278a
--- /dev/null
@@ -0,0 +1,161 @@
+# Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+import sys
+import salome
+
+salome.salome_init()
+
+###
+### SHAPER component
+###
+
+from SketchAPI 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, "r", "15")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_1.addCircle(25, 25, 15)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchCircle_1.center(), SketchAPI_Point(SketchPoint_1).coordinates(), 25)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchCircle_1.center(), SketchAPI_Point(SketchPoint_1).coordinates(), 25)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], "r")
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2r")], model.selection(), 10, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Sketch_2 = model.addSketch(Part_2_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_2.addLine(-5.176380902051512, 19.31851652579896, 19.31851652579829, -5.176380902058602)
+SketchLine_2 = Sketch_2.addLine(19.31851652579829, -5.176380902058602, -14.14213562374638, -14.14213562374059)
+SketchConstraintCoincidence_1 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(-14.14213562374638, -14.14213562374059, -5.176380902051512, 19.31851652579896)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintEqual_2 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_2.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintDistance_1 = Sketch_2.setDistance(SketchLine_2.startPoint(), SketchAPI_Point(SketchPoint_2).coordinates(), 20, True)
+SketchConstraintDistance_2 = Sketch_2.setDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_2).coordinates(), 20, True)
+SketchConstraintDistance_3 = Sketch_2.setDistance(SketchLine_3.startPoint(), SketchAPI_Point(SketchPoint_2).coordinates(), 20, True)
+SketchProjection_3 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_4 = SketchProjection_3.createdFeature()
+SketchConstraintAngle_1 = Sketch_2.setAngle(SketchLine_3.result(), SketchLine_4.result(), 75)
+model.do()
+Extrusion_2 = model.addExtrusion(Part_2_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_3r-SketchLine_2r-SketchLine_1r")], model.selection(), 30, 0)
+Fillet_1 = model.addFillet(Part_2_doc, [model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3][Extrusion_1_1/To_Face]")], 2)
+model.do()
+
+Part_3 = model.addPart(partSet)
+Part_3_doc = Part_3.document()
+Sketch_3 = model.addSketch(Part_3_doc, model.defaultPlane("XOZ"))
+SketchLine_5 = Sketch_3.addLine(52.5, 35, 22.5, 35)
+SketchLine_6 = Sketch_3.addLine(22.5, 35, 22.5, 15)
+SketchLine_7 = Sketch_3.addLine(22.5, 15, 52.5, 15)
+SketchLine_8 = Sketch_3.addLine(52.5, 15, 52.5, 35)
+SketchConstraintCoincidence_4 = Sketch_3.setCoincident(SketchLine_8.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_5 = Sketch_3.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_6 = Sketch_3.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_7 = Sketch_3.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintHorizontal_1 = Sketch_3.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_1 = Sketch_3.setVertical(SketchLine_6.result())
+SketchConstraintHorizontal_2 = Sketch_3.setHorizontal(SketchLine_7.result())
+SketchConstraintVertical_2 = Sketch_3.setVertical(SketchLine_8.result())
+SketchLine_9 = Sketch_3.addLine(0, 0, 52.5, 35)
+SketchLine_9.setAuxiliary(True)
+SketchProjection_4 = Sketch_3.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_3 = SketchProjection_4.createdFeature()
+SketchConstraintCoincidence_8 = Sketch_3.setCoincident(SketchLine_9.startPoint(), SketchPoint_3.result())
+SketchConstraintCoincidence_9 = Sketch_3.setCoincident(SketchLine_5.startPoint(), SketchLine_9.endPoint())
+SketchConstraintCoincidence_10 = Sketch_3.setCoincident(SketchLine_6.endPoint(), SketchLine_9.result())
+SketchConstraintLength_1 = Sketch_3.setLength(SketchLine_8.result(), 20)
+SketchConstraintLength_2 = Sketch_3.setLength(SketchLine_5.result(), 30)
+SketchConstraintDistanceVertical_2 = Sketch_3.setVerticalDistance(SketchLine_7.endPoint(), SketchAPI_Point(SketchPoint_3).coordinates(), 15)
+model.do()
+Revolution_1 = model.addRevolution(Part_3_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f")], model.selection("EDGE", "PartSet/OX"), 45, 0)
+model.end()
+
+###
+### SHAPERSTUDY component
+###
+
+if 'model' in globals():
+  model.publishToShaperStudy()
+import SHAPERSTUDY
+Extrusion_1_1, = SHAPERSTUDY.shape(model.featureStringId(Extrusion_1))
+Fillet_1_1, = SHAPERSTUDY.shape(model.featureStringId(Fillet_1))
+Revolution_1_1, = SHAPERSTUDY.shape(model.featureStringId(Revolution_1))
+###
+### SMESH component
+###
+
+import  SMESH, SALOMEDS
+from salome.smesh import smeshBuilder
+
+smesh = smeshBuilder.New()
+#smesh.SetEnablePublish( False ) # Set to False to avoid publish in study if not needed or in some particular situations:
+                                 # multiples meshes built in parallel, complex and numerous mesh edition (performance)
+
+Mesh_1 = smesh.Mesh(Fillet_1_1)
+Regular_1D = Mesh_1.Segment()
+Number_of_Segments_1 = Regular_1D.NumberOfSegments(7,None,[])
+MEFISTO_2D = Mesh_1.Triangle(algo=smeshBuilder.MEFISTO)
+Max_Element_Area_1 = MEFISTO_2D.MaxElementArea(20)
+isDone = Mesh_1.Compute()
+assert(isDone)
+Mesh_2 = smesh.Mesh(Extrusion_1_1)
+Cartesian_3D = Mesh_2.BodyFitted()
+Body_Fitting_Parameters_1 = Cartesian_3D.SetGrid([ [ '4.3589' ], [ 0, 1 ]],[ [ '4.3589' ], [ 0, 1 ]],[ [ '4.3589' ], [ 0, 1 ]],4,0)
+Body_Fitting_Parameters_1.SetFixedPoint( SMESH.PointStruct ( 0, 0, 0 ), 1 )
+Body_Fitting_Parameters_1.SetAxesDirs( SMESH.DirStruct( SMESH.PointStruct ( 1, 0, 0 )), SMESH.DirStruct( SMESH.PointStruct ( 0, 1, 0 )), SMESH.DirStruct( SMESH.PointStruct ( 0, 0, 1 )) )
+isDone = Mesh_2.Compute()
+assert(isDone)
+Mesh_3 = smesh.Mesh(Revolution_1_1)
+status = Mesh_3.AddHypothesis(Number_of_Segments_1)
+Regular_1D_1 = Mesh_3.Segment()
+isDone = Mesh_3.Compute()
+assert(isDone)
+
+## Set names of Mesh objects
+smesh.SetName(Regular_1D.GetAlgorithm(), 'Regular_1D')
+smesh.SetName(MEFISTO_2D.GetAlgorithm(), 'MEFISTO_2D')
+smesh.SetName(Cartesian_3D.GetAlgorithm(), 'Cartesian_3D')
+smesh.SetName(Mesh_1.GetMesh(), 'Mesh_1')
+smesh.SetName(Mesh_2.GetMesh(), 'Mesh_2')
+smesh.SetName(Mesh_3.GetMesh(), 'Mesh_3')
+smesh.SetName(Body_Fitting_Parameters_1, 'Body Fitting Parameters_1')
+smesh.SetName(Max_Element_Area_1, 'Max. Element Area_1')
+smesh.SetName(Number_of_Segments_1, 'Number of Segments_1')
+
+# check the SHAPER study objects generated names
+assert(Extrusion_1_1.GetName() == "Extrusion_1_1")
+assert(Fillet_1_1.GetName() == "Fillet_1_1")
+assert(Revolution_1_1.GetName() == "Revolution_1_1")
+# check the smesh mesh is computed correctly
+assert(Mesh_1.NbNodes() == 235)
+assert(Mesh_2.NbNodes() == 168)
+assert(Mesh_3.NbNodes() == 80)
diff --git a/src/ConnectorAPI/Test/TestShaperStudy2.py b/src/ConnectorAPI/Test/TestShaperStudy2.py
new file mode 100644 (file)
index 0000000..6b37049
--- /dev/null
@@ -0,0 +1,116 @@
+# Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+import os
+import sys
+import salome
+
+salome.salome_init()
+
+#=========================================================================
+# A function to get the XAO file path
+#=========================================================================
+def getPath(path):
+    shapes_dir = os.path.join(os.getenv("DATA_DIR"), "Shapes")
+    return os.path.join(shapes_dir, path)
+
+###
+### SHAPER component
+###
+
+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(147.3929660820667, 79.1580464539047, 58.09363834643254, 79.1580464539047)
+SketchLine_2 = Sketch_1.addLine(58.09363834643254, 79.1580464539047, 58.09363834643254, 8.969712804393431)
+SketchLine_3 = Sketch_1.addLine(58.09363834643254, 8.969712804393431, 147.3929660820667, 8.969712804393431)
+SketchLine_4 = Sketch_1.addLine(147.3929660820667, 8.969712804393431, 147.3929660820667, 79.1580464539047)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f")], model.selection(), 150, 0)
+Extrusion_1.setName("Box")
+Extrusion_1.result().setName("Box")
+Group_1 = model.addGroup(Part_1_doc, "Vertices", [model.selection("VERTEX", "[Box/Generated_Face&Sketch_1/SketchLine_1][Box/Generated_Face&Sketch_1/SketchLine_2][Box/To_Face]"), model.selection("VERTEX", "[Box/Generated_Face&Sketch_1/SketchLine_3][Box/Generated_Face&Sketch_1/SketchLine_4][Box/To_Face]")])
+Group_1.setName("VerticesGroup")
+Group_1.result().setName("VerticesGroup")
+Group_2 = model.addGroup(Part_1_doc, "Faces", [model.selection("FACE", "Box/Generated_Face&Sketch_1/SketchLine_4"), model.selection("FACE", "Box/Generated_Face&Sketch_1/SketchLine_3")])
+Group_2.setName("FacesGroup")
+Group_2.result().setName("FacesGroup")
+Field_1 = model.addField(Part_1_doc, 1, "DOUBLE", 3, ["Comp 1", "Comp 2", "Comp 3"], [model.selection("EDGE", "[Box/Generated_Face&Sketch_1/SketchLine_2][Box/Generated_Face&Sketch_1/SketchLine_3]")])
+Field_1.setName("MyField")
+Field_1.result().setName("MyField")
+Field_1.addStep(0, 0, [[0, 0, 0], [1, 1.5, 37.2]])
+
+model.end()
+
+###
+### SHAPERSTUDY component
+###
+
+if 'model' in globals():
+  model.publishToShaperStudy()
+import SHAPERSTUDY
+Box, VerticesGroup, FacesGroup, MyField, = SHAPERSTUDY.shape(model.featureStringId(Extrusion_1))
+Box_1, VerticesGroup_1, FacesGroup_1, MyField_1, = SHAPERSTUDY.archive(Box, getPath("Xao/TestShaperStudy2.xao"))
+###
+### SMESH component
+###
+
+import  SMESH, SALOMEDS
+from salome.smesh import smeshBuilder
+
+smesh = smeshBuilder.New()
+#smesh.SetEnablePublish( False ) # Set to False to avoid publish in study if not needed or in some particular situations:
+                                 # multiples meshes built in parallel, complex and numerous mesh edition (performance)
+
+Mesh_1 = smesh.Mesh(Box)
+Regular_1D = Mesh_1.Segment()
+Number_of_Segments_1 = Regular_1D.NumberOfSegments(4)
+MEFISTO_2D = Mesh_1.Triangle(algo=smeshBuilder.MEFISTO)
+Length_From_Edges_1 = MEFISTO_2D.LengthFromEdges()
+MEFISTO_2D_1 = Mesh_1.Triangle(algo=smeshBuilder.MEFISTO,geom=FacesGroup)
+Max_Element_Area_1 = MEFISTO_2D_1.MaxElementArea(2)
+Mesh_1.Compute()
+Mesh_1.GetMesh().ReplaceShape( Box_1 )
+SHAPERSTUDY.breakLinkForSubElements(salome.ObjectToSObject(Mesh_1.GetMesh()), Box_1)
+Mesh_1.Clear()
+Sub_mesh_1 = MEFISTO_2D_1.GetSubMesh()
+
+
+## Set names of Mesh objects
+smesh.SetName(Regular_1D.GetAlgorithm(), 'Regular_1D')
+smesh.SetName(MEFISTO_2D.GetAlgorithm(), 'MEFISTO_2D')
+smesh.SetName(Number_of_Segments_1, 'Number of Segments_1')
+smesh.SetName(Max_Element_Area_1, 'Max. Element Area_1')
+smesh.SetName(Length_From_Edges_1, 'Length From Edges_1')
+smesh.SetName(Mesh_1.GetMesh(), 'Mesh_1')
+smesh.SetName(Sub_mesh_1, 'Sub-mesh_1')
+
+assert(Mesh_1.Compute())
diff --git a/src/ConnectorAPI/Test/TestShaperStudy3.py b/src/ConnectorAPI/Test/TestShaperStudy3.py
new file mode 100644 (file)
index 0000000..991c333
--- /dev/null
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+
+###
+### This file is generated automatically by SALOME v9.4.0 with dump python functionality
+###
+
+import os
+import sys
+import salome
+
+salome.salome_init()
+
+#=========================================================================
+# A function to get the XAO file path
+#=========================================================================
+def getPath(path):
+    shapes_dir = os.path.join(os.getenv("DATA_DIR"), "Shapes")
+    return os.path.join(shapes_dir, path)
+
+###
+### SHAPER component
+###
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Param_H = model.addParameter(Part_1_doc, "h", "20")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(75.09305815883349, 77.46634028730745, 23.30071943952229, 77.46634028730745)
+SketchLine_2 = Sketch_1.addLine(23.30071943952229, 77.46634028730745, 23.30071943952229, 23.93663846925804)
+SketchLine_3 = Sketch_1.addLine(23.30071943952229, 23.93663846925804, 75.09305815883349, 23.93663846925804)
+SketchLine_4 = Sketch_1.addLine(75.09305815883349, 23.93663846925804, 75.09305815883349, 77.46634028730745)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f")], model.selection(), "h", 0)
+
+model.end()
+
+###
+### SHAPERSTUDY component
+###
+
+if 'model' in globals():
+  model.publishToShaperStudy()
+import SHAPERSTUDY
+Extrusion_1_1, = SHAPERSTUDY.shape(model.featureStringId(Extrusion_1))
+Extrusion_1_1_1, = SHAPERSTUDY.archive(Extrusion_1_1, getPath("Xao/TestShaperStudy2.xao"))
+###
+### SMESH component
+###
+
+import  SMESH, SALOMEDS
+from salome.smesh import smeshBuilder
+
+smesh = smeshBuilder.New()
+#smesh.SetEnablePublish( False ) # Set to False to avoid publish in study if not needed or in some particular situations:
+                                 # multiples meshes built in parallel, complex and numerous mesh edition (performance)
+
+Mesh_1 = smesh.Mesh(Extrusion_1_1)
+Cartesian_3D = Mesh_1.BodyFitted()
+Body_Fitting_Parameters_1 = Cartesian_3D.SetGrid([ [ '7.71225' ], [ 0, 1 ]],[ [ '7.71225' ], [ 0, 1 ]],[ [ '7.71225' ], [ 0, 1 ]],4,0)
+Body_Fitting_Parameters_1.SetFixedPoint( SMESH.PointStruct ( 0, 0, 0 ), 1 )
+Body_Fitting_Parameters_1.SetAxesDirs( SMESH.DirStruct( SMESH.PointStruct ( 1, 0, 0 )), SMESH.DirStruct( SMESH.PointStruct ( 0, 1, 0 )), SMESH.DirStruct( SMESH.PointStruct ( 0, 0, 1 )) )
+isDone = Mesh_1.Compute()
+Mesh_2 = smesh.Mesh(Extrusion_1_1)
+Regular_1D = Mesh_2.Segment()
+Number_of_Segments_1 = Regular_1D.NumberOfSegments(7)
+MEFISTO_2D = Mesh_2.Triangle(algo=smeshBuilder.MEFISTO)
+Max_Element_Area_1 = MEFISTO_2D.MaxElementArea(20)
+SHAPERSTUDY.breakLinkForSubElements(salome.ObjectToSObject(Mesh_2.GetMesh()), Extrusion_1_1_1)
+Mesh_2.GetMesh().ReplaceShape( Extrusion_1_1_1 )
+isDone = Mesh_2.Compute()
+
+
+## Set names of Mesh objects
+smesh.SetName(Cartesian_3D.GetAlgorithm(), 'Cartesian_3D')
+smesh.SetName(Regular_1D.GetAlgorithm(), 'Regular_1D')
+smesh.SetName(MEFISTO_2D.GetAlgorithm(), 'MEFISTO_2D')
+smesh.SetName(Mesh_1.GetMesh(), 'Mesh_1')
+smesh.SetName(Mesh_2.GetMesh(), 'Mesh_2')
+smesh.SetName(Max_Element_Area_1, 'Max. Element Area_1')
+smesh.SetName(Body_Fitting_Parameters_1, 'Body Fitting Parameters_1')
+smesh.SetName(Number_of_Segments_1, 'Number of Segments_1')
+
+# check on update of the initial box Mesh_1 computed on it is changed, Mesh_2 on dead shape is unchanged
+aNb1 = Mesh_1.NbElements()
+aNb2 = Mesh_2.NbElements()
+model.begin()
+Param_H.setValue(50)
+model.end()
+model.publishToShaperStudy()
+assert(Mesh_1.Compute())
+assert(Mesh_1.NbElements() > aNb1)
+assert(Mesh_2.Compute())
+assert(Mesh_2.NbElements() == aNb2)
index be23a5a85583f459f3a2b2cac302b9692448f6a5..fcd2f7f1ca470c9eed9f0467de441e831a60e908 100644 (file)
@@ -25,4 +25,7 @@ SET(TEST_NAMES
   TestExportToGEOMWholeFeature
   Test2882
   Test17917
+  TestShaperStudy1
+  TestShaperStudy2
+  TestShaperStudy3
 )
index 17a885057e9dfb3f69597e62025ea52b74b426b0..ddf16fa67fa71de1c6e103337e4e0721596db723 100644 (file)
@@ -22,6 +22,7 @@ INCLUDE(Common)
 SET(PYTHON_FILES
     ConnectorPlugin.py
     ConnectorPlugin_ExportFeature.py
+    ConnectorPlugin_PublishToStudyFeature.py
 )
 
 SET(XML_RESOURCES
index f16adee55871b3ad29316e9a96c67ca254acbae3..3886c20e2240480dcaf114acadd4b2e92319e4d7 100644 (file)
@@ -23,6 +23,7 @@
 import ModelAPI
 
 from ConnectorPlugin_ExportFeature import ExportFeature
+from ConnectorPlugin_PublishToStudyFeature import PublishToStudyFeature
 
 ## @ingroup Plugins
 #  The main class for management the construction features as plugin.
@@ -37,6 +38,8 @@ class ConnectorPlugin(ModelAPI.ModelAPI_Plugin):
     def createFeature(self, theFeatureID):
         if theFeatureID == ExportFeature.ID():
             return ExportFeature().__disown__()
+        elif theFeatureID == PublishToStudyFeature.ID():
+            return PublishToStudyFeature().__disown__()
         else:
             print("ConnectorPlugin: No such feature %s" % theFeatureID)
 
diff --git a/src/ConnectorPlugin/ConnectorPlugin_PublishToStudyFeature.py b/src/ConnectorPlugin/ConnectorPlugin_PublishToStudyFeature.py
new file mode 100644 (file)
index 0000000..509b9a3
--- /dev/null
@@ -0,0 +1,245 @@
+# Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+## @package Plugins
+#  ExportFeature class definition
+
+import ModelAPI
+import ExchangeAPI
+import EventsAPI
+from GeomAPI import *
+import GeomAlgoAPI
+
+import salome
+from salome.shaper import model
+
+import SHAPERSTUDY_ORB
+import SHAPERSTUDY_utils
+
+## @ingroup Plugins
+#  Feature to export all shapes and groups into the GEOM module
+class PublishToStudyFeature(ModelAPI.ModelAPI_Feature):
+
+    ## The constructor.
+    def __init__(self):
+        ModelAPI.ModelAPI_Feature.__init__(self)
+        pass
+
+    @staticmethod
+    ## Export kind. Static.
+    def ID():
+        return "PublishToStudy"
+
+    ## Returns the kind of a feature.
+    def getKind(self):
+        return PublishToStudyFeature.ID()
+
+    ## This feature is action: has no property panel and executes immediately.
+    def isAction(self):
+        return True
+
+    ## This feature has no attributes, as it is action.
+    def initAttributes(self):
+        pass
+
+    ## Exports all shapes and groups into the GEOM module.
+    def execute(self):
+        aSession = ModelAPI.ModelAPI_Session.get()
+        aPartSet = aSession.moduleDocument()
+        # check that the PartSet document current feature is the last to avoid problems with all
+        # features update
+        if aPartSet.size(model.ModelAPI_Feature_group()) > 0:
+          aLastFeature = ModelAPI.objectToFeature(aPartSet.object(model.ModelAPI_Feature_group(), aPartSet.size(model.ModelAPI_Feature_group()) - 1))
+          aCurrentFeature = aPartSet.currentFeature(True)
+          if aLastFeature.data().featureId() != aCurrentFeature.data().featureId():
+            EventsAPI.Events_InfoMessage("PublishToStudy", "Not all PartSet parts are up-to-date, nothing is published. Please, make the last PartSet feature as current.", self).send()
+            return
+        # find a shaper-study component
+        salome.salome_init(1)
+        aComponent = SHAPERSTUDY_utils.findOrCreateComponent()
+        anEngine = SHAPERSTUDY_utils.getEngine()
+        # collect all processed internal entries to break the link of unprocessed later
+        allProcessed = []
+
+        # iterate all parts and all results to publish them in SHAPER_STUDY
+        for aPartId in range(aPartSet.size(model.ModelAPI_ResultPart_group())):
+          aPartObject = aPartSet.object(model.ModelAPI_ResultPart_group(), aPartId)
+          aPartRes = ModelAPI.modelAPI_ResultPart(ModelAPI.modelAPI_Result(aPartObject))
+          aPartDoc = aPartRes.partDoc()
+          if aPartDoc is None and aPartObject is not None:
+            EventsAPI.Events_InfoMessage("PublishToStudy", "For publish to SHAPER-STUDY some Part is not activated", self).send()
+            break
+          aPartFeatureId = aPartSet.feature(aPartRes).data().featureId()
+          for aResId in range(aPartDoc.size(model.ModelAPI_ResultBody_group())):
+            aResObject = aPartDoc.object(model.ModelAPI_ResultBody_group(), aResId)
+            aRes = model.objectToResult(aResObject)
+            aResFeatureId = aPartDoc.feature(aRes).data().featureId()
+            aSSEntry = str(aPartFeatureId) + ":" + str(aResFeatureId)
+            aSShape = anEngine.FindOrCreateShape(aSSEntry)
+            aSShape.SetShapeByStream(aRes.shape().getShapeStream(False))
+            if not aSShape.GetSO(): # publish in case it is a new shape
+              anEngine.AddInStudy(aSShape, aRes.data().name(), None)
+            else: # restore a red reference if it was deleted
+              aDone, aSO2 = aSShape.GetSO().FindSubObject(1)
+              if aDone:
+                aDone, aRef = aSO2.ReferencedObject()
+                if not aDone:
+                  aBuilder = SHAPERSTUDY_utils.getStudy().NewBuilder()
+                  aBuilder.Addreference(aSO2, aSShape.GetSO())
+            allProcessed.append(aSSEntry)
+            # Groups
+            self.processGroups(aRes, anEngine, aPartFeatureId, aSShape, False)
+            # Fields
+            self.processGroups(aRes, anEngine, aPartFeatureId, aSShape, True)
+
+        # process all SHAPER-STUDY shapes to find dead
+        aSOIter = SHAPERSTUDY_utils.getStudy().NewChildIterator(aComponent)
+        while aSOIter.More():
+          aSO = aSOIter.Value()
+          aSOIter.Next() ### here because there is continue inside the loop!
+          anIOR = aSO.GetIOR()
+          if len(anIOR):
+            anObj = salome.orb.string_to_object(anIOR)
+            if isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Object):
+              anEntry = anObj.GetEntry()
+              if len(anEntry) == 0:
+                continue;
+              elif anEntry not in allProcessed: # found a removed shape: make it dead for the moment
+                # remove the reference - red node
+                aRes, aSO2 = aSO.FindSubObject(1)
+                if aRes:
+                  aRes, aRef = aSO2.ReferencedObject()
+                  if aRes:
+                    aBuilder = SHAPERSTUDY_utils.getStudy().NewBuilder()
+                    aBuilder.RemoveReference(aSO2)
+
+    # Part of the "execute" method: processes the Groups of theRes result publication.
+    # If theFields is true, the same is performed for Fields.
+    def processGroups(self, theRes, theEngine, thePartFeatureId, theStudyShape, theFields):
+      allGroupsProcessed = []
+      if theFields:
+        aRefGroups = ModelAPI.referencedFeatures(theRes, "Field", True)
+      else:
+        aRefGroups = ModelAPI.referencedFeatures(theRes, "Group", True)
+      for aRef in aRefGroups:
+        aGroupIndices = []
+        aGroupHasIndex = {}
+        aResShape = theRes.shape()
+        if theFields:
+          aSelList = aRef.selectionList("selected")
+        else:
+          aSelList = aRef.selectionList("group_list")
+        aSelType = GeomAPI_Shape.shapeTypeByStr(aSelList.selectionType())
+        for aSelIndex in range(aSelList.size()):
+          aSelection = aSelList.value(aSelIndex)
+          if aSelection.contextObject():
+            aShape = aSelection.value()
+            if aShape:
+              allShapesList = [] # collect all sub-shapes selected in the group
+              if aShape.shapeType() == 0: # compound
+                anExplorer = GeomAPI_ShapeExplorer(aShape, aSelType)
+                while anExplorer.more():
+                  allShapesList.append(anExplorer.current())
+                  anExplorer.next()
+              else:
+                allShapesList.append(aShape)
+              # get index of each selected shape: if 0, this sub-shape is not in our result
+              for aSelected in allShapesList:
+                anId = GeomAlgoAPI.GeomAlgoAPI_CompoundBuilder.id(aResShape, aSelected)
+                if anId > 0 and not anId in aGroupHasIndex:
+                  aGroupIndices.append(anId)
+                  aGroupHasIndex[anId] = 0
+        if len(aGroupIndices): # create group
+          aGroupFeatureId = aRef.data().featureId()
+          if theFields:
+            aFieldOp = theEngine.GetIFieldOperations()
+            aGroupEntry = "field" + str(thePartFeatureId) + ":" + str(aGroupFeatureId)
+            aGroup = aFieldOp.FindField(theStudyShape, aGroupEntry)
+          else:
+            aGroupOp = theEngine.GetIGroupOperations()
+            aGroupEntry = "group" + str(thePartFeatureId) + ":" + str(aGroupFeatureId)
+            aGroup = aGroupOp.FindGroup(theStudyShape, aGroupEntry)
+          if not aGroup: # create a new
+            if theFields:
+              aGroup = aFieldOp.CreateFieldByType(theStudyShape, aSelType)
+            else:
+              aGroup = aGroupOp.CreateGroup(theStudyShape, aSelType)
+            aGroup.SetEntry(aGroupEntry)
+            theEngine.AddInStudy(aGroup, aRef.firstResult().data().name(), theStudyShape)
+          aGroup.SetSelection(aGroupIndices)
+          if theFields:
+            self.fillField(aGroup, aRef, theEngine, aGroupIndices)
+          # a group takes shape from the main result
+          #aGroup.SetShapeByStream(aRef.firstResult().shape().getShapeStream(False)) # group shape
+          allGroupsProcessed.append(aGroupEntry)
+      # check all existing groups: if some does not processed, remove it from the tree
+      aSOIter = SHAPERSTUDY_utils.getStudy().NewChildIterator(theStudyShape.GetSO())
+      while aSOIter.More():
+        aSO = aSOIter.Value()
+        anIOR = aSO.GetIOR()
+        if len(anIOR):
+          anObj = salome.orb.string_to_object(anIOR)
+          if (theFields and isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Field)) or \
+             (not theFields and type(anObj) == SHAPERSTUDY_ORB._objref_SHAPER_Group):
+            anEntry = anObj.GetEntry()
+            if anEntry not in allGroupsProcessed: # found a removed group => remove
+              aBuilder = SHAPERSTUDY_utils.getStudy().NewBuilder()
+              aBuilder.RemoveObject(anObj.GetSO())
+        aSOIter.Next()
+
+    # Part of the "execute" method: theFiled fields filling.
+    def fillField(self, theField, theFeature, theEngine, theSelectionIndices):
+      aTables = theFeature.tables("values")
+      aValType = aTables.type() # type of the values
+      theField.SetValuesType(aValType)
+      aNumSteps = aTables.tables() # number of steps is number of tables
+      aSteps = []
+      for aVal in range(aNumSteps):
+        aSteps.append(aVal + 1)
+      theField.SetSteps(aSteps)
+      aCompNames = []
+      aCompNamesAttr = theFeature.stringArray("components_names")
+      for anIndex in range(aCompNamesAttr.size()):
+        aCompNames.append(aCompNamesAttr.value(anIndex))
+      theField.SetComponents(aCompNames)
+      # prepare the sub-shapes indices: all values for all sub-shapes must be defined
+      aShapeOp = theEngine.GetIShapesOperations()
+      allIndices = aShapeOp.GetAllSubShapesIDs(theField.GetShape(), theField.GetSelectionType(), False)
+      # define steps
+      theField.ClearFieldSteps()
+      for aVal in range(aNumSteps):
+        aVals = []
+        for aCol in range(aTables.columns()):
+          #for aRow in range(aTables.rows()):
+          for anIndex in allIndices:
+            if anIndex in theSelectionIndices:
+              aRow = theSelectionIndices.index(anIndex) + 1 # starting from the first line
+            else:
+              aRow = 0 # default value
+            aStrVal = aTables.valueStr(aRow, aCol, aVal)
+            if aValType == 0: # boolean
+              if aStrVal == "True":
+                aVals.append(1)
+              else:
+                aVals.append(0)
+            elif aValType == 1: # int
+              aVals.append(int(aStrVal))
+            elif aValType == 2: # double
+              aVals.append(float(aStrVal))
+        theField.AddFieldStep(theFeature.intArray("stamps").value(aVal), aVal + 1, aVals)
index d0eb76878874fbf3892dbfc29e1db9a65084dba7..0d30be9b41990a9b73efc0347b04b40122403995 100644 (file)
@@ -7,6 +7,10 @@
         tooltip="Export all results and groups into GEOM module"
         icon="icons/Connector/geom_export.png"
         helpfile="ConnectorPlugin/ConnectorPlugin.html"/>
+      <feature
+        id="PublishToStudy"
+        title="Pyblish to study"
+        internal="1"/>
     </group>
   </workbench>
 </plugin>
\ No newline at end of file
index 2d764635a27b543c56fcc5f751cba48a17417922..87f51426c68b289fc29c24d1795f526da9a9bc58 100644 (file)
@@ -68,7 +68,7 @@ ExchangeAPI_Export::ExchangeAPI_Export(const std::shared_ptr<ModelAPI_Feature>&
   std::list<ModelHighAPI_Selection> aListOfOneSel;
   aListOfOneSel.push_back(theResult);
   fillAttribute(aListOfOneSel,
-    theFeature->selectionList(ExchangePlugin_ExportFeature::SELECTION_LIST_ID()));
+    theFeature->selectionList(ExchangePlugin_ExportFeature::XAO_SELECTION_LIST_ID()));
   execute();
   apply(); // finish operation to make sure the export is done on the current state of the history
 }
@@ -130,7 +130,7 @@ void ExchangeAPI_Export::dump(ModelHighAPI_Dumper& theDumper) const
     correctSeparators(aTmpXAOFile);
     theDumper << "exportToXAO(" << aDocName << ", '" << aTmpXAOFile << "'" ;
     AttributeSelectionListPtr aShapeSelected =
-      aBase->selectionList(ExchangePlugin_ExportFeature::SELECTION_LIST_ID());
+      aBase->selectionList(ExchangePlugin_ExportFeature::XAO_SELECTION_LIST_ID());
     if (aShapeSelected->isInitialized() && aShapeSelected->size() == 1) {
       theDumper<<", "<<aShapeSelected->value(0);
     }
index 83a6dd5702c79a2945df917a20c5df4736633365..30e5036e08c9f7e1656f0a249d57e8822f63be59 100644 (file)
@@ -42,6 +42,7 @@ SET(PROJECT_HEADERS
     ExchangePlugin_Dump.h
     ExchangePlugin_ImportPart.h
     ExchangePlugin_ExportPart.h
+    ExchangePlugin_Import.h
 )
 
 SET(PROJECT_SOURCES
@@ -53,6 +54,7 @@ SET(PROJECT_SOURCES
     ExchangePlugin_Dump.cpp
     ExchangePlugin_ImportPart.cpp
     ExchangePlugin_ExportPart.cpp
+    ExchangePlugin_Import.cpp
 )
 
 SET(XML_RESOURCES
@@ -106,6 +108,7 @@ ADD_UNIT_TESTS(
   TestExport.py
   Test2290.py
   Test2459.py
+  Test18710.py
   TestExportToXAOWithFields.py
   TestExportToXAOWithGroupNotUpdated.py
   TestExport_FiniteValidator.py
index 097042a286c29427aa9dd52a64d2d1b56ed4b8f9..e955db6548ec522c169b2aac63f24b1785da8c86 100644 (file)
@@ -65,10 +65,13 @@ void ExchangePlugin_Dump::initAttributes()
   data()->addAttribute(GEOMETRIC_DUMP_ID(), ModelAPI_AttributeBoolean::typeId());
   data()->addAttribute(WEAK_NAMING_DUMP_ID(), ModelAPI_AttributeBoolean::typeId());
 
+  data()->addAttribute(EXPORT_VARIABLES_ID(), ModelAPI_AttributeBoolean::typeId());
+
   // default values
   boolean(TOPOLOGICAL_NAMING_DUMP_ID())->setValue(THE_DUMP_NAMING);
   boolean(GEOMETRIC_DUMP_ID())->setValue(THE_DUMP_GEO);
   boolean(WEAK_NAMING_DUMP_ID())->setValue(THE_DUMP_WEAK);
+  boolean(EXPORT_VARIABLES_ID())->setValue(false);
 }
 
 void ExchangePlugin_Dump::execute()
@@ -159,6 +162,14 @@ void ExchangePlugin_Dump::dump(const std::string& theFileName)
     aDumper->addCustomStorage(aWeakNamingStorage);
   }
 
-  if (!aDumper->process(aDoc, theFileName))
-    setError("An error occured while dumping to " + theFileName);
+  if (!aDumper->process(aDoc, theFileName)) {
+    setError("An error occurred while dumping to " + theFileName);
+  } else {
+    if (boolean(EXPORT_VARIABLES_ID())->value()) {
+      aDumper->exportVariables();
+    }
+  }
+  // clear cashed data after export variables was performed
+  aDumper->clearCustomStorage();
+
 }
index 5ee0f004b89e02e75912d3688a8ca3569b1f00f1..1d7127b0b5926c8ddf2e83447f131afd0d3bc419 100644 (file)
@@ -71,6 +71,13 @@ public:
     return MY_WEAK_NAMING_DUMP_ID;
   }
 
+  /// attribute name for boolean flag to export variable names correspondence to another module
+  inline static const std::string& EXPORT_VARIABLES_ID()
+  {
+    static const std::string MY_EXPORT_VARIABLES_ID("export_variables");
+    return MY_EXPORT_VARIABLES_ID;
+  }
+
   /// Default constructor
   EXCHANGEPLUGIN_EXPORT ExchangePlugin_Dump();
   /// Default destructor
index 4eedccc2604e1078446fe24cbd99dbde9ea37b5a..93500cc5e7660a345a7aa6e851878269123e23fe 100644 (file)
@@ -94,6 +94,8 @@ void ExchangePlugin_ExportFeature::initAttributes()
     ModelAPI_AttributeString::typeId());
   data()->addAttribute(ExchangePlugin_ExportFeature::XAO_GEOMETRY_NAME_ID(),
     ModelAPI_AttributeString::typeId());
+  data()->addAttribute(ExchangePlugin_ExportFeature::XAO_SELECTION_LIST_ID(),
+    ModelAPI_AttributeSelectionList::typeId());
 
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(),
     ExchangePlugin_ExportFeature::XAO_FILE_PATH_ID());
@@ -101,6 +103,21 @@ void ExchangePlugin_ExportFeature::initAttributes()
     ExchangePlugin_ExportFeature::XAO_AUTHOR_ID());
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(),
     ExchangePlugin_ExportFeature::XAO_GEOMETRY_NAME_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(),
+    ExchangePlugin_ExportFeature::XAO_SELECTION_LIST_ID());
+
+  // to support previous version of document, move the selection list
+  // if the type of export operation is XAO
+  AttributeStringPtr aTypeAttr = string(EXPORT_TYPE_ID());
+  if (aTypeAttr->isInitialized() && aTypeAttr->value() == "XAO") {
+    bool aWasBlocked = data()->blockSendAttributeUpdated(true, false);
+    AttributeSelectionListPtr aSelList = selectionList(SELECTION_LIST_ID());
+    AttributeSelectionListPtr aXAOSelList = selectionList(XAO_SELECTION_LIST_ID());
+    if (aSelList->size() > 0 && aXAOSelList->size() == 0)
+      aSelList->copyTo(aXAOSelList);
+    aSelList->clear();
+    data()->blockSendAttributeUpdated(aWasBlocked, false);
+  }
 }
 
 void ExchangePlugin_ExportFeature::attributeChanged(const std::string& theID)
@@ -316,7 +333,7 @@ void ExchangePlugin_ExportFeature::exportXAO(const std::string& theFileName)
   std::list<DocumentPtr> aDocuments; /// documents of Parts selected and used in export
   std::map<DocumentPtr, GeomTrsfPtr> aDocTrsf; /// translation of the part
 
-  AttributeSelectionListPtr aSelection = selectionList(SELECTION_LIST_ID());
+  AttributeSelectionListPtr aSelection = selectionList(XAO_SELECTION_LIST_ID());
   bool aIsSelection = aSelection->isInitialized() && aSelection->size() > 0;
   if (aIsSelection) { // a mode for export to geom result by result
     for(int a = 0; a < aSelection->size(); a++) {
@@ -575,9 +592,9 @@ bool ExchangePlugin_ExportFeature::isMacro() const
     }
   }
 
-  if (aFormat == "XAO") { // on export to GEOm the selection attribute is filled - this is
+  if (aFormat == "XAO") { // on export to GEOM the selection attribute is filled - this is
                           // an exceptional case where export to XAO feature must be kept
-    AttributeSelectionListPtr aList = aThis->selectionList(SELECTION_LIST_ID());
+    AttributeSelectionListPtr aList = aThis->selectionList(XAO_SELECTION_LIST_ID());
     return !aList->isInitialized() || aList->size() == 0;
   }
   return true;
index c0a79a8c5ea092bcbbba0d7fff00d3a97f0d6d7a..aa24b3d4980d62c72e4a07851f7b4d3ac5067cd1 100644 (file)
@@ -72,6 +72,12 @@ public:
     static const std::string MY_SELECTION_LIST_ID("selection_list");
     return MY_SELECTION_LIST_ID;
   }
+  /// attribute name of xao selection list
+  inline static const std::string& XAO_SELECTION_LIST_ID()
+  {
+    static const std::string MY_SELECTION_LIST_ID("xao_selection_list");
+    return MY_SELECTION_LIST_ID;
+  }
   /// attribute name of author for XAO format
   inline static const std::string& XAO_AUTHOR_ID()
   {
diff --git a/src/ExchangePlugin/ExchangePlugin_Import.cpp b/src/ExchangePlugin/ExchangePlugin_Import.cpp
new file mode 100644 (file)
index 0000000..0f22369
--- /dev/null
@@ -0,0 +1,160 @@
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "ExchangePlugin_Import.h"
+#include "ExchangePlugin_ImportFeature.h"
+
+#include <PartSetPlugin_Part.h>
+
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeStringArray.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_ResultPart.h>
+#include <ModelAPI_Tools.h>
+
+
+static const std::string THE_NEW_PART_STR("New Part");
+
+DocumentPtr findDocument(DocumentPtr thePartSetDoc, const std::string& thePartName)
+{
+  DocumentPtr aDoc;
+  FeaturePtr aPartFeature;
+  if (thePartName == THE_NEW_PART_STR) {
+    // create new part
+    aPartFeature = thePartSetDoc->addFeature(PartSetPlugin_Part::ID());
+    if (aPartFeature)
+      aPartFeature->execute();
+  }
+  else {
+    // find existing part by its name
+    std::list<FeaturePtr> aSubFeatures = thePartSetDoc->allFeatures();
+    for (std::list<FeaturePtr>::iterator aFIt = aSubFeatures.begin();
+      aFIt != aSubFeatures.end(); ++aFIt) {
+      if ((*aFIt)->getKind() == PartSetPlugin_Part::ID() && (*aFIt)->name() == thePartName) {
+        aPartFeature = *aFIt;
+        break;
+      }
+    }
+  }
+
+  if (aPartFeature) {
+    ResultPartPtr aPartResult =
+      std::dynamic_pointer_cast<ModelAPI_ResultPart>(aPartFeature->lastResult());
+    if (aPartResult)
+      aDoc = aPartResult->partDoc();
+  }
+  return aDoc;
+}
+
+
+ExchangePlugin_Import::ExchangePlugin_Import()
+{
+}
+
+ExchangePlugin_Import::~ExchangePlugin_Import()
+{
+  // TODO Auto-generated destructor stub
+}
+
+/*
+ * Request for initialization of data model of the feature: adding all attributes
+ */
+void ExchangePlugin_Import::initAttributes()
+{
+  data()->addAttribute(FILE_PATH_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(TARGET_PART_ID(), ModelAPI_AttributeInteger::typeId());
+  data()->addAttribute(TARGET_PARTS_LIST_ID(), ModelAPI_AttributeStringArray::typeId());
+}
+
+/*
+ * Computes or recomputes the results
+ */
+void ExchangePlugin_Import::execute()
+{
+  AttributeStringPtr aFilePathAttr = string(ExchangePlugin_Import::FILE_PATH_ID());
+  std::string aFilePath = aFilePathAttr->value();
+  if (aFilePath.empty()) {
+    setError("File path is empty.");
+    return;
+  }
+
+  // get the document where to import
+  AttributeStringArrayPtr aPartsAttr = stringArray(TARGET_PARTS_LIST_ID());
+  AttributeIntegerPtr aTargetAttr = integer(TARGET_PART_ID());
+  SessionPtr aSession = ModelAPI_Session::get();
+  DocumentPtr aDoc =
+    findDocument(aSession->moduleDocument(), aPartsAttr->value(aTargetAttr->value()));
+
+  if (aDoc.get()) {
+    FeaturePtr aImportFeature = aDoc->addFeature(ExchangePlugin_ImportFeature::ID());
+    DataPtr aData = aImportFeature->data();
+    AttributeStringPtr aPathAttr = aData->string(ExchangePlugin_ImportFeature::FILE_PATH_ID());
+    aPathAttr->setValue(aFilePathAttr->value());
+    aImportFeature->execute();
+  }
+}
+
+
+void ExchangePlugin_Import::attributeChanged(const std::string& theID)
+{
+  if (theID == FILE_PATH_ID()) {
+    AttributeStringPtr aFilePathAttr = string(FILE_PATH_ID());
+    if (aFilePathAttr->value().empty())
+      return;
+
+    AttributeStringArrayPtr aPartsAttr = stringArray(TARGET_PARTS_LIST_ID());
+    AttributeIntegerPtr aTargetAttr = integer(TARGET_PART_ID());
+
+    // update the list of target parts
+    SessionPtr aSession = ModelAPI_Session::get();
+    DocumentPtr aDoc = document();
+    bool isPartSet = aDoc == aSession->moduleDocument();
+    if (isPartSet) {
+      std::list<std::string> anAcceptedValues;
+      anAcceptedValues.push_back(THE_NEW_PART_STR);
+
+      // append names of all parts
+      std::list<FeaturePtr> aSubFeatures = aDoc->allFeatures();
+      for (std::list<FeaturePtr>::iterator aFIt = aSubFeatures.begin();
+        aFIt != aSubFeatures.end(); ++aFIt) {
+        if ((*aFIt)->getKind() == PartSetPlugin_Part::ID())
+          anAcceptedValues.push_back((*aFIt)->name());
+      }
+
+      if (aPartsAttr->size() != anAcceptedValues.size())
+        aTargetAttr->setValue(0);
+
+      aPartsAttr->setSize((int)anAcceptedValues.size());
+      std::list<std::string>::iterator anIt = anAcceptedValues.begin();
+      for (int anInd = 0; anIt != anAcceptedValues.end(); ++anIt, ++anInd)
+        aPartsAttr->setValue(anInd, *anIt);
+    }
+    else {
+      // keep only the name of the current part
+      if (aPartsAttr->size() == 0) {
+        FeaturePtr aPartFeature = ModelAPI_Tools::findPartFeature(aSession->moduleDocument(), aDoc);
+
+        aPartsAttr->setSize(1);
+        aPartsAttr->setValue(0, aPartFeature->name());
+        aTargetAttr->setValue(0);
+      }
+    }
+  }
+}
diff --git a/src/ExchangePlugin/ExchangePlugin_Import.h b/src/ExchangePlugin/ExchangePlugin_Import.h
new file mode 100644 (file)
index 0000000..7869483
--- /dev/null
@@ -0,0 +1,92 @@
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef EXCHANGEPLUGIN_IMPORT_H_
+#define EXCHANGEPLUGIN_IMPORT_H_
+
+#include "ExchangePlugin.h"
+
+#include <ModelAPI_CompositeFeature.h>
+#include <ModelAPI_Result.h>
+
+#include <map>
+
+/**
+ * \class ExchangePlugin_ImportFeature
+ * \ingroup Plugins
+ * \brief Feature for import shapes from the external files in CAD formats.
+ *
+ * The list of supported formats is defined in the configuration file.
+ */
+class ExchangePlugin_Import : public ModelAPI_Feature
+{
+ public:
+  /// Feature kind
+  inline static const std::string& ID()
+  {
+    static const std::string MY_IMPORT_ID("ImportMacro");
+    return MY_IMPORT_ID;
+  }
+  /// attribute name of file path
+  inline static const std::string& FILE_PATH_ID()
+  {
+    static const std::string MY_FILE_PATH_ID("file_path");
+    return MY_FILE_PATH_ID;
+  }
+  /// attribute name of target part
+  inline static const std::string& TARGET_PART_ID()
+  {
+    static const std::string MY_TARGET_PART_ID("target_part");
+    return MY_TARGET_PART_ID;
+  }
+  /// attribute name of list of target parts
+  inline static const std::string& TARGET_PARTS_LIST_ID()
+  {
+    static const std::string MY_TARGET_PARTS_LIST_ID("target_parts_list");
+    return MY_TARGET_PARTS_LIST_ID;
+  }
+  /// Default constructor
+  EXCHANGEPLUGIN_EXPORT ExchangePlugin_Import();
+  /// Default destructor
+  EXCHANGEPLUGIN_EXPORT virtual ~ExchangePlugin_Import();
+
+  /// Returns the unique kind of a feature
+  EXCHANGEPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    return ExchangePlugin_Import::ID();
+  }
+
+  /// Request for initialization of data model of the feature: adding all attributes
+  EXCHANGEPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Called on change of any argument-attribute of this object
+  /// \param theID identifier of changed attribute
+  EXCHANGEPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+  /// Computes or recomputes the results
+  EXCHANGEPLUGIN_EXPORT virtual void execute();
+
+  /// Returns true if this feature is used as macro: creates other features and then removed.
+  EXCHANGEPLUGIN_EXPORT virtual bool isMacro() const { return true; }
+
+  /// Reimplemented from ModelAPI_Feature::isPreviewNeeded(). Returns false.
+  EXCHANGEPLUGIN_EXPORT virtual bool isPreviewNeeded() const { return false; }
+};
+
+#endif /* IMPORT_IMPORTFEATURE_H_ */
index ccb5439e7b331337437d4a8b17ad19d2a0586693..078b50873657489c73580b1ff196f966f1d8cc2f 100644 (file)
@@ -23,6 +23,7 @@
 #include <ExchangePlugin_ExportFeature.h>
 #include <ExchangePlugin_ImportPart.h>
 #include <ExchangePlugin_ExportPart.h>
+#include <ExchangePlugin_Import.h>
 #include <ExchangePlugin_Validators.h>
 
 #include <Config_PropManager.h>
@@ -65,6 +66,9 @@ FeaturePtr ExchangePlugin_Plugin::createFeature(std::string theFeatureID)
   } else
   if (theFeatureID == ExchangePlugin_Dump::ID()) {
     return FeaturePtr(new ExchangePlugin_Dump);
+  } else
+  if (theFeatureID == ExchangePlugin_Import::ID()) {
+    return FeaturePtr(new ExchangePlugin_Import);
   }
   // feature of such kind is not found
   return FeaturePtr();
diff --git a/src/ExchangePlugin/Test/Test18710.py b/src/ExchangePlugin/Test/Test18710.py
new file mode 100644 (file)
index 0000000..93a1fb9
--- /dev/null
@@ -0,0 +1,56 @@
+# Copyright (C) 2020  CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from salome.shaper import model
+
+from GeomAPI import *
+from ModelAPI import *
+from SketchAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Export_1 = model.exportToXAO(Part_1_doc, '/tmp/shaper_vcnhioqf.xao', model.selection("SOLID", "Cylinder_1_1"), 'XAO')
+Export_1.setName("XAO")
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+model.end()
+
+model.testNbResults(Part_1, 1)
+model.testNbSubResults(Part_1, [0])
+model.testNbSubShapes(Part_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Part_1, GeomAPI_Shape.FACE, [9])
+model.testNbSubShapes(Part_1, GeomAPI_Shape.EDGE, [30])
+model.testNbSubShapes(Part_1, GeomAPI_Shape.VERTEX, [60])
+model.testResultsVolumes(Part_1, [1785.39816339744857])
+
+model.begin()
+ModelAPI.removeFeaturesAndReferences(FeatureSet([Cylinder_1.feature()]))
+model.end()
+
+model.testNbResults(Part_1, 1)
+model.testNbSubResults(Part_1, [0])
+model.testNbSubShapes(Part_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Part_1, GeomAPI_Shape.FACE, [6])
+model.testNbSubShapes(Part_1, GeomAPI_Shape.EDGE, [24])
+model.testNbSubShapes(Part_1, GeomAPI_Shape.VERTEX, [48])
+model.testResultsVolumes(Part_1, [1000])
+
+assert(model.checkPythonDump())
index ac0ad0711fc51012eed6a3f00254d01aaaaa232a..d47c5cd83339c116ac1519f626dfda6363872f1b 100644 (file)
@@ -1,14 +1,25 @@
 <plugin>
   <workbench id="Part">
     <group id="Exchange">
-      <feature id="Import" title="Import" tooltip="Import a file" icon="icons/Exchange/import.png" document="Part"
-               helpfile="importFeature.html">
+      <feature id="ImportMacro" title="Import" tooltip="Import a file" icon="icons/Exchange/import.png"
+               helpfile="importFeature.html"
+               internal="1">
+        <file_selector id="file_path" title="Import file" path="">
+          <validator id="ExchangePlugin_ImportFormat" parameters="BREP|BRP:BREP,STEP|STP:STEP,IGES|IGS:IGES,XAO:XAO" />
+        </file_selector>
+        <choice id="target_part"
+                string_list_attribute="target_parts_list"
+                label="Import to"
+                tooltip="Select the part to import the document" />
+      </feature>
+      <feature id="Import" title="Import" tooltip="Import a file" icon="icons/Exchange/import.png"
+               helpfile="importFeature.html" internal="1">
         <file_selector id="file_path" title="Import file" path="">
           <validator id="ExchangePlugin_ImportFormat" parameters="BREP|BRP:BREP,STEP|STP:STEP,IGES|IGS:IGES,XAO:XAO" />
         </file_selector>
       </feature>
       <feature id="Export" title="Export" tooltip="Export to file" icon="icons/Exchange/export.png"
-               helpfile="exportFeature.html">
+               helpfile="exportFeature.html" internal="1">
         <source path="export_widget.xml" />
       </feature>
       <feature id="Dump" title="Dump" tooltip="Dump Python script" icon="icons/Exchange/dump.png"
index e472d6fc1e3904be345c51b6504e9a18616878cc..dea751490ab701ff1b63bb004f9e585246474e29 100644 (file)
@@ -570,6 +570,7 @@ ADD_UNIT_TESTS(TestExtrusion.py
                TestDefeaturing_OnCompound.py
                Test3137_1.py
                Test3137_2.py
+               Test2918.py
                Test3139.py
                TestPlacement_MultiLevelCompound_v0_1.py
                TestPlacement_MultiLevelCompound_v0_2.py
diff --git a/src/FeaturesPlugin/Test/Test2918.py b/src/FeaturesPlugin/Test/Test2918.py
new file mode 100644 (file)
index 0000000..530acf2
--- /dev/null
@@ -0,0 +1,328 @@
+# Copyright (C) 2019-2020  CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from GeomAPI import *
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_1 = Sketch_1.addLine(6.188, 9.028, 6.188, -3.45)
+SketchLine_2 = Sketch_1.addLine(6.188, -3.45, 0, -3.45)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(0, -3.45, 0, -6.45)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(0, -6.45, 7.782, -6.45)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(7.782, -6.45, 7.782, -3.45)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_1.addLine(7.782, -3.45, 6.538, -3.45)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchLine_7 = Sketch_1.addLine(6.538, -3.45, 6.538, -2.4)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchLine_8 = Sketch_1.addLine(6.538, -2.4, 6.376, -2.25)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchLine_9 = Sketch_1.addLine(6.376, -2.25, 6.376, 9.028)
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchLine_10 = Sketch_1.addLine(6.376, 9.028, 6.188, 9.028)
+SketchLine_10.setAuxiliary(True)
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint())
+SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_10.endPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_10.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_1.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_9.result())
+SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_3.result())
+SketchConstraintVertical_4 = Sketch_1.setVertical(SketchLine_5.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_2.result())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_6.result())
+SketchConstraintHorizontal_4 = Sketch_1.setHorizontal(SketchLine_4.result())
+SketchConstraintCoincidence_11 = Sketch_1.setCoincident(SketchLine_7.startPoint(), SketchLine_2.result())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_11 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_12 = Sketch_1.setCoincident(SketchLine_3.startPoint(), SketchLine_11.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_5.result(), 3)
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Line(SketchLine_11).startPoint(), SketchLine_1.result(), 6.188, True)
+SketchConstraintVertical_5 = Sketch_1.setVertical(SketchLine_7.result())
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_12 = SketchProjection_2.createdFeature()
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchLine_9.endPoint(), SketchLine_12.result(), 9.028, True)
+SketchConstraintDistance_3 = Sketch_1.setDistance(SketchLine_2.startPoint(), SketchLine_9.result(), 0.188, True)
+SketchConstraintDistance_4 = Sketch_1.setDistance(SketchLine_2.startPoint(), SketchLine_7.result(), 0.35, True)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_7.endPoint(), SketchLine_8.endPoint(), 0.15)
+SketchConstraintDistance_5 = Sketch_1.setDistance(SketchLine_5.endPoint(), SketchLine_12.result(), 3.45, True)
+SketchConstraintDistance_6 = Sketch_1.setDistance(SketchLine_8.endPoint(), SketchLine_12.result(), 2.25, True)
+SketchLine_13 = Sketch_1.addLine(7.032, -4.05, 5.532, -4.05)
+SketchLine_14 = Sketch_1.addLine(5.532, -4.05, 5.532, -5.85)
+SketchLine_15 = Sketch_1.addLine(5.532, -5.85, 7.032, -5.85)
+SketchLine_16 = Sketch_1.addLine(7.032, -5.85, 7.032, -4.05)
+SketchConstraintCoincidence_13 = Sketch_1.setCoincident(SketchLine_16.endPoint(), SketchLine_13.startPoint())
+SketchConstraintCoincidence_14 = Sketch_1.setCoincident(SketchLine_13.endPoint(), SketchLine_14.startPoint())
+SketchConstraintCoincidence_15 = Sketch_1.setCoincident(SketchLine_14.endPoint(), SketchLine_15.startPoint())
+SketchConstraintCoincidence_16 = Sketch_1.setCoincident(SketchLine_15.endPoint(), SketchLine_16.startPoint())
+SketchConstraintHorizontal_5 = Sketch_1.setHorizontal(SketchLine_13.result())
+SketchConstraintVertical_6 = Sketch_1.setVertical(SketchLine_14.result())
+SketchConstraintHorizontal_6 = Sketch_1.setHorizontal(SketchLine_15.result())
+SketchConstraintVertical_7 = Sketch_1.setVertical(SketchLine_16.result())
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_14.result(), 1.8)
+SketchConstraintLength_3 = Sketch_1.setLength(SketchLine_15.result(), 1.5)
+SketchLine_17 = Sketch_1.addLine(6.282, -4.05, 6.282, 9.028)
+SketchLine_17.setAuxiliary(True)
+SketchConstraintCoincidence_17 = Sketch_1.setCoincident(SketchLine_17.startPoint(), SketchLine_13.result())
+SketchConstraintCoincidence_18 = Sketch_1.setCoincident(SketchLine_17.endPoint(), SketchLine_10.result())
+SketchConstraintVertical_8 = Sketch_1.setVertical(SketchLine_17.result())
+SketchConstraintMiddle_1 = Sketch_1.setMiddlePoint(SketchLine_17.startPoint(), SketchLine_13.result())
+SketchConstraintDistance_7 = Sketch_1.setDistance(SketchLine_17.startPoint(), SketchLine_5.result(), 1.5, True)
+SketchConstraintMiddle_2 = Sketch_1.setMiddlePoint(SketchLine_10.result(), SketchLine_17.endPoint())
+SketchConstraintDistance_8 = Sketch_1.setDistance(SketchLine_14.startPoint(), SketchLine_2.result(), 0.6, True)
+SketchLine_18 = Sketch_1.addLine(6.376, 9.028, 6.535, 9.187)
+SketchConstraintCoincidence_19 = Sketch_1.setCoincident(SketchLine_9.endPoint(), SketchLine_18.startPoint())
+SketchLine_19 = Sketch_1.addLine(6.535, 9.187, 6.535, 10.256)
+SketchConstraintCoincidence_20 = Sketch_1.setCoincident(SketchLine_18.endPoint(), SketchLine_19.startPoint())
+SketchLine_20 = Sketch_1.addLine(6.535, 10.256, 6.185, 10.256)
+SketchConstraintCoincidence_21 = Sketch_1.setCoincident(SketchLine_19.endPoint(), SketchLine_20.startPoint())
+SketchLine_21 = Sketch_1.addLine(6.185, 10.256, 4.9175, 10.94235984621998)
+SketchConstraintCoincidence_22 = Sketch_1.setCoincident(SketchLine_20.endPoint(), SketchLine_21.startPoint())
+SketchConstraintHorizontal_7 = Sketch_1.setHorizontal(SketchLine_20.result())
+SketchConstraintVertical_9 = Sketch_1.setVertical(SketchLine_19.result())
+SketchConstraintAngle_1 = Sketch_1.setAngle(SketchLine_10.result(), SketchLine_18.result(), 45, type = "Supplementary")
+SketchConstraintLength_4 = Sketch_1.setLength(SketchLine_20.result(), 0.35)
+SketchConstraintDistance_9 = Sketch_1.setDistance(SketchLine_19.endPoint(), SketchLine_12.result(), 10.256, True)
+SketchArc_1 = Sketch_1.addArc(0, 2.425, 4.9175, 10.94235984621998, 0, 12.26, False)
+SketchConstraintCoincidence_23 = Sketch_1.setCoincident(SketchLine_11.result(), SketchArc_1.center())
+SketchConstraintCoincidence_24 = Sketch_1.setCoincident(SketchLine_21.endPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_25 = Sketch_1.setCoincident(SketchLine_11.result(), SketchArc_1.endPoint())
+SketchLine_22 = Sketch_1.addLine(6.188, 9.028, 6.082, 9.532)
+SketchConstraintCoincidence_26 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_22.startPoint())
+SketchArc_2 = Sketch_1.addArc(4.79378612024245, 9.263, 6.082, 9.532, 5.676067550792229, 10.23944020672391, False)
+SketchConstraintCoincidence_27 = Sketch_1.setCoincident(SketchLine_22.endPoint(), SketchArc_2.startPoint())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_2.results()[1], 1.316)
+SketchConstraintDistance_10 = Sketch_1.setDistance(SketchArc_2.startPoint(), SketchLine_1.result(), 0.106, True)
+SketchLine_23 = Sketch_1.addLine(5.676067550792229, 10.23944020672391, 5.405090045827156, 10.43837553323928)
+SketchConstraintCoincidence_28 = Sketch_1.setCoincident(SketchArc_2.endPoint(), SketchLine_23.startPoint())
+SketchLine_24 = Sketch_1.addLine(5.405090045827156, 10.43837553323928, 5.126644475052085, 10.62934617154252)
+SketchConstraintCoincidence_29 = Sketch_1.setCoincident(SketchLine_23.endPoint(), SketchLine_24.startPoint())
+SketchLine_25 = Sketch_1.addLine(5.126644475052085, 10.62934617154252, 4.8355, 10.80033167999934)
+SketchConstraintCoincidence_30 = Sketch_1.setCoincident(SketchLine_24.endPoint(), SketchLine_25.startPoint())
+SketchArc_3 = Sketch_1.addArc(0, 2.425, 4.8355, 10.80033167999934, 0, 12.096, False)
+SketchConstraintCoincidence_31 = Sketch_1.setCoincident(SketchLine_11.result(), SketchArc_3.center())
+SketchConstraintCoincidence_32 = Sketch_1.setCoincident(SketchLine_25.endPoint(), SketchArc_3.startPoint())
+SketchConstraintCoincidence_33 = Sketch_1.setCoincident(SketchLine_11.result(), SketchArc_3.endPoint())
+SketchLine_26 = Sketch_1.addLine(0, 12.096, 0, 12.26)
+SketchConstraintCoincidence_34 = Sketch_1.setCoincident(SketchArc_3.endPoint(), SketchLine_26.startPoint())
+SketchConstraintCoincidence_35 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_26.endPoint())
+SketchConstraintDistance_11 = Sketch_1.setDistance(SketchArc_1.center(), SketchLine_12.result(), 2.425, True)
+SketchConstraintCoincidence_36 = Sketch_1.setCoincident(SketchArc_3.center(), SketchArc_1.center())
+SketchConstraintLength_5 = Sketch_1.setLength(SketchLine_26.result(), 0.164)
+SketchLine_27 = Sketch_1.addLine(0, 2.425, 4.9175, 10.94235984621998)
+SketchLine_27.setAuxiliary(True)
+SketchConstraintCoincidence_37 = Sketch_1.setCoincident(SketchArc_1.center(), SketchLine_27.startPoint())
+SketchConstraintCoincidence_38 = Sketch_1.setCoincident(SketchLine_21.endPoint(), SketchLine_27.endPoint())
+SketchConstraintCoincidence_39 = Sketch_1.setCoincident(SketchArc_3.startPoint(), SketchLine_27.result())
+SketchLine_28 = Sketch_1.addLine(0, 2.425, 5.21991026555713, 10.77860263646605)
+SketchLine_28.setAuxiliary(True)
+SketchConstraintCoincidence_40 = Sketch_1.setCoincident(SketchArc_1.center(), SketchLine_28.startPoint())
+SketchConstraintCoincidence_41 = Sketch_1.setCoincident(SketchLine_28.endPoint(), SketchLine_21.result())
+SketchConstraintCoincidence_42 = Sketch_1.setCoincident(SketchLine_28.result(), SketchLine_25.startPoint())
+SketchLine_29 = Sketch_1.addLine(0, 2.425, 5.523638941362955, 10.61413149862094)
+SketchLine_29.setAuxiliary(True)
+SketchConstraintCoincidence_43 = Sketch_1.setCoincident(SketchArc_1.center(), SketchLine_29.startPoint())
+SketchConstraintCoincidence_44 = Sketch_1.setCoincident(SketchLine_29.endPoint(), SketchLine_21.result())
+SketchConstraintCoincidence_45 = Sketch_1.setCoincident(SketchLine_29.result(), SketchLine_24.startPoint())
+SketchConstraintDistance_12 = Sketch_1.setDistance(SketchLine_25.startPoint(), SketchLine_28.endPoint(), 0.176, True)
+SketchConstraintDistance_13 = Sketch_1.setDistance(SketchLine_24.startPoint(), SketchLine_29.endPoint(), 0.212, True)
+SketchConstraintAngle_2 = Sketch_1.setAngle(SketchLine_28.result(), SketchLine_11.result(), 32, type = "Direct")
+SketchConstraintAngle_3 = Sketch_1.setAngle(SketchLine_29.result(), SketchLine_11.result(), 34, type = "Direct")
+SketchConstraintAngle_4 = Sketch_1.setAngle(SketchLine_27.result(), SketchLine_11.result(), 30, type = "Direct")
+SketchLine_30 = Sketch_1.addLine(4.79378612024245, 9.263, 5.676067550792229, 10.23944020672391)
+SketchLine_30.setAuxiliary(True)
+SketchConstraintCoincidence_46 = Sketch_1.setCoincident(SketchArc_2.center(), SketchLine_30.startPoint())
+SketchConstraintCoincidence_47 = Sketch_1.setCoincident(SketchArc_2.endPoint(), SketchLine_30.endPoint())
+SketchLine_31 = Sketch_1.addLine(4.79378612024245, 9.263, 4.79378612024245, 10.72808112087839)
+SketchLine_31.setAuxiliary(True)
+SketchConstraintCoincidence_48 = Sketch_1.setCoincident(SketchArc_2.center(), SketchLine_31.startPoint())
+SketchConstraintVertical_10 = Sketch_1.setVertical(SketchLine_31.result())
+SketchConstraintAngle_5 = Sketch_1.setAngle(SketchLine_30.result(), SketchLine_31.result(), 42.1, type = "Direct")
+SketchConstraintDistance_14 = Sketch_1.setDistance(SketchArc_2.center(), SketchLine_12.result(), 9.263, True)
+SketchConstraintCoincidence_49 = Sketch_1.setCoincident(SketchLine_31.endPoint(), SketchLine_27.result())
+SketchConstraintDistance_15 = Sketch_1.setDistance(SketchLine_22.endPoint(), SketchLine_12.result(), 9.532, True)
+SketchConstraintDistance_16 = Sketch_1.setDistance(SketchLine_18.endPoint(), SketchLine_12.result(), 9.187, True)
+SketchConstraintRadius_2 = Sketch_1.setRadius(SketchArc_1.results()[1], 9.835)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", (3.891, 0, 2.905000000000017))], model.selection("EDGE", "PartSet/OZ"), 360, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchProjection_3 = Sketch_2.addProjection(model.selection("VERTEX_5", (0, 0, 2.425)), False)
+SketchPoint_1 = SketchProjection_3.createdFeature()
+SketchProjection_4 = Sketch_2.addProjection(model.selection("EDGE", (0, 0, 12.178)), False)
+SketchLine_32 = SketchProjection_4.createdFeature()
+SketchArc_4 = Sketch_2.addArc(0, 2.425, 0, 12.178, 5.453808387550563, 10.51060344512907, True)
+SketchArc_4.setAuxiliary(True)
+SketchConstraintCoincidence_50 = Sketch_2.setCoincident(SketchPoint_1.result(), SketchArc_4.center())
+SketchConstraintCoincidence_51 = Sketch_2.setCoincident(SketchLine_32.result(), SketchArc_4.startPoint())
+SketchProjection_5 = Sketch_2.addProjection(model.selection("EDGE", (2.761819470681477, 0, 6.519565749310471)), False)
+SketchLine_33 = SketchProjection_5.createdFeature()
+SketchConstraintCoincidence_52 = Sketch_2.setCoincident(SketchArc_4.endPoint(), SketchLine_33.result())
+SketchConstraintMiddle_3 = Sketch_2.setMiddlePoint(SketchArc_4.startPoint(), SketchLine_32.result())
+SketchLine_34 = Sketch_2.addLine(0, 2.425, 3.282538500974084, 11.74164236673399)
+SketchLine_34.setAuxiliary(True)
+SketchConstraintCoincidence_53 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_34.startPoint())
+SketchLine_35 = Sketch_2.addLine(3.282538500974084, 11.74164236673399, 3.199461499025965, 11.50584963625379)
+SketchConstraintCoincidence_54 = Sketch_2.setCoincident(SketchLine_34.endPoint(), SketchLine_35.startPoint())
+SketchConstraintCoincidence_55 = Sketch_2.setCoincident(SketchLine_35.endPoint(), SketchLine_34.result())
+SketchConstraintLength_6 = Sketch_2.setLength(SketchLine_35.result(), 0.25)
+SketchPoint_2 = Sketch_2.addPoint(3.241, 11.6237460014939)
+SketchConstraintCoincidence_56 = Sketch_2.setCoincident(SketchPoint_2.coordinates(), SketchArc_4.results()[1])
+SketchConstraintCoincidence_57 = Sketch_2.setCoincident(SketchPoint_2.coordinates(), SketchLine_35.result())
+SketchProjection_6 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_36 = SketchProjection_6.createdFeature()
+SketchConstraintDistance_17 = Sketch_2.setDistance(SketchPoint_2.coordinates(), SketchLine_36.result(), 3.241, True)
+SketchArc_5 = Sketch_2.addArc(0, 2.425, 3.282538500974084, 11.74164236673399, 4.1398177019328, 11.393656164374, True)
+SketchConstraintCoincidence_58 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchArc_5.center())
+SketchConstraintCoincidence_59 = Sketch_2.setCoincident(SketchLine_34.endPoint(), SketchArc_5.startPoint())
+SketchArc_6 = Sketch_2.addArc(0, 2.425, 3.199461499025965, 11.50584963625379, 4.035044020470642, 11.16667053559353, True)
+SketchConstraintCoincidence_60 = Sketch_2.setCoincident(SketchAPI_Line(SketchLine_33).startPoint(), SketchArc_6.center())
+SketchConstraintCoincidence_61 = Sketch_2.setCoincident(SketchLine_35.endPoint(), SketchArc_6.startPoint())
+SketchLine_37 = Sketch_2.addLine(0, 2.425, 3.911506014428326, 11.49555702253677)
+SketchLine_37.setAuxiliary(True)
+SketchConstraintCoincidence_62 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_37.startPoint())
+SketchConstraintCoincidence_63 = Sketch_2.setCoincident(SketchLine_37.endPoint(), SketchArc_5.results()[1])
+SketchLine_38 = Sketch_2.addLine(0, 2.425, 4.1398177019328, 11.393656164374)
+SketchLine_38.setAuxiliary(True)
+SketchConstraintCoincidence_64 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_38.startPoint())
+SketchConstraintCoincidence_65 = Sketch_2.setCoincident(SketchArc_5.endPoint(), SketchLine_38.endPoint())
+SketchConstraintCoincidence_66 = Sketch_2.setCoincident(SketchArc_6.endPoint(), SketchLine_38.result())
+SketchConstraintDistance_18 = Sketch_2.setDistance(SketchLine_35.startPoint(), SketchLine_37.result(), 0.675, True)
+SketchConstraintMiddle_4 = Sketch_2.setMiddlePoint(SketchPoint_2.coordinates(), SketchLine_35.result())
+SketchLine_39 = Sketch_2.addLine(3.911506014428326, 11.49555702253677, 3.81251062025875, 11.26599240868435)
+SketchConstraintCoincidence_67 = Sketch_2.setCoincident(SketchLine_37.endPoint(), SketchLine_39.startPoint())
+SketchConstraintCoincidence_68 = Sketch_2.setCoincident(SketchLine_39.endPoint(), SketchArc_6.results()[1])
+SketchConstraintCoincidence_69 = Sketch_2.setCoincident(SketchLine_39.endPoint(), SketchLine_37.result())
+SketchLine_40 = Sketch_2.addLine(4.1398177019328, 11.393656164374, 4.459277785066647, 11.19096067956113)
+SketchConstraintCoincidence_70 = Sketch_2.setCoincident(SketchArc_5.endPoint(), SketchLine_40.startPoint())
+SketchProjection_7 = Sketch_2.addProjection(model.selection("EDGE_3", (2.545485308583308, 0, 11.92488050155302)), False)
+SketchArc_7 = SketchProjection_7.createdFeature()
+SketchConstraintCoincidence_71 = Sketch_2.setCoincident(SketchLine_40.endPoint(), SketchArc_7.results()[1])
+SketchLine_41 = Sketch_2.addLine(4.459277785066647, 11.19096067956113, 4.390495384356095, 11.04194790978503)
+SketchConstraintCoincidence_72 = Sketch_2.setCoincident(SketchLine_40.endPoint(), SketchLine_41.startPoint())
+SketchProjection_8 = Sketch_2.addProjection(model.selection("EDGE_3", (2.503038985186497, 0, 11.76646866604162)), False)
+SketchArc_8 = SketchProjection_8.createdFeature()
+SketchConstraintCoincidence_73 = Sketch_2.setCoincident(SketchLine_41.endPoint(), SketchArc_8.results()[1])
+SketchLine_42 = Sketch_2.addLine(4.390495384356095, 11.04194790978503, 4.035044020470642, 11.16667053559353)
+SketchConstraintCoincidence_74 = Sketch_2.setCoincident(SketchLine_41.endPoint(), SketchLine_42.startPoint())
+SketchConstraintCoincidence_75 = Sketch_2.setCoincident(SketchLine_42.endPoint(), SketchLine_38.result())
+SketchConstraintCoincidence_76 = Sketch_2.setCoincident(SketchLine_42.endPoint(), SketchArc_6.endPoint())
+SketchConstraintDistance_19 = Sketch_2.setDistance(SketchArc_5.endPoint(), SketchLine_41.result(), 0.375, True)
+SketchConstraintDistance_20 = Sketch_2.setDistance(SketchLine_39.startPoint(), SketchLine_38.result(), 0.25, True)
+SketchConstraintParallel_1 = Sketch_2.setParallel(SketchLine_41.result(), SketchLine_38.result())
+model.do()
+Revolution_2 = model.addRevolution(Part_1_doc, [model.selection("WIRE", (3.862008317343538, 0, 11.38077471561056))], model.selection("EDGE", (3.241000000000025, 0, 11.62374600149389)), 360, 0)
+Revolution_3 = model.addRevolution(Part_1_doc, [model.selection("WIRE", (4.212769702413368, 0, 11.10430922268928))], model.selection("EDGE", (3.241000000000025, 0, 11.62374600149389)), 360, 0)
+Symmetry_1 = model.addSymmetry(Part_1_doc, [model.selection("SOLID", (3.237001631529592, 7.752869270149964e-17, 11.61239765963003)), model.selection("SOLID", (3.223059230627338, 1.806177914907969e-16, 11.57282573597984))], model.selection("FACE", "PartSet/YOZ"), True)
+Cut_1 = model.addCut(Part_1_doc, [model.selection("SOLID", (9.171993615882458e-05, 1.467829010982793e-16, 1.298864381774082))], [model.selection("COMPOUND", (0, 0, 11.60508262087049))])
+Fuse_1 = model.addFuse(Part_1_doc, [model.selection("SOLID", (9.190387067667382e-05, -2.335384201710612e-09, 1.278348504308934)), model.selection("COMPOUND", (0, 0, 11.54608275997197))], removeEdges = True)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOY"), 3.6, False)
+Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", (0, 0, 3.6)))
+SketchProjection_9 = Sketch_3.addProjection(model.selection("EDGE", (-6.188, 7.578114393123822e-16, -3.45)), True)
+SketchCircle_1 = SketchProjection_9.createdFeature()
+SketchProjection_10 = Sketch_3.addProjection(model.selection("EDGE", (-6.376, 7.808347991363525e-16, -2.25)), True)
+SketchCircle_2 = SketchProjection_10.createdFeature()
+SketchArc_9 = Sketch_3.addArc(0, 0, 6.094, 0, 5.859569950090201, -1.674, True)
+SketchConstraintCoincidence_77 = Sketch_3.setCoincident(SketchAPI_Circle(SketchCircle_1).center(), SketchArc_9.center())
+SketchProjection_11 = Sketch_3.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_43 = SketchProjection_11.createdFeature()
+SketchConstraintCoincidence_78 = Sketch_3.setCoincident(SketchArc_9.startPoint(), SketchLine_43.result())
+SketchPoint_3 = Sketch_3.addPoint(6.188, 0)
+SketchConstraintCoincidence_79 = Sketch_3.setCoincident(SketchPoint_3.coordinates(), SketchLine_43.result())
+SketchConstraintCoincidence_80 = Sketch_3.setCoincident(SketchPoint_3.coordinates(), SketchCircle_1.results()[1])
+SketchConstraintDistance_21 = Sketch_3.setDistance(SketchArc_9.startPoint(), SketchPoint_3.coordinates(), 0.094, True)
+SketchConstraintDistance_22 = Sketch_3.setDistance(SketchArc_9.endPoint(), SketchLine_43.result(), 1.674, True)
+SketchLine_44 = Sketch_3.addLine(5.859569950090201, -1.674, 5.870724657144867, -1.956)
+SketchConstraintCoincidence_81 = Sketch_3.setCoincident(SketchArc_9.endPoint(), SketchLine_44.startPoint())
+SketchConstraintCoincidence_82 = Sketch_3.setCoincident(SketchLine_44.endPoint(), SketchCircle_1.results()[1])
+SketchArc_10 = Sketch_3.addArc(0, 0, 6.47, 0, 6.167249305809295, -1.956, True)
+SketchConstraintCoincidence_83 = Sketch_3.setCoincident(SketchAPI_Circle(SketchCircle_1).center(), SketchArc_10.center())
+SketchConstraintCoincidence_84 = Sketch_3.setCoincident(SketchLine_43.result(), SketchArc_10.startPoint())
+SketchLine_45 = Sketch_3.addLine(6.167249305809295, -1.956, 6.068561608816571, -1.956)
+SketchConstraintCoincidence_85 = Sketch_3.setCoincident(SketchArc_10.endPoint(), SketchLine_45.startPoint())
+SketchConstraintCoincidence_86 = Sketch_3.setCoincident(SketchLine_45.endPoint(), SketchCircle_2.results()[1])
+SketchConstraintHorizontal_8 = Sketch_3.setHorizontal(SketchLine_45.result())
+SketchConstraintCoincidence_87 = Sketch_3.setCoincident(SketchLine_44.endPoint(), SketchLine_45.result())
+SketchConstraintDistance_23 = Sketch_3.setDistance(SketchArc_10.startPoint(), SketchLine_45.result(), 1.956, True)
+SketchPoint_4 = Sketch_3.addPoint(6.376, 0)
+SketchConstraintCoincidence_88 = Sketch_3.setCoincident(SketchPoint_4.coordinates(), SketchCircle_2.results()[1])
+SketchConstraintCoincidence_89 = Sketch_3.setCoincident(SketchPoint_4.coordinates(), SketchLine_43.result())
+SketchConstraintDistance_24 = Sketch_3.setDistance(SketchPoint_4.coordinates(), SketchArc_10.startPoint(), 0.094, True)
+SketchConstraintMirror_1_objects = [SketchArc_9.results()[1], SketchLine_44.result(), SketchArc_10.results()[1], SketchLine_45.result()]
+SketchConstraintMirror_1 = Sketch_3.addMirror(SketchLine_43.result(), SketchConstraintMirror_1_objects)
+[SketchArc_11, SketchLine_46, SketchArc_12, SketchLine_47] = SketchConstraintMirror_1.mirrored()
+model.do()
+Sketch_3.changeFacesOrder([[SketchProjection_9.result(), SketchProjection_9.result(), SketchLine_46.result(), SketchArc_11.results()[1], SketchArc_9.results()[1], SketchLine_44.result()],
+                           [SketchProjection_10.result(), SketchProjection_10.result(), SketchProjection_10.result(), SketchProjection_9.result(), SketchProjection_9.result(), SketchProjection_9.result()],
+                           [SketchProjection_9.result(), SketchLine_44.result(), SketchArc_9.results()[1], SketchArc_11.results()[1], SketchLine_46.result()],
+                           [SketchProjection_10.result(), SketchLine_45.result(), SketchArc_10.results()[1], SketchArc_12.results()[1], SketchLine_47.result(), SketchProjection_10.result()]
+                          ])
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", (6.023784975045098, 0, 3.6)), model.selection("WIRE", (6.393864363926704, 0.9896456414839456, 3.6))], model.selection(), 0, 4.2)
+Sketch_4 = model.addSketch(Part_1_doc, model.standardPlane("YOZ"))
+SketchLine_48 = Sketch_4.addLine(0.75, 2.1, -0.75, 2.1)
+SketchLine_49 = Sketch_4.addLine(-0.75, 2.1, -0.75, 0.3)
+SketchLine_50 = Sketch_4.addLine(-0.75, 0.3, 0.75, 0.3)
+SketchLine_51 = Sketch_4.addLine(0.75, 0.3, 0.75, 2.1)
+SketchConstraintCoincidence_90 = Sketch_4.setCoincident(SketchLine_51.endPoint(), SketchLine_48.startPoint())
+SketchConstraintCoincidence_91 = Sketch_4.setCoincident(SketchLine_48.endPoint(), SketchLine_49.startPoint())
+SketchConstraintCoincidence_92 = Sketch_4.setCoincident(SketchLine_49.endPoint(), SketchLine_50.startPoint())
+SketchConstraintCoincidence_93 = Sketch_4.setCoincident(SketchLine_50.endPoint(), SketchLine_51.startPoint())
+SketchConstraintHorizontal_9 = Sketch_4.setHorizontal(SketchLine_48.result())
+SketchConstraintVertical_11 = Sketch_4.setVertical(SketchLine_49.result())
+SketchConstraintHorizontal_10 = Sketch_4.setHorizontal(SketchLine_50.result())
+SketchConstraintVertical_12 = Sketch_4.setVertical(SketchLine_51.result())
+SketchProjection_12 = Sketch_4.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_52 = SketchProjection_12.createdFeature()
+SketchConstraintDistance_25 = Sketch_4.setDistance(SketchLine_52.result(), SketchLine_50.endPoint(), 0.3, True)
+SketchConstraintDistance_26 = Sketch_4.setDistance(SketchLine_51.endPoint(), SketchLine_52.result(), 2.1, True)
+SketchPoint_5 = Sketch_4.addPoint(0, 2.1)
+SketchConstraintCoincidence_94 = Sketch_4.setCoincident(SketchPoint_5.coordinates(), SketchLine_48.result())
+SketchConstraintMiddle_5 = Sketch_4.setMiddlePoint(SketchLine_48.result(), SketchPoint_5.coordinates())
+SketchProjection_13 = Sketch_4.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_53 = SketchProjection_13.createdFeature()
+SketchConstraintCoincidence_95 = Sketch_4.setCoincident(SketchPoint_5.coordinates(), SketchLine_53.result())
+SketchConstraintDistance_27 = Sketch_4.setDistance(SketchPoint_5.coordinates(), SketchLine_51.endPoint(), 0.75, True)
+model.do()
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", (0, 0, 1.2))], model.selection(), 10, 0)
+Rotation_1_objects = [model.selection("SOLID", (5, 1.166200656118862e-18, 1.2)), model.selection("SOLID", (6.038396788450424, -2.054057850558325e-15, 1.5)), model.selection("SOLID", (6.316150725419533, -7.758519898162708e-14, 1.5))]
+Rotation_1 = model.addRotation(Part_1_doc, Rotation_1_objects, model.selection("EDGE", "PartSet/OZ"), -90)
+Fuse_2_objects_1 = [model.selection("SOLID", (9.187239971515918e-05, -6.832080613557312e-09, 1.282177819724956)), model.selection("SOLID", (-1.349638054860434e-15, -6.038396788450424, 1.5)), model.selection("SOLID", (-7.680624658573511e-14, -6.316150725419533, 1.5))]
+Fuse_2 = model.addFuse(Part_1_doc, Fuse_2_objects_1)
+Cut_2 = model.addCut(Part_1_doc, [model.selection("SOLID", (9.177890659903279e-05, -0.006341145656800184, 1.28239948002437))], [model.selection("SOLID", (6.393306363619619e-16, -4.999999999999998, 1.2))])
+FusionFaces_1 = model.addFusionFaces(Part_1_doc, model.selection("SOLID", (9.190526314899106e-05, 0.002297421001363739, 1.282512923455053)))
+
+model.end()
+
+model.testNbResults(FusionFaces_1, 1)
+model.testNbSubResults(FusionFaces_1, [0])
+model.testNbSubShapes(FusionFaces_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(FusionFaces_1, GeomAPI_Shape.FACE, [47])
+model.testNbSubShapes(FusionFaces_1, GeomAPI_Shape.EDGE, [202])
+model.testNbSubShapes(FusionFaces_1, GeomAPI_Shape.VERTEX, [404])
+model.testResultsVolumes(FusionFaces_1, [612.7268292882])
+
+assert(model.checkPythonDump())
\ No newline at end of file
index 14bdbf6658c60cd8c39246a5c5428455b47cb201..5fe14fd73362f36d0f21a34ae326d9b7425794fc 100644 (file)
@@ -23,6 +23,8 @@
 
 #include <ModelHighAPI_Dumper.h>
 #include <ModelHighAPI_Tools.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_FiltersFactory.h>
 
 FiltersAPI_Feature::FiltersAPI_Feature(
     const std::shared_ptr<ModelAPI_Feature> & theFeature)
@@ -57,8 +59,8 @@ void FiltersAPI_Feature::setFilters(const std::list<FilterAPIPtr>& theFilters)
   FiltersFeaturePtr aBase = std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(feature());
   for (std::list<FilterAPIPtr>::const_iterator anIt = theFilters.begin();
        anIt != theFilters.end(); ++anIt) {
-    aBase->addFilter((*anIt)->name());
-    aBase->setReversed((*anIt)->name(), (*anIt)->isReversed());
+    std::string aFilterID = aBase->addFilter((*anIt)->name());
+    aBase->setReversed(aFilterID, (*anIt)->isReversed());
 
     const std::list<FiltersAPI_Argument>& anArgs = (*anIt)->arguments();
     if (!anArgs.empty()) {
@@ -68,7 +70,7 @@ void FiltersAPI_Feature::setFilters(const std::list<FilterAPIPtr>& theFilters)
       std::list<bool> aBools;
       separateArguments(anArgs, aSelections, aTexts, aBools);
 
-      std::list<AttributePtr> aFilterArgs = aBase->filterArgs((*anIt)->name());
+      std::list<AttributePtr> aFilterArgs = aBase->filterArgs(aFilterID);
       std::list<AttributePtr>::iterator aFIt = aFilterArgs.begin();
       // first boolean argument is always "Reversed" flag
       AttributeBooleanPtr aReversedFlag =
@@ -115,9 +117,12 @@ void FiltersAPI_Feature::dump(ModelHighAPI_Dumper& theDumper) const
   const std::string& aDocName = theDumper.name(aBase->document());
   theDumper << "model.filters(" << aDocName << ", [";
 
+  ModelAPI_FiltersFactory* aFFactory = ModelAPI_Session::get()->filters();
   std::list<std::string> aFilters = aBase->filters();
   for (std::list<std::string>::iterator aFIt = aFilters.begin(); aFIt != aFilters.end(); ++aFIt) {
-    FiltersAPI_Filter aFilter(*aFIt, aBase->filterArgs(*aFIt));
+    // for multiple filters get original id
+    std::string aFilterKind = aFFactory->id(aFFactory->filter(*aFIt));
+    FiltersAPI_Filter aFilter(aFilterKind, aBase->filterArgs(*aFIt));
     if (aFIt != aFilters.begin())
       theDumper << ", ";
     aFilter.dump(theDumper);
index d80b525159d47c74ec9c1f85be48c46b12d995f1..c84636f165c02ef4da1b2af4224d4abc2e15f3c1 100644 (file)
@@ -193,4 +193,9 @@ ADD_UNIT_TESTS(
   Test2951.py
   Test17924.py
   Test17962.py
+  TestFilter_OnLine_Multi.py
+  TestFilter_OnPlane_Multi.py
+  TestFilter_OnPlaneSide_Multi.py
+  TestFilter_RelativeToSolid_Multi.py
+  TestFilter_TopoConnectedFaces_Multi.py
 )
index b609bd940ae0697d0660021b8ad1393ab1705941..773af38eb4cf8e30bb0ea401c27ec8e4b0541bb1 100644 (file)
@@ -41,6 +41,9 @@ public:
   /// Returns true for any type because it supports all selection types
   virtual bool isSupported(GeomAPI_Shape::ShapeType theType) const override;
 
+  /// Returns True if the filter can be used several times within one selection
+  virtual bool isMultiple() const { return true; }
+
   /// This method should contain the filter logic. It returns true if the given shape
   /// is accepted by the filter.
   /// \param theShape the given shape
index 62fccd1fc7bb4f56b8dee528054ef5eb20b3a9bf..94c0914894714cc9095c5fc656c00cda468221dd 100644 (file)
@@ -41,6 +41,9 @@ public:
   /// Returns true for any type because it supports all selection types
   virtual bool isSupported(GeomAPI_Shape::ShapeType theType) const override;
 
+  /// Returns True if the filter can be used several times within one selection
+  virtual bool isMultiple() const { return true; }
+
   /// This method should contain the filter logic. It returns true if the given shape
   /// is accepted by the filter.
   /// \param theShape the given shape
index 9939e45888c5b51fbdc2770abca5ea8b5bc3e3bc..eae3fee509a5e8faa3407997803620a972ac3a6c 100644 (file)
@@ -41,6 +41,9 @@ public:
   /// Returns true for any type because it supports all selection types
   virtual bool isSupported(GeomAPI_Shape::ShapeType theType) const override;
 
+  /// Returns True if the filter can be used several times within one selection
+  virtual bool isMultiple() const { return true; }
+
   /// This method should contain the filter logic. It returns true if the given shape
   /// is accepted by the filter.
   /// \param theShape the given shape
index 821b9a7ec243b649f19c9459f05889c368efc0c4..70b616cc013f7604bd99932bd241bc80917d0a3d 100644 (file)
@@ -41,6 +41,9 @@ public:
   /// Returns true for any type because it supports all selection types
   virtual bool isSupported(GeomAPI_Shape::ShapeType theType) const override;
 
+  /// Returns True if the filter can be used several times within one selection
+  virtual bool isMultiple() const { return true; }
+
   /// This method should contain the filter logic. It returns true if the given shape
   /// is accepted by the filter.
   /// \param theShape the given shape
index 7fe056aba5aee9fadbf2b5d2f65023ac9b21a4e8..23343cf617bd5ce7bda89e65c0769dfe518233c8 100644 (file)
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_FiltersFactory.h>
 #include <ModelAPI_Session.h>
+#include <sstream>
 
 // identifier of the reverse flag of a filter
 static const std::string kReverseAttrID("");
 
-void FiltersPlugin_Selection::addFilter(const std::string theFilterID)
+std::string FiltersPlugin_Selection::addFilter(const std::string theFilterID)
 {
   ModelAPI_FiltersFactory* aFactory = ModelAPI_Session::get()->filters();
   FilterPtr aFilter = aFactory->filter(theFilterID);
+
+  std::string aFilterID = theFilterID;
+  if (aFilter->isMultiple()) { // check that there is already such filter, so, increment ID
+    std::list<std::string> aFilters;
+    data()->allGroups(aFilters);
+    for(int anID = 0; true; anID++) {
+      if (anID != 0) {
+        std::ostringstream aStream;
+        aStream<<"_"<<anID<<"_"<<theFilterID;
+        aFilterID = aStream.str();
+      }
+      std::list<std::string>::iterator aFiltersIDs = aFilters.begin();
+      for(; aFiltersIDs != aFilters.end(); aFiltersIDs++) {
+        if (*aFiltersIDs == aFilterID)
+          break;
+      }
+      if (aFiltersIDs == aFilters.end())
+        break;
+    }
+  }
+
   if (aFilter.get()) {
     std::shared_ptr<ModelAPI_AttributeBoolean> aBool =
       std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(data()->addFloatingAttribute(
-        kReverseAttrID, ModelAPI_AttributeBoolean::typeId(), theFilterID));
+        kReverseAttrID, ModelAPI_AttributeBoolean::typeId(), aFilterID));
     aBool->setValue(false); // not reversed by default
     // to add attributes related to the filter
     ModelAPI_FiltersArgs anArgs;
     anArgs.setFeature(std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(data()->owner()));
-    anArgs.setFilter(theFilterID);
+    anArgs.setFilter(aFilterID);
     aFilter->initAttributes(anArgs);
   }
+  return aFilterID;
 }
 
 void FiltersPlugin_Selection::removeFilter(const std::string theFilterID)
index 8fe3850a72d2eab2d200d6c6469a19c640ec7b23..1c494582d5a72150784f0e48fad3f6e1396ceb40 100644 (file)
@@ -59,7 +59,8 @@ public:
   // methods related to the filters management
 
   /// Adds a filter to the feature. Also initializes arguments of this filter.
-  FILTERS_EXPORT virtual void addFilter(const std::string theFilterID) override;
+  /// Returns the real identifier of the filter.
+  FILTERS_EXPORT virtual std::string addFilter(const std::string theFilterID) override;
 
   /// Removes an existing filter from the feature.
   FILTERS_EXPORT virtual void removeFilter(const std::string theFilterID) override;
index 6f27040e9da26f4c6f54373cd33c92b17a88f352..9e0c61670344c7e982eef982a1ba41a08b365948 100644 (file)
@@ -48,6 +48,10 @@ class FiltersPlugin_TopoConnectedFaces(ModelAPI_Filter):
     """ Supported types of filtered shapes """
     return theType == GeomAPI_Shape.FACE
 
+  def isMultiple(self):
+    """ Returns True if the filter can be used several times within one selection """
+    return True
+
   def isOk(self, theShape, theResult, theArgs):
     """ True if theShape is applicable for the filter """
     selectedShapeAttr = modelAPI_AttributeSelection(theArgs.argument("Shape"))
diff --git a/src/FiltersPlugin/Test/TestFilter_OnLine_Multi.py b/src/FiltersPlugin/Test/TestFilter_OnLine_Multi.py
new file mode 100644 (file)
index 0000000..9e23a85
--- /dev/null
@@ -0,0 +1,46 @@
+# Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+# two filters with two edges each
+Filters = model.filters(Part_1_doc, [
+  model.addFilter(name = "OnLine", args = [model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Right]")]),
+  model.addFilter(name = "OnLine", args = [model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Bottom]")])])
+model.end()
+
+# 2 vertices on intersection of edges
+Reference = {
+    model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Left][Box_1_1/Top]"): True,
+    model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Left][Box_1_1/Top]"): False,
+    model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Left][Box_1_1/Bottom]"): False,
+    model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Right][Box_1_1/Top]"): False,
+    model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Right][Box_1_1/Top]"): False,
+    model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Left][Box_1_1/Bottom]"): False,
+    model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Right][Box_1_1/Bottom]"): True,
+    model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Right][Box_1_1/Bottom]"): False
+}
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_OnPlaneSide_Multi.py b/src/FiltersPlugin/Test/TestFilter_OnPlaneSide_Multi.py
new file mode 100644 (file)
index 0000000..49f94d8
--- /dev/null
@@ -0,0 +1,88 @@
+# Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+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(20, 23, -19, 23)
+SketchLine_2 = Sketch_1.addLine(-19, 23, -19, -21)
+SketchLine_3 = Sketch_1.addLine(-19, -21, 20, -21)
+SketchLine_4 = Sketch_1.addLine(20, -21, 20, 23)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f")], model.selection(), 30, 0)
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), 0, 20, [model.selection("SOLID", "Extrusion_1_1")])
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_5 = Sketch_2.addLine(34, 36, -11, 36)
+SketchLine_6 = Sketch_2.addLine(-11, 36, -11, -10)
+SketchLine_7 = Sketch_2.addLine(-11, -10, 34, -10)
+SketchLine_8 = Sketch_2.addLine(34, -10, 34, 36)
+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_3 = Sketch_2.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_6.result())
+SketchConstraintHorizontal_4 = Sketch_2.setHorizontal(SketchLine_7.result())
+SketchConstraintVertical_4 = Sketch_2.setVertical(SketchLine_8.result())
+ExtrusionCut_1.setNestedSketch(Sketch_2)
+# two filters with different faces each, the second is reversed
+Filters = model.filters(Part_1_doc, [
+  model.addFilter(name = "OnPlaneSide", args = [model.selection("FACE", "ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7")]),
+  model.addFilter(name = "OnPlaneSide", exclude = True, args = [model.selection("FACE", "ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6")]),
+  model.addFilter(name = "OnPlaneSide", args = [model.selection("FACE", "ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face")])])
+model.end()
+
+# 5 edges are in result
+Reference = {
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_2]"): True,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Modified_Face&Extrusion_1_1/To_Face]"): True,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6]"): True,
+    model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_2][ExtrusionCut_1_1/Modified_Face&Extrusion_1_1/To_Face]"): True,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Extrusion_1_1/To_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6]"): True,
+    model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_2][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3]"): False,
+    model.selection("EDGE", "[Extrusion_1_1/From_Face][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Extrusion_1_1/To_Face][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Extrusion_1_1/To_Face][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Extrusion_1_1/To_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7]"): False,
+    model.selection("EDGE", "([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4])([ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7])([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7])"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6][ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face]"): False,
+    model.selection("EDGE", "[Extrusion_1_1/From_Face][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4]"): False,
+    model.selection("EDGE", "[Extrusion_1_1/From_Face][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_2]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][Extrusion_1_1/From_Face]"): False,
+    model.selection("EDGE", "([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6])([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4])([ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6][ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face])"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4]"): False,
+}
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_OnPlane_Multi.py b/src/FiltersPlugin/Test/TestFilter_OnPlane_Multi.py
new file mode 100644 (file)
index 0000000..dbe25bc
--- /dev/null
@@ -0,0 +1,143 @@
+# Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [], model.selection(), 20, 0)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(40, 30, 5, 30)
+SketchLine_2 = Sketch_1.addLine(5, 30, 5, 3)
+SketchLine_3 = Sketch_1.addLine(5, 3, 40, 3)
+SketchLine_4 = Sketch_1.addLine(40, 3, 40, 30)
+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())
+Extrusion_1.setNestedSketch(Sketch_1)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_5 = Sketch_2.addLine(18, 39, 29, 39)
+SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_5.result())
+SketchLine_6 = Sketch_2.addLine(29, 39, 29, 21)
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_6.result())
+SketchLine_7 = Sketch_2.addLine(29, 21, 46, 21)
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintHorizontal_4 = Sketch_2.setHorizontal(SketchLine_7.result())
+SketchLine_8 = Sketch_2.addLine(46, 21, 46, 11)
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintVertical_4 = Sketch_2.setVertical(SketchLine_8.result())
+SketchLine_9 = Sketch_2.addLine(46, 11, 29, 11)
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchConstraintHorizontal_5 = Sketch_2.setHorizontal(SketchLine_9.result())
+SketchLine_10 = Sketch_2.addLine(29, 11, 29, -3)
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint())
+SketchConstraintVertical_5 = Sketch_2.setVertical(SketchLine_10.result())
+SketchLine_11 = Sketch_2.addLine(29, -3, 18, -3)
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint())
+SketchLine_12 = Sketch_2.addLine(18, -3, 18, 11)
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_11.endPoint(), SketchLine_12.startPoint())
+SketchConstraintVertical_6 = Sketch_2.setVertical(SketchLine_12.result())
+SketchLine_13 = Sketch_2.addLine(18, 11, 3, 11)
+SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchLine_12.endPoint(), SketchLine_13.startPoint())
+SketchLine_14 = Sketch_2.addLine(3, 11, 3, 21)
+SketchConstraintCoincidence_13 = Sketch_2.setCoincident(SketchLine_13.endPoint(), SketchLine_14.startPoint())
+SketchConstraintVertical_7 = Sketch_2.setVertical(SketchLine_14.result())
+SketchLine_15 = Sketch_2.addLine(3, 21, 18, 21)
+SketchConstraintCoincidence_14 = Sketch_2.setCoincident(SketchLine_14.endPoint(), SketchLine_15.startPoint())
+SketchConstraintHorizontal_6 = Sketch_2.setHorizontal(SketchLine_15.result())
+SketchLine_16 = Sketch_2.addLine(18, 21, 18, 39)
+SketchConstraintCoincidence_15 = Sketch_2.setCoincident(SketchLine_15.endPoint(), SketchLine_16.startPoint())
+SketchConstraintCoincidence_16 = Sketch_2.setCoincident(SketchLine_5.startPoint(), SketchLine_16.endPoint())
+SketchConstraintVertical_8 = Sketch_2.setVertical(SketchLine_16.result())
+SketchConstraintHorizontal_7 = Sketch_2.setHorizontal(SketchLine_13.result())
+SketchConstraintHorizontal_8 = Sketch_2.setHorizontal(SketchLine_11.result())
+SketchConstraintCoincidence_17 = Sketch_2.setCoincident(SketchLine_16.result(), SketchLine_12.endPoint())
+SketchConstraintCoincidence_18 = Sketch_2.setCoincident(SketchLine_6.result(), SketchLine_10.startPoint())
+SketchConstraintCoincidence_19 = Sketch_2.setCoincident(SketchLine_15.result(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_20 = Sketch_2.setCoincident(SketchLine_13.result(), SketchLine_10.startPoint())
+model.do()
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_16r-SketchLine_15r-SketchLine_14r-SketchLine_13r-SketchLine_12r-SketchLine_11r-SketchLine_10r-SketchLine_9r-SketchLine_8r-SketchLine_7r-SketchLine_6r-SketchLine_5r")], model.selection(), 0, 10, [model.selection("SOLID", "Extrusion_1_1")])
+# two smae filters with two planes each
+Filters = model.filters(Part_1_doc, [
+  model.addFilter(name = "OnPlane", args = [model.selection("FACE", "ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16"), model.selection("FACE", "ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6")]),
+  model.addFilter(name = "OnPlane", args = [model.selection("FACE", "ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15"), model.selection("FACE", "ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13")])])
+
+model.end()
+
+# 4 edges are in result: intersection of pairs of planes
+Reference = {
+    model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15]"): True,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7]"): True,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12]"): True,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10]"): True,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)2(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10)2]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)2(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10)2]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12]"): False,
+    model.selection("EDGE", "[(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)2(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10)2][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12]"): False,
+    model.selection("EDGE", "([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13])([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15])([ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13])([ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15])"): False,
+    model.selection("EDGE", "[(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)2(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10)2][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13]"): False,
+    model.selection("EDGE", "[(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15)(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13)2][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15]"): False,
+    model.selection("EDGE", "[Extrusion_1_1/From_Face][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16][ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15)(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13)2]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15)(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13)2]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16]"): False,
+    model.selection("EDGE", "[(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15)(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13)2][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16]"): False,
+    model.selection("EDGE", "[Extrusion_1_1/From_Face][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7)(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9)2]"): False,
+    model.selection("EDGE", "([ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10])([ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12])([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10])([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12])"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)2(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12)2]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][Extrusion_1_1/From_Face]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10]"): False,
+    model.selection("EDGE", "([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16])([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6])([ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16][ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face])([ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6])"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)2(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12)2]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)2(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12)2]"): False,
+    model.selection("EDGE", "([ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7])([ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9])([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7])([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9])"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)2(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12)2]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9]"): False,
+    model.selection("EDGE", "[Extrusion_1_1/From_Face][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7]"): False,
+    model.selection("EDGE", "[(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7)(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9)2][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4]"): False,
+    model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7)(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9)2]"): False,
+    model.selection("EDGE", "[(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7)(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9)2][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4]"): False,
+}
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_RelativeToSolid_Multi.py b/src/FiltersPlugin/Test/TestFilter_RelativeToSolid_Multi.py
new file mode 100644 (file)
index 0000000..1007428
--- /dev/null
@@ -0,0 +1,61 @@
+# Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_1.addCircle(18.85055999990443, 20.40038647424626, 12.41450630559296)
+SketchCircle_2 = Sketch_1.addCircle(25.08744138385902, 26.81117176326632, 2.271058181559462)
+SketchCircle_2.setName("SketchCircle_3")
+SketchCircle_2.result().setName("SketchCircle_3")
+SketchCircle_2.results()[1].setName("SketchCircle_3_2")
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_3 = Sketch_2.addCircle(30.95603034069762, 31.40670583726882, 10.95693005417035)
+SketchCircle_3.setName("SketchCircle_4")
+SketchCircle_3.result().setName("SketchCircle_4")
+SketchCircle_3.results()[1].setName("SketchCircle_4_2")
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_1/Face-SketchCircle_1_2r-SketchCircle_3_2r_wire")], model.selection(), 50, 0)
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_2/Face-SketchCircle_4_2r_wire")], model.selection(), 40, -10)
+Extrusion_3 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_3_2f")], model.selection(), 20, -30)
+# Two filters to search all face inside of two solids
+Filters = model.filters(Part_1_doc, [
+  model.addFilter(name = "RelativeToSolid", args = [model.selection("SOLID", "Extrusion_1_1"), "in"]),
+  model.addFilter(name = "RelativeToSolid", args = [model.selection("SOLID", "Extrusion_2_1"), "in"])])
+model.end()
+
+# 3 faces of internal cylinder is inside
+Reference = {
+    model.selection("FACE", "Extrusion_3_1/Generated_Face&Sketch_1/SketchCircle_3_2"): True,
+    model.selection("FACE", "Extrusion_3_1/From_Face"): True,
+    model.selection("FACE", "Extrusion_3_1/To_Face"): True,
+    model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2"): False,
+    model.selection("FACE", "Extrusion_1_1/From_Face"): False,
+    model.selection("FACE", "Extrusion_1_1/To_Face"): False,
+    model.selection("FACE", "Extrusion_2_1/Generated_Face&Sketch_2/SketchCircle_4_2"): False,
+    model.selection("FACE", "Extrusion_2_1/From_Face"): False,
+    model.selection("FACE", "Extrusion_2_1/To_Face"): False
+}
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Multi.py b/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Multi.py
new file mode 100644 (file)
index 0000000..84f263c
--- /dev/null
@@ -0,0 +1,94 @@
+# Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from SketchAPI import *
+from GeomAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-21.08194442253927, 8.656344751543489, 0, 30)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_2 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.result())
+SketchLine_3 = Sketch_1.addLine(0, 30, 25.98076211353316, 15)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(25.98076211353316, 15, 18.03758667002239, -13.92932705531892)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(18.03758667002239, -13.92932705531892, -11.39496253934835, -19.73665406849542)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_1.addLine(-11.39496253934835, -19.73665406849542, -21.08194442253927, 8.656344751543489)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_6.endPoint())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_3.result(), SketchLine_5.result())
+SketchConstraintEqual_2 = Sketch_1.setEqual(SketchLine_4.result(), SketchLine_1.result())
+SketchConstraintEqual_3 = Sketch_1.setEqual(SketchLine_6.result(), SketchLine_3.result())
+SketchConstraintEqual_4 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_5.result())
+SketchLine_7 = Sketch_1.addLine(-11.39496253934835, -19.73665406849542, 0, 0)
+SketchLine_7.setAuxiliary(True)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_2).startPoint(), SketchLine_7.endPoint())
+SketchLine_8 = Sketch_1.addLine(-21.08194442253927, 8.656344751543489, 0, 0)
+SketchLine_8.setAuxiliary(True)
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_2).startPoint(), SketchLine_8.endPoint())
+SketchLine_9 = Sketch_1.addLine(0, 30, 0, 0)
+SketchLine_9.setAuxiliary(True)
+SketchConstraintCoincidence_11 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_9.startPoint())
+SketchConstraintCoincidence_12 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_2).startPoint(), SketchLine_9.endPoint())
+SketchLine_10 = Sketch_1.addLine(25.98076211353316, 15, 0, 0)
+SketchLine_10.setAuxiliary(True)
+SketchConstraintCoincidence_13 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_10.startPoint())
+SketchConstraintCoincidence_14 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_2).startPoint(), SketchLine_10.endPoint())
+SketchLine_11 = Sketch_1.addLine(18.03758667002239, -13.92932705531892, 0, 0)
+SketchLine_11.setAuxiliary(True)
+SketchConstraintCoincidence_15 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_11.startPoint())
+SketchConstraintCoincidence_16 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_2).startPoint(), SketchLine_11.endPoint())
+SketchConstraintEqual_5 = Sketch_1.setEqual(SketchLine_7.result(), SketchLine_8.result())
+SketchConstraintEqual_6 = Sketch_1.setEqual(SketchLine_11.result(), SketchLine_7.result())
+SketchConstraintEqual_7 = Sketch_1.setEqual(SketchLine_10.result(), SketchLine_9.result())
+SketchConstraintEqual_8 = Sketch_1.setEqual(SketchLine_10.result(), SketchLine_3.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_3.result(), 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_6r-SketchLine_5r-SketchLine_4r-SketchLine_3r-SketchLine_1r")], model.selection(), 10, 0)
+model.do()
+# Two filters TopoConnectedFaces and not horizontal to search lateral face connected to two selected faces
+Filters = model.filters(Part_1_doc, [
+  model.addFilter(name = "TopoConnectedFaces", args = [model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_5"), False]),
+  model.addFilter(name = "HorizontalFaces", exclude = True),
+  model.addFilter(name = "TopoConnectedFaces", args = [model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3"), False])])
+model.end()
+
+Result = Extrusion_1.feature().firstResult()
+exp = GeomAPI_ShapeExplorer(Result.shape(), GeomAPI_Shape.FACE)
+Reference = {}
+# 1 face is in result - between two selected faces for filters
+Reference[model.selection(Result, exp.current())] = False; exp.next()
+Reference[model.selection(Result, exp.current())] = False;  exp.next()
+Reference[model.selection(Result, exp.current())] = True; exp.next()
+Reference[model.selection(Result, exp.current())] = False;  exp.next()
+Reference[model.selection(Result, exp.current())] = False;  exp.next()
+Reference[model.selection(Result, exp.current())] = False;  exp.next()
+Reference[model.selection(Result, exp.current())] = False;  exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
index 8e6d0babdd9daf0881f1a542830dd42626fd0cfc..1e9aade08d1ab575aeadfa7951dfd6dd90df2e4d 100644 (file)
@@ -33,6 +33,8 @@ In this panel:
 .. centered::
   Filters **Horizontal faces** and **On plane** added to the property panel.
   
+If filter is implemented as "Multiple", several instances of this filter may be added in one selection. Otherwise the added filter is removed from the "Add new filter..." list.
+
 Each filter item can be deleted with help of |delete.icon| button. A filter can be reverced with help of toggle button |plus.icon|/|minus.icon|. Also a filter could have input fields in case
 if the filter has arguments.
 
@@ -73,7 +75,7 @@ By default, the result of Selection feature all selectable entities from all Sha
 
 - **Result type:** Any
 - **Argument:** Any Shape, multiple OR selection accepted
-- **Algorithm:** Returns the shapes which have the similar underlying geometry of the given Shape. Like all faces laying of the same geometrical surface or edges laying of the same geometrical surface or edges laying on the line.
+- **Algorithm:** Returns the shapes which have the similar underlying geometry of the given Shape. Like all faces laying of the same geometrical surface or edges laying on the line.
 
 **On plane side**
 
index 45f57fa5a241a7a8b3012b8d0fe7c5f8a8d65b2e..ac3a6ff4d2f2341954e610a386b62647ed0371f6 100644 (file)
@@ -92,6 +92,7 @@ void GeomAPI_AISObject::createShape(std::shared_ptr<GeomAPI_Shape> theShape)
       aDrawer->PointAspect()->SetTypeOfMarker(Aspect_TOM_PLUS);
     else
       aDrawer->SetPointAspect(new Prs3d_PointAspect(Aspect_TOM_PLUS, Quantity_NOC_YELLOW, 1.));
+    aDrawer->SetIsoOnPlane(false);
     setImpl(new Handle(AIS_InteractiveObject)(aShape));
   }
 }
index ce7788b54eacc00f2339011271663f62e27b0435..78a10ac3c5ffb0bb6940a29828e1a07dca6c034d 100644 (file)
@@ -32,6 +32,7 @@
 #include <BRepAlgoAPI_Section.hxx>
 #include <BRepBndLib.hxx>
 #include <BRepBuilderAPI_FindPlane.hxx>
+#include <BRepBuilderAPI_Copy.hxx>
 #include <BRepExtrema_DistShapeShape.hxx>
 #include <BRepTools.hxx>
 #include <Bnd_Box.hxx>
@@ -638,11 +639,17 @@ GeomPointPtr GeomAPI_Shape::middlePoint() const
 }
 
 // LCOV_EXCL_START
-std::string GeomAPI_Shape::getShapeStream() const
+std::string GeomAPI_Shape::getShapeStream(const bool theWithTriangulation) const
 {
   std::ostringstream aStream;
   const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
-  BRepTools::Write(aShape, aStream);
+  if (!theWithTriangulation) { // make a copy of shape without triangulation
+    BRepBuilderAPI_Copy aCopy(aShape, Standard_False, Standard_False);
+    const TopoDS_Shape& aCopyShape = aCopy.Shape();
+    BRepTools::Write(aCopyShape, aStream);
+  } else {
+    BRepTools::Write(aShape, aStream);
+  }
   return aStream.str();
 }
 // LCOV_EXCL_STOP
index ec6e5737475df793f1c9dc9c5814a9f27b47b778..61fd4f5bc36372462ed275eaed21fa02e3edb47d 100644 (file)
@@ -192,7 +192,7 @@ public:
 
   /// Returns the shape as BRep stream
   GEOMAPI_EXPORT
-  std::string getShapeStream() const;
+  std::string getShapeStream(const bool theWithTriangulation = true) const;
 
   /// Returns intersection of shapes
   GEOMAPI_EXPORT
index 10dfe84b296c08413ce33958f1bf576bd0711ab9..5c85b0237b5f44592c577b59afa127a7d3a5fbb7 100644 (file)
@@ -1381,7 +1381,8 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr<Model_Document>
   TDF_Label theAccessLabel,
   std::list<ResultPtr>& theResults, TopTools_ListOfShape& theValShapes)
 {
-  std::set<ResultPtr> aResults; // to avoid duplicates, new context, null if deleted
+  std::list<ResultPtr> aResults; // keep order, new context, null if deleted
+  std::set<ResultPtr> aResultsSet; // to avoid duplicates
   // iterate context and shape, but also if it is sub-shape of main shape, check also it
   TopTools_ListOfShape aContextList;
   aContextList.Append(theContShape);
@@ -1417,23 +1418,32 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr<Model_Document>
       Handle(TNaming_NamedShape) aNewNS;
       aModifIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNewNS);
       if (aNewNS->Evolution() == TNaming_MODIFY || aNewNS->Evolution() == TNaming_GENERATED) {
-        aResults.insert(aModifierObj);
+        if (aResultsSet.find(aModifierObj) == aResultsSet.end()) {
+          aResultsSet.insert(aModifierObj);
+          aResults.push_back(aModifierObj);
+        }
       } else if (aNewNS->Evolution() == TNaming_DELETE) { // a shape was deleted => result is empty
-        aResults.insert(ResultPtr());
+        aResults.push_back(ResultPtr());
       } else { // not-processed modification => don't support it
         continue;
       }
     }
   }
   // if there exist context composite and sub-result(s), leave only sub(s)
-  for(std::set<ResultPtr>::iterator aResIter = aResults.begin(); aResIter != aResults.end();) {
+  for(std::list<ResultPtr>::iterator aResIter = aResults.begin(); aResIter != aResults.end();) {
     ResultPtr aParent = ModelAPI_Tools::bodyOwner(*aResIter);
     for(; aParent.get(); aParent = ModelAPI_Tools::bodyOwner(aParent))
-      if (aResults.count(aParent))
+      if (aResultsSet.count(aParent))
         break;
-    if (aParent.get()) { // erase from set, so, restart iteration
-      aResults.erase(aParent);
-      aResIter = aResults.begin();
+    if (aParent.get()) {
+      aResultsSet.erase(aParent);
+      for(std::list<ResultPtr>::iterator anIt = aResults.begin(); anIt != aResults.end(); anIt++) {
+        if (*anIt == aParent) {
+          aResults.erase(anIt);
+          aResIter = aResults.begin(); // erase from set, so, restart iteration
+          break;
+        }
+      }
     } else aResIter++;
   }
 
@@ -1458,7 +1468,7 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr<Model_Document>
           continue;
         if (aRefShape->impl<TopoDS_Shape>().IsSame(theContShape)) {
           // add the new context result with the same shape
-          aResults.insert(aRefBody);
+          aResults.push_back(aRefBody);
         }
       }
       if (aResults.empty())
@@ -1468,7 +1478,6 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr<Model_Document>
   }
   if (myParent && myParent->isMakeCopy()) {
     // check there are copies before the new results, so, make a copy
-    std::set<ResultPtr>::iterator aResIter = aResults.begin();
     std::list<ObjectPtr> aCopyContext;
     std::list<GeomShapePtr> aCopyVals;
     // features between the new and the old: check the "Move" interface to get a copy
@@ -1527,7 +1536,7 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr<Model_Document>
     return false;
 
   // iterate all results to find further modifications
-  std::set<ResultPtr>::iterator aResIter = aResults.begin();
+  std::list<ResultPtr>::iterator aResIter = aResults.begin();
   for(aResIter = aResults.begin(); aResIter != aResults.end(); aResIter++) {
     if (aResIter->get() != NULL) {
       ResultPtr aNewResObj = *aResIter;
index 170190ef66879e1e44f82e71e4be35340ea4f2ca..9e7b0b6ff1144cf9957a4cf6599808398844e791 100644 (file)
@@ -269,6 +269,16 @@ void Model_AttributeSelectionList::remove(const std::set<int>& theIndices)
   }
 }
 
+void Model_AttributeSelectionList::copyTo(AttributeSelectionListPtr theTarget) const
+{
+  std::shared_ptr<Model_AttributeSelectionList> aTarget =
+    std::dynamic_pointer_cast<Model_AttributeSelectionList>(theTarget);
+  if (aTarget) {
+    copyAttrs(myLab, aTarget->myLab);
+    aTarget->reinit();
+  }
+}
+
 int Model_AttributeSelectionList::size()
 {
   return mySize->Get();
index 3ed3e2804aca7e396befd8f711a858dd1829a9d2..2db50d9b400f5b49254550a7493886c7bcbd24ec 100644 (file)
@@ -66,6 +66,9 @@ public:
   MODEL_EXPORT virtual void append(const std::string& theType, const std::string& theContextName,
                                    const int theIndex);
 
+  /// Copy the selection list to the destination attribute
+  MODEL_EXPORT virtual void copyTo(AttributeSelectionListPtr theTarget) const;
+
   /// Reset temporary stored values
   virtual void removeTemporaryValues();
 
index 2c5c5c38187c29e3b3d63b96730e679d3294dd82..fd85d452a0a894c34f87483d931c78823968ce60 100644 (file)
@@ -365,7 +365,8 @@ void Model_BodyBuilder::storeModified(const std::list<GeomShapePtr>& theOldShape
   std::list<GeomShapePtr>::const_iterator anOldIter = theOldShapes.cbegin();
   for(; anOldIter != theOldShapes.cend(); anOldIter++) {
     // compounds may cause crash if call "modified"
-    bool aStore = (*anOldIter)->isCompound() || (*anOldIter)->isShell() || (*anOldIter)->isWire();
+    bool aStore = (*anOldIter)->isCompound() || (*anOldIter)->isShell() || (*anOldIter)->isWire() ||
+               (*anOldIter)->isCompSolid();
     if (!aStore) {
       ListOfShape aNews; // check this old really modifies theNewShape
       theMakeShape->modified(*anOldIter, aNews);
index a47d95c2fa49b1db4321432f53b7515651e303f6..41f9980b3d60ed0ea435515b477b236452023090 100644 (file)
@@ -458,7 +458,8 @@ void Model_Data::sendAttributeUpdated(ModelAPI_Attribute* theAttr)
   } else {
     // trim: need to redisplay or set color in the python script
     if (myObject && (theAttr->attributeType() == "Point2D" || theAttr->id() == "Color" ||
-      theAttr->id() == "Transparency" || theAttr->id() == "Deflection")) {
+      theAttr->id() == "Transparency" || theAttr->id() == "Deflection" ||
+      theAttr->id() == "Iso_lines" || theAttr->id() == "Show_Iso_lines")) {
       static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
       ModelAPI_EventCreator::get()->sendUpdated(myObject, anEvent);
     }
index f84febdfcb599a7d476ef74903c06387a630056a..d02682d68caafbcec06f9ba8fec193fe86cd2df2 100644 (file)
@@ -40,6 +40,21 @@ struct FilterArgs {
   std::string myFilterID;
 };
 
+/// Returns the filter ID without the filter index
+static std::string pureFilterID(const std::string& theID)
+{
+  // remove from aPure "_" + number + "_" starting part
+  if (theID.size() > 3 && theID[0] == '_') {
+    int aNumDigits = 0;
+    while(theID[aNumDigits + 1] < '9' && theID[aNumDigits + 1] > '0')
+      aNumDigits++;
+    if (aNumDigits && theID[aNumDigits + 1] == '_') {
+      return theID.substr(aNumDigits + 2);
+    }
+  }
+  return theID;
+}
+
 bool Model_FiltersFactory::isValid(FeaturePtr theFiltersFeature,
                                    ResultPtr theResult,
                                    GeomShapePtr theShape)
@@ -63,7 +78,8 @@ bool Model_FiltersFactory::isValid(FeaturePtr theFiltersFeature,
   theFiltersFeature->data()->allGroups(aGroups);
   for(std::list<std::string>::iterator aGIter = aGroups.begin(); aGIter != aGroups.end(); aGIter++)
   {
-    if (myFilters.find(*aGIter) == myFilters.end())
+    std::string aPureID = pureFilterID(*aGIter);
+    if (myFilters.find(aPureID) == myFilters.end())
       continue;
     std::list<std::shared_ptr<ModelAPI_Attribute> > anAttrs;
     theFiltersFeature->data()->attributesOfGroup(*aGIter, anAttrs);
@@ -73,7 +89,7 @@ bool Model_FiltersFactory::isValid(FeaturePtr theFiltersFeature,
       if (anArgID.empty()) { // reverse flag
         std::shared_ptr<ModelAPI_AttributeBoolean> aReverse =
           std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(*anAttrIter);
-        FilterArgs aFArgs = { myFilters[*aGIter] , aReverse->value() , *aGIter };
+        FilterArgs aFArgs = { myFilters[aPureID] , aReverse->value() , *aGIter };
         aFilters.push_back(aFArgs);
 
       } else {
@@ -113,7 +129,8 @@ std::list<FilterPtr> Model_FiltersFactory::filters(GeomAPI_Shape::ShapeType theT
 
 FilterPtr Model_FiltersFactory::filter(std::string theID)
 {
-  std::map<std::string, FilterPtr>::iterator aFound = myFilters.find(theID);
+  std::string aPureID = pureFilterID(theID);
+  std::map<std::string, FilterPtr>::iterator aFound = myFilters.find(aPureID);
   return aFound == myFilters.end() ? FilterPtr() : aFound->second;
 }
 
index 152aaaeb84ee27a8c4211c1c3d3618dae7221f50..047a4c10586ec96004bdfa7487a6aa89d15ecceb 100644 (file)
@@ -1490,17 +1490,20 @@ std::shared_ptr<ModelAPI_Folder> Model_Objects::findFolder(
     if (theBelow)
       continue;
 
-    // if feature is in sub-component, skip it
-    FeaturePtr aCurFeature = feature(aCurLabel);
-    if (isSkippedFeature(aCurFeature))
-      continue;
-
+    // issue #18733: check for the last feature in folder before checking the sub-feature,
+    //               because the folder may end by the feature which is
+    //               neither a sub-feature nor a feature in history.
     if (!aLastFeatureInFolder.IsNull()) {
       if (IsEqual(aCurLabel, aLastFeatureInFolder))
         aLastFeatureInFolder.Nullify(); // the last feature in the folder is achieved
       continue;
     }
 
+    // if feature is in sub-component, skip it
+    FeaturePtr aCurFeature = feature(aCurLabel);
+    if (isSkippedFeature(aCurFeature))
+      continue;
+
     const ObjectPtr& aFolderObj = folder(aCurLabel);
     if (aFolderObj.get()) {
       aFoundFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(aFolderObj);
index 4d19917385d6b25111e39640d112c97475bee7fe..62b47c7cbddcf468710296cbe5fbe00c5594bf87 100644 (file)
@@ -408,7 +408,7 @@ void Model_ResultBody::computeOldForSub(const GeomShapePtr& theSub,
     for (TopTools_MapOfShape::Iterator anOldIter(anOldSubs); anOldIter.More(); anOldIter.Next()) {
       TopoDS_Shape anOldShape = anOldIter.Value();
       if (anOldShape.ShapeType() == TopAbs_COMPOUND || anOldShape.ShapeType() == TopAbs_SHELL ||
-          anOldShape.ShapeType() == TopAbs_WIRE)
+          anOldShape.ShapeType() == TopAbs_WIRE || anOldShape.ShapeType() == TopAbs_COMPSOLID)
         continue; // container old-shapes are not supported by the history, may cause crash
       GeomShapePtr anOldSub(new GeomAPI_Shape);
       anOldSub->setImpl<TopoDS_Shape>(new TopoDS_Shape(anOldShape));
index f89eff7d738ec5632febcd3f19e9f44ff4b2046a..fd752bc7282da60eb110f4a8ae70d5e44b590378 100644 (file)
@@ -54,6 +54,7 @@ void Model_ResultPart::initAttributes()
   data()->addAttribute(BASE_REF_ID(), ModelAPI_AttributeReference::typeId());
   data()->addAttribute(DEFLECTION_ID(), ModelAPI_AttributeDouble::typeId());
   data()->addAttribute(TRANSPARENCY_ID(), ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(ISO_LINES_ID(), ModelAPI_AttributeIntArray::typeId());
 
   if (aDocRef->isInitialized() && // initialized immediately means already exist and will be loaded
       !Model_Application::getApplication()->hasDocument(aDocRef->docId()))
index 60b9becfad0f08d09dc1acf4e2b56597a343095e..16cd5f97981514ce40dbfae7fe18e50d94c438be 100644 (file)
@@ -64,6 +64,9 @@ public:
   virtual void append(const std::string& theType, const std::string& theContextName,
                       const int theIndex) = 0;
 
+  /// Copy the selection list to the destination attribute
+  virtual void copyTo(std::shared_ptr<ModelAPI_AttributeSelectionList> theTarget) const = 0;
+
   /// Reset temporary stored values
   virtual void removeTemporaryValues() = 0;
 
index 4adeec43261d103ce4a0d486916ed2b1781f6145..25439241168ad6812b360049ead822246174d3cf 100644 (file)
@@ -50,6 +50,9 @@ public:
                     const ResultPtr& theResult,
                     const ModelAPI_FiltersArgs& theArgs) const = 0;
 
+  /// Returns True if the filter can be used several times within one filtering
+  virtual bool isMultiple() const { return false; }
+
   /// Returns XML string which represents GUI of the filter
   /// By default it returns nothing (no GUI)
   virtual std::string xmlRepresentation() const { return ""; }
index b4790994376d8aa1c6a996b47a237c5ed6889a8a..9c2064d45af282a99a65cdb06169a3d82d9bbb13 100644 (file)
@@ -33,7 +33,8 @@ class ModelAPI_FiltersFeature: public ModelAPI_Feature
 {
 public:
   /// Adds a filter to the feature. Also initializes arguments of this filter.
-  virtual void addFilter(const std::string theFilterID) = 0;
+  /// Returns the real identifier of the filter.
+  virtual std::string addFilter(const std::string theFilterID) = 0;
 
   /// Removes an existing filter from the feature.
   virtual void removeFilter(const std::string theFilterID) = 0;
index 18c96fbc91edff5665d7319f270921dd2fb66244..bc838a548f9618d85617b96670d09496261622be 100644 (file)
@@ -23,6 +23,7 @@
 #include <ModelAPI_Attribute.h>
 #include <ModelAPI_AttributeIntArray.h>
 #include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeBoolean.h>
 
 #include <Events_Loop.h>
 
@@ -37,6 +38,9 @@ void ModelAPI_Result::initAttributes()
   aData->addAttribute(COLOR_ID(), ModelAPI_AttributeIntArray::typeId())->setIsArgument(false);
   aData->addAttribute(DEFLECTION_ID(), ModelAPI_AttributeDouble::typeId())->setIsArgument(false);
   aData->addAttribute(TRANSPARENCY_ID(), ModelAPI_AttributeDouble::typeId())->setIsArgument(false);
+  aData->addAttribute(ISO_LINES_ID(), ModelAPI_AttributeIntArray::typeId())->setIsArgument(false);
+  aData->addAttribute(SHOW_ISO_LINES_ID(), ModelAPI_AttributeBoolean::typeId())->
+    setIsArgument(false);
 }
 
 bool ModelAPI_Result::setDisabled(std::shared_ptr<ModelAPI_Result> theThis, const bool theFlag)
index 81709e749e22f35a65e570547bae02b8aeb16a87..f242ce3d300a0acdd5fa6f358de29fd52b309a20 100644 (file)
@@ -63,6 +63,22 @@ class ModelAPI_Result : public ModelAPI_Object
     return MY_TRANSPARENCY_ID;
   }
 
+  /// Reference to the transparency of the result.
+  /// The double value is used. The value is in [0, 1] range
+  inline static const std::string& ISO_LINES_ID()
+  {
+    static const std::string MY_ISO_LINES_ID("Iso_lines");
+    return MY_ISO_LINES_ID;
+  }
+
+  /// Reference to the transparency of the result.
+  /// The double value is used. The value is in [0, 1] range
+  inline static const std::string& SHOW_ISO_LINES_ID()
+  {
+    static const std::string MY_SHOW_ISO_LINES_ID("Show_Iso_lines");
+    return MY_SHOW_ISO_LINES_ID;
+  }
+
   /// Returns true if the result is concealed from the data tree (referenced by other objects)
   MODELAPI_EXPORT virtual bool isConcealed();
 
index f77e99951ae430e70d004b73e5b4a641d5ce5ddb..b2a7e0f39ddf3693f2e9e3d726028cf77e24b018 100644 (file)
@@ -30,6 +30,8 @@
 #include <ModelAPI_AttributeDocRef.h>
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_AttributeIntArray.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_AttributeBoolean.h>
 #include <list>
 #include <map>
 #include <iostream>
@@ -647,6 +649,7 @@ std::pair<std::string, bool> getDefaultName(const std::shared_ptr<ModelAPI_Resul
         // check the referred object is a Body
         // (for example, ExtrusionCut has a sketch as a first attribute which is concealing)
         bool isBody = aRefIt->second.size() > 1 || (aRefIt->second.size() == 1 &&
+                      aRefIt->second.front().get() &&
                       aRefIt->second.front()->groupName() == ModelAPI_ResultBody::group());
         if (isBody && (isMainArg || aFoundRef == aReferences.end() ||
             aData->isPrecedingAttribute(aRefIt->first, aFoundRef->first)))
@@ -802,6 +805,19 @@ void removeResults(const std::list<ResultPtr>& theResults)
   }
 }
 
+
+//**************************************************************
+void setDeflection(ResultPtr theResult, const double theDeflection)
+{
+  if (!theResult.get())
+    return;
+
+  AttributeDoublePtr aDeflectionAttr = theResult->data()->real(ModelAPI_Result::DEFLECTION_ID());
+  if (aDeflectionAttr.get() != NULL) {
+    aDeflectionAttr->setValue(theDeflection);
+  }
+}
+
 // used by GUI only
 // LCOV_EXCL_START
 double getDeflection(const std::shared_ptr<ModelAPI_Result>& theResult)
@@ -820,6 +836,22 @@ double getDeflection(const std::shared_ptr<ModelAPI_Result>& theResult)
   return aDeflection;
 }
 
+//******************************************************
+void setColor(ResultPtr theResult, const std::vector<int>& theColor)
+{
+  if (!theResult.get())
+    return;
+
+  AttributeIntArrayPtr aColorAttr = theResult->data()->intArray(ModelAPI_Result::COLOR_ID());
+  if (aColorAttr.get() != NULL) {
+    if (!aColorAttr->size()) {
+      aColorAttr->setSize(3);
+    }
+    aColorAttr->setValue(0, theColor[0]);
+    aColorAttr->setValue(1, theColor[1]);
+    aColorAttr->setValue(2, theColor[2]);
+  }
+}
 
 void getColor(const std::shared_ptr<ModelAPI_Result>& theResult, std::vector<int>& theColor)
 {
@@ -836,6 +868,88 @@ void getColor(const std::shared_ptr<ModelAPI_Result>& theResult, std::vector<int
   }
 }
 
+//******************************************************
+void getIsoLines(const std::shared_ptr<ModelAPI_Result>& theResult,
+  bool& isVisible, std::vector<int>& theNbLines)
+{
+  theNbLines.clear();
+  isVisible = false;
+  if (!theResult.get())
+    return;
+  if (theResult->groupName() == ModelAPI_ResultConstruction::group()) {
+    theNbLines.push_back(0);
+    theNbLines.push_back(0);
+  }
+  else {
+    // get color from the attribute of the result
+    AttributeIntArrayPtr aAttr = theResult->data()->intArray(ModelAPI_Result::ISO_LINES_ID());
+    if (aAttr.get()) {
+      if (aAttr->size()) {
+        theNbLines.push_back(aAttr->value(0));
+        theNbLines.push_back(aAttr->value(1));
+      }
+    }
+    AttributeBooleanPtr aBoolAttr =
+      theResult->data()->boolean(ModelAPI_Result::SHOW_ISO_LINES_ID());
+    if (aBoolAttr.get()) {
+      isVisible = aBoolAttr->value();
+    }
+  }
+}
+
+//******************************************************
+void setIsoLines(ResultPtr theResult, const std::vector<int>& theIso)
+{
+  if (!theResult.get())
+    return;
+
+  AttributeIntArrayPtr aAttr = theResult->data()->intArray(ModelAPI_Result::ISO_LINES_ID());
+  if (aAttr.get() != NULL) {
+    if (!aAttr->size()) {
+      aAttr->setSize(2);
+    }
+    aAttr->setValue(0, theIso[0]);
+    aAttr->setValue(1, theIso[1]);
+  }
+}
+
+//******************************************************
+void showIsoLines(std::shared_ptr<ModelAPI_Result> theResult, bool theShow)
+{
+  if (!theResult.get())
+    return;
+
+  AttributeBooleanPtr aAttr = theResult->data()->boolean(ModelAPI_Result::SHOW_ISO_LINES_ID());
+  if (aAttr.get() != NULL) {
+    aAttr->setValue(theShow);
+  }
+}
+
+//******************************************************
+bool isShownIsoLines(std::shared_ptr<ModelAPI_Result> theResult)
+{
+  if (!theResult.get())
+    return false;
+
+  AttributeBooleanPtr aAttr = theResult->data()->boolean(ModelAPI_Result::SHOW_ISO_LINES_ID());
+  if (aAttr.get() != NULL) {
+    return aAttr->value();
+  }
+  return false;
+}
+
+//**************************************************************
+void setTransparency(ResultPtr theResult, double theTransparency)
+{
+  if (!theResult.get())
+    return;
+
+  AttributeDoublePtr anAttribute = theResult->data()->real(ModelAPI_Result::TRANSPARENCY_ID());
+  if (anAttribute.get() != NULL) {
+    anAttribute->setValue(theTransparency);
+  }
+}
+
 double getTransparency(const std::shared_ptr<ModelAPI_Result>& theResult)
 {
   double aTransparency = -1;
@@ -864,6 +978,16 @@ void copyVisualizationAttrs(
         aDestColor->setValue(a, aSourceColor->value(a));
     }
   }
+  // Iso-lines
+  AttributeIntArrayPtr aSource = theSource->data()->intArray(ModelAPI_Result::ISO_LINES_ID());
+  if (aSource.get() && aSource->isInitialized() && aSource->size()) {
+    AttributeIntArrayPtr aDest = theDest->data()->intArray(ModelAPI_Result::ISO_LINES_ID());
+    if (aDest.get()) {
+      aDest->setSize(aSource->size());
+      for(int a = 0; a < aSource->size(); a++)
+        aDest->setValue(a, aSource->value(a));
+    }
+  }
   // deflection
   AttributeDoublePtr aSourceDefl = theSource->data()->real(ModelAPI_Result::DEFLECTION_ID());
   if (aSourceDefl.get() && aSourceDefl->isInitialized()) {
@@ -882,4 +1006,53 @@ void copyVisualizationAttrs(
   }
 }
 
+std::list<FeaturePtr> referencedFeatures(
+  std::shared_ptr<ModelAPI_Result> theTarget, const std::string& theFeatureKind,
+  const bool theSortResults)
+{
+  std::set<FeaturePtr> aResSet; // collect in the set initially to avoid duplicates
+  std::list<ResultPtr> allSubRes;
+  allSubRes.push_back(theTarget);
+  ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theTarget);
+  if (aBody.get())
+    allSubs(aBody, allSubRes);
+  std::list<ResultPtr>::iterator aSub = allSubRes.begin();
+  for(; aSub != allSubRes.end(); aSub++) {
+    const std::set<AttributePtr>& aRefs = (*aSub)->data()->refsToMe();
+    std::set<AttributePtr>::const_iterator aRef = aRefs.cbegin();
+    for(; aRef != aRefs.cend(); aRef++) {
+      FeaturePtr aFeat = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRef)->owner());
+      if (aFeat.get() && (theFeatureKind.empty() || aFeat->getKind() == theFeatureKind))
+        aResSet.insert(aFeat);
+    }
+  }
+  // add also feature of the target that may be referenced as a whole
+  FeaturePtr aTargetFeature = theTarget->document()->feature(theTarget);
+  const std::set<AttributePtr>& aRefs = aTargetFeature->data()->refsToMe();
+  std::set<AttributePtr>::const_iterator aRef = aRefs.cbegin();
+  for(; aRef != aRefs.cend(); aRef++) {
+    FeaturePtr aFeat = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRef)->owner());
+    if (aFeat.get() && (theFeatureKind.empty() || aFeat->getKind() == theFeatureKind))
+      aResSet.insert(aFeat);
+  }
+
+  std::list<FeaturePtr> aResList;
+  std::set<FeaturePtr>::iterator aResIter = aResSet.begin();
+  for(; aResIter != aResSet.end(); aResIter++) {
+    if (theSortResults) { // sort results by creation-order
+      std::list<FeaturePtr>::iterator aListIter = aResList.begin();
+      for(; aListIter != aResList.end(); aListIter++) {
+        if ((*aResIter)->document()->isLater(*aListIter, *aResIter))
+          break;
+      }
+      if (aListIter == aResList.end()) // goes to the end
+        aResList.push_back(*aResIter);
+      else
+        aResList.insert(aListIter, *aResIter);
+    } else //just push to the end unsorted
+      aResList.push_back(*aResIter);
+  }
+  return aResList;
+}
+
 } // namespace ModelAPI_Tools
index 57cdea0c9aff9d25b5a4ae30b4de086bbe034abb..a90cd60fa461c124dad9516f301a20cc3ec71156 100644 (file)
@@ -227,6 +227,13 @@ MODELAPI_EXPORT void removeResults(const std::list<std::shared_ptr<ModelAPI_Resu
 */
 MODELAPI_EXPORT double getDeflection(const std::shared_ptr<ModelAPI_Result>& theResult);
 
+/*! Sets the deflection value
+* \param theResult a result object
+* \param a deflection value
+*/
+MODELAPI_EXPORT void setDeflection(std::shared_ptr<ModelAPI_Result> theResult,
+  const double theDeflection);
+
 /*! Returns current color of the current result
 * \param[in] theResult a result object
 * \param[out] theColor a color values if it is defined
@@ -234,12 +241,49 @@ MODELAPI_EXPORT double getDeflection(const std::shared_ptr<ModelAPI_Result>& the
 MODELAPI_EXPORT void getColor(const std::shared_ptr<ModelAPI_Result>& theResult,
   std::vector<int>& theColor);
 
+/*! Set color of the result
+* \param[in] theResult a result object
+* \param[in] theColor a color values
+*/
+MODELAPI_EXPORT void setColor(std::shared_ptr<ModelAPI_Result> theResult,
+  const std::vector<int>& theColor);
+
+/*! Returns number of iso-lines of the current result
+* \param[in] theResult a result object
+* \param[out] theNbLines values of iso-lines
+*/
+MODELAPI_EXPORT void getIsoLines(const std::shared_ptr<ModelAPI_Result>& theResult,
+  bool& isVisible, std::vector<int>& theNbLines);
+
+/*! Set number of iso-lines of the result
+* \param[in] theResult a result object
+* \param[in] theIso nb iso-lines
+*/
+MODELAPI_EXPORT void setIsoLines(std::shared_ptr<ModelAPI_Result> theResult,
+  const std::vector<int>& theIso);
+
+/*! Set visibility of Iso lines
+* \param[in] theResult a result object
+* \param[in] theShow is a visibility flag
+*/
+MODELAPI_EXPORT void showIsoLines(std::shared_ptr<ModelAPI_Result> theResult, bool theShow);
+
+MODELAPI_EXPORT bool isShownIsoLines(std::shared_ptr<ModelAPI_Result> theResult);
+
 /*! Returns current transparency in the given result
 * \param theResult a result object
 * \return a transparency value or -1 if it was not defined
 */
 MODELAPI_EXPORT double getTransparency(const std::shared_ptr<ModelAPI_Result>& theResult);
 
+/*! Set transparency for the given result
+* \param theResult a result object
+* \param a transparency value
+*/
+MODELAPI_EXPORT void setTransparency(std::shared_ptr<ModelAPI_Result> theResult,
+  double theTransparency);
+
+
 /*! Copies all visualization attributes from one result to another.
 * \param theSource a result that contains the copied attributes
 * \param theDest a destination result that takes the visualization attributes
@@ -247,6 +291,15 @@ MODELAPI_EXPORT double getTransparency(const std::shared_ptr<ModelAPI_Result>& t
 MODELAPI_EXPORT void copyVisualizationAttrs(std::shared_ptr<ModelAPI_Result> theSource,
                                             std::shared_ptr<ModelAPI_Result> theDest);
 
+/*! Produces list of features that reference to the given target (directly or through sub-results)
+* \param theTarget the referenced result
+* \param theFeatureKind the resulting features filter: the feature kind or all for the empty string
+* \param theSortResults to sort the resulting list of features by the features creation order
+*/
+MODELAPI_EXPORT std::list<std::shared_ptr<ModelAPI_Feature> > referencedFeatures(
+  std::shared_ptr<ModelAPI_Result> theTarget, const std::string& theFeatureKind,
+  const bool theSortResults);
+
 }
 
 #endif
index 3cb222a88f848b92295a9bdf10f854c74c6c34d3..7956062dde22d6a48501f3f005e8fc43cb29412e 100644 (file)
@@ -687,7 +687,6 @@ bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_Document>& theD
 
   // dump subfeatures and store result to file
   bool isOk = process(theDoc) && myDumpStorage->exportTo(theFileName, myModules);
-  clearCustomStorage();
   return isOk;
 }
 
@@ -1590,3 +1589,24 @@ ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper,
 
   return theDumper;
 }
+
+
+void ModelHighAPI_Dumper::exportVariables() const
+{
+  DocumentPtr aRoot = ModelAPI_Session::get()->moduleDocument();
+  EntityNameMap::const_iterator aNameIter = myNames.cbegin();
+  for(; aNameIter != myNames.end(); aNameIter++) {
+    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aNameIter->first);
+    if (aFeature.get() && aFeature->document() != aRoot) {
+      FeaturePtr aPartFeat = ModelAPI_Tools::findPartFeature(aRoot, aFeature->document());
+      if (aPartFeat.get()) {
+        int aFeatureId = aFeature->data()->featureId();
+        int aPartId = aPartFeat->data()->featureId();
+        std::ostringstream anEntryStr;
+        anEntryStr<<aPartId<<":"<<aFeatureId;
+        std::string anEntry = anEntryStr.str();
+        exportVariable(anEntry, aNameIter->second.myCurrentName);
+      }
+    }
+  }
+}
index 90242c3aac90f0a2fd0a2f86b9ff6a1d05d13af5..ef81ae2128e2466bce9df2205cb8b6f1fa408930 100644 (file)
@@ -162,7 +162,6 @@ public:
   /// Clear custom storages list
   MODELHIGHAPI_EXPORT
   void clearCustomStorage();
-
   /// Dump given document into the file
   /// \return \c true, if succeed
   MODELHIGHAPI_EXPORT
@@ -347,6 +346,13 @@ public:
   MODELHIGHAPI_EXPORT
   bool isDumped(const std::shared_ptr<ModelAPI_AttributeRefList>& theRefList) const;
 
+  /// Export variables names to another module (calls exportVariable implemented in python)
+  MODELHIGHAPI_EXPORT virtual void exportVariables() const;
+
+  /// Export one variable name to another module (implemented in python)
+  MODELHIGHAPI_EXPORT virtual void exportVariable(
+    const std::string& theEntry, const std::string& theVarName) const {}
+
 protected:
   /// Dump "setName" command if last entity had user-defined name
   MODELHIGHAPI_EXPORT void dumpEntitySetName();
index 405dfb85a29df16395612eabc5589b1ceb23cca7..f94b65780416ef08c19eb73621c68de7733dc6b5 100644 (file)
@@ -45,6 +45,7 @@
 #include <Prs3d_PointAspect.hxx>
 #include <Prs3d_IsoAspect.hxx>
 #include <Prs3d_ShadingAspect.hxx>
+#include <Prs3d_PlaneAspect.hxx>
 #include <SelectMgr_SequenceOfOwner.hxx>
 #include <SelectMgr_EntityOwner.hxx>
 #include <SelectMgr_SelectionManager.hxx>
@@ -83,8 +84,26 @@ ModuleBase_ResultPrs::ModuleBase_ResultPrs(ResultPtr theResult)
   aDrawer->SetFreeBoundaryAspect(new Prs3d_LineAspect(Quantity_NOC_GREEN, Aspect_TOL_SOLID, 1));
   aDrawer->SetFaceBoundaryAspect(new Prs3d_LineAspect(Quantity_NOC_BLACK, Aspect_TOL_SOLID, 1));
 
-  aDrawer->VIsoAspect()->SetNumber(0);
-  aDrawer->UIsoAspect()->SetNumber(0);
+  Quantity_Color aColor;
+  Color(aColor);
+
+  std::vector<int> aIsoValues;
+  bool isIsoVisible;
+  ModelAPI_Tools::getIsoLines(myResult, isIsoVisible, aIsoValues);
+  if (isIsoVisible) {
+    if (aIsoValues.size() == 0) {
+      aIsoValues.push_back(1);
+      aIsoValues.push_back(1);
+    }
+  }
+  else {
+    aIsoValues.push_back(0);
+    aIsoValues.push_back(0);
+  }
+  myUIsoAspect = new Prs3d_IsoAspect(aColor, Aspect_TOL_SOLID, 1, aIsoValues[0]);
+  myVIsoAspect = new Prs3d_IsoAspect(aColor, Aspect_TOL_SOLID, 1, aIsoValues[1]);
+  aDrawer->SetUIsoAspect(myUIsoAspect);
+  aDrawer->SetVIsoAspect(myVIsoAspect);
 
   if (aDrawer->HasOwnPointAspect())
     aDrawer->PointAspect()->SetTypeOfMarker(Aspect_TOM_PLUS);
@@ -95,14 +114,12 @@ ModuleBase_ResultPrs::ModuleBase_ResultPrs(ResultPtr theResult)
   if (aDrawer.IsNull()) {
     if (!ModuleBase_IViewer::DefaultHighlightDrawer.IsNull()) {
       aDrawer = new Prs3d_Drawer(*ModuleBase_IViewer::DefaultHighlightDrawer);
-      aDrawer->VIsoAspect()->SetNumber(0);
-      aDrawer->UIsoAspect()->SetNumber(0);
+      aDrawer->SetUIsoAspect(myUIsoAspect);
+      aDrawer->SetVIsoAspect(myVIsoAspect);
       SetDynamicHilightAttributes(aDrawer);
     }
-  } else {
-    aDrawer->VIsoAspect()->SetNumber(0);
-    aDrawer->UIsoAspect()->SetNumber(0);
   }
+
   myHiddenSubShapesDrawer = new AIS_ColoredDrawer(myDrawer);
   Handle(Prs3d_ShadingAspect) aShadingAspect = new Prs3d_ShadingAspect();
   aShadingAspect->SetMaterial(Graphic3d_NOM_BRASS); //default value of context material
@@ -127,6 +144,8 @@ void ModuleBase_ResultPrs::SetColor (const Quantity_Color& theColor)
   ViewerData_AISShape::SetColor(theColor);
   myHiddenSubShapesDrawer->ShadingAspect()->SetColor (theColor, myCurrentFacingModel);
   setEdgesDefaultColor();
+  myUIsoAspect->SetColor(theColor);
+  myVIsoAspect->SetColor(theColor);
 }
 
 void ModuleBase_ResultPrs::setEdgesDefaultColor()
@@ -457,3 +476,30 @@ void ModuleBase_ResultPrs::HilightOwnerWithColor(const Handle(PrsMgr_Presentatio
       thePM->AddToImmediateList(aHilightPrs);
   }
 }
+
+
+//********************************************************************
+void ModuleBase_ResultPrs::updateIsoLines()
+{
+  std::vector<int> aIsoValues;
+  bool isIsoVisible;
+  ModelAPI_Tools::getIsoLines(myResult, isIsoVisible, aIsoValues);
+  if (isIsoVisible) {
+    if (aIsoValues.size() == 0) {
+      aIsoValues.push_back(1);
+      aIsoValues.push_back(1);
+    }
+  }
+  else {
+    if (aIsoValues.size() == 0) {
+      aIsoValues.push_back(0);
+      aIsoValues.push_back(0);
+    }
+    else {
+      aIsoValues[0] = 0;
+      aIsoValues[1] = 0;
+    }
+  }
+  myUIsoAspect->SetNumber(aIsoValues[0]);
+  myVIsoAspect->SetNumber(aIsoValues[1]);
+}
index 84500eba65dfff600d2f6cbad61b76defbefa624..a1f40f9fedd134a65a3c322734281f9d96ca3714 100644 (file)
@@ -30,6 +30,7 @@
 #include <ViewerData_AISShape.hxx>
 #include <Standard_DefineHandle.hxx>
 #include <TopoDS_Compound.hxx>
+#include <Prs3d_IsoAspect.hxx>
 
 #include <QMap>
 
@@ -112,10 +113,13 @@ public:
   /// \return false if parameter is out of [0, 1]
   Standard_EXPORT bool setHiddenSubShapeTransparency(double theTransparency);
 
+  /// Returns the original shape of the presentation
   Standard_EXPORT TopoDS_Shape originalShape() const { return myOriginalShape; }
 
+  /// Returns True if the original shape is substituted by a corresponded shell
   Standard_EXPORT bool isSubstituted() const { return myIsSubstituted; }
 
+  Standard_EXPORT void updateIsoLines();
 
   DEFINE_STANDARD_RTTIEXT(ModuleBase_ResultPrs, ViewerData_AISShape)
 
@@ -171,6 +175,9 @@ private:
   /// selection priority that will be added to the standard
   /// selection priority of the selection entity
   int myAdditionalSelectionPriority;
+
+  Handle(Prs3d_IsoAspect) myUIsoAspect;
+  Handle(Prs3d_IsoAspect) myVIsoAspect;
 };
 
 
index ab7b17e103e4882e54c016ac02de634f101e2834..269d445b52e2927af8a7bb9e14e0eecfa1526dcd 100644 (file)
 #include <climits>
 
 ModuleBase_WidgetFactory::ModuleBase_WidgetFactory(const std::string& theXmlRepresentation,
-                                                   ModuleBase_IWorkshop* theWorkshop)
+                                                   ModuleBase_IWorkshop* theWorkshop,
+                                                   const std::string theAttributePrefix)
     : myWorkshop(theWorkshop)
 {
-  myWidgetApi = new Config_WidgetAPI(theXmlRepresentation);
+  myWidgetApi = new Config_WidgetAPI(theXmlRepresentation, theAttributePrefix);
 }
 
 ModuleBase_WidgetFactory::~ModuleBase_WidgetFactory()
index 90ea7428b54936be913a9ce98774de8ac8479f14..49fc9a05370b3ce00e71db73ef4bad4006012e54 100644 (file)
@@ -43,8 +43,10 @@ class MODULEBASE_EXPORT ModuleBase_WidgetFactory
    /// Constructor
    /// \param theXmlRepresentation content of XML file
    /// \param theWorkshop reference to workshop instance
-  ModuleBase_WidgetFactory(const std::string& theXmlRepresentation,
-                           ModuleBase_IWorkshop* theWorkshop);
+   /// \param theAttributePrefix prefix that must be added to the attribute name
+   ModuleBase_WidgetFactory(const std::string& theXmlRepresentation,
+                           ModuleBase_IWorkshop* theWorkshop,
+                           const std::string theAttributePrefix = "");
   virtual ~ModuleBase_WidgetFactory();
 
   /// Creates content widget for property panel
index 500bd5b68ff21f3737233b55515e9469d0c6038f..6e916b7ab2c6e870247999018c26a08739a9e6d7 100644 (file)
@@ -143,12 +143,17 @@ ModuleBase_FilterItem::ModuleBase_FilterItem(
   : QWidget(theParent->filtersWidget()), myFilterID(theFilter),
     mySelection(std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(theParent->feature()))
 {
-  std::string aXmlString =
-      ModelAPI_Session::get()->filters()->filter(theFilter)->xmlRepresentation();
+  FilterPtr aFilter = ModelAPI_Session::get()->filters()->filter(theFilter);
+  std::string aXmlString = aFilter->xmlRepresentation();
   if (aXmlString.length() == 0)
     addItemRow(this);
   else {
-    ModuleBase_WidgetFactory aFactory(aXmlString, theParent->workshop());
+    std::string anAttrPrefix; // this must be added to the attributes names for multiple filters
+    std::string aFilterKind = ModelAPI_Session::get()->filters()->id(aFilter);
+    if (theFilter != aFilterKind) {
+      anAttrPrefix = theFilter.substr(0, theFilter.size() - aFilterKind.size());
+    }
+    ModuleBase_WidgetFactory aFactory(aXmlString, theParent->workshop(), anAttrPrefix);
     Config_ValidatorReader aValidatorReader(aXmlString, true);
     aValidatorReader.setFeatureId(mySelection->getKind());
     aValidatorReader.readAll();
@@ -263,7 +268,6 @@ ModuleBase_WidgetSelectionFilter::ModuleBase_WidgetSelectionFilter(QWidget* theP
   std::list<FilterPtr>::const_iterator aIt;
   for (aIt = allFilters.cbegin(); aIt != allFilters.cend(); aIt++) {
     aItems.push_back((*aIt)->name().c_str());
-    myFilters.push_back(aSession->filters()->id(*aIt));
   }
   myFiltersCombo->addItems(aItems);
   connect(myFiltersCombo, SIGNAL(currentIndexChanged(int)), SLOT(onAddFilter(int)));
@@ -346,26 +350,28 @@ void ModuleBase_WidgetSelectionFilter::onAddFilter(int theIndex)
   if (theIndex == 0)
     return;
 
-  std::list<std::string>::iterator aIt;
+  ModelAPI_FiltersFactory* aFactory = ModelAPI_Session::get()->filters();
+  std::list<FilterPtr> aFilters = aFactory->filters((GeomAPI_Shape::ShapeType) mySelectionType);
+  FiltersFeaturePtr aFiltersFeature =
+    std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(myFeature);
+
+  std::string aText = myFiltersCombo->itemText(theIndex).toStdString();
+
+  std::list<FilterPtr>::iterator aIt;
   int i;
   std::string aFilter;
-  for (aIt = myFilters.begin(), i = 0; aIt != myFilters.cend(); i++, aIt++) {
-    if (i == (theIndex - 1)) {
-      aFilter = (*aIt);
+  for (aIt = aFilters.begin(), i = 0; aIt != aFilters.cend(); i++, aIt++) {
+    if (aText == (*aIt)->name()) {
+      aFilter = aFactory->id(*aIt);
       break;
     }
   }
-  ModuleBase_FilterItem* aItem = onAddFilter(aFilter);
-  FiltersFeaturePtr aFiltersFeature =
-    std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(myFeature);
   aFiltersFeature->addFilter(aFilter);
-
-  myFiltersCombo->setCurrentIndex(0);
-  myFiltersCombo->removeItem(theIndex);
   updateObject(myFeature);
 
-  if (aItem && (aItem->widgets().size() > 0))
-    aItem->widgets().first()->emitFocusInWidget();
+  QList<ModuleBase_FilterItem*> aList = itemsList();
+  if (!aList.isEmpty() && (aList.last()->widgets().size() > 0))
+    aList.last()->widgets().first()->emitFocusInWidget();
   else
     emitFocusInWidget();
 }
@@ -374,13 +380,6 @@ ModuleBase_FilterItem* ModuleBase_WidgetSelectionFilter::onAddFilter(const std::
 {
   if (theFilter.length() == 0)
     return 0;
-  std::list<std::string>::const_iterator aIt;
-  for (aIt = myUseFilters.cbegin(); aIt != myUseFilters.cend(); aIt++) {
-    if (theFilter == (*aIt))
-      return 0;
-  }
-  myFilters.remove(theFilter);
-  myUseFilters.push_back(theFilter);
   ModuleBase_FilterItem* aItem = new ModuleBase_FilterItem(theFilter, this);
   connect(aItem, SIGNAL(deleteItem(ModuleBase_FilterItem*)),
     SLOT(onDeleteItem(ModuleBase_FilterItem*)));
@@ -404,10 +403,11 @@ void ModuleBase_WidgetSelectionFilter::onDeleteItem(ModuleBase_FilterItem* theIt
   myFiltersLayout->removeWidget(theItem);
   theItem->deleteLater();
 
-  myUseFilters.remove(aFilter);
-  myFilters.push_back(aFilter);
-  myFiltersCombo->addItem(ModelAPI_Session::get()->filters()->filter(aFilter)->name().c_str());
-
+  ModelAPI_FiltersFactory* aFactory = ModelAPI_Session::get()->filters();
+  if (!aFactory->filter(aFilter)->isMultiple()) {
+    //myFilters.push_back(aFilter);
+    myFiltersCombo->addItem(ModelAPI_Session::get()->filters()->filter(aFilter)->name().c_str());
+  }
   FiltersFeaturePtr aFiltersFeature =
     std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(myFeature);
   aFiltersFeature->removeFilter(aFilter);
@@ -441,8 +441,6 @@ void ModuleBase_WidgetSelectionFilter::onReverseItem(ModuleBase_FilterItem* theI
 
 void ModuleBase_WidgetSelectionFilter::onSelect()
 {
-  if (myUseFilters.size() == 0)
-    return;
   Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
   if (aCtx.IsNull())
     return;
@@ -550,7 +548,8 @@ void ModuleBase_WidgetSelectionFilter::onShowOnly(bool theShow)
 
 void ModuleBase_WidgetSelectionFilter::updateSelectBtn()
 {
-  mySelectBtn->setEnabled(myUseFilters.size() > 0);
+  FiltersFeaturePtr aFiltersFeature = std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(myFeature);
+  mySelectBtn->setEnabled(aFiltersFeature.get() && (aFiltersFeature->filters().size() > 0));
 }
 
 void ModuleBase_WidgetSelectionFilter::updateNumberSelected()
@@ -651,6 +650,12 @@ bool ModuleBase_WidgetSelectionFilter::storeValueCustom()
   return true;
 }
 
+QList<ModuleBase_FilterItem*> ModuleBase_WidgetSelectionFilter::itemsList() const
+{
+  return  myFiltersWgt->findChildren<ModuleBase_FilterItem*>();
+}
+
+
 bool ModuleBase_WidgetSelectionFilter::restoreValueCustom()
 {
   ModelAPI_FiltersFactory* aFactory = ModelAPI_Session::get()->filters();
@@ -662,23 +667,33 @@ bool ModuleBase_WidgetSelectionFilter::restoreValueCustom()
     aAttrList->setFilters(aFiltersFeature);
   }
 
+  QList<ModuleBase_FilterItem*> aItemsList = itemsList();
   std::list<std::string> aFilters = aFiltersFeature->filters();
+
   std::list<std::string>::const_iterator aIt;
-  for (aIt = aFilters.cbegin(); aIt != aFilters.cend(); aIt++) {
+  int i = 0;
+  int aNbItems = aItemsList.size();
+  ModuleBase_FilterItem* aItem = 0;
+  bool isBlocked = myFiltersCombo->blockSignals(true);
+  for (aIt = aFilters.cbegin(); aIt != aFilters.cend(); aIt++, i++) {
     std::string aStr = (*aIt);
-    ModuleBase_FilterItem* aItem = onAddFilter(aStr);
-    FilterPtr aFilterObj = aFactory->filter(aStr);
-    int aId = myFiltersCombo->findText(aFilterObj->name().c_str());
-    if (aId != -1)
-      myFiltersCombo->removeItem(aId);
-
-    if (aItem) {
-      QList<ModuleBase_ModelWidget*> aSubList = aItem->widgets();
-      foreach(ModuleBase_ModelWidget* aWgt, aSubList) {
-        aWgt->restoreValue();
+    aItem = 0;
+    if (i >= aNbItems) {
+      aItem = onAddFilter(aStr);
+      FilterPtr aFilterObj = aFactory->filter(aStr);
+      int aId = myFiltersCombo->findText(aFilterObj->name().c_str());
+      if ((aId != -1) && !aFilterObj->isMultiple())
+        myFiltersCombo->removeItem(aId);
+      if (aItem) {
+        QList<ModuleBase_ModelWidget*> aSubList = aItem->widgets();
+        foreach(ModuleBase_ModelWidget* aWgt, aSubList) {
+          aWgt->restoreValue();
+        }
       }
     }
   }
+  myFiltersCombo->setCurrentIndex(0);
+  myFiltersCombo->blockSignals(isBlocked);
   return true;
 }
 
@@ -698,7 +713,7 @@ void ModuleBase_WidgetSelectionFilter::onObjectUpdated()
   clearCurrentSelection(true);
   updateNumberSelected();
 
-  QList<ModuleBase_FilterItem*> aItemsList = myFiltersWgt->findChildren<ModuleBase_FilterItem*>();
+  QList<ModuleBase_FilterItem*> aItemsList = itemsList();
   foreach(ModuleBase_FilterItem* aItem, aItemsList) {
     QList<ModuleBase_ModelWidget*> aWidgetsList = aItem->widgets();
     foreach(ModuleBase_ModelWidget* aWidget, aWidgetsList) {
index 4862581b89559f93174489232afa4137d16117e0..011cbaaa10f8c3bdd0814cfba5d9e8fb9fa0cb5c 100644 (file)
@@ -217,6 +217,9 @@ private:
   /// Add a filter by name
   ModuleBase_FilterItem* onAddFilter(const std::string& theFilter);
 
+  /// Return currently created filter items
+  QList<ModuleBase_FilterItem*> itemsList() const;
+
 private:
   ModuleBase_IWorkshop* myWorkshop;
 
@@ -231,12 +234,6 @@ private:
   /// Type of selection mode
   int mySelectionType;
 
-  /// List of non-used filters
-  std::list<std::string> myFilters;
-
-  /// List of used filters
-  std::list<std::string> myUseFilters;
-
   /// Result of filtering
   QList<ModuleBase_ViewerPrsPtr> myValues;
 
index f27f35f1910f58dcb960a425dba5781c233621f7..5c2d2ae1135a92aa30c527495910ad23f6c88fa0 100644 (file)
@@ -58,6 +58,7 @@
 #include <BRepBuilderAPI_MakeVertex.hxx>
 #include <BRep_Builder.hxx>
 #include <TopoDS_Compound.hxx>
+#include <Prs3d_IsoAspect.hxx>
 
 //#define DEBUG_EMPTY_SHAPE
 //#define DEBUG_OPERATION_PRS
@@ -84,6 +85,13 @@ PartSet_OperationPrs::PartSet_OperationPrs(ModuleBase_IWorkshop* theWorkshop)
   BRepBuilderAPI_MakeVertex aMaker(aPnt);
   TopoDS_Vertex aVertex = aMaker.Vertex();
   myShapeToPrsMap.Bind(aVertex, NULL);
+
+  Handle(Prs3d_Drawer) aDrawer = Attributes();
+  Handle(Prs3d_IsoAspect) aUIsoAspect = new Prs3d_IsoAspect(myShapeColor, Aspect_TOL_SOLID, 1, 0);
+  Handle(Prs3d_IsoAspect) aVIsoAspect = new Prs3d_IsoAspect(myShapeColor, Aspect_TOL_SOLID, 1, 0);
+  aDrawer->SetUIsoAspect(aUIsoAspect);
+  aDrawer->SetVIsoAspect(aVIsoAspect);
+  aDrawer->SetIsoOnPlane(false);
 }
 
 bool PartSet_OperationPrs::hasShapes()
index bcf6db4be9bedf1554dc90a14d4d49f0b548d4ee..8d57a5a3cc5a7b6d58c9a428aa890a953045d7a7 100644 (file)
@@ -592,6 +592,7 @@ void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouse
       aProcessor->mouseReleased(theWnd, theEvent);
   }
   if (MyModeByDrag && aOp) {
+    aViewer->enableMultiselection(true);
     QString aOpId = aOp->id();
     if (aOpId == "Sketch")
       return;
index 0b3eeb16745ef1f9f940a79467f389833bae1ce7..3170cc8570794ee6d7be7beeb43b2d38fb071a4e 100644 (file)
@@ -44,6 +44,7 @@ class DumpAssistant(ModelHighAPI.ModelHighAPI_Dumper):
         ModelHighAPI.ModelHighAPI_Dumper.__init__(self)
         ModelHighAPI.ModelHighAPI_Dumper.setInstance(self)
         self.collectFeatures()
+        self.myEngine = None
 
     ## Collect feature wrappers, which allow dumping (have method dump)
     def collectFeatures(self):
@@ -97,5 +98,18 @@ class DumpAssistant(ModelHighAPI.ModelHighAPI_Dumper):
             return self.myWrapperNames[aFeatureKind]
         return std_string()
 
+    ## Exports the dumped variables names to the SHAPERSTUDY
+    def exportVariable(self, theEntry, theVarName):
+        try:
+          if self.myEngine == None:
+            import SHAPERSTUDY_utils
+            aComponent = SHAPERSTUDY_utils.findOrCreateComponent()
+            self.myEngine = SHAPERSTUDY_utils.getEngine()
+          if self.myEngine != 1:
+            self.myEngine.StoreVariableName(theEntry, theVarName)
+        except:
+          self.myEngine = 1 # invalid access
+        pass
+
 # Instance of dumper
 dumper = DumpAssistant
index d585c1891f9f763f7c72b283abf3af3268d7c1f0..a8bd057618b390629cf6d69983c5173f11af4493 100644 (file)
@@ -29,3 +29,18 @@ from ModelHighAPI import reset
 from ModelHighAPI import addFolder, removeFolder
 from ModelHighAPI import ModelHighAPI_Selection as selection
 from ModelHighAPI import checkPythonDump as checkPythonDump
+from ModelAPI import findPartFeature
+
+# a method used for the python dump of the SHAPER STUDY
+def publishToShaperStudy():
+  begin()
+  activeDocument().addFeature("PublishToStudy")
+  end()
+
+# returns unique identifier of the feature : id of part it belongs to + ":" + id of feature
+def featureStringId(theFeature):
+  aRoot = moduleDocument()
+  aCurrent = theFeature.feature().document()
+  if aRoot and aCurrent:
+    return str(findPartFeature(aRoot, aCurrent).data().featureId()) + ":" + str(theFeature.feature().data().featureId())
+  return ""
index e9e7c0c0fddcea68b262c31c391c3977330e9f70..ee1b07deb8dc4c0a85776e4fee636af4262c62f7 100644 (file)
@@ -452,6 +452,8 @@ bool SHAPERGUI::deactivateModule(SUIT_Study* theStudy)
   connect(getApp()->action(LightApp_Application::FileSaveAsId), SIGNAL(triggered(bool)),
           getApp(), SLOT(onSaveAsDoc()));
 
+  publishToStudy();
+
   return LightApp_Module::deactivateModule(theStudy);
 }
 
@@ -699,9 +701,14 @@ QAction* SHAPERGUI::addFeatureOfNested(const QString& theWBName,
 QAction* SHAPERGUI::addDesktopCommand(const QString& theId, const QString& theTitle,
                                            const QString& theTip, const QIcon& theIcon,
                                            const QKeySequence& theKeys, bool isCheckable,
-                                           const char* theMenuSourceText, const int theMenuPosition)
+                                           const char* theMenuSourceText,
+                                           const QString& theSubMenu,
+                                           const int theMenuPosition,
+                                           const int theSuibMenuPosition)
 {
   int aMenu = createMenu(tr(theMenuSourceText), -1, -1);
+  if (!theSubMenu.isNull())
+    aMenu = createMenu(theSubMenu, aMenu, -1, theSuibMenuPosition);
 
   int aId = getNextCommandId();
   myActionsList.append(aId);
@@ -1186,3 +1193,9 @@ void SHAPERGUI::resetToolbars()
   SUIT_ResourceMgr* aResMgr = application()->resourceMgr();
   aResMgr->remove(ToolbarsSection);
 }
+
+void SHAPERGUI::publishToStudy()
+{
+  if (isActiveModule())
+    myWorkshop->module()->launchOperation("PublishToStudy", false);
+}
index 1c52678385d50ea1ab3a12f52032bbd8579d5f45..348923c1b521bd48036a59ddc1a0392397501c31 100644 (file)
@@ -91,10 +91,11 @@ Q_OBJECT
   virtual bool isFeatureOfNested(const QAction* theAction);
 
   virtual QAction* addDesktopCommand(const QString& theId, const QString& theTitle,
-                                     const QString& theTip, const QIcon& theIcon,
-                                     const QKeySequence& theKeys, bool isCheckable,
-                                     const char* theMenuSourceText,
-                                     const int theMenuPosition = 10);
+    const QString& theTip, const QIcon& theIcon,
+    const QKeySequence& theKeys, bool isCheckable,
+    const char* theMenuSourceText, const QString& theSubMenu = QString(),
+    const int theMenuPosition = 10,
+    const int theSuibMenuPosition = -1) Standard_OVERRIDE;
 
   virtual void addDesktopMenuSeparator(const char* theMenuSourceText,
                                        const int theMenuPosition = 10);
@@ -170,6 +171,8 @@ Q_OBJECT
 
   void resetToolbars();
 
+  void publishToStudy();
+
  public slots:
   /// \brief The method is redefined to connect to the study viewer before the data
   /// model is filled by opened file. This file open will flush redisplay signals for,
index efb30f936765a43c170cefea155ee697679e16a2..5a2effdc7fa16695843f6e1806feadc4aac9dffe 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <ModelAPI_Session.h>
 #include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeBoolean.h>
 #include <ExchangePlugin_Dump.h>
 
 #include <LightApp_Study.h>
@@ -85,6 +86,9 @@ bool SHAPERGUI_DataModel::open(const QString& thePath, CAM_Study* theStudy, QStr
 
 bool SHAPERGUI_DataModel::save(QStringList& theFiles)
 {
+  // Publish to study before saving of the data model
+  myModule->publishToStudy();
+
   LightApp_DataModel::save( theFiles );
   XGUI_Workshop* aWorkShop = myModule->workshop();
   std::list<std::string> aFileNames;
@@ -175,6 +179,8 @@ bool SHAPERGUI_DataModel::dumpPython(const QString& thePath, CAM_Study* theStudy
   if (!aStudy)
     return false;
 
+  myModule->publishToStudy();
+
   std::shared_ptr<ModelAPI_Document> aDoc = ModelAPI_Session::get()->activeDocument();
   ModelAPI_Session::get()->startOperation(ExchangePlugin_Dump::ID());
   FeaturePtr aFeature = aDoc->addFeature(ExchangePlugin_Dump::ID());
@@ -194,6 +200,10 @@ bool SHAPERGUI_DataModel::dumpPython(const QString& thePath, CAM_Study* theStudy
     if (aAttr.get())
       aAttr->setValue(".py");
 
+#ifdef HAVE_SALOME
+    aFeature->boolean(ExchangePlugin_Dump::EXPORT_VARIABLES_ID())->setValue(true);
+#endif
+
     ModelAPI_Session::get()->finishOperation();
 
     if (QFile::exists(aFileName.c_str())) {
@@ -232,4 +242,3 @@ bool SHAPERGUI_DataModel::dumpPython(const QString& thePath, CAM_Study* theStudy
   }
   return false;
 }
-
index c6e85fba300e5e60c16cee2521294998c538cb40..fcd1899e10b16f56c531cadff3ff8084a78fd737 100644 (file)
@@ -221,6 +221,7 @@ ADD_UNIT_TESTS(
   Test3087_1.py
   Test3087_2.py
   Test3132.py
+  Test3154.py
   TestArcBehavior.py
   TestBSplineAddPole.py
   TestChangeSketchPlane1.py
index 94236695e053cfa67cba433d1e51ca1f970354ae..9e60ab2e3441dad5e39418527b13c09d8df1251a 100644 (file)
@@ -976,7 +976,7 @@ bool SketchPlugin_SplitValidator::isValid(const AttributePtr& theAttribute,
   GeomShapePtr anAttrShape = (*anEdgeShapes.begin())->shape();
   std::shared_ptr<SketchPlugin_Feature> aSFeature =
                                 std::dynamic_pointer_cast<SketchPlugin_Feature>(anAttrFeature);
-  if (!aSFeature)
+  if (!aSFeature || aSFeature->isCopy())
     return false;
   SketchPlugin_Sketch* aSketch = aSFeature->sketch();
 
diff --git a/src/SketchPlugin/Test/Test3154.py b/src/SketchPlugin/Test/Test3154.py
new file mode 100755 (executable)
index 0000000..b891abc
--- /dev/null
@@ -0,0 +1,42 @@
+# Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from salome.shaper import model
+from salome.shaper import geom
+
+from SketchAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Cylinder_1_1/Face_2"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "[Cylinder_1_1/Face_1][Cylinder_1_1/Face_3]"), True)
+SketchCircle_1 = SketchProjection_1.createdFeature()
+SketchLine_1 = Sketch_1.addLine(-0.2715703110882526, -4.992619509449466, -1.152966889672805, 4.865251005995354)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchCircle_1.results()[1])
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchCircle_1.results()[1])
+model.do()
+
+SketchSplit_1 = Sketch_1.addSplit(SketchAPI_Circle(SketchCircle_1), geom.Pnt2d(-5, 0))
+model.end()
+
+# check Split is invalid
+assert(SketchSplit_1.feature().error() != "")
index a4fa551c1f874e057706104d9d912e682b838cbf..0ea99e989ae8ba17a7df24bf9929c72d3402126d 100644 (file)
@@ -90,3 +90,4 @@ SET(XAO_SOURCES
 ADD_LIBRARY(XAOShaper SHARED ${XAO_SOURCES} ${XAO_HEADERS})
 TARGET_LINK_LIBRARIES(XAOShaper ${PROJECT_LIBRARIES})
 INSTALL(TARGETS XAOShaper DESTINATION ${SHAPER_INSTALL_BIN})
+INSTALL(FILES ${XAO_HEADERS} DESTINATION ${SHAPER_INSTALL_HEADERS})
index 625bc9fe437be7af90daa2c8cb025204bc57a86f..071173173efc9c0c16edadfc827912855284bf81 100644 (file)
@@ -30,7 +30,7 @@
 #include <QDialogButtonBox>
 
 XGUI_ColorDialog::XGUI_ColorDialog(QWidget* theParent)
-  : QDialog(theParent)
+  : QDialog(theParent, Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint)
 {
   setWindowTitle(tr("Color"));
   QGridLayout* aLay = new QGridLayout(this);
index a174bea87b737f8ae17402cf8e0e725739ea0687..fe220b6578c83044f9938a0b15e9f4329e7be525 100644 (file)
@@ -140,6 +140,14 @@ void XGUI_ContextMenuMgr::createActions()
                                            aDesktop);
   addAction("WIREFRAME_CMD", aAction);
 
+  aAction = ModuleBase_Tools::createAction(QIcon(":pictures/iso_lines.png"), tr("Define Isos..."),
+                                           aDesktop);
+  addAction("ISOLINES_CMD", aAction);
+
+  aAction = ModuleBase_Tools::createAction(QIcon(), tr("Show Isos..."), aDesktop);
+  aAction->setCheckable(true);
+  addAction("SHOW_ISOLINES_CMD", aAction);
+
   mySeparator1 = ModuleBase_Tools::createAction(QIcon(), "", aDesktop);
   mySeparator1->setSeparator(true);
 
@@ -302,6 +310,9 @@ void XGUI_ContextMenuMgr::updateObjectBrowserMenu()
     //Process Feature
     if (aSelected == 1) { // single selection
       ObjectPtr aObject = aObjects.first();
+      ResultPtr aResult;
+      if (hasResult)
+        aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObject);
       if (aObject) {
         if (hasResult && myWorkshop->canBeShaded(aObject)) {
           XGUI_Displayer::DisplayMode aMode = aDisplayer->displayMode(aObject);
@@ -312,10 +323,12 @@ void XGUI_ContextMenuMgr::updateObjectBrowserMenu()
             action("WIREFRAME_CMD")->setEnabled(true);
             action("SHADING_CMD")->setEnabled(true);
           }
+          action("SHOW_ISOLINES_CMD")->setEnabled(true);
+          action("SHOW_ISOLINES_CMD")->setChecked(ModelAPI_Tools::isShownIsoLines(aResult));
+          action("ISOLINES_CMD")->setEnabled(true);
         }
         if (!hasFeature) {
-          bool aHasSubResults = ModelAPI_Tools::hasSubResults(
-                                            std::dynamic_pointer_cast<ModelAPI_Result>(aObject));
+          bool aHasSubResults = ModelAPI_Tools::hasSubResults(aResult);
           if (aHasSubResults) {
             action("HIDE_CMD")->setEnabled(true);
             action("SHOW_CMD")->setEnabled(true);
@@ -352,6 +365,8 @@ void XGUI_ContextMenuMgr::updateObjectBrowserMenu()
         action("SHOW_ONLY_CMD")->setEnabled(true);
         action("SHADING_CMD")->setEnabled(true);
         action("WIREFRAME_CMD")->setEnabled(true);
+        action("SHOW_ISOLINES_CMD")->setEnabled(true);
+        action("ISOLINES_CMD")->setEnabled(true);
       }
       if (hasFeature && myWorkshop->canMoveFeature()) {
         action("MOVE_CMD")->setEnabled(true);
@@ -541,6 +556,15 @@ void XGUI_ContextMenuMgr::updateViewerMenu()
           action("WIREFRAME_CMD")->setEnabled(true);
           action("SHADING_CMD")->setEnabled(true);
         }
+        action("ISOLINES_CMD")->setEnabled(true);
+
+        if (aPrsList.size() == 1) {
+          ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObject);
+          if (aResult.get()) {
+            action("SHOW_ISOLINES_CMD")->setEnabled(true);
+            action("SHOW_ISOLINES_CMD")->setChecked(ModelAPI_Tools::isShownIsoLines(aResult));
+          }
+        }
       }
       action("SHOW_ONLY_CMD")->setEnabled(true);
       action("HIDE_CMD")->setEnabled(true);
@@ -655,6 +679,8 @@ void XGUI_ContextMenuMgr::buildObjBrowserMenu()
   aList.append(action("COLOR_CMD"));
   aList.append(action("DEFLECTION_CMD"));
   aList.append(action("TRANSPARENCY_CMD"));
+  aList.append(action("SHOW_ISOLINES_CMD"));
+  aList.append(action("ISOLINES_CMD"));
   aList.append(action("SHOW_FEATURE_CMD"));
   aList.append(mySeparator3);
   aList.append(action("DELETE_CMD"));
@@ -730,6 +756,8 @@ void XGUI_ContextMenuMgr::buildViewerMenu()
   aList.append(action("COLOR_CMD"));
   aList.append(action("DEFLECTION_CMD"));
   aList.append(action("TRANSPARENCY_CMD"));
+  aList.append(action("SHOW_ISOLINES_CMD"));
+  aList.append(action("ISOLINES_CMD"));
   aList.append(mySeparator3);
   aList.append(action("SET_VIEW_NORMAL_CMD"));
   aList.append(action("SET_VIEW_INVERTEDNORMAL_CMD"));
@@ -783,6 +811,8 @@ void XGUI_ContextMenuMgr::addObjBrowserMenu(QMenu* theMenu) const
       aActions.append(action("COLOR_CMD"));
       aActions.append(action("DEFLECTION_CMD"));
       aActions.append(action("TRANSPARENCY_CMD"));
+      aActions.append(action("SHOW_ISOLINES_CMD"));
+      aActions.append(action("ISOLINES_CMD"));
       aActions.append(action("CLEAN_HISTORY_CMD"));
       aActions.append(action("DELETE_CMD"));
   }
index 598d33e11dfc782c670662daa79252ff2c670c47..568343a74367f2b02d665fb47b440307e73003a7 100644 (file)
@@ -30,7 +30,7 @@
 #include <QDialogButtonBox>
 
 XGUI_DeflectionDialog::XGUI_DeflectionDialog(QWidget* theParent)
-  : QDialog(theParent)
+  : QDialog(theParent, Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint)
 {
   setWindowTitle(tr("Deflection"));
   QGridLayout* aLay = new QGridLayout(this);
index 3f7d23326ef5544ae0d448665bd08a89e2c2c3bf..00360a96defc2743b9c8edb97c976c1f76507aaa 100644 (file)
@@ -314,6 +314,11 @@ bool XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer)
       double aTransparency = ModelAPI_Tools::getTransparency(aResult);
       if ((aTransparency >= 0) && (aTransparency != aAISObj->getTransparency()))
         aAISObj->setTransparency(aTransparency);
+
+      // Set Iso-Lines
+      Handle(ModuleBase_ResultPrs) aResPrs = Handle(ModuleBase_ResultPrs)::DownCast(aAISIO);
+      if (!aResPrs.IsNull())
+        aResPrs->updateIsoLines();
     }
     myWorkshop->module()->storeSelection();
 
index 8e872a3d82f345b9285f39e33e935bfd0eb68b9a..487c11ec5b0d1c70123ffb33cfd3210cb20a0aef 100644 (file)
@@ -25,7 +25,8 @@
 #include <QGridLayout>
 
 XGUI_PropertyDialog::XGUI_PropertyDialog(QWidget* theParent)
-: QDialog(theParent), myContentWidget(0)
+: QDialog(theParent, Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint),
+  myContentWidget(0)
 {
   myLayout = new QGridLayout(this);
 
index acf23e2bedad624445c442cd055e52efed61845f..c249619430129e3c6bc4e0e46efd9c4bf610b579 100644 (file)
@@ -92,13 +92,17 @@ class XGUI_EXPORT XGUI_SalomeConnector
   //! \param isCheckable - is checkable or not
   //! \param theKeys - hot keys
   //! \param theMenuSourceText - a source text of the desktop menu
+  //! \param theSubMenu - a sub-menu name
   //! \param theMenuPosition - a position of the command in the desktop menu
+  //! \param theSuibMenuPosition - a position of the sub-menu in the desktop menu
   //! returns created action
   virtual QAction* addDesktopCommand(const QString& theId, const QString& theTitle,
                                      const QString& theTip, const QIcon& theIcon,
                                      const QKeySequence& theKeys, bool isCheckable,
                                      const char* theMenuSourceText,
-                                     const int theMenuPosition = 10) = 0;
+                                     const QString& theSubMenu = QString(),
+                                     const int theMenuPosition = 10,
+                                     const int theSuibMenuPosition = -1) = 0;
 
   //! Insert separator into Edit menu of SALOME desktop
   virtual void addDesktopMenuSeparator(const char* theMenuSourceText,
index 82154a769367c2167bca85c0aa9ede133f73834a..4b82e3ed627b289936b4967ed3dd504302dcf052 100644 (file)
@@ -466,6 +466,7 @@ void XGUI_ViewerProxy::displayHighlight(FeaturePtr theFeature, const TopoDS_Shap
           aAis->SetZLayer(Graphic3d_ZLayerId_Top); //Graphic3d_ZLayerId_Topmost
           aDeflection = Config_PropManager::real("Visualization", "construction_deflection");
           aAis->Attributes()->SetDeviationCoefficient(aDeflection);
+          aAis->Attributes()->SetIsoOnPlane(false);
           myHighlights.Append(aAis);
           aContext->Display(aAis, false);
           aContext->Deactivate(aAis);
@@ -480,6 +481,7 @@ void XGUI_ViewerProxy::displayHighlight(FeaturePtr theFeature, const TopoDS_Shap
     aAis->SetZLayer(Graphic3d_ZLayerId_Top); //Graphic3d_ZLayerId_Topmost
     aDeflection = Config_PropManager::real("Visualization", "body_deflection");
     aAis->Attributes()->SetDeviationCoefficient(aDeflection);
+    aAis->Attributes()->SetIsoOnPlane(false);
     myHighlights.Append(aAis);
     aContext->Display(aAis, false);
     aContext->Deactivate(aAis);
index bb845edb3f7407a49bba83d7de00642fc69c5d7d..6963c8426af58ed400ce5e7c7727e14205d5b445 100644 (file)
@@ -80,6 +80,7 @@
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_ResultField.h>
+#include <ModuleBase_IconFactory.h>
 
 //#include <PartSetPlugin_Part.h>
 
@@ -89,6 +90,8 @@
 
 #include <ExchangePlugin_ExportPart.h>
 #include <ExchangePlugin_ImportPart.h>
+#include <ExchangePlugin_Import.h>
+#include <ExchangePlugin_ExportFeature.h>
 
 #include <GeomAPI_Pnt.h>
 #include <GeomAPI_ShapeExplorer.h>
 #include <QDesktopWidget>
 #include <QProcess>
 #include <QDesktopServices>
+#include <QFormLayout>
+#include <QSpinBox>
+#include <QDialogButtonBox>
 
 #include <iterator>
 
@@ -467,31 +473,43 @@ void XGUI_Workshop::initMenu()
 
 
   // Add commands to a file menu
-  aAction = salomeConnector()->addDesktopCommand("SAVEAS_CMD", tr("Export native..."),
-                                             tr("Export the current document into a native file"),
-                                              QIcon(), QKeySequence(),
-                                              false, "MEN_DESK_FILE");
-  connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onSaveAs()));
-
-  aAction = salomeConnector()->addDesktopCommand("OPEN_CMD", tr("Import native..."),
+  // Import sub-menu
+  aAction = salomeConnector()->addDesktopCommand("OPEN_CMD", tr("Part set..."),
                                               tr("Import native file"),
                                               QIcon(), QKeySequence(),
-                                              false, "MEN_DESK_FILE");
+                                              false, "MEN_DESK_FILE", tr("Import"), 10, 10);
   connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onOpen()));
-  salomeConnector()->addDesktopMenuSeparator("MEN_DESK_FILE");
 
-  aAction = salomeConnector()->addDesktopCommand("EXPORT_PART_CMD", tr("Export part..."),
+  aAction = salomeConnector()->addDesktopCommand("IMPORT_PART_CMD", tr("Part..."),
+                                          tr("Import structure of a part"),
+                                          QIcon(), QKeySequence(),
+                                          false, "MEN_DESK_FILE", tr("Import"), 10, 10);
+  connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onImportPart()));
+
+  aAction = salomeConnector()->addDesktopCommand("IMPORT_SHAPE_CMD", tr("From CAD format..."),
+    tr("Import shape from a CAD format file"),
+    ModuleBase_IconFactory::loadIcon("icons/Exchange/import.png"),
+    QKeySequence(), false, "MEN_DESK_FILE", tr("Import"), 10, 10);
+  connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onImportShape()));
+
+  // Export sub-menu
+  aAction = salomeConnector()->addDesktopCommand("SAVEAS_CMD", tr("Part set..."),
+                                             tr("Export the current document into a native file"),
+                                              QIcon(), QKeySequence(),
+                                              false, "MEN_DESK_FILE", tr("Export"), 10, 11);
+  connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onSaveAs()));
+
+  aAction = salomeConnector()->addDesktopCommand("EXPORT_PART_CMD", tr("Part..."),
                                           tr("Export a part of the current document into a file"),
                                           QIcon(), QKeySequence(),
-                                          false, "MEN_DESK_FILE");
+                                          false, "MEN_DESK_FILE", tr("Export"), 10, 11);
   connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onExportPart()));
 
-  aAction = salomeConnector()->addDesktopCommand("IMPORT_PART_CMD", tr("Import part..."),
-                                          tr("Import structure of a part"),
-                                          QIcon(), QKeySequence(),
-                                          false, "MEN_DESK_FILE");
-  connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onImportPart()));
-  salomeConnector()->addDesktopMenuSeparator("MEN_DESK_FILE");
+  aAction = salomeConnector()->addDesktopCommand("EXPORT_SHAPE_CMD", tr("To CAD format..."),
+    tr("Export shape to a CAD format file"),
+    ModuleBase_IconFactory::loadIcon("icons/Exchange/export.png"),
+    QKeySequence(), false, "MEN_DESK_FILE", tr("Export"), 10, 11);
+  connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onExportShape()));
 
 #else
   // File commands group
@@ -1298,6 +1316,28 @@ void XGUI_Workshop::onImportPart()
   }
 }
 
+//******************************************************
+void XGUI_Workshop::onImportShape()
+{
+  if (abortAllOperations()) {
+    ModuleBase_OperationFeature* anImportOp = dynamic_cast<ModuleBase_OperationFeature*>(
+        module()->createOperation(ExchangePlugin_Import::ID()));
+    myPropertyPanel->updateApplyPlusButton(anImportOp->feature());
+    operationMgr()->startOperation(anImportOp);
+  }
+}
+
+//******************************************************
+void XGUI_Workshop::onExportShape()
+{
+  if (abortAllOperations()) {
+    ModuleBase_OperationFeature* anExportOp = dynamic_cast<ModuleBase_OperationFeature*>(
+        module()->createOperation(ExchangePlugin_ExportFeature::ID()));
+    myPropertyPanel->updateApplyPlusButton(anExportOp->feature());
+    operationMgr()->startOperation(anExportOp);
+  }
+}
+
 //******************************************************
 void XGUI_Workshop::onExportPart()
 {
@@ -1656,6 +1696,17 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked)
     moveObjects(theId == "MOVE_SPLIT_CMD");
   else if (theId == "COLOR_CMD")
     changeColor(aObjects);
+  else if (theId == "ISOLINES_CMD")
+    changeIsoLines(aObjects);
+  else if (theId == "SHOW_ISOLINES_CMD") {
+    foreach(ObjectPtr aObj, aObjects) {
+      ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
+      if (aResult.get())
+        ModelAPI_Tools::showIsoLines(aResult, !ModelAPI_Tools::isShownIsoLines(aResult));
+    }
+    mySelector->clearSelection();
+    Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+  }
   else if (theId == "DEFLECTION_CMD")
     changeDeflection(aObjects);
   else if (theId == "TRANSPARENCY_CMD")
@@ -2337,22 +2388,6 @@ bool XGUI_Workshop::canChangeProperty(const QString& theActionName) const
   return false;
 }
 
-//******************************************************
-void setColor(ResultPtr theResult, const std::vector<int>& theColor)
-{
-  if (!theResult.get())
-    return;
-
-  AttributeIntArrayPtr aColorAttr = theResult->data()->intArray(ModelAPI_Result::COLOR_ID());
-  if (aColorAttr.get() != NULL) {
-    if (!aColorAttr->size()) {
-      aColorAttr->setSize(3);
-    }
-    aColorAttr->setValue(0, theColor[0]);
-    aColorAttr->setValue(1, theColor[1]);
-    aColorAttr->setValue(2, theColor[2]);
-  }
-}
 
 //**************************************************************
 void getDefaultColor(ObjectPtr theObject, const bool isEmptyColorValid,
@@ -2435,10 +2470,10 @@ void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects)
         std::list<ResultPtr> allRes;
         ModelAPI_Tools::allSubs(aBodyResult, allRes);
         for(std::list<ResultPtr>::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) {
-          setColor(*aRes, !isRandomColor ? aColorResult : aDlg->getRandomColor());
+          ModelAPI_Tools::setColor(*aRes, !isRandomColor ? aColorResult : aDlg->getRandomColor());
         }
       }
-      setColor(aResult, !isRandomColor ? aColorResult : aDlg->getRandomColor());
+      ModelAPI_Tools::setColor(aResult, !isRandomColor ? aColorResult : aDlg->getRandomColor());
     }
   }
   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
@@ -2447,30 +2482,6 @@ void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects)
   myViewerProxy->update();
 }
 
-//**************************************************************
-void setDeflection(ResultPtr theResult, const double theDeflection)
-{
-  if (!theResult.get())
-    return;
-
-  AttributeDoublePtr aDeflectionAttr = theResult->data()->real(ModelAPI_Result::DEFLECTION_ID());
-  if (aDeflectionAttr.get() != NULL) {
-    aDeflectionAttr->setValue(theDeflection);
-  }
-}
-
-//**************************************************************
-void setTransparency(ResultPtr theResult, double theTransparency)
-{
-  if (!theResult.get())
-    return;
-
-  AttributeDoublePtr anAttribute = theResult->data()->real(ModelAPI_Result::TRANSPARENCY_ID());
-  if (anAttribute.get() != NULL) {
-    anAttribute->setValue(theTransparency);
-  }
-}
-
 //**************************************************************
 void setTransparency(double theTransparency, const QObjectPtrList& theObjects)
 {
@@ -2483,10 +2494,10 @@ void setTransparency(double theTransparency, const QObjectPtrList& theObjects)
         ModelAPI_Tools::allSubs(aBodyResult, allRes);
         std::list<ResultPtr>::iterator aRes;
         for(aRes = allRes.begin(); aRes != allRes.end(); aRes++) {
-          setTransparency(*aRes, theTransparency);
+          ModelAPI_Tools::setTransparency(*aRes, theTransparency);
         }
       }
-      setTransparency(aResult, theTransparency);
+      ModelAPI_Tools::setTransparency(aResult, theTransparency);
     }
   }
 }
@@ -2574,10 +2585,10 @@ void XGUI_Workshop::changeDeflection(const QObjectPtrList& theObjects)
         std::list<ResultPtr> allRes;
         ModelAPI_Tools::allSubs(aBodyResult, allRes);
         for(std::list<ResultPtr>::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) {
-          setDeflection(*aRes, aDeflection);
+          ModelAPI_Tools::setDeflection(*aRes, aDeflection);
         }
       }
-      setDeflection(aResult, aDeflection);
+      ModelAPI_Tools::setDeflection(aResult, aDeflection);
     }
   }
   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
@@ -3177,3 +3188,66 @@ void XGUI_Workshop::deactivateCurrentSelector()
 {
   myActiveControlMgr->deactivateSelector(myActiveControlMgr->activeSelector());
 }
+
+void XGUI_Workshop::changeIsoLines(const QObjectPtrList& theObjects)
+{
+  if (theObjects.isEmpty())
+    return;
+
+  QList<ResultPtr> aResultList;
+  ResultPtr aRes;
+  foreach(ObjectPtr aObj, theObjects) {
+    aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
+    if (aRes.get())
+      aResultList.append(aRes);
+  }
+
+  std::vector<int> aValues;
+  bool isVisible;
+  if (aResultList.size() == 1) {
+    ResultPtr aRes = aResultList.first();
+    if (aRes.get())
+      ModelAPI_Tools::getIsoLines(aRes, isVisible, aValues);
+    else
+      return;
+  }
+  if (aValues.size() == 0) {
+    aValues.push_back(1);
+    aValues.push_back(1);
+  }
+
+  if (!abortAllOperations())
+    return;
+
+  XGUI_PropertyDialog aDlg(desktop());
+  aDlg.setWindowTitle(tr("Number of Iso-lines"));
+
+  QWidget* aIsosWgt = new QWidget(&aDlg);
+  QFormLayout* aLayout = new QFormLayout(aIsosWgt);
+  ModuleBase_Tools::adjustMargins(aLayout);
+  aDlg.setContent(aIsosWgt);
+
+  QSpinBox* aUNb = new QSpinBox(&aDlg);
+  aUNb->setValue(aValues[0]);
+  aLayout->addRow("U:", aUNb);
+
+  QSpinBox* aVNb = new QSpinBox(&aDlg);
+  aVNb->setValue(aValues[1]);
+  aLayout->addRow("V:", aVNb);
+
+  if (aDlg.exec() == QDialog::Accepted) {
+    SessionPtr aMgr = ModelAPI_Session::get();
+    QString aDescription = contextMenuMgr()->action("ISOLINES_CMD")->text();
+    aMgr->startOperation(aDescription.toStdString());
+
+    aValues[0] = aUNb->value();
+    aValues[1] = aVNb->value();
+    foreach(ResultPtr aRes, aResultList) {
+      ModelAPI_Tools::setIsoLines(aRes, aValues);
+    }
+    mySelector->clearSelection();
+    Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+    aMgr->finishOperation();
+    updateCommandStatus();
+  }
+}
\ No newline at end of file
index 37ae6a8a2be07ea5265ba5463d38f4670c141f45..18f9cd77c3a3932aab81f4262c8e335a068b92e9 100644 (file)
@@ -213,6 +213,10 @@ Q_OBJECT
   /// theObjects a list of selected objects
   void changeTransparency(const QObjectPtrList& theObjects);
 
+  /// Change number of iso-lines for the given objects
+  /// theObjects a list of selected objects
+  void changeIsoLines(const QObjectPtrList& theObjects);
+
   /// Show the given features in 3d Viewer
   void showObjects(const QObjectPtrList& theList, bool isVisible);
 
@@ -401,9 +405,15 @@ signals:
   /// Import part structure from a file
   void onImportPart();
 
+  /// Import shape from a file
+  void onImportShape();
+
   /// Export features to a file
   void onExportPart();
 
+  /// Export a shape to a file
+  void onExportShape();
+
 #ifndef HAVE_SALOME
   /// Exit application
   void onExit();
index 859c4018b776aab83ead3ff470427fdd4979088d..270adced61a4e837f85effc7226b2349ed546eb9 100644 (file)
     </message>
     <message>
         <source>Iso-lines...</source>
-        <translation></translation>
+        <translation type="vanished">Iso-lines...</translation>
+    </message>
+    <message>
+        <source>Define Isos...</source>
+        <translation>Définir l&apos;Isos...</translation>
+    </message>
+    <message>
+        <source>Show Isos...</source>
+        <translation>Show Isos...</translation>
     </message>
 </context>
 <context>
     </message>
     <message>
         <source>Export native...</source>
-        <translation>Exporter natif...</translation>
+        <translation type="vanished">Exporter natif...</translation>
     </message>
     <message>
         <source>Export the current document into a native file</source>
     </message>
     <message>
         <source>Import native...</source>
-        <translation>Importer natif...</translation>
+        <translation type="vanished">Importer natif...</translation>
     </message>
     <message>
         <source>Import native file</source>
@@ -671,7 +679,7 @@ Supprimer des objets du panneau à afficher ?</translation>
     </message>
     <message>
         <source>Export part...</source>
-        <translation>Partie export...</translation>
+        <translation type="vanished">Partie export...</translation>
     </message>
     <message>
         <source>Export a part of the current document into a file</source>
@@ -679,23 +687,47 @@ Supprimer des objets du panneau à afficher ?</translation>
     </message>
     <message>
         <source>Import part...</source>
-        <translation>Importer une partie...</translation>
+        <translation type="vanished">Importer une partie...</translation>
     </message>
     <message>
         <source>Import structure of a part</source>
         <translation>Structure d&apos;importation d&apos;une pièce</translation>
     </message>
     <message>
-        <source>Import shape...</source>
-        <translation>Forme de l&apos;importation...</translation>
+        <source>Part set...</source>
+        <translation>Ensemble de parties...</translation>
+    </message>
+    <message>
+        <source>Import</source>
+        <translation>Importation</translation>
+    </message>
+    <message>
+        <source>Part...</source>
+        <translation>Partie...</translation>
     </message>
     <message>
-        <source>Import shape from a file</source>
-        <translation>Importer une forme à partir d&apos;un fichier</translation>
+        <source>From CAD format...</source>
+        <translation>A partir du format CAO...</translation>
+    </message>
+    <message>
+        <source>Import shape from a CAD format file</source>
+        <translation>Importer une forme à partir d&apos;un fichier au format CAO</translation>
+    </message>
+    <message>
+        <source>Export</source>
+        <translation>Exporter</translation>
+    </message>
+    <message>
+        <source>To CAD format...</source>
+        <translation>Au format CAO...</translation>
     </message>
     <message>
         <source>Number of Iso-lines</source>
-        <translation>Nombre de lignes Iso-Lines</translation>
+        <translation>Nombre de Iso-lignes</translation>
+    </message>
+    <message>
+        <source>Export shape to a CAD format file</source>
+        <translation>Exportation de la forme vers un fichier au format CAO</translation>
     </message>
 </context>
 </TS>
index 2178d9dda21d4ebf86037792b770e8fcd2f5c9c2..1225bcc3205411410d31cc2b11a1982605738a30 100644 (file)
@@ -95,5 +95,6 @@
      <file>pictures/ArrowCursor.png</file>
      <file>pictures/CrossCursor.png</file>
      <file>pictures/HandCursor.png</file>
+     <file>pictures/iso_lines.png</file>
  </qresource>
  </RCC>
diff --git a/src/XGUI/pictures/iso_lines.png b/src/XGUI/pictures/iso_lines.png
new file mode 100644 (file)
index 0000000..20f86bc
Binary files /dev/null and b/src/XGUI/pictures/iso_lines.png differ