]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Merge remote-tracking branch 'origin/ngo/Lot5'
authormpv <mpv@opencascade.com>
Wed, 2 Oct 2019 10:04:46 +0000 (13:04 +0300)
committermpv <mpv@opencascade.com>
Wed, 2 Oct 2019 10:04:46 +0000 (13:04 +0300)
237 files changed:
env.sh
src/BuildPlugin/compound_widget.xml
src/BuildPlugin/compsolid_widget.xml
src/BuildPlugin/edge_widget.xml
src/BuildPlugin/face_widget.xml
src/BuildPlugin/filling_widget.xml
src/BuildPlugin/interpolation_widget.xml
src/BuildPlugin/plugin-Build.xml
src/BuildPlugin/polyline_widget.xml
src/BuildPlugin/shell_widget.xml
src/BuildPlugin/solid_widget.xml
src/BuildPlugin/subshapes_widget.xml
src/BuildPlugin/vertex_widget.xml
src/BuildPlugin/wire_widget.xml
src/CollectionAPI/CMakeLists.txt
src/CollectionAPI/CollectionAPI.i
src/CollectionAPI/CollectionAPI_GroupAddition.cpp [new file with mode: 0644]
src/CollectionAPI/CollectionAPI_GroupAddition.h [new file with mode: 0644]
src/CollectionAPI/CollectionAPI_GroupIntersection.cpp [new file with mode: 0644]
src/CollectionAPI/CollectionAPI_GroupIntersection.h [new file with mode: 0644]
src/CollectionAPI/CollectionAPI_GroupSubstraction.cpp [new file with mode: 0644]
src/CollectionAPI/CollectionAPI_GroupSubstraction.h [new file with mode: 0644]
src/CollectionPlugin/CMakeLists.txt
src/CollectionPlugin/CollectionPlugin_GroupAddition.cpp [new file with mode: 0644]
src/CollectionPlugin/CollectionPlugin_GroupAddition.h [new file with mode: 0644]
src/CollectionPlugin/CollectionPlugin_GroupIntersection.cpp [new file with mode: 0644]
src/CollectionPlugin/CollectionPlugin_GroupIntersection.h [new file with mode: 0644]
src/CollectionPlugin/CollectionPlugin_GroupOperation.cpp [new file with mode: 0644]
src/CollectionPlugin/CollectionPlugin_GroupOperation.h [new file with mode: 0644]
src/CollectionPlugin/CollectionPlugin_GroupSubstraction.cpp [new file with mode: 0644]
src/CollectionPlugin/CollectionPlugin_GroupSubstraction.h [new file with mode: 0644]
src/CollectionPlugin/CollectionPlugin_Plugin.cpp
src/CollectionPlugin/CollectionPlugin_Validators.cpp
src/CollectionPlugin/CollectionPlugin_Validators.h
src/CollectionPlugin/CollectionPlugin_WidgetField.cpp
src/CollectionPlugin/CollectionPlugin_msg_en.ts
src/CollectionPlugin/Test/Test2977.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupAddition.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupAddition_Error.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupIntersection.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupIntersection_Error.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupSubstraction.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupSubstraction_Error1.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupSubstraction_Error2.py [new file with mode: 0644]
src/CollectionPlugin/doc/CollectionPlugin.rst
src/CollectionPlugin/doc/TUI_groupAdditionFeature.rst [new file with mode: 0644]
src/CollectionPlugin/doc/TUI_groupIntersectionFeature.rst [new file with mode: 0644]
src/CollectionPlugin/doc/TUI_groupSubstractionFeature.rst [new file with mode: 0644]
src/CollectionPlugin/doc/examples/group_addition.py [new file with mode: 0644]
src/CollectionPlugin/doc/examples/group_intersection.py [new file with mode: 0644]
src/CollectionPlugin/doc/examples/group_substraction.py [new file with mode: 0644]
src/CollectionPlugin/doc/groupAdditionFeature.rst [new file with mode: 0644]
src/CollectionPlugin/doc/groupFeature.rst
src/CollectionPlugin/doc/groupIntersectionFeature.rst [new file with mode: 0644]
src/CollectionPlugin/doc/groupSubstractionFeature.rst [new file with mode: 0644]
src/CollectionPlugin/doc/images/add.png [deleted file]
src/CollectionPlugin/doc/images/delete.png [deleted file]
src/CollectionPlugin/doc/images/group_addition.png [new file with mode: 0644]
src/CollectionPlugin/doc/images/group_addition_property_panel.png [new file with mode: 0644]
src/CollectionPlugin/doc/images/group_intersection.png [new file with mode: 0644]
src/CollectionPlugin/doc/images/group_intersection_property_panel.png [new file with mode: 0644]
src/CollectionPlugin/doc/images/group_substraction.png [new file with mode: 0644]
src/CollectionPlugin/doc/images/group_substraction_property_panel.png [new file with mode: 0644]
src/CollectionPlugin/doc/images/reverce.png [deleted file]
src/CollectionPlugin/doc/images/selection_by_filters.png [deleted file]
src/CollectionPlugin/doc/images/selection_by_filters_added.png [deleted file]
src/CollectionPlugin/group_addition_widget.xml [new file with mode: 0644]
src/CollectionPlugin/group_intersection_widget.xml [new file with mode: 0644]
src/CollectionPlugin/group_substraction_widget.xml [new file with mode: 0644]
src/CollectionPlugin/group_widget.xml
src/CollectionPlugin/icons/group_addition.png [new file with mode: 0644]
src/CollectionPlugin/icons/group_intersection.png [new file with mode: 0644]
src/CollectionPlugin/icons/group_substraction.png [new file with mode: 0644]
src/CollectionPlugin/plugin-Collection.xml
src/Config/Config_FeatureMessage.cpp
src/Config/Config_FeatureReader.cpp
src/Config/plugins.xml.in
src/ConnectorAPI/Test/TestExportToGEOMAllGroupsAndFields.py
src/ExchangePlugin/ExchangePlugin_Validators.cpp
src/ExchangePlugin/export_widget.xml
src/FeaturesAPI/CMakeLists.txt
src/FeaturesAPI/FeaturesAPI.i
src/FeaturesAPI/FeaturesAPI_Chamfer.cpp [new file with mode: 0644]
src/FeaturesAPI/FeaturesAPI_Chamfer.h [new file with mode: 0644]
src/FeaturesAPI/FeaturesAPI_swig.h
src/FeaturesPlugin/CMakeLists.txt
src/FeaturesPlugin/FeaturesPlugin_Chamfer.cpp [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_Chamfer.h [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_MultiTranslation.cpp
src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp
src/FeaturesPlugin/Test/Test17261.py [new file with mode: 0644]
src/FeaturesPlugin/Test/Test17281.py [new file with mode: 0644]
src/FeaturesPlugin/Test/Test2971.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestChamfer.py [new file with mode: 0644]
src/FeaturesPlugin/boolean_common_widget.xml
src/FeaturesPlugin/boolean_fuse_widget.xml
src/FeaturesPlugin/boolean_smash_widget.xml
src/FeaturesPlugin/boolean_split_widget.xml
src/FeaturesPlugin/boolean_widget.xml
src/FeaturesPlugin/chamfer_widget.xml [new file with mode: 0644]
src/FeaturesPlugin/doc/FeaturesPlugin.rst
src/FeaturesPlugin/doc/TUI_chamferDistAngle.rst [new file with mode: 0644]
src/FeaturesPlugin/doc/TUI_chamferDistances.rst [new file with mode: 0644]
src/FeaturesPlugin/doc/chamferFeature.rst [new file with mode: 0644]
src/FeaturesPlugin/doc/examples/chamfer1.py [new file with mode: 0644]
src/FeaturesPlugin/doc/examples/chamfer2.py [new file with mode: 0644]
src/FeaturesPlugin/doc/images/ChamferDistAngle.png [new file with mode: 0644]
src/FeaturesPlugin/doc/images/ChamferDistances.png [new file with mode: 0644]
src/FeaturesPlugin/doc/images/chamfer.png [new file with mode: 0644]
src/FeaturesPlugin/doc/images/chamfer_dist_angle.png [new file with mode: 0644]
src/FeaturesPlugin/doc/images/chamfer_distances.png [new file with mode: 0644]
src/FeaturesPlugin/doc/images/chamfer_res_dist_angle.png [new file with mode: 0644]
src/FeaturesPlugin/doc/images/chamfer_res_distances.png [new file with mode: 0644]
src/FeaturesPlugin/extrusion_widget.xml
src/FeaturesPlugin/extrusioncut_widget.xml
src/FeaturesPlugin/extrusionfuse_widget.xml
src/FeaturesPlugin/fillet_widget.xml
src/FeaturesPlugin/icons/chamfer.png [new file with mode: 0644]
src/FeaturesPlugin/icons/chamfer_dist_angle.png [new file with mode: 0644]
src/FeaturesPlugin/icons/chamfer_distances.png [new file with mode: 0644]
src/FeaturesPlugin/intersection_widget.xml
src/FeaturesPlugin/multirotation_widget.xml
src/FeaturesPlugin/multitranslation_widget.xml
src/FeaturesPlugin/partition_widget.xml
src/FeaturesPlugin/pipe_widget.xml
src/FeaturesPlugin/placement_widget.xml
src/FeaturesPlugin/plugin-Features.xml
src/FeaturesPlugin/remove_subshapes_widget.xml
src/FeaturesPlugin/revolution_widget.xml
src/FeaturesPlugin/revolutioncut_widget.xml
src/FeaturesPlugin/revolutionfuse_widget.xml
src/FeaturesPlugin/rotation_widget.xml
src/FeaturesPlugin/scale_widget.xml
src/FeaturesPlugin/symmetry_widget.xml
src/FeaturesPlugin/translation_widget.xml
src/FeaturesPlugin/union_widget.xml
src/FiltersAPI/FiltersAPI_Feature.cpp
src/FiltersPlugin/CMakeLists.txt
src/FiltersPlugin/FiltersPlugin_RelativeToSolid.cpp
src/FiltersPlugin/Test/TestFilter_OnGeometry_Exclude_Face4.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_OnGeometry_Face4.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_RelativeToSolid_Exclude_In.py
src/FiltersPlugin/Test/TestFilter_RelativeToSolid_Exclude_InAndOn.py
src/FiltersPlugin/Test/TestFilter_RelativeToSolid_Exclude_NotOn.py
src/FiltersPlugin/Test/TestFilter_RelativeToSolid_Exclude_On.py
src/FiltersPlugin/Test/TestFilter_RelativeToSolid_Exclude_Out.py
src/FiltersPlugin/Test/TestFilter_RelativeToSolid_Exclude_OutAndOn.py
src/FiltersPlugin/Test/TestFilter_RelativeToSolid_In.py
src/FiltersPlugin/Test/TestFilter_RelativeToSolid_InAndOn.py
src/FiltersPlugin/Test/TestFilter_RelativeToSolid_NotOn.py
src/FiltersPlugin/Test/TestFilter_RelativeToSolid_On.py
src/FiltersPlugin/Test/TestFilter_RelativeToSolid_Out.py
src/FiltersPlugin/Test/TestFilter_RelativeToSolid_OutAndOn.py
src/FiltersPlugin/Test/TestFilters.py
src/FiltersPlugin/Test/TestFilters_Supported.py
src/FiltersPlugin/doc/FiltersPlugin.rst [new file with mode: 0644]
src/FiltersPlugin/doc/images/add.png [new file with mode: 0644]
src/FiltersPlugin/doc/images/delete.png [new file with mode: 0644]
src/FiltersPlugin/doc/images/reverce.png [new file with mode: 0644]
src/FiltersPlugin/doc/images/selection_by_filters.png [new file with mode: 0644]
src/FiltersPlugin/doc/images/selection_by_filters_added.png [new file with mode: 0644]
src/FiltersPlugin/filter-BelongsTo.xml
src/FiltersPlugin/filter-OnGeometry.xml
src/FiltersPlugin/filter-OnLine.xml
src/FiltersPlugin/filter-OnPlane.xml
src/GeomAPI/GeomAPI_Curve.cpp
src/GeomAPI/GeomAPI_Curve.h
src/GeomAlgoAPI/CMakeLists.txt
src/GeomAlgoAPI/GeomAlgoAPI_Chamfer.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Chamfer.h [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp
src/GeomAlgoAPI/GeomAlgoAPI_Sewing.cpp
src/GeomAlgoAPI/GeomAlgoAPI_Tools.cpp
src/GeomValidators/GeomValidators_MinObjectsSelected.cpp
src/InitializationPlugin/InitializationPlugin_PyInterp.cpp
src/Model/Model_AttributeSelection.cpp
src/Model/Model_Document.cpp
src/Model/Model_Objects.cpp
src/Model/Model_ResultConstruction.cpp
src/Model/Model_ResultConstruction.h
src/Model/Model_ResultGroup.cpp
src/Model/Model_ResultGroup.h
src/ModelAPI/ModelAPI_ResultConstruction.h
src/ModelAPI/ModelAPI_ResultGroup.h
src/ModelAPI/Test/TestFolder_Sketch.py
src/ModelHighAPI/ModelHighAPI.i
src/ModelHighAPI/ModelHighAPI_Dumper.cpp
src/ModelHighAPI/ModelHighAPI_Dumper.h
src/ModuleBase/CMakeLists.txt
src/ModuleBase/ModuleBase_IModule.cpp
src/ModuleBase/ModuleBase_IModule.h
src/ModuleBase/ModuleBase_SelectionFilterType.h [new file with mode: 0644]
src/ModuleBase/ModuleBase_Tools.cpp
src/ModuleBase/ModuleBase_Tools.h
src/ModuleBase/ModuleBase_ViewerFilters.h
src/ModuleBase/ModuleBase_WidgetFileSelector.cpp
src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp
src/ModuleBase/ModuleBase_WidgetMultiSelector.h
src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp
src/ModuleBase/ModuleBase_WidgetSelector.cpp
src/ParametersPlugin/ParametersPlugin_WidgetParamsMgr.cpp
src/PartSet/PartSet_Filters.cpp
src/PartSet/PartSet_Filters.h
src/PartSet/PartSet_IconFactory.cpp
src/PartSet/PartSet_Module.cpp
src/PartSet/PartSet_Module.h
src/PartSet/PartSet_SketcherMgr.cpp
src/PartSet/PartSet_SketcherMgr.h
src/PartSet/PartSet_SketcherReentrantMgr.cpp
src/PartSet/PartSet_WidgetSketchLabel.cpp
src/PythonAPI/model/collection/__init__.py
src/PythonAPI/model/features/__init__.py
src/PythonAddons/macros/compoundVertices/feature.py
src/PythonAddons/macros/compoundVertices/widget.xml
src/PythonAddons/macros/importParameters/feature.py
src/PythonAddons/macros/importParameters/widget.xml
src/SHAPERGUI/SHAPERGUI.cpp
src/SketchAPI/CMakeLists.txt
src/SketchAPI/SketchAPI_Sketch.cpp
src/SketchAPI/SketchAPI_Sketch.h
src/SketchPlugin/plugin-Sketch.xml
src/SketcherPrs/SketcherPrs_Coincident.cpp
src/SketcherPrs/SketcherPrs_HVDirection.cpp
src/SketcherPrs/SketcherPrs_SymbolPrs.cpp
src/SketcherPrs/SketcherPrs_Tools.cpp
src/SketcherPrs/SketcherPrs_Tools.h
src/XGUI/CMakeLists.txt
src/XGUI/XGUI_ContextMenuMgr.cpp
src/XGUI/XGUI_DataModel.cpp
src/XGUI/XGUI_Displayer.cpp
src/XGUI/XGUI_ErrorDialog.cpp
src/XGUI/XGUI_FacesPanel.cpp
src/XGUI/XGUI_PropertyPanel.cpp
src/XGUI/XGUI_SelectionFilterType.h [deleted file]
src/XGUI/XGUI_ViewerProxy.cpp
src/XGUI/XGUI_Workshop.cpp
src/XGUI/XGUI_msg_fr.ts

diff --git a/env.sh b/env.sh
index 900a12be8621e3b64525b9b622097b6bee33c81b..72508628da329541210088ee4871270f00d651c1 100644 (file)
--- a/env.sh
+++ b/env.sh
@@ -1,6 +1,6 @@
 #!/bin/bash -x
 
-export SALOME_DIR=/dn46/SALOME/series9x/current-2019-07-29
+export SALOME_DIR=/dn46/SALOME/series9x/current-2019-08-19
 
 # Path to sources
 export SOURCES_DIR=$(pwd)
index 5984821f952b9620316cd4baba85fe06e5b857dc..0a3f626fca5fbd06e9697095d1974ddc8ea4231f 100644 (file)
@@ -2,7 +2,7 @@
   <multi_selector id="base_objects"
                   label="Objects:"
                   tooltip="Select any kind of objects."
-                  type_choice="vertices edges wires faces shells solids compsolids compounds"
+                  shape_types="vertices edges wires faces shells solids compsolids compounds"
                   concealment="true">
   </multi_selector>
 </source>
index ccad859480a22f36d7ffade180236377b90dd3c6..28fab58baafbf21c9aec41a69aed33f1ed26e5cf 100644 (file)
@@ -2,7 +2,7 @@
   <multi_selector id="base_objects"
                   label="Solids and CompSolids:"
                   tooltip="Select solids or compsolids."
-                  type_choice="faces shells solids compsolids"
+                  shape_types="faces shells solids compsolids"
                   concealment="true">
     <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="face,shell,solid,compsolid"/>
   </multi_selector>
index be088557818ee0d083ec375f0d348ab196f459a9..f7ff1144731a23fb064600ec8dc04b8d9e7a32b3 100644 (file)
@@ -4,7 +4,7 @@
       <multi_selector id="base_objects"
                       label="Edges:"
                       tooltip="Select edges on sketch or edges objects."
-                      type_choice="edges"
+                      shape_types="edges"
                       concealment="true">
         <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="edge"/>
       </multi_selector>
index a23c7cf073d40c56f26904bfde30aa9a89eeba98..e61ce59d10aec18995e763c482cba998b6eb7049 100644 (file)
@@ -2,7 +2,7 @@
   <multi_selector id="base_objects"
                   label="Objects:"
                   tooltip="Select edges, wires or faces."
-                  type_choice="edges wires faces"
+                  shape_types="edges wires faces"
                   concealment="true">
     <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="edge,wire,face"/>
   </multi_selector>
index da22fc0d7e730bcf9a71c57db38d1a0722260b77..5cd076931638b9f73374d7263eabd28c30fe4960 100644 (file)
@@ -2,7 +2,7 @@
   <multi_selector id="base_objects"
                   label="Segments and wires:"
                   tooltip="Select edges or wires."
-                  type_choice="edges wires"
+                  shape_types="edges wires"
                   concealment="false">
     <validator id="PartSet_DifferentObjects"/>
     <validator id="BuildPlugin_ValidatorFillingSelection"/>
index 0922732438ef65d4a8d512541e0b3e125e29b744..5a0acee2fed3d086753912d7314983c60f264d3d 100644 (file)
@@ -2,7 +2,7 @@
   <multi_selector id="base_objects"
                   label="Points and vertices:"
                   tooltip="Select points or vertices objects."
-                  type_choice="vertices"
+                  shape_types="vertices"
                   concealment="true">
     <validator id="GeomValidators_DifferentShapes"/>
   </multi_selector>
index b46aa51b18ec308f8f0b1ec07208a4ad44ec5458..be1d599973a2ab050bfab323ea02a5b0d4fe3460 100644 (file)
@@ -1,11 +1,11 @@
 <plugin>
   <workbench id="Build" document="Part">
     <group id="Generate">
-      <feature id="Vertex" title="Vertex" tooltip ="Create a vertex from sketch vertex and vertex objects" icon="icons/Build/feature_vertex.png"
+      <feature id="Vertex" title="Vertex" tooltip ="Create vertices from sketch point or other vertex objects" icon="icons/Build/feature_vertex.png"
                helpfile="vertexFeature.html">
         <source path="vertex_widget.xml"/>
       </feature>
-      <feature id="Edge" title="Edge" tooltip ="Create an edge from sketch edges and edge objects" icon="icons/Build/feature_edge.png"
+      <feature id="Edge" title="Edge" tooltip ="Create edges from sketch edges or other edge objects" icon="icons/Build/feature_edge.png"
                helpfile="edgeFeature.html">
         <source path="edge_widget.xml"/>
       </feature>
@@ -33,7 +33,7 @@
                helpfile="solidFeature.html">
         <source path="solid_widget.xml"/>
       </feature>
-      <feature id="CompSolid" title="CompSolid" tooltip ="Create a compsolid from solids or another compsolids" icon="icons/Build/feature_compsolid.png"
+      <feature id="CompSolid" title="CompSolid" tooltip ="Create a compsolid from solids or other compsolids" icon="icons/Build/feature_compsolid.png"
                helpfile="compsolidFeature.html">
         <source path="compsolid_widget.xml"/>
       </feature>
index 3760b4ede9ef4553f3ef708d6986f08dd3d807e8..2c283b8b1c309e415d3068b1610001d42f6b5698 100644 (file)
@@ -2,7 +2,7 @@
   <multi_selector id="base_objects"
                   label="Points and vertices:"
                   tooltip="Select points or vertices objects."
-                  type_choice="vertices"
+                  shape_types="vertices"
                   concealment="true">
     <validator id="GeomValidators_DifferentShapes"/>
   </multi_selector>
index 27b8e3971b7d716b5053cca6e5466bc721943d4e..50575ff1e55873270f40079f3eb92f6496f76404 100644 (file)
@@ -2,7 +2,7 @@
   <multi_selector id="base_objects"
                   label="Faces and shells:"
                   tooltip="Select faces or shells objects."
-                  type_choice="faces shells"
+                  shape_types="faces shells"
                   concealment="true">
     <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="face,shell"/>
   </multi_selector>
index 4eb1ce88f4a5baad96eb0b30a9746bc13e94caa5..8c9234f57a7a7228f3341475d00a02be8b9f69c3 100644 (file)
@@ -2,7 +2,7 @@
   <multi_selector id="base_objects"
                   label="Faces and shells:"
                   tooltip="Select faces or shells."
-                  type_choice="faces shells"
+                  shape_types="faces shells"
                   concealment="true">
     <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="face,shell"/>
   </multi_selector>
index 7d74c0c9adb10ab2e7dc112c8b179763f106e6ca..5f42c96a9b818639f5041bfeab89539038a32e73 100644 (file)
@@ -10,7 +10,7 @@
   <multi_selector id="subshapes"
                   label="Sub-Shapes:"
                   tooltip="Select shapes on sketch to add."
-                  type_choice="vertices edges"
+                  shape_types="vertices edges"
                   concealment="true"
                   clear_in_neutral_point="false">
     <validator id="BuildPlugin_ValidatorSubShapesSelection" parameters="Sketch"/>
index 446ed1a454937c22e96ce2c2fcad9f6fcad8ff92..77af0a18f5aeec634dc2270fd1abfd3fdace7e04 100644 (file)
@@ -2,7 +2,7 @@
   <multi_selector id="base_objects"
                   label="Vertices:"
                   tooltip="Select vertices on sketch or vertex objects."
-                  type_choice="vertices"
+                  shape_types="vertices"
                   concealment="true">
   </multi_selector>
 </source>
index 87f03df669d4cec1dff81c0e1ba1ef9fda2f40ad..96067ebe6d9917d26bfda0e59bbfe7d2ddea87bc 100644 (file)
@@ -2,7 +2,7 @@
   <multi_selector id="base_objects"
                   label="Segments and wires:"
                   tooltip="Select edges on sketch, edges or wires objects."
-                  type_choice="edges wires"
+                  shape_types="edges wires"
                   concealment="true">
     <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="edge,wire"/>
   </multi_selector>
index 0b2815bdd7250efc16593edcce438936a3efd033..f5c90abee6966ff63ada5cd6274526537390f50b 100644 (file)
@@ -22,11 +22,17 @@ INCLUDE(Common)
 SET(PROJECT_HEADERS
   CollectionAPI.h
   CollectionAPI_Group.h
+  CollectionAPI_GroupAddition.h
+  CollectionAPI_GroupIntersection.h
+  CollectionAPI_GroupSubstraction.h
   CollectionAPI_Field.h
 )
 
 SET(PROJECT_SOURCES
   CollectionAPI_Group.cpp
+  CollectionAPI_GroupAddition.cpp
+  CollectionAPI_GroupIntersection.cpp
+  CollectionAPI_GroupSubstraction.cpp
   CollectionAPI_Field.cpp
 )
 
index c27d56cb22240e9bc29f2187c5b7deee85e2c28a..552a33d3d64f1089ba22a94b1763f353cfbcc815 100644 (file)
@@ -29,6 +29,9 @@
 
   #include "CollectionAPI.h"
   #include "CollectionAPI_Group.h"
+  #include "CollectionAPI_GroupAddition.h"
+  #include "CollectionAPI_GroupIntersection.h"
+  #include "CollectionAPI_GroupSubstraction.h"
   #include "CollectionAPI_Field.h"
 
 #endif // CollectionAPI_swig_H_
 
 // shared pointers
 %shared_ptr(CollectionAPI_Group)
+%shared_ptr(CollectionAPI_GroupAddition)
+%shared_ptr(CollectionAPI_GroupIntersection)
+%shared_ptr(CollectionAPI_GroupSubstraction)
 %shared_ptr(CollectionAPI_Field)
 
 // all supported interfaces
 %include "CollectionAPI_Group.h"
+%include "CollectionAPI_GroupAddition.h"
+%include "CollectionAPI_GroupIntersection.h"
+%include "CollectionAPI_GroupSubstraction.h"
 %include "CollectionAPI_Field.h"
diff --git a/src/CollectionAPI/CollectionAPI_GroupAddition.cpp b/src/CollectionAPI/CollectionAPI_GroupAddition.cpp
new file mode 100644 (file)
index 0000000..48e1f8e
--- /dev/null
@@ -0,0 +1,71 @@
+// 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 "CollectionAPI_GroupAddition.h"
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Tools.h>
+
+CollectionAPI_GroupAddition::CollectionAPI_GroupAddition(
+    const std::shared_ptr<ModelAPI_Feature>& theFeature)
+  : ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+CollectionAPI_GroupAddition::CollectionAPI_GroupAddition(
+    const std::shared_ptr<ModelAPI_Feature>& theFeature,
+    const std::list<ModelHighAPI_Selection>& theGroupList)
+  : ModelHighAPI_Interface(theFeature)
+{
+  if(initialize()) {
+    setGroupList(theGroupList);
+  }
+}
+
+CollectionAPI_GroupAddition::~CollectionAPI_GroupAddition()
+{
+}
+
+void CollectionAPI_GroupAddition::setGroupList(
+    const std::list<ModelHighAPI_Selection>& theGroupList)
+{
+  fillAttribute(theGroupList, mygroupList);
+  execute();
+}
+
+void CollectionAPI_GroupAddition::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  const std::string& aDocName = theDumper.name(aBase->document());
+
+  AttributeSelectionListPtr anAttrList =
+      aBase->selectionList(CollectionPlugin_GroupAddition::LIST_ID());
+
+  theDumper << aBase << " = model.addGroupAddition(" << aDocName << ", "
+            << anAttrList << ")" << std::endl;
+}
+
+GroupAdditionPtr addGroupAddition(const std::shared_ptr<ModelAPI_Document>& thePart,
+                                  const std::list<ModelHighAPI_Selection>& theGroupList)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+      thePart->addFeature(CollectionAPI_GroupAddition::ID());
+  return GroupAdditionPtr(new CollectionAPI_GroupAddition(aFeature, theGroupList));
+}
diff --git a/src/CollectionAPI/CollectionAPI_GroupAddition.h b/src/CollectionAPI/CollectionAPI_GroupAddition.h
new file mode 100644 (file)
index 0000000..102e84a
--- /dev/null
@@ -0,0 +1,74 @@
+// 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 CollectionAPI_GroupAddition_H_
+#define CollectionAPI_GroupAddition_H_
+
+#include "CollectionAPI.h"
+
+#include <CollectionPlugin_GroupAddition.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Dumper;
+class ModelHighAPI_Selection;
+
+/// \class CollectionAPI_GroupAddition
+/// \ingroup CPPHighAPI
+/// \brief Interface for Group Addition feature.
+class CollectionAPI_GroupAddition : public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  COLLECTIONAPI_EXPORT
+  explicit CollectionAPI_GroupAddition(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values.
+  COLLECTIONAPI_EXPORT
+  CollectionAPI_GroupAddition(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                              const std::list<ModelHighAPI_Selection>& theGroupList);
+
+  /// Destructor.
+  COLLECTIONAPI_EXPORT
+  virtual ~CollectionAPI_GroupAddition();
+
+  INTERFACE_1(CollectionPlugin_GroupAddition::ID(),
+              groupList, CollectionPlugin_GroupAddition::LIST_ID(),
+              ModelAPI_AttributeSelectionList, /** Group list*/)
+
+  /// Set main objects.
+  COLLECTIONAPI_EXPORT
+  void setGroupList(const std::list<ModelHighAPI_Selection>& theGroupList);
+
+  /// Dump wrapped feature
+  COLLECTIONAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+};
+
+/// Pointer on Group Addition object.
+typedef std::shared_ptr<CollectionAPI_GroupAddition> GroupAdditionPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create Group Addition feature.
+COLLECTIONAPI_EXPORT
+GroupAdditionPtr addGroupAddition(const std::shared_ptr<ModelAPI_Document>& thePart,
+                                  const std::list<ModelHighAPI_Selection>& theGroupsList);
+
+#endif // CollectionAPI_GroupAddition_H_
diff --git a/src/CollectionAPI/CollectionAPI_GroupIntersection.cpp b/src/CollectionAPI/CollectionAPI_GroupIntersection.cpp
new file mode 100644 (file)
index 0000000..7d4fad7
--- /dev/null
@@ -0,0 +1,71 @@
+// 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 "CollectionAPI_GroupIntersection.h"
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Tools.h>
+
+CollectionAPI_GroupIntersection::CollectionAPI_GroupIntersection(
+    const std::shared_ptr<ModelAPI_Feature>& theFeature)
+  : ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+CollectionAPI_GroupIntersection::CollectionAPI_GroupIntersection(
+    const std::shared_ptr<ModelAPI_Feature>& theFeature,
+    const std::list<ModelHighAPI_Selection>& theGroupList)
+  : ModelHighAPI_Interface(theFeature)
+{
+  if(initialize()) {
+    setGroupList(theGroupList);
+  }
+}
+
+CollectionAPI_GroupIntersection::~CollectionAPI_GroupIntersection()
+{
+}
+
+void CollectionAPI_GroupIntersection::setGroupList(
+    const std::list<ModelHighAPI_Selection>& theGroupList)
+{
+  fillAttribute(theGroupList, mygroupList);
+  execute();
+}
+
+void CollectionAPI_GroupIntersection::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  const std::string& aDocName = theDumper.name(aBase->document());
+
+  AttributeSelectionListPtr anAttrList =
+      aBase->selectionList(CollectionPlugin_GroupIntersection::LIST_ID());
+
+  theDumper << aBase << " = model.addGroupIntersection(" << aDocName << ", "
+            << anAttrList << ")" << std::endl;
+}
+
+GroupIntersectionPtr addGroupIntersection(const std::shared_ptr<ModelAPI_Document>& thePart,
+                                          const std::list<ModelHighAPI_Selection>& theGroupList)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+      thePart->addFeature(CollectionAPI_GroupIntersection::ID());
+  return GroupIntersectionPtr(new CollectionAPI_GroupIntersection(aFeature, theGroupList));
+}
diff --git a/src/CollectionAPI/CollectionAPI_GroupIntersection.h b/src/CollectionAPI/CollectionAPI_GroupIntersection.h
new file mode 100644 (file)
index 0000000..007853c
--- /dev/null
@@ -0,0 +1,74 @@
+// 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 CollectionAPI_GroupIntersection_H_
+#define CollectionAPI_GroupIntersection_H_
+
+#include "CollectionAPI.h"
+
+#include <CollectionPlugin_GroupIntersection.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Dumper;
+class ModelHighAPI_Selection;
+
+/// \class CollectionAPI_GroupIntersection
+/// \ingroup CPPHighAPI
+/// \brief Interface for Group Intersection feature.
+class CollectionAPI_GroupIntersection : public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  COLLECTIONAPI_EXPORT
+  explicit CollectionAPI_GroupIntersection(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values.
+  COLLECTIONAPI_EXPORT
+  CollectionAPI_GroupIntersection(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                  const std::list<ModelHighAPI_Selection>& theGroupList);
+
+  /// Destructor.
+  COLLECTIONAPI_EXPORT
+  virtual ~CollectionAPI_GroupIntersection();
+
+  INTERFACE_1(CollectionPlugin_GroupIntersection::ID(),
+              groupList, CollectionPlugin_GroupIntersection::LIST_ID(),
+              ModelAPI_AttributeSelectionList, /** Group list*/)
+
+  /// Set main objects.
+  COLLECTIONAPI_EXPORT
+  void setGroupList(const std::list<ModelHighAPI_Selection>& theGroupList);
+
+  /// Dump wrapped feature
+  COLLECTIONAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+};
+
+/// Pointer on Group Addition object.
+typedef std::shared_ptr<CollectionAPI_GroupIntersection> GroupIntersectionPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create Group Intersection feature.
+COLLECTIONAPI_EXPORT
+GroupIntersectionPtr addGroupIntersection(const std::shared_ptr<ModelAPI_Document>& thePart,
+                                          const std::list<ModelHighAPI_Selection>& theGroupsList);
+
+#endif // CollectionAPI_GroupIntersection_H_
diff --git a/src/CollectionAPI/CollectionAPI_GroupSubstraction.cpp b/src/CollectionAPI/CollectionAPI_GroupSubstraction.cpp
new file mode 100644 (file)
index 0000000..bdd6494
--- /dev/null
@@ -0,0 +1,84 @@
+// 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 "CollectionAPI_GroupSubstraction.h"
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Tools.h>
+
+CollectionAPI_GroupSubstraction::CollectionAPI_GroupSubstraction(
+    const std::shared_ptr<ModelAPI_Feature>& theFeature)
+  : ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+CollectionAPI_GroupSubstraction::CollectionAPI_GroupSubstraction(
+    const std::shared_ptr<ModelAPI_Feature>& theFeature,
+    const std::list<ModelHighAPI_Selection>& theObjectsList,
+    const std::list<ModelHighAPI_Selection>& theToolsList)
+  : ModelHighAPI_Interface(theFeature)
+{
+  if(initialize()) {
+    setObjectsList(theObjectsList);
+    setToolsList(theToolsList);
+  }
+}
+
+CollectionAPI_GroupSubstraction::~CollectionAPI_GroupSubstraction()
+{
+}
+
+void CollectionAPI_GroupSubstraction::setObjectsList(
+    const std::list<ModelHighAPI_Selection>& theGroupList)
+{
+  fillAttribute(theGroupList, myobjectsList);
+  execute();
+}
+
+void CollectionAPI_GroupSubstraction::setToolsList(
+    const std::list<ModelHighAPI_Selection>& theGroupList)
+{
+  fillAttribute(theGroupList, mytoolsList);
+  execute();
+}
+
+void CollectionAPI_GroupSubstraction::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  const std::string& aDocName = theDumper.name(aBase->document());
+
+  AttributeSelectionListPtr anObjectsList =
+      aBase->selectionList(CollectionPlugin_GroupSubstraction::LIST_ID());
+  AttributeSelectionListPtr aToolsList =
+      aBase->selectionList(CollectionPlugin_GroupSubstraction::TOOLS_ID());
+
+  theDumper << aBase << " = model.addGroupSubstraction(" << aDocName << ", "
+            << anObjectsList << ", " << aToolsList << ")" << std::endl;
+}
+
+GroupSubstractionPtr addGroupSubstraction(const std::shared_ptr<ModelAPI_Document>& thePart,
+                                        const std::list<ModelHighAPI_Selection>& theObjectsList,
+                                        const std::list<ModelHighAPI_Selection>& theToolsList)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+      thePart->addFeature(CollectionAPI_GroupSubstraction::ID());
+  return GroupSubstractionPtr(new CollectionAPI_GroupSubstraction(
+      aFeature, theObjectsList, theToolsList));
+}
diff --git a/src/CollectionAPI/CollectionAPI_GroupSubstraction.h b/src/CollectionAPI/CollectionAPI_GroupSubstraction.h
new file mode 100644 (file)
index 0000000..0e11992
--- /dev/null
@@ -0,0 +1,82 @@
+// 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 CollectionAPI_GroupSubstraction_H_
+#define CollectionAPI_GroupSubstraction_H_
+
+#include "CollectionAPI.h"
+
+#include <CollectionPlugin_GroupSubstraction.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Dumper;
+class ModelHighAPI_Selection;
+
+/// \class CollectionAPI_GroupSubstraction
+/// \ingroup CPPHighAPI
+/// \brief Interface for Group Intersection feature.
+class CollectionAPI_GroupSubstraction : public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  COLLECTIONAPI_EXPORT
+  explicit CollectionAPI_GroupSubstraction(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values.
+  COLLECTIONAPI_EXPORT
+  CollectionAPI_GroupSubstraction(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                  const std::list<ModelHighAPI_Selection>& theObjectsList,
+                                  const std::list<ModelHighAPI_Selection>& theToolsList);
+
+  /// Destructor.
+  COLLECTIONAPI_EXPORT
+  virtual ~CollectionAPI_GroupSubstraction();
+
+  INTERFACE_2(CollectionPlugin_GroupSubstraction::ID(),
+              objectsList, CollectionPlugin_GroupSubstraction::LIST_ID(),
+              ModelAPI_AttributeSelectionList, /** Objects list*/,
+              toolsList, CollectionPlugin_GroupSubstraction::TOOLS_ID(),
+              ModelAPI_AttributeSelectionList, /** Tools list*/)
+
+  /// Set main objects.
+  COLLECTIONAPI_EXPORT
+  void setObjectsList(const std::list<ModelHighAPI_Selection>& theGroupList);
+
+  /// Set tools.
+  COLLECTIONAPI_EXPORT
+  void setToolsList(const std::list<ModelHighAPI_Selection>& theGroupList);
+
+  /// Dump wrapped feature
+  COLLECTIONAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+};
+
+/// Pointer on Group Addition object.
+typedef std::shared_ptr<CollectionAPI_GroupSubstraction> GroupSubstractionPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create Group Substraction feature.
+COLLECTIONAPI_EXPORT
+GroupSubstractionPtr addGroupSubstraction(const std::shared_ptr<ModelAPI_Document>& thePart,
+                                          const std::list<ModelHighAPI_Selection>& theObjectsList,
+                                          const std::list<ModelHighAPI_Selection>& theToolsList);
+
+#endif // CollectionAPI_GroupSubstraction_H_
index 2e2ff961d3687bae504a1d0492e4bffebcc75bec..251b91ffea8ef1c42fcb567da8d9a4604bab0b7f 100644 (file)
@@ -31,6 +31,10 @@ SET(PROJECT_HEADERS
     CollectionPlugin.h
     CollectionPlugin_Plugin.h
     CollectionPlugin_Group.h
+    CollectionPlugin_GroupAddition.h
+    CollectionPlugin_GroupIntersection.h
+    CollectionPlugin_GroupOperation.h
+    CollectionPlugin_GroupSubstraction.h
     CollectionPlugin_Field.h
     CollectionPlugin_WidgetCreator.h
     CollectionPlugin_WidgetField.h
@@ -44,6 +48,10 @@ SET(PROJECT_MOC_HEADERS
 SET(PROJECT_SOURCES
     CollectionPlugin_Plugin.cpp
     CollectionPlugin_Group.cpp
+    CollectionPlugin_GroupAddition.cpp
+    CollectionPlugin_GroupIntersection.cpp
+    CollectionPlugin_GroupOperation.cpp
+    CollectionPlugin_GroupSubstraction.cpp
     CollectionPlugin_Field.cpp
     CollectionPlugin_WidgetCreator.cpp
     CollectionPlugin_WidgetField.cpp
@@ -53,6 +61,9 @@ SET(PROJECT_SOURCES
 SET(XML_RESOURCES
   plugin-Collection.xml
   group_widget.xml
+  group_addition_widget.xml
+  group_intersection_widget.xml
+  group_substraction_widget.xml
 )
 
 SET(TEXT_RESOURCES
@@ -128,4 +139,12 @@ ADD_UNIT_TESTS(
                TestGroupMove19.py
                TestGroupMove20.py
                TestGroupShareTopology.py
+               TestGroupAddition.py
+               TestGroupAddition_Error.py
+               TestGroupIntersection.py
+               TestGroupIntersection_Error.py
+               TestGroupSubstraction.py
+               TestGroupSubstraction_Error1.py
+               TestGroupSubstraction_Error2.py
+               Test2977.py
 )
diff --git a/src/CollectionPlugin/CollectionPlugin_GroupAddition.cpp b/src/CollectionPlugin/CollectionPlugin_GroupAddition.cpp
new file mode 100644 (file)
index 0000000..042633c
--- /dev/null
@@ -0,0 +1,90 @@
+// 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 "CollectionPlugin_GroupAddition.h"
+
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_ResultGroup.h>
+
+#include <GeomAPI_ShapeIterator.h>
+#include <GeomAlgoAPI_CompoundBuilder.h>
+
+CollectionPlugin_GroupAddition::CollectionPlugin_GroupAddition()
+{
+}
+
+void CollectionPlugin_GroupAddition::initAttributes()
+{
+  data()->addAttribute(CollectionPlugin_GroupAddition::LIST_ID(),
+                       ModelAPI_AttributeSelectionList::typeId());
+}
+
+static void explodeCompound(const GeomShapePtr& theCompound, ListOfShape& theSubs)
+{
+  if (theCompound->isCompound()) {
+    GeomAPI_ShapeIterator anIt(theCompound);
+    for (; anIt.more(); anIt.next())
+      explodeCompound(anIt.current(), theSubs);
+  }
+  else
+    theSubs.push_back(theCompound);
+}
+
+static void keepUniqueShapes(ListOfShape& theShapes)
+{
+  ListOfShape::iterator anIt = theShapes.begin();
+  while (anIt != theShapes.end()) {
+    GeomShapePtr aCurrent = *anIt;
+    ListOfShape::iterator anIt2 = theShapes.begin();
+    for (; anIt2 != anIt; ++anIt2)
+      if (aCurrent->isEqual(*anIt2))
+        break;
+    if (anIt2 != anIt) {
+      // the same shape is found
+      ListOfShape::iterator aRemoveIt = anIt++;
+      theShapes.erase(aRemoveIt);
+    }
+    else
+      ++anIt;
+  }
+}
+
+void CollectionPlugin_GroupAddition::execute()
+{
+  ResultGroupPtr aGroup = document()->createGroup(data());
+  // clean the result of the operation
+  aGroup->store(GeomShapePtr());
+
+  // collect all unique sub-shapes
+  GeomShapePtr aCompound = aGroup->shape();
+  ListOfShape aSubs;
+  explodeCompound(aCompound, aSubs);
+  keepUniqueShapes(aSubs);
+  aCompound = aSubs.empty() ? GeomShapePtr() : GeomAlgoAPI_CompoundBuilder::compound(aSubs);
+  aGroup->store(aCompound);
+
+  // update the type of selection
+  updateGroupType(LIST_ID());
+
+  setResult(aGroup);
+}
diff --git a/src/CollectionPlugin/CollectionPlugin_GroupAddition.h b/src/CollectionPlugin/CollectionPlugin_GroupAddition.h
new file mode 100644 (file)
index 0000000..850c7d7
--- /dev/null
@@ -0,0 +1,64 @@
+// 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 COLLECTIONPLUGIN_GROUPADDITION_H_
+#define COLLECTIONPLUGIN_GROUPADDITION_H_
+
+#include "CollectionPlugin.h"
+#include "CollectionPlugin_GroupOperation.h"
+
+/**\class CollectionPlugin_GroupAddition
+ * \ingroup Plugins
+ * \brief Merge several groups of same shape type into single group.
+ */
+class CollectionPlugin_GroupAddition : public CollectionPlugin_GroupOperation
+{
+public:
+  /// Extrusion kind
+  inline static const std::string& ID()
+  {
+    static const std::string MY_GROUP_ID("GroupAddition");
+    return MY_GROUP_ID;
+  }
+  /// attribute name of selected entities list
+  inline static const std::string& LIST_ID()
+  {
+    static const std::string MY_GROUP_LIST_ID("group_list");
+    return MY_GROUP_LIST_ID;
+  }
+
+  /// Returns the kind of a feature
+  COLLECTIONPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = CollectionPlugin_GroupAddition::ID();
+    return MY_KIND;
+  }
+
+  /// Creates a new group result if needed
+  COLLECTIONPLUGIN_EXPORT virtual void execute();
+
+  /// Request for initialization of data model of the feature: adding all attributes
+  COLLECTIONPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Use plugin manager for features creation
+  CollectionPlugin_GroupAddition();
+
+};
+
+#endif
diff --git a/src/CollectionPlugin/CollectionPlugin_GroupIntersection.cpp b/src/CollectionPlugin/CollectionPlugin_GroupIntersection.cpp
new file mode 100644 (file)
index 0000000..55f5200
--- /dev/null
@@ -0,0 +1,106 @@
+// 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 "CollectionPlugin_GroupIntersection.h"
+
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_ResultGroup.h>
+
+#include <GeomAPI_ShapeIterator.h>
+#include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+
+typedef std::set<GeomShapePtr, GeomAPI_Shape::ComparatorWithOri> SetOfShape;
+
+CollectionPlugin_GroupIntersection::CollectionPlugin_GroupIntersection()
+{
+}
+
+void CollectionPlugin_GroupIntersection::initAttributes()
+{
+  data()->addAttribute(CollectionPlugin_GroupIntersection::LIST_ID(),
+                       ModelAPI_AttributeSelectionList::typeId());
+}
+
+static void explodeCompound(const GeomShapePtr& theCompound, SetOfShape& theSet)
+{
+  for (GeomAPI_ShapeIterator anIt(theCompound); anIt.more(); anIt.next())
+    theSet.insert(anIt.current());
+}
+
+static void keepCommonShapes(const GeomShapePtr& theCompound, ListOfShape& theShapes)
+{
+  if (theShapes.empty()) {
+    for (GeomAPI_ShapeIterator anIt(theCompound); anIt.more(); anIt.next())
+      theShapes.push_back(anIt.current());
+  }
+  else {
+    SetOfShape aSubs;
+    explodeCompound(theCompound, aSubs);
+
+    ListOfShape::iterator anIt = theShapes.begin();
+    while (anIt != theShapes.end()) {
+      if (aSubs.find(*anIt) == aSubs.end()) {
+        // the shape is not found
+        ListOfShape::iterator aRemoveIt = anIt++;
+        theShapes.erase(aRemoveIt);
+      }
+      else
+        ++anIt;
+    }
+  }
+}
+
+void CollectionPlugin_GroupIntersection::execute()
+{
+  ResultGroupPtr aGroup = document()->createGroup(data());
+  // clean the result of the operation
+  aGroup->store(GeomShapePtr());
+
+  // shapes containing in each group
+  ListOfShape aCommon;
+
+  // collect shapes containing in all groups
+  AttributeSelectionListPtr aSelectedGroups = selectionList(LIST_ID());
+  for (int anIndex = 0; anIndex < aSelectedGroups->size(); ++anIndex) {
+    AttributeSelectionPtr aCurSelection = aSelectedGroups->value(anIndex);
+    ResultGroupPtr aCurGroup =
+        std::dynamic_pointer_cast<ModelAPI_ResultGroup>(aCurSelection->context());
+    keepCommonShapes(aCurGroup->shape(), aCommon);
+    if (aCommon.empty())
+      break;
+  }
+
+  if (aCommon.empty()) {
+    setError("Error: Empty result.");
+    removeResults(0);
+  }
+  else {
+    // update the type of selection
+    updateGroupType(LIST_ID());
+
+    GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aCommon);
+    aGroup->store(aCompound);
+    setResult(aGroup);
+  }
+}
diff --git a/src/CollectionPlugin/CollectionPlugin_GroupIntersection.h b/src/CollectionPlugin/CollectionPlugin_GroupIntersection.h
new file mode 100644 (file)
index 0000000..72b0984
--- /dev/null
@@ -0,0 +1,64 @@
+// 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 COLLECTIONPLUGIN_GROUPINTERSECTION_H_
+#define COLLECTIONPLUGIN_GROUPINTERSECTION_H_
+
+#include "CollectionPlugin.h"
+#include "CollectionPlugin_GroupOperation.h"
+
+/**\class CollectionPlugin_GroupIntersection
+ * \ingroup Plugins
+ * \brief Merge several groups of same shape type into single group.
+ */
+class CollectionPlugin_GroupIntersection : public CollectionPlugin_GroupOperation
+{
+public:
+  /// Extrusion kind
+  inline static const std::string& ID()
+  {
+    static const std::string MY_GROUP_ID("GroupIntersection");
+    return MY_GROUP_ID;
+  }
+  /// attribute name of selected entities list
+  inline static const std::string& LIST_ID()
+  {
+    static const std::string MY_GROUP_LIST_ID("group_list");
+    return MY_GROUP_LIST_ID;
+  }
+
+  /// Returns the kind of a feature
+  COLLECTIONPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = CollectionPlugin_GroupIntersection::ID();
+    return MY_KIND;
+  }
+
+  /// Creates a new group result if needed
+  COLLECTIONPLUGIN_EXPORT virtual void execute();
+
+  /// Request for initialization of data model of the feature: adding all attributes
+  COLLECTIONPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Use plugin manager for features creation
+  CollectionPlugin_GroupIntersection();
+
+};
+
+#endif
diff --git a/src/CollectionPlugin/CollectionPlugin_GroupOperation.cpp b/src/CollectionPlugin/CollectionPlugin_GroupOperation.cpp
new file mode 100644 (file)
index 0000000..d8965f1
--- /dev/null
@@ -0,0 +1,36 @@
+// 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 "CollectionPlugin_GroupOperation.h"
+
+#include <ModelAPI_AttributeSelectionList.h>
+
+void CollectionPlugin_GroupOperation::updateGroupType(const std::string& theAttributeName)
+{
+  AttributeSelectionListPtr aSelected = selectionList(theAttributeName);
+  if (aSelected->size()) {
+    FeaturePtr aFirstGroup = ModelAPI_Feature::feature(aSelected->value(0)->context());
+    if (aFirstGroup) {
+      AttributeSelectionListPtr aFirstGroupShapes =
+        aFirstGroup->selectionList(CollectionPlugin_Group::LIST_ID());
+      if (aFirstGroupShapes)
+        aSelected->setSelectionType(aFirstGroupShapes->selectionType());
+    }
+  }
+}
diff --git a/src/CollectionPlugin/CollectionPlugin_GroupOperation.h b/src/CollectionPlugin/CollectionPlugin_GroupOperation.h
new file mode 100644 (file)
index 0000000..fb47e99
--- /dev/null
@@ -0,0 +1,41 @@
+// 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 COLLECTIONPLUGIN_GROUPOPERATION_H_
+#define COLLECTIONPLUGIN_GROUPOPERATION_H_
+
+#include "CollectionPlugin.h"
+#include "CollectionPlugin_Group.h"
+
+/**\class CollectionPlugin_GroupOperation
+ * \ingroup Plugins
+ * \brief Base class for operations on groups.
+ */
+class CollectionPlugin_GroupOperation : public CollectionPlugin_Group
+{
+public:
+  /// Result of groups is created on the fly and don't stored to the document
+  COLLECTIONPLUGIN_EXPORT virtual bool isPersistentResult() {return true;}
+
+protected:
+  /// Updates the type of selection list based on types of selected groups
+  void updateGroupType(const std::string& theAttributeName);
+};
+
+#endif
diff --git a/src/CollectionPlugin/CollectionPlugin_GroupSubstraction.cpp b/src/CollectionPlugin/CollectionPlugin_GroupSubstraction.cpp
new file mode 100644 (file)
index 0000000..9d39711
--- /dev/null
@@ -0,0 +1,111 @@
+// 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 "CollectionPlugin_GroupSubstraction.h"
+
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_ResultGroup.h>
+
+#include <GeomAPI_ShapeIterator.h>
+#include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+
+typedef std::set<GeomShapePtr, GeomAPI_Shape::ComparatorWithOri> SetOfShape;
+
+CollectionPlugin_GroupSubstraction::CollectionPlugin_GroupSubstraction()
+{
+}
+
+void CollectionPlugin_GroupSubstraction::initAttributes()
+{
+  data()->addAttribute(CollectionPlugin_GroupSubstraction::LIST_ID(),
+                       ModelAPI_AttributeSelectionList::typeId());
+  data()->addAttribute(CollectionPlugin_GroupSubstraction::TOOLS_ID(),
+                       ModelAPI_AttributeSelectionList::typeId());
+}
+
+static void explodeCompound(const GeomShapePtr& theCompound, SetOfShape& theSet)
+{
+  for (GeomAPI_ShapeIterator anIt(theCompound); anIt.more(); anIt.next())
+    theSet.insert(anIt.current());
+}
+
+static void subtractLists(const GeomShapePtr& theCompound,
+                          const SetOfShape& theExclude,
+                                ListOfShape& theResult)
+{
+  for (GeomAPI_ShapeIterator anIt(theCompound); anIt.more(); anIt.next()) {
+    GeomShapePtr aCurrent = anIt.current();
+    if (theExclude.find(aCurrent) != theExclude.end())
+      continue; // shape has to be excluded
+    // check the shape is already in the list
+    ListOfShape::iterator anIt2 = theResult.begin();
+    for (; anIt2 != theResult.end(); ++anIt2)
+      if (aCurrent->isEqual(*anIt2))
+        break;
+    if (anIt2 == theResult.end())
+      theResult.push_back(aCurrent);
+  }
+}
+
+void CollectionPlugin_GroupSubstraction::execute()
+{
+  ResultGroupPtr aGroup = document()->createGroup(data());
+  // clean the result of the operation
+  aGroup->store(GeomShapePtr());
+
+  // collect shapes to be excluded (tools)
+  SetOfShape aShapesToExclude;
+  AttributeSelectionListPtr aTools = selectionList(TOOLS_ID());
+  for (int anIndex = 0; anIndex < aTools->size(); ++anIndex) {
+    AttributeSelectionPtr aCurSelection = aTools->value(anIndex);
+    ResultGroupPtr aCurGroup =
+      std::dynamic_pointer_cast<ModelAPI_ResultGroup>(aCurSelection->context());
+    explodeCompound(aCurGroup->shape(), aShapesToExclude);
+  }
+
+  // keep only shapes that should not be excluded
+  ListOfShape aCut;
+  AttributeSelectionListPtr anObjects = selectionList(LIST_ID());
+  for (int anIndex = 0; anIndex < anObjects->size(); ++anIndex) {
+    AttributeSelectionPtr aCurSelection = anObjects->value(anIndex);
+    ResultGroupPtr aCurGroup =
+        std::dynamic_pointer_cast<ModelAPI_ResultGroup>(aCurSelection->context());
+    subtractLists(aCurGroup->shape(), aShapesToExclude, aCut);
+    if (aCut.empty())
+      break;
+  }
+
+  if (aCut.empty()) {
+    setError("Error: Empty result.");
+    removeResults(0);
+  }
+  else {
+    // update the type of selection
+    updateGroupType(LIST_ID());
+
+    GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aCut);
+    aGroup->store(aCompound);
+    setResult(aGroup);
+  }
+}
diff --git a/src/CollectionPlugin/CollectionPlugin_GroupSubstraction.h b/src/CollectionPlugin/CollectionPlugin_GroupSubstraction.h
new file mode 100644 (file)
index 0000000..0b4f8ea
--- /dev/null
@@ -0,0 +1,70 @@
+// 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 COLLECTIONPLUGIN_GROUPSUBSTRACTION_H_
+#define COLLECTIONPLUGIN_GROUPSUBSTRACTION_H_
+
+#include "CollectionPlugin.h"
+#include "CollectionPlugin_GroupOperation.h"
+
+/**\class CollectionPlugin_GroupSubstraction
+ * \ingroup Plugins
+ * \brief Remove all elements in "objects" groups which contain in "tools" groups.
+ */
+class CollectionPlugin_GroupSubstraction : public CollectionPlugin_GroupOperation
+{
+public:
+  /// Extrusion kind
+  inline static const std::string& ID()
+  {
+    static const std::string MY_GROUP_ID("GroupSubstraction");
+    return MY_GROUP_ID;
+  }
+  /// attribute name of selected objects list
+  inline static const std::string& LIST_ID()
+  {
+    static const std::string MY_GROUP_LIST_ID("group_list");
+    return MY_GROUP_LIST_ID;
+  }
+  /// attribute name of selected tools list
+  inline static const std::string& TOOLS_ID()
+  {
+    static const std::string MY_GROUP_LIST_ID("tools_list");
+    return MY_GROUP_LIST_ID;
+  }
+
+  /// Returns the kind of a feature
+  COLLECTIONPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = CollectionPlugin_GroupSubstraction::ID();
+    return MY_KIND;
+  }
+
+  /// Creates a new group result if needed
+  COLLECTIONPLUGIN_EXPORT virtual void execute();
+
+  /// Request for initialization of data model of the feature: adding all attributes
+  COLLECTIONPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Use plugin manager for features creation
+  CollectionPlugin_GroupSubstraction();
+
+};
+
+#endif
index 7b0fc28e1e4210a783f0c73411daa334484bb8d9..8a62c07a803e2626c71b4d4a655a5b1f7fd6834c 100644 (file)
@@ -20,6 +20,9 @@
 #include <CollectionPlugin_Plugin.h>
 
 #include <CollectionPlugin_Group.h>
+#include <CollectionPlugin_GroupAddition.h>
+#include <CollectionPlugin_GroupIntersection.h>
+#include <CollectionPlugin_GroupSubstraction.h>
 #include <CollectionPlugin_Field.h>
 #include <CollectionPlugin_Validators.h>
 #include <ModelAPI_Session.h>
@@ -45,6 +48,8 @@ CollectionPlugin_Plugin::CollectionPlugin_Plugin()
   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
   aFactory->registerValidator("CollectionPlugin_FieldValidator",
     new CollectionPlugin_FieldValidator);
+  aFactory->registerValidator("CollectionPlugin_OperationAttribute",
+    new CollectionPlugin_GroupOperationAttributeValidator);
 
   // register this plugin
   ModelAPI_Session::get()->registerPlugin(this);
@@ -56,6 +61,12 @@ FeaturePtr CollectionPlugin_Plugin::createFeature(std::string theFeatureID)
     return FeaturePtr(new CollectionPlugin_Group);
   } else if (theFeatureID == CollectionPlugin_Field::ID()) {
     return FeaturePtr(new CollectionPlugin_Field);
+  } else if (theFeatureID == CollectionPlugin_GroupAddition::ID()) {
+    return FeaturePtr(new CollectionPlugin_GroupAddition);
+  } else if (theFeatureID == CollectionPlugin_GroupIntersection::ID()) {
+    return FeaturePtr(new CollectionPlugin_GroupIntersection);
+  } else if (theFeatureID == CollectionPlugin_GroupSubstraction::ID()) {
+    return FeaturePtr(new CollectionPlugin_GroupSubstraction);
   }
 
   // feature of such kind is not found
index d644c13f64817c4bc9f0da5fa700e3ddaea72fe1..7620506cf3d0b57e97c7e45efb1bf55d3cf7af50 100644 (file)
 //
 
 #include "CollectionPlugin_Validators.h"
+#include "CollectionPlugin_Group.h"
 #include "CollectionPlugin_Field.h"
 #include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_ResultGroup.h>
 #include <Events_InfoMessage.h>
 
 
@@ -42,3 +44,59 @@ bool CollectionPlugin_FieldValidator::isValid(const FeaturePtr& theFeature,
   theError = "Selection list is not initialized";
   return false;
 }
+
+static bool isGroupTypeCorrect(const AttributeSelectionPtr& theSelection,
+                               std::string& theType,
+                               Events_InfoMessage& theError)
+{
+  // applicable the groups only
+  ResultPtr aGroupResult = theSelection->context();
+  if (!aGroupResult.get() || aGroupResult->groupName() != ModelAPI_ResultGroup::group()) {
+    theError = "Error: Groups can be selected only.";
+    return false;
+  }
+  // groups of same type can be selected only
+  FeaturePtr aGroupFeature = ModelAPI_Feature::feature(aGroupResult->data()->owner());
+  std::string aGroupType =
+      aGroupFeature->selectionList(CollectionPlugin_Group::LIST_ID())->selectionType();
+  if (theType.empty())
+    theType = aGroupType;
+  else if (theType != aGroupType) {
+    theError = "Error: Groups should have same type";
+    return false;
+  }
+  return true;
+}
+
+bool CollectionPlugin_GroupOperationAttributeValidator::isValid(
+    const AttributePtr& theAttribute,
+    const std::list<std::string>& theArguments,
+    Events_InfoMessage& theError) const
+{
+  AttributeSelectionListPtr aSelList =
+      std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+  if (!aSelList) {
+    theError = "Error: This validator can only work with selection list of attributes";
+    return false;
+  }
+
+  FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
+  // check selected items
+  std::string aType;
+  for (int anIndex = 0; anIndex < aSelList->size(); ++anIndex) {
+    AttributeSelectionPtr aCurSelection = aSelList->value(anIndex);
+    if (!isGroupTypeCorrect(aCurSelection, aType, theError))
+      return false;
+  }
+  // check types of all selection lists are the same
+  for (std::list<std::string>::const_iterator aParIt = theArguments.begin();
+       aParIt != theArguments.end() && !aType.empty(); ++aParIt) {
+    AttributeSelectionListPtr aCurList = anOwner->selectionList(*aParIt);
+    if (aCurList->size() == 0)
+      continue;
+    AttributeSelectionPtr aCurSelection = aCurList->value(0);
+    if (!isGroupTypeCorrect(aCurSelection, aType, theError))
+      return false;
+  }
+  return true;
+}
index 5932e2c4f7d163e8228d2a2407ab00261656bcd5..4f5db68d31cfcc7a14e6fde63f8108cc9d650941 100644 (file)
 #define CollectionPlugin_Validators_H
 
 #include "CollectionPlugin.h"
+#include <ModelAPI_AttributeValidator.h>
 #include <ModelAPI_FeatureValidator.h>
 
-/**\class SketchPlugin_SolverErrorValidator
-* \ingroup Validators
-* \brief Validator for the solver error.
-*
-* Simply checks that solver error attribute is empty. Returns the attribute value as an error.
-*/
+/**\class CollectionPlugin_FieldValidator
+ * \ingroup Validators
+ * \brief Validator for the field.
+ */
 class CollectionPlugin_FieldValidator : public ModelAPI_FeatureValidator
 {
 public:
@@ -41,4 +40,19 @@ public:
     Events_InfoMessage& theError) const;
 };
 
+/**\class CollectionPlugin_GroupOperationAttributeValidator
+ * \ingroup Validators
+ * \brief Validator for the parameters of operation on groups.
+ */
+class CollectionPlugin_GroupOperationAttributeValidator : public ModelAPI_AttributeValidator
+{
+  //! Returns true if attribute is ok.
+  //! \param[in] theAttribute the checked attribute.
+  //! \param[in] theArguments arguments of the attribute.
+  //! \param[out] theError error message.
+  virtual bool isValid(const AttributePtr& theAttribute,
+                       const std::list<std::string>& theArguments,
+                       Events_InfoMessage& theError) const;
+};
+
 #endif
\ No newline at end of file
index 52a54c022b656b3cf0bc8fd46d414673b00b3121..a2e291ed8a8f5d39e4a8386895e893fd5ffb3dc0 100644 (file)
@@ -975,6 +975,9 @@ void CollectionPlugin_WidgetField::onShapeTypeChanged(int theType)
   if (aTypeName == aSelList->selectionType())
     return;
   aSelList->setSelectionType(aTypeName);
+  // Updated event has to be sent here in case if type of shapes
+  // was changed from Part to any other in order to updater Apply button status
+  myFeature->data()->sendAttributeUpdated(aSelList.get());
 
   //Clear old selection
   clearData();
index 061f3923dee325bbad096d981a30234e417c17fb..3c2d28234f0d7a1e12046faff1037271fad59caa 100644 (file)
       <translation>Components are not selected</translation>
     </message>
   </context>
+  <context>
+    <name>GroupIntersection:EmptyResult</name>
+    <message>
+      <source>Error: Empty result.</source>
+      <translation>Error: Empty result.</translation>
+    </message>
+  </context>
 
 </TS>
diff --git a/src/CollectionPlugin/Test/Test2977.py b/src/CollectionPlugin/Test/Test2977.py
new file mode 100644 (file)
index 0000000..26568fe
--- /dev/null
@@ -0,0 +1,44 @@
+# Copyright (C) 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)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Top")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Top")])
+Group_3 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Top")])
+GroupAddition_1 = model.addGroupAddition(Part_1_doc, [model.selection("COMPOUND", "Group_1"), model.selection("COMPOUND", "Group_2")])
+GroupSubstraction_1 = model.addGroupSubstraction(Part_1_doc, [model.selection("COMPOUND", "GroupAddition_1")], [model.selection("COMPOUND", "Group_3")])
+model.end()
+
+from GeomAPI import *
+
+model.testNbResults(GroupSubstraction_1, 1)
+model.testNbSubResults(GroupSubstraction_1, [0])
+model.testNbSubShapes(GroupSubstraction_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(GroupSubstraction_1, GeomAPI_Shape.FACE, [2])
+model.testNbSubShapes(GroupSubstraction_1, GeomAPI_Shape.EDGE, [8])
+model.testNbSubShapes(GroupSubstraction_1, GeomAPI_Shape.VERTEX, [16])
+model.testResultsVolumes(GroupSubstraction_1, [200])
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupAddition.py b/src/CollectionPlugin/Test/TestGroupAddition.py
new file mode 100644 (file)
index 0000000..a5e88cc
--- /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
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"), model.selection("FACE", "Box_1_1/Left")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Top")])
+GroupAddition_1 = model.addGroupAddition(Part_1_doc, [model.selection("COMPOUND", "Group_1"), model.selection("COMPOUND", "Group_2")])
+model.end()
+
+from GeomAPI import *
+
+model.testNbResults(GroupAddition_1, 1)
+model.testNbSubResults(GroupAddition_1, [0])
+model.testNbSubShapes(GroupAddition_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(GroupAddition_1, GeomAPI_Shape.FACE, [3])
+model.testNbSubShapes(GroupAddition_1, GeomAPI_Shape.EDGE, [12])
+model.testNbSubShapes(GroupAddition_1, GeomAPI_Shape.VERTEX, [24])
+model.testResultsVolumes(GroupAddition_1, [300])
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupAddition_Error.py b/src/CollectionPlugin/Test/TestGroupAddition_Error.py
new file mode 100644 (file)
index 0000000..b69a249
--- /dev/null
@@ -0,0 +1,33 @@
+# 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)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"), model.selection("FACE", "Box_1_1/Left")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Right]")])
+GroupAddition_1 = model.addGroupAddition(Part_1_doc, [model.selection("COMPOUND", "Group_1"), model.selection("COMPOUND", "Group_2")])
+GroupAddition_2 = model.addGroupAddition(Part_1_doc, [model.selection("COMPOUND", "Group_1"), model.selection("FACE", "Box_1_1/Front")])
+model.end()
+
+assert(GroupAddition_1.feature().error() != "")
diff --git a/src/CollectionPlugin/Test/TestGroupIntersection.py b/src/CollectionPlugin/Test/TestGroupIntersection.py
new file mode 100644 (file)
index 0000000..e53bfb1
--- /dev/null
@@ -0,0 +1,45 @@
+# 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)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"), model.selection("FACE", "Box_1_1/Left")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Top")])
+Group_3_objects = [model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Right"), model.selection("FACE", "Box_1_1/Top")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+GroupIntersection_1_objects = [model.selection("COMPOUND", "Group_1"), model.selection("COMPOUND", "Group_2"), model.selection("COMPOUND", "Group_3")]
+GroupIntersection_1 = model.addGroupIntersection(Part_1_doc, GroupIntersection_1_objects)
+model.end()
+
+from GeomAPI import *
+
+model.testNbResults(GroupIntersection_1, 1)
+model.testNbSubResults(GroupIntersection_1, [0])
+model.testNbSubShapes(GroupIntersection_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(GroupIntersection_1, GeomAPI_Shape.FACE, [1])
+model.testNbSubShapes(GroupIntersection_1, GeomAPI_Shape.EDGE, [4])
+model.testNbSubShapes(GroupIntersection_1, GeomAPI_Shape.VERTEX, [8])
+model.testResultsVolumes(GroupIntersection_1, [100])
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupIntersection_Error.py b/src/CollectionPlugin/Test/TestGroupIntersection_Error.py
new file mode 100644 (file)
index 0000000..cfa9601
--- /dev/null
@@ -0,0 +1,34 @@
+# 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)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"), model.selection("FACE", "Box_1_1/Left")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Top")])
+Group_3 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Right")])
+GroupIntersection_1_objects = [model.selection("COMPOUND", "Group_1"), model.selection("COMPOUND", "Group_2"), model.selection("COMPOUND", "Group_3")]
+GroupIntersection_1 = model.addGroupIntersection(Part_1_doc, GroupIntersection_1_objects)
+model.end()
+
+assert(GroupIntersection_1.feature().error() != "")
diff --git a/src/CollectionPlugin/Test/TestGroupSubstraction.py b/src/CollectionPlugin/Test/TestGroupSubstraction.py
new file mode 100644 (file)
index 0000000..98669ca
--- /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
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1_objects = [model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Left]")]
+Group_1 = model.addGroup(Part_1_doc, Group_1_objects)
+Group_2_objects = [model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Right]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Group_3_objects = [model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Top]")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+Group_4_objects = [model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Bottom]")]
+Group_4 = model.addGroup(Part_1_doc, Group_4_objects)
+GroupSubstraction_1 = model.addGroupSubstraction(Part_1_doc, [model.selection("COMPOUND", "Group_1"), model.selection("COMPOUND", "Group_2")], [model.selection("COMPOUND", "Group_3"), model.selection("COMPOUND", "Group_4")])
+model.end()
+
+from GeomAPI import *
+
+model.testNbResults(GroupSubstraction_1, 1)
+model.testNbSubResults(GroupSubstraction_1, [0])
+model.testNbSubShapes(GroupSubstraction_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(GroupSubstraction_1, GeomAPI_Shape.FACE, [0])
+model.testNbSubShapes(GroupSubstraction_1, GeomAPI_Shape.EDGE, [3])
+model.testNbSubShapes(GroupSubstraction_1, GeomAPI_Shape.VERTEX, [6])
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupSubstraction_Error1.py b/src/CollectionPlugin/Test/TestGroupSubstraction_Error1.py
new file mode 100644 (file)
index 0000000..65ba668
--- /dev/null
@@ -0,0 +1,33 @@
+# 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)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"), model.selection("FACE", "Box_1_1/Left")])
+Group_2_objects = [model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Right]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+GroupSubstraction_1 = model.addGroupSubstraction(Part_1_doc, [model.selection("COMPOUND", "Group_1")], [model.selection("COMPOUND", "Group_2")])
+model.end()
+
+assert(GroupSubstraction_1.feature().error() != "")
diff --git a/src/CollectionPlugin/Test/TestGroupSubstraction_Error2.py b/src/CollectionPlugin/Test/TestGroupSubstraction_Error2.py
new file mode 100644 (file)
index 0000000..46967dd
--- /dev/null
@@ -0,0 +1,33 @@
+# 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)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"), model.selection("FACE", "Box_1_1/Left")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Front")])
+Group_3 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Top")])
+GroupSubstraction_1 = model.addGroupSubstraction(Part_1_doc, [model.selection("COMPOUND", "Group_1")], [model.selection("COMPOUND", "Group_2"), model.selection("COMPOUND", "Group_3")])
+model.end()
+
+assert(GroupSubstraction_1.feature().error() != "")
index e31d778235bfd4f5e072efc9536f7b7ef10b07dd..2b83ddd8cfc0ba857884478d711d43ad92ba32be 100644 (file)
@@ -13,3 +13,6 @@ Collection plug-in deals with groups of geometrical entities created by selectio
 
    fieldFeature.rst
    groupFeature.rst
+   groupAdditionFeature.rst
+   groupIntersectionFeature.rst
+   groupSubstractionFeature.rst
diff --git a/src/CollectionPlugin/doc/TUI_groupAdditionFeature.rst b/src/CollectionPlugin/doc/TUI_groupAdditionFeature.rst
new file mode 100644 (file)
index 0000000..ea9cbaf
--- /dev/null
@@ -0,0 +1,11 @@
+
+  .. _tui_create_group_addition:
+
+Create Group Addition
+=====================
+
+.. literalinclude:: examples/group_addition.py
+    :linenos:
+    :language: python
+
+:download:`Download this script <examples/group_addition.py>`
diff --git a/src/CollectionPlugin/doc/TUI_groupIntersectionFeature.rst b/src/CollectionPlugin/doc/TUI_groupIntersectionFeature.rst
new file mode 100644 (file)
index 0000000..37a7d8d
--- /dev/null
@@ -0,0 +1,11 @@
+
+  .. _tui_create_group_intersection:
+
+Create Group Intersection
+=========================
+
+.. literalinclude:: examples/group_intersection.py
+    :linenos:
+    :language: python
+
+:download:`Download this script <examples/group_intersection.py>`
diff --git a/src/CollectionPlugin/doc/TUI_groupSubstractionFeature.rst b/src/CollectionPlugin/doc/TUI_groupSubstractionFeature.rst
new file mode 100644 (file)
index 0000000..ca836f9
--- /dev/null
@@ -0,0 +1,11 @@
+
+  .. _tui_create_group_substraction:
+
+Create Group Substraction
+=========================
+
+.. literalinclude:: examples/group_substraction.py
+    :linenos:
+    :language: python
+
+:download:`Download this script <examples/group_substraction.py>`
diff --git a/src/CollectionPlugin/doc/examples/group_addition.py b/src/CollectionPlugin/doc/examples/group_addition.py
new file mode 100644 (file)
index 0000000..20f80fc
--- /dev/null
@@ -0,0 +1,14 @@
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"),
+                                      model.selection("FACE", "Box_1_1/Left")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Front"),
+                                      model.selection("FACE", "Box_1_1/Top")])
+GroupAddition_1 = model.addGroupAddition(Part_1_doc, [model.selection("COMPOUND", "Group_1"),
+                                                      model.selection("COMPOUND", "Group_2")])
+model.end()
diff --git a/src/CollectionPlugin/doc/examples/group_intersection.py b/src/CollectionPlugin/doc/examples/group_intersection.py
new file mode 100644 (file)
index 0000000..84cb476
--- /dev/null
@@ -0,0 +1,19 @@
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"),
+                                      model.selection("FACE", "Box_1_1/Left")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Front"),
+                                      model.selection("FACE", "Box_1_1/Top")])
+Group_3 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Front"),
+                                      model.selection("FACE", "Box_1_1/Right"),
+                                      model.selection("FACE", "Box_1_1/Top")])
+GroupIntersection_1_objects = [model.selection("COMPOUND", "Group_1"),
+                               model.selection("COMPOUND", "Group_2"),
+                               model.selection("COMPOUND", "Group_3")]
+GroupIntersection_1 = model.addGroupIntersection(Part_1_doc, GroupIntersection_1_objects)
+model.end()
diff --git a/src/CollectionPlugin/doc/examples/group_substraction.py b/src/CollectionPlugin/doc/examples/group_substraction.py
new file mode 100644 (file)
index 0000000..75cf556
--- /dev/null
@@ -0,0 +1,33 @@
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1_objects = [model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Bottom]"),
+                   model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]"),
+                   model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"),
+                   model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Left]")]
+Group_1 = model.addGroup(Part_1_doc, Group_1_objects)
+Group_2_objects = [model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]"),
+                   model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Bottom]"),
+                   model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Right]"),
+                   model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Group_3_objects = [model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"),
+                   model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]"),
+                   model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Top]"),
+                   model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Top]")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+Group_4_objects = [model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Bottom]"),
+                   model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Bottom]"),
+                   model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Bottom]"),
+                   model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Bottom]")]
+Group_4 = model.addGroup(Part_1_doc, Group_4_objects)
+GroupSubstraction_1 = model.addGroupSubstraction(Part_1_doc,
+                                                 [model.selection("COMPOUND", "Group_1"),
+                                                  model.selection("COMPOUND", "Group_2")],
+                                                 [model.selection("COMPOUND", "Group_3"),
+                                                  model.selection("COMPOUND", "Group_4")])
+model.end()
diff --git a/src/CollectionPlugin/doc/groupAdditionFeature.rst b/src/CollectionPlugin/doc/groupAdditionFeature.rst
new file mode 100644 (file)
index 0000000..fc6c78c
--- /dev/null
@@ -0,0 +1,37 @@
+.. |group_addition.icon|    image:: images/group_addition.png
+
+Group Addition
+==============
+
+Group addition produces a union of all the elements of the selected groups.
+To create a Group Addition in the active part:
+
+#. select in the Main Menu *Features - > Group Addition* item  or
+#. click |group_addition.icon| **Group Addition** button in the toolbar:
+
+The following property panel appears. 
+
+.. image:: images/group_addition_property_panel.png
+  :align: center
+
+.. centered::
+  Create a group addition operation
+
+Input fields:
+
+- **Name** defines the name of the group, by default, it is **GroupAddition_n**.
+- The list of selected groups of the same type.  Multiple selection can be done manually in OCC 3D Viewer by mouse click with Shift button pressed or by rectangle selection. To delete entities from the list, select them and call pop-up menu *Delete* item.
+
+Note, that operation is valid only for the groups of the same type.
+
+**TUI Command**:
+
+.. py:function:: model.addGroupAddition(Part_1_doc,
+                                       [model.selection("COMPOUND", "Group_1"), model.selection("COMPOUND", "Group_2")])
+
+    :param part: The current part object
+    :param list: A list of selected groups
+    :return: Created group.
+
+
+**See Also** a sample TUI Script of :ref:`tui_create_group_addition` operation.
index 1522bf7e0fe059036628439fb0bfdd13fb616c0a..436653e025dff401143fe450f7142eabed7385f0 100644 (file)
@@ -3,6 +3,8 @@
 .. |minus.icon|  image:: images/reverce.png
 .. |delete.icon|  image:: images/delete.png
 
+.. _groupPage:
+
 Group
 =====
 
@@ -43,45 +45,12 @@ Input fields:
  
 - The list of selected entities of the given type.  Multiple selection can be done manually in OCC 3D Viewer by mouse click with Shift button pressed or by rectangle selection. To delete entities from the list, select them and call pop-up menu *Delete* item.
 
-- **Selection by filters** button opens "selection by filters" property panel and allows to select entities by set of selected filters.
+- **Selection by filters** button opens "selection by filters" property panel and allows to select entities by set of selected filters. For details on filters see :ref:`filtersPlugin`
 
 - **Show only** button allows to hide all other objects and shapes and show only selected ones.
 
 - Control **Add elements that share the same topology** allows to add automatically all elements laying on the same topology that was selected and remove these elements if they have disappeared due to the parametrical update. They will be represented as one line in the list of selection and managed in the viewer as one object if this flag is enabled. If flag becomes disabled when such elements are already in the list, they will become divided in one line per one shape.
 
-**Selection by filters**
-
-If user presses this button then following property panel appears.
-
-.. image:: images/selection_by_filters.png
-  :align: center
-
-.. centered::
-  Selection by filters property panel
-
-In this panel:
-
-- **Filters** a panel for added filters.
-
-- **Add new filter** combo box. It contains accessible filters according to the selection mode defined in **Group** property panel. When user selects an item from this combo box a filter item appears in **Filters** panel like in the following example:
-
-.. image:: images/selection_by_filters_added.png
-  :align: center
-
-.. centered::
-  Filters **Horizontal faces** and **On plane** added to the property panel.
-  
-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.
-
-- **Select** button traverces all objects of a current document and selects entities acceptable by currently defined set of filters. All selected entities will be shown in viewer 3d with
-blue semi-transparent color. Any modification in filters clears current selection.
-
-- **Number of selected objects** shows number currently selected entities.
-
-- **Show only** check box lets to hide all non-selected objects.
-
-**Accept** button in the **Selection by filters** property panel reopens **Group** property panel again and transfers all selected entities to the corresponded list.
 
 **TUI Command**:
 
diff --git a/src/CollectionPlugin/doc/groupIntersectionFeature.rst b/src/CollectionPlugin/doc/groupIntersectionFeature.rst
new file mode 100644 (file)
index 0000000..c31116d
--- /dev/null
@@ -0,0 +1,37 @@
+.. |group_intersection.icon|    image:: images/group_intersection.png
+
+Group Intersection
+==================
+
+Group intersection produces a group of elements present in all the selected groups.
+To create a Group Intersection in the active part:
+
+#. select in the Main Menu *Features - > Group Intersection* item  or
+#. click |group_intersection.icon| **Group Intersection** button in the toolbar:
+
+The following property panel appears. 
+
+.. image:: images/group_intersection_property_panel.png
+  :align: center
+
+.. centered::
+  Create a group intersection operation
+
+Input fields:
+
+- **Name** defines the name of the group, by default, it is **GroupIntersection_n**.
+- The list of selected groups of the same type.  Multiple selection can be done manually in OCC 3D Viewer by mouse click with Shift button pressed or by rectangle selection. To delete entities from the list, select them and call pop-up menu *Delete* item.
+
+Note, that operation is valid only for the groups of the same type.
+
+**TUI Command**:
+
+.. py:function:: model.addGroupIntersection(Part_1_doc,
+                                       [model.selection("COMPOUND", "Group_1"), model.selection("COMPOUND", "Group_2")])
+
+    :param part: The current part object
+    :param list: A list of selected groups
+    :return: Created group.
+
+
+**See Also** a sample TUI Script of :ref:`tui_create_group_intersection` operation.
diff --git a/src/CollectionPlugin/doc/groupSubstractionFeature.rst b/src/CollectionPlugin/doc/groupSubstractionFeature.rst
new file mode 100644 (file)
index 0000000..1f269ac
--- /dev/null
@@ -0,0 +1,40 @@
+.. |group_substraction.icon|    image:: images/group_substraction.png
+
+Group Substraction
+==================
+
+Group substraction produces a group containing all elements of the main groups but not present in the tool groups.
+To create a Group Substraction in the active part:
+
+#. select in the Main Menu *Features - > Group Substraction* item  or
+#. click |group_substraction.icon| **Group Substraction** button in the toolbar:
+
+The following property panel appears. 
+
+.. image:: images/group_substraction_property_panel.png
+  :align: center
+
+.. centered::
+  Create a group substraction operation
+
+Input fields:
+
+- **Name** defines the name of the group, by default, it is **GroupSubstraction_n**.
+- The list of main groups.  Multiple selection can be done manually in OCC 3D Viewer by mouse click with Shift button pressed or by rectangle selection. To delete entities from the list, select them and call pop-up menu *Delete* item.
+- The list of tool groups.  Selection approaches are the same as for the main groups.
+
+Note, that operation is valid only if all the main groups and all the tool groups have the same type.
+
+**TUI Command**:
+
+.. py:function:: model.addGroupSubstraction(Part_1_doc,
+                                       [model.selection("COMPOUND", "Group_1"), model.selection("COMPOUND", "Group_2")],
+                                       [model.selection("COMPOUND", "Group_3"), model.selection("COMPOUND", "Group_4")])
+
+    :param part: The current part object
+    :param list: A list of main groups
+    :param list: A list of tool groups
+    :return: Created group.
+
+
+**See Also** a sample TUI Script of :ref:`tui_create_group_substraction` operation.
diff --git a/src/CollectionPlugin/doc/images/add.png b/src/CollectionPlugin/doc/images/add.png
deleted file mode 100644 (file)
index 388f8ff..0000000
Binary files a/src/CollectionPlugin/doc/images/add.png and /dev/null differ
diff --git a/src/CollectionPlugin/doc/images/delete.png b/src/CollectionPlugin/doc/images/delete.png
deleted file mode 100644 (file)
index 6d2aea8..0000000
Binary files a/src/CollectionPlugin/doc/images/delete.png and /dev/null differ
diff --git a/src/CollectionPlugin/doc/images/group_addition.png b/src/CollectionPlugin/doc/images/group_addition.png
new file mode 100644 (file)
index 0000000..6bc76e0
Binary files /dev/null and b/src/CollectionPlugin/doc/images/group_addition.png differ
diff --git a/src/CollectionPlugin/doc/images/group_addition_property_panel.png b/src/CollectionPlugin/doc/images/group_addition_property_panel.png
new file mode 100644 (file)
index 0000000..0506316
Binary files /dev/null and b/src/CollectionPlugin/doc/images/group_addition_property_panel.png differ
diff --git a/src/CollectionPlugin/doc/images/group_intersection.png b/src/CollectionPlugin/doc/images/group_intersection.png
new file mode 100644 (file)
index 0000000..aba074c
Binary files /dev/null and b/src/CollectionPlugin/doc/images/group_intersection.png differ
diff --git a/src/CollectionPlugin/doc/images/group_intersection_property_panel.png b/src/CollectionPlugin/doc/images/group_intersection_property_panel.png
new file mode 100644 (file)
index 0000000..e91c3d1
Binary files /dev/null and b/src/CollectionPlugin/doc/images/group_intersection_property_panel.png differ
diff --git a/src/CollectionPlugin/doc/images/group_substraction.png b/src/CollectionPlugin/doc/images/group_substraction.png
new file mode 100644 (file)
index 0000000..7db75ec
Binary files /dev/null and b/src/CollectionPlugin/doc/images/group_substraction.png differ
diff --git a/src/CollectionPlugin/doc/images/group_substraction_property_panel.png b/src/CollectionPlugin/doc/images/group_substraction_property_panel.png
new file mode 100644 (file)
index 0000000..6cac1b7
Binary files /dev/null and b/src/CollectionPlugin/doc/images/group_substraction_property_panel.png differ
diff --git a/src/CollectionPlugin/doc/images/reverce.png b/src/CollectionPlugin/doc/images/reverce.png
deleted file mode 100644 (file)
index 40239ad..0000000
Binary files a/src/CollectionPlugin/doc/images/reverce.png and /dev/null differ
diff --git a/src/CollectionPlugin/doc/images/selection_by_filters.png b/src/CollectionPlugin/doc/images/selection_by_filters.png
deleted file mode 100644 (file)
index c4ac7ee..0000000
Binary files a/src/CollectionPlugin/doc/images/selection_by_filters.png and /dev/null differ
diff --git a/src/CollectionPlugin/doc/images/selection_by_filters_added.png b/src/CollectionPlugin/doc/images/selection_by_filters_added.png
deleted file mode 100644 (file)
index a3e0a25..0000000
Binary files a/src/CollectionPlugin/doc/images/selection_by_filters_added.png and /dev/null differ
diff --git a/src/CollectionPlugin/group_addition_widget.xml b/src/CollectionPlugin/group_addition_widget.xml
new file mode 100644 (file)
index 0000000..98f21d9
--- /dev/null
@@ -0,0 +1,13 @@
+<source>
+  <namevalue id="name"
+             label="Name"
+             placeholder="Please input the group name">
+  </namevalue>
+  <multi_selector id="group_list"
+                  label="Base groups:"
+                  tooltip="Select a set of groups"
+                  shape_types="objects"
+                  allow_objects="Group">
+    <validator id="CollectionPlugin_OperationAttribute"/>
+  </multi_selector>
+</source>
diff --git a/src/CollectionPlugin/group_intersection_widget.xml b/src/CollectionPlugin/group_intersection_widget.xml
new file mode 100644 (file)
index 0000000..35cbf71
--- /dev/null
@@ -0,0 +1,12 @@
+<source>
+  <namevalue id="name"
+             label="Name"
+             placeholder="Please input the group name">
+  </namevalue>
+  <multi_selector id="group_list"
+                  label="Base groups:"
+                  tooltip="Select a set of groups"
+                  shape_types="objects">
+    <validator id="CollectionPlugin_OperationAttribute"/>
+  </multi_selector>
+</source>
diff --git a/src/CollectionPlugin/group_substraction_widget.xml b/src/CollectionPlugin/group_substraction_widget.xml
new file mode 100644 (file)
index 0000000..ebd76f0
--- /dev/null
@@ -0,0 +1,18 @@
+<source>
+  <namevalue id="name"
+             label="Name"
+             placeholder="Please input the group name">
+  </namevalue>
+  <multi_selector id="group_list"
+                  label="Main groups:"
+                  tooltip="Select a set of groups"
+                  shape_types="objects">
+    <validator id="CollectionPlugin_OperationAttribute" parameters="tools_list"/>
+  </multi_selector>
+  <multi_selector id="tools_list"
+                  label="Tool groups:"
+                  tooltip="Select a set of groups"
+                  shape_types="objects">
+    <validator id="CollectionPlugin_OperationAttribute" parameters="group_list"/>
+  </multi_selector>
+</source>
index 59bd93fb4001e414434bddd767e2434b445473ce..6c304ade6eb852943c7dfe8d0ccbcaf2362ed787 100644 (file)
@@ -5,7 +5,7 @@
   </namevalue>
   <multi_selector id="group_list"
     tooltip="Select a set of objects"
-    type_choice="Vertices Edges Faces Solids"
+    shape_types="Vertices Edges Faces Solids"
     use_choice="true"
     use_filters="FiltersSelection"
     clear_in_neutral_point="false"
diff --git a/src/CollectionPlugin/icons/group_addition.png b/src/CollectionPlugin/icons/group_addition.png
new file mode 100644 (file)
index 0000000..6bc76e0
Binary files /dev/null and b/src/CollectionPlugin/icons/group_addition.png differ
diff --git a/src/CollectionPlugin/icons/group_intersection.png b/src/CollectionPlugin/icons/group_intersection.png
new file mode 100644 (file)
index 0000000..aba074c
Binary files /dev/null and b/src/CollectionPlugin/icons/group_intersection.png differ
diff --git a/src/CollectionPlugin/icons/group_substraction.png b/src/CollectionPlugin/icons/group_substraction.png
new file mode 100644 (file)
index 0000000..7db75ec
Binary files /dev/null and b/src/CollectionPlugin/icons/group_substraction.png differ
index 27057f56f81d62468e1d79f1235410329fe56840..a02f0bf2fb81c8b901d93f71b50aa83efe1d1043 100644 (file)
@@ -1,15 +1,6 @@
 <plugin>
   <workbench id="Features" document="Part">
     <group id="Collections">
-      <feature id="Group"
-        title="Group"
-        tooltip="Create named collection of geometry entities"
-        icon="icons/Collection/shape_group.png"
-        apply_continue="true"
-        helpfile="groupFeature.html">
-        <source path="group_widget.xml"/>
-      </feature>
-
       <feature id="Field"
         title="Field"
         tooltip="Create fields for selected shapes"
         </field-panel>
         <validator id="CollectionPlugin_FieldValidator"/>
       </feature>
+
+      <feature id="Group"
+        title="Group"
+        tooltip="Create named collection of geometry entities"
+        icon="icons/Collection/shape_group.png"
+        apply_continue="true"
+        helpfile="groupFeature.html">
+        <source path="group_widget.xml"/>
+      </feature>
+
+      <feature id="GroupAddition"
+        title="Group Addition"
+        tooltip="Join several groups to single group"
+        icon="icons/Collection/group_addition.png"
+        helpfile="groupAdditionFeature.html">
+        <source path="group_addition_widget.xml"/>
+      </feature>
+
+      <feature id="GroupIntersection"
+        title="Group Intersection"
+        tooltip="Get elements existing in all groups"
+        icon="icons/Collection/group_intersection.png"
+        helpfile="groupIntersectionFeature.html">
+        <source path="group_intersection_widget.xml"/>
+      </feature>
+
+      <feature id="GroupSubstraction"
+        title="Group Substraction"
+        tooltip="Exclude elements existing tool groups"
+        icon="icons/Collection/group_substraction.png"
+        helpfile="groupSubstractionFeature.html">
+        <source path="group_substraction_widget.xml"/>
+      </feature>
     </group>
   </workbench>
 </plugin>
index fdc684cc3b849dda2f57b1585bb35cd664e98e70..47baeae2ee4da30faf6e77d3bb567fcf84bdd26e 100644 (file)
@@ -147,6 +147,7 @@ void Config_FeatureMessage::setPluginLibrary(const std::string& myPluginLibrary)
   this->myPluginLibrary = myPluginLibrary;
 }
 
+// LCOV_EXCL_START
 bool Config_FeatureMessage::isUseInput() const
 {
   return myUseInput;
@@ -176,7 +177,7 @@ bool Config_FeatureMessage::isApplyContinue() const
 {
   return myIsApplyContinue;
 }
-
+// LCOV_EXCL_STOP
 
 void Config_FeatureMessage::setUseInput(bool isUseInput)
 {
index 16da267c6fa950021871982cf609f2fc017bb287..7d93e060e7dc85163cad07be11d650a6b2444239 100644 (file)
@@ -174,6 +174,11 @@ void Config_FeatureReader::fillFeature(xmlNodePtr theFeatureNode,
 
   bool isInternal = getBooleanAttribute(theFeatureNode, ATTR_INTERNAL, false);
   outFeatureMessage->setInternal(isInternal);
+
+  std::string aHelpFile = getProperty(theFeatureNode, HELP_FILE);
+  if (!aHelpFile.empty())
+    outFeatureMessage->setHelpFileName(myLibraryName + "/" + aHelpFile);
+
   if (isInternal) {
     //Internal feature has no visual representation.
     return;
@@ -183,14 +188,11 @@ void Config_FeatureReader::fillFeature(xmlNodePtr theFeatureNode,
   outFeatureMessage->setText(aText);
   bool isTitleInToolbar = getBooleanAttribute(theFeatureNode, FEATURE_TITLE_IN_TOOLBAR, true);
   outFeatureMessage->setTitleInToolbar(isTitleInToolbar);
-  //std::string aToolTip = Config_Translator::translate(
-  //  anId, getProperty(theFeatureNode, FEATURE_TOOLTIP));
-  //outFeatureMessage->setTooltip(aToolTip);
+  std::string aToolTip = Config_Translator::translate(
+    anId, getProperty(theFeatureNode, FEATURE_TOOLTIP));
+  outFeatureMessage->setTooltip(aToolTip);
   outFeatureMessage->setIcon(getProperty(theFeatureNode, FEATURE_ICON));
   outFeatureMessage->setKeysequence(getProperty(theFeatureNode, FEATURE_KEYSEQUENCE));
-  std::string aHelpFile = getProperty(theFeatureNode, HELP_FILE);
-  if (!aHelpFile.empty())
-    outFeatureMessage->setHelpFileName(myLibraryName + "/" + aHelpFile);
 
   std::string aGroupName = restoreAttribute(NODE_GROUP, _ID);
   std::string aWBNName = restoreAttribute(NODE_WORKBENCH, _ID);
index 87476727f5305315c0cd1e4d6e6386681811565e..77c60c23c3efd7c8be4b63ce1cff38e221955a50 100644 (file)
@@ -19,7 +19,7 @@
 @ALL_SOLVERS@
 -->
   <plugin library="GeomValidators"/>
-  <plugin library="Filters" configuration="plugin-Filters.xml"/>
+  <plugin library="FiltersPlugin" configuration="plugin-Filters.xml"/>
   <plugin library="DFBrowser" internal="true"/>
 <!--
   <plugin library="SamplePanelPlugin" configuration="plugin-SamplePanel.xml"/>
index 9de0ea04d47d1ac58ac70043ece07a2c6af15781..77377191c754a5a96d89bd42d46efead4e3b83f6 100644 (file)
@@ -165,19 +165,19 @@ def checkResultInGEOM():
 
   field_1_GEOM = getSubObject(geomObject_1, 5)
   assert field_1_GEOM.GetName() == 'Field_solids'
-  assert field_1_GEOM.GetStep(0).GetValues() == [3.0]
+  assert field_1_GEOM.GetStep(1).GetValues() == [3.0]
 
   field_2_GEOM = getSubObject(geomObject_1, 6)
   assert field_2_GEOM.GetName() == 'Field_faces'
-  assert field_2_GEOM.GetStep(0).GetValues() == [0.0, 0.0, 0.0, 0.0, 1.0, 2.0]
+  assert field_2_GEOM.GetStep(1).GetValues() == [0.0, 0.0, 0.0, 0.0, 1.0, 2.0]
 
   field_3_GEOM = getSubObject(geomObject_1, 7)
   assert field_3_GEOM.GetName() == 'Field_edges'
-  assert field_3_GEOM.GetStep(0).GetValues() == [0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 2.0, 0.0, 1.0, 0.0, 0.0, 0.0]
+  assert field_3_GEOM.GetStep(1).GetValues() == [0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 2.0, 0.0, 1.0, 0.0, 0.0, 0.0]
 
   field_4_GEOM = getSubObject(geomObject_1, 8)
   assert field_4_GEOM.GetName() == 'Field_vertices'
-  assert field_4_GEOM.GetStep(0).GetValues() == [0.0, 0.0, 0.0, 1.0, 3.0, 1.0, 3.0, 1.0]
+  assert field_4_GEOM.GetStep(1).GetValues() == [0.0, 0.0, 0.0, 1.0, 3.0, 1.0, 3.0, 1.0]
 
   pass
 
index 3f52e2cf1023ccd86dc3161e219e459e8555a57e..33464e0874f11c3fe1661a83ae9819b0a0a968d7 100644 (file)
@@ -87,9 +87,10 @@ bool ExchangePlugin_FormatValidator::isValid(const AttributePtr& theAttribute,
   std::transform(aFileName.begin(), aFileName.end(), aFileName.begin(), toupper);
   // Is file name ends with the format
   for (; itFormats != aFormats.end(); ++itFormats) {
-    if (aFileNameLen > (*itFormats).length()) {
-      size_t aFormatBeginPos = aFileNameLen - (*itFormats).length();
-      if (aFileName.compare(aFormatBeginPos, std::string::npos, *itFormats) == 0) {
+    std::string aFormat = "." + *itFormats;
+    if (aFileNameLen > aFormat.length()) {
+      size_t aFormatBeginPos = aFileNameLen - aFormat.length();
+      if (aFileName.compare(aFormatBeginPos, std::string::npos, aFormat) == 0) {
         return true;
       }
     }
index 6c60d9f569c4c4f84ffa3ff3b11584e7e1064528..9e134b805c32601d268fc1ce6e73a25e165e2a50 100644 (file)
@@ -10,7 +10,7 @@
       </export_file_selector>
       <multi_selector id="selection_list"
                       tooltip="Select a set of objects"
-                      type_choice="Vertices Edges Faces Solids Compsolids Objects">
+                      shape_types="Vertices Edges Faces Solids Compsolids Objects">
         <validator id="GeomValidators_Finite"/>
       </multi_selector>
     </case>
index 9311f491d42cef0d6eabb07111bbfefbc0851865..acd6222f5e1cc4c674c701072acaf6b93b2f4f21 100644 (file)
@@ -26,6 +26,7 @@ SET(PROJECT_HEADERS
   FeaturesAPI_BooleanCommon.h
   FeaturesAPI_BooleanSmash.h
   FeaturesAPI_BooleanFill.h
+  FeaturesAPI_Chamfer.h
   FeaturesAPI_Extrusion.h
   FeaturesAPI_ExtrusionBoolean.h
   FeaturesAPI_Fillet.h
@@ -55,6 +56,7 @@ SET(PROJECT_SOURCES
   FeaturesAPI_BooleanCommon.cpp
   FeaturesAPI_BooleanSmash.cpp
   FeaturesAPI_BooleanFill.cpp
+  FeaturesAPI_Chamfer.cpp
   FeaturesAPI_Extrusion.cpp
   FeaturesAPI_ExtrusionBoolean.cpp
   FeaturesAPI_Fillet.cpp
index 35bdfcefcc62383ddad656957c4c2b174045629b..a1a7fbe1f9ff9d59c25704a4e4f2ff37a450b591 100644 (file)
@@ -43,6 +43,7 @@
 %shared_ptr(FeaturesAPI_BooleanCommon)
 %shared_ptr(FeaturesAPI_BooleanSmash)
 %shared_ptr(FeaturesAPI_BooleanFill)
+%shared_ptr(FeaturesAPI_Chamfer)
 %shared_ptr(FeaturesAPI_Extrusion)
 %shared_ptr(FeaturesAPI_ExtrusionBoolean)
 %shared_ptr(FeaturesAPI_ExtrusionCut)
@@ -74,6 +75,7 @@
 %include "FeaturesAPI_BooleanCommon.h"
 %include "FeaturesAPI_BooleanSmash.h"
 %include "FeaturesAPI_BooleanFill.h"
+%include "FeaturesAPI_Chamfer.h"
 %include "FeaturesAPI_Extrusion.h"
 %include "FeaturesAPI_ExtrusionBoolean.h"
 %include "FeaturesAPI_Fillet.h"
diff --git a/src/FeaturesAPI/FeaturesAPI_Chamfer.cpp b/src/FeaturesAPI/FeaturesAPI_Chamfer.cpp
new file mode 100644 (file)
index 0000000..0d1e815
--- /dev/null
@@ -0,0 +1,131 @@
+// Copyright (C) 2017-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 "FeaturesAPI_Chamfer.h"
+
+#include <ModelHighAPI_Double.h>
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Tools.h>
+
+FeaturesAPI_Chamfer::FeaturesAPI_Chamfer(const std::shared_ptr<ModelAPI_Feature>& theFeature)
+  : ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+FeaturesAPI_Chamfer::FeaturesAPI_Chamfer(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                         const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                                         const bool performDistances,
+                                         const ModelHighAPI_Double& theVal1,
+                                         const ModelHighAPI_Double& theVal2)
+  : ModelHighAPI_Interface(theFeature)
+{
+  if (initialize()) {
+    fillAttribute(theBaseObjects, mybaseObjects);
+    if (performDistances) {
+      fillAttribute(FeaturesPlugin_Chamfer::CREATION_METHOD_DISTANCE_DISTANCE(), mycreationMethod);
+      fillAttribute(theVal1, myd1);
+      fillAttribute(theVal2, myd2);
+    } else {
+      fillAttribute(FeaturesPlugin_Chamfer::CREATION_METHOD_DISTANCE_ANGLE(), mycreationMethod);
+      fillAttribute(theVal1, myd);
+      fillAttribute(theVal2, myangle);
+    }
+
+    execIfBaseNotEmpty();
+  }
+}
+
+FeaturesAPI_Chamfer::~FeaturesAPI_Chamfer()
+{
+}
+
+//==================================================================================================
+void FeaturesAPI_Chamfer::setBase(const std::list<ModelHighAPI_Selection>& theBaseObjects)
+{
+  mybaseObjects->clear();
+  fillAttribute(theBaseObjects, mybaseObjects);
+
+  execIfBaseNotEmpty();
+}
+
+void FeaturesAPI_Chamfer::setDistances(const ModelHighAPI_Double& theD1,
+                                       const ModelHighAPI_Double& theD2)
+{
+  fillAttribute(FeaturesPlugin_Chamfer::CREATION_METHOD_DISTANCE_DISTANCE(), mycreationMethod);
+  fillAttribute(theD1, myd1);
+  fillAttribute(theD2, myd2);
+
+  execIfBaseNotEmpty();
+}
+
+void FeaturesAPI_Chamfer::setDistAngle(const ModelHighAPI_Double& theDistance,
+                                       const ModelHighAPI_Double& theAngle)
+{
+  fillAttribute(FeaturesPlugin_Chamfer::CREATION_METHOD_DISTANCE_ANGLE(), mycreationMethod);
+  fillAttribute(theDistance, myd);
+  fillAttribute(theAngle, myangle);
+
+  execIfBaseNotEmpty();
+}
+
+void FeaturesAPI_Chamfer::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  const std::string& aDocName = theDumper.name(aBase->document());
+
+  AttributeSelectionListPtr anAttrObjects =
+    aBase->selectionList(FeaturesPlugin_Chamfer::OBJECT_LIST_ID());
+
+  theDumper << aBase << " = model.addChamfer(" << aDocName << ", " << anAttrObjects;
+
+  std::string aCreationMethod = aBase->string(FeaturesPlugin_Chamfer::CREATION_METHOD())->value();
+
+  if(aCreationMethod == FeaturesPlugin_Chamfer::CREATION_METHOD_DISTANCE_DISTANCE()) {
+    AttributeDoublePtr anAttrD1 = aBase->real(FeaturesPlugin_Chamfer::D1_ID());
+    AttributeDoublePtr anAttrD2 = aBase->real(FeaturesPlugin_Chamfer::D2_ID());
+    theDumper << ", True, " << anAttrD1 << ", " << anAttrD2;
+  } else if(aCreationMethod == FeaturesPlugin_Chamfer::CREATION_METHOD_DISTANCE_ANGLE()) {
+    AttributeDoublePtr anAttrD = aBase->real(FeaturesPlugin_Chamfer::D_ID());
+    AttributeDoublePtr anAttrAngle = aBase->real(FeaturesPlugin_Chamfer::ANGLE_ID());
+    theDumper << ", False, " << anAttrD << ", " << anAttrAngle;
+  }
+
+  theDumper << ")" << std::endl;
+}
+
+void FeaturesAPI_Chamfer::execIfBaseNotEmpty()
+{
+  if (mybaseObjects->size() > 0)
+    execute();
+}
+
+
+//==================================================================================================
+
+ChamferPtr addChamfer(const std::shared_ptr<ModelAPI_Document>& thePart,
+                      const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                      const bool performDistances,
+                      const ModelHighAPI_Double& theVal1,
+                      const ModelHighAPI_Double& theVal2)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(FeaturesAPI_Chamfer::ID());
+  return ChamferPtr(new FeaturesAPI_Chamfer(aFeature, theBaseObjects, performDistances,
+                                            theVal1, theVal2));
+}
diff --git a/src/FeaturesAPI/FeaturesAPI_Chamfer.h b/src/FeaturesAPI/FeaturesAPI_Chamfer.h
new file mode 100644 (file)
index 0000000..3baf2dd
--- /dev/null
@@ -0,0 +1,107 @@
+// Copyright (C) 2017-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 FeaturesAPI_Chamfer_H_
+#define FeaturesAPI_Chamfer_H_
+
+#include "FeaturesAPI.h"
+
+#include <FeaturesPlugin_Chamfer.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Double;
+class ModelHighAPI_Selection;
+
+/// \class FeaturesAPI_Chamfer
+/// \ingroup CPPHighAPI
+/// \brief Interface for Chamfer feature.
+class FeaturesAPI_Chamfer: public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  FEATURESAPI_EXPORT
+  explicit FeaturesAPI_Chamfer(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values.
+  FEATURESAPI_EXPORT
+  explicit FeaturesAPI_Chamfer(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                               const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                               const bool performDistances,
+                               const ModelHighAPI_Double& aVal1,
+                               const ModelHighAPI_Double& aVal2);
+
+  /// Destructor.
+  FEATURESAPI_EXPORT
+  virtual ~FeaturesAPI_Chamfer();
+
+  INTERFACE_6(FeaturesPlugin_Chamfer::ID(),
+              creationMethod, FeaturesPlugin_Chamfer::CREATION_METHOD(),
+                              ModelAPI_AttributeString,
+                              /** Creation method */,
+              baseObjects, FeaturesPlugin_Chamfer::OBJECT_LIST_ID(),
+                           ModelAPI_AttributeSelectionList,
+                           /** Base objects */,
+              d1, FeaturesPlugin_Chamfer::D1_ID(),
+                  ModelAPI_AttributeDouble,
+                  /** Value of the first distance chamfer */,
+              d2, FeaturesPlugin_Chamfer::D2_ID(),
+                  ModelAPI_AttributeDouble,
+                  /** Value of the second distance chamfer */,
+              d, FeaturesPlugin_Chamfer::D_ID(),
+                 ModelAPI_AttributeDouble,
+                 /** Value of the distance chamfer */,
+              angle, FeaturesPlugin_Chamfer::ANGLE_ID(),
+                     ModelAPI_AttributeDouble,
+                     /** Angle chamfer */)
+
+  /// Modify base objects of the chamfer.
+  FEATURESAPI_EXPORT
+  void setBase(const std::list<ModelHighAPI_Selection>& theBaseObjects);
+
+  /// Modify chamfer to have two distances
+  FEATURESAPI_EXPORT
+  void setDistances(const ModelHighAPI_Double& theD1, const ModelHighAPI_Double& theD2);
+
+  /// Modify chamfer to have distance  and angle
+  FEATURESAPI_EXPORT
+  void setDistAngle(const ModelHighAPI_Double& theDistance, const ModelHighAPI_Double& theAngle);
+
+  /// Dump wrapped feature
+  FEATURESAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+
+private:
+  void execIfBaseNotEmpty();
+};
+
+/// Pointer on Chamfer object.
+typedef std::shared_ptr<FeaturesAPI_Chamfer> ChamferPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create Chamfer feature.
+FEATURESAPI_EXPORT
+ChamferPtr addChamfer(const std::shared_ptr<ModelAPI_Document>& thePart,
+                      const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                      const bool performDistances,
+                      const ModelHighAPI_Double& theVal1,
+                      const ModelHighAPI_Double& theVal2);
+
+#endif // FeaturesAPI_Chamfer_H_
index f427c3f7da8f4c63d3632babaef77d7e5516f894..cd71216fae72dacf4ad6f159760cf424ba686105 100644 (file)
@@ -28,6 +28,7 @@
   #include "FeaturesAPI_BooleanCommon.h"
   #include "FeaturesAPI_BooleanSmash.h"
   #include "FeaturesAPI_BooleanFill.h"
+  #include "FeaturesAPI_Chamfer.h"
   #include "FeaturesAPI_Extrusion.h"
   #include "FeaturesAPI_ExtrusionBoolean.h"
   #include "FeaturesAPI_Fillet.h"
index 0e5ed0f99de0f0151ce70594ffb774d9104dace7..d244454475e2191b5fccd585c1871d9f52fc02f5 100644 (file)
@@ -60,6 +60,7 @@ SET(PROJECT_HEADERS
     FeaturesPlugin_Measurement.h
     FeaturesPlugin_FusionFaces.h
     FeaturesPlugin_RemoveResults.h
+    FeaturesPlugin_Chamfer.h
 )
 
 SET(PROJECT_SOURCES
@@ -101,6 +102,7 @@ SET(PROJECT_SOURCES
     FeaturesPlugin_Measurement.cpp
     FeaturesPlugin_FusionFaces.cpp
     FeaturesPlugin_RemoveResults.cpp
+    FeaturesPlugin_Chamfer.cpp
 )
 
 SET(XML_RESOURCES
@@ -132,6 +134,7 @@ SET(XML_RESOURCES
   fillet_widget.xml
   measurement_widget.xml
   fusion_faces_widget.xml
+  chamfer_widget.xml
 )
 
 SET(TEXT_RESOURCES
@@ -486,6 +489,7 @@ ADD_UNIT_TESTS(TestExtrusion.py
                Test2826.py
                Test2854.py
                Test2878.py
+               Test2971.py
                TestBooleanCommon_MultiLevelCompound_v0_1.py
                TestBooleanCommon_MultiLevelCompound_v0_2.py
                TestBooleanCommon_MultiLevelCompound_v20190506_1.py
@@ -523,4 +527,6 @@ ADD_UNIT_TESTS(TestExtrusion.py
                TestRemoveResultsConstruction.py
                TestRemoveResultsPart.py
                Test17000.py
+               Test17261.py
+               Test17281.py
 )
diff --git a/src/FeaturesPlugin/FeaturesPlugin_Chamfer.cpp b/src/FeaturesPlugin/FeaturesPlugin_Chamfer.cpp
new file mode 100644 (file)
index 0000000..0419b57
--- /dev/null
@@ -0,0 +1,235 @@
+// Copyright (C) 2017-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 "FeaturesPlugin_Chamfer.h"
+#include "FeaturesPlugin_Tools.h"
+
+#include <ModelAPI_Data.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Tools.h>
+#include <ModelAPI_Validator.h>
+
+#include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_Chamfer.h>
+#include <GeomAlgoAPI_MakeShapeList.h>
+#include <GeomAlgoAPI_Tools.h>
+
+#include <GeomAPI_DataMapOfShapeMapOfShapes.h>
+#include <GeomAPI_ShapeExplorer.h>
+#include <GeomAPI_ShapeIterator.h>
+
+// Obtain all sub-shapes from the shape and append them to the list
+static void collectSubs(const GeomShapePtr& theShape,
+                              ListOfShape& theSubs,
+                        const GeomAPI_Shape::ShapeType theShapeType)
+{
+  GeomAPI_ShapeExplorer anExp(theShape, theShapeType);
+  for (; anExp.more(); anExp.next()) {
+    GeomShapePtr aShape = anExp.current();
+    // Store all shapes with FORWARD orientation to avoid duplication of shared edges/vertices
+    aShape->setOrientation(GeomAPI_Shape::FORWARD);
+    theSubs.push_back(aShape);
+  }
+}
+
+// Extract edges from the list
+static ListOfShape selectEdges(const ListOfShape& theShapes)
+{
+  ListOfShape anEdges;
+  for (ListOfShape::const_iterator anIt = theShapes.begin(); anIt != theShapes.end(); ++anIt)
+    if ((*anIt)->isEdge())
+      anEdges.push_back(*anIt);
+  return anEdges;
+}
+
+// If theShape is a compound of a single sub-shape, return this sub-shape
+static GeomShapePtr unwrapCompound(const GeomShapePtr& theShape)
+{
+  GeomShapePtr aShape = theShape;
+  if(aShape->shapeType() == GeomAPI_Shape::COMPOUND) {
+    int aSubResultsNb = 0;
+    GeomAPI_ShapeIterator anIt(aShape);
+    for(; anIt.more(); anIt.next())
+      ++aSubResultsNb;
+
+    if(aSubResultsNb == 1) {
+      anIt.init(aShape);
+      aShape = anIt.current();
+    }
+  }
+  return aShape;
+}
+
+
+FeaturesPlugin_Chamfer::FeaturesPlugin_Chamfer()
+{
+}
+
+void FeaturesPlugin_Chamfer::initAttributes()
+{
+  data()->addAttribute(FeaturesPlugin_Chamfer::CREATION_METHOD(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(FeaturesPlugin_Chamfer::OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId());
+  data()->addAttribute(FeaturesPlugin_Chamfer::D1_ID(), ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(FeaturesPlugin_Chamfer::D2_ID(), ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(FeaturesPlugin_Chamfer::D_ID(), ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(FeaturesPlugin_Chamfer::ANGLE_ID(), ModelAPI_AttributeDouble::typeId());
+}
+
+
+void FeaturesPlugin_Chamfer::execute()
+{
+   AttributeStringPtr aCreationMethod = string(CREATION_METHOD());
+   if (!aCreationMethod)
+     return;
+
+   std::list<std::pair<GeomShapePtr, ListOfShape> > aSolidsAndSubs;
+   std::map<GeomShapePtr, GeomShapePtr> aMapEdgeFace;
+
+   // getting objects and sort them according to parent solids
+   AttributeSelectionListPtr anObjectsSelList = selectionList(OBJECT_LIST_ID());
+   for (int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); ++anObjectsIndex) {
+     AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex);
+     GeomShapePtr anObject = anObjectAttr->value();
+     if (!anObject)
+       return;
+
+     ResultPtr aContext = anObjectAttr->context();
+     GeomShapePtr aParent;
+     if (aContext.get()) {
+       ResultBodyPtr aCtxOwner = ModelAPI_Tools::bodyOwner(aContext);
+       aParent = aCtxOwner ? aCtxOwner->shape() : aContext->shape();
+     } else { // get it from a feature
+       FeaturePtr aFeature = anObjectAttr->contextFeature();
+       if (aFeature.get()) {
+         aParent = aFeature->firstResult()->shape();
+       }
+     }
+     if (!aParent)
+       return;
+
+     // searching this parent is already in the list aSolidsAndSubs
+     std::list<std::pair<GeomShapePtr, ListOfShape> >::iterator aSearch = aSolidsAndSubs.begin();
+     ListOfShape* aFound;
+     for(; aSearch != aSolidsAndSubs.end(); aSearch++) {
+       if (aSearch->first->isSame(aParent)) {
+         aFound = &(aSearch->second);
+         break;
+       }
+     }
+     if (aSearch == aSolidsAndSubs.end()) { // not found, so, add a new one
+       aSolidsAndSubs.push_back(std::pair<GeomShapePtr, ListOfShape>(aParent, ListOfShape()));
+       aFound = &(aSolidsAndSubs.back().second);
+     }
+
+    ListOfShape anEdgesAndVertices;
+    collectSubs(anObject, anEdgesAndVertices, GeomAPI_Shape::EDGE);
+    collectSubs(anObject, anEdgesAndVertices, GeomAPI_Shape::VERTEX);
+    for (ListOfShape::iterator aEIt = anEdgesAndVertices.begin();
+         aEIt != anEdgesAndVertices.end(); ++aEIt)
+      aFound->push_back(*aEIt);
+
+     if (anObject->isFace()) {
+       for (ListOfShape::iterator aEIt = anEdgesAndVertices.begin();
+          aEIt != anEdgesAndVertices.end(); ++aEIt) {
+         if ((*aEIt)->isEdge()) {
+           aMapEdgeFace[(*aEIt)] = anObject;
+         }
+       }
+     }
+   }
+
+   //bool isOption1 = true;
+   double aD1 = 0.0, aD2 = 0.0, aD = 0.0, anAngle = 0.0;
+   if (aCreationMethod->value() == CREATION_METHOD_DISTANCE_DISTANCE()) {
+     aD1 = real(FeaturesPlugin_Chamfer::D1_ID())->value();
+     aD2 = real(FeaturesPlugin_Chamfer::D2_ID())->value();
+   } else {
+     aD = real(FeaturesPlugin_Chamfer::D_ID())->value();
+     anAngle = real(FeaturesPlugin_Chamfer::ANGLE_ID())->value();
+   }
+
+   // Perform chamfer operation
+   GeomAlgoAPI_MakeShapeList aMakeShapeList;
+   std::shared_ptr<GeomAlgoAPI_Chamfer> aChamferBuilder;
+   int aResultIndex = 0;
+   std::string anError;
+
+
+   std::vector<FeaturesPlugin_Tools::ResultBaseAlgo> aResultBaseAlgoList;
+   ListOfShape anOriginalShapesList, aResultShapesList;
+
+   std::list<std::pair<GeomShapePtr, ListOfShape> >::iterator anIt = aSolidsAndSubs.begin();
+   for (; anIt != aSolidsAndSubs.end(); ++anIt) {
+     GeomShapePtr aSolid = anIt->first;
+     ListOfShape aFilletEdgesAndVertices = anIt->second;
+
+     ListOfShape aFilletEdges = selectEdges(aFilletEdgesAndVertices);
+     if (aCreationMethod->value() == CREATION_METHOD_DISTANCE_DISTANCE()) {
+       aChamferBuilder.reset(new GeomAlgoAPI_Chamfer(aSolid, aFilletEdges, aMapEdgeFace, true, aD1, aD2));
+     } else {
+       aChamferBuilder.reset(new GeomAlgoAPI_Chamfer(aSolid, aFilletEdges, aMapEdgeFace, false, aD, anAngle));
+     }
+
+     if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aChamferBuilder, getKind(), anError)) {
+       setError(anError);
+       return;
+     }
+
+    GeomShapePtr aResult = unwrapCompound(aChamferBuilder->shape());
+    std::shared_ptr<ModelAPI_ResultBody> aResultBody =
+        document()->createBody(data(), aResultIndex);
+
+    ListOfShape aBaseShapes;
+    aBaseShapes.push_back(aSolid);
+    FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, aBaseShapes, ListOfShape(),
+                                             aChamferBuilder, aResult, "Chamfer");
+
+    setResult(aResultBody, aResultIndex);
+    aResultIndex++;
+
+    FeaturesPlugin_Tools::ResultBaseAlgo aRBA;
+    aRBA.resultBody = aResultBody;
+    aRBA.baseShape = aSolid;
+    aRBA.makeShape = aChamferBuilder;
+    aResultBaseAlgoList.push_back(aRBA);
+    aResultShapesList.push_back(aResult);
+    anOriginalShapesList.push_back(aSolid);
+
+    const std::string aFilletFaceName = "Chamfer";
+    ListOfShape::iterator aSelectedBase = aFilletEdges.begin();
+    for(; aSelectedBase != aFilletEdges.end(); aSelectedBase++) {
+      GeomShapePtr aBase = *aSelectedBase;
+      // Store new faces generated from edges and vertices
+      aResultBody->loadGeneratedShapes(
+        aChamferBuilder, aBase, GeomAPI_Shape::EDGE, aFilletFaceName, true);
+    }
+  }
+
+  // Store deleted shapes after all results has been proceeded. This is to avoid issue when in one
+  // result shape has been deleted, but in another it was modified or stayed.
+  GeomShapePtr aResultShapesCompound = GeomAlgoAPI_CompoundBuilder::compound(aResultShapesList);
+  FeaturesPlugin_Tools::loadDeletedShapes(aResultBaseAlgoList,
+      anOriginalShapesList, aResultShapesCompound);
+
+  removeResults(aResultIndex);
+}
diff --git a/src/FeaturesPlugin/FeaturesPlugin_Chamfer.h b/src/FeaturesPlugin/FeaturesPlugin_Chamfer.h
new file mode 100644 (file)
index 0000000..cad7204
--- /dev/null
@@ -0,0 +1,123 @@
+// Copyright (C) 2017-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 FeaturesPlugin_Chamfer_H_
+#define FeaturesPlugin_Chamfer_H_
+
+#include "FeaturesPlugin.h"
+
+#include <GeomAPI_Shape.h>
+
+#include <ModelAPI_Feature.h>
+
+class GeomAlgoAPI_MakeShape;
+class GeomAPI_DataMapOfShapeMapOfShapes;
+
+/// \class FeaturesPlugin_Chamfer
+/// \ingroup Plugins
+/// \brief Feature for applying the Chamfer operations on Solids.
+///        Supports two distances chamfer and distance-angle chamfer.
+class FeaturesPlugin_Chamfer : public ModelAPI_Feature
+{
+public:
+  /// Feature kind.
+  inline static const std::string& ID()
+  {
+    static const std::string MY_ID("Chamfer");
+    return MY_ID;
+  }
+
+  /// \return the kind of a feature.
+  FEATURESPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = FeaturesPlugin_Chamfer::ID();
+    return MY_KIND;
+  }
+
+  inline static const std::string& CREATION_METHOD()
+  {
+    static std::string MY_CREATION_METHOD("creation_method");
+    return MY_CREATION_METHOD;
+  }
+
+  inline static const std::string CREATION_METHOD_DISTANCE_DISTANCE()
+  {
+    static std::string MY_SINGLE_RADIUS("distance_distance");
+    return MY_SINGLE_RADIUS;
+  }
+
+  inline static const std::string CREATION_METHOD_DISTANCE_ANGLE()
+  {
+    static std::string MY_VARYING_RADIUS("distance_angle");
+    return MY_VARYING_RADIUS;
+  }
+
+  /// Attribute name of main objects.
+  inline static const std::string& OBJECT_LIST_ID()
+  {
+    static const std::string MY_OBJECT_LIST_ID("main_objects");
+    return MY_OBJECT_LIST_ID;
+  }
+
+  /// Attribute name of D1.
+  inline static const std::string& D1_ID()
+  {
+    static const std::string MY_D1_ID("d1");
+    return MY_D1_ID;
+  }
+
+  /// Attribute name of D2.
+  inline static const std::string& D2_ID()
+  {
+    static const std::string MY_D2_ID("d2");
+    return MY_D2_ID;
+  }
+
+  /// Attribute name of D.
+  inline static const std::string& D_ID()
+  {
+    static const std::string MY_D_ID("d");
+    return MY_D_ID;
+  }
+
+  /// Attribute name of Angle.
+  inline static const std::string& ANGLE_ID()
+  {
+    static const std::string MY_ANGLE_ID("angle");
+    return MY_ANGLE_ID;
+  }
+
+  /// Creates a new part document if needed.
+  FEATURESPLUGIN_EXPORT virtual void execute();
+
+  /// Request for initialization of data model of the feature: adding all attributes.
+  FEATURESPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Use plugin manager for features creation.
+  FeaturesPlugin_Chamfer();
+
+private:
+  /// Load Naming data structure of the feature to the document
+  void loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> theResultBody,
+                    const std::shared_ptr<GeomAPI_Shape> theBaseShape,
+                    const std::shared_ptr<GeomAPI_Shape> theResultShape,
+                    const std::shared_ptr<GeomAlgoAPI_MakeShape>& theMakeShape);
+};
+
+#endif
index b9af9671352fd044aa1e628b1af8dad648aa5916..10368e91e643f8d0cac8bb6486611ee036cc5994 100644 (file)
@@ -173,8 +173,7 @@ void FeaturesPlugin_MultiTranslation::performOneDirection()
     } else {
       std::string anError;
       ListOfShape aListOfShape;
-      std::shared_ptr<GeomAlgoAPI_MakeShapeList>
-          aListOfTranslationAlgo(new GeomAlgoAPI_MakeShapeList);
+      ListOfMakeShape aMakeShapeList;
 
       for (int i=0; i<nbCopies; i++) {
         std::shared_ptr<GeomAlgoAPI_Translation> aTranslationAlgo(
@@ -194,8 +193,12 @@ void FeaturesPlugin_MultiTranslation::performOneDirection()
           break;
         }
         aListOfShape.push_back(aTranslationAlgo->shape());
-        aListOfTranslationAlgo->appendAlgo(aTranslationAlgo);
+        aMakeShapeList.push_back(aTranslationAlgo);
       }
+
+      std::shared_ptr<GeomAlgoAPI_MakeShapeList>
+          aListOfTranslationAlgo(new GeomAlgoAPI_MakeShapeList(aMakeShapeList));
+
       std::shared_ptr<GeomAPI_Shape> aCompound =
         GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
@@ -366,8 +369,7 @@ void FeaturesPlugin_MultiTranslation::performTwoDirection()
     } else {
       std::string anError;
       ListOfShape aListOfShape;
-      std::shared_ptr<GeomAlgoAPI_MakeShapeList>
-          aListOfTranslationAlgo(new GeomAlgoAPI_MakeShapeList);
+      ListOfMakeShape aMakeShapeList;
 
       for (int j=0; j<aSecondNbCopies; j++) {
         for (int i=0; i<aFirstNbCopies; i++) {
@@ -391,9 +393,13 @@ void FeaturesPlugin_MultiTranslation::performTwoDirection()
             break;
           }
           aListOfShape.push_back(aTranslationAlgo->shape());
-          aListOfTranslationAlgo->appendAlgo(aTranslationAlgo);
+          aMakeShapeList.push_back(aTranslationAlgo);
         }
       }
+
+      std::shared_ptr<GeomAlgoAPI_MakeShapeList>
+          aListOfTranslationAlgo(new GeomAlgoAPI_MakeShapeList(aMakeShapeList));
+
       std::shared_ptr<GeomAPI_Shape> aCompound =
         GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
index 87db42a877e209be75b8d0261aac0777cd56eb00..7973434462db3f8af12183e9c78748163ed714b5 100644 (file)
@@ -24,6 +24,7 @@
 #include <FeaturesPlugin_BooleanCommon.h>
 #include <FeaturesPlugin_BooleanSmash.h>
 #include <FeaturesPlugin_BooleanFill.h>
+#include <FeaturesPlugin_Chamfer.h>
 #include <FeaturesPlugin_Extrusion.h>
 #include <FeaturesPlugin_ExtrusionCut.h>
 #include <FeaturesPlugin_ExtrusionFuse.h>
@@ -176,6 +177,8 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(std::string theFeatureID)
     return FeaturePtr(new FeaturesPlugin_Measurement);
   } else if (theFeatureID == FeaturesPlugin_RemoveResults::ID()) {
     return FeaturePtr(new FeaturesPlugin_RemoveResults);
+  } else if (theFeatureID == FeaturesPlugin_Chamfer::ID()) {
+    return FeaturePtr(new FeaturesPlugin_Chamfer);
   }
 
   // feature of such kind is not found
diff --git a/src/FeaturesPlugin/Test/Test17261.py b/src/FeaturesPlugin/Test/Test17261.py
new file mode 100644 (file)
index 0000000..bb87495
--- /dev/null
@@ -0,0 +1,147 @@
+# Copyright (C) 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 salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0.5, 0, 0, 0)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchPoint_1.result())
+SketchLine_2 = Sketch_1.addLine(0, 37.39521866225591, 0, 40)
+SketchLine_3 = Sketch_1.addLine(0, 40, 0.5, 40)
+SketchLine_4 = Sketch_1.addLine(1, 40, 1, 0.5)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_2.result(), 2.604781337744086)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_3.result(), 0.5)
+SketchPoint_2 = Sketch_1.addPoint(0.5, 40)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchPoint_2.coordinates(), SketchLine_3.endPoint())
+SketchLine_5 = Sketch_1.addLine(1, 40, 0.5, 40)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.startPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_5.endPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_4.startPoint(), SketchLine_5.result())
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_5.endPoint())
+SketchPoint_3 = Sketch_1.addPoint(0, 36.39521866225591)
+SketchPoint_4 = Sketch_1.addPoint(0, 37.39521866225591)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchPoint_4.coordinates(), SketchPoint_3.coordinates(), 1)
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchPoint_4.coordinates(), SketchLine_2.startPoint())
+SketchLine_6 = Sketch_1.addLine(0, 36.39521866225591, 0, 37.39521866225591)
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchPoint_3.coordinates(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchLine_2.startPoint(), SketchLine_6.endPoint())
+SketchConstraintCoincidence_11 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_2.result())
+SketchLine_7 = Sketch_1.addLine(0, 0, 0, 36.39521866225591)
+SketchConstraintCoincidence_12 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_13 = Sketch_1.setCoincident(SketchPoint_3.coordinates(), SketchLine_7.endPoint())
+SketchConstraintCoincidence_14 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_6.result())
+SketchConstraintCoincidence_15 = Sketch_1.setCoincident(SketchLine_7.result(), SketchLine_1.endPoint())
+SketchLine_8 = Sketch_1.addLine(1, 0.5, 0.5, 0)
+SketchConstraintCoincidence_16 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_17 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_18 = Sketch_1.setCoincident(SketchLine_8.startPoint(), SketchLine_4.endPoint())
+SketchConstraintCoincidence_19 = Sketch_1.setCoincident(SketchLine_8.startPoint(), SketchLine_4.endPoint())
+SketchConstraintCoincidence_20 = Sketch_1.setCoincident(SketchLine_8.startPoint(), SketchLine_4.endPoint())
+SketchConstraintParallel_1 = Sketch_1.setParallel(SketchLine_7.result(), SketchLine_4.result())
+SketchConstraintParallel_2 = Sketch_1.setParallel(SketchLine_2.result(), SketchLine_6.result())
+SketchConstraintCoincidence_21 = Sketch_1.setCoincident(SketchLine_2.result(), SketchLine_6.endPoint())
+SketchConstraintCoincidence_22 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_6.result())
+SketchConstraintCoincidence_23 = Sketch_1.setCoincident(SketchLine_3.result(), SketchLine_2.endPoint())
+SketchConstraintCoincidence_24 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_3.result())
+SketchConstraintLength_3 = Sketch_1.setLength(SketchLine_1.result(), 0.5)
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_9 = SketchProjection_2.createdFeature()
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchLine_8.startPoint(), SketchLine_9.result(), 0.5, True)
+SketchConstraintCoincidence_25 = Sketch_1.setCoincident(SketchLine_4.result(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_26 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_8.result())
+SketchConstraintCoincidence_27 = Sketch_1.setCoincident(SketchLine_8.result(), SketchLine_8.startPoint())
+SketchConstraintParallel_3 = Sketch_1.setParallel(SketchLine_3.result(), SketchLine_5.result())
+SketchConstraintLength_4 = Sketch_1.setLength(SketchLine_5.result(), 0.5)
+SketchConstraintCoincidence_28 = Sketch_1.setCoincident(SketchLine_5.result(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_29 = Sketch_1.setCoincident(SketchLine_5.result(), SketchLine_3.endPoint())
+SketchConstraintLength_5 = Sketch_1.setLength(SketchLine_4.result(), 39.5)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1")], model.selection("EDGE", "Sketch_1/SketchLine_4"), 360, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Revolution_1_1/Generated_Face&Sketch_1/SketchLine_1"))
+SketchLine_10 = Sketch_2.addLine(1, 1, 1, -1)
+SketchProjection_3 = Sketch_2.addProjection(model.selection("EDGE", "[Revolution_1_1/Generated_Face&Sketch_1/SketchLine_7][Revolution_1_1/Generated_Face&Sketch_1/SketchLine_1]"), False)
+SketchCircle_1 = SketchProjection_3.createdFeature()
+SketchConstraintCoincidence_30 = Sketch_2.setCoincident(SketchLine_10.startPoint(), SketchCircle_1.results()[1])
+SketchConstraintCoincidence_31 = Sketch_2.setCoincident(SketchLine_10.endPoint(), SketchCircle_1.results()[1])
+SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_10.result())
+SketchConstraintCoincidence_32 = Sketch_2.setCoincident(SketchAPI_Circle(SketchCircle_1).center(), SketchLine_10.result())
+SketchLine_11 = Sketch_2.addLine(0, 0, 2, 0)
+SketchProjection_4 = Sketch_2.addProjection(model.selection("VERTEX", "[Revolution_1_1/Generated_Face&Sketch_1/SketchLine_7][Revolution_1_1/Generated_Face&Sketch_1/SketchLine_1]"), False)
+SketchPoint_5 = SketchProjection_4.createdFeature()
+SketchConstraintCoincidence_33 = Sketch_2.setCoincident(SketchLine_11.startPoint(), SketchPoint_5.result())
+SketchProjection_5 = Sketch_2.addProjection(model.selection("EDGE", "[Revolution_1_1/Generated_Face&Sketch_1/SketchLine_7][Revolution_1_1/Generated_Face&Sketch_1/SketchLine_1]"), False)
+SketchCircle_2 = SketchProjection_5.createdFeature()
+SketchConstraintCoincidence_34 = Sketch_2.setCoincident(SketchLine_11.endPoint(), SketchCircle_2.results()[1])
+SketchConstraintCoincidence_35 = Sketch_2.setCoincident(SketchAPI_Circle(SketchCircle_1).center(), SketchLine_11.result())
+SketchLine_12 = Sketch_2.addLine(1.25, 0, 1.176776695296637, 0.1767766952966369)
+SketchConstraintCoincidence_36 = Sketch_2.setCoincident(SketchLine_12.startPoint(), SketchLine_11.result())
+SketchLine_13 = Sketch_2.addLine(1.176776695296637, 0.1767766952966369, 1, 0.25)
+SketchConstraintCoincidence_37 = Sketch_2.setCoincident(SketchLine_12.endPoint(), SketchLine_13.startPoint())
+SketchConstraintCoincidence_38 = Sketch_2.setCoincident(SketchLine_13.endPoint(), SketchLine_10.result())
+SketchProjection_6 = Sketch_2.addProjection(model.selection("EDGE", "[Revolution_1_1/Generated_Face&Sketch_1/SketchLine_8][Revolution_1_1/Generated_Face&Sketch_1/SketchLine_1]"), True)
+SketchCircle_3 = SketchProjection_6.createdFeature()
+SketchLine_14 = Sketch_2.addLine(1.176776695296637, 0.1767766952966369, 1.738436468990353, 0.6743230541046004)
+SketchConstraintCoincidence_39 = Sketch_2.setCoincident(SketchLine_12.endPoint(), SketchLine_14.startPoint())
+SketchProjection_7 = Sketch_2.addProjection(model.selection("EDGE", "[Revolution_1_1/Generated_Face&Sketch_1/SketchLine_7][Revolution_1_1/Generated_Face&Sketch_1/SketchLine_1]"), False)
+SketchCircle_4 = SketchProjection_7.createdFeature()
+SketchConstraintCoincidence_40 = Sketch_2.setCoincident(SketchLine_14.endPoint(), SketchCircle_4.results()[1])
+SketchCircle_5 = Sketch_2.addCircle(1, 0, 0.25)
+SketchCircle_5.setAuxiliary(True)
+SketchConstraintCoincidence_41 = Sketch_2.setCoincident(SketchAPI_Circle(SketchCircle_1).center(), SketchCircle_5.center())
+SketchConstraintCoincidence_42 = Sketch_2.setCoincident(SketchLine_12.startPoint(), SketchCircle_5.results()[1])
+SketchConstraintCoincidence_43 = Sketch_2.setCoincident(SketchLine_12.endPoint(), SketchCircle_5.results()[1])
+SketchConstraintRadius_1 = Sketch_2.setRadius(SketchCircle_5.results()[1], 0.25)
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_13.result(), SketchLine_12.result())
+SketchConstraintCoincidence_44 = Sketch_2.setCoincident(SketchLine_13.endPoint(), SketchCircle_5.results()[1])
+SketchConstraintMirror_1_objects = [SketchLine_13.result(), SketchLine_12.result(), SketchLine_14.result()]
+SketchConstraintMirror_1 = Sketch_2.addMirror(SketchLine_10.result(), SketchConstraintMirror_1_objects)
+[SketchLine_15, SketchLine_16, SketchLine_17] = SketchConstraintMirror_1.mirrored()
+SketchConstraintMirror_2_objects = [SketchLine_14.result(), SketchLine_12.result(), SketchLine_13.result(), SketchLine_15.result(), SketchLine_16.result(), SketchLine_17.result()]
+SketchConstraintMirror_2 = Sketch_2.addMirror(SketchLine_11.result(), SketchConstraintMirror_2_objects)
+[SketchLine_18, SketchLine_19, SketchLine_20, SketchLine_21, SketchLine_22, SketchLine_23] = SketchConstraintMirror_2.mirrored()
+model.do()
+Edge_1_objects = [model.selection("EDGE", "Sketch_2/SketchLine_23"), model.selection("EDGE", "Sketch_2/SketchLine_21"), model.selection("EDGE", "Sketch_2/SketchLine_22"), model.selection("EDGE", "Sketch_2/SketchLine_10"), model.selection("EDGE", "Sketch_2/SketchLine_15"), model.selection("EDGE", "Sketch_2/SketchLine_16"), model.selection("EDGE", "Sketch_2/SketchLine_17"), model.selection("EDGE", "Sketch_2/SketchLine_11"), model.selection("EDGE", "Sketch_2/SketchLine_12"), model.selection("EDGE", "Sketch_2/SketchLine_20"), model.selection("EDGE", "Sketch_2/SketchLine_19"), model.selection("EDGE", "Sketch_2/SketchLine_18"), model.selection("EDGE", "Sketch_2/SketchLine_13"), model.selection("EDGE", "Sketch_2/SketchLine_14"), model.selection("EDGE", "Sketch_2/SketchProjection_6")]
+Edge_1 = model.addEdge(Part_1_doc, Edge_1_objects)
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "all-in-Edge_1")], model.selection("EDGE", "PartSet/OY"), model.selection("FACE", "Revolution_1_1/Generated_Face&Sketch_1/SketchLine_3"), 0, model.selection(), 0)
+model.end()
+
+from GeomAPI import *
+
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [15])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [15])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [102])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [204])
+model.testResultsVolumes(Extrusion_1, [466.947878])
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/Test17281.py b/src/FeaturesPlugin/Test/Test17281.py
new file mode 100644 (file)
index 0000000..0757422
--- /dev/null
@@ -0,0 +1,86 @@
+# Copyright (C) 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()
+Point_2 = model.addPoint(Part_1_doc, -106.704990237, 59.3180779141, 313.27249047)
+Point_2.setName("Point_30")
+Point_2.result().setName("Point_30")
+Point_3 = model.addPoint(Part_1_doc, -101.376950979, 62.2815769566, 321)
+Point_3.setName("Point_31")
+Point_3.result().setName("Point_31")
+Point_4 = model.addPoint(Part_1_doc, -100.200106232, 69.3301090863, 329.729339172)
+Point_4.setName("Point_32")
+Point_4.result().setName("Point_32")
+Point_5 = model.addPoint(Part_1_doc, -71.22799999999999, 49.284, 328.95)
+Point_5.setName("Point_33")
+Point_5.result().setName("Point_33")
+Point_6 = model.addPoint(Part_1_doc, -74.8174225795, 47.3826420932, 326)
+Point_6.setName("Point_34")
+Point_6.result().setName("Point_34")
+Point_7 = model.addPoint(Part_1_doc, -82.6510873528, 45.946338858, 320.314271667)
+Point_7.setName("Point_35")
+Point_7.result().setName("Point_35")
+Polyline_1_objects = [model.selection("VERTEX", "Point_30"), model.selection("VERTEX", "Point_31"), model.selection("VERTEX", "Point_32"), model.selection("VERTEX", "Point_33"), model.selection("VERTEX", "Point_34"), model.selection("VERTEX", "Point_35")]
+Polyline_1 = model.addPolyline3D(Part_1_doc, Polyline_1_objects, True)
+Polyline_1.setName("Polyline_8")
+Polyline_1.result().setName("Polyline_8_1")
+Polyline_2 = model.addPolyline3D(Part_1_doc, [model.selection("VERTEX", "Point_31"), model.selection("VERTEX", "Point_34")], False)
+Polyline_2.setName("Polyline_11")
+Polyline_2.result().setName("Polyline_11_1")
+Point_8 = model.addPoint(Part_1_doc, model.selection("EDGE", "Polyline_11_1/Generated_Edge&Point_31/Point_31"), 0.5, True, False)
+Point_8.setName("Point_36")
+Point_8.result().setName("Point_36")
+Scale_1 = model.addScale(Part_1_doc, [model.selection("WIRE", "Polyline_8_1")] , model.selection("VERTEX", "Point_36"), 1.05)
+Scale_1.setName("Scale_4")
+Scale_1.result().setName("Scale_4_1")
+Polyline_3 = model.addPolyline3D(Part_1_doc, [model.selection("VERTEX", "[Scale_4_1/ME:Scaled&Point_33/Point_33]e[Scale_4_1/ME:Scaled&Point_35/Point_35]e"), model.selection("VERTEX", "[Scale_4_1/ME:Scaled&Point_30/Point_30]e[Scale_4_1/ME:Scaled&Point_32/Point_32]e")], False)
+Polyline_3.setName("Polyline_10")
+Polyline_3.result().setName("Polyline_10_1")
+Recover_1 = model.addRecover(Part_1_doc, Polyline_3, [Scale_1.result()])
+Recover_1.setName("Recover_10")
+Recover_1.result().setName("Recover_10_1")
+Pipe_1 = model.addPipe(Part_1_doc, [model.selection("EDGE", "Recover_10_1/Modified_Edge&Point_31/Point_31"), model.selection("EDGE", "Polyline_10_1/Generated_Edge&weak_name_1")], model.selection("EDGE", "Recover_10_1/Modified_Edge&Point_33/Point_33"), [])
+Pipe_1.setName("Pipe_3")
+Pipe_1.result().setName("Pipe_3_1")
+Recover_2 = model.addRecover(Part_1_doc, Pipe_1, [Recover_1.result()])
+Recover_2.setName("Recover_11")
+Recover_2.result().setName("Recover_11_1")
+Pipe_2 = model.addPipe(Part_1_doc, [model.selection("EDGE", "Recover_11_1/Modified_Edge&Point_32/Point_32"), model.selection("EDGE", "Recover_11_1/Modified_Edge&Point_35/Point_35")], model.selection("EDGE", "Pipe_3_1/From_Edge_1"), [])
+Pipe_2.setName("Pipe_4")
+Pipe_2.result().setName("Pipe_4_1")
+model.end()
+
+assert(Pipe_2.feature().error() == "")
+
+from GeomAPI import *
+
+model.testNbResults(Pipe_2, 1)
+model.testNbSubResults(Pipe_2, [0])
+model.testNbSubShapes(Pipe_2, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Pipe_2, GeomAPI_Shape.FACE, [1])
+model.testNbSubShapes(Pipe_2, GeomAPI_Shape.EDGE, [4])
+model.testNbSubShapes(Pipe_2, GeomAPI_Shape.VERTEX, [8])
+model.testResultsVolumes(Pipe_2, [280.91366299542733])
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/Test2971.py b/src/FeaturesPlugin/Test/Test2971.py
new file mode 100644 (file)
index 0000000..4116aec
--- /dev/null
@@ -0,0 +1,422 @@
+# Copyright (C) 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 salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+toto=model.addParameter(Part_1_doc, "r_fond_ext", "1950")
+model.addParameter(Part_1_doc, "r_fond_int", "1724")
+model.addParameter(Part_1_doc, "r_fillet_38", "38")
+model.addParameter(Part_1_doc, "r_fillet_40", "40")
+model.addParameter(Part_1_doc, "ep_fond", "170")
+model.addParameter(Part_1_doc, "ep_support", "254")
+model.addParameter(Part_1_doc, "dist_1", "89.6")
+model.addParameter(Part_1_doc, "ep_homo", "603.4")
+model.addParameter(Part_1_doc, "ep_virole", "98.6")
+model.addParameter(Part_1_doc, "h_virole", "1720")
+model.addParameter(Part_1_doc, "r_ext_virole", "1897")
+model.addParameter(Part_1_doc, "dist_cer_1", "3")
+model.addParameter(Part_1_doc, "dist_cer_2", "55")
+model.addParameter(Part_1_doc, "r_homo", "1653")
+model.addParameter(Part_1_doc, "half_pp", "30")
+model.addParameter(Part_1_doc, "pitch", "27.43")
+model.addParameter(Part_1_doc, "rue_eau", "150")
+model.addParameter(Part_1_doc, "dist_rue", "rue_eau/2 - pitch/2")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_1 = Sketch_1.addLine(1897, 693, 1897, 2413)
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), "h_virole")
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_1.result())
+SketchLine_2 = Sketch_1.addLine(1897, 2413, 1798.4, 2413)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_2.result())
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), "ep_virole")
+SketchLine_3 = Sketch_1.addLine(1798.4, 2413, 1798.4, 641.4)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.endPoint(), "r_ext_virole")
+SketchLine_4 = Sketch_1.addLine(1760.4, 603.4, 1653, 603.4)
+SketchLine_5 = Sketch_1.addLine(1653, 603.4, 1653, 0)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_1.addLine(1653, 0, 1683.450919985492, 0)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_3.result())
+SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_5.result())
+SketchConstraintLength_3 = Sketch_1.setLength(SketchLine_5.result(), "ep_homo")
+SketchArc_1 = Sketch_1.addArc(1760.4, 641.4, 1760.4, 603.4, 1798.4, 641.4, False)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_3.endPoint())
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchArc_1.results()[1], SketchLine_3.result())
+SketchConstraintTangent_2 = Sketch_1.setTangent(SketchArc_1.results()[1], SketchLine_4.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_4.result())
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_5.startPoint(), SketchLine_1.startPoint(), "dist_1 ")
+SketchLine_7 = Sketch_1.addLine(1897, 693, 1897, -214)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_7.startPoint())
+SketchLine_8 = Sketch_1.addLine(1937, -254, 2151, -254)
+SketchLine_9 = Sketch_1.addLine(2151, -254, 2151, -508)
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchLine_10 = Sketch_1.addLine(2151, -508, 1892.243906054397, -508)
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint())
+SketchConstraintParallel_1 = Sketch_1.setParallel(SketchLine_10.result(), SketchLine_8.result())
+SketchConstraintLength_4 = Sketch_1.setLength(SketchLine_9.result(), "ep_support")
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_8.result())
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_11 = SketchProjection_2.createdFeature()
+SketchArc_2 = Sketch_1.addArc(0, 3, 1723.437877704862, -41.02137767220898, 0, -1721, True)
+SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchLine_11.result(), SketchArc_2.center())
+SketchLine_12 = Sketch_1.addLine(0, -1721, 0, -1891)
+SketchConstraintCoincidence_11 = Sketch_1.setCoincident(SketchArc_2.endPoint(), SketchLine_12.startPoint())
+SketchConstraintVertical_4 = Sketch_1.setVertical(SketchLine_12.result())
+SketchConstraintDistanceVertical_2 = Sketch_1.setVerticalDistance(SketchArc_2.center(), SketchAPI_Line(SketchLine_11).startPoint(), "dist_cer_1")
+SketchConstraintLength_5 = Sketch_1.setLength(SketchLine_12.result(), "ep_fond")
+SketchArc_3 = Sketch_1.addArc(1683.450919985492, -40, 1723.437877704862, -41.02137767220898, 1683.450919985492, 0, False)
+SketchConstraintCoincidence_12 = Sketch_1.setCoincident(SketchArc_3.startPoint(), SketchArc_2.startPoint())
+SketchConstraintCoincidence_13 = Sketch_1.setCoincident(SketchArc_3.endPoint(), SketchLine_6.endPoint())
+SketchConstraintTangent_3 = Sketch_1.setTangent(SketchArc_3.results()[1], SketchLine_6.result())
+SketchConstraintTangent_4 = Sketch_1.setTangent(SketchArc_3.results()[1], SketchArc_2.results()[1])
+SketchArc_4 = Sketch_1.addArc(1937, -214, 1897, -214, 1937, -254, False)
+SketchConstraintCoincidence_14 = Sketch_1.setCoincident(SketchArc_4.startPoint(), SketchLine_7.endPoint())
+SketchConstraintCoincidence_15 = Sketch_1.setCoincident(SketchArc_4.endPoint(), SketchLine_8.startPoint())
+SketchConstraintTangent_5 = Sketch_1.setTangent(SketchArc_4.results()[1], SketchLine_7.result())
+SketchConstraintTangent_6 = Sketch_1.setTangent(SketchArc_4.results()[1], SketchLine_8.result())
+SketchConstraintHorizontal_4 = Sketch_1.setHorizontal(SketchLine_6.result())
+SketchArc_5 = Sketch_1.addArc(0, 55, 0, -1891, 1854.132246315134, -535.8549848942598, False)
+SketchConstraintCoincidence_16 = Sketch_1.setCoincident(SketchLine_11.result(), SketchArc_5.center())
+SketchConstraintCoincidence_17 = Sketch_1.setCoincident(SketchLine_12.endPoint(), SketchArc_5.startPoint())
+SketchConstraintDistanceVertical_3 = Sketch_1.setVerticalDistance(SketchArc_5.center(), SketchAPI_Line(SketchLine_11).startPoint(), "dist_cer_2")
+SketchArc_6 = Sketch_1.addArc(1892.243906054397, -548, 1892.243906054397, -508, 1854.132246315134, -535.8549848942598, False)
+SketchConstraintCoincidence_18 = Sketch_1.setCoincident(SketchArc_6.startPoint(), SketchLine_10.endPoint())
+SketchConstraintCoincidence_19 = Sketch_1.setCoincident(SketchArc_6.endPoint(), SketchArc_5.endPoint())
+SketchConstraintTangent_7 = Sketch_1.setTangent(SketchArc_6.results()[1], SketchLine_10.result())
+SketchConstraintTangent_8 = Sketch_1.setTangent(SketchArc_6.results()[1], SketchArc_5.results()[1])
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_6.results()[1], "r_fillet_40")
+SketchConstraintRadius_2 = Sketch_1.setRadius(SketchArc_4.results()[1], "r_fillet_40")
+SketchConstraintRadius_3 = Sketch_1.setRadius(SketchArc_3.results()[1], "r_fillet_40")
+SketchConstraintRadius_4 = Sketch_1.setRadius(SketchArc_1.results()[1], "r_fillet_38")
+SketchConstraintRadius_5 = Sketch_1.setRadius(SketchArc_2.results()[1], "r_fond_int")
+SketchConstraintVertical_5 = Sketch_1.setVertical(SketchLine_7.result())
+SketchConstraintVertical_6 = Sketch_1.setVertical(SketchLine_9.result())
+SketchConstraintDistanceHorizontal_2 = Sketch_1.setHorizontalDistance(SketchLine_12.startPoint(), SketchLine_7.startPoint(), "r_ext_virole")
+SketchConstraintDistanceHorizontal_3 = Sketch_1.setHorizontalDistance(SketchAPI_Line(SketchLine_11).startPoint(), SketchLine_6.startPoint(), "r_homo")
+SketchConstraintDistanceVertical_4 = Sketch_1.setVerticalDistance(SketchAPI_Line(SketchLine_11).startPoint(), SketchLine_5.startPoint(), "ep_homo")
+SketchConstraintDistanceHorizontal_4 = Sketch_1.setHorizontalDistance(SketchArc_4.startPoint(), SketchLine_9.startPoint(), "ep_support")
+SketchConstraintDistanceVertical_5 = Sketch_1.setVerticalDistance(SketchAPI_Line(SketchLine_11).startPoint(), SketchLine_9.startPoint(), "ep_support")
+SketchLine_13 = Sketch_1.addLine(1723.437877704863, -41.02137767220899, 1897, -41.02137767220221)
+SketchLine_13.setName("SketchLine_23")
+SketchLine_13.result().setName("SketchLine_23")
+SketchConstraintCoincidence_20 = Sketch_1.setCoincident(SketchArc_2.startPoint(), SketchLine_13.startPoint())
+SketchConstraintCoincidence_21 = Sketch_1.setCoincident(SketchLine_13.endPoint(), SketchLine_7.result())
+SketchConstraintHorizontal_5 = Sketch_1.setHorizontal(SketchLine_13.result())
+SketchLine_14 = Sketch_1.addLine(1897, 693, 1798.4, 693)
+SketchLine_14.setName("SketchLine_24")
+SketchLine_14.result().setName("SketchLine_24")
+SketchConstraintCoincidence_22 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_14.startPoint())
+SketchConstraintCoincidence_23 = Sketch_1.setCoincident(SketchLine_14.endPoint(), SketchLine_3.result())
+SketchConstraintHorizontal_6 = Sketch_1.setHorizontal(SketchLine_14.result())
+model.do()
+Sketch_1.setName("GVProfile")
+Sketch_1.result().setName("GVProfile")
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("COMPOUND", "all-in-GVProfile")], model.selection("EDGE", "PartSet/OZ"), 180, 0)
+Revolution_1.setName("GVBody")
+Revolution_1.result().setName("Revolution_1_1")
+Revolution_1.result().subResult(0).setName("GVBody_1_1")
+Revolution_1.result().subResult(1).setName("GVBody_1_2")
+Revolution_1.result().subResult(2).setName("GVBody_1_3")
+Sketch_2 = model.addSketch(Part_1_doc, model.standardPlane("XOZ"))
+SketchProjection_3 = Sketch_2.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_2 = SketchProjection_3.createdFeature()
+SketchProjection_4 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_15 = SketchProjection_4.createdFeature()
+SketchLine_15.setName("SketchLine_14")
+SketchLine_15.result().setName("SketchLine_14")
+SketchLine_16 = Sketch_2.addLine(30, -40, 30, -1806)
+SketchLine_16.setName("SketchLine_15")
+SketchLine_16.result().setName("SketchLine_15")
+SketchLine_17 = Sketch_2.addLine(30, -1806, 0, -1806)
+SketchLine_17.setName("SketchLine_16")
+SketchLine_17.result().setName("SketchLine_16")
+SketchConstraintCoincidence_24 = Sketch_2.setCoincident(SketchLine_16.endPoint(), SketchLine_17.startPoint())
+SketchLine_18 = Sketch_2.addLine(0, 0, 70, 0)
+SketchLine_18.setName("SketchLine_18")
+SketchLine_18.result().setName("SketchLine_18")
+SketchConstraintCoincidence_25 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_18.startPoint())
+SketchArc_7 = Sketch_2.addArc(70, -40, 70, 0, 30, -40, False)
+SketchConstraintCoincidence_26 = Sketch_2.setCoincident(SketchLine_18.endPoint(), SketchArc_7.startPoint())
+SketchConstraintTangent_9 = Sketch_2.setTangent(SketchLine_18.result(), SketchArc_7.results()[1])
+SketchConstraintCoincidence_27 = Sketch_2.setCoincident(SketchLine_16.result(), SketchArc_7.endPoint())
+SketchConstraintRadius_6 = Sketch_2.setRadius(SketchArc_7.results()[1], "r_fillet_40")
+SketchConstraintHorizontal_7 = Sketch_2.setHorizontal(SketchLine_18.result())
+SketchConstraintVertical_7 = Sketch_2.setVertical(SketchLine_16.result())
+SketchConstraintCoincidence_28 = Sketch_2.setCoincident(SketchLine_16.startPoint(), SketchArc_7.endPoint())
+SketchConstraintDistanceHorizontal_5 = Sketch_2.setHorizontalDistance(SketchLine_18.startPoint(), SketchLine_16.startPoint(), "half_pp")
+SketchConstraintHorizontal_8 = Sketch_2.setHorizontal(SketchLine_17.result())
+SketchConstraintTangent_10 = Sketch_2.setTangent(SketchArc_7.results()[1], SketchLine_16.result())
+SketchProjection_5 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchProjection_5.setName("SketchProjection_6")
+SketchProjection_5.result().setName("SketchProjection_6")
+SketchLine_19 = SketchProjection_5.createdFeature()
+SketchLine_19.setName("SketchLine_19")
+SketchLine_19.result().setName("SketchLine_19")
+SketchProjection_6 = Sketch_2.addProjection(model.selection("EDGE", "[GVBody_1_3/From_Face][GVBody_1_3/To_Face]"), False)
+SketchProjection_6.setName("SketchProjection_7")
+SketchProjection_6.result().setName("SketchProjection_7")
+SketchLine_20 = SketchProjection_6.createdFeature()
+SketchLine_20.setName("SketchLine_25")
+SketchLine_20.result().setName("SketchLine_25")
+SketchConstraintMiddle_1 = Sketch_2.setMiddlePoint(SketchLine_20.result(), SketchLine_17.endPoint())
+SketchProjection_7 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchProjection_7.setName("SketchProjection_8")
+SketchProjection_7.result().setName("SketchProjection_8")
+SketchLine_21 = SketchProjection_7.createdFeature()
+SketchLine_21.setName("SketchLine_21")
+SketchLine_21.result().setName("SketchLine_21")
+SketchConstraintMirror_1_objects = [SketchLine_18.result(), SketchArc_7.results()[1], SketchLine_16.result(), SketchLine_17.result()]
+SketchConstraintMirror_1 = Sketch_2.addMirror(SketchLine_21.result(), SketchConstraintMirror_1_objects)
+[SketchLine_22, SketchArc_8, SketchLine_23, SketchLine_24] = SketchConstraintMirror_1.mirrored()
+SketchLine_24.setName("SketchLine_27")
+SketchLine_24.result().setName("SketchLine_27")
+SketchLine_23.setName("SketchLine_26")
+SketchLine_23.result().setName("SketchLine_26")
+SketchLine_22.setName("SketchLine_22")
+SketchLine_22.result().setName("SketchLine_22")
+model.do()
+Sketch_2.setName("PPProfile")
+Sketch_2.result().setName("PPProfile")
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "all-in-PPProfile")], model.selection(), 0, 2300)
+Cut_1 = model.addCut(Part_1_doc, [model.selection("COMPOUND", "all-in-Extrusion_1")], [model.selection("COMPSOLID", "Revolution_1_1")])
+Recover_1 = model.addRecover(Part_1_doc, Cut_1, [Revolution_1.result()])
+Remove_SubShapes_1 = model.addRemoveSubShapes(Part_1_doc, model.selection("COMPOUND", "Cut_1_1"))
+Remove_SubShapes_1.setSubShapesToRemove([model.selection("SOLID", "Cut_1_1_2")])
+Sketch_3 = model.addSketch(Part_1_doc, model.standardPlane("XOY"))
+SketchLine_25 = Sketch_3.addLine(0, 0, 0, 1653)
+SketchLine_25.setName("SketchLine_28")
+SketchLine_25.result().setName("SketchLine_28")
+SketchProjection_8 = Sketch_3.addProjection(model.selection("VERTEX", "[Recover_1_1_2/Modified_Face&GVProfile/SketchLine_6][Recover_1_1_2/Modified_Face&GVProfile/SketchArc_3_2]__cc"), False)
+SketchProjection_8.setName("SketchProjection_9")
+SketchProjection_8.result().setName("SketchProjection_9")
+SketchPoint_3 = SketchProjection_8.createdFeature()
+SketchConstraintCoincidence_29 = Sketch_3.setCoincident(SketchLine_25.startPoint(), SketchPoint_3.result())
+SketchProjection_9 = Sketch_3.addProjection(model.selection("VERTEX", "[(Remove_SubShapes_1_1/Modified_Face&PPProfile/SketchArc_7_2)(Remove_SubShapes_1_1/Modified_Face&Extrusion_1_1/To_Face)(Remove_SubShapes_1_1/Modified_Face&GVProfile/SketchLine_6&PPProfile/SketchLine_18)][Remove_SubShapes_1_1/Modified_Face&GVProfile/SketchLine_6&PPProfile/SketchLine_18][Remove_SubShapes_1_1/Modified_Face&GVProfile/SketchLine_6&PPProfile/SketchLine_22][(Remove_SubShapes_1_1/Modified_Face&Extrusion_1_1/To_Face)(Remove_SubShapes_1_1/Modified_Face&GVProfile/SketchLine_6&PPProfile/SketchLine_22)(Remove_SubShapes_1_1/Modified_Face&PPProfile/SketchArc_8_2)]"), False)
+SketchProjection_9.setName("SketchProjection_10")
+SketchProjection_9.result().setName("SketchProjection_10")
+SketchPoint_4 = SketchProjection_9.createdFeature()
+SketchConstraintCoincidence_30 = Sketch_3.setCoincident(SketchLine_25.endPoint(), SketchPoint_4.result())
+SketchLine_26 = Sketch_3.addLine(0, 0, -1653, 0)
+SketchLine_26.setName("SketchLine_29")
+SketchLine_26.result().setName("SketchLine_29")
+SketchConstraintCoincidence_31 = Sketch_3.setCoincident(SketchLine_25.startPoint(), SketchLine_26.startPoint())
+SketchProjection_10 = Sketch_3.addProjection(model.selection("VERTEX", "Recover_1_1_2/Modified_Vertex&weak_name_8"), False)
+SketchProjection_10.setName("SketchProjection_11")
+SketchProjection_10.result().setName("SketchProjection_11")
+SketchPoint_5 = SketchProjection_10.createdFeature()
+SketchConstraintCoincidence_32 = Sketch_3.setCoincident(SketchLine_26.endPoint(), SketchPoint_5.result())
+SketchArc_9 = Sketch_3.addArc(0, 0, -1653, 0, 0, 1653, True)
+SketchConstraintCoincidence_33 = Sketch_3.setCoincident(SketchLine_25.startPoint(), SketchArc_9.center())
+SketchConstraintCoincidence_34 = Sketch_3.setCoincident(SketchLine_26.endPoint(), SketchArc_9.startPoint())
+SketchConstraintCoincidence_35 = Sketch_3.setCoincident(SketchLine_25.result(), SketchArc_9.endPoint())
+SketchLine_27 = Sketch_3.addLine(-75, 0, -75, 1651.297671529879)
+SketchLine_27.setName("SketchLine_30")
+SketchLine_27.result().setName("SketchLine_30")
+SketchConstraintCoincidence_36 = Sketch_3.setCoincident(SketchLine_27.startPoint(), SketchLine_26.result())
+SketchConstraintCoincidence_37 = Sketch_3.setCoincident(SketchLine_27.endPoint(), SketchArc_9.results()[1])
+SketchConstraintVertical_8 = Sketch_3.setVertical(SketchLine_27.result())
+SketchConstraintDistanceHorizontal_6 = Sketch_3.setHorizontalDistance(SketchLine_27.startPoint(), SketchArc_9.center(), "rue_eau/2")
+SketchLine_28 = Sketch_3.addLine(-75, 0, -1205.745800334843, 1130.745800334845)
+SketchLine_28.setName("SketchLine_31")
+SketchLine_28.result().setName("SketchLine_31")
+SketchLine_28.setAuxiliary(True)
+SketchConstraintCoincidence_38 = Sketch_3.setCoincident(SketchLine_27.startPoint(), SketchLine_28.startPoint())
+SketchConstraintCoincidence_39 = Sketch_3.setCoincident(SketchLine_28.endPoint(), SketchArc_9.results()[1])
+SketchConstraintAngle_1 = Sketch_3.setAngle(SketchLine_28.result(), SketchLine_26.result(), 45)
+SketchLine_29 = Sketch_3.addLine(-743.85, 0, -743.85, 825.6488357649396)
+SketchLine_29.setName("SketchLine_32")
+SketchLine_29.result().setName("SketchLine_32")
+SketchConstraintCoincidence_40 = Sketch_3.setCoincident(SketchLine_29.startPoint(), SketchLine_26.result())
+SketchLine_30 = Sketch_3.addLine(-743.85, 825.6488357649396, -75, 825.6488357649395)
+SketchLine_30.setName("SketchLine_33")
+SketchLine_30.result().setName("SketchLine_33")
+SketchConstraintCoincidence_41 = Sketch_3.setCoincident(SketchLine_29.endPoint(), SketchLine_30.startPoint())
+SketchConstraintCoincidence_42 = Sketch_3.setCoincident(SketchLine_30.endPoint(), SketchLine_27.result())
+SketchLine_31 = Sketch_3.addLine(-743.85, 825.6488357649396, -1127.232311682702, 1209.031147447615)
+SketchLine_31.setName("SketchLine_34")
+SketchLine_31.result().setName("SketchLine_34")
+SketchConstraintCoincidence_43 = Sketch_3.setCoincident(SketchLine_29.endPoint(), SketchLine_31.startPoint())
+SketchConstraintCoincidence_44 = Sketch_3.setCoincident(SketchLine_31.endPoint(), SketchArc_9.results()[1])
+SketchConstraintParallel_2 = Sketch_3.setParallel(SketchLine_31.result(), SketchLine_28.result())
+SketchConstraintMiddle_2 = Sketch_3.setMiddlePoint(SketchLine_30.endPoint(), SketchLine_27.result())
+SketchConstraintHorizontal_9 = Sketch_3.setHorizontal(SketchLine_30.result())
+SketchConstraintVertical_9 = Sketch_3.setVertical(SketchLine_29.result())
+SketchConstraintDistanceHorizontal_7 = Sketch_3.setHorizontalDistance(SketchLine_25.startPoint(), SketchLine_29.startPoint(), "r_homo*0.5*0.9")
+SketchProjection_11 = Sketch_3.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchProjection_11.setName("SketchProjection_12")
+SketchProjection_11.result().setName("SketchProjection_12")
+SketchLine_32 = SketchProjection_11.createdFeature()
+SketchLine_32.setName("SketchLine_35")
+SketchLine_32.result().setName("SketchLine_35")
+SketchConstraintMirror_2_objects = [SketchLine_26.result(), SketchLine_29.result(), SketchArc_9.results()[1], SketchLine_31.result(), SketchLine_30.result(), SketchLine_27.result()]
+SketchConstraintMirror_2 = Sketch_3.addMirror(SketchLine_32.result(), SketchConstraintMirror_2_objects)
+[SketchLine_33, SketchLine_34, SketchArc_10, SketchLine_35, SketchLine_36, SketchLine_37] = SketchConstraintMirror_2.mirrored()
+SketchLine_37.setName("SketchLine_40")
+SketchLine_37.result().setName("SketchLine_40")
+SketchLine_36.setName("SketchLine_39")
+SketchLine_36.result().setName("SketchLine_39")
+SketchLine_35.setName("SketchLine_38")
+SketchLine_35.result().setName("SketchLine_38")
+SketchLine_34.setName("SketchLine_37")
+SketchLine_34.result().setName("SketchLine_37")
+SketchLine_33.setName("SketchLine_36")
+SketchLine_33.result().setName("SketchLine_36")
+model.do()
+Sketch_3.setName("PHomoProfile")
+Sketch_3.result().setName("PHomoProfile")
+Sketch_3.changeFacesOrder([[SketchLine_25.result(), SketchArc_9.results()[1], SketchLine_27.result(), SketchLine_27.result(), SketchLine_26.result()],
+                           [SketchLine_29.result(), SketchLine_31.result(), SketchArc_9.results()[1], SketchLine_26.result()],
+                           [SketchLine_27.result(), SketchLine_30.result(), SketchLine_29.result(), SketchLine_26.result()],
+                           [SketchArc_9.results()[1], SketchLine_31.result(), SketchLine_30.result(), SketchLine_27.result()],
+                           [SketchLine_33.result(), SketchLine_37.result(), SketchLine_37.result(), SketchArc_10.results()[1], SketchLine_25.result()],
+                           [SketchLine_33.result(), SketchArc_10.results()[1], SketchLine_35.result(), SketchLine_34.result()],
+                           [SketchLine_33.result(), SketchLine_34.result(), SketchLine_36.result(), SketchLine_37.result()],
+                           [SketchArc_10.results()[1], SketchLine_37.result(), SketchLine_36.result(), SketchLine_35.result()]
+                          ])
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "all-in-PHomoProfile")], model.selection(), "ep_homo", 0)
+Partition_1_objects = [model.selection("SOLID", "Remove_SubShapes_1_1"), model.selection("COMPSOLID", "Recover_1_1"), model.selection("COMPSOLID", "Extrusion_2_1")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Partition_1_1_2")])
+Group_1.setName("virole")
+Group_1.result().setName("virole")
+Group_2 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Partition_1_1_4")])
+Group_2.setName("bol")
+Group_2.result().setName("bol")
+Group_3 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Partition_1_1_1")])
+Group_3.setName("pp")
+Group_3.result().setName("pp")
+Group_4_objects = [model.selection("SOLID", "Partition_1_1_6"),
+                   model.selection("SOLID", "Partition_1_1_8"),
+                   model.selection("SOLID", "Partition_1_1_7"),
+                   model.selection("SOLID", "Partition_1_1_12"),
+                   model.selection("SOLID", "Partition_1_1_11"),
+                   model.selection("SOLID", "Partition_1_1_10")]
+Group_4 = model.addGroup(Part_1_doc, Group_4_objects)
+Group_4.setName("pt")
+Group_4.result().setName("pt")
+Group_5 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Partition_1_1_3")])
+Group_5.setName("pt_virole")
+Group_5.result().setName("pt_virole")
+Group_6 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Partition_1_1_9"), model.selection("SOLID", "Partition_1_1_5")])
+Group_6.setName("axe_eau")
+Group_6.result().setName("axe_eau")
+Group_7_objects = [model.selection("FACE", "Partition_1_1_3/Modified_Face&GVProfile/SketchLine_4"),
+                   model.selection("FACE", "Recover_1_1_2/Modified_Face&GVProfile/SketchArc_1_2"),
+                   model.selection("FACE", "Recover_1_1_2/Modified_Face&GVProfile/SketchLine_3"),
+                   model.selection("FACE", "Recover_1_1_1/Modified_Face&GVProfile/SketchLine_3"),
+                   model.selection("FACE", "Extrusion_2_1_1/To_Face"),
+                   model.selection("FACE", "Extrusion_2_1_5/To_Face")]
+Group_7 = model.addGroup(Part_1_doc, Group_7_objects)
+Group_7.setName("faces_sec")
+Group_7.result().setName("faces_sec")
+Group_8_objects = [model.selection("FACE", "(Partition_1_1_4/Modified_Face&GVProfile/SketchLine_23)(Partition_1_1_4/Modified_Face&GVBody_1_3/To_Face)(Recover_1_1_3/Modified_Face&GVProfile/SketchArc_5_2)2(Recover_1_1_3/Modified_Face&GVProfile/SketchArc_6_2)2(Recover_1_1_3/Modified_Face&GVProfile/SketchLine_10)2(Recover_1_1_3/Modified_Face&GVProfile/SketchLine_9)2(Recover_1_1_3/Modified_Face&GVProfile/SketchLine_8)2(Recover_1_1_3/Modified_Face&GVProfile/SketchArc_4_2)2(Recover_1_1_3/Modified_Face&GVProfile/SketchLine_7)2(Partition_1_1_4/Modified_Face&GVBody_1_3/From_Face)2"),
+                   model.selection("FACE", "(Partition_1_1_3/Modified_Face&GVProfile/SketchLine_23)(Partition_1_1_3/Modified_Face&GVBody_1_2/To_Face)(Recover_1_1_2/Modified_Face&GVProfile/SketchLine_3)2(Recover_1_1_2/Modified_Face&GVProfile/SketchArc_1_2)2(Partition_1_1_3/Modified_Face&GVProfile/SketchLine_4)2(Partition_1_1_3/Modified_Face&GVProfile/SketchLine_6&PPProfile/SketchLine_18)2(Partition_1_1_3/Modified_Face&GVProfile/SketchLine_6&PPProfile/SketchLine_22)2(Recover_1_1_2/Modified_Face&GVProfile/SketchLine_7)2(Recover_1_1_2/Modified_Face&GVProfile/SketchLine_24)2(Partition_1_1_3/Modified_Face&GVBody_1_2/From_Face)2"),
+                   model.selection("FACE", "(Partition_1_1_3/Modified_Face&GVProfile/SketchLine_6&PPProfile/SketchLine_22)(Partition_1_1_3/Modified_Face&GVBody_1_2/To_Face)"),
+                   model.selection("FACE", "Remove_SubShapes_1_1/Modified_Face&PPProfile/SketchLine_26"),
+                   model.selection("FACE", "Remove_SubShapes_1_1/Modified_Face&PPProfile/SketchArc_8_2"),
+                   model.selection("FACE", "(Partition_1_1_5/Modified_Face&PHomoProfile/SketchArc_9_2&GVProfile/SketchLine_5)(Extrusion_2_1_4/Generated_Face&PHomoProfile/SketchLine_30)(Extrusion_2_1_3/Generated_Face&PHomoProfile/SketchLine_30)(Partition_1_1_5/Modified_Face&PHomoProfile/SketchLine_29)(Partition_1_1_5/Modified_Face&Extrusion_2_1_1/From_Face&PPProfile/SketchLine_22)"),
+                   model.selection("FACE", "Remove_SubShapes_1_1/Modified_Face&PPProfile/SketchLine_15"),
+                   model.selection("FACE", "Remove_SubShapes_1_1/Modified_Face&PPProfile/SketchArc_7_2"),
+                   model.selection("FACE", "(Partition_1_1_9/Modified_Face&PHomoProfile/SketchLine_36)(Extrusion_2_1_7/Generated_Face&PHomoProfile/SketchLine_40)(Extrusion_2_1_8/Generated_Face&PHomoProfile/SketchLine_40)(Partition_1_1_9/Modified_Face&PHomoProfile/SketchArc_10_2&GVProfile/SketchLine_5)(Partition_1_1_9/Modified_Face&Extrusion_2_1_5/From_Face&PPProfile/SketchLine_18)"),
+                   model.selection("FACE", "(Partition_1_1_4/Modified_Face&GVProfile/SketchLine_23)(Partition_1_1_4/Modified_Face&GVBody_1_3/From_Face)(Recover_1_1_3/Modified_Face&GVProfile/SketchArc_5_2)2(Recover_1_1_3/Modified_Face&GVProfile/SketchArc_6_2)2(Recover_1_1_3/Modified_Face&GVProfile/SketchLine_10)2(Recover_1_1_3/Modified_Face&GVProfile/SketchLine_9)2(Recover_1_1_3/Modified_Face&GVProfile/SketchLine_8)2(Recover_1_1_3/Modified_Face&GVProfile/SketchArc_4_2)2(Recover_1_1_3/Modified_Face&GVProfile/SketchLine_7)2(Partition_1_1_4/Modified_Face&GVBody_1_3/To_Face)2"),
+                   model.selection("FACE", "(Partition_1_1_3/Modified_Face&GVProfile/SketchLine_23)(Partition_1_1_3/Modified_Face&GVBody_1_2/From_Face)(Recover_1_1_2/Modified_Face&GVProfile/SketchLine_3)2(Recover_1_1_2/Modified_Face&GVProfile/SketchArc_1_2)2(Partition_1_1_3/Modified_Face&GVProfile/SketchLine_4)2(Partition_1_1_3/Modified_Face&GVProfile/SketchLine_6&PPProfile/SketchLine_18)2(Partition_1_1_3/Modified_Face&GVProfile/SketchLine_6&PPProfile/SketchLine_22)2(Recover_1_1_2/Modified_Face&GVProfile/SketchLine_7)2(Recover_1_1_2/Modified_Face&GVProfile/SketchLine_24)2(Partition_1_1_3/Modified_Face&GVBody_1_2/To_Face)2"),
+                   model.selection("FACE", "(Partition_1_1_3/Modified_Face&GVProfile/SketchLine_6&PPProfile/SketchLine_18)(Partition_1_1_3/Modified_Face&GVBody_1_2/From_Face)")]
+Group_8 = model.addGroup(Part_1_doc, Group_8_objects)
+Group_8.setName("faces_pr")
+Group_8.result().setName("faces_pr")
+Group_9_objects = [model.selection("FACE", "Partition_1_1_6/Modified_Face&PHomoProfile/SketchLine_29"),
+                   model.selection("FACE", "Extrusion_2_1_3/Generated_Face&PHomoProfile/SketchLine_29"),
+                   model.selection("FACE", "Extrusion_2_1_7/Generated_Face&PHomoProfile/SketchLine_36"),
+                   model.selection("FACE", "Partition_1_1_10/Modified_Face&PHomoProfile/SketchLine_36")]
+Group_9 = model.addGroup(Part_1_doc, Group_9_objects)
+Group_9.setName("pt_symz")
+Group_9.result().setName("pt_symz")
+Group_10_objects = [model.selection("FACE", "Recover_1_1_1/Modified_Face&GVBody_1_1/To_Face"),
+                    model.selection("FACE", "Recover_1_1_1/Modified_Face&GVBody_1_1/From_Face"),
+                    model.selection("FACE", "Partition_1_1_3/Modified_Face&GVBody_1_2/From_Face"),
+                    model.selection("FACE", "Partition_1_1_10/Modified_Face&PHomoProfile/SketchLine_36"),
+                    model.selection("FACE", "Extrusion_2_1_7/Generated_Face&PHomoProfile/SketchLine_36"),
+                    model.selection("FACE", "Extrusion_2_1_3/Generated_Face&PHomoProfile/SketchLine_29"),
+                    model.selection("FACE", "Partition_1_1_6/Modified_Face&PHomoProfile/SketchLine_29"),
+                    model.selection("FACE", "Partition_1_1_3/Modified_Face&GVBody_1_2/To_Face"),
+                    model.selection("FACE", "Partition_1_1_5/Modified_Face&PHomoProfile/SketchLine_29"),
+                    model.selection("FACE", "Partition_1_1_9/Modified_Face&PHomoProfile/SketchLine_36"),
+                    model.selection("FACE", "Partition_1_1_1/Modified_Face&Extrusion_1_1/To_Face"),
+                    model.selection("FACE", "Partition_1_1_4/Modified_Face&GVBody_1_3/From_Face"),
+                    model.selection("FACE", "Partition_1_1_4/Modified_Face&GVBody_1_3/To_Face")]
+Group_10 = model.addGroup(Part_1_doc, Group_10_objects)
+Group_10.setName("symz")
+Group_10.result().setName("symz")
+Group_11 = model.addGroup(Part_1_doc, [model.selection("FACE", "Recover_1_1_3/Modified_Face&GVProfile/SketchLine_10")])
+Group_11.setName("appui")
+Group_11.result().setName("appui")
+Group_12 = model.addGroup(Part_1_doc, [model.selection("FACE", "Recover_1_1_1/Modified_Face&GVProfile/SketchLine_2")])
+Group_12.setName("sup")
+Group_12.result().setName("sup")
+Group_13_objects = [model.selection("FACE", "Partition_1_1_6/Modified_Face&Extrusion_2_1_2/To_Face"),
+                    model.selection("FACE", "Extrusion_2_1_4/To_Face"),
+                    model.selection("FACE", "Extrusion_2_1_3/To_Face"),
+                    model.selection("FACE", "Extrusion_2_1_8/To_Face"),
+                    model.selection("FACE", "Extrusion_2_1_7/To_Face"),
+                    model.selection("FACE", "Partition_1_1_10/Modified_Face&Extrusion_2_1_6/To_Face")]
+Group_13 = model.addGroup(Part_1_doc, Group_13_objects)
+Group_13.setName("pt_sec")
+Group_13.result().setName("pt_sec")
+Group_14_objects = [model.selection("FACE", "Partition_1_1_6/Modified_Face&Extrusion_2_1_2/From_Face"),
+                    model.selection("FACE", "Extrusion_2_1_3/From_Face"),
+                    model.selection("FACE", "Extrusion_2_1_4/From_Face"),
+                    model.selection("FACE", "Extrusion_2_1_7/From_Face"),
+                    model.selection("FACE", "Extrusion_2_1_8/From_Face"),
+                    model.selection("FACE", "Partition_1_1_10/Modified_Face&Extrusion_2_1_6/From_Face")]
+Group_14 = model.addGroup(Part_1_doc, Group_14_objects)
+Group_14.setName("pt_pr")
+Group_14.result().setName("pt_pr")
+Group_15 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "Recover_1_1_3/Modified_Vertex&weak_name_9")])
+Group_15.setName("NO_DX")
+Group_15.result().setName("NO_DX")
+model.end()
+
+from ModelAPI import *
+
+aFactory = ModelAPI_Session.get().validators()
+
+# Check groups
+for i in range(Part_1_doc.size("Groups")):
+  GroupFeature = Part_1_doc.feature(objectToResult(Part_1_doc.object("Groups", i)))
+  assert(aFactory.validate(GroupFeature))
+
+model.begin()
+toto.setValue(2000)
+model.end()
+
+# Check groups again
+for i in range(Part_1_doc.size("Groups")):
+  GroupFeature = Part_1_doc.feature(objectToResult(Part_1_doc.object("Groups", i)))
+  assert(aFactory.validate(GroupFeature))
diff --git a/src/FeaturesPlugin/Test/TestChamfer.py b/src/FeaturesPlugin/Test/TestChamfer.py
new file mode 100644 (file)
index 0000000..6138921
--- /dev/null
@@ -0,0 +1,134 @@
+# Copyright (C) 2017-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
+#
+
+"""
+      TestChamfer.py
+      Unit test of FeaturesPlugin_Chamfer class
+"""
+
+from ModelAPI import *
+from GeomDataAPI import *
+
+__updated__ = "2017-11-30"
+
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+aSession = ModelAPI_Session.get()
+aDocument = aSession.moduleDocument()
+# Create a part for extrusion
+aSession.startOperation()
+aPartFeature = aDocument.addFeature("Part")
+aSession.finishOperation()
+aPart = aSession.activeDocument()
+
+# Create a box and a cylinder for filleting
+aSession.startOperation()
+aBox = aPart.addFeature("Box")
+aBox.string("CreationMethod").setValue("BoxByDimensions")
+aBox.real("dx").setValue(10)
+aBox.real("dy").setValue(10)
+aBox.real("dz").setValue(10)
+aSession.finishOperation()
+
+# a point to anchor a cylinder
+aSession.startOperation()
+aPoint = aPart.addFeature("Point")
+aPoint.string("creation_method").setValue("by_xyz")
+geomDataAPI_Point(aPoint.attribute("point3d")).setValue(20, 5, 0)
+aSession.finishOperation()
+
+aSession.startOperation()
+aCylinder = aPart.addFeature("Cylinder")
+aCylinder.string("CreationMethod").setValue("Cylinder")
+aCylinder.selection("base_point").selectSubShape("vertex", "Point_1")
+aCylinder.selection("axis").selectSubShape("edge", "PartSet/OZ")
+aCylinder.real("radius").setValue(5)
+aCylinder.real("height").setValue(10)
+aSession.finishOperation()
+
+#=========================================================================
+# Test 1. Create chamfer with two distances
+#=========================================================================
+aSession.startOperation()
+aChamfer1 = aPart.addFeature("Chamfer")
+aChamfer1.string("creation_method").setValue("distance_distance")
+anObjects = aChamfer1.selectionList("main_objects")
+anObjects.append("[Box_1_1/Left][Box_1_1/Top]", "edge")
+aChamfer1.real("d1").setValue(1.5)
+aChamfer1.real("d2").setValue(2)
+aSession.finishOperation()
+assert(aChamfer1.error() == ""), "FAILED: Chamfer reports error \"{}\"".format(aChamfer1.error())
+
+#=========================================================================
+# Test 2. Change chamfer type
+#=========================================================================
+aSession.startOperation()
+aChamfer1.string("creation_method").setValue("distance_angle")
+aChamfer1.real("d").setValue(1)
+aChamfer1.real("angle").setValue(30)
+aSession.finishOperation()
+assert(aChamfer1.error() == ""), "FAILED: Chamfer reports error \"{}\"".format(aChamfer1.error())
+
+##=========================================================================
+## Test 3. Check chamfer reports error if selected entities from different solids
+##=========================================================================
+aSession.startOperation()
+aChamfer2 = aPart.addFeature("Chamfer")
+aChamfer2.string("creation_method").setValue("distance_distance")
+anObjects = aChamfer2.selectionList("main_objects")
+anObjects.append("Box_1_1/Bottom", "face")
+aChamfer2.real("d1").setValue(-2)
+aChamfer2.real("d2").setValue(2)
+aSession.finishOperation()
+assert(aChamfer2.error() != ""), "FAILED: Chamfer does not report error"
+
+##=========================================================================
+## Test 4. Fix the error
+##=========================================================================
+aSession.startOperation()
+aChamfer2.real("d1").setValue(1)
+aSession.finishOperation()
+assert(aChamfer2.error() == ""), "FAILED: Chamfer reports error \"{}\"".format(aChamfer2.error())
+
+#=========================================================================
+# Test 5. Check chamfer reports error on smoothly connected edges
+#=========================================================================
+aSession.startOperation()
+aChamfer3 = aPart.addFeature("Chamfer")
+aChamfer3.string("creation_method").setValue("distance_distance")
+aChamfer3.selectionList("main_objects").append("Cylinder_1_1/Modified_Face_1", "face")
+aChamfer3.real("d1").setValue(1)
+aChamfer3.real("d2").setValue(1)
+aSession.finishOperation()
+assert(aChamfer3.lastResult() is None), "FAILED: Chamfer chamfer not produce a result"
+
+#=========================================================================
+# Test 6. Remove last fillet feature
+#=========================================================================
+aSession.startOperation()
+aPart.removeFeature(aChamfer3)
+aSession.finishOperation()
+
+#=========================================================================
+# End of test
+#=========================================================================
+
+from salome.shaper import model
+assert(model.checkPythonDump())
index 987dadc3a7b5b85850edfd23d795a17500f9e853..9198588ce6e52e1984601736e259c76d2334942c 100644 (file)
@@ -7,7 +7,7 @@
         label="Objects"
         icon=""
         tooltip="Select objects"
-        type_choice="vertices edges wires faces shells solids compsolids compounds"
+        shape_types="vertices edges wires faces shells solids compsolids compounds"
         use_choice="false"
         concealment="true">
         <validator id="FeaturesPlugin_ValidatorBooleanCommonSelection"/>
@@ -20,7 +20,7 @@
         label="Main objects"
         icon=""
         tooltip="Select objects"
-        type_choice="vertices edges wires faces shells solids compsolids compounds"
+        shape_types="vertices edges wires faces shells solids compsolids compounds"
         use_choice="false"
         concealment="true">
         <validator id="PartSet_DifferentObjects"/>
@@ -30,7 +30,7 @@
         label="Tool objects"
         icon=""
         tooltip="Select tools"
-        type_choice="vertices edges wires faces shells solids compsolids compounds"
+        shape_types="vertices edges wires faces shells solids compsolids compounds"
         use_choice="false"
         concealment="true" >
         <validator id="PartSet_DifferentObjects"/>
index cf622baf62ce668b36b2bed244554ebb8cbda7e2..8617460db436c417b70d714f97e6c2ee231be99a 100644 (file)
@@ -7,7 +7,7 @@
         label="Objects"
         icon=""
         tooltip="Select objects"
-        type_choice="vertices edges wires faces shells solids compsolids compounds"
+        shape_types="vertices edges wires faces shells solids compsolids compounds"
         use_choice="false"
         concealment="true">
         <validator id="FeaturesPlugin_ValidatorBooleanFuseSelection"/>
@@ -20,7 +20,7 @@
         label="Main objects"
         icon=""
         tooltip="Select objects"
-        type_choice="vertices edges wires faces shells solids compsolids compounds"
+        shape_types="vertices edges wires faces shells solids compsolids compounds"
         use_choice="false"
         concealment="true">
         <validator id="PartSet_DifferentObjects"/>
@@ -30,7 +30,7 @@
         label="Tool objects"
         icon=""
         tooltip="Select tools"
-        type_choice="vertices edges wires faces shells solids compsolids compounds"
+        shape_types="vertices edges wires faces shells solids compsolids compounds"
         use_choice="false"
         concealment="true" >
         <validator id="PartSet_DifferentObjects"/>
index 227fd02d87c4c95b1cf0ed6afd7cb34d2ef38ced..07abf751d819cab11ba71ce0276c778be356793e 100644 (file)
@@ -3,7 +3,7 @@
     label="Main objects"
     icon=""
     tooltip="Select objects"
-    type_choice="faces solids compsolids"
+    shape_types="faces solids compsolids"
     use_choice="false"
     concealment="true">
     <validator id="PartSet_DifferentObjects"/>
@@ -13,7 +13,7 @@
     label="Tool objects"
     icon=""
     tooltip="Select tools"
-    type_choice="faces solids compsolids"
+    shape_types="faces solids compsolids"
     use_choice="false"
     concealment="true" >
     <validator id="PartSet_DifferentObjects"/>
index 0b0281098a7c2f4e9999ed5772dad72c3ead9424..2131c8dda7e2e6ed0f978be6b6771082decae8f9 100644 (file)
@@ -3,7 +3,7 @@
     label="Main objects"
     icon=""
     tooltip="Select objects"
-    type_choice="vertices edges wires faces shells solids compsolids compounds"
+    shape_types="vertices edges wires faces shells solids compsolids compounds"
     use_choice="false"
     concealment="true">
     <validator id="PartSet_DifferentObjects"/>
@@ -13,7 +13,7 @@
     label="Tool objects"
     icon=""
     tooltip="Select tools"
-    type_choice="vertices edges wires faces shells solids compsolids compounds"
+    shape_types="vertices edges wires faces shells solids compsolids compounds"
     use_choice="false"
     concealment="true" >
     <validator id="PartSet_DifferentObjects"/>
index 9ea5db5d13a5081b944b3fde8d73f46bbc25b2e8..dca9d22a906ef1ca8133c66aba4441940638d82a 100644 (file)
@@ -3,7 +3,7 @@
     label="Main objects"
     icon=""
     tooltip="Select objects"
-    type_choice="vertices edges wires faces shells solids compsolids compounds"
+    shape_types="vertices edges wires faces shells solids compsolids compounds"
     use_choice="false"
     concealment="true">
     <validator id="PartSet_DifferentObjects"/>
@@ -13,7 +13,7 @@
     label="Tool objects"
     icon=""
     tooltip="Select tools"
-    type_choice="vertices edges wires faces shells solids compsolids compounds"
+    shape_types="vertices edges wires faces shells solids compsolids compounds"
     use_choice="false"
     concealment="true" >
     <validator id="PartSet_DifferentObjects"/>
diff --git a/src/FeaturesPlugin/chamfer_widget.xml b/src/FeaturesPlugin/chamfer_widget.xml
new file mode 100644 (file)
index 0000000..ae881d5
--- /dev/null
@@ -0,0 +1,63 @@
+<source>
+  <toolbox id="creation_method">
+    <box id="distance_distance"
+         title="Two distances"
+         tooltip="Chamfer with two distances"
+         icon="icons/Features/chamfer_distances.png">
+      <multi_selector id="main_objects"
+                      label="Faces or/and edges"
+                      icon=""
+                      tooltip="Select objects"
+                      shape_types="edges faces"
+                      use_choice="false"
+                      concealment="true">
+        <validator id="PartSet_DifferentObjects"/>
+        <validator id="FeaturesPlugin_ValidatorFilletSelection"/>
+      </multi_selector>
+      <doublevalue id="d1"
+                   label="D1"
+                   tooltip="First distance."
+                   min="0"
+                   default="2">
+        <validator id="GeomValidators_Positive"/>
+      </doublevalue>
+      <doublevalue id="d2"
+                   label="D2"
+                   tooltip="Second distance."
+                   min="0"
+                   default="2">
+        <validator id="GeomValidators_Positive"/>
+      </doublevalue>
+    </box>
+    <box id="distance_angle"
+         title="Distance and angle"
+         tooltip="Chamfer with a distance and an angle"
+         icon="icons/Features/chamfer_dist_angle.png">
+      <multi_selector id="main_objects"
+                      label="Faces or/and edges"
+                      icon=""
+                      tooltip="Select objects"
+                      shape_types="edges faces"
+                      use_choice="false"
+                      concealment="true">
+        <validator id="PartSet_DifferentObjects"/>
+        <validator id="FeaturesPlugin_ValidatorFilletSelection"/>
+      </multi_selector>
+      <doublevalue id="d"
+                   label="D"
+                   tooltip="Distance."
+                   min="0"
+                   default="2">
+        <validator id="GeomValidators_Positive"/>
+      </doublevalue>
+      <doublevalue id="angle"
+                   label="Angle"
+                   tooltip="Angle."
+                   min="0"
+                   max="90"
+                   default="25">
+        <validator id="GeomValidators_Positive"/>
+      </doublevalue>
+    </box>
+  </toolbox>
+</source>
index 4200c3f2a816b478282e25ea0d2122e63544975f..f701574c7a0d137ee74088fce0e64a379b6e8a8f 100644 (file)
@@ -11,11 +11,12 @@ Features plug-in provides a set of common topological operations. It implements
    :maxdepth: 1
 
    angularCopyFeature.rst
+   chamferFeature.rst
    commonFeature.rst
    cutFeature.rst
    extrusionCutFeature.rst
    extrusionFeature.rst
-   extrusionFuseFeature.
+   extrusionFuseFeature.rst
    filletFeature.rst
    fuseFeature.rst
    fuseFeatureFaces.rst
@@ -31,7 +32,7 @@ Features plug-in provides a set of common topological operations. It implements
    revolutionFeature.rst
    revolutionFuseFeature.rst
    rotationFeature.rst
-   smashFeature.rstrst
+   smashFeature.rst
    splitFeature.rst
    symmetryFeature.rst
    transformationFeature.rst
diff --git a/src/FeaturesPlugin/doc/TUI_chamferDistAngle.rst b/src/FeaturesPlugin/doc/TUI_chamferDistAngle.rst
new file mode 100644 (file)
index 0000000..db62e1d
--- /dev/null
@@ -0,0 +1,12 @@
+
+  .. _tui_create_chamfer2:
+
+Create Chamfer by a distance and an angle
+=========================================
+
+.. literalinclude:: examples/chamfer2.py 
+    :linenos:
+    :language: python
+
+:download:`Download this script <examples/chamfer2.py >` 
+   
diff --git a/src/FeaturesPlugin/doc/TUI_chamferDistances.rst b/src/FeaturesPlugin/doc/TUI_chamferDistances.rst
new file mode 100644 (file)
index 0000000..b9786ab
--- /dev/null
@@ -0,0 +1,12 @@
+
+  .. _tui_create_chamfer1:
+
+Create Chamfer by distances
+===========================
+
+.. literalinclude:: examples/chamfer1.py 
+    :linenos:
+    :language: python
+
+:download:`Download this script <examples/chamfer1.py >` 
+   
diff --git a/src/FeaturesPlugin/doc/chamferFeature.rst b/src/FeaturesPlugin/doc/chamferFeature.rst
new file mode 100644 (file)
index 0000000..dae55df
--- /dev/null
@@ -0,0 +1,105 @@
+.. |chamfer.icon|    image:: images/chamfer.png
+
+.. _featureChamfer:
+
+Chamfer
+======
+
+**Chamfer** feature creates chamfers on the edges or on the faces of a shape. 
+
+To create a Chamfer in the active part:
+
+#. select in the Main Menu *Feature - > Chamfer* item  or
+#. click |chamfer.icon| **Chamfer** button in the toolbar
+
+There are 2 types of chamfer:
+
+  .. image:: images/chamfer_distances.png   
+    :align: left
+  chamfer by two distances
+
+  .. image:: images/chamfer_dist_angle.png   
+    :align: left
+  chamfer by a distance and an angle
+
+Chamfer by two distances
+------------------------
+
+The  property panel is shown below.
+
+.. image:: images/ChamferDistances.png
+  :align: center
+
+.. centered::
+  Chamfer by two distances property panel
+
+Input fields:
+
+- **Faces or/and edges** panel contains chamfered faces and edges. All edges of a face are subject to chamfer operation. Faces and edges are selected in 3D OCC viewer;
+- **D1** define the first chamfer distance;
+- **D2** define the second chamfer distance;
+
+**TUI Command**:
+
+.. py:function:: model.addChamfer(Part_doc, [face,edge], perfomDistances, D1, D2)
+
+    :param part: The current part object.
+    :param list: A list of faces and edges subject to fillet operation in format *model.selection(TYPE, shape)*.
+    :param boolean: A "True" flag to indicate that the type of chamfer is by two distances. 
+    :param number: D1 value.
+    :param number: D2 value.
+    :return: Created object.
+
+Result
+""""""
+
+Result of **Chamfer by two distances** is shown below.
+
+.. image:: images/chamfer_res_distances.png
+   :align: center
+
+.. centered::
+   Chamfer by two distances
+
+**See Also** a sample TUI Script of :ref:`tui_create_chamfer1` operation.
+
+Chamfer by a distance and an angle
+----------------------------------
+
+Alternatively, there is a possibility to create a chamfer with a distance and an angle.
+
+.. image:: images/ChamferDistAngle.png
+  :align: center
+
+.. centered::
+  Chamfer by a distance and an angle
+
+Input fields:
+
+- **Faces or/and edges** panel contains filleted faces and edges. All edges of a face are subject to fillet operation. Faces and edges are selected in 3D OCC viewer;
+- **D** defines the chamfer distance;  
+- **Angle** defines the chamfer angle.
+
+**TUI Command**:
+
+.. py:function:: model.addChamfer(Part_doc, [face,edge], perfomDistances, D, Angle)
+
+    :param part: The current part object.
+    :param list: A list of faces and edges subject to fillet operation in format *model.selection(TYPE, shape)*.
+    :param boolean: A "False" flag to indicate that the type of chamfer is by a distance and an angle.
+    :param number: D value.
+    :param number: Angle value.
+    :return: Created object.
+
+Result
+""""""
+
+Result of **Chamfer by a distance and an angle** is shown below.
+
+.. image:: images/chamfer_res_dist_angle.png
+   :align: center
+
+.. centered::
+   Chamfer by a distance and an angle
+
+**See Also** a sample TUI Script of :ref:`tui_create_chamfer2` operation.
diff --git a/src/FeaturesPlugin/doc/examples/chamfer1.py b/src/FeaturesPlugin/doc/examples/chamfer1.py
new file mode 100644 (file)
index 0000000..ed603f6
--- /dev/null
@@ -0,0 +1,10 @@
+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, 20, 20, 20)
+Chamfer_1 = model.addChamfer(Part_1_doc, [model.selection("FACE", "Box_1_1/Top")], True, 2, 2)
+model.do()
+model.end()
diff --git a/src/FeaturesPlugin/doc/examples/chamfer2.py b/src/FeaturesPlugin/doc/examples/chamfer2.py
new file mode 100644 (file)
index 0000000..387b60c
--- /dev/null
@@ -0,0 +1,11 @@
+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, 20, 20, 20)
+Chamfer_1_objects = [model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Top]")]
+Chamfer_1 = model.addChamfer(Part_1_doc, Chamfer_1_objects, False, 2, 25)
+model.do()
+model.end()
diff --git a/src/FeaturesPlugin/doc/images/ChamferDistAngle.png b/src/FeaturesPlugin/doc/images/ChamferDistAngle.png
new file mode 100644 (file)
index 0000000..444034c
Binary files /dev/null and b/src/FeaturesPlugin/doc/images/ChamferDistAngle.png differ
diff --git a/src/FeaturesPlugin/doc/images/ChamferDistances.png b/src/FeaturesPlugin/doc/images/ChamferDistances.png
new file mode 100644 (file)
index 0000000..3bd9f06
Binary files /dev/null and b/src/FeaturesPlugin/doc/images/ChamferDistances.png differ
diff --git a/src/FeaturesPlugin/doc/images/chamfer.png b/src/FeaturesPlugin/doc/images/chamfer.png
new file mode 100644 (file)
index 0000000..3fcc3a4
Binary files /dev/null and b/src/FeaturesPlugin/doc/images/chamfer.png differ
diff --git a/src/FeaturesPlugin/doc/images/chamfer_dist_angle.png b/src/FeaturesPlugin/doc/images/chamfer_dist_angle.png
new file mode 100644 (file)
index 0000000..7ba6e83
Binary files /dev/null and b/src/FeaturesPlugin/doc/images/chamfer_dist_angle.png differ
diff --git a/src/FeaturesPlugin/doc/images/chamfer_distances.png b/src/FeaturesPlugin/doc/images/chamfer_distances.png
new file mode 100644 (file)
index 0000000..2e67ab1
Binary files /dev/null and b/src/FeaturesPlugin/doc/images/chamfer_distances.png differ
diff --git a/src/FeaturesPlugin/doc/images/chamfer_res_dist_angle.png b/src/FeaturesPlugin/doc/images/chamfer_res_dist_angle.png
new file mode 100644 (file)
index 0000000..9d4d8f5
Binary files /dev/null and b/src/FeaturesPlugin/doc/images/chamfer_res_dist_angle.png differ
diff --git a/src/FeaturesPlugin/doc/images/chamfer_res_distances.png b/src/FeaturesPlugin/doc/images/chamfer_res_distances.png
new file mode 100644 (file)
index 0000000..0b6c648
Binary files /dev/null and b/src/FeaturesPlugin/doc/images/chamfer_res_distances.png differ
index 77e543915373c4d303ddaa44148bc339ade4304f..9ea0416c129bde364bfbfe83da2669b62beabb9a 100644 (file)
@@ -11,7 +11,7 @@
   <multi_selector id="base"
                   label="Base objects:"
                   tooltip="Select a base objects"
-                  type_choice="vertices edges wires faces shells compounds"
+                  shape_types="vertices edges wires faces shells compounds"
                   concealment="true">
     <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell,compound"/>
   </multi_selector>
index e0c30ab3e43dee8fe1d53bbedd02117d05a6d367..96079ccbd281a6b1de39bc7de8417fa733c58224 100644 (file)
@@ -13,7 +13,7 @@
       label="Select a sketch face"
       icon="icons/Features/sketch.png"
       tooltip="Select a sketch face"
-      type_choice="wires faces shells"
+      shape_types="wires faces shells"
       concealment="true">
       <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="face,shell"/>
     </multi_selector>
@@ -89,7 +89,7 @@
     label="Cut from:"
     icon="icons/Features/cut_shape.png"
     tooltip="Objects to Cut"
-    type_choice="Objects"
+    shape_types="Objects"
     use_choice="false"
     concealment="true"
     main_argument="true">
index 932f7d8a1a3077d20947ea2dac580f9997acfb00..80082d14ec637dc2c0b1ccebc6d0c205ef33dea1 100644 (file)
@@ -13,7 +13,7 @@
       label="Select a sketch face"
       icon="icons/Features/sketch.png"
       tooltip="Select a sketch face"
-      type_choice="vertices edges wires faces shells compounds"
+      shape_types="vertices edges wires faces shells compounds"
       concealment="true">
       <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell,compound"/>
     </multi_selector>
@@ -89,7 +89,7 @@
     label="Fuse with:"
     icon="icons/Features/cut_shape.png"
     tooltip="Objects to Fuse"
-    type_choice="Objects"
+    shape_types="Objects"
     use_choice="false"
     concealment="true"
     main_argument="true">
index 898173efb0e273c43c1de1c60c895b8ca5d4c6e0..7abb4a5dfab0e5ebe2363695ad3f13707ddc9c36 100644 (file)
@@ -8,7 +8,7 @@
                       label="Faces or/and edges"
                       icon=""
                       tooltip="Select objects"
-                      type_choice="edges faces"
+                      shape_types="edges faces"
                       use_choice="false"
                       concealment="true">
         <validator id="PartSet_DifferentObjects"/>
@@ -30,7 +30,7 @@
                       label="Faces or/and edges"
                       icon=""
                       tooltip="Select objects"
-                      type_choice="edges faces"
+                      shape_types="edges faces"
                       use_choice="false"
                       concealment="true">
         <validator id="PartSet_DifferentObjects"/>
diff --git a/src/FeaturesPlugin/icons/chamfer.png b/src/FeaturesPlugin/icons/chamfer.png
new file mode 100644 (file)
index 0000000..3fcc3a4
Binary files /dev/null and b/src/FeaturesPlugin/icons/chamfer.png differ
diff --git a/src/FeaturesPlugin/icons/chamfer_dist_angle.png b/src/FeaturesPlugin/icons/chamfer_dist_angle.png
new file mode 100644 (file)
index 0000000..8f3610e
Binary files /dev/null and b/src/FeaturesPlugin/icons/chamfer_dist_angle.png differ
diff --git a/src/FeaturesPlugin/icons/chamfer_distances.png b/src/FeaturesPlugin/icons/chamfer_distances.png
new file mode 100644 (file)
index 0000000..e40a9c5
Binary files /dev/null and b/src/FeaturesPlugin/icons/chamfer_distances.png differ
index 167080c6efe9d481d23a18e8b095054e1402e24d..5f09fb238a73758d5fa9c8f5981f0038351fd435 100644 (file)
@@ -3,7 +3,7 @@
     label="Objects"
     icon="icons/Features/cut_shape.png"
     tooltip="Select objects(compounds, compsolids, solids, shells, faces or edges)"
-    type_choice="edges faces shells solids compsolids compounds"
+    shape_types="edges faces shells solids compsolids compounds"
     use_choice="false"
     concealment="true">
     <validator id="PartSet_DifferentObjects"/>
index a14b35035d8a4ae6c74e5b159c772c4fa67ff43d..8fce3fb33eb620316064e33386edb7c1594f38ae 100644 (file)
@@ -3,7 +3,7 @@
                   label="Main objects"
                   icon=""
                   tooltip="Select objects"
-                  type_choice="objects"
+                  shape_types="objects"
                   concealment="true">
     <validator id="FeaturesPlugin_ValidatorTransform"/>
   </multi_selector>
index b7cf37cb0059e40a91d4aed1d07e1951d53f41ed..6589394089fef32c524943d7216587e19d30df5a 100644 (file)
@@ -3,7 +3,7 @@
                   label="Main objects"
                   icon=""
                   tooltip="Select objects"
-                  type_choice="objects"
+                  shape_types="objects"
                   concealment="true">
     <validator id="FeaturesPlugin_ValidatorTransform"/>
   </multi_selector>
index a0d358bd187b2eb09b24f62baaabdfe9dd048fa0..ad5e97ef545f4fdd06c5ec8c5a428ca1f2992a03 100644 (file)
@@ -2,7 +2,7 @@
   <multi_selector id="base_objects"
     label="Base objects:"
     tooltip="Select objects for partitioning."
-    type_choice="objects"
+    shape_types="objects"
     concealment="true"
     clear_in_neutral_point="false">
     <validator id="FeaturesPlugin_ValidatorPartitionSelection" parameters="Plane"/>
index 11a967d03fc33b59e4ae85c5dd602cc3e704e15b..6211dbc25a09b5c6472494c8c89f30dfa49f49cb 100644 (file)
@@ -2,7 +2,7 @@
   <multi_selector id="base_objects"
                   label="Base objects:"
                   tooltip="Select a base objects"
-                  type_choice="vertices edges wires faces shells compsolids"
+                  shape_types="vertices edges wires faces shells compsolids"
                   use_choice="false"
                   concealment="true">
     <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell,compound"/>
@@ -27,7 +27,7 @@
       <multi_selector id="locations_objects"
                       label="Locations:"
                       tooltip="Select one or more vertices to specify the locations"
-                      type_choice="vertex">
+                      shape_types="vertex">
         <validator id="FeaturesPlugin_ValidatorPipeLocations"/>
       </multi_selector>
     </box>
index b62c06dba3bc48c0098fd721aab5f937e96b3403..5f277ff3691c04e68b773b660bf99245b89fc960 100644 (file)
@@ -3,7 +3,7 @@
     label="Select objects to move"
     icon="icons/Features/cut_shape.png"
     tooltip="Select objects"
-    type_choice="objects"
+    shape_types="objects"
     concealment="true" >
     <validator id="FeaturesPlugin_ValidatorTransform"/>
   </multi_selector>
index cec9dd59eb2e649e62b660fa9a38f15c078c09af..8577aa6ee16e06b579843999b700f75372058de7 100644 (file)
                icon="icons/Features/fillet.png" auto_preview="true" helpfile="filletFeature.html">
         <source path="fillet_widget.xml"/>
       </feature>
+      <feature id="Chamfer" title="Chamfer" tooltip="Perform chamfer on face or edge"
+               icon="icons/Features/chamfer.png" auto_preview="true" helpfile="chamferFeature.html">
+        <source path="chamfer_widget.xml"/>
+      </feature>
       <feature id="FusionFaces" title="Fuse Faces" tooltip="Performs fusion of connected faces"
                icon="icons/Features/fusion_faces.png" auto_preview="true" helpfile="FeaturesPlugin/fusionFacesFeature.html">
         <source path="fusion_faces_widget.xml"/>
   </workbench>
   <workbench id="Part">
     <group id="Movement">
-      <feature id="Placement" title="Placement" tooltip="Place an objects relatively to another one"
+      <feature id="Placement" title="Placement" tooltip="Place objects relatively to another one"
                icon="icons/Features/placement.png" helpfile="placementFeature.html">
         <source path="placement_widget.xml"/>
       </feature>
-      <feature id="Translation" title="Translation" tooltip="Perform translation of an objects along the axis to specified distance"
+      <feature id="Translation" title="Translation" tooltip="Perform translation of objects along the axis to specified distance"
                icon="icons/Features/movement.png" helpfile="translationFeature.html">
         <source path="translation_widget.xml"/>
       </feature>
-      <feature id="Rotation" title="Rotation" tooltip="Perform rotation of an objects around the axis to specified angle"
+      <feature id="Rotation" title="Rotation" tooltip="Perform rotation of objects around the axis to specified angle"
                icon="icons/Features/rotation.png" helpfile="rotationFeature.html">
         <source path="rotation_widget.xml"/>
       </feature>
index c880f816d233c32e553460f0d863a26e4ac723dd..28a13de3bc9ce04121622209ed2f7c683b7abac4 100644 (file)
@@ -15,7 +15,7 @@
       <multi_selector id="subshapes_to_remove"
                 label="Sub-Shapes to remove:"
                 tooltip="Select shapes to remove."
-                type_choice="vertices edges wires faces shells solids compsolids compounds"
+                shape_types="vertices edges wires faces shells solids compsolids compounds"
                 clear_in_neutral_point="false">
         <validator id="FeaturesPlugin_ValidatorRemoveSubShapesSelection"/>
       </multi_selector>
@@ -26,7 +26,7 @@
       <multi_selector id="subshapes_to_keep"
                 label="Sub-Shapes to keep:"
                 tooltip="Select shapes to keep."
-                type_choice="vertices edges wires faces shells solids compsolids compounds"
+                shape_types="vertices edges wires faces shells solids compsolids compounds"
                 clear_in_neutral_point="false">
         <validator id="FeaturesPlugin_ValidatorRemoveSubShapesSelection"/>
       </multi_selector>
index e5a28b89f50745a5f8d0da40d9c0d8ee45be6e4c..3a641befbb6c73cf46031437a8dcd25caf138169 100644 (file)
@@ -11,7 +11,7 @@
   <multi_selector id="base"
                   label="Base objects:"
                   tooltip="Select a base objects"
-                  type_choice="vertices edges wires faces shells compounds"
+                  shape_types="vertices edges wires faces shells compounds"
                   concealment="true">
     <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell,compound"/>
   </multi_selector>
index fc2b822436ece70a48478d90f01e68bd68659a89..217f4fb60896860f2a7ee5aab24059ec9143e19b 100644 (file)
@@ -13,7 +13,7 @@
       label="Select a sketch face"
       icon="icons/Features/sketch.png"
       tooltip="Select a sketch face"
-      type_choice="wires faces shells"
+      shape_types="wires faces shells"
       concealment="true">
       <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="face,shell"/>
     </multi_selector>
@@ -89,7 +89,7 @@
     label="Cut from:"
     icon="icons/Features/cut_shape.png"
     tooltip="Objects to Cut"
-    type_choice="Objects"
+    shape_types="Objects"
     use_choice="false"
     concealment="true"
     main_argument="true">
index 575c6c4bf37718d97e5db09cd64328184b3505d8..26c0de8ffec76c7048b3c67048efb259a20b2c8d 100644 (file)
@@ -13,7 +13,7 @@
       label="Select a sketch face"
       icon="icons/Features/sketch.png"
       tooltip="Select a sketch face"
-      type_choice="vertices edges wires faces shells compounds"
+      shape_types="vertices edges wires faces shells compounds"
       concealment="true">
       <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell,compound"/>
     </multi_selector>
@@ -89,7 +89,7 @@
     label="Fuse with:"
     icon="icons/Features/cut_shape.png"
     tooltip="Objects to Fuse"
-    type_choice="Objects"
+    shape_types="Objects"
     use_choice="false"
     concealment="true"
     main_argument="true">
index def2c3fa9dc57b9eeb882020214a6aad00d49ed1..52b945ebb100126beb0aeb681ae6504ab0188239 100644 (file)
@@ -7,7 +7,7 @@
                       label="Main objects"
                       icon=""
                       tooltip="Select solid objects"
-                      type_choice="objects"
+                      shape_types="objects"
                       concealment="true">
         <validator id="FeaturesPlugin_ValidatorTransform"/>
       </multi_selector>
@@ -35,7 +35,7 @@
                       label="Main objects"
                       icon=""
                       tooltip="Select solid objects"
-                      type_choice="objects"
+                      shape_types="objects"
                       concealment="true">
         <validator id="FeaturesPlugin_ValidatorTransform"/>
       </multi_selector>
index 6dc4303c15b479f99015454eda0010ec39603c8d..c9ade559a0273913c4f34e9dd0fb10f303fea602 100644 (file)
@@ -7,7 +7,7 @@
                       label="Main objects"
                       icon=""
                       tooltip="Select objects"
-                      type_choice="objects"
+                      shape_types="objects"
                       concealment="true">
         <validator id="FeaturesPlugin_ValidatorTransform"/>
       </multi_selector>
@@ -35,7 +35,7 @@
                       label="Main objects"
                       icon=""
                       tooltip="Select objects"
-                      type_choice="objects"
+                      shape_types="objects"
                       concealment="true">
         <validator id="FeaturesPlugin_ValidatorTransform"/>
       </multi_selector>
index bda3367eaf34269f9c92bed42afd06d365afbe8c..91133e99c5c5a000e087b9eff6e259a1dfc0202b 100644 (file)
@@ -5,7 +5,7 @@
                       label="Main objects"
                       icon="icons/Features/cut_shape.png"
                       tooltip="Select solid objects"
-                      type_choice="solid objects"
+                      shape_types="solid objects"
                       concealment="true">
         <validator id="FeaturesPlugin_ValidatorTransform"/>
       </multi_selector>
@@ -23,7 +23,7 @@
                       label="Main objects"
                       icon="icons/Features/cut_shape.png"
                       tooltip="Select solid objects"
-                      type_choice="solid objects"
+                      shape_types="solid objects"
                       concealment="true">
         <validator id="FeaturesPlugin_ValidatorTransform"/>
       </multi_selector>
@@ -42,7 +42,7 @@
                       label="Main objects"
                       icon="icons/Features/cut_shape.png"
                       tooltip="Select solid objects"
-                      type_choice="solid objects"
+                      shape_types="solid objects"
                       concealment="true">
         <validator id="FeaturesPlugin_ValidatorTransform"/>
       </multi_selector>
index ca02649513c9debeafe44ae95b7921ff7ce22edb..eb4d5636a14bdb08fae75d314b0b4c41e84c9046 100644 (file)
@@ -7,7 +7,7 @@
                       label="Main objects"
                       icon=""
                       tooltip="Select solid objects"
-                      type_choice="objects"
+                      shape_types="objects"
                       concealment="true">
         <validator id="FeaturesPlugin_ValidatorTransform"/>
       </multi_selector>
@@ -35,7 +35,7 @@
                       label="Main objects"
                       icon=""
                       tooltip="Select solid objects"
-                      type_choice="objects"
+                      shape_types="objects"
                       concealment="true">
         <validator id="FeaturesPlugin_ValidatorTransform"/>
       </multi_selector>
@@ -68,7 +68,7 @@
                       label="Main objects"
                       icon=""
                       tooltip="Select solid objects"
-                      type_choice="objects"
+                      shape_types="objects"
                       concealment="true">
         <validator id="FeaturesPlugin_ValidatorTransform"/>
       </multi_selector>
index 966068352604118bbc8cab10fe4edf772a2bcb86..6bbc3239554fb3474ea8809f4a886c5ed2e23858 100644 (file)
@@ -2,7 +2,7 @@
   <multi_selector id="base_objects"
     label="Base objects:"
     tooltip="Select solids for union."
-    type_choice="faces solids compsolids"
+    shape_types="faces solids compsolids"
     use_choice="false"
     concealment="true">
     <validator id="FeaturesPlugin_ValidatorUnionSelection"/>
index 301f5167004789f0f6330fa0e6ab1acab66a52c6..14bdbf6658c60cd8c39246a5c5428455b47cb201 100644 (file)
@@ -29,6 +29,7 @@ FiltersAPI_Feature::FiltersAPI_Feature(
 : ModelHighAPI_Interface(theFeature)
 {
   initialize();
+  std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(theFeature)->initAttributes();
 }
 
 FiltersAPI_Feature::~FiltersAPI_Feature()
index 8cebbbaa6dfa7a832898b15b276da0506c57d5e7..2c856188db730598fb3f6b7aa2a253c84201029b 100644 (file)
@@ -79,8 +79,8 @@ SET(XML_RESOURCES
 )
 
 ADD_DEFINITIONS(-DFILTERS_EXPORTS ${OpenCASCADE_DEFINITIONS})
-ADD_LIBRARY(Filters SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${XML_RESOURCES})
-TARGET_LINK_LIBRARIES(Filters ${PROJECT_LIBRARIES})
+ADD_LIBRARY(FiltersPlugin SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${XML_RESOURCES})
+TARGET_LINK_LIBRARIES(FiltersPlugin ${PROJECT_LIBRARIES})
 
 INCLUDE_DIRECTORIES(
   ${OpenCASCADE_INCLUDE_DIR}
@@ -94,7 +94,7 @@ INCLUDE_DIRECTORIES(
   ${PROJECT_SOURCE_DIR}/src/CollectionPlugin
 )
 
-INSTALL(TARGETS Filters DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES})
+INSTALL(TARGETS FiltersPlugin DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES})
 INSTALL(FILES ${XML_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
 INSTALL(FILES ${PROJECT_PYFILES} DESTINATION ${SHAPER_INSTALL_ADDONS})
 
@@ -119,11 +119,13 @@ ADD_UNIT_TESTS(
   TestFilter_OnGeometry_Face1.py
   TestFilter_OnGeometry_Face2.py
   TestFilter_OnGeometry_Face3.py
+  TestFilter_OnGeometry_Face4.py
   TestFilter_OnGeometry_Exclude_Edge1.py
   TestFilter_OnGeometry_Exclude_Edge2.py
   TestFilter_OnGeometry_Exclude_Face1.py
   TestFilter_OnGeometry_Exclude_Face2.py
   TestFilter_OnGeometry_Exclude_Face3.py
+  TestFilter_OnGeometry_Exclude_Face4.py
   TestFilter_OnPlaneSide_Face.py
   TestFilter_OnPlaneSide_Plane.py
   TestFilter_OnPlaneSide_Exclude_Face.py
index 3a0a76cd4fada9af9e74acade21d1ede801e6409..e3be677e26311fc6c3d96c2a6bdbeba3728ddb7c 100644 (file)
@@ -29,7 +29,7 @@
 
 bool FiltersPlugin_RelativeToSolid::isSupported(GeomAPI_Shape::ShapeType theType) const
 {
-  return true;
+  return theType >= GeomAPI_Shape::SHELL;
 }
 
 bool FiltersPlugin_RelativeToSolid::isOk(const GeomShapePtr& theShape, const ResultPtr&,
diff --git a/src/FiltersPlugin/Test/TestFilter_OnGeometry_Exclude_Face4.py b/src/FiltersPlugin/Test/TestFilter_OnGeometry_Exclude_Face4.py
new file mode 100644 (file)
index 0000000..3105218
--- /dev/null
@@ -0,0 +1,52 @@
+# 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 GeomAPI 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, 45)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Cylinder_1_1/Face_4"))
+SketchArc_1 = Sketch_1.addArc(2.402631123626777, 4.538350751693263, 2.946623076146047, 2.768866376496988, 3.159520035183744, 6.227765257973941, False)
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_1/SketchArc_1_2")])
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("EDGE", "Edge_1_1")], model.selection("EDGE", "PartSet/OZ"), 0, 90)
+FiltersCyl = model.filters(Part_1_doc, [model.addFilter(name = "OnGeometry", exclude = True, args = [model.selection("FACE", "Cylinder_1_1/Face_1")])])
+FiltersRev = model.filters(Part_1_doc, [model.addFilter(name = "OnGeometry", exclude = True, args = [model.selection("FACE", "Revolution_1_1")])])
+model.end()
+
+Reference = {}
+ResultRevolution = Revolution_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultRevolution.shape(), GeomAPI_Shape.FACE)
+Reference[model.selection(ResultRevolution, exp.current())] = True; exp.next()
+assert(not exp.more())
+
+model.checkFilter(Part_1_doc, model, FiltersCyl, Reference)
+
+Reference = {}
+ResultCylinder = Cylinder_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultCylinder.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultCylinder, exp.current())] = True
+  exp.next()
+
+model.checkFilter(Part_1_doc, model, FiltersRev, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_OnGeometry_Face4.py b/src/FiltersPlugin/Test/TestFilter_OnGeometry_Face4.py
new file mode 100644 (file)
index 0000000..8734e05
--- /dev/null
@@ -0,0 +1,52 @@
+# 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 GeomAPI 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, 45)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Cylinder_1_1/Face_4"))
+SketchArc_1 = Sketch_1.addArc(2.402631123626777, 4.538350751693263, 2.946623076146047, 2.768866376496988, 3.159520035183744, 6.227765257973941, False)
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_1/SketchArc_1_2")])
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("EDGE", "Edge_1_1")], model.selection("EDGE", "PartSet/OZ"), 0, 90)
+FiltersCyl = model.filters(Part_1_doc, [model.addFilter(name = "OnGeometry", args = [model.selection("FACE", "Cylinder_1_1/Face_1")])])
+FiltersRev = model.filters(Part_1_doc, [model.addFilter(name = "OnGeometry", args = [model.selection("FACE", "Revolution_1_1")])])
+model.end()
+
+Reference = {}
+ResultRevolution = Revolution_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultRevolution.shape(), GeomAPI_Shape.FACE)
+Reference[model.selection(ResultRevolution, exp.current())] = False; exp.next()
+assert(not exp.more())
+
+model.checkFilter(Part_1_doc, model, FiltersCyl, Reference)
+
+Reference = {}
+ResultCylinder = Cylinder_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultCylinder.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultCylinder, exp.current())] = False
+  exp.next()
+
+model.checkFilter(Part_1_doc, model, FiltersRev, Reference)
index 34ac97fc24fae4e08fa89400bbc2765450101fd3..6ca93c92a533e12c57229ce9fa44a13ee5cb48c6 100644 (file)
@@ -76,25 +76,7 @@ Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cyli
 Filters = model.filters(Part_1_doc, [model.addFilter(name = "RelativeToSolid", exclude = True, args = [model.selection("SOLID", "Extrusion_1_1"), "in"])])
 model.end()
 
-Solid1 = Extrusion_1.results()[0].resultSubShapePair()[0]
-Solid2 = Extrusion_1.results()[1].resultSubShapePair()[0]
-Solid3 = Extrusion_2.result().resultSubShapePair()[0]
-Solid4 = Extrusion_3.result().resultSubShapePair()[0]
-Solid5 = Extrusion_4.result().resultSubShapePair()[0]
-Solid6 = Translation_1.result().resultSubShapePair()[0]
-
-from GeomAPI import GeomAPI_Shape
-emptyShape = GeomAPI_Shape()
-
 Reference = {
-    # Solids
-    model.selection(Solid1, emptyShape): True,
-    model.selection(Solid2, emptyShape): True,
-    model.selection(Solid3, emptyShape): True,
-    model.selection(Solid4, emptyShape): True,
-    model.selection(Solid5, emptyShape): False,
-    model.selection(Solid6, emptyShape): True,
-
     # Faces of solid 1
     model.selection("FACE", "Extrusion_1_1/To_Face"): True,
     model.selection("FACE", "Extrusion_1_1/From_Face"): True,
index dd44bef5f07fa94ac2d40a5916823f97cc896de5..b1753228bb09b088847cb6a5e1ce5a1dd825da5a 100644 (file)
@@ -76,25 +76,7 @@ Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cyli
 Filters = model.filters(Part_1_doc, [model.addFilter(name = "RelativeToSolid", exclude = True, args = [model.selection("SOLID", "Extrusion_1_1"), "not_out"])])
 model.end()
 
-Solid1 = Extrusion_1.results()[0].resultSubShapePair()[0]
-Solid2 = Extrusion_1.results()[1].resultSubShapePair()[0]
-Solid3 = Extrusion_2.result().resultSubShapePair()[0]
-Solid4 = Extrusion_3.result().resultSubShapePair()[0]
-Solid5 = Extrusion_4.result().resultSubShapePair()[0]
-Solid6 = Translation_1.result().resultSubShapePair()[0]
-
-from GeomAPI import GeomAPI_Shape
-emptyShape = GeomAPI_Shape()
-
 Reference = {
-    # Solids
-    model.selection(Solid1, emptyShape): False,
-    model.selection(Solid2, emptyShape): True,
-    model.selection(Solid3, emptyShape): True,
-    model.selection(Solid4, emptyShape): False,
-    model.selection(Solid5, emptyShape): False,
-    model.selection(Solid6, emptyShape): True,
-
     # Faces of solid 1
     model.selection("FACE", "Extrusion_1_1/To_Face"): False,
     model.selection("FACE", "Extrusion_1_1/From_Face"): False,
index 63154f145f003c41f8dd214066a93fef68754f0f..7d66cf27e62d79933239850afc70203873d7847a 100644 (file)
@@ -76,25 +76,7 @@ Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cyli
 Filters = model.filters(Part_1_doc, [model.addFilter(name = "RelativeToSolid", exclude = True, args = [model.selection("SOLID", "Extrusion_1_1"), "not_on"])])
 model.end()
 
-Solid1 = Extrusion_1.results()[0].resultSubShapePair()[0]
-Solid2 = Extrusion_1.results()[1].resultSubShapePair()[0]
-Solid3 = Extrusion_2.result().resultSubShapePair()[0]
-Solid4 = Extrusion_3.result().resultSubShapePair()[0]
-Solid5 = Extrusion_4.result().resultSubShapePair()[0]
-Solid6 = Translation_1.result().resultSubShapePair()[0]
-
-from GeomAPI import GeomAPI_Shape
-emptyShape = GeomAPI_Shape()
-
 Reference = {
-    # Solids
-    model.selection(Solid1, emptyShape): True,
-    model.selection(Solid2, emptyShape): False,
-    model.selection(Solid3, emptyShape): True,
-    model.selection(Solid4, emptyShape): True,
-    model.selection(Solid5, emptyShape): False,
-    model.selection(Solid6, emptyShape): True,
-
     # Faces of solid 1
     model.selection("FACE", "Extrusion_1_1/To_Face"): True,
     model.selection("FACE", "Extrusion_1_1/From_Face"): True,
index 7dd9283acde299aa070fa4d584c33114f5d86774..841c693cc0567c5713c3b0aa8a8a8f313c97150e 100644 (file)
@@ -76,25 +76,7 @@ Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cyli
 Filters = model.filters(Part_1_doc, [model.addFilter(name = "RelativeToSolid", exclude = True, args = [model.selection("SOLID", "Extrusion_1_1"), "on"])])
 model.end()
 
-Solid1 = Extrusion_1.results()[0].resultSubShapePair()[0]
-Solid2 = Extrusion_1.results()[1].resultSubShapePair()[0]
-Solid3 = Extrusion_2.result().resultSubShapePair()[0]
-Solid4 = Extrusion_3.result().resultSubShapePair()[0]
-Solid5 = Extrusion_4.result().resultSubShapePair()[0]
-Solid6 = Translation_1.result().resultSubShapePair()[0]
-
-from GeomAPI import GeomAPI_Shape
-emptyShape = GeomAPI_Shape()
-
 Reference = {
-    # Solids
-    model.selection(Solid1, emptyShape): True,
-    model.selection(Solid2, emptyShape): True,
-    model.selection(Solid3, emptyShape): True,
-    model.selection(Solid4, emptyShape): True,
-    model.selection(Solid5, emptyShape): True,
-    model.selection(Solid6, emptyShape): True,
-
     # Faces of solid 1
     model.selection("FACE", "Extrusion_1_1/To_Face"): False,
     model.selection("FACE", "Extrusion_1_1/From_Face"): False,
index 66cc31f064b1452badc4cfccafbf8d2cc8c6f45b..ff2ae3001019d9d641054523ffd05aadce4c2237 100644 (file)
@@ -76,25 +76,7 @@ Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cyli
 Filters = model.filters(Part_1_doc, [model.addFilter(name = "RelativeToSolid", exclude = True, args = [model.selection("SOLID", "Extrusion_1_1"), "out"])])
 model.end()
 
-Solid1 = Extrusion_1.results()[0].resultSubShapePair()[0]
-Solid2 = Extrusion_1.results()[1].resultSubShapePair()[0]
-Solid3 = Extrusion_2.result().resultSubShapePair()[0]
-Solid4 = Extrusion_3.result().resultSubShapePair()[0]
-Solid5 = Extrusion_4.result().resultSubShapePair()[0]
-Solid6 = Translation_1.result().resultSubShapePair()[0]
-
-from GeomAPI import GeomAPI_Shape
-emptyShape = GeomAPI_Shape()
-
 Reference = {
-    # Solids
-    model.selection(Solid1, emptyShape): True,
-    model.selection(Solid2, emptyShape): False,
-    model.selection(Solid3, emptyShape): True,
-    model.selection(Solid4, emptyShape): True,
-    model.selection(Solid5, emptyShape): True,
-    model.selection(Solid6, emptyShape): True,
-
     # Faces of solid 1
     model.selection("FACE", "Extrusion_1_1/To_Face"): True,
     model.selection("FACE", "Extrusion_1_1/From_Face"): True,
index f63183c47bb809ee5c14b0155544290c3c6b50e5..81d78595a927f76fb46da71ca209d214b62688c9 100644 (file)
@@ -76,25 +76,7 @@ Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cyli
 Filters = model.filters(Part_1_doc, [model.addFilter(name = "RelativeToSolid", exclude = True, args = [model.selection("SOLID", "Extrusion_1_1"), "not_in"])])
 model.end()
 
-Solid1 = Extrusion_1.results()[0].resultSubShapePair()[0]
-Solid2 = Extrusion_1.results()[1].resultSubShapePair()[0]
-Solid3 = Extrusion_2.result().resultSubShapePair()[0]
-Solid4 = Extrusion_3.result().resultSubShapePair()[0]
-Solid5 = Extrusion_4.result().resultSubShapePair()[0]
-Solid6 = Translation_1.result().resultSubShapePair()[0]
-
-from GeomAPI import GeomAPI_Shape
-emptyShape = GeomAPI_Shape()
-
 Reference = {
-    # Solids
-    model.selection(Solid1, emptyShape): True,
-    model.selection(Solid2, emptyShape): False,
-    model.selection(Solid3, emptyShape): False,
-    model.selection(Solid4, emptyShape): True,
-    model.selection(Solid5, emptyShape): True,
-    model.selection(Solid6, emptyShape): True,
-
     # Faces of solid 1
     model.selection("FACE", "Extrusion_1_1/To_Face"): False,
     model.selection("FACE", "Extrusion_1_1/From_Face"): False,
index 69937f82ca175960a840266dde1b3c07642d73a6..9ff836284322b3bb9d09a5c88d068eb8cc78b0d8 100644 (file)
@@ -76,25 +76,7 @@ Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cyli
 Filters = model.filters(Part_1_doc, [model.addFilter(name = "RelativeToSolid", args = [model.selection("SOLID", "Extrusion_1_1"), "in"])])
 model.end()
 
-Solid1 = Extrusion_1.results()[0].resultSubShapePair()[0]
-Solid2 = Extrusion_1.results()[1].resultSubShapePair()[0]
-Solid3 = Extrusion_2.result().resultSubShapePair()[0]
-Solid4 = Extrusion_3.result().resultSubShapePair()[0]
-Solid5 = Extrusion_4.result().resultSubShapePair()[0]
-Solid6 = Translation_1.result().resultSubShapePair()[0]
-
-from GeomAPI import GeomAPI_Shape
-emptyShape = GeomAPI_Shape()
-
 Reference = {
-    # Solids
-    model.selection(Solid1, emptyShape): False,
-    model.selection(Solid2, emptyShape): False,
-    model.selection(Solid3, emptyShape): False,
-    model.selection(Solid4, emptyShape): False,
-    model.selection(Solid5, emptyShape): True,
-    model.selection(Solid6, emptyShape): False,
-
     # Faces of solid 1
     model.selection("FACE", "Extrusion_1_1/To_Face"): False,
     model.selection("FACE", "Extrusion_1_1/From_Face"): False,
index c3247dee69d5fbec9b9945501bd70f8e129ae1e2..09fafe4fe29a5ef74c76a319b834e4e8f2d533ba 100644 (file)
@@ -76,25 +76,7 @@ Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cyli
 Filters = model.filters(Part_1_doc, [model.addFilter(name = "RelativeToSolid", args = [model.selection("SOLID", "Extrusion_1_1"), "not_out"])])
 model.end()
 
-Solid1 = Extrusion_1.results()[0].resultSubShapePair()[0]
-Solid2 = Extrusion_1.results()[1].resultSubShapePair()[0]
-Solid3 = Extrusion_2.result().resultSubShapePair()[0]
-Solid4 = Extrusion_3.result().resultSubShapePair()[0]
-Solid5 = Extrusion_4.result().resultSubShapePair()[0]
-Solid6 = Translation_1.result().resultSubShapePair()[0]
-
-from GeomAPI import GeomAPI_Shape
-emptyShape = GeomAPI_Shape()
-
 Reference = {
-    # Solids
-    model.selection(Solid1, emptyShape): True,
-    model.selection(Solid2, emptyShape): False,
-    model.selection(Solid3, emptyShape): False,
-    model.selection(Solid4, emptyShape): True,
-    model.selection(Solid5, emptyShape): True,
-    model.selection(Solid6, emptyShape): False,
-
     # Faces of solid 1
     model.selection("FACE", "Extrusion_1_1/To_Face"): True,
     model.selection("FACE", "Extrusion_1_1/From_Face"): True,
index 4c82e357b9ddfa2c3fe3a963cb96253cabfc7ce8..276da9622850bce2ce7d8c0af5d3362f09f513e2 100644 (file)
@@ -76,25 +76,7 @@ Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cyli
 Filters = model.filters(Part_1_doc, [model.addFilter(name = "RelativeToSolid", args = [model.selection("SOLID", "Extrusion_1_1"), "not_on"])])
 model.end()
 
-Solid1 = Extrusion_1.results()[0].resultSubShapePair()[0]
-Solid2 = Extrusion_1.results()[1].resultSubShapePair()[0]
-Solid3 = Extrusion_2.result().resultSubShapePair()[0]
-Solid4 = Extrusion_3.result().resultSubShapePair()[0]
-Solid5 = Extrusion_4.result().resultSubShapePair()[0]
-Solid6 = Translation_1.result().resultSubShapePair()[0]
-
-from GeomAPI import GeomAPI_Shape
-emptyShape = GeomAPI_Shape()
-
 Reference = {
-    # Solids
-    model.selection(Solid1, emptyShape): False,
-    model.selection(Solid2, emptyShape): True,
-    model.selection(Solid3, emptyShape): False,
-    model.selection(Solid4, emptyShape): False,
-    model.selection(Solid5, emptyShape): True,
-    model.selection(Solid6, emptyShape): False,
-
     # Faces of solid 1
     model.selection("FACE", "Extrusion_1_1/To_Face"): False,
     model.selection("FACE", "Extrusion_1_1/From_Face"): False,
index aa57cfe4d3e506afe47a6834ff6de7e33b2d50d2..24cabe3a0d5237e953ea18f4c87c47477fdbffa7 100644 (file)
@@ -76,25 +76,7 @@ Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cyli
 Filters = model.filters(Part_1_doc, [model.addFilter(name = "RelativeToSolid", args = [model.selection("SOLID", "Extrusion_1_1"), "on"])])
 model.end()
 
-Solid1 = Extrusion_1.results()[0].resultSubShapePair()[0]
-Solid2 = Extrusion_1.results()[1].resultSubShapePair()[0]
-Solid3 = Extrusion_2.result().resultSubShapePair()[0]
-Solid4 = Extrusion_3.result().resultSubShapePair()[0]
-Solid5 = Extrusion_4.result().resultSubShapePair()[0]
-Solid6 = Translation_1.result().resultSubShapePair()[0]
-
-from GeomAPI import GeomAPI_Shape
-emptyShape = GeomAPI_Shape()
-
 Reference = {
-    # Solids
-    model.selection(Solid1, emptyShape): False,
-    model.selection(Solid2, emptyShape): False,
-    model.selection(Solid3, emptyShape): False,
-    model.selection(Solid4, emptyShape): False,
-    model.selection(Solid5, emptyShape): False,
-    model.selection(Solid6, emptyShape): False,
-
     # Faces of solid 1
     model.selection("FACE", "Extrusion_1_1/To_Face"): True,
     model.selection("FACE", "Extrusion_1_1/From_Face"): True,
index eeb33a2bd4ccd0583d318ed0a7ece96bac28ce56..480c4f8b7fd2d73035c1a4308c391265127bf833 100644 (file)
@@ -76,25 +76,7 @@ Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cyli
 Filters = model.filters(Part_1_doc, [model.addFilter(name = "RelativeToSolid", args = [model.selection("SOLID", "Extrusion_1_1"), "out"])])
 model.end()
 
-Solid1 = Extrusion_1.results()[0].resultSubShapePair()[0]
-Solid2 = Extrusion_1.results()[1].resultSubShapePair()[0]
-Solid3 = Extrusion_2.result().resultSubShapePair()[0]
-Solid4 = Extrusion_3.result().resultSubShapePair()[0]
-Solid5 = Extrusion_4.result().resultSubShapePair()[0]
-Solid6 = Translation_1.result().resultSubShapePair()[0]
-
-from GeomAPI import GeomAPI_Shape
-emptyShape = GeomAPI_Shape()
-
 Reference = {
-    # Solids
-    model.selection(Solid1, emptyShape): False,
-    model.selection(Solid2, emptyShape): True,
-    model.selection(Solid3, emptyShape): False,
-    model.selection(Solid4, emptyShape): False,
-    model.selection(Solid5, emptyShape): False,
-    model.selection(Solid6, emptyShape): False,
-
     # Faces of solid 1
     model.selection("FACE", "Extrusion_1_1/To_Face"): False,
     model.selection("FACE", "Extrusion_1_1/From_Face"): False,
index 6154daae8696631c93c8d55632aae4ae0af18ca7..f12d335d2c768f19ca2c88db888d12c94ed28e34 100644 (file)
@@ -76,25 +76,7 @@ Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cyli
 Filters = model.filters(Part_1_doc, [model.addFilter(name = "RelativeToSolid", args = [model.selection("SOLID", "Extrusion_1_1"), "not_in"])])
 model.end()
 
-Solid1 = Extrusion_1.results()[0].resultSubShapePair()[0]
-Solid2 = Extrusion_1.results()[1].resultSubShapePair()[0]
-Solid3 = Extrusion_2.result().resultSubShapePair()[0]
-Solid4 = Extrusion_3.result().resultSubShapePair()[0]
-Solid5 = Extrusion_4.result().resultSubShapePair()[0]
-Solid6 = Translation_1.result().resultSubShapePair()[0]
-
-from GeomAPI import GeomAPI_Shape
-emptyShape = GeomAPI_Shape()
-
 Reference = {
-    # Solids
-    model.selection(Solid1, emptyShape): False,
-    model.selection(Solid2, emptyShape): True,
-    model.selection(Solid3, emptyShape): True,
-    model.selection(Solid4, emptyShape): False,
-    model.selection(Solid5, emptyShape): False,
-    model.selection(Solid6, emptyShape): False,
-
     # Faces of solid 1
     model.selection("FACE", "Extrusion_1_1/To_Face"): True,
     model.selection("FACE", "Extrusion_1_1/From_Face"): True,
index c08497fe88281dba8369c6c6084064c836c1ac0c..a0fd32cc413535c338559b9fb6bbb99a2de4c7a9 100644 (file)
@@ -25,13 +25,14 @@ partSet = model.moduleDocument()
 Part_1 = model.addPart(partSet)
 Part_1_doc = Part_1.document()
 Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
-Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Bottom"), model.selection("FACE", "Box_1_1/Top"), model.filters(Part_1_doc, [model.addFilter(name = "BelongsTo", args = []), model.addFilter(name = "HorizontalFaces")])])
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "BelongsTo", args = [model.selection("SOLID", "Box_1_1")]), model.addFilter(name = "HorizontalFaces"), model.addFilter(name = "OnGeometry", args = [model.selection("FACE", "PartSet/XOY")])])
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Bottom"), Filters])
 model.end()
 
 aFactory = ModelAPI_Session.get().validators()
 
 GroupFeature = Group_1.feature()
 assert(aFactory.validate(GroupFeature))
-assert(GroupFeature.selectionList("group_list").size() == 2)
+assert(GroupFeature.selectionList("group_list").size() == 1)
 
 assert(model.checkPythonDump())
index 418a68707b0e9fda1b150ce661f5853979cbb065..2eb7ffb65ef094f797d37853449f5306abf3a435 100644 (file)
@@ -42,7 +42,7 @@ Reference = {
     GeomAPI_Shape.WIRE   : [FILTER_BELONGS_TO, FILTER_ON_PLANE, FILTER_ON_PLANE_SIDE, FILTER_RELATIVE_TO_SOLID],
     GeomAPI_Shape.FACE   : [FILTER_BELONGS_TO, FILTER_ON_PLANE, FILTER_ON_GEOMETRY, FILTER_ON_PLANE_SIDE, FILTER_RELATIVE_TO_SOLID, FILTER_EXTERNAL_FACES, FILTER_HORIZONTAL_FACES, FILTER_VERTICAL_FACES, FILTER_CONNECTED_FACES],
     GeomAPI_Shape.SHELL  : [FILTER_BELONGS_TO, FILTER_ON_PLANE, FILTER_ON_PLANE_SIDE, FILTER_RELATIVE_TO_SOLID],
-    GeomAPI_Shape.SOLID  : [FILTER_BELONGS_TO, FILTER_ON_PLANE_SIDE, FILTER_RELATIVE_TO_SOLID],
+    GeomAPI_Shape.SOLID  : [FILTER_BELONGS_TO, FILTER_ON_PLANE_SIDE],
 }
 
 model.begin()
diff --git a/src/FiltersPlugin/doc/FiltersPlugin.rst b/src/FiltersPlugin/doc/FiltersPlugin.rst
new file mode 100644 (file)
index 0000000..8e6d0ba
--- /dev/null
@@ -0,0 +1,138 @@
+.. |plus.icon|  image:: images/add.png
+.. |minus.icon|  image:: images/reverce.png
+.. |delete.icon|  image:: images/delete.png
+
+
+.. _filtersPlugin:
+
+Filters Plugin
+==============
+
+Filters plug-in provides a collection of filters used Filters property panel (for example see :ref:`groupPage` feature).
+
+
+**Selection filters**
+
+Selection by filters panel looks like following:
+
+.. image:: images/selection_by_filters.png
+  :align: center
+
+.. centered::
+  Selection by filters property panel
+
+In this panel:
+
+- **Filters** a panel for added filters.
+
+- **Add new filter** combo box. It contains accessible filters according to the selection mode. When user selects an item from this combo box a filter item appears in **Filters** panel like in the following example:
+
+.. image:: images/selection_by_filters_added.png
+  :align: center
+
+.. centered::
+  Filters **Horizontal faces** and **On plane** added to the property panel.
+  
+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.
+
+- **Select** button traverces all objects of a current document and selects entities acceptable by currently defined set of filters. All selected entities will be shown in viewer 3d with
+blue semi-transparent color. Any modification in filters clears current selection.
+
+- **Number of selected objects** shows number currently selected entities.
+
+- **Show only** check box hides all non-selected objects.
+
+**Accept** button in the **Selection filters** property panel reopens a property panel where the **selection filters** was called and transfers all selected entities to the corresponded list.
+
+
+Filters
+-------
+
+**Belongs to**
+
+By default, the result of Selection feature all selectable entities from all Shapes registered in the “Results” folder. This filter provides a way to explicit (restrict) the results in which looking for selectable entities.
+
+- **Result type:** Any
+- **Argument:** Any result object, multiple OR selection accepted
+- **Algorithm:** Returns only shapes that belong to selected results.
+
+**On a plane**
+
+- **Result type:** Vertex, Edge, Face
+- **Argument:** Planar face or Construction plane, multiple OR selection accepted
+- **Algorithm:** Returns all vertices, edges or planar faces geometrically located on (co-planar) the given plane.
+
+**On a Line**
+
+- **Result type:** Vertex, Edge
+- **Argument:** Straight Edge or Construction axis, multiple OR selection accepted
+- **Algorithm:** Returns all vertices coincident or all edges collinear to the given line.
+
+**On geometry**
+
+- **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.
+
+**On plane side**
+
+- **Result type:** Any
+- **Argument:** Planar face or Construction plane
+- **Algorithm:** By default, the side is in direction of normal of the given plane. For getting the other side, simply invert the filter by clicking on the Check button.
+
+**Opposite to an edge**
+
+This algorithm is based on the Propagate geompy function. It works on a model partitioned into quadrangular faces blocks for the purpose of hexahedral meshing.
+
+- **Result type:** Edge
+- **Argument:** An edge belonging to a quadrangular face
+- **Algorithm:** Returns all Edges opposite to the given Edge on all quadrangular faces connected to this Edge. The algorithm is recursive: after an edge is found on one face, it adds edges opposite to this new one.
+
+**On/In/Out a Solid**
+
+This algorithm reproduces the GetShapesOnShape function of geompy.
+
+- **Result type:** Vertex, Edge or Face
+- **Arguments:** Solid. Location according to the given Solid, as described below
+- **Algorithm:**
+    - **In:** strictly inside the solid. 
+    - **Not In:** strictly outside the solid. 
+    - **On:** confused with the boundary of the solid
+    - **Not On:** strictly inside or outside the solid
+    - **In & On:** i.e. inside or confused with the boundary of the solid
+    - **Not In & On:** outside or confused with the boundary of the solid.
+
+**External Faces**
+
+This algorithm finds all not-shared faces.
+
+- **Result type:** Face
+- **Arguments:** None
+- **Algorithm:** Returns all faces which are not shared between higher level shapes of the connected compound of the connected compound of compsolid. For an example, if there is a compsolid of two boxes with one shared face between them, the filter returns all faces except the shared.
+
+**Horizontal Faces**
+
+This algorithm finds all the horizontal faces of the model.
+
+- **Result type:** Face
+- **Arguments:** None
+- **Algorithm:** Returns only planar faces with normal of the plane perpendicular to OZ.
+
+**Vertical Faces**
+
+This algorithm finds all the vertical faces of the model.
+
+- **Result type:** Face
+- **Arguments:** None
+- **Algorithm:** Returns only planar faces with normal of the plane parallel to OZ or cylindrical faces with axis parallel to OZ.
+
+**Topologically connected Faces**
+
+This algorithm finds all the faces topologically connected the argument selected by the user.
+
+- **Result type:** Face
+- **Arguments:** A point, an edge or a face. A “propagation” flag (check-box).
+- **Algorithm:**
+    - If a point of an edge is selected as an argument, the result is all faces that contain this argument.If a face is selected, the result is all faces that have shared edges or vertices with this selection.
+    - If “propagation” flag is enabled (it is disabled by default), the algorithm becomes recursive: all connected faces are added to the results. So, for the solid shape there will be all faces except internal-volumes faces, not connected to any external faces.
\ No newline at end of file
diff --git a/src/FiltersPlugin/doc/images/add.png b/src/FiltersPlugin/doc/images/add.png
new file mode 100644 (file)
index 0000000..388f8ff
Binary files /dev/null and b/src/FiltersPlugin/doc/images/add.png differ
diff --git a/src/FiltersPlugin/doc/images/delete.png b/src/FiltersPlugin/doc/images/delete.png
new file mode 100644 (file)
index 0000000..6d2aea8
Binary files /dev/null and b/src/FiltersPlugin/doc/images/delete.png differ
diff --git a/src/FiltersPlugin/doc/images/reverce.png b/src/FiltersPlugin/doc/images/reverce.png
new file mode 100644 (file)
index 0000000..40239ad
Binary files /dev/null and b/src/FiltersPlugin/doc/images/reverce.png differ
diff --git a/src/FiltersPlugin/doc/images/selection_by_filters.png b/src/FiltersPlugin/doc/images/selection_by_filters.png
new file mode 100644 (file)
index 0000000..c4ac7ee
Binary files /dev/null and b/src/FiltersPlugin/doc/images/selection_by_filters.png differ
diff --git a/src/FiltersPlugin/doc/images/selection_by_filters_added.png b/src/FiltersPlugin/doc/images/selection_by_filters_added.png
new file mode 100644 (file)
index 0000000..a3e0a25
Binary files /dev/null and b/src/FiltersPlugin/doc/images/selection_by_filters_added.png differ
index 217645b3a3ca71659dce9ba983142548d633e7ec..7500646c043affc0d520360217837cc8bab22e2d 100644 (file)
@@ -2,6 +2,6 @@
   <multi_selector id="BelongsTo__BelongsTo"
                   label="Objects:"
                   tooltip="Select objects to limit selection."
-                  type_choice="objects">
+                  shape_types="objects">
   </multi_selector>
 </filter>
index 80053d57ecaf236b4fe714ddefb7b62643b5b26e..6af2e9d5ea955a273795cf4ff0c4714a55586bf2 100644 (file)
@@ -2,7 +2,7 @@
   <multi_selector id="OnGeometry__OnGeometry"
                   label="Shapes:"
                   tooltip="Select objects to limit selection."
-                  type_choice="edges faces">
+                  shape_types="edges faces">
     <validator id="FiltersPlugin_ShapeType"/>
   </multi_selector>
 </filter>
index 8f8f5270270e2afb7976c5d30d659858ac188849..0a7eeccfc239f0db0069990540b12fd2ef33e1e4 100644 (file)
@@ -2,7 +2,7 @@
   <multi_selector id="OnLine__OnLine"
                   label="Lines:"
                   tooltip="Select vertices or segments."
-                  type_choice="edges">
+                  shape_types="edges">
     <validator id="GeomValidators_ShapeType" parameters="line"/>
   </multi_selector>
 </filter>
index fa65cc0a446a071bc344f557a1a3638b0356fb2e..dceb874e71e42daa117d048e6f535ecc583d7f8c 100644 (file)
@@ -2,7 +2,7 @@
   <multi_selector id="OnPlane__OnPlane"
                   label="Planes:"
                   tooltip="Select planes or planar faces."
-                  type_choice="faces">
+                  shape_types="faces">
     <validator id="GeomValidators_ShapeType" parameters="plane"/>
   </multi_selector>
 </filter>
index 07fb93d65c858bfc5b3be00cf2bdc4f9ab91ad77..7276c848597b451c2dca046099d894e6b26ac7aa 100644 (file)
 #include<GeomAPI_Pnt.h>
 
 #include <TopoDS_Shape.hxx>
+#include <Geom_Circle.hxx>
 #include <Geom_Curve.hxx>
 #include <Geom_Line.hxx>
-#include <Geom_Circle.hxx>
+#include <Geom_TrimmedCurve.hxx>
 #include <BRep_Tool.hxx>
 #include <TopoDS_Edge.hxx>
 #include <TopoDS.hxx>
@@ -70,3 +71,37 @@ std::shared_ptr<GeomAPI_Pnt> GeomAPI_Curve::getPoint(double theParam)
   gp_Pnt aPnt = aAdaptor.Value(theParam);
   return std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aPnt.X(), aPnt.Y(), aPnt.Z()));
 }
+
+bool GeomAPI_Curve::isEqual(const std::shared_ptr<GeomAPI_Curve>& theOther) const
+{
+  return MY_CURVE == theOther->impl<Handle_Geom_Curve>();
+}
+
+bool GeomAPI_Curve::isTrimmed() const
+{
+  return !isNull() && MY_CURVE->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve);
+}
+
+// unused in the unit tests for now
+// LCOV_EXCL_START
+GeomCurvePtr GeomAPI_Curve::basisCurve() const
+{
+  Handle(Geom_Curve) aCurve = MY_CURVE;
+  if (aCurve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
+    aCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve)->BasisCurve();
+
+  GeomCurvePtr aNewCurve(new GeomAPI_Curve);
+  aNewCurve->setImpl(new Handle(Geom_Curve)(aCurve));
+  return aNewCurve;
+}
+// LCOV_EXCL_STOP
+
+// ================================================================================================
+
+bool GeomAPI_Curve::Comparator::operator()(const GeomCurvePtr& theCurve1,
+                                           const GeomCurvePtr& theCurve2) const
+{
+  const Handle(Geom_Curve)& aCurve1 = theCurve1->impl<Handle_Geom_Curve>();
+  const Handle(Geom_Curve)& aCurve2 = theCurve2->impl<Handle_Geom_Curve>();
+  return aCurve1.get() < aCurve2.get();
+}
index d002d4250189c63bb5015d681424bfc7ecf38784..30b9bd99840b9ebae2cc9637b2f0a055b08e4fd2 100644 (file)
@@ -45,6 +45,10 @@ class GeomAPI_Curve : public GeomAPI_Interface
   GEOMAPI_EXPORT
   bool isNull() const;
 
+  /// Returns \c true if curves are equal
+  GEOMAPI_EXPORT
+  bool isEqual(const std::shared_ptr<GeomAPI_Curve>& theOther) const;
+
   /// Returns whether the curve is linear
   GEOMAPI_EXPORT
   virtual bool isLine() const;
@@ -61,11 +65,30 @@ class GeomAPI_Curve : public GeomAPI_Interface
   GEOMAPI_EXPORT
   double endParam() const { return myEnd; }
 
+  /// Returns \c true if the curve is trimmed
+  GEOMAPI_EXPORT
+  virtual bool isTrimmed() const;
+
+  /// Returns basis for the trimmed curve
+  GEOMAPI_EXPORT
+  virtual std::shared_ptr<GeomAPI_Curve> basisCurve() const;
+
   /// Returns point on the curve by parameter
   /// \param theParam parameter on the curve
   GEOMAPI_EXPORT
   std::shared_ptr<GeomAPI_Pnt> getPoint(double theParam);
 
+public:
+  /// \brief Compare addresses of curves
+  class Comparator
+  {
+  public:
+    /// Return \c true if the address of the first curve is less than the address of the second
+    GEOMAPI_EXPORT
+    bool operator ()(const std::shared_ptr<GeomAPI_Curve>& theCurve1,
+                     const std::shared_ptr<GeomAPI_Curve>& theCurve2) const;
+  };
+
 private:
   double myStart;
   double myEnd;
index 6e09db85a3fe8abd9ae5b4d26420949266df26be..e80d9cf2928f39abc3ec85bded664a2426df79d1 100644 (file)
@@ -81,6 +81,7 @@ SET(PROJECT_HEADERS
     GeomAlgoAPI_Offset.h
     GeomAlgoAPI_SolidClassifier.h
     GeomAlgoAPI_MapShapesAndAncestors.h
+    GeomAlgoAPI_Chamfer.h
 )
 
 SET(PROJECT_SOURCES
@@ -141,6 +142,7 @@ SET(PROJECT_SOURCES
     GeomAlgoAPI_Offset.cpp
     GeomAlgoAPI_SolidClassifier.cpp
     GeomAlgoAPI_MapShapesAndAncestors.cpp
+    GeomAlgoAPI_Chamfer.cpp
 )
 
 SET(PROJECT_LIBRARIES
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Chamfer.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Chamfer.cpp
new file mode 100644 (file)
index 0000000..ecba849
--- /dev/null
@@ -0,0 +1,96 @@
+// Copyright (C) 2017-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 "GeomAlgoAPI_Chamfer.h"
+
+#include <BRep_Tool.hxx>
+#include <BRepFilletAPI_MakeChamfer.hxx>
+#include <BRepTools.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Face.hxx>
+
+//=================================================================================================
+GeomAlgoAPI_Chamfer::GeomAlgoAPI_Chamfer(const GeomShapePtr& theBaseSolid,
+                                         const ListOfShape&  theChamferShapes,
+                                         const std::map<GeomShapePtr, GeomShapePtr> aMapEdgeFace,
+                                         const bool performDistances,
+                                         const double aVal1,
+                                         const double aVal2)
+{
+  build(theBaseSolid, theChamferShapes, aMapEdgeFace, performDistances, aVal1, aVal2);
+}
+
+//=================================================================================================
+void GeomAlgoAPI_Chamfer::build(const GeomShapePtr& theBaseSolid,
+                                const ListOfShape&  theChamferShapes,
+                                const std::map<GeomShapePtr, GeomShapePtr> aMapEdgeFace,
+                                const bool performDistances,
+                                const double aVal1,
+                                const double aVal2)
+{
+  TopoDS_Shape aShapeBase = theBaseSolid->impl<TopoDS_Shape>();
+  TopTools_IndexedDataMapOfShapeListOfShape M;
+  TopExp::MapShapesAndAncestors(aShapeBase, TopAbs_EDGE, TopAbs_FACE, M);
+
+  // create chamfer builder
+  BRepFilletAPI_MakeChamfer* aChamferBuilder =
+      new BRepFilletAPI_MakeChamfer(aShapeBase);
+  setImpl(aChamferBuilder);
+  setBuilderType(OCCT_BRepBuilderAPI_MakeShape);
+
+  for (ListOfShape::const_iterator anIt = theChamferShapes.begin();
+     anIt != theChamferShapes.end(); ++anIt) {
+    if ((*anIt)->isEdge()) {
+      TopoDS_Edge E = (*anIt)->impl<TopoDS_Edge>();
+      if (aMapEdgeFace.find(*anIt) != aMapEdgeFace.end()) {
+        //TopoDS_Face F = (aMapEdgeFace[*anIt])->impl<TopoDS_Face>();
+        TopoDS_Face F = (aMapEdgeFace.at(*anIt))->impl<TopoDS_Face>();
+        if (!BRepTools::IsReallyClosed(E,F) && !BRep_Tool::Degenerated(E) &&
+              M.FindFromKey(E).Extent() == 2) {
+          if (performDistances) {
+              aChamferBuilder->Add(aVal1, aVal2, E, F);
+            } else {
+              aChamferBuilder->AddDA(aVal1, aVal2 * M_PI / 180., E, F);
+            }
+          }
+      } else {
+        const TopTools_ListOfShape& aFacesList = M.FindFromKey(E);
+        TopoDS_Face F = TopoDS::Face(aFacesList.First());
+        if (performDistances) {
+          aChamferBuilder->Add(aVal1, aVal2, E, F);
+        } else {
+          aChamferBuilder->AddDA(aVal1, aVal2 * M_PI / 180., E, F);
+        }
+      }
+    }
+  }
+
+  // build and get result
+  aChamferBuilder->Build();
+  if (!aChamferBuilder->IsDone())
+    return;
+  const TopoDS_Shape& aResult = aChamferBuilder->Shape();
+
+  std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
+  aShape->setImpl(new TopoDS_Shape(aResult));
+  setShape(aShape);
+  setDone(true);
+}
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Chamfer.h b/src/GeomAlgoAPI/GeomAlgoAPI_Chamfer.h
new file mode 100644 (file)
index 0000000..4061ef2
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright (C) 2017-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 GeomAlgoAPI_Chamfer_H_
+#define GeomAlgoAPI_Chamfer_H_
+
+#include <GeomAlgoAPI.h>
+#include <GeomAlgoAPI_MakeShape.h>
+
+#include <GeomAPI_Shape.h>
+//#include <GeomAPI_Edge.h>
+//#include <GeomAPI_Face.h>
+
+/// \class GeomAlgoAPI_Chamfer
+/// \ingroup DataAlgo
+/// \brief Perform chamfer
+class GeomAlgoAPI_Chamfer : public GeomAlgoAPI_MakeShape
+{
+public:
+  /// Run chamfer operation with two distances or with a distance and an angle .
+  /// \param theBaseSolid      a changing solid
+  /// \param theChamferShapes  list of edges the chamfer is performed on
+  /// \param aMapEdgeFace      map that associates an edge to a face when the chamfer is applied to a face
+  /// \param performDistances  boolean that indicates whether the operation is performed with two distances or not
+  /// \param aVal1             double D1 if performDistances is true or D
+  /// \param aVal2             double D2 if performDistances is true or Angle
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_Chamfer(const GeomShapePtr& theBaseSolid,
+                                         const ListOfShape&  theChamferShapes,
+                                         const std::map<GeomShapePtr, GeomShapePtr> aMapEdgeFace,
+                                         const bool performDistances,
+                                         const double aVal1,
+                                         const double aVal2);
+
+private:
+  /// Perform chamfer operation.
+  /// \param theBaseSolid    a changing solid
+  /// \param theChamferShapes  list of edges the chamfer is performed on
+  /// \param aMapEdgeFace      map that associates an edge to a face when the chamfer is applied to a face
+  /// \param performDistances  boolean that indicates whether the operation is performed with two distances or not
+  /// \param aVal1             double D1 if performDistances is true or D
+  /// \param aVal2             double D2 if performDistances is true or Angle
+  GEOMALGOAPI_EXPORT void build(const GeomShapePtr& theBaseSolid,
+                                const ListOfShape&  theChamferShapes,
+                                const std::map<GeomShapePtr, GeomShapePtr> aMapEdgeFace,
+                                const bool performDistances,
+                                const double aVal1,
+                                const double aVal2);
+};
+
+#endif
index 500fbf8e6fac56cfa6bea0819585835fa3ba892e..cc1ff67b2f6b7e041338607ae48be3c40c1048fb 100644 (file)
@@ -313,12 +313,10 @@ void GeomAlgoAPI_Prism::buildByPlanes(const GeomShapePtr             theBaseShap
   std::shared_ptr<GeomAPI_Pnt> aFromPnt(
     new GeomAPI_Pnt(aFromLoc->xyz()->added(anExtDir->multiplied(
                     aSign ? theFromSize : -theFromSize))));
-  GeomShapePtr aBoundingFromShape = GeomAlgoAPI_FaceBuilder::planarFace(aFromPnt, aFromDir);
 
   std::shared_ptr<GeomAPI_Pnt> aToPnt(
     new GeomAPI_Pnt(aToLoc->xyz()->added(anExtDir->multiplied(
                     aSign ? -theToSize : theToSize))));
-  GeomShapePtr aBoundingToShape = GeomAlgoAPI_FaceBuilder::planarFace(aToPnt, aToDir);
 
   // Getting bounding box for base shape.
   Bnd_Box aBndBox;
@@ -382,6 +380,9 @@ void GeomAlgoAPI_Prism::buildByPlanes(const GeomShapePtr             theBaseShap
     new GeomAlgoAPI_MakeShape(aPrismBuilder)));
   TopoDS_Shape aResult = aPrismBuilder->Shape();
 
+  BRepBndLib::Add(aResult, aBndBox);
+  Standard_Real aBndBoxSize = aBndBox.CornerMin().Distance(aBndBox.CornerMax());
+
   // Orienting bounding planes.
   std::shared_ptr<GeomAPI_Pnt> aCentreOfMass = GeomAlgoAPI_ShapeTools::centreOfMass(theBaseShape);
   const gp_Pnt& aCentrePnt = aCentreOfMass->impl<gp_Pnt>();
@@ -392,44 +393,42 @@ void GeomAlgoAPI_Prism::buildByPlanes(const GeomShapePtr             theBaseShap
   Standard_Real aFromParameter = aFromIntAna.ParamOnConic(1);
   if(aToParameter > aFromParameter) {
     gp_Vec aVec = aToDir->impl<gp_Dir>();
-    if((aVec * anExtVec) > 0) {
+    if((aVec * anExtVec) > 0)
       aToDir->setImpl(new gp_Dir(aVec.Reversed()));
-      aBoundingToShape = GeomAlgoAPI_FaceBuilder::planarFace(aToPnt, aToDir);
-    }
     aVec = aFromDir->impl<gp_Dir>();
-    if((aVec * anExtVec) < 0) {
+    if((aVec * anExtVec) < 0)
       aFromDir->setImpl(new gp_Dir(aVec.Reversed()));
-      aBoundingFromShape = GeomAlgoAPI_FaceBuilder::planarFace(aFromPnt, aFromDir);
-    }
   } else {
     gp_Vec aVec = aToDir->impl<gp_Dir>();
-    if((aVec * anExtVec) < 0) {
+    if((aVec * anExtVec) < 0)
       aToDir->setImpl(new gp_Dir(aVec.Reversed()));
-      aBoundingToShape = GeomAlgoAPI_FaceBuilder::planarFace(aToPnt, aToDir);
-    }
     aVec = aFromDir->impl<gp_Dir>();
-    if((aVec * anExtVec) > 0) {
+    if((aVec * anExtVec) > 0)
       aFromDir->setImpl(new gp_Dir(aVec.Reversed()));
-      aBoundingFromShape = GeomAlgoAPI_FaceBuilder::planarFace(aFromPnt, aFromDir);
-    }
   }
 
-  // Making solids from bounding planes.
-  TopoDS_Shell aToShell, aFromShell;
-  TopoDS_Solid aToSolid, aFromSolid;
+  static const double THE_FACE_SIZE_COEFF = 10.0;
+  GeomShapePtr aBoundingFromShape =
+      GeomAlgoAPI_FaceBuilder::squareFace(aFromPnt, aFromDir, THE_FACE_SIZE_COEFF * aBndBoxSize);
+  GeomShapePtr aBoundingToShape =
+      GeomAlgoAPI_FaceBuilder::squareFace(aToPnt, aToDir, THE_FACE_SIZE_COEFF * aBndBoxSize);
+
+  // bounding planes
   const TopoDS_Shape& aToShape   = aBoundingToShape->impl<TopoDS_Shape>();
   const TopoDS_Shape& aFromShape = aBoundingFromShape->impl<TopoDS_Shape>();
   TopoDS_Face aToFace   = TopoDS::Face(aToShape);
   TopoDS_Face aFromFace = TopoDS::Face(aFromShape);
-  BRep_Builder aBoundingBuilder;
-  aBoundingBuilder.MakeShell(aToShell);
-  aBoundingBuilder.Add(aToShell, aToShape);
-  aBoundingBuilder.MakeShell(aFromShell);
-  aBoundingBuilder.Add(aFromShell, aFromShape);
-  aBoundingBuilder.MakeSolid(aToSolid);
-  aBoundingBuilder.Add(aToSolid, aToShell);
-  aBoundingBuilder.MakeSolid(aFromSolid);
-  aBoundingBuilder.Add(aFromSolid, aFromShell);
+
+  // Solid based on "To" bounding plane
+  gp_Vec aNormal = aToDir->impl<gp_Dir>();
+  BRepPrimAPI_MakePrism* aToPrismBuilder =
+      new BRepPrimAPI_MakePrism(aToShape, aNormal * (-2.0 * aBndBoxSize));
+  if (!aToPrismBuilder || !aToPrismBuilder->IsDone()) {
+    return;
+  }
+  this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
+    new GeomAlgoAPI_MakeShape(aToPrismBuilder)));
+  TopoDS_Shape aToSolid = aToPrismBuilder->Shape();
 
   // Cutting with to plane.
   BRepAlgoAPI_Cut* aToCutBuilder = new BRepAlgoAPI_Cut(aResult, aToSolid);
@@ -444,14 +443,30 @@ void GeomAlgoAPI_Prism::buildByPlanes(const GeomShapePtr             theBaseShap
     aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
   }
   if (theTypeToExp == GeomAPI_Shape::FACE || theTypeToExp == GeomAPI_Shape::COMPOUND) {
-    const TopTools_ListOfShape& aToShapes = aToCutBuilder->Modified(aToShape);
-    for(TopTools_ListIteratorOfListOfShape anIt(aToShapes); anIt.More(); anIt.Next()) {
-      GeomShapePtr aGeomSh = toShape(anIt.Value());
-      fixOrientation(aGeomSh);
-      this->addToShape(aGeomSh);
+    TopTools_ListOfShape aPrismShapes = aToPrismBuilder->Modified(aToShape);
+    if (aPrismShapes.IsEmpty())
+      aPrismShapes.Append(aToShape);
+    for (TopTools_ListIteratorOfListOfShape anIt1(aPrismShapes); anIt1.More(); anIt1.Next()) {
+      const TopTools_ListOfShape& aToShapes = aToCutBuilder->Modified(anIt1.Value());
+      for (TopTools_ListIteratorOfListOfShape anIt2(aToShapes); anIt2.More(); anIt2.Next()) {
+        GeomShapePtr aGeomSh = toShape(anIt2.Value());
+        fixOrientation(aGeomSh);
+        this->addToShape(aGeomSh);
+      }
     }
   }
 
+  // Solid based on "From" bounding plane
+  aNormal = aFromDir->impl<gp_Dir>();
+  BRepPrimAPI_MakePrism* aFromPrismBuilder =
+      new BRepPrimAPI_MakePrism(aFromShape, aNormal * (-2.0 * aBndBoxSize));
+  if (!aFromPrismBuilder || !aFromPrismBuilder->IsDone()) {
+    return;
+  }
+  this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
+    new GeomAlgoAPI_MakeShape(aFromPrismBuilder)));
+  TopoDS_Shape aFromSolid = aFromPrismBuilder->Shape();
+
   // Cutting with from plane.
   BRepAlgoAPI_Cut* aFromCutBuilder = new BRepAlgoAPI_Cut(aResult, aFromSolid);
   aFromCutBuilder->Build();
@@ -469,11 +484,16 @@ void GeomAlgoAPI_Prism::buildByPlanes(const GeomShapePtr             theBaseShap
     aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
   }
   if (theTypeToExp == GeomAPI_Shape::FACE || theTypeToExp == GeomAPI_Shape::COMPOUND) {
-    const TopTools_ListOfShape& aFromShapes = aFromCutBuilder->Modified(aFromShape);
-    for(TopTools_ListIteratorOfListOfShape anIt(aFromShapes); anIt.More(); anIt.Next()) {
-      GeomShapePtr aGeomSh = toShape(anIt.Value());
-      fixOrientation(aGeomSh);
-      this->addFromShape(aGeomSh);
+    TopTools_ListOfShape aPrismShapes = aFromPrismBuilder->Modified(aFromShape);
+    if (aPrismShapes.IsEmpty())
+      aPrismShapes.Append(aFromShape);
+    for (TopTools_ListIteratorOfListOfShape anIt1(aPrismShapes); anIt1.More(); anIt1.Next()) {
+      const TopTools_ListOfShape& aFromShapes = aFromCutBuilder->Modified(anIt1.Value());
+      for (TopTools_ListIteratorOfListOfShape anIt2(aFromShapes); anIt2.More(); anIt2.Next()) {
+        GeomShapePtr aGeomSh = toShape(anIt2.Value());
+        fixOrientation(aGeomSh);
+        this->addFromShape(aGeomSh);
+      }
     }
   }
 
index 264c6bd30367566b8e8d401cf51d0cbaef9c7f38..24fc81624b9355d7731cbc1a18da1af01c54a269 100644 (file)
@@ -79,30 +79,8 @@ void GeomAlgoAPI_Sewing::build(const ListOfShape& theShapes)
 }
 
 //==================================================================================================
-#include <GeomAPI_ShapeExplorer.h>
 #include <GeomAPI_ShapeIterator.h>
 
-typedef std::map<GeomShapePtr, ListOfShape, GeomAPI_Shape::Comparator> MapFaceSolid;
-static void facesBelongingToSolids(const GeomShapePtr& theShape,
-                                   MapFaceSolid& theShapeRelations)
-{
-  for (GeomAPI_ShapeExplorer aSolidExp(theShape, GeomAPI_Shape::SHELL);
-       aSolidExp.more(); aSolidExp.next()) {
-    GeomShapePtr aSolid = aSolidExp.current();
-    for (GeomAPI_ShapeExplorer aFaceExp(aSolid, GeomAPI_Shape::FACE);
-         aFaceExp.more(); aFaceExp.next())
-      theShapeRelations[aFaceExp.current()].push_back(aSolid);
-  }
-}
-
-static bool isShapeInList(const GeomShapePtr& theShape, const ListOfShape& theList)
-{
-  for (ListOfShape::const_iterator anIt = theList.begin(); anIt != theList.end(); ++anIt)
-    if (theShape->isEqual(*anIt))
-      return true;
-  return false;
-}
-
 void GeomAlgoAPI_Sewing::modified(const std::shared_ptr<GeomAPI_Shape> theShape,
                                   ListOfShape& theHistory)
 {
index 9f7f5ec7848bf162c2355050222202457f16e86d..55e1e6df9c6fbffb88afd952012172ca61b4781a 100644 (file)
@@ -45,6 +45,8 @@ std::string File_Tools::extension(const std::string& theFileName)
   TCollection_AsciiString aFileName(theFileName.c_str());
   OSD_Path aPath(aFileName);
   TCollection_AsciiString anExtension = aPath.Extension();
+  if (anExtension.Length() < 2)
+    return "";
   // TCollection_AsciiString are numbered from 1
   anExtension = anExtension.SubString(2, anExtension.Length());
   anExtension.UpperCase();
index 56f93b2bfaf7763eb1223a4dd1b42f320807f10d..ca3ebc7a2aef4c871355f0c678c700ca4844d958 100644 (file)
@@ -52,7 +52,7 @@ bool GeomValidators_MinObjectsSelected::isValid(const std::shared_ptr<ModelAPI_F
 
   if(anObjectsNb < aMinObjectsNb) {
     theError = "Error: Attribute \"%1\" should contain at least %2 items.";
-    theError.arg(aSelectionListId).arg(theArguments.back());
+    theError.arg(aSelectionListId).arg(aMinObjectsNb);
     return false;
   }
 
index de62f8b742a3e692580d06568948665085e89da7..57ef46d48b4c0e98a8363ed934e1eb2dd4884e1e 100644 (file)
@@ -227,6 +227,26 @@ bool InitializationPlugin_PyInterp::initContext()
   _local_context = PyDict_New();
   Py_INCREF(_local_context);
 
+  // to avoid "help()" hang in the python console
+  const static char* aHelpTxt = "def help(): print(\"Available modules:\\n"
+    "  salome.shaper.model : higher level access to features and data model\\n"
+    "  BuildAPI            : Build plugin features allowing to build shapes\\n"
+    "  ConfigAPI           : configuration management: preferences and XML properties\\n"
+    "  ConstructionAPI     : Construction plugin for auxiliary features creation\\n"
+    "  EventsAPI           : application events receiving and emitting manager\\n"
+    "  ExchangeAPI         : Exchange plugin with import/export features\\n"
+    "  FeaturesAPI         : Features plugin with general 3D features\\n"
+    "  GeomAlgoAPI         : geometrical algorithms\\n"
+    "  GeomAPI             : geometrical data structures\\n"
+    "  GeomDataAPI         : specific geometrical data structures stored in the data model\\n"
+    "  ModelAPI            : general low-level interface to access data model\\n"
+    "  ModelHighAPI        : general high-level interface to access data model\\n"
+    "  ParametersAPI       : Parameters plugin for parameters feature management\\n"
+    "  PartSetAPI          : PartSet plugin for management Parts features\\n"
+    "  SketchAPI           : Sketch plugin with all sketch features\")";
+
+  PyRun_SimpleString(aHelpTxt);
+
   return PyRun_SimpleString("from math import *") == 0;
 }
 
index e9c92ad53de831ba8267f4c58d38c73214489675..ff194dac58e821903d20d866074e6cb6efb238ad 100644 (file)
@@ -29,6 +29,7 @@
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_ResultGroup.h>
 #include <ModelAPI_ResultPart.h>
 #include <ModelAPI_CompositeFeature.h>
 #include <ModelAPI_Tools.h>
@@ -180,6 +181,9 @@ bool Model_AttributeSelection::setValue(const ObjectPtr& theContext,
     aSelLab.ForgetAllAttributes(true);
     TDataStd_UAttribute::Set(aSelLab, kPART_REF_ID);
     selectPart(std::dynamic_pointer_cast<ModelAPI_Result>(theContext), theSubShape);
+  } else if (theContext->groupName() == ModelAPI_ResultGroup::group()) {
+    aSelLab.ForgetAllAttributes(true);
+    TDataStd_UAttribute::Set(aSelLab, kSIMPLE_REF_ID);
   } else { // check the feature context: parent-Part of this feature should not be used
     FeaturePtr aFeatureContext = std::dynamic_pointer_cast<ModelAPI_Feature>(theContext);
     if (aFeatureContext.get()) {
@@ -892,8 +896,11 @@ void Model_AttributeSelection::selectSubShape(
     // the whole result selection check
     if (aSubShapeName.find('/') == std::string::npos) {
       ObjectPtr aRes = aDoc->objectByName(ModelAPI_ResultConstruction::group(), aSubShapeName);
-      if (!aRes.get())
+      if (!aRes.get()) {
         aRes = aDoc->objectByName(ModelAPI_ResultBody::group(), aSubShapeName);
+        if (!aRes.get())
+          aRes = aDoc->objectByName(ModelAPI_ResultGroup::group(), aSubShapeName);
+      }
       if (aRes.get()) {
         setValue(aRes, anEmptyShape);
         return;
index 082a6c60fd51f13be8e96a2cacab2d9b536eac75..b7a295935dd09db70ae86de99417a1ea951a0b9c 100644 (file)
@@ -892,9 +892,10 @@ void Model_Document::undoInternal(const bool theWithSubs, const bool theSynchron
     myDoc->Undo();
   }
 
+  std::set<int> aSubs;
   if (theWithSubs) {
     // undo for all subs
-    const std::set<int> aSubs = subDocuments();
+    aSubs = subDocuments();
     std::set<int>::iterator aSubIter = aSubs.begin();
     for (; aSubIter != aSubs.end(); aSubIter++) {
       if (!subDoc(*aSubIter)->myObjs)
@@ -907,6 +908,19 @@ void Model_Document::undoInternal(const bool theWithSubs, const bool theSynchron
     myObjs->synchronizeFeatures(aDeltaLabels, true, false, false, isRoot());
     // update the current features status
     setCurrentFeature(currentFeature(false), false);
+
+    if (theWithSubs) {
+      // undo for all subs
+      const std::set<int> aNewSubs = subDocuments();
+      std::set<int>::iterator aNewSubIter = aNewSubs.begin();
+      for (; aNewSubIter != aNewSubs.end(); aNewSubIter++) {
+        // synchronize only newly appeared documents
+        if (!subDoc(*aNewSubIter)->myObjs || aSubs.find(*aNewSubIter) != aSubs.end())
+          continue;
+        TDF_LabelList anEmptyDeltas;
+        subDoc(*aNewSubIter)->myObjs->synchronizeFeatures(anEmptyDeltas, true, false, true, true);
+      }
+    }
   }
 }
 
index f0bd858070c7b9ac6cf9fcccfb29d1f2d23f7349..152aaaeb84ee27a8c4211c1c3d3618dae7221f50 100644 (file)
@@ -886,6 +886,19 @@ void Model_Objects::synchronizeFeatures(
             std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
             for(; anAttr != anAttrs.end(); anAttr++)
               (*anAttr)->reinit();
+            // if feature contains results, re-init them too
+            if (aFeature.get()) {
+              std::list<ResultPtr> aResults;
+              ModelAPI_Tools::allResults(aFeature, aResults);
+              std::list<ResultPtr>::iterator aResIter = aResults.begin();
+              for(; aResIter != aResults.end(); aResIter++) {
+                std::list<std::shared_ptr<ModelAPI_Attribute> > anAttrs =
+                  (*aResIter)->data()->attributes("");
+                std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
+                for(; anAttr != anAttrs.end(); anAttr++)
+                  (*anAttr)->reinit();
+              }
+            }
           }
         }
         ModelAPI_EventCreator::get()->sendUpdated(anObject, anUpdateEvent);
@@ -1835,6 +1848,10 @@ void Model_Objects::updateResults(FeaturePtr theFeature, std::set<FeaturePtr>& t
     }
   }
 
+  // it may be on undo
+  if (!theFeature->data() || !theFeature->data()->isValid() || theFeature->isDisabled())
+    return;
+
   // check the existing results and remove them if there is nothing on the label
   std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
   while(aResIter != theFeature->results().cend()) {
@@ -1851,9 +1868,6 @@ void Model_Objects::updateResults(FeaturePtr theFeature, std::set<FeaturePtr>& t
     }
     aResIter++;
   }
-  // it may be on undo
-  if (!theFeature->data() || !theFeature->data()->isValid() || theFeature->isDisabled())
-    return;
   // check that results are presented on all labels
   int aResSize = int(theFeature->results().size());
   TDF_ChildIterator aLabIter(resultLabel(theFeature->data(), 0).Father());
index 9b5dd872929d5411888083f73e4f44f62b04ad84..997eeab619de6daf694e0788b623ca2c9b88f7ce 100644 (file)
 
 #include <algorithm>
 
+typedef NCollection_IndexedDataMap<TopoDS_Face, TColStd_ListOfInteger> MapFaceToEdgeIndices;
+
+/// Convert each edge of sketch to corresponding integer value
+/// \param[in]  theComposite      sketch feature
+/// \param[out] theCurvesIndices  map curve to its index
+/// \param[out] theEdgesIndices   indexed edge
+/// \param[out] theEdgesNames     indexed name for edge
+static void indexingSketchEdges(
+    const CompositeFeaturePtr& theComposite,
+    NCollection_DataMap<Handle(Geom_Curve), int>& theCurvesIndices,
+    NCollection_DataMap<int, TopoDS_Edge>& theEdgesIndices,
+    std::map<int, std::string>& theEdgesNames);
+
+/// Convert each face to the list of indices of its edges
+/// \param[in]  theFaces          list of faces to proceed
+/// \param[in]  theCurvesIndices  index of each curve
+/// \param[out] theFaceEdges      map face to indices of its edges
+static void faceToEdgeIndices(
+    const ListOfShape& theFaces,
+    const NCollection_DataMap<Handle(Geom_Curve), int>& theCurvesIndices,
+    MapFaceToEdgeIndices& theFaceEdges);
+
+/// Assign faces to tags for the specified label
+/// \param theDocument        current document
+/// \param theShapeLabel      label to store shapes
+/// \param theName            name of the object
+/// \param theShape           shape to be stored to the label
+/// \param theFacesOrder      faces to be assigned to specified tag
+/// \param theUnorderedFaces  faces which may be stored to any tag
+/// \param theFaceEdges       indices of edges for each face
+/// \param theEdgesIndices    indices of edges
+/// \param theEdgesNames      named of edges
+static void storeFacesOnLabel(std::shared_ptr<Model_Document>& theDocument,
+                              TDF_Label& theShapeLabel,
+                              const std::string& theName,
+                              const TopoDS_Shape& theShape,
+                              NCollection_DataMap<int, TopoDS_Face>& theFacesOrder,
+                              NCollection_List<TopoDS_Face>& theUnorderedFaces,
+                              const MapFaceToEdgeIndices& theFaceEdges,
+                              const NCollection_DataMap<int, TopoDS_Edge>& theEdgesIndices,
+                              const std::map<int, std::string>& theEdgesNames);
+
 
 // identifier of the infinite result
 Standard_GUID kIS_INFINITE("dea8cc5a-53f2-49c1-94e8-a947bed20a9f");
@@ -275,56 +317,19 @@ void Model_ResultConstruction::storeShape(std::shared_ptr<GeomAPI_Shape> theShap
       NCollection_DataMap<Handle(Geom_Curve), int> aCurvesIndices;
       NCollection_DataMap<int, TopoDS_Edge> anEdgeIndices;
       std::map<int, std::string> aComponentsNames; // names of components that lay on index
-      const int aSubNum = aComposite->numberOfSubs();
-      for (int a = 0; a < aSubNum; a++) {
-        FeaturePtr aSub = aComposite->subFeature(a);
-        const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
-        std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResults.cbegin();
-        for (; aRes != aResults.cend(); aRes++) {
-          ResultConstructionPtr aConstr =
-            std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
-          if (aConstr->shape() && aConstr->shape()->isEdge()) {
-            TopoDS_Edge anEdge = TopoDS::Edge(aConstr->shape()->impl<TopoDS_Shape>());
-            Standard_Real aFirst, aLast;
-            Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
-            aCurvesIndices.Bind(aCurve, a);
-            anEdgeIndices.Bind(a, anEdge);
-            aComponentsNames[a] = shortName(aConstr);
-          }
-        }
-      }
+      indexingSketchEdges(aComposite, aCurvesIndices, anEdgeIndices, aComponentsNames);
 
       GeomAlgoAPI_SketchBuilder aSketchBuilder(aWirePtr->origin(), aWirePtr->dirX(),
                                                aWirePtr->norm(), aWirePtr);
       const ListOfShape& aFaces = aSketchBuilder.faces();
       // order is important to store faces in the same order if sketch is created from scratch
-      NCollection_IndexedDataMap<TopoDS_Face, TColStd_ListOfInteger> aNewIndices; // edges indices
-      std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator aFIter = aFaces.begin();
-      for (; aFIter != aFaces.end(); aFIter++) {
-        std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(*aFIter));
-        // put them to a label, trying to keep the same faces on the same labels
-        if (aFace.get() && !aFace->isNull()) {
-          TopoDS_Face aTopoFace = TopoDS::Face(aFace->impl<TopoDS_Shape>());
-          aNewIndices.Add(aTopoFace, TColStd_ListOfInteger());
-          // keep new indices of sub-elements used in this face
-          for (TopExp_Explorer anEdges(aTopoFace, TopAbs_EDGE); anEdges.More(); anEdges.Next()) {
-            TopoDS_Edge anEdge = TopoDS::Edge(anEdges.Current());
-            Standard_Real aFirst, aLast;
-            Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
-            if (aCurvesIndices.IsBound(aCurve)) {
-              int anIndex = aCurvesIndices.Find(aCurve);
-              if ((aFirst > aLast) != (anEdge.Orientation() == TopAbs_REVERSED))
-                anIndex = -anIndex;
-              aNewIndices.ChangeFromKey(aTopoFace).Append(anIndex);
-            }
-          }
-        }
-      }
+      MapFaceToEdgeIndices aNewIndices; // edges indices
+      faceToEdgeIndices(aFaces, aCurvesIndices, aNewIndices);
+
       NCollection_DataMap<int, TopoDS_Face> aFacesOrder; // faces -> tag where they must be set
       NCollection_List<TopoDS_Face> anUnorderedFaces; // faces that may be located at any index
       // searching for the best new candidate to old location
-      NCollection_IndexedDataMap<TopoDS_Face, TColStd_ListOfInteger>::Iterator
-        aNewIter(aNewIndices);
+      MapFaceToEdgeIndices::Iterator aNewIter(aNewIndices);
       for (; aNewIter.More(); aNewIter.Next()) {
         double aBestFound = 0, aBestNotFound = 1.e+100;
         int aBestTag = 0;
@@ -364,105 +369,221 @@ void Model_ResultConstruction::storeShape(std::shared_ptr<GeomAPI_Shape> theShap
           anUnorderedFaces.Append(aNewIter.Key());
         }
       }
-      aShapeLab.ForgetAllAttributes(); // clear all previously stored
-      TDataStd_Name::Set(aShapeLab, aMyName.c_str()); // restore name forgotten
-      TNaming_Builder aBuilder(aShapeLab); // store the compound to get it ready on open of document
-      aBuilder.Generated(aShape);
-      aMyDoc->addNamingName(aShapeLab, aMyName);
-      // set new faces to the labels
-      int aCurrentTag = 1;
-      NCollection_List<TopoDS_Face>::Iterator anUnordered(anUnorderedFaces);
-      for(int aCurrentTag = 1; !aFacesOrder.IsEmpty() || anUnordered.More(); aCurrentTag++) {
-        TopoDS_Face aFaceToPut;
-        if (aFacesOrder.IsBound(aCurrentTag)) {
-          aFaceToPut = aFacesOrder.Find(aCurrentTag);
-          aFacesOrder.UnBind(aCurrentTag);
-        } else if (anUnordered.More()){
-          aFaceToPut = anUnordered.Value();
-          anUnordered.Next();
-        }
+      storeFacesOnLabel(aMyDoc, aShapeLab, aMyName, aShape, aFacesOrder, anUnorderedFaces,
+                        aNewIndices, anEdgeIndices, aComponentsNames);
+    }
+  }
+}
 
-        if (!aFaceToPut.IsNull()) {
-          TopTools_MapOfShape aFaceEdges;
-          for(TopExp_Explorer anEdges(aFaceToPut, TopAbs_EDGE); anEdges.More(); anEdges.Next()) {
-            aFaceEdges.Add(anEdges.Current());
-          }
+void Model_ResultConstruction::setFacesOrder(const std::list<GeomFacePtr>& theFaces)
+{
+  std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
+  if (aData && aData->isValid()) {
+    std::string aMyName = data()->name();
+    TDF_Label aShapeLab = aData->shapeLab();
+    GeomShapePtr aResShape = shape();
+    if (!aResShape.get() || aResShape->isNull()) {
+      // do nothing
+      return;
+    }
+    std::shared_ptr<Model_Document> aMyDoc =
+        std::dynamic_pointer_cast<Model_Document>(document());
+    const TopoDS_Shape& aShape = aResShape->impl<TopoDS_Shape>();
+    if (aShape.ShapeType() != TopAbs_VERTEX &&
+        aShape.ShapeType() != TopAbs_EDGE) {
+      ResultPtr aThisPtr = std::dynamic_pointer_cast<ModelAPI_Result>(data()->owner());
+      FeaturePtr aThisFeature = aMyDoc->feature(aThisPtr);
+      CompositeFeaturePtr aComposite =
+        std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aThisFeature);
+      if (!aComposite || aComposite->numberOfSubs() == 0)
+        return; // unknown case
+      // collect indices of curves of current composite
+      NCollection_DataMap<Handle(Geom_Curve), int> aCurvesIndices;
+      NCollection_DataMap<int, TopoDS_Edge> anEdgeIndices;
+      std::map<int, std::string> aComponentsNames; // names of components that lay on index
+      indexingSketchEdges(aComposite, aCurvesIndices, anEdgeIndices, aComponentsNames);
 
-          TDF_Label aLab = aShapeLab.FindChild(aCurrentTag);
-          TNaming_Builder aFaceBuilder(aLab);
-          aFaceBuilder.Generated(aFaceToPut);
-          // store also indices of the new face edges
-          Handle(TDataStd_IntPackedMap) aNewMap = TDataStd_IntPackedMap::Set(aLab);
-          const TColStd_ListOfInteger& aNewInd = aNewIndices.FindFromKey(aFaceToPut);
-          std::stringstream aName;
-          aName<<"Face";
-          TopExp_Explorer aPutEdges(aFaceToPut, TopAbs_EDGE);
-          TNaming_Builder *anEdgesBuilder = 0, *aVerticesBuilder = 0;
-          for(TColStd_ListOfInteger::Iterator anIter(aNewInd); anIter.More(); anIter.Next()) {
-            int anIndex = anIter.Value();
-            int aModIndex = anIndex > 0 ? anIndex : -anIndex;
-            aNewMap->Add(anIndex);
-            aName<<"-"<<aComponentsNames[aModIndex];
-            if (anIter.Value() > 0)
-              aName<<"f";
-            else
-              aName<<"r";
-            // collect all edges of the face which are modified in sub-label of the face
-            if (anEdgeIndices.IsBound(aModIndex) &&
-                !aFaceEdges.Contains(anEdgeIndices.Find(aModIndex))) {
-              if (!anEdgesBuilder) {
-                TDF_Label anEdgesLabel = aLab.FindChild(1);
-                anEdgesBuilder = new TNaming_Builder(anEdgesLabel);
-                std::ostringstream aSubName;
-                // tag is needed for Test1922 to distinguish sub-edges of different faces
-                aSubName<<"SubEdge_"<<aCurrentTag;
-                TDataStd_Name::Set(anEdgesLabel, aSubName.str().c_str());
-              }
-              anEdgesBuilder->Modify(anEdgeIndices.Find(aModIndex), aPutEdges.Current());
-            }
-            // put also modified vertices, otherwise vertex of original edge has no history
-            if (anEdgeIndices.IsBound(aModIndex)) {
-              TopExp_Explorer aVExpOld(anEdgeIndices.Find(aModIndex), TopAbs_VERTEX);
-              TopExp_Explorer aVExpNew(aPutEdges.Current(), TopAbs_VERTEX);
-              for(; aVExpNew.More() && aVExpOld.More(); aVExpNew.Next(), aVExpOld.Next()) {
-                if (!aVExpOld.Current().IsSame(aVExpNew.Current())) {
-                  if (!aVerticesBuilder) {
-                    TDF_Label aVertLabel = aLab.FindChild(2);
-                    aVerticesBuilder = new TNaming_Builder(aVertLabel);
-                    std::ostringstream aSubName;
-                    // tag is needed for Test1922 to distinguish sub-edges of different faces
-                    aSubName<<"SubVertex_"<<aCurrentTag;
-                    TDataStd_Name::Set(aVertLabel, aSubName.str().c_str());
-                  }
-                  aVerticesBuilder->Modify(aVExpOld.Current(), aVExpNew.Current());
-
-                }
-              }
+      ListOfShape aFaces;
+      NCollection_DataMap<int, TopoDS_Face> aFacesOrder; // faces -> tag where they must be set
+      NCollection_List<TopoDS_Face> anUnorderedFaces; // unordered faces are empty in this case
+      int aTagId = 0;
+      for (std::list<GeomFacePtr>::const_iterator aFIt = theFaces.begin();
+           aFIt != theFaces.end(); ++aFIt) {
+        aFaces.push_back(*aFIt);
+        aFacesOrder.Bind(++aTagId, (*aFIt)->impl<TopoDS_Face>());
+      }
+
+      MapFaceToEdgeIndices aNewIndices; // edges indices
+      faceToEdgeIndices(aFaces, aCurvesIndices, aNewIndices);
+
+      storeFacesOnLabel(aMyDoc, aShapeLab, aMyName, aShape, aFacesOrder, anUnorderedFaces,
+                        aNewIndices, anEdgeIndices, aComponentsNames);
+    }
+  }
+}
+
+// ==========================     Auxiliary functions     =========================================
+
+void storeFacesOnLabel(std::shared_ptr<Model_Document>& theDocument,
+                       TDF_Label& theShapeLabel,
+                       const std::string& theName,
+                       const TopoDS_Shape& theShape,
+                       NCollection_DataMap<int, TopoDS_Face>& theFacesOrder,
+                       NCollection_List<TopoDS_Face>& theUnorderedFaces,
+                       const MapFaceToEdgeIndices& theFaceEdges,
+                       const NCollection_DataMap<int, TopoDS_Edge>& theEdgesIndices,
+                       const std::map<int, std::string>& theEdgesNames)
+{
+  theShapeLabel.ForgetAllAttributes(); // clear all previously stored
+  TDataStd_Name::Set(theShapeLabel, theName.c_str()); // restore name forgotten
+  TNaming_Builder aBuilder(theShapeLabel); // store the compound to get it ready on open of document
+  aBuilder.Generated(theShape);
+  theDocument->addNamingName(theShapeLabel, theName);
+  // set new faces to the labels
+  int aCurrentTag = 1;
+  NCollection_List<TopoDS_Face>::Iterator anUnordered(theUnorderedFaces);
+  for (int aCurrentTag = 1; !theFacesOrder.IsEmpty() || anUnordered.More(); aCurrentTag++) {
+    TopoDS_Face aFaceToPut;
+    if (theFacesOrder.IsBound(aCurrentTag)) {
+      aFaceToPut = theFacesOrder.Find(aCurrentTag);
+      theFacesOrder.UnBind(aCurrentTag);
+    }
+    else if (anUnordered.More()) {
+      aFaceToPut = anUnordered.Value();
+      anUnordered.Next();
+    }
+
+    if (aFaceToPut.IsNull())
+      continue;
+
+    TopTools_MapOfShape aFaceEdges;
+    for (TopExp_Explorer anEdges(aFaceToPut, TopAbs_EDGE); anEdges.More(); anEdges.Next())
+      aFaceEdges.Add(anEdges.Current());
+
+    TDF_Label aLab = theShapeLabel.FindChild(aCurrentTag);
+    TNaming_Builder aFaceBuilder(aLab);
+    aFaceBuilder.Generated(aFaceToPut);
+    // store also indices of the new face edges
+    Handle(TDataStd_IntPackedMap) aNewMap = TDataStd_IntPackedMap::Set(aLab);
+    const TColStd_ListOfInteger& aNewInd = theFaceEdges.FindFromKey(aFaceToPut);
+    std::stringstream aName;
+    aName<<"Face";
+    TopExp_Explorer aPutEdges(aFaceToPut, TopAbs_EDGE);
+    TNaming_Builder *anEdgesBuilder = 0, *aVerticesBuilder = 0;
+    for(TColStd_ListOfInteger::Iterator anIter(aNewInd); anIter.More(); anIter.Next()) {
+      int anIndex = anIter.Value();
+      int aModIndex = anIndex > 0 ? anIndex : -anIndex;
+      aNewMap->Add(anIndex);
+      aName<<"-"<<theEdgesNames.find(aModIndex)->second;
+      if (anIter.Value() > 0)
+        aName<<"f";
+      else
+        aName<<"r";
+      // collect all edges of the face which are modified in sub-label of the face
+      if (theEdgesIndices.IsBound(aModIndex) &&
+          !aFaceEdges.Contains(theEdgesIndices.Find(aModIndex))) {
+        if (!anEdgesBuilder) {
+          TDF_Label anEdgesLabel = aLab.FindChild(1);
+          anEdgesBuilder = new TNaming_Builder(anEdgesLabel);
+          std::ostringstream aSubName;
+          // tag is needed for Test1922 to distinguish sub-edges of different faces
+          aSubName<<"SubEdge_"<<aCurrentTag;
+          TDataStd_Name::Set(anEdgesLabel, aSubName.str().c_str());
+        }
+        anEdgesBuilder->Modify(theEdgesIndices.Find(aModIndex), aPutEdges.Current());
+      }
+      // put also modified vertices, otherwise vertex of original edge has no history
+      if (theEdgesIndices.IsBound(aModIndex)) {
+        TopExp_Explorer aVExpOld(theEdgesIndices.Find(aModIndex), TopAbs_VERTEX);
+        TopExp_Explorer aVExpNew(aPutEdges.Current(), TopAbs_VERTEX);
+        for(; aVExpNew.More() && aVExpOld.More(); aVExpNew.Next(), aVExpOld.Next()) {
+          if (!aVExpOld.Current().IsSame(aVExpNew.Current())) {
+            if (!aVerticesBuilder) {
+              TDF_Label aVertLabel = aLab.FindChild(2);
+              aVerticesBuilder = new TNaming_Builder(aVertLabel);
+              std::ostringstream aSubName;
+              // tag is needed for Test1922 to distinguish sub-edges of different faces
+              aSubName<<"SubVertex_"<<aCurrentTag;
+              TDataStd_Name::Set(aVertLabel, aSubName.str().c_str());
             }
-            aPutEdges.Next();
-          }
-          if (anEdgesBuilder)
-            delete anEdgesBuilder;
-          if (aVerticesBuilder)
-            delete aVerticesBuilder;
-          TDataStd_Name::Set(aLab, TCollection_ExtendedString(aName.str().c_str()));
-          aMyDoc->addNamingName(aLab, aName.str());
-          // put also wires to sub-labels to correctly select them instead of collection by edges
-          int aWireTag = 3; // first tag is for SubEdge-s, second - for vertices
-          for(TopExp_Explorer aWires(aFaceToPut, TopAbs_WIRE); aWires.More(); aWires.Next()) {
-            TDF_Label aWireLab = aLab.FindChild(aWireTag);
-            TNaming_Builder aWireBuilder(aWireLab);
-            aWireBuilder.Generated(aWires.Current());
-            std::ostringstream aWireName;
-            aWireName<<aName.str()<<"_wire";
-            if (aWireTag > 3)
-              aWireName<<"_"<<aWireTag - 2;
-            TDataStd_Name::Set(aWireLab, aWireName.str().c_str());
-            aMyDoc->addNamingName(aWireLab, aWireName.str());
-            aWireTag++;
+            aVerticesBuilder->Modify(aVExpOld.Current(), aVExpNew.Current());
+
           }
         }
       }
+      aPutEdges.Next();
+    }
+    if (anEdgesBuilder)
+      delete anEdgesBuilder;
+    if (aVerticesBuilder)
+      delete aVerticesBuilder;
+    TDataStd_Name::Set(aLab, TCollection_ExtendedString(aName.str().c_str()));
+    theDocument->addNamingName(aLab, aName.str());
+    // put also wires to sub-labels to correctly select them instead of collection by edges
+    int aWireTag = 3; // first tag is for SubEdge-s, second - for vertices
+    for(TopExp_Explorer aWires(aFaceToPut, TopAbs_WIRE); aWires.More(); aWires.Next()) {
+      TDF_Label aWireLab = aLab.FindChild(aWireTag);
+      TNaming_Builder aWireBuilder(aWireLab);
+      aWireBuilder.Generated(aWires.Current());
+      std::ostringstream aWireName;
+      aWireName<<aName.str()<<"_wire";
+      if (aWireTag > 3)
+        aWireName<<"_"<<aWireTag - 2;
+      TDataStd_Name::Set(aWireLab, aWireName.str().c_str());
+      theDocument->addNamingName(aWireLab, aWireName.str());
+      aWireTag++;
+    }
+  }
+}
+
+void indexingSketchEdges(const CompositeFeaturePtr& theComposite,
+                         NCollection_DataMap<Handle(Geom_Curve), int>& theCurvesIndices,
+                         NCollection_DataMap<int, TopoDS_Edge>& theEdgesIndices,
+                         std::map<int, std::string>& theEdgesNames)
+{
+  const int aSubNum = theComposite->numberOfSubs();
+  for (int a = 0; a < aSubNum; a++) {
+    FeaturePtr aSub = theComposite->subFeature(a);
+    const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
+    std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResults.cbegin();
+    for (; aRes != aResults.cend(); aRes++) {
+      ResultConstructionPtr aConstr =
+        std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
+      if (aConstr->shape() && aConstr->shape()->isEdge()) {
+        TopoDS_Edge anEdge = TopoDS::Edge(aConstr->shape()->impl<TopoDS_Shape>());
+        Standard_Real aFirst, aLast;
+        Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
+        theCurvesIndices.Bind(aCurve, a);
+        theEdgesIndices.Bind(a, anEdge);
+        theEdgesNames[a] = shortName(aConstr);
+      }
+    }
+  }
+}
+
+void faceToEdgeIndices(const ListOfShape& theFaces,
+                       const NCollection_DataMap<Handle(Geom_Curve), int>& theCurvesIndices,
+                       MapFaceToEdgeIndices& theFaceEdges)
+{
+  std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator aFIter = theFaces.begin();
+  for (; aFIter != theFaces.end(); aFIter++) {
+    std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(*aFIter));
+    // put them to a label, trying to keep the same faces on the same labels
+    if (aFace.get() && !aFace->isNull()) {
+      TopoDS_Face aTopoFace = TopoDS::Face(aFace->impl<TopoDS_Shape>());
+      theFaceEdges.Add(aTopoFace, TColStd_ListOfInteger());
+      // keep new indices of sub-elements used in this face
+      for (TopExp_Explorer anEdges(aTopoFace, TopAbs_EDGE); anEdges.More(); anEdges.Next()) {
+        TopoDS_Edge anEdge = TopoDS::Edge(anEdges.Current());
+        Standard_Real aFirst, aLast;
+        Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
+        if (theCurvesIndices.IsBound(aCurve)) {
+          int anIndex = theCurvesIndices.Find(aCurve);
+          if ((aFirst > aLast) != (anEdge.Orientation() == TopAbs_REVERSED))
+            anIndex = -anIndex;
+          theFaceEdges.ChangeFromKey(aTopoFace).Append(anIndex);
+        }
+      }
     }
   }
 }
index a6913c4aeb91306cccc95eed11ba51daa5c78685..71a015a981740990be5858be751e12cbb8db646f 100644 (file)
@@ -58,6 +58,9 @@ class Model_ResultConstruction : public ModelAPI_ResultConstruction
   MODEL_EXPORT virtual int facesNum(const bool theUpdateNaming = true);
   /// if the construction result may be used as faces, this method returns face by zero based index
   MODEL_EXPORT virtual std::shared_ptr<GeomAPI_Face> face(const int theIndex);
+  /// Change the order of faces
+  MODEL_EXPORT
+  virtual void setFacesOrder(const std::list<std::shared_ptr<GeomAPI_Face> >& theFaces);
 
   /// By default object is not infinite.
   MODEL_EXPORT virtual bool isInfinite();
index 7a4c5cfaf740f12e177ec415a201f3c356e1ab05..87d1620f6b3644f3525ac35273734dda34f595b8 100644 (file)
 //
 
 #include <Model_ResultGroup.h>
+#include <Model_Data.h>
 #include <ModelAPI_AttributeSelectionList.h>
 
 #include <GeomAlgoAPI_CompoundBuilder.h>
 
 #include <Config_PropManager.h>
 
+#include <TDF_Label.hxx>
+#include <TDF_Reference.hxx>
+#include <TNaming_Builder.hxx>
+#include <TNaming_NamedShape.hxx>
+#include <TopoDS_Shape.hxx>
+
 Model_ResultGroup::Model_ResultGroup(std::shared_ptr<ModelAPI_Data> theOwnerData)
 {
   myOwnerData = theOwnerData;
@@ -40,7 +47,25 @@ void Model_ResultGroup::colorConfigInfo(std::string& theSection, std::string& th
 std::shared_ptr<GeomAPI_Shape> Model_ResultGroup::shape()
 {
   std::shared_ptr<GeomAPI_Shape> aResult;
-  if (myOwnerData) {
+  // obtain stored shape
+  std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
+  if (aData && aData->isValid()) {
+    TDF_Label aShapeLab = aData->shapeLab();
+    Handle(TDF_Reference) aRef;
+    if (aShapeLab.FindAttribute(TDF_Reference::GetID(), aRef)) {
+      aShapeLab = aRef->Get();
+    }
+    Handle(TNaming_NamedShape) aName;
+    if (aShapeLab.FindAttribute(TNaming_NamedShape::GetID(), aName)) {
+      TopoDS_Shape aShape = aName->Get();
+      if (!aShape.IsNull()) {
+        aResult.reset(new GeomAPI_Shape);
+        aResult->setImpl(new TopoDS_Shape(aShape));
+      }
+    }
+  }
+  // collect shapes selected in group
+  if (!aResult && myOwnerData) {
     AttributeSelectionListPtr aList = myOwnerData->selectionList("group_list");
     if (aList) {
       std::list<std::shared_ptr<GeomAPI_Shape> > aSubs;
@@ -57,3 +82,23 @@ std::shared_ptr<GeomAPI_Shape> Model_ResultGroup::shape()
   }
   return aResult;
 }
+
+void Model_ResultGroup::store(const GeomShapePtr& theShape)
+{
+  std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
+  if (aData) {
+    TDF_Label aShapeLab = aData->shapeLab();
+    aShapeLab.ForgetAttribute(TDF_Reference::GetID());
+    aShapeLab.ForgetAttribute(TNaming_NamedShape::GetID());
+
+    if (!theShape)
+      return;  // bad shape
+    TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
+    if (aShape.IsNull())
+      return;  // null shape inside
+
+    // store the new shape as primitive
+    TNaming_Builder aBuilder(aShapeLab);
+    aBuilder.Generated(aShape);
+  }
+}
index aa0c068dd5014ad09ab6e7cfb5cd101d1afee0d5..68e549d327d6ba8b493855a8c9e4c138917753dd 100644 (file)
@@ -41,6 +41,11 @@ public:
   /// Returns the compound of selected entities
   MODEL_EXPORT virtual std::shared_ptr<GeomAPI_Shape> shape();
 
+  /// \brief Stores the result of operation made on groups.
+  ///        Cleans the storage if empty shape is given.
+  /// param[in] theShape shape to store.
+  MODEL_EXPORT virtual void store(const GeomShapePtr& theShape);
+
   /// Removes the stored builders
   MODEL_EXPORT virtual ~Model_ResultGroup() {}
 
index 0f24b3829ab8584f33db216d8182656334b1f2e5..2a2cf8bff1b1124ff95a0afbf280e3cd58486440 100644 (file)
@@ -74,6 +74,8 @@ class ModelAPI_ResultConstruction : public ModelAPI_Result
   virtual int facesNum(const bool theUpdateNaming = true) = 0;
   /// if the construction result may be used as faces, this method returns face by zero based index
   virtual std::shared_ptr<GeomAPI_Face> face(const int theIndex) = 0;
+  /// Change the order of faces
+  virtual void setFacesOrder(const std::list<std::shared_ptr<GeomAPI_Face> >& theFaces) = 0;
 
   /// By default object is not infinite.
   virtual bool isInfinite() = 0;
index 8644fc1cfda754e909db316bf36c11e9f54c4eee..040f2a05ccbe3fc36d579337519dbbf9a5d297d8 100644 (file)
@@ -52,6 +52,11 @@ public:
     return RESULT_GROUP_COLOR;
   }
 
+  /// \brief Stores the result of operation made on groups.
+  ///        Cleans the storage if empty shape is given.
+  /// param[in] theShape shape to store.
+  MODELAPI_EXPORT virtual void store(const GeomShapePtr& theShape)
+  {}
 };
 
 //! Pointer on feature object
index ecaef91c0f50a562f190d668e4b465df03c117b0..0918ddaec0175632007a8a4484c58a3778d51d4e 100644 (file)
@@ -132,6 +132,10 @@ aFound = aPartDoc.findContainingFolder(Sketch_2.feature())
 assert(aFound[0].data().isEqual(aFolder.data()))
 assert(aFound[1] == 0)
 
+# check sketch is the last feature in the folder
+aLastFeature = Folder_2.lastVisibleFeature()
+assert(aLastFeature.getKind() == "Sketch")
+
 
 #=========================================================================
 # Test 3. Sketch could be removed from the folder
index 896af71efcf0385e682f72f244454bef69a068dd..f26df1e5d32b3b5610fb1c06347d111d0284936f 100644 (file)
 
 // std::list -> []
 %template(SelectionList) std::list<ModelHighAPI_Selection>;
+%template(SelectionListList) std::list<std::list<ModelHighAPI_Selection> >;
 %template(RefAttrList) std::list<ModelHighAPI_RefAttr>;
 %template(RefList) std::list<ModelHighAPI_Reference>;
 
index 409f1b4306313f2eb47a89eaae331be86122aa7d..c8e37dc1c6598fbffb86604342bdce884a57119d 100644 (file)
@@ -52,6 +52,7 @@
 #include <ModelAPI_Result.h>
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_ResultGroup.h>
 #include <ModelAPI_ResultPart.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Tools.h>
@@ -289,7 +290,8 @@ static void getShapeAndContext(const AttributeSelectionPtr& theAttrSelect,
     if (theAttrSelect->isGeometricalSelection() &&
         theShape.get() && theShape->shapeType() == GeomAPI_Shape::COMPOUND &&
         theContext.get() && !theShape->isEqual(theContext->shape()) &&
-        theContext->groupName() != ModelAPI_ResultPart::group()) {
+        theContext->groupName() != ModelAPI_ResultPart::group() &&
+        theContext->groupName() != ModelAPI_ResultGroup::group()) {
       GeomAPI_ShapeIterator anIt(theShape);
       theShape = anIt.current();
     }
@@ -1187,6 +1189,19 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const ResultPtr& theResult)
   return *this;
 }
 
+ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const std::list<ResultPtr>& theResults)
+{
+  *this << "[";
+  for (std::list<ResultPtr>::const_iterator anIt = theResults.begin();
+       anIt != theResults.end(); ++anIt) {
+    if (anIt != theResults.begin())
+      *this << ", ";
+    *this << *anIt;
+  }
+  *this << "]";
+  return *this;
+}
+
 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const ObjectPtr& theObject)
 {
   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
index f4d0be3eb82f3aeb07f2599e92f5fd12697ca0e1..ccd80c626bd8da98bc5c46553cd73418c83284bf 100644 (file)
@@ -287,6 +287,10 @@ public:
   MODELHIGHAPI_EXPORT
   ModelHighAPI_Dumper& operator<<(const ResultPtr& theResult);
 
+  /// Dump a list of results
+  MODELHIGHAPI_EXPORT
+  ModelHighAPI_Dumper& operator<<(const std::list<ResultPtr>& theResults);
+
   /// Dump Attribute
   MODELHIGHAPI_EXPORT ModelHighAPI_Dumper&
     operator<<(const std::shared_ptr<ModelAPI_Attribute>& theAttr);
index f8a1ff2c4d66fb68cb814c3c6e1a9296db2ba35a..a7ce541f2aa7a71e7bce714288104a660dbedfc3 100644 (file)
@@ -105,6 +105,7 @@ SET(PROJECT_HEADERS
   ModuleBase_ITreeNode.h
   ModuleBase_WidgetSelectionFilter.h
   ModuleBase_IStepPrs.h
+  ModuleBase_SelectionFilterType.h
 )
 
 SET(PROJECT_MOC_HEADERS
index 05d1f93ef2dbbcb1c0632000046c682d318135a0..03abb8233950ce89c26d887b94dd8c5206dc5b36 100644 (file)
@@ -71,6 +71,18 @@ ModuleBase_IModule::ModuleBase_IModule(ModuleBase_IWorkshop* theParent)
   //        SLOT(onMouseDoubleClick(QMouseEvent*)));
 }
 
+ModuleBase_IModule::~ModuleBase_IModule()
+{
+  std::map<ModuleBase_SelectionFilterType, Handle(SelectMgr_Filter)>::const_iterator aFiltersIt =
+    mySelectionFilters.begin();
+  for (; aFiltersIt != mySelectionFilters.end(); aFiltersIt++) {
+    Handle(SelectMgr_Filter) aFilter = aFiltersIt->second;
+    if (!aFilter.IsNull())
+      aFilter.Nullify();
+  }
+}
+
+
 void ModuleBase_IModule::launchModal(const QString& theCmdId)
 {
   bool isCommitted;
@@ -323,3 +335,35 @@ void ModuleBase_IModule::getXMLRepresentation(const std::string& theFeatureId,
   theXmlCfg = aWdgReader.featureWidgetCfg(theFeatureId);
   theDescription = aWdgReader.featureDescription(theFeatureId);
 }
+
+
+//******************************************************
+QIntList ModuleBase_IModule::selectionFilters()
+{
+  QIntList aTypes;
+
+  std::map<ModuleBase_SelectionFilterType, Handle(SelectMgr_Filter)>::const_iterator aFiltersIt =
+    mySelectionFilters.begin();
+  for (; aFiltersIt != mySelectionFilters.end(); aFiltersIt++)
+    aTypes.append(aFiltersIt->first);
+
+  return aTypes;
+}
+
+//******************************************************
+void ModuleBase_IModule::registerSelectionFilter(const ModuleBase_SelectionFilterType theFilterType,
+  const Handle(SelectMgr_Filter)& theFilter)
+{
+  mySelectionFilters[theFilterType] = theFilter;
+}
+
+//******************************************************
+Handle(SelectMgr_Filter) ModuleBase_IModule::selectionFilter(const int theType)
+{
+  ModuleBase_SelectionFilterType aType = (ModuleBase_SelectionFilterType)theType;
+
+  if (mySelectionFilters.find(aType) != mySelectionFilters.end())
+    return mySelectionFilters[aType];
+  else
+    return Handle(SelectMgr_Filter)();
+}
index 529c1f1531e94a02876c2d182f049c769fa4bf15..b748d6a148c2721b89fd659551cc38cf50f11c82 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "ModuleBase.h"
 #include "ModuleBase_IWorkshop.h"
+#include <ModuleBase_SelectionFilterType.h>
 
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Attribute.h>
@@ -76,7 +77,7 @@ class MODULEBASE_EXPORT ModuleBase_IModule : public QObject
    /// \param theParent instance of workshop interface
    ModuleBase_IModule(ModuleBase_IWorkshop* theParent);
 
-  virtual ~ModuleBase_IModule() {}
+   virtual ~ModuleBase_IModule();
 
   /// Stores the current selection
   virtual void storeSelection() {}
@@ -242,12 +243,18 @@ class MODULEBASE_EXPORT ModuleBase_IModule : public QObject
 
   /// Returns types of registered module selection filters
   /// \param theSelectionFilters [out] container of type value
-  virtual QIntList selectionFilters() { return QIntList(); }
+  virtual QIntList selectionFilters();
 
   /// Returns selection filter
   /// \param theType selection filter type
   /// \param theFilter instance of filter
-  virtual Handle(SelectMgr_Filter) selectionFilter(const int theType) = 0;
+  virtual Handle(SelectMgr_Filter) selectionFilter(const int theType);
+
+  /// Append selection filter into the module and type of the filter in internal container
+  /// \param theFilterType selection filter type
+  /// \param theFilter added filter
+  void registerSelectionFilter(const ModuleBase_SelectionFilterType theFilterType,
+    const Handle(SelectMgr_Filter)& theFilter);
 
   /// Return true if the custom presentation is activated
   /// \param theFlag a flag of level of customization, which means that only part of sub-elements
@@ -424,6 +431,9 @@ protected:
 
   /// Map of features in XML
   std::map<std::string, std::string> myFeaturesInFiles;
+
+  std::map<ModuleBase_SelectionFilterType, Handle(SelectMgr_Filter)> mySelectionFilters;
+
 };
 
 
diff --git a/src/ModuleBase/ModuleBase_SelectionFilterType.h b/src/ModuleBase/ModuleBase_SelectionFilterType.h
new file mode 100644 (file)
index 0000000..8b494f6
--- /dev/null
@@ -0,0 +1,34 @@
+// 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 ModuleBase_SelectionFilterType_H
+#define ModuleBase_SelectionFilterType_H
+
+#include "ModuleBase.h"
+
+/// Enumeration to specify module selection filters
+enum MODULEBASE_EXPORT ModuleBase_SelectionFilterType {
+  SF_GlobalFilter, /// filter for different documents, group results
+  SF_FilterInfinite, /// filter for infinite construction results
+  SF_ResultGroupNameFilter, /// filter for selection some kind of results
+  SF_SketchCirclePointFilter, /// filter for selection circle points on current sketch
+  SF_SketchPlaneFilter /// filter for selection in the current sketch plane only
+};
+
+#endif
index b528344ce493df558b99541aabaa011b1cdc12fd..a3c4d0ebdbf3c7c874d2abc25315c6594763d22d 100644 (file)
@@ -82,6 +82,8 @@
 #include <QMessageBox>
 #include <QAction>
 #include <QTextCodec>
+#include <QWindow>
+#include <QScreen>
 
 #include <sstream>
 #include <string>
@@ -152,7 +154,6 @@ void activateWindow(QWidget* theWidget, const QString& theInfo)
 
 void setFocus(QWidget* theWidget, const QString& theInfo)
 {
-  activateWindow(theWidget);
   theWidget->setFocus();
   // rectangle of focus is not visible on tool button widgets
   theWidget->repaint();
@@ -1299,6 +1300,36 @@ std::string generateName(const AttributePtr& theAttribute,
   return aName;
 }
 
+bool isSameShape(const TopoDS_Shape& theShape1, const TopoDS_Shape& theShape2)
+{
+  // In case of compound we cannot rely on simple comparison method.
+  // If the compound is generated by Group feature then this compound is alwais new.
+  // So, we have to compare content of these compounds
+  if (theShape1.ShapeType() != theShape2.ShapeType())
+    return false;
+
+  if (theShape1.ShapeType() != TopAbs_COMPOUND)
+    return theShape1.IsSame(theShape2);
+
+  TopoDS_Iterator aIt1(theShape1);
+  TopoDS_Iterator aIt2(theShape2);
+
+  for (; aIt1.More() && aIt2.More(); aIt1.Next(), aIt2.Next()) {
+    if (!(aIt1.Value()).IsSame(aIt2.Value()))
+      return false;
+  }
+  return true;
+}
+
+qreal currentPixelRatio()
+{
+  QWindowList aWnds = qApp->topLevelWindows();
+  if (aWnds.size() > 0)
+    return aWnds.first()->devicePixelRatio();
+  return qApp->primaryScreen()->devicePixelRatio();
+}
+
+
 } // namespace ModuleBase_Tools
 
 
index 4523b7d809106e23170060953120ac7bddf48a9e..2d1ad9227f50d12ab0d49e4da220256b374f5a77 100644 (file)
@@ -389,6 +389,12 @@ bool MODULEBASE_EXPORT isNameExist(const QString& theName, FeaturePtr theIgnoreP
 /// \theName a name of parameter
 FeaturePtr MODULEBASE_EXPORT findParameter(const QString& theName);
 
+/// Returns true if both shapes are the same. In case of compounds it
+/// compares their contents.
+/// \param theShape1 a first shape to compare
+/// \param theShape2 a second shape to compare
+/// \return true if both shapes are the same
+bool MODULEBASE_EXPORT isSameShape(const TopoDS_Shape& theShape1, const TopoDS_Shape& theShape2);
 
 //----------- Class members -------------
 /// Returns a name in the next form: attribute_feature_name/attribute_id
@@ -398,6 +404,8 @@ FeaturePtr MODULEBASE_EXPORT findParameter(const QString& theName);
 std::string MODULEBASE_EXPORT generateName(const AttributePtr& theAttribute,
   ModuleBase_IWorkshop* theWorkshop);
 
+/// Returns pixel ratio of a screen where main window is displayed
+qreal MODULEBASE_EXPORT currentPixelRatio();
 }
 
 #endif
index 7481d9f5d0a29f4ec0641d359431fd32404fb70b..1eb0232228c4e4b7eda7911f3718876da9981545 100644 (file)
@@ -53,11 +53,35 @@ public:
   Standard_EXPORT virtual
     Standard_Boolean IsOk(const Handle(SelectMgr_EntityOwner)& theOwner) const;
 
+  /// Add an object type name to list of non selectable objects
+  /// \param theType - a name of an object type
+  Standard_EXPORT void addNonSelectableType(const QString& theType)
+  {
+    if (!myNonSelectableTypes.contains(theType))
+      myNonSelectableTypes.append(theType);
+  }
+
+  /// Removes an object type name from list of non selectable objects
+  /// \param theType - a name of an object type
+  Standard_EXPORT void removeNonSelectableType(const QString& theType)
+  {
+    if (myNonSelectableTypes.contains(theType))
+      myNonSelectableTypes.removeAll(theType);
+  }
+
+  /// Returns list of non-selectable an object type names
+  Standard_EXPORT QStringList nonSelectableTypes() const
+  {
+    return myNonSelectableTypes;
+  }
+
   DEFINE_STANDARD_RTTIEXT(ModuleBase_ShapeDocumentFilter, SelectMgr_Filter)
 
 protected:
   /// Reference to workshop
   ModuleBase_IWorkshop* myWorkshop;
+
+  QStringList myNonSelectableTypes;
 };
 
 /**
index 531b7fa80f6e8da55c8fb52adf872256d72639ed..7191889876c70c5b4b58ceb8083e761ea6b35781 100644 (file)
@@ -246,7 +246,7 @@ QString ModuleBase_WidgetFileSelector::applyExtension(const QString& theFileName
   bool hasExtension = false;
   QStringList anExtensions = filterToExtensions(theFilter);
   foreach(const QString& anExtension, anExtensions) {
-    if (theFileName.endsWith(anExtension.section(".", 1, 1), Qt::CaseInsensitive)) {
+    if (theFileName.endsWith(QString(".") + anExtension.section(".", 1, 1), Qt::CaseInsensitive)) {
       hasExtension = true;
       break;
     }
index 349b61502e0921878fd37ddd801bddfe93520e27..1740c62ffd732e623fd73c1bc67091195791889b 100644 (file)
@@ -116,20 +116,26 @@ ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParen
   myIsSetSelectionBlocked(false), myCurrentHistoryIndex(-1),
   myIsFirst(true), myFiltersWgt(0)
 {
-  std::string aPropertyTypes = theData->getProperty("type_choice");
+  std::string aPropertyTypes = theData->getProperty("shape_types");
   QString aTypesStr = aPropertyTypes.c_str();
   myShapeTypes = aTypesStr.split(' ', QString::SkipEmptyParts);
   myIsUseChoice = theData->getBooleanAttribute("use_choice", false);
 
+  QString aAllowedList(theData->getProperty("allow_objects").c_str());
+  if (!aAllowedList.isEmpty())
+    myAllowedObjects = aAllowedList.split(' ', QString::SkipEmptyParts);
+
   QVBoxLayout* aMainLay = new QVBoxLayout(this);
   ModuleBase_Tools::adjustMargins(aMainLay);
 
   QStringList aIconsList = getIconsList(myShapeTypes);
   myTypeCtrl = new ModuleBase_ChoiceCtrl(this, myShapeTypes, aIconsList);
   myTypeCtrl->setLabel(tr("Type"));
-  myTypeCtrl->setValue(0);
+  if (!myShapeTypes.empty()) {
+    myTypeCtrl->setValue(0);
+    myDefMode = myShapeTypes.first().toStdString();
+  }
   aMainLay->addWidget(myTypeCtrl);
-  myDefMode = myShapeTypes.first().toStdString();
 
   // There is no sense to parameterize list of types while we can not parameterize selection mode
   // if the xml definition contains one type, the controls to select a type should not be shown
@@ -215,9 +221,26 @@ void ModuleBase_WidgetMultiSelector::activateCustom()
 {
   ModuleBase_WidgetSelector::activateCustom();
 
-  myWorkshop->module()->activateCustomPrs(myFeature,
+  ModuleBase_IModule* aModule = myWorkshop->module();
+  aModule->activateCustomPrs(myFeature,
                             ModuleBase_IModule::CustomizeHighlightedObjects, true);
   clearSelectedHistory();
+  if (myAllowedObjects.length() > 0) {
+    Handle(SelectMgr_Filter) aFilter = aModule->selectionFilter(SF_GlobalFilter);
+    if (!aFilter.IsNull()) {
+      Handle(ModuleBase_ShapeDocumentFilter) aDocFilter =
+        Handle(ModuleBase_ShapeDocumentFilter)::DownCast(aFilter);
+      if (!aDocFilter.IsNull()) {
+        QStringList aSelFilters = aDocFilter->nonSelectableTypes();
+        foreach(QString aType, aSelFilters) {
+          if (aSelFilters.contains(aType)) {
+            aDocFilter->removeNonSelectableType(aType);
+            myTmpAllowed.append(aType);
+          }
+        }
+      }
+    }
+  }
 }
 
 //********************************************************************
@@ -231,6 +254,20 @@ void ModuleBase_WidgetMultiSelector::deactivate()
 
   myWorkshop->module()->deactivateCustomPrs(ModuleBase_IModule::CustomizeHighlightedObjects, true);
   clearSelectedHistory();
+  if (myTmpAllowed.length() > 0) {
+    ModuleBase_IModule* aModule = myWorkshop->module();
+    Handle(SelectMgr_Filter) aFilter = aModule->selectionFilter(SF_GlobalFilter);
+    if (!aFilter.IsNull()) {
+      Handle(ModuleBase_ShapeDocumentFilter) aDocFilter =
+        Handle(ModuleBase_ShapeDocumentFilter)::DownCast(aFilter);
+      if (!aDocFilter.IsNull()) {
+        foreach(QString aType, myTmpAllowed) {
+          aDocFilter->addNonSelectableType(aType);
+        }
+      }
+    }
+    myTmpAllowed.clear();
+  }
 }
 
 //********************************************************************
@@ -259,12 +296,23 @@ bool ModuleBase_WidgetMultiSelector::storeValueCustom()
   std::string aType = anAttribute->attributeType();
   if (aType == ModelAPI_AttributeSelectionList::typeId()) {
     AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID());
-    std::string aMode = myTypeCtrl->textValue().toStdString();
-    if (myTypeCtrl->isVisible() && myIsFirst && (!myDefMode.empty()))
-      aMode = myDefMode;
+    if (myTypeCtrl->isVisible()) {
+      std::string aMode = myTypeCtrl->textValue().toStdString();
+      if (myIsFirst && (!myDefMode.empty()))
+        aMode = myDefMode;
 
-    aSelectionListAttr->setSelectionType(aMode);
-    myIsFirst = false;
+      aSelectionListAttr->setSelectionType(aMode);
+      myIsFirst = false;
+    } else { // no type, set the type as a first element of the list shape type when it is appeared
+      if (aSelectionListAttr->size()) {
+        AttributeSelectionPtr aSel = aSelectionListAttr->value(0);
+        GeomShapePtr aFirstVal = aSel->value();
+        if (!aFirstVal.get() && aSel->context().get())
+          aFirstVal = aSel->context()->shape();
+        if (aFirstVal.get() && !aFirstVal->isNull())
+          aSelectionListAttr->setSelectionType(aFirstVal->shapeTypeStr());
+      }
+    }
   }
   return true;
 }
index 1dec34d90856dd41359d592c55bb0f7201b350cf..f34e18ef568e40ffacf0ad776ebf6a952e3d7111 100644 (file)
@@ -50,12 +50,12 @@ class ModuleBase_FilterStarter;
 * \code
 * <multi_selector id="group_list" 
 *    tooltip="Select a set of objects" 
-*    type_choice="Vertices Edges Faces Solids" /> 
+*    shape_types="Vertices Edges Faces Solids" />
 * \endcode
 * It uses following parameters:
 * - id - is a name of corresponded attribute
 * - tooltip - a tooltip for the widget
-* - type_choice - list of expected shape types.
+* - shape_types - list of expected shape types.
 */
 class MODULEBASE_EXPORT ModuleBase_WidgetMultiSelector : public ModuleBase_WidgetSelector
 {
@@ -257,6 +257,8 @@ protected:
   ModuleBase_FilterStarter* myFiltersWgt;
 
   QObjectPtrList myVisibleObjects;
+  QStringList myAllowedObjects;
+  QStringList myTmpAllowed;
 };
 
 #endif /* MODULEBASE_WIDGETFILESELECTOR_H_ */
index 7f1a8a599ba8788c1480359033351033e43968a0..10437dca097d5844528e9b04e863f2cc412fc492 100644 (file)
@@ -52,6 +52,7 @@
 #include <QDialog>
 #include <QToolButton>
 #include <QCheckBox>
+#include <QDir>
 
 static FeaturePtr SelectorFeature;
 static std::string AttributeId;
@@ -98,6 +99,9 @@ ModuleBase_FilterStarter::ModuleBase_FilterStarter(const std::string& theFeature
 
 void ModuleBase_FilterStarter::onFiltersLaunch()
 {
+  static QString aHelpFileName = QString("FiltersPlugin") + QDir::separator() +
+    QString("FiltersPlugin.html");
+
   ModuleBase_Operation* aParentOp = myWorkshop->currentOperation();
   ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(aParentOp);
   if (aFeatureOp)
@@ -124,6 +128,7 @@ void ModuleBase_FilterStarter::onFiltersLaunch()
   FiltersFeaturePtr aFilters = aAttrList->filters();
   if (aFilters.get())
     aFOperation->setFeature(aFilters);
+  aFOperation->setHelpFileName(aHelpFileName);
   myWorkshop->processLaunchOperation(aFOperation);
 }
 
index b0c30bb74f4df4383f9cfa9376108179d44f3f82..7d701aaf55616c5e93f9c54a17a02be658caf427 100644 (file)
@@ -149,11 +149,13 @@ bool ModuleBase_WidgetSelector::acceptSubShape(const GeomShapePtr& theShape,
   if (aShape.get()) {
     // Check that the selection corresponds to selection type
     TopoDS_Shape aTopoShape = aShape->impl<TopoDS_Shape>();
-    aShapeType = aTopoShape.ShapeType();
-    // for compounds check sub-shapes: it may be compound of needed type:
-    // Booleans may produce compounds of Solids
-    if (aShapeType == TopAbs_COMPOUND) {
-      aShapeType = ModuleBase_Tools::getCompoundSubType(aTopoShape);
+    if (!aTopoShape.IsNull()) {
+      aShapeType = aTopoShape.ShapeType();
+      // for compounds check sub-shapes: it may be compound of needed type:
+      // Booleans may produce compounds of Solids
+      if (aShapeType == TopAbs_COMPOUND) {
+        aShapeType = ModuleBase_Tools::getCompoundSubType(aTopoShape);
+      }
     }
   }
 
index a08b1572bd5d343b85e313cd1fdb33c99c4cec64..d03062163d77941b0130eac26b983f5a6b7e2953 100644 (file)
@@ -33,6 +33,9 @@
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_Expression.h>
 
+#include <GeomDataAPI_Point.h>
+#include <GeomDataAPI_Point2D.h>
+
 #include <ModuleBase_Tools.h>
 
 #include <Events_Loop.h>
@@ -374,18 +377,40 @@ QList<QStringList> ParametersPlugin_WidgetParamsMgr::
             QStringList aValNames;
             aValNames << aReferenced->data()->name().c_str();
 
-            AttributeDoublePtr aDouble =
-              std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aAttr);
-            if (aDouble.get()) {
+            std::string aId = aAttr->attributeType();
+            if (aId == ModelAPI_AttributeDouble::typeId()) {
+              AttributeDoublePtr aDouble =
+                std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aAttr);
               aValNames << aDouble->text().c_str();
               aValNames << QString::number(aDouble->value());
-            } else {
+            }
+            else if (aId == ModelAPI_AttributeInteger::typeId()) {
               AttributeIntegerPtr aInt =
                 std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(aAttr);
-              if (aInt.get()) {
-                aValNames << aInt->text().c_str();
-                aValNames << QString::number(aInt->value());
-              }
+              aValNames << aInt->text().c_str();
+              aValNames << QString::number(aInt->value());
+            }
+            else if (aId == GeomDataAPI_Point::typeId()) {
+              std::shared_ptr<GeomDataAPI_Point> aPnt =
+                std::dynamic_pointer_cast<GeomDataAPI_Point>(aAttr);
+
+              QString aExpr = QString("%1,%2,%3").arg(aPnt->textX().c_str()).
+                arg(aPnt->textY().c_str()).arg(aPnt->textZ().c_str());
+              aValNames << aExpr;
+
+              QString aRes = QString("%1,%2,%3").arg(aPnt->x()).arg(aPnt->y()).arg(aPnt->z());
+              aValNames << aRes;
+            }
+            else if (aId == GeomDataAPI_Point2D::typeId()) {
+              std::shared_ptr<GeomDataAPI_Point2D> aPnt =
+                std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aAttr);
+
+              QString aExpr = QString("%1,%2").arg(aPnt->textX().c_str()).
+                arg(aPnt->textY().c_str());
+              aValNames << aExpr;
+
+              QString aRes = QString("%1,%2").arg(aPnt->x()).arg(aPnt->y());
+              aValNames << aRes;
             }
             aItemsList.append(aValNames);
             theFeatureList.append(aReferenced);
index b7e5ccbb1e62e2d116921ed8220e201ff44e65af..88ba16c9ad36518e8722fbb5326eea378693d354 100644 (file)
 
 IMPLEMENT_STANDARD_RTTIEXT(PartSet_GlobalFilter, ModuleBase_ShapeDocumentFilter);
 
+PartSet_GlobalFilter::PartSet_GlobalFilter(ModuleBase_IWorkshop* theWorkshop)
+  : ModuleBase_ShapeDocumentFilter(theWorkshop)
+{
+  addNonSelectableType(ModelAPI_ResultField::group().c_str());
+  addNonSelectableType(ModelAPI_ResultGroup::group().c_str());
+}
+
+
 Standard_Boolean PartSet_GlobalFilter::IsOk(const Handle(SelectMgr_EntityOwner)& theOwner) const
 {
   bool aValid = true;
@@ -63,8 +71,7 @@ Standard_Boolean PartSet_GlobalFilter::IsOk(const Handle(SelectMgr_EntityOwner)&
           if (aResultGroupName == ModelAPI_ResultPart::group()) {
             SessionPtr aMgr = ModelAPI_Session::get();
             aValid = aMgr->activeDocument() == aMgr->moduleDocument();
-          } else if (aResultGroupName == ModelAPI_ResultGroup::group() ||
-                     aResultGroupName == ModelAPI_ResultField::group()) {
+          } else if (myNonSelectableTypes.contains(aResultGroupName.c_str())) {
             aValid = Standard_False;
           } else
             aValid = Standard_True;
@@ -73,7 +80,7 @@ Standard_Boolean PartSet_GlobalFilter::IsOk(const Handle(SelectMgr_EntityOwner)&
           // only and there can not be Group feature
           FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
           if (aFeature) {
-            aValid = aFeature->getKind() != "Group";
+            aValid = !myNonSelectableTypes.contains(aFeature->getKind().c_str());
           } else
             aValid = Standard_True;
         }
index 55cde03bbdb4e31d62e86dc54db11125d63bbf7c..f4ea76ddf5acb5131bf739b7f2f7f244ff111809 100644 (file)
@@ -36,8 +36,7 @@ class PartSet_GlobalFilter: public ModuleBase_ShapeDocumentFilter
 public:
   /// Constructor
   /// \param theWorkshop a pointer to workshop
-  PartSet_GlobalFilter(ModuleBase_IWorkshop* theWorkshop)
-    : ModuleBase_ShapeDocumentFilter(theWorkshop) {}
+  PartSet_GlobalFilter(ModuleBase_IWorkshop* theWorkshop);
 
   /// Returns True if selected presentation can be selected
   /// \param theOwner an owner of the persentation
index 2b811848733c1bbe2b93af5829b7aa8ef43762e4..abe6aa02599cb656bcd66a7f60d0044856004e3a 100644 (file)
@@ -28,6 +28,7 @@
 #include <ModuleBase_ActionInfo.h>
 #include <ModuleBase_Tools.h>
 
+#include <ModelAPI_ResultGroup.h>
 #include <ModelAPI_ResultPart.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_ResultBody.h>
@@ -35,8 +36,6 @@
 #include <Config_FeatureMessage.h>
 #include <Events_Loop.h>
 
-#include <CollectionPlugin_Group.h>
-
 QMap<QString, QString> PartSet_IconFactory::myIcons;
 
 PartSet_IconFactory::PartSet_IconFactory(PartSet_Module* theModule)
@@ -128,8 +127,7 @@ QIcon PartSet_IconFactory::getIcon(ObjectPtr theObj)
     if(aShape.get()) {
       switch(aShape->shapeType()) {
         case GeomAPI_Shape::COMPOUND: {
-          FeaturePtr aFeature = ModelAPI_Feature::feature(theObj);
-          if (aFeature.get() && aFeature->getKind() == CollectionPlugin_Group::ID()) {
+          if (aResult->groupName() == ModelAPI_ResultGroup::group()) {
             switch (aShape->typeOfCompoundShapes()) {
             case GeomAPI_Shape::VERTEX:
               return QIcon(":icons/group_vertex.png");
index e9dbb6a38ace075ebd901aeec175cc17aa78e3f9..7859a701c54d767aa784f40617a6538a50141bf4 100644 (file)
@@ -233,13 +233,6 @@ PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop)
 //******************************************************
 PartSet_Module::~PartSet_Module()
 {
-  std::map<XGUI_SelectionFilterType, Handle(SelectMgr_Filter)>::const_iterator aFiltersIt =
-    mySelectionFilters.begin();
-  for (; aFiltersIt != mySelectionFilters.end(); aFiltersIt++) {
-    Handle(SelectMgr_Filter) aFilter = aFiltersIt->second;
-    if (!aFilter.IsNull())
-      aFilter.Nullify();
-  }
   delete myCustomPrs;
   delete myOverconstraintListener;
   delete myRoot;
@@ -659,7 +652,7 @@ void PartSet_Module::moduleSelectionFilters(const QIntList& theFilterTypes,
 {
   bool isSketchActive = mySketchMgr->activeSketch().get();
 
-  std::map<XGUI_SelectionFilterType, Handle(SelectMgr_Filter)>::const_iterator aFiltersIt =
+  std::map<ModuleBase_SelectionFilterType, Handle(SelectMgr_Filter)>::const_iterator aFiltersIt =
     mySelectionFilters.begin();
   for (; aFiltersIt != mySelectionFilters.end(); aFiltersIt++) {
     int aFilterType = aFiltersIt->first;
@@ -669,7 +662,7 @@ void PartSet_Module::moduleSelectionFilters(const QIntList& theFilterTypes,
 
     // using sketch filters only if sketch operation is active
     if (!isSketchActive &&
-        mySketchMgr->sketchSelectionFilter((XGUI_SelectionFilterType)aFilterType))
+        mySketchMgr->sketchSelectionFilter((ModuleBase_SelectionFilterType)aFilterType))
       continue;
 
     // using filtering of construction results only from faces panel
@@ -680,37 +673,6 @@ void PartSet_Module::moduleSelectionFilters(const QIntList& theFilterTypes,
   }
 }
 
-//******************************************************
-QIntList PartSet_Module::selectionFilters()
-{
-  QIntList aTypes;
-
-  std::map<XGUI_SelectionFilterType, Handle(SelectMgr_Filter)>::const_iterator aFiltersIt =
-    mySelectionFilters.begin();
-  for (; aFiltersIt != mySelectionFilters.end(); aFiltersIt++)
-    aTypes.append(aFiltersIt->first);
-
-  return aTypes;
-}
-
-//******************************************************
-void PartSet_Module::registerSelectionFilter(const XGUI_SelectionFilterType theFilterType,
-                                             const Handle(SelectMgr_Filter)& theFilter)
-{
-  mySelectionFilters[theFilterType] = theFilter;
-}
-
-//******************************************************
-Handle(SelectMgr_Filter) PartSet_Module::selectionFilter(const int theType)
-{
-  XGUI_SelectionFilterType aType = (XGUI_SelectionFilterType)theType;
-
-  if (mySelectionFilters.find(aType) != mySelectionFilters.end())
-    return mySelectionFilters[aType];
-  else
-    return Handle(SelectMgr_Filter)();
-}
-
 //******************************************************
 void PartSet_Module::customSubShapesSelectionModes(QIntList& theModes)
 {
index 66264e3ec54691a8e0c44e4c9a098f164e95a1eb..bcd16ee1771476c5a5cfd3854f611d087bcfb479 100644 (file)
@@ -23,7 +23,6 @@
 #include "PartSet.h"
 #include "PartSet_Tools.h"
 #include "PartSet_OverconstraintListener.h"
-#include "XGUI_SelectionFilterType.h"
 #include "PartSet_SketcherMgr.h"
 
 #include <ModuleBase_IModule.h>
@@ -230,20 +229,6 @@ public:
   virtual void moduleSelectionFilters(const QIntList& theFilterTypes,
                                       SelectMgr_ListOfFilter& theSelectionFilters);
 
-  /// Returns types of registered module selection filters
-  /// \param theSelectionFilters [out] container of type value
-  virtual QIntList selectionFilters();
-
-  /// Append selection filter into the module and type of the filter in internal container
-  /// \param theFilterType selection filter type
-  /// \param theFilter added filter
-  void registerSelectionFilter(const XGUI_SelectionFilterType theFilterType,
-                               const Handle(SelectMgr_Filter)& theFilter);
-
-  /// Returns selection filter
-  /// \param theType selection filter type
-  /// \param theFilter instance of filter
-  virtual Handle(SelectMgr_Filter) selectionFilter(const int theType);
 
   /// Returns whether the mouse enter the viewer's window
   /// \return true if items are added and there is no necessity to provide standard menu
@@ -485,7 +470,6 @@ protected:
 
 private:
   bool myIsOperationIsLaunched; /// state of application between launch and stop operation
-  std::map<XGUI_SelectionFilterType, Handle(SelectMgr_Filter)> mySelectionFilters;
 
   PartSet_SketcherMgr* mySketchMgr;
   PartSet_SketcherReentrantMgr* mySketchReentrantMgr;
index 004bdaf88e0e8e3261ee559589867fcbafd65589..e936d729bdd6952ba32ada7763f5cb52f6bf48df 100644 (file)
@@ -459,6 +459,10 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE
 
 void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
 {
+  ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
+  if (myIsDragging)
+    aWorkshop->viewer()->enableDrawMode(myPreviousDrawModeEnabled);
+
   bool aWasDragging = myIsDragging;
   myIsDragging = false;
 
@@ -469,7 +473,6 @@ void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouse
   if (!myIsMouseOverViewProcessed)
     return;
 
-  ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
   ModuleBase_IViewer* aViewer = aWorkshop->viewer();
   if (!aViewer->canDragByMouse())
     return;
@@ -489,7 +492,6 @@ void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouse
     }
   }
 
-  aWorkshop->viewer()->enableDrawMode(myPreviousDrawModeEnabled);
 
   ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
   PartSet_MouseProcessor* aProcessor = dynamic_cast<PartSet_MouseProcessor*>(anActiveWidget);
@@ -959,6 +961,8 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
   if (!aFOperation)
     return;
 
+  SketcherPrs_Tools::setPixelRatio(ModuleBase_Tools::currentPixelRatio());
+
   myModule->onViewTransformed();
 
   // Display all sketcher sub-Objects
@@ -1198,13 +1202,13 @@ void PartSet_SketcherMgr::commitNestedSketch(ModuleBase_Operation* theOperation)
   }
 }
 
-bool PartSet_SketcherMgr::sketchSelectionFilter(const XGUI_SelectionFilterType theFilterType)
+bool PartSet_SketcherMgr::sketchSelectionFilter(const ModuleBase_SelectionFilterType theFilterType)
 {
   return mySelectionFilterTypes.find(theFilterType) != mySelectionFilterTypes.end();
 }
 
-void PartSet_SketcherMgr::registerSelectionFilter(const XGUI_SelectionFilterType theFilterType,
-                                                  const Handle(SelectMgr_Filter)& theFilter)
+void PartSet_SketcherMgr::registerSelectionFilter(
+  const ModuleBase_SelectionFilterType theFilterType, const Handle(SelectMgr_Filter)& theFilter)
 {
   mySelectionFilterTypes.insert(theFilterType);
   myModule->registerSelectionFilter(theFilterType, theFilter);
index 07c3160e6b226cdee4c875af93cdc460881f359c..c036615b5ee29855a4495cceedd625903b47b521 100644 (file)
 #include "PartSet.h"
 
 #include "PartSet_PreviewSketchPlane.h"
-#include "XGUI_SelectionFilterType.h"
 #include "PartSet_Tools.h"
 
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Attribute.h>
 #include <ModelAPI_CompositeFeature.h>
 #include <ModelAPI_Result.h>
+#include <ModuleBase_SelectionFilterType.h>
 
 #include <ModuleBase_Definitions.h>
 #include <ModuleBase_ModelWidget.h>
@@ -201,12 +201,12 @@ public:
   /// Returns true if the filter is created by the sketch manager
   /// \param theFilterType a checked type
   /// \return boolean value
-  bool sketchSelectionFilter(const XGUI_SelectionFilterType theFilterType);
+  bool sketchSelectionFilter(const ModuleBase_SelectionFilterType theFilterType);
 
   /// Append selection filter into the module and type of the filter in internal container
   /// \param theFilterType selection filter type
   /// \param theFilter added filter
-  void registerSelectionFilter(const XGUI_SelectionFilterType theFilterType,
+  void registerSelectionFilter(const ModuleBase_SelectionFilterType theFilterType,
                                const Handle(SelectMgr_Filter)& theFilter);
 
   /// Commit the operation if it is possible. If the operation is dimention constraint,
@@ -451,7 +451,7 @@ private:
 
   CompositeFeaturePtr myCurrentSketch;
 
-  std::set<XGUI_SelectionFilterType> mySelectionFilterTypes;
+  std::set<ModuleBase_SelectionFilterType> mySelectionFilterTypes;
 
   FeatureToSelectionMap myCurrentSelection;
   bool myPreviousUpdateViewerEnabled;
index 1e117834c1c9001ea113dde6092dbed8f8f04625..60134597f37250120035825e71ac8e5ecc405b64 100644 (file)
@@ -397,7 +397,9 @@ bool PartSet_SketcherReentrantMgr::processEnter(const std::string& thePreviousAt
 
   if (!isSketchSolverError) {
     myRestartingMode = RM_EmptyFeatureUsed;
-    isDone = startInternalEdit(thePreviousAttributeID);
+    // It seems that the call is obsolete for Enter key processing
+    // It prevent finalysing of the current operation by Enter key
+    //isDone = startInternalEdit(thePreviousAttributeID);
   }
 
   return isDone;
index 231c512fa895b2770608c9b24c5c84b1e9240fd0..221207f9d910ebb8b42d124d0f4ef273ca30a160 100644 (file)
@@ -539,6 +539,12 @@ void PartSet_WidgetSketchLabel::deactivate()
 
   if (aHidePreview)
     myWorkshop->viewer()->update();
+
+  if (myOpenTransaction) {
+    SessionPtr aMgr = ModelAPI_Session::get();
+    aMgr->finishOperation();
+    myOpenTransaction = false;
+  }
 }
 
 void PartSet_WidgetSketchLabel::selectionModes(int& theModuleSelectionModes, QIntList& theModes)
@@ -680,6 +686,13 @@ void PartSet_WidgetSketchLabel::onChangePlane()
     myRemoveExternal->setVisible(true);
     myStackWidget->setCurrentIndex(0);
 
+    bool aBodyIsVisualized = myPreviewPlanes->hasVisualizedBodies(myWorkshop);
+
+    if (!aBodyIsVisualized) {
+      // We have to select a plane before any operation
+      myPreviewPlanes->showPreviewPlanes(myWorkshop);
+    }
+
     CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
     PartSet_Tools::nullifySketchPlane(aSketch);
 
index 5718df5f5c99294827b246ce2663786c96da14c6..695d5303db9f11fd9b4f6c4fff916cab8315da47 100644 (file)
@@ -20,3 +20,4 @@
 """
 
 from CollectionAPI import addGroup, addField
+from CollectionAPI import addGroupAddition, addGroupIntersection, addGroupSubstraction
index 19f7b2ed03a94e9394086f0a5632e3dd520ec49d..475fdbae834ef5d578a50c2407ce91628d8e4fa5 100644 (file)
@@ -27,7 +27,7 @@ from FeaturesAPI import addPipe
 from FeaturesAPI import addCut, addFuse, addCommon, addSmash, addSplit
 from FeaturesAPI import addIntersection, addPartition, addUnion, addRemoveSubShapes
 from FeaturesAPI import addRecover
-from FeaturesAPI import addFillet
+from FeaturesAPI import addFillet, addChamfer
 from FeaturesAPI import addFusionFaces
 from FeaturesAPI import measureLength, measureDistance, measureRadius, measureAngle
 from FeaturesAPI import addRemoveResults
index bf5ce564b89506f0d73898da78a7c5e25310779c..492594c4ae9eeec0d028f93159e55c388e70f570 100644 (file)
@@ -61,7 +61,7 @@ class compoundVertices(model.Feature):
 
         filepath = apath.value()
         if filepath != "" :
-            part = model.activeDocument()            
+            part = model.activeDocument()
             if self.lfeatures :
                 for feature in self.lfeatures:
                    part.removeFeature(feature.feature())
@@ -92,7 +92,7 @@ class compoundVertices(model.Feature):
                 self.folder = model.addFolder(part, self.lfeatures[0], compound)
                 self.folder.setName(nameRes)
                 return
-        
+
             setError("The file does not exist")
 
     def isMacro(self):
index 75e5a6c21b76133b20e6a5686325e8e0d6374f97..c33e845dd1f9511d3560bbb6a32ca6207dceb280 100644 (file)
@@ -1,19 +1,17 @@
-<source>\r
-  <workbench id="Macros" document="Part">\r
-    <group id="Samples">\r
-\r
-      <feature\r
-        id="compoundVertices"\r
-        title="Points set"\r
-        tooltip="Import a set of construction points"\r
-        icon="icons/Addons/import.png"\r
-        helpfile="compoundVerticesFeature.html">\r
-        <file_selector id="file_path" title="Import txt file (X Y Z)" path="">\r
-        </file_selector>\r
-        <stringvalue id="separator"  label="Separator (optional): ">\r
-        </stringvalue>\r
-      </feature>\r
-\r
-    </group>\r
-  </workbench>  \r
-</source>\r
+<source>
+  <workbench id="Macros" document="Part">
+    <group id="Samples">
+      <feature
+        id="compoundVertices"
+        title="Points set"
+        tooltip="Import a set of construction points"
+        icon="icons/Addons/import.png"
+        helpfile="compoundVerticesFeature.html">
+        <file_selector id="file_path" title="Import txt file (X Y Z)" path="">
+        </file_selector>
+        <stringvalue id="separator"  label="Separator (optional): ">
+        </stringvalue>
+      </feature>
+    </group>
+  </workbench>
+</source>
index 6abd0ddf355219abcabb9669489d0ee4558c3e6b..72111d75bb2c41a0e235086ac235b0a520a936cb 100644 (file)
@@ -58,7 +58,7 @@ class importParameters(model.Feature):
                         model.addParameter(part, defParameters[0], defParameters[1])
                 file.close()
                 return
-        
+
             setError("The file does not exist")
 
     def isMacro(self):
@@ -69,5 +69,3 @@ class importParameters(model.Feature):
         finish.
         """
         return True
-
-                       
index 0865719931043ea94664e7f280e97d9098c8588c..37e0208d7219019bc65ea5d064b2eb1c7c3ece20 100644 (file)
@@ -1,16 +1,14 @@
-<source>\r
-  <workbench id="Macros" document="Part">\r
-    <group id="Samples">\r
-\r
-      <feature id="importParameters"\r
-        title="List of Parameters"\r
-        tooltip="Import a set of parameters"\r
-        icon="icons/Addons/parameters.png"\r
-        helpfile="importParametersFeature.html">\r
-        <file_selector id="file_path" title="Import file" path="">\r
-        </file_selector>\r
-      </feature>\r
-\r
-    </group>\r
-  </workbench>  \r
-</source>\r
+<source>
+  <workbench id="Macros" document="Part">
+    <group id="Samples">
+      <feature id="importParameters"
+        title="List of Parameters"
+        tooltip="Import a set of parameters"
+        icon="icons/Addons/parameters.png"
+        helpfile="importParametersFeature.html">
+        <file_selector id="file_path" title="Import file" path="">
+        </file_selector>
+      </feature>
+    </group>
+  </workbench>
+</source>
index 61716cafc711f4115cb7d8521a071c4ab7d4ce0d..5b69d3593ffb8e02830a296173cbdf0abf0185bb 100644 (file)
@@ -40,6 +40,8 @@
 #include <ModuleBase_ActionInfo.h>
 #include <ModuleBase_IModule.h>
 
+#include <ModelAPI_Tools.h>
+
 #include <LightApp_Application.h>
 #include <LightApp_SelectionMgr.h>
 #include <LightApp_OCCSelector.h>
@@ -283,7 +285,7 @@ bool SHAPERGUI::activateModule(SUIT_Study* theStudy)
       ViewManagerList OCCViewManagers;
       application()->viewManagers(OCCViewer_Viewer::Type(), OCCViewManagers);
       if (OCCViewManagers.size() > 0) {
-        mySelector = createSelector(OCCViewManagers.first());
+        onViewManagerAdded(OCCViewManagers.first());
       }
     }
     // it should be performed after the selector creation in order to have AISContext
@@ -447,8 +449,16 @@ void SHAPERGUI::onViewManagerRemoved(SUIT_ViewManager* theMgr)
       if (mySelector->viewer() == aViewer) {
         XGUI_Displayer* aDisp = myWorkshop->displayer();
         QObjectPtrList aObjects = aDisp->displayedObjects();
-        foreach(ObjectPtr aObj, aObjects)
+        ResultPtr aRes;
+        foreach(ObjectPtr aObj, aObjects) {
           aObj->setDisplayed(false);
+          aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
+          if (aRes.get()) {
+            while (aRes = ModelAPI_Tools::bodyOwner(aRes)) {
+              aRes->setDisplayed(false);
+            }
+          }
+        }
         Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
         myProxyViewer->setSelector(0);
         delete mySelector;
@@ -792,32 +802,32 @@ void SHAPERGUI::createPreferences()
 
   int colorScaleGroup = pref->addItem(tr("Color scale"), viewTab);
   pref->setItemProperty("columns", 4, colorScaleGroup);
-  int aItem = pref->addItem(tr("X position"), colorScaleGroup,
+  int aItem = aMgr.addPreference(tr("X position"), colorScaleGroup,
     SUIT_PreferenceMgr::Double, ModuleBase_Preferences::VIEWER_SECTION, "scalar_bar_x_position");
   pref->setItemProperty("min", 0, aItem);
   pref->setItemProperty("max", 1, aItem);
 
-  aItem = pref->addItem(tr("Y position"), colorScaleGroup,
+  aItem = aMgr.addPreference(tr("Y position"), colorScaleGroup,
     SUIT_PreferenceMgr::Double, ModuleBase_Preferences::VIEWER_SECTION, "scalar_bar_y_position");
   pref->setItemProperty("min", 0, aItem);
   pref->setItemProperty("max", 1, aItem);
 
-  aItem = pref->addItem(tr("Width"), colorScaleGroup,
+  aItem = aMgr.addPreference(tr("Width"), colorScaleGroup,
     SUIT_PreferenceMgr::Double, ModuleBase_Preferences::VIEWER_SECTION, "scalar_bar_width");
   pref->setItemProperty("min", 0, aItem);
   pref->setItemProperty("max", 1, aItem);
 
-  aItem = pref->addItem(tr("Height"), colorScaleGroup,
+  aItem = aMgr.addPreference(tr("Height"), colorScaleGroup,
     SUIT_PreferenceMgr::Double, ModuleBase_Preferences::VIEWER_SECTION, "scalar_bar_height");
   pref->setItemProperty("min", 0, aItem);
   pref->setItemProperty("max", 1, aItem);
 
-  aItem = pref->addItem(tr("Intervals number"), colorScaleGroup,
+  aItem = aMgr.addPreference(tr("Intervals number"), colorScaleGroup,
     SUIT_PreferenceMgr::Integer, ModuleBase_Preferences::VIEWER_SECTION, "scalar_bar_nb_intervals");
   pref->setItemProperty("min", 0, aItem);
   pref->setItemProperty("max", 100, aItem);
 
-  aItem = pref->addItem(tr("Text height"), colorScaleGroup,
+  aItem = aMgr.addPreference(tr("Text height"), colorScaleGroup,
     SUIT_PreferenceMgr::Integer, ModuleBase_Preferences::VIEWER_SECTION, "scalar_bar_text_height");
   pref->setItemProperty("min", 0, aItem);
   pref->setItemProperty("max", 100, aItem);
index 4cc22fb6c380c93c9653d859e0eaaccead5c0732..b93b91f9e4590e8cdc4059f51874d8677c6b16f5 100644 (file)
@@ -59,6 +59,7 @@ SET(PROJECT_SOURCES
 )
 
 SET(PROJECT_LIBRARIES
+  GeomAlgoAPI
   ModelAPI
   ModelHighAPI
   SketcherPrs
@@ -78,6 +79,7 @@ INCLUDE_DIRECTORIES(
   # TODO(spo): modify ConstructionPlugin headers to remove dependency on GeomAPI headers
   ${PROJECT_SOURCE_DIR}/src/Config
   ${PROJECT_SOURCE_DIR}/src/GeomAPI
+  ${PROJECT_SOURCE_DIR}/src/GeomAlgoAPI
   ${PROJECT_SOURCE_DIR}/src/SketchPlugin
 )
 
index 66e043c1c85b201f3ebc64051c866b825a7a0263..722cbbaa77e40782003c6940d9f14d61f867801a 100644 (file)
 #include "SketchAPI_Rotation.h"
 #include "SketchAPI_Translation.h"
 //--------------------------------------------------------------------------------------
+#include <GeomAPI_Curve.h>
 #include <GeomAPI_Dir2d.h>
+#include <GeomAPI_PlanarEdges.h>
+#include <GeomAPI_ShapeExplorer.h>
 #include <GeomAPI_XY.h>
+#include <GeomAlgoAPI_SketchBuilder.h>
 #include <cmath>
 //--------------------------------------------------------------------------------------
 SketchAPI_Sketch::SketchAPI_Sketch(
@@ -235,6 +239,65 @@ std::list< std::shared_ptr<SketchAPI_Point> > SketchAPI_Sketch::getFreePoints()
   return aFreePoints;
 }
 
+//--------------------------------------------------------------------------------------
+static GeomCurvePtr untrimmedCurve(GeomShapePtr theShape)
+{
+  GeomCurvePtr aCurve(new GeomAPI_Curve(theShape));
+  if (aCurve->isTrimmed())
+    aCurve = aCurve->basisCurve();
+  return aCurve;
+}
+
+void SketchAPI_Sketch::changeFacesOrder(
+    const std::list<std::list<ModelHighAPI_Selection> >& theFaces)
+{
+  // collect faces of the sketch
+  ResultConstructionPtr aSketchResult =
+      std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(feature()->lastResult());
+  if (!aSketchResult) {
+    // sketch is nested to a boolean operation, thus, it has no result yet.
+    feature()->execute();
+    aSketchResult =
+        std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(feature()->lastResult());
+  }
+  std::list<GeomFacePtr> aFaces;
+  int aFacesNum = aSketchResult->facesNum();
+  for (int i = 0; i < aFacesNum; ++i)
+    aFaces.push_back(aSketchResult->face(i));
+  // find new faces order according to the given lists of edges
+  std::list<GeomFacePtr> aNewFacesOrder;
+  std::list<std::list<ModelHighAPI_Selection> >::const_iterator anIt = theFaces.begin();
+  for (; anIt != theFaces.end(); ++anIt) {
+    // find the appropriate face
+    std::list<GeomFacePtr>::iterator aFIt = aFaces.begin();
+    for (; aFIt != aFaces.end(); ++aFIt) {
+      std::list<ModelHighAPI_Selection>::const_iterator aEdgeIt = anIt->begin();
+      GeomAPI_ShapeExplorer aFExp(*aFIt, GeomAPI_Shape::EDGE);
+      for (; aEdgeIt != anIt->end() && aFExp.more(); ++aEdgeIt, aFExp.next()) {
+        ResultPtr aCurRes = aEdgeIt->resultSubShapePair().first;
+        if (!aCurRes)
+          break;
+        GeomCurvePtr aCurve1 = untrimmedCurve(aCurRes->shape());
+        GeomCurvePtr aCurve2 = untrimmedCurve(aFExp.current());
+        if (!aCurve1->isEqual(aCurve2))
+          break;
+      }
+
+      if (aEdgeIt == anIt->end() && !aFExp.more()) {
+        // face is found
+        aNewFacesOrder.push_back(*aFIt);
+        aFaces.erase(aFIt);
+        break;
+      }
+    }
+  }
+  // place the rest faces at the end of new faces list
+  if (!aFaces.empty())
+    aNewFacesOrder.insert(aNewFacesOrder.end(), aFaces.begin(), aFaces.end());
+  // update the result of the sketch with the new order of faces
+  aSketchResult->setFacesOrder(aNewFacesOrder);
+}
+
 //--------------------------------------------------------------------------------------
 std::shared_ptr<SketchAPI_Point> SketchAPI_Sketch::addPoint(
     double theX, double theY)
@@ -1008,6 +1071,99 @@ std::shared_ptr<GeomAPI_Pnt2d> SketchAPI_Sketch::to2D(const std::shared_ptr<Geom
 
 //--------------------------------------------------------------------------------------
 
+static bool isDifferent(GeomFacePtr theFace1, GeomFacePtr theFace2)
+{
+  // collect edges of the first face
+  std::list<GeomShapePtr> anEdges1;
+  for (GeomAPI_ShapeExplorer anExp(theFace1, GeomAPI_Shape::EDGE); anExp.more(); anExp.next())
+    anEdges1.push_back(anExp.current());
+  // compare edges of faces
+  for (GeomAPI_ShapeExplorer anExp(theFace2, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
+    GeomShapePtr aCurrent = anExp.current();
+    bool isFound = false;
+    std::list<GeomShapePtr>::iterator anIt1 = anEdges1.begin();
+    for (; anIt1 != anEdges1.end(); ++anIt1)
+      if (aCurrent->isSameGeometry(*anIt1)) {
+        isFound = true;
+        anEdges1.erase(anIt1);
+        break;
+      }
+    if (!isFound)
+      return true;
+  }
+  return !anEdges1.empty();
+}
+
+static bool isCustomFacesOrder(CompositeFeaturePtr theSketch)
+{
+  ResultConstructionPtr aSketchResult =
+      std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theSketch->lastResult());
+  if (!aSketchResult)
+    return false;
+
+  std::shared_ptr<GeomAPI_PlanarEdges> aWires =
+      std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aSketchResult->shape());
+  if (!aWires)
+    return false;
+
+  // collect faces constructed by SketchBuilder algorithm
+  GeomAlgoAPI_SketchBuilder aSketchBuilder(aWires->origin(), aWires->dirX(),
+                                           aWires->norm(), aWires);
+  const ListOfShape& aFaces = aSketchBuilder.faces();
+
+  // compare faces stored in sketch with faces generated by SketchBuilder
+  int aNbSketchFaces = aSketchResult->facesNum();
+  int aFaceIndex = 0;
+  for (ListOfShape::const_iterator aFIt = aFaces.begin();
+       aFIt != aFaces.end() && aFaceIndex < aNbSketchFaces;
+       ++aFIt, ++aFaceIndex) {
+    GeomFacePtr aSketchFace = aSketchResult->face(aFaceIndex);
+    GeomFacePtr aCurFace = (*aFIt)->face();
+    if (isDifferent(aSketchFace, aCurFace))
+      return true;
+  }
+  return false;
+}
+
+static void edgesOfSketchFaces(CompositeFeaturePtr theSketch,
+                               std::list<std::list<ResultPtr> >& theEdges)
+{
+  ResultConstructionPtr aSketchResult =
+      std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theSketch->lastResult());
+  if (!aSketchResult)
+    return;
+
+  // collect curves of the sketch
+  std::map<GeomCurvePtr, ResultPtr, GeomAPI_Curve::Comparator> aCurves;
+  int aSubNum = theSketch->numberOfSubs();
+  for (int a = 0; a < aSubNum; ++a) {
+    FeaturePtr aSub = theSketch->subFeature(a);
+    const std::list<ResultPtr>& aResults = aSub->results();
+    std::list<ResultPtr>::const_iterator aRes = aResults.cbegin();
+    for (; aRes != aResults.cend(); aRes++) {
+      GeomShapePtr aCurShape = (*aRes)->shape();
+      if (aCurShape && aCurShape->isEdge())
+        aCurves[untrimmedCurve(aCurShape)] = *aRes;
+    }
+  }
+
+  // convert each face to the list of results of its edges
+  int aFacesNum = aSketchResult->facesNum();
+  for (int a = 0; a < aFacesNum; ++a) {
+    theEdges.push_back(std::list<ResultPtr>());
+    std::list<ResultPtr>& aCurEdges = theEdges.back();
+
+    GeomFacePtr aFace = aSketchResult->face(a);
+    for (GeomAPI_ShapeExplorer anExp(aFace, GeomAPI_Shape::EDGE);
+         anExp.more(); anExp.next()) {
+      GeomCurvePtr aCurrent = untrimmedCurve(anExp.current());
+      aCurEdges.push_back(aCurves[aCurrent]);
+    }
+  }
+}
+
+//--------------------------------------------------------------------------------------
+
 void SketchAPI_Sketch::dump(ModelHighAPI_Dumper& theDumper) const
 {
   FeaturePtr aBase = feature();
@@ -1067,4 +1223,24 @@ void SketchAPI_Sketch::dump(ModelHighAPI_Dumper& theDumper) const
   // dump sketch's subfeatures
   CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aBase);
   theDumper.processSubs(aCompFeat, true);
+
+  // if face order differs to the order generated by SketchBuilder,
+  // dump the list of faces for correct execution of the script
+  if (isCustomFacesOrder(aCompFeat)) {
+    std::list<std::list<ResultPtr> > aFaces;
+    edgesOfSketchFaces(aCompFeat, aFaces);
+
+    const std::string& aSketchName = theDumper.name(aBase);
+    std::string aMethodName(".changeFacesOrder");
+    std::string aSpaceShift(aSketchName.size() + aMethodName.size(), ' ');
+
+    theDumper << aSketchName << aMethodName << "([";
+    for (std::list<std::list<ResultPtr> >::iterator aFIt = aFaces.begin();
+         aFIt != aFaces.end(); ++aFIt) {
+      if (aFIt != aFaces.begin())
+        theDumper << ",\n" << aSpaceShift << "  ";
+      theDumper << *aFIt;
+    }
+    theDumper << "\n" << aSpaceShift << " ])" << std::endl;
+  }
 }
index 8b3237f7f04df08e3cb8e3da1dbf4a4e49185f90..c32c88d9daf73dc0980d559d2988f126f56a2f10 100644 (file)
@@ -111,6 +111,10 @@ public:
   SKETCHAPI_EXPORT
   void setExternal(std::shared_ptr<ModelAPI_Object> thePlaneObject);
 
+  /// Change order of sketch results (faces)
+  SKETCHAPI_EXPORT
+  void changeFacesOrder(const std::list<std::list<ModelHighAPI_Selection> >& theFaces);
+
   /// List points not connected by constraints with other sketch entitites
   SKETCHAPI_EXPORT
   std::list< std::shared_ptr<SketchAPI_Point> > getFreePoints();
index 336d8af5f1ea18c3d490624646f84c232bfe312f..118bec3ac059912f37d713c125f5f615b27bac1d 100644 (file)
       <!--  SketchFillet  -->
       <feature id="SketchFillet"
                title="Fillet"
-               tooltip="Create constraint defining fillet between two objects"
+               tooltip="Create constraint defining fillet between two connected segments"
                icon="icons/Sketch/fillet.png"
                helpfile="filletFeature.html">
         <sketch_shape_selector id="fillet_point"
         <sketch_multi_selector id="ConstraintMirrorList"
             label="Segments:"
             tooltip="Select list of objects to be mirrored"
-            type_choice="Edges"
+            shape_types="Edges"
             use_external="true"
             greed ="true">
           <validator id="SketchPlugin_MirrorAttr" />
         <sketch_multi_selector id="MultiTranslationList"
             label="Segments:"
             tooltip="Select list of objects to be translated"
-            type_choice="Edges"
+            shape_types="Edges"
             use_external="true"
             greed ="true">
           <validator id="SketchPlugin_CopyValidator" />
         <sketch_multi_selector id="MultiRotationList"
             label="Segments:"
             tooltip="Select list of objects to be rotated"
-            type_choice="Edges"
+            shape_types="Edges"
             use_external="true"
             greed ="true">
           <validator id="SketchPlugin_CopyValidator" />
       </feature>
 
       <!--  SketchConstraintTangent  -->
-      <feature id="SketchConstraintTangent" title="Tangent" tooltip="Create constraint defining tangency of two objects with common coincident point" icon="icons/Sketch/tangent.png"
+      <feature id="SketchConstraintTangent" title="Tangent" tooltip="Create constraint defining tangency of two segments with common coincident point" icon="icons/Sketch/tangent.png"
                helpfile="tangentFeature.html">
         <sketch_shape_selector id="ConstraintEntityA"
             label="First object" tooltip="Select line or arc" shape_types="edge">
index 9397f212a48e51f6d80cf332eccd5b90044d2e6d..d6029af489621f5d48a1b0785dd47bce43dd7db6 100644 (file)
@@ -140,12 +140,14 @@ void SketcherPrs_Coincident::Compute(
   Quantity_Color aExternalColor = aIsEdge ? Quantity_NOC_BLACK : Quantity_NOC_YELLOW;
   Quantity_Color aInternalColor = aIsEdge ? Quantity_NOC_YELLOW : Quantity_NOC_BLACK;
 
+  int aRatio = SketcherPrs_Tools::pixelRatio();
+
   // Create the presentation as a combination of standard point markers
   bool aCustomColor = myIsCustomColor;
   // The external yellow contour
   Handle(Graphic3d_AspectMarker3d) aPtA = new Graphic3d_AspectMarker3d();
   aPtA->SetType(Aspect_TOM_RING3);
-  aPtA->SetScale(2.);
+  aPtA->SetScale(2. * aRatio);
   aPtA->SetColor(!aCustomColor ? aExternalColor : myCustomColor);
 
   Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup(thePresentation);
@@ -157,7 +159,7 @@ void SketcherPrs_Coincident::Compute(
   // Make a black mid ring
   aPtA = new Graphic3d_AspectMarker3d();
   aPtA->SetType(aIsEdge ? Aspect_TOM_STAR : Aspect_TOM_RING1);
-  aPtA->SetScale(1.);
+  aPtA->SetScale(1. * aRatio);
   aPtA->SetColor(!aCustomColor ? aInternalColor : myCustomColor);
   aGroup->SetPrimitivesAspect(aPtA);
   aGroup->AddPrimitiveArray (aPntArray);
@@ -165,7 +167,7 @@ void SketcherPrs_Coincident::Compute(
   // Make an internal ring
   aPtA = new Graphic3d_AspectMarker3d();
   aPtA->SetType(Aspect_TOM_POINT);
-  aPtA->SetScale(5.);
+  aPtA->SetScale(5. * aRatio);
   aPtA->SetColor(!aCustomColor ? aInternalColor : myCustomColor);
   aGroup->SetPrimitivesAspect(aPtA);
   aGroup->AddPrimitiveArray (aPntArray);
index 942bd909e82d5ee64ff52e8250742dcae3463f68..336f298b28b7305853dd04d79779435c143da702 100644 (file)
@@ -39,13 +39,14 @@ SketcherPrs_HVDirection::SketcherPrs_HVDirection(ModelAPI_Feature* theConstraint
 }
 
 bool SketcherPrs_HVDirection::IsReadyToDisplay(ModelAPI_Feature* theConstraint,
-                                               const std::shared_ptr<GeomAPI_Ax3>&/* thePlane*/)
+                                               const std::shared_ptr<GeomAPI_Ax3>& thePlane)
 {
   bool aReadyToDisplay = false;
-  ObjectPtr aObj =
-    SketcherPrs_Tools::getResult(theConstraint, SketchPlugin_Constraint::ENTITY_A());
-
-  aReadyToDisplay = SketcherPrs_Tools::getShape(aObj).get() != NULL;
+  if (thePlane.get()) {
+    ObjectPtr aObj =
+        SketcherPrs_Tools::getResult(theConstraint, SketchPlugin_Constraint::ENTITY_A());
+    aReadyToDisplay = SketcherPrs_Tools::getShape(aObj).get() != NULL;
+  }
   return aReadyToDisplay;
 }
 
index d23827aa7f745111e1cf1edda79b1b2e1bfad6a3..a251d2539f357b9661c0747b1463877e38f25c2d 100644 (file)
@@ -177,6 +177,19 @@ Handle(Image_AlienPixMap) SketcherPrs_SymbolPrs::icon()
   aFile += iconName();
   Handle(Image_AlienPixMap) aPixMap = new Image_AlienPixMap();
   if (aPixMap->Load(aFile.c_str())) {
+    int aRatio = SketcherPrs_Tools::pixelRatio();
+    if (aRatio > 1) {
+      Handle(Image_AlienPixMap) aSizedMap = new Image_AlienPixMap();
+      Standard_Size aWidth = aPixMap->Width() * aRatio;
+      Standard_Size aHeigh = aPixMap->Height() * aRatio;
+      aSizedMap->InitTrash(aPixMap->Format(), aWidth, aHeigh);
+      for (Standard_Size i = 0; i < aWidth; i++) {
+        for (Standard_Size j = 0; j < aHeigh; j++) {
+          aSizedMap->SetPixelColor(i, j, aPixMap->PixelColor(i / aRatio, j / aRatio));
+        }
+      }
+      aPixMap = aSizedMap;
+    }
     myIconsMap[iconName()] = aPixMap;
     return aPixMap;
   }
index 0aecb72c9614bba19f5cb07eaad943a7c03efdae..394a638ff948a89e833e6a0961d0a4f74b88acfe 100644 (file)
@@ -255,8 +255,20 @@ std::shared_ptr<GeomAPI_Pnt2d> getProjectionPoint(const FeaturePtr theLine,
   return aLin2d.project(thePoint);
 }
 
+static int MyPixelRatio = 1;
+
+void setPixelRatio(int theRatio)
+{
+  MyPixelRatio = theRatio;
+}
+
+int pixelRatio()
+{
+  return MyPixelRatio;
+}
 
 static double MyArrowSize = 20;
+
 double getArrowSize()
 {
   return MyArrowSize;
@@ -280,7 +292,7 @@ int getConfigArrowSize()
 static double MyTextHeight = 16;
 double getTextHeight()
 {
-  return MyTextHeight;
+  return MyTextHeight * MyPixelRatio;
 }
 
 void setTextHeight(double theHeight)
@@ -290,12 +302,12 @@ void setTextHeight(double theHeight)
 
 double getDefaultTextHeight()
 {
-  return 16;
+  return 16 * MyPixelRatio;
 }
 
 double getConfigTextHeight()
 {
-  return Config_PropManager::integer("Visualization", "dimension_value_size");
+  return Config_PropManager::integer("Visualization", "dimension_value_size") * MyPixelRatio;
 }
 
 double getFlyoutDistance(const ModelAPI_Feature* theConstraint)
index 75d1b351e0d1716bc7ab2cf055bcce835cbb4941..5a719646c22e8c46447befffb461f15fbf6ab329 100644 (file)
@@ -206,6 +206,10 @@ namespace SketcherPrs_Tools {
   /// \param theError a debug error information
   SKETCHERPRS_EXPORT void sendEmptyPresentationError(ModelAPI_Feature* theFeature,
                                                      const std::string theError);
+
+  SKETCHERPRS_EXPORT void setPixelRatio(int theRatio);
+
+  SKETCHERPRS_EXPORT int pixelRatio();
 };
 
 #endif
index d9178afe1674ec1a03558eba3672fa07903239fc..de8c26897ccac5dea6927af09ba4911514cb403e 100644 (file)
@@ -25,6 +25,10 @@ INCLUDE_DIRECTORIES(${QT_INCLUDES})
 # additional preprocessor / compiler flags
 ADD_DEFINITIONS(${QT_DEFINITIONS})
 
+SET(UPDATE_TRANSLATION OFF)
+
+
+
 SET(PROJECT_HEADERS
     XGUI.h
     XGUI_ActionsMgr.h
@@ -54,7 +58,6 @@ SET(PROJECT_HEADERS
     XGUI_SalomeConnector.h
     XGUI_Selection.h
     XGUI_SelectionActivate.h
-    XGUI_SelectionFilterType.h
     XGUI_SelectionMgr.h
     XGUI_Tools.h
     XGUI_TransparencyWidget.h
@@ -172,12 +175,19 @@ ELSE()
 ENDIF()
 
 QT_ADD_RESOURCES(PROJECT_COMPILED_RESOURCES ${PROJECT_RESOURCES})
-#QT5_ADD_TRANSLATION(QM_RESOURCES ${TEXT_RESOURCES})
-# QT4_CREATE_TRANSLATION(QM_RESOURCES
-#                        ${PROJECT_SOURCES}
-#                        ${TEXT_RESOURCES}
-#                        OPTIONS -extensions cpp -no-recursive
-#                        )
+
+
+
+IF (${UPDATE_TRANSLATION})
+    SET(PROJECT_FILES ${PROJECT_SOURCES} ${ROJECT_HEADERS} )
+    QT5_CREATE_TRANSLATION(QM_RESOURCES
+                           ${PROJECT_FILES}
+                           ${TEXT_RESOURCES}
+                           OPTIONS -extensions cpp -no-recursive
+                          )
+ELSE(${UPDATE_TRANSLATION)
+    QT5_ADD_TRANSLATION(QM_RESOURCES ${TEXT_RESOURCES})
+ENDIF(${UPDATE_TRANSLATION)
 
 
 SOURCE_GROUP ("Generated Files" FILES ${PROJECT_AUTOMOC} ${PROJECT_COMPILED_RESOURCES} ${QM_RESOURCES})
index a24747d5c4666845fc25f8315126c3e5f5fd2558..226aa30dda252dfedcba4bca6b533df7f10a1a5d 100644 (file)
@@ -293,6 +293,7 @@ void XGUI_ContextMenuMgr::updateObjectBrowserMenu()
     bool hasCompositeOwner = false;
     bool hasResultInHistory = false;
     bool hasFolder = false;
+    bool canBeDeleted = true;
     ModuleBase_Tools::checkObjects(aObjects, hasResult, hasFeature, hasParameter,
                                    hasCompositeOwner, hasResultInHistory, hasFolder);
     //Process Feature
@@ -332,7 +333,13 @@ void XGUI_ContextMenuMgr::updateObjectBrowserMenu()
         if( aMgr->activeDocument() == aObject->document() )
         {
           action("RENAME_CMD")->setEnabled(true);
-          action("DELETE_CMD")->setEnabled(!hasCompositeOwner);
+          if (aObject->groupName() == ModelAPI_ResultConstruction::group()) {
+            FeaturePtr aFeature = ModelAPI_Feature::feature(aObject);
+            canBeDeleted = aFeature->isInHistory();
+            action("DELETE_CMD")->setEnabled(canBeDeleted);
+          }
+          else
+            action("DELETE_CMD")->setEnabled(!hasCompositeOwner);
           action("CLEAN_HISTORY_CMD")->setEnabled(!hasCompositeOwner &&
                                                   (hasFeature || hasParameter));
         }
@@ -346,6 +353,15 @@ void XGUI_ContextMenuMgr::updateObjectBrowserMenu()
         action("SHOW_ONLY_CMD")->setEnabled(true);
         action("SHADING_CMD")->setEnabled(true);
         action("WIREFRAME_CMD")->setEnabled(true);
+
+        foreach(ObjectPtr aObj, aObjects) {
+          FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
+          if (!aFeature->isInHistory()) {
+            canBeDeleted = false;
+            break;
+          }
+        }
+        action("DELETE_CMD")->setEnabled(canBeDeleted);
       }
     } // end multi-selection
 
@@ -446,8 +462,8 @@ void XGUI_ContextMenuMgr::updateObjectBrowserMenu()
         break;
       }
     if (!hasCompositeOwner && allActive ) {
-      if (hasResult || hasFeature || hasParameter) // #2924 results can be erased
-        action("DELETE_CMD")->setEnabled(true);
+      if (hasResult || hasFeature || hasParameter)  // #2924 results can be erased
+        action("DELETE_CMD")->setEnabled(canBeDeleted);
     }
     if (!hasCompositeOwner && allActive && (hasFeature|| hasParameter))
       action("CLEAN_HISTORY_CMD")->setEnabled(true);
@@ -506,6 +522,8 @@ void XGUI_ContextMenuMgr::updateViewerMenu()
     ObjectPtr aObject;
     foreach(ModuleBase_ViewerPrsPtr aPrs, aPrsList) {
       aObject = aPrs->object();
+      if (!aObject.get())
+        continue;
       GeomShapePtr aShape = aPrs->shape();
       if (aObject->isDisplayed()) {
         isVisible = true;
@@ -591,7 +609,8 @@ void XGUI_ContextMenuMgr::updateViewerMenu()
   if (myWorkshop->canChangeProperty("TRANSPARENCY_CMD"))
     action("TRANSPARENCY_CMD")->setEnabled(true);
 
-  action("DELETE_CMD")->setEnabled(true);
+  // Delete command is not used in viewer pop-up menu
+  action("DELETE_CMD")->setEnabled(false);
 }
 
 void XGUI_ContextMenuMgr::connectObjectBrowser()
index 32548038ce2b4ab3cb3be13906c04d5f89a73e8c..d624d14ad7d06ceecef304ebe80dc6fb8225ab72 100644 (file)
@@ -67,6 +67,13 @@ void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMess
     for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++) {
       if ((*aIt)->isInHistory())
         aCreated.append(*aIt);
+      if ((*aIt)->groupName() == ModelAPI_ResultPart::group()) {
+        emit beforeTreeRebuild();
+        myRoot->update();
+        rebuildDataTree();
+        emit treeRebuilt();
+        return;
+      }
     }
     if (aCreated.length() == 0)
       return;
@@ -78,7 +85,6 @@ void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMess
     QModelIndex aParentIndex1, aParentIndex2;
     ObjectPtr aObj;
     bool aRebuildAll = false;
-    bool isInserted = false;
 
     foreach(ModuleBase_ITreeNode* aNode, aNodes) {
       aObj = aNode->object();
@@ -93,13 +99,10 @@ void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMess
         aParentIndex2 = getParentIndex(aNode, 2);
         insertRows(aRow, 1, aParentIndex1);
         dataChanged(aParentIndex1, aParentIndex2);
-        isInserted = true;
       }
     }
     if (aRebuildAll)
       rebuildDataTree();
-    else if (isInserted)
-      endInsertRows();
 
     emit treeRebuilt();
   }
@@ -216,8 +219,6 @@ void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMess
     }
     if (aCreated.length() == 0)
       return;
-    bool isInsert = false;
-    bool isRemove = false;
     emit beforeTreeRebuild();
     foreach(ObjectPtr aObj, aCreated) {
       ModuleBase_ITreeNode* aNode = myRoot->subNode(aObj);
@@ -231,22 +232,16 @@ void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMess
 
         if (aNewNb > aOldNb) {
           insertRows(aOldNb - 1, aNewNb - aOldNb, aFirstIdx);
-          isInsert = true;
         }
         else if (aNewNb < aOldNb) {
           if (aNewNb)
             removeRows(aNewNb - 1, aOldNb - aNewNb, aFirstIdx);
           else if (aOldNb)
             removeRows(0, aOldNb, aFirstIdx);
-          isRemove = aNewNb || aOldNb;
         }
         dataChanged(aFirstIdx, aLastIdx);
       }
     }
-    if (isRemove)
-      endRemoveRows();
-    if (isInsert)
-      endInsertRows();
     emit treeRebuilt();
   }
 }
@@ -347,6 +342,7 @@ bool XGUI_DataModel::hasChildren(const QModelIndex& theParent) const
 bool XGUI_DataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
 {
   beginInsertRows(theParent, theRow, theRow + theCount - 1);
+  endInsertRows();
   return true;
 }
 
@@ -354,6 +350,7 @@ bool XGUI_DataModel::insertRows(int theRow, int theCount, const QModelIndex& the
 bool XGUI_DataModel::removeRows(int theRow, int theCount, const QModelIndex& theParent)
 {
   beginRemoveRows(theParent, theRow, theRow + theCount - 1);
+  endRemoveRows();
   return true;
 }
 
index 23753cf8ca2811567bb4dc9c5ceece3f3ab4d4af..2b1c9a1ab470310e6f801f5dbda772c9a4760d9d 100644 (file)
@@ -370,11 +370,16 @@ void XGUI_Displayer::redisplayObjects()
   // redisplay objects visualized in the viewer
   static Events_ID EVENT_DISP = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
   static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
-  QObjectPtrList aDisplayed = myWorkshop->displayer()->displayedObjects();
+  QObjectPtrList aDisplayed = displayedObjects();
   QObjectPtrList::const_iterator anIt = aDisplayed.begin(), aLast = aDisplayed.end();
   for (; anIt != aLast; anIt++) {
     aECreator->sendUpdated(*anIt, EVENT_DISP);
   }
+  XGUI_ViewerProxy* aViewer = myWorkshop->viewer();
+  if (aViewer->isColorScaleVisible()) {
+    aViewer->setupColorScale();
+    aViewer->setColorScaleShown(true);
+  }
   Events_Loop::loop()->flush(EVENT_DISP);
 }
 
@@ -1097,17 +1102,21 @@ void XGUI_Displayer::AddOrRemoveSelectedShapes(Handle(AIS_InteractiveContext) th
                                              ::Iterator aShapeIt(theShapesToBeSelected);
       for (; aShapeIt.More(); aShapeIt.Next()) {
         const TopoDS_Shape& aParameterShape = aShapeIt.Key();
-        // isSame should be used here as it does not check orientation of shapes
-        // despite on isEqual of shapes or IsBound for shape in QMap. Orientation is
-        // different for Edges shapes in model shape and owner even if this is the same shape
-        if (aParameterShape.IsSame(aShape)) {
+        // In case of compound we cannot rely on simple comparison method.
+        // If the compound is generated by Group feature then this compound is alwais new.
+        // So, we have to compare content of these compounds
+
+          // isSame should be used here as it does not check orientation of shapes
+          // despite on isEqual of shapes or IsBound for shape in QMap. Orientation is
+          // different for Edges shapes in model shape and owner even if this is the same shape
+        if (ModuleBase_Tools::isSameShape(aParameterShape, aShape)) {
           Handle(AIS_InteractiveObject) anOwnerPresentation =
-                            Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable());
+            Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable());
           NCollection_Map<Handle(AIS_InteractiveObject)> aPresentations =
-                                      theShapesToBeSelected.Find(aParameterShape);
+            theShapesToBeSelected.Find(aParameterShape);
           if (aPresentations.Contains(anOwnerPresentation)) {
             theContext->AddOrRemoveSelected(anOwner, Standard_False);
-            anOwner->SetSelected (Standard_True);
+            anOwner->SetSelected(Standard_True);
             // collect selected presentations to do not select them if compsolid is selected
             if (!aSelectedPresentations.Contains(anOwnerPresentation))
               aSelectedPresentations.Add(anOwnerPresentation);
index 27b2c0e408db7091ddc719e0d8883b835b50b1d2..d3ec481022c29575a9ae4a8d2270eaee1db33032 100644 (file)
@@ -30,7 +30,8 @@
 #include <QTextCodec>
 
 XGUI_ErrorDialog::XGUI_ErrorDialog(QWidget* parent)
-    : QDialog(parent)
+    : QDialog(parent, Qt::CustomizeWindowHint | Qt::WindowTitleHint |
+      Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
 {
   QVBoxLayout* aDlgLay = new QVBoxLayout(this);
   setWindowTitle(tr("Application errors"));
index ba5e5f82a87eeb2442f8656db1d934e708747b2b..bc35ff26760f9c87b95e4186e4e0edc94c1cc3e1 100644 (file)
 //
 
 #include "XGUI_FacesPanel.h"
+#include "XGUI_ObjectsBrowser.h"
+#include "XGUI_SelectionMgr.h"
+#include "XGUI_Tools.h"
+#include "XGUI_Workshop.h"
+
+#include <ModuleBase_IModule.h>
+#include <ModuleBase_ISelection.h>
+#include <ModuleBase_IWorkshop.h>
+#include <ModuleBase_ListView.h>
+#include <ModuleBase_ResultPrs.h>
+#include <ModuleBase_Tools.h>
+#include <ModuleBase_ViewerPrs.h>
+#include <ModuleBase_SelectionFilterType.h>
 
 #include <Config_PropManager.h>
 #include <Events_Loop.h>
 
 #include <ModelAPI_Events.h>
 
-#include <ModuleBase_IModule.h>
-#include <ModuleBase_ISelection.h>
-#include "ModuleBase_IWorkshop.h"
-#include "ModuleBase_ListView.h"
-#include "ModuleBase_ResultPrs.h"
-#include "ModuleBase_Tools.h"
-#include "ModuleBase_ViewerPrs.h"
-
-#include "XGUI_ObjectsBrowser.h"
-#include "XGUI_SelectionMgr.h"
-#include "XGUI_SelectionFilterType.h"
-#include "XGUI_Tools.h"
-#include "XGUI_Workshop.h"
-
 #include <QAction>
 #include <QCheckBox>
 #include <QFocusEvent>
@@ -256,18 +255,18 @@ void XGUI_FacesPanel::processSelection()
       continue;
     Handle(ModuleBase_ResultPrs) aResultPrs = anObjectToPrs.at(anObject);
 
-    if (aResultPrs->hasSubShapeVisible(anIt->second) || useTransparency()) // redisplay
-      ModelAPI_EventCreator::get()->sendUpdated(anObject, aDispEvent);
-    else { // erase object because it is entirely hidden
+    if (!aResultPrs->hasSubShapeVisible(anIt->second)) { // redisplay
+      // erase object because it is entirely hidden
       anObject->setDisplayed(false);
       myHiddenObjects.insert(anObject);
-      ModelAPI_EventCreator::get()->sendUpdated(anObject, aDispEvent);
     }
+    ModelAPI_EventCreator::get()->sendUpdated(anObject, aDispEvent);
   }
   if (isModified) {
     updateProcessedObjects(myItems, myItemObjects);
     flushRedisplay();
   }
+  onTransparencyChanged();
 }
 
 //********************************************************************
index 7bfd6a3d4013eb7bdf9e06a25f96281eed264090..8b5ccaf65b408673ae09be020965f1dddbbdd80b 100644 (file)
@@ -295,7 +295,6 @@ void XGUI_PropertyPanel::activateNextWidget(ModuleBase_ModelWidget* theWidget,
 
   QList<ModuleBase_ModelWidget*>::const_iterator anIt = myWidgets.begin(), aLast = myWidgets.end();
   bool isFoundWidget = false;
-  ModuleBase_Tools::activateWindow(this, "XGUI_PropertyPanel::activateNextWidget()");
   for (; anIt != aLast; anIt++) {
     ModuleBase_ModelWidget* aCurrentWidget = *anIt;
     if (isFoundWidget || !theWidget) {
diff --git a/src/XGUI/XGUI_SelectionFilterType.h b/src/XGUI/XGUI_SelectionFilterType.h
deleted file mode 100644 (file)
index 8bc9f81..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-
-#ifndef XGUI_SelectionFilterType_H
-#define XGUI_SelectionFilterType_H
-
-#include "XGUI.h"
-
-/// Enumeration to specify module selection filters
-enum XGUI_EXPORT XGUI_SelectionFilterType {
-  SF_GlobalFilter, /// filter for different documents, group results
-  SF_FilterInfinite, /// filter for infinite construction results
-  SF_ResultGroupNameFilter, /// filter for selection some kind of results
-  SF_SketchCirclePointFilter, /// filter for selection circle points on current sketch
-  SF_SketchPlaneFilter /// filter for selection in the current sketch plane only
-};
-
-#endif
index 175ed87790b880f08b2aa83415bac3c2c7e2c19d..0523975fffdf12e70b31c72fc608c725eb6c8fa2 100644 (file)
@@ -299,18 +299,34 @@ void XGUI_ViewerProxy::onMouseMove(AppElements_ViewWindow* theWnd, QMouseEvent*
   if (myIs2dMode) {
     bool aHighlight2d =
       ModuleBase_Preferences::resourceMgr()->booleanValue("Viewer", "highlighting-2d", true);
-    if (aHighlight2d || myShowHighlight)
-      updateHighlight();
-    else
-      eraseHighlight();
+    if (aHighlight2d) {
+      if (myShowHighlight)
+        eraseHighlight();
+      else
+        updateHighlight();
+    }
+    else {
+      if (myShowHighlight)
+        updateHighlight();
+      else
+        eraseHighlight();
+    }
   }
   else {
     bool aHighlight3d =
       ModuleBase_Preferences::resourceMgr()->booleanValue("Viewer", "highlighting-3d", false);
-    if (aHighlight3d || myShowHighlight)
-      updateHighlight();
-    else
-      eraseHighlight();
+    if (aHighlight3d) {
+      if (myShowHighlight)
+        eraseHighlight();
+      else
+        updateHighlight();
+    }
+    else {
+      if (myShowHighlight)
+        updateHighlight();
+      else
+        eraseHighlight();
+    }
   }
   emit mouseMove(theWnd, theEvent);
 }
@@ -528,18 +544,34 @@ void XGUI_ViewerProxy::onMouseMove(ModuleBase_IViewWindow* theWnd, QMouseEvent*
   if (myIs2dMode) {
     bool aHighlight2d =
       ModuleBase_Preferences::resourceMgr()->booleanValue("Viewer", "highlighting-2d", true);
-    if (aHighlight2d || myShowHighlight)
-      updateHighlight();
-    else
-      eraseHighlight();
+    if (aHighlight2d) {
+      if (myShowHighlight)
+        eraseHighlight();
+      else
+        updateHighlight();
+    }
+    else {
+      if (myShowHighlight)
+        updateHighlight();
+      else
+        eraseHighlight();
+    }
   }
   else {
     bool aHighlight3d =
       ModuleBase_Preferences::resourceMgr()->booleanValue("Viewer", "highlighting-3d", false);
-    if (aHighlight3d || myShowHighlight)
-      updateHighlight();
-    else
-      eraseHighlight();
+    if (aHighlight3d) {
+      if (myShowHighlight)
+        eraseHighlight();
+      else
+        updateHighlight();
+    }
+    else {
+      if (myShowHighlight)
+        updateHighlight();
+      else
+        eraseHighlight();
+    }
   }
   emit mouseMove(theWnd, theEvent);
 }
@@ -665,7 +697,7 @@ void XGUI_ViewerProxy::setupColorScale()
   double aH = aResMgr->doubleValue("Viewer", "scalar_bar_height", 0.5);
   setColorScaleSize(aW, aH);
 
-  QColor aColor = aResMgr->integerValue("Viewer", "scalar_bar_text_color", Qt::black);
+  QColor aColor = aResMgr->colorValue("Viewer", "scalar_bar_text_color", Qt::black);
   setColorScaleTextColor(aColor);
 
   int aT = aResMgr->integerValue("Viewer", "scalar_bar_text_height", 14);
index d10ccc61278a39e8c73840d8c2e5ddcfcf1d578a..df5c48cb13c153a11760d59bac5b59329ef848f6 100644 (file)
@@ -174,13 +174,13 @@ QString XGUI_Workshop::MOVE_TO_END_COMMAND = QObject::tr("Move to the end");
 //#define DEBUG_CLEAN_HISTORY
 
 #ifdef HAVE_SALOME
-static QString MyFilter(QObject::tr("SHAPER files (*.shaper *.opp)"));
+static QString MyFilter(QObject::tr("SHAPER files (*.shaper *.cadbld)"));
 static QString MyFilter2(QObject::tr("SHAPER files (*.shaper)"));
 static QString MyExtension(".shaper");
 #else
-static QString MyFilter(QObject::tr("CAD Builder files (*.opp);;All files (*.*)"));
-static QString MyFilter2(QObject::tr("CAD Builder files (*.opp)"));
-static QString MyExtension(".opp");
+static QString MyFilter(QObject::tr("CAD Builder files (*.cadbld);;All files (*.*)"));
+static QString MyFilter2(QObject::tr("CAD Builder files (*.cadbld)"));
+static QString MyExtension(".cadbld");
 #endif
 
 
@@ -939,7 +939,11 @@ void XGUI_Workshop::onOpen()
   }
 
   //show file dialog, check if readable and open
-  QString aFile = QFileDialog::getOpenFileName(desktop(), tr("Open file"), QString(), MyFilter);
+  qreal aRatio = ModuleBase_Tools::currentPixelRatio();
+  // If the ratio is > 1 (HD screen) then QT has a bug in
+  // displaying of system open file dialog (too small)
+  QString aFile = QFileDialog::getOpenFileName(desktop(), tr("Open file"), QString(), MyFilter,
+    Q_NULLPTR, ((aRatio > 1)? QFileDialog::DontUseNativeDialog : QFileDialog::Options()));
   if (!aFile.isNull())
     openFile(aFile);
 }
@@ -1106,8 +1110,10 @@ bool XGUI_Workshop::onSaveAs()
 {
   if(!myOperationMgr->abortAllOperations(XGUI_OperationMgr::XGUI_InformationMessage))
     return false;
+  qreal aRatio = ModuleBase_Tools::currentPixelRatio();
   myCurrentFile = QFileDialog::getSaveFileName(desktop(), tr("Select name to save file..."),
-    QString(), MyFilter2);
+    QString(), MyFilter2,
+    Q_NULLPTR, ((aRatio > 1) ? QFileDialog::DontUseNativeDialog : QFileDialog::Options()));
   if (!myCurrentFile.isNull()) {
     if (!myCurrentFile.endsWith(MyExtension)) {
       myCurrentFile += MyExtension;
@@ -2460,14 +2466,16 @@ void XGUI_Workshop::changeTransparency(const QObjectPtrList& theObjects)
   QString aDescription = contextMenuMgr()->action("TRANSPARENCY_CMD")->text();
   aMgr->startOperation(aDescription.toStdString());
 
-  if (aDlg->exec() != QDialog::Accepted)
-    return;
-
-  // 4. set the value to all results
-  aCurrentValue = aTransparencyWidget->getValue();
-  setTransparency(aCurrentValue, theObjects);
+  if (aDlg->exec() == QDialog::Accepted) {
+    // 4. set the value to all results
+    aCurrentValue = aTransparencyWidget->getValue();
+    setTransparency(aCurrentValue, theObjects);
+    aMgr->finishOperation();
+  } else {
+    aMgr->abortOperation();
+    Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+  }
 
-  aMgr->finishOperation();
   updateCommandStatus();
 }
 
@@ -2791,8 +2799,12 @@ void XGUI_Workshop::synchronizeResultTree(const ResultBodyPtr& theRes, bool theU
       if (aRes.get())
         synchronizeResultTree(aRes, theUpdateViewer);
     }
-  else
-    myDisplayer->display(theRes, theUpdateViewer);
+  else {
+    if (theRes->isDisplayed())
+      myDisplayer->display(theRes, theUpdateViewer);
+    else
+      myDisplayer->erase(theRes, theUpdateViewer);
+  }
 }
 #endif
 
index 913ff0f71b66f3290ceebbf5530fd6685a78b0c7..3f0661c06764b8fdfe48ca85b1ac680192a516c2 100644 (file)
 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE TS>
-<TS version="2.0" language="fr_FR">
+<TS version="2.1" language="fr_FR">
 <context>
     <name>QObject</name>
     <message>
-        <location filename="XGUI_Tools.cpp" line="116"/>
+        <location filename="XGUI_Tools.cpp" line="154"/>
         <source>Warning</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Tools.cpp" line="117"/>
-        <source>Selected objects can be used in Part documents which are not loaded: %1. Whould you like to continue?</source>
+        <location filename="XGUI_Tools.cpp" line="213"/>
+        <source>Name %2 already exists in %1.</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Tools.cpp" line="134"/>
-        <source>Selected parameter can not be renamed to: %1.  There is a parameter with the same name. Its value is: %2.</source>
+        <location filename="XGUI_Workshop.cpp" line="170"/>
+        <source>Move to the end</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="113"/>
-        <source>Move to the end</source>
+        <location filename="XGUI_Workshop.cpp" line="177"/>
+        <source>SHAPER files (*.shaper *.cadbld)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_Workshop.cpp" line="178"/>
+        <source>SHAPER files (*.shaper)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_Workshop.cpp" line="181"/>
+        <source>CAD Builder files (*.cadbld);;All files (*.*)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_Workshop.cpp" line="182"/>
+        <source>CAD Builder files (*.cadbld)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_OperationMgr.cpp" line="893"/>
+        <source>Abort operation</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_OperationMgr.cpp" line="904"/>
+        <source>Validate operation</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
 <context>
     <name>XGUI_ActionsMgr</name>
     <message>
-        <location filename="XGUI_ActionsMgr.cpp" line="176"/>
+        <location filename="XGUI_ActionsMgr.cpp" line="194"/>
         <source>Shortcut %1 is already defined. Ignore.</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_ActionsMgr.cpp" line="254"/>
+        <location filename="XGUI_ActionsMgr.cpp" line="274"/>
         <source>See preview</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
+<context>
+    <name>XGUI_ColorDialog</name>
+    <message>
+        <location filename="XGUI_ColorDialog.cpp" line="35"/>
+        <source>Color</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_ColorDialog.cpp" line="53"/>
+        <source>Random</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
 <context>
     <name>XGUI_ContextMenuMgr</name>
     <message>
-        <location filename="XGUI_ContextMenuMgr.cpp" line="67"/>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="88"/>
         <source>Delete</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_ContextMenuMgr.cpp" line="74"/>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="95"/>
         <source>Rename</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_ContextMenuMgr.cpp" line="83"/>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="104"/>
         <source>Clean history</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_ContextMenuMgr.cpp" line="86"/>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="107"/>
         <source>Color...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_ContextMenuMgr.cpp" line="89"/>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="110"/>
+        <source>Deflection...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="114"/>
+        <source>Transparency...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="117"/>
         <source>Show</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_ContextMenuMgr.cpp" line="92"/>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="120"/>
         <source>Show only</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_ContextMenuMgr.cpp" line="96"/>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="124"/>
         <source>Hide</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_ContextMenuMgr.cpp" line="100"/>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="128"/>
         <source>Hide all</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_ContextMenuMgr.cpp" line="104"/>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="132"/>
         <source>Shading</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_ContextMenuMgr.cpp" line="107"/>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="135"/>
         <source>Wireframe</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_ContextMenuMgr.cpp" line="117"/>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="148"/>
         <source>Vertices</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_ContextMenuMgr.cpp" line="123"/>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="153"/>
         <source>Edges</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_ContextMenuMgr.cpp" line="129"/>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="158"/>
         <source>Faces</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_ContextMenuMgr.cpp" line="135"/>
-        <source>Result</source>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="163"/>
+        <source>Results</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_ContextMenuMgr.cpp" line="144"/>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="171"/>
         <source>Select results</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_ContextMenuMgr.cpp" line="148"/>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="175"/>
         <source>Select parent feature</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_ContextMenuMgr.cpp" line="561"/>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="179"/>
+        <source>TInspector</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="185"/>
+        <source>Insert a folder before</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="189"/>
+        <source>Move into the previous folder</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="193"/>
+        <source>Move into the next folder</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="197"/>
+        <source>Move out before the folder</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="201"/>
+        <source>Move out after the folder</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="205"/>
+        <source>Set view by inverted normal to face</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="209"/>
+        <source>Set view by normal to face</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="811"/>
         <source>Selection mode</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_ContextMenuMgr.cpp" line="610"/>
+        <location filename="XGUI_ContextMenuMgr.cpp" line="864"/>
         <source>Windows</source>
         <translation type="unfinished"></translation>
     </message>
 <context>
     <name>XGUI_DataTree</name>
     <message>
-        <location filename="XGUI_ObjectsBrowser.cpp" line="160"/>
+        <location filename="XGUI_ObjectsBrowser.cpp" line="203"/>
         <source>History change</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
+<context>
+    <name>XGUI_DeflectionDialog</name>
+    <message>
+        <location filename="XGUI_DeflectionDialog.cpp" line="35"/>
+        <source>Deflection</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
 <context>
     <name>XGUI_ErrorDialog</name>
     <message>
-        <location filename="XGUI_ErrorDialog.cpp" line="25"/>
+        <location filename="XGUI_ErrorDialog.cpp" line="37"/>
         <source>Application errors</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
+<context>
+    <name>XGUI_FacesPanel</name>
+    <message>
+        <location filename="XGUI_FacesPanel.cpp" line="54"/>
+        <source>Hide Faces</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_FacesPanel.cpp" line="63"/>
+        <source>Transparent</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>XGUI_InspectionPanel</name>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="115"/>
+        <source>Inspection Panel</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="125"/>
+        <source>Object</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="137"/>
+        <source>Sub-shapes</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="137"/>
+        <source>Number</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="165"/>
+        <source>Type:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="340"/>
+        <source>Vertex</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="343"/>
+        <source>Coordinates</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="352"/>
+        <source>Degenerated</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="359"/>
+        <source>Line segment</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="371"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="385"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="624"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="662"/>
+        <source>Center</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="372"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="386"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="458"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="615"/>
+        <source>Normal</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="373"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="387"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="459"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="625"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="637"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="650"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="664"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="676"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="692"/>
+        <source>Dimensions</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="374"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="626"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="638"/>
+        <source>Radius</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="388"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="665"/>
+        <source>Major radius</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="389"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="666"/>
+        <source>Minor radius</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="393"/>
+        <source>Edge</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="398"/>
+        <source>Start point</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="399"/>
+        <source>End point</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="408"/>
+        <source>Closed</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="413"/>
+        <source>Polygon</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="417"/>
+        <source>Point</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="421"/>
+        <source>Wire</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="456"/>
+        <source>Rectangle</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="457"/>
+        <source>Corner</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="460"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="677"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="693"/>
+        <source>Width</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="461"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="639"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="653"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="679"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="695"/>
+        <source>Height</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="470"/>
+        <source>Plane</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="476"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="507"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="547"/>
+        <source>Sphere</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="481"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="512"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="552"/>
+        <source>Cylinder</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="486"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="517"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="557"/>
+        <source>Cone</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="491"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="522"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="562"/>
+        <source>Torus</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="494"/>
+        <source>Face</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="528"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="568"/>
+        <source>Box</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="530"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="570"/>
+        <source>Rotated Box</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="534"/>
+        <source>Shell</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="574"/>
+        <source>Solid</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="604"/>
+        <source>Bounding box</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="605"/>
+        <source>Minimal corner</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="606"/>
+        <source>Maximal corner</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="614"/>
+        <source>Origin</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="635"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="648"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="675"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="689"/>
+        <source>Position</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="636"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="649"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="663"/>
+        <source>Axis</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="651"/>
+        <source>Radius 1</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="652"/>
+        <source>Radius 2</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="678"/>
+        <location filename="XGUI_InspectionPanel.cpp" line="694"/>
+        <source>Depth</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="690"/>
+        <source>Z axis</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_InspectionPanel.cpp" line="691"/>
+        <source>X axis</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
 <context>
     <name>XGUI_ObjectsBrowser</name>
     <message>
-        <location filename="XGUI_ObjectsBrowser.cpp" line="342"/>
+        <location filename="XGUI_ObjectsBrowser.cpp" line="396"/>
         <source>Part set</source>
         <translation type="unfinished"></translation>
     </message>
 <context>
     <name>XGUI_OperationMgr</name>
     <message>
-        <location filename="XGUI_OperationMgr.cpp" line="222"/>
-        <location filename="XGUI_OperationMgr.cpp" line="300"/>
-        <source>Abort operation</source>
+        <location filename="XGUI_OperationMgr.cpp" line="254"/>
+        <source>All active operations will be aborted.</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_OperationMgr.cpp" line="223"/>
-        <source>All active operations will be aborted.</source>
+        <location filename="XGUI_OperationMgr.cpp" line="259"/>
+        <source>Please validate all your active operations before saving.</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_OperationMgr.cpp" line="298"/>
+        <location filename="XGUI_OperationMgr.cpp" line="341"/>
         <source>%1 operation will be aborted.</source>
         <translation type="unfinished"></translation>
     </message>
+    <message>
+        <location filename="XGUI_OperationMgr.cpp" line="348"/>
+        <source>Please validate your %1 before saving.</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>XGUI_PropertyPanel</name>
     <message>
-        <location filename="XGUI_PropertyPanel.cpp" line="49"/>
-        <location filename="XGUI_PropertyPanel.cpp" line="130"/>
+        <location filename="XGUI_PropertyPanel.cpp" line="73"/>
+        <location filename="XGUI_PropertyPanel.cpp" line="167"/>
         <source>Property Panel</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
+<context>
+    <name>XGUI_TransparencyWidget</name>
+    <message>
+        <location filename="XGUI_TransparencyWidget.cpp" line="39"/>
+        <source>Opaque</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_TransparencyWidget.cpp" line="45"/>
+        <source>Transparent</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
 <context>
     <name>XGUI_Workshop</name>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="310"/>
-        <location filename="XGUI_Workshop.cpp" line="364"/>
+        <location filename="XGUI_Workshop.cpp" line="427"/>
+        <location filename="XGUI_Workshop.cpp" line="489"/>
         <source>Undo</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="311"/>
-        <location filename="XGUI_Workshop.cpp" line="364"/>
+        <location filename="XGUI_Workshop.cpp" line="428"/>
+        <location filename="XGUI_Workshop.cpp" line="489"/>
         <source>Undo last command</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="314"/>
+        <location filename="XGUI_Workshop.cpp" line="432"/>
         <source>INF_DESK_TOOLBAR_STANDARD</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="320"/>
-        <location filename="XGUI_Workshop.cpp" line="373"/>
+        <location filename="XGUI_Workshop.cpp" line="438"/>
+        <location filename="XGUI_Workshop.cpp" line="498"/>
         <source>Redo</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="320"/>
-        <location filename="XGUI_Workshop.cpp" line="373"/>
+        <location filename="XGUI_Workshop.cpp" line="438"/>
+        <location filename="XGUI_Workshop.cpp" line="498"/>
         <source>Redo last command</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="337"/>
+        <location filename="XGUI_Workshop.cpp" line="460"/>
         <source>Export native...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="337"/>
+        <location filename="XGUI_Workshop.cpp" line="461"/>
         <source>Export the current document into a native file</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="342"/>
+        <location filename="XGUI_Workshop.cpp" line="466"/>
         <source>Import native...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="342"/>
+        <location filename="XGUI_Workshop.cpp" line="467"/>
         <source>Import native file</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="354"/>
-        <location filename="XGUI_Workshop.cpp" line="842"/>
+        <location filename="XGUI_Workshop.cpp" line="479"/>
         <source>Save</source>
-        <extracomment>Title of the dialog which asks user if he wants to save study in existing non-empty folder</extracomment>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="354"/>
+        <location filename="XGUI_Workshop.cpp" line="479"/>
         <source>Save the document</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="359"/>
+        <location filename="XGUI_Workshop.cpp" line="484"/>
         <source>Save as...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="359"/>
+        <location filename="XGUI_Workshop.cpp" line="484"/>
         <source>Save the document into a file</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="387"/>
+        <location filename="XGUI_Workshop.cpp" line="506"/>
         <source>Open...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="387"/>
+        <location filename="XGUI_Workshop.cpp" line="506"/>
         <source>Open a new document</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="391"/>
+        <location filename="XGUI_Workshop.cpp" line="511"/>
+        <source>Auto rebuild</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_Workshop.cpp" line="512"/>
+        <source>Blocks immediate apply of modifications</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="XGUI_Workshop.cpp" line="517"/>
         <source>Preferences</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="391"/>
+        <location filename="XGUI_Workshop.cpp" line="517"/>
         <source>Edit preferences</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="395"/>
+        <location filename="XGUI_Workshop.cpp" line="521"/>
         <source>Exit</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="395"/>
+        <location filename="XGUI_Workshop.cpp" line="521"/>
         <source>Exit application</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="704"/>
-        <location filename="XGUI_Workshop.cpp" line="760"/>
+        <location filename="XGUI_Workshop.cpp" line="930"/>
+        <location filename="XGUI_Workshop.cpp" line="1029"/>
         <source>Save current file</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="705"/>
+        <location filename="XGUI_Workshop.cpp" line="931"/>
         <source>The document is modified, save before opening another?</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="716"/>
-        <source>Select directory</source>
+        <location filename="XGUI_Workshop.cpp" line="942"/>
+        <source>Open file</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="721"/>
-        <source>Warning</source>
+        <location filename="XGUI_Workshop.cpp" line="1109"/>
+        <source>Select name to save file...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="721"/>
-        <source>Unable to open the file.</source>
+        <location filename="XGUI_Workshop.cpp" line="1772"/>
+        <source>Show object</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="760"/>
-        <source>The document is modified, save before exit?</source>
+        <location filename="XGUI_Workshop.cpp" line="1773"/>
+        <source>&apos;%1&apos;
+ are hidden by %2:
+Remove objects from the panel to be displayed?</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="826"/>
-        <source>Select directory to save files...</source>
+        <location filename="XGUI_Workshop.cpp" line="956"/>
+        <source>Warning</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="828"/>
-        <source>Directories (*)</source>
+        <location filename="XGUI_Workshop.cpp" line="956"/>
+        <source>Unable to open the file.</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="843"/>
-        <source>The directory already contains some files, save anyway?</source>
+        <location filename="XGUI_Workshop.cpp" line="1029"/>
+        <source>The document is modified, save before exit?</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="976"/>
+        <location filename="XGUI_Workshop.cpp" line="1241"/>
         <source>Information about module &quot;%1&quot; doesn&apos;t exist.</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="1107"/>
+        <location filename="XGUI_Workshop.cpp" line="1402"/>
         <source>Object browser</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="1436"/>
-        <source>Unused features are the following: %1.
-These features will be deleted.
-Would you like to continue?</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="XGUI_Workshop.cpp" line="1474"/>
+        <location filename="XGUI_Workshop.cpp" line="2005"/>
         <source>All features are relevant, there is nothing to be deleted</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="1975"/>
+        <location filename="XGUI_Workshop.cpp" line="2827"/>
         <source>Find results</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="XGUI_Workshop.cpp" line="1976"/>
+        <location filename="XGUI_Workshop.cpp" line="2828"/>
         <source>Results not found</source>
         <translation type="unfinished"></translation>
     </message>