Salome HOME
Merge branch 'Dev_GroupsRevision'
authorvsv <vsv@opencascade.com>
Mon, 25 Dec 2017 14:42:02 +0000 (17:42 +0300)
committervsv <vsv@opencascade.com>
Mon, 25 Dec 2017 14:42:02 +0000 (17:42 +0300)
# Conflicts:
# src/ModuleBase/CMakeLists.txt
# src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp
# src/ModuleBase/ModuleBase_WidgetMultiSelector.h
# src/XGUI/XGUI_pictures.qrc

363 files changed:
CMakeLists.txt
src/BuildAPI/BuildAPI.i
src/BuildAPI/BuildAPI_CompSolid.cpp [new file with mode: 0644]
src/BuildAPI/BuildAPI_CompSolid.h [new file with mode: 0644]
src/BuildAPI/BuildAPI_Compound.cpp [new file with mode: 0644]
src/BuildAPI/BuildAPI_Compound.h [new file with mode: 0644]
src/BuildAPI/BuildAPI_Filling.cpp [new file with mode: 0644]
src/BuildAPI/BuildAPI_Filling.h [new file with mode: 0644]
src/BuildAPI/BuildAPI_Solid.cpp [new file with mode: 0644]
src/BuildAPI/BuildAPI_Solid.h [new file with mode: 0644]
src/BuildAPI/BuildAPI_swig.h
src/BuildAPI/CMakeLists.txt
src/BuildPlugin/BuildPlugin_CompSolid.cpp [new file with mode: 0644]
src/BuildPlugin/BuildPlugin_CompSolid.h [new file with mode: 0644]
src/BuildPlugin/BuildPlugin_Compound.cpp [new file with mode: 0644]
src/BuildPlugin/BuildPlugin_Compound.h [new file with mode: 0644]
src/BuildPlugin/BuildPlugin_Face.cpp
src/BuildPlugin/BuildPlugin_Face.h
src/BuildPlugin/BuildPlugin_Filling.cpp [new file with mode: 0644]
src/BuildPlugin/BuildPlugin_Filling.h [new file with mode: 0644]
src/BuildPlugin/BuildPlugin_Plugin.cpp
src/BuildPlugin/BuildPlugin_Solid.cpp [new file with mode: 0644]
src/BuildPlugin/BuildPlugin_Solid.h [new file with mode: 0644]
src/BuildPlugin/BuildPlugin_Validators.cpp
src/BuildPlugin/BuildPlugin_Validators.h
src/BuildPlugin/CMakeLists.txt
src/BuildPlugin/Test/Test1920.py
src/BuildPlugin/Test/TestCompSolid.py [new file with mode: 0644]
src/BuildPlugin/Test/TestCompound.py [new file with mode: 0644]
src/BuildPlugin/Test/TestEdge.py
src/BuildPlugin/Test/TestFace.py
src/BuildPlugin/Test/TestFilling_ByEdges.py [new file with mode: 0644]
src/BuildPlugin/Test/TestFilling_ByWires.py [new file with mode: 0644]
src/BuildPlugin/Test/TestFilling_Mixed.py [new file with mode: 0644]
src/BuildPlugin/Test/TestShell.py
src/BuildPlugin/Test/TestSolid.py [new file with mode: 0644]
src/BuildPlugin/Test/TestWire.py
src/BuildPlugin/compound_widget.xml [new file with mode: 0644]
src/BuildPlugin/compsolid_widget.xml [new file with mode: 0644]
src/BuildPlugin/face_widget.xml
src/BuildPlugin/filling_widget.xml [new file with mode: 0644]
src/BuildPlugin/icons/feature_compound.png [new file with mode: 0644]
src/BuildPlugin/icons/feature_compsolid.png [new file with mode: 0644]
src/BuildPlugin/icons/feature_filling.png [new file with mode: 0644]
src/BuildPlugin/icons/feature_solid.png [new file with mode: 0644]
src/BuildPlugin/plugin-Build.xml
src/BuildPlugin/shell_widget.xml
src/BuildPlugin/solid_widget.xml [new file with mode: 0644]
src/CollectionPlugin/CollectionPlugin_WidgetField.cpp
src/CollectionPlugin/Test/TestGroupMove2.py
src/ConnectorAPI/CMakeLists.txt
src/ConnectorAPI/Test/CMakeLists.txt [new file with mode: 0755]
src/ConnectorAPI/Test/CTestTestfileInstall.cmake [new file with mode: 0644]
src/ConnectorAPI/Test/TestExportToGEOM.py
src/ConnectorAPI/Test/TestExportToGEOMAllGroupsAndFields.py [new file with mode: 0644]
src/ConnectorAPI/Test/testme.py [new file with mode: 0755]
src/ConnectorAPI/Test/tests.set [new file with mode: 0644]
src/ConnectorPlugin/ConnectorPlugin_ExportFeature.py
src/ExchangeAPI/ExchangeAPI_Export.cpp
src/ExchangeAPI/ExchangeAPI_Export.h
src/ExchangePlugin/CMakeLists.txt
src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp
src/ExchangePlugin/ExchangePlugin_ExportFeature.h
src/ExchangePlugin/ExchangePlugin_Tools.cpp
src/ExchangePlugin/Test/Data/export_ref.xao
src/ExchangePlugin/Test/Test2290.py [new file with mode: 0644]
src/ExchangePlugin/Test/TestExport.py
src/FeaturesAPI/CMakeLists.txt
src/FeaturesAPI/FeaturesAPI.i
src/FeaturesAPI/FeaturesAPI_Fillet.cpp [new file with mode: 0644]
src/FeaturesAPI/FeaturesAPI_Fillet.h [new file with mode: 0644]
src/FeaturesAPI/FeaturesAPI_swig.h
src/FeaturesPlugin/CMakeLists.txt
src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp
src/FeaturesPlugin/FeaturesPlugin_Fillet.cpp [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_Fillet.h [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_MultiRotation.h
src/FeaturesPlugin/FeaturesPlugin_MultiTranslation.h
src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp
src/FeaturesPlugin/FeaturesPlugin_Union.cpp
src/FeaturesPlugin/FeaturesPlugin_Validators.cpp
src/FeaturesPlugin/FeaturesPlugin_Validators.h
src/FeaturesPlugin/Test/Test1922.py
src/FeaturesPlugin/Test/Test1942.py
src/FeaturesPlugin/Test/Test2023.py
src/FeaturesPlugin/Test/Test2038.py
src/FeaturesPlugin/Test/Test2046.py
src/FeaturesPlugin/Test/Test2194.py
src/FeaturesPlugin/Test/Test2197_2.py
src/FeaturesPlugin/Test/Test2240.py
src/FeaturesPlugin/Test/Test2246.py
src/FeaturesPlugin/Test/Test2255.py
src/FeaturesPlugin/Test/Test2289.py
src/FeaturesPlugin/Test/Test2377.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestBooleanFillWithPlane.py
src/FeaturesPlugin/Test/TestFillCompFaceSolid.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillEdgeEdge.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillEdgeEdgeIntersected.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillEdgeFace.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillEdgeShell.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillEdgeSolid.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillEdgeSolidIntersected.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillEdgeVertex.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillEdgeWire.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillFaceEdge.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillFaceEdgeInside.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillFaceEdgePerpendicular.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillFaceFace.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillFaceShell.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillFaceSolid.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillFaceVertex.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillFaceWire.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillShellConstrPlane.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillShellEdge.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillShellFace.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillShellShell.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillShellSolid.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillShellVertex.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillShellWire.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillSolid2ConstructionPlanes.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillSolidCompFace.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillSolidCompShell.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillSolidEdge.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillSolidFace.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillSolidShell.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillWireEdge.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillWireFace.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillWireShell.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillWireSolid.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillWireVertex.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillWireWire.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestFillet.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestPartition2Faces.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestPartition2Solids.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestPartition2Wires.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestPartitionBox4Planes.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestPartitionEdgeSolid.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestPartitionFace2Solid.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestPartitionFaceSolid.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestPartitionFaceWire.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestPartitionInclinedFaceSolid.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestPartitionWireFaceSolid.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestUnion4CurvedFaces.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestUnion4Faces.py [new file with mode: 0644]
src/FeaturesPlugin/boolean_widget.xml
src/FeaturesPlugin/fillet_widget.xml [new file with mode: 0644]
src/FeaturesPlugin/icons/fillet.png [new file with mode: 0644]
src/FeaturesPlugin/icons/fillet_fixed_radius.png [new file with mode: 0644]
src/FeaturesPlugin/icons/fillet_var_radius.png [new file with mode: 0644]
src/FeaturesPlugin/plugin-Features.xml
src/GeomAPI/GeomAPI_DataMapOfShapeMapOfShapes.cpp
src/GeomAPI/GeomAPI_DataMapOfShapeMapOfShapes.h
src/GeomAPI/GeomAPI_Shape.cpp
src/GeomAPI/GeomAPI_Shape.h
src/GeomAPI/GeomAPI_Wire.cpp
src/GeomAPI/GeomAPI_Wire.h
src/GeomAlgoAPI/CMakeLists.txt
src/GeomAlgoAPI/GeomAlgoAPI.i
src/GeomAlgoAPI/GeomAlgoAPI_Fillet.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Fillet.h [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Filling.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Filling.h [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_MakeVolume.cpp
src/GeomAlgoAPI/GeomAlgoAPI_PaveFiller.cpp
src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp
src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp
src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h
src/GeomAlgoAPI/GeomAlgoAPI_SortListOfShapes.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_SortListOfShapes.h [new file with mode: 0644]
src/GeomValidators/CMakeLists.txt
src/GeomValidators/GeomValidators_ValueOrder.cpp [new file with mode: 0644]
src/GeomValidators/GeomValidators_ValueOrder.h [new file with mode: 0644]
src/Model/Model_AttributeSelection.cpp
src/Model/Model_BodyBuilder.cpp
src/Model/Model_Data.cpp
src/Model/Model_Data.h
src/Model/Model_Document.cpp
src/Model/Model_Document.h
src/Model/Model_Objects.cpp
src/Model/Model_Objects.h
src/Model/Model_ResultConstruction.cpp
src/Model/Model_SelectionNaming.cpp
src/ModelAPI/CMakeLists.txt
src/ModelAPI/ModelAPI.i
src/ModelAPI/ModelAPI_Data.h
src/ModelAPI/ModelAPI_Document.h
src/ModelAPI/ModelAPI_Folder.cpp [new file with mode: 0644]
src/ModelAPI/ModelAPI_Folder.h [new file with mode: 0644]
src/ModelAPI/ModelAPI_Tools.cpp
src/ModelAPI/ModelAPI_Tools.h
src/ModelAPI/ModelAPI_swig.h
src/ModelAPI/Test/Test1512.py
src/ModelAPI/Test/Test1757.py
src/ModelAPI/Test/Test2170.py
src/ModelAPI/Test/Test2228.py
src/ModelAPI/Test/Test2241.py
src/ModelAPI/Test/TestCustomName_BooleanCut.py
src/ModelAPI/Test/TestCustomName_CutCompSolid.py
src/ModelAPI/Test/TestCustomName_CutGroup.py
src/ModelAPI/Test/TestFolder_Create.py [new file with mode: 0644]
src/ModelAPI/Test/TestFolder_Remove.py [new file with mode: 0644]
src/ModelAPI/Test/TestFolder_Sketch.py [new file with mode: 0644]
src/ModelAPI/Test/TestFolder_Stability.py [new file with mode: 0644]
src/ModelAPI/Test/TestFolder_Update.py [new file with mode: 0644]
src/ModelHighAPI/CMakeLists.txt
src/ModelHighAPI/ModelHighAPI.i
src/ModelHighAPI/ModelHighAPI_Dumper.cpp
src/ModelHighAPI/ModelHighAPI_Dumper.h
src/ModelHighAPI/ModelHighAPI_FeatureStore.cpp
src/ModelHighAPI/ModelHighAPI_FeatureStore.h
src/ModelHighAPI/ModelHighAPI_Folder.cpp [new file with mode: 0644]
src/ModelHighAPI/ModelHighAPI_Folder.h [new file with mode: 0644]
src/ModelHighAPI/ModelHighAPI_Tools.cpp
src/ModelHighAPI/ModelHighAPI_swig.h
src/ModuleBase/CMakeLists.txt
src/ModuleBase/ModuleBase_ActionIntParameter.h [new file with mode: 0644]
src/ModuleBase/ModuleBase_ActionParameter.h [new file with mode: 0644]
src/ModuleBase/ModuleBase_ActionType.h
src/ModuleBase/ModuleBase_BRepOwner.cpp [new file with mode: 0644]
src/ModuleBase/ModuleBase_BRepOwner.h [new file with mode: 0644]
src/ModuleBase/ModuleBase_IModule.h
src/ModuleBase/ModuleBase_IPropertyPanel.h
src/ModuleBase/ModuleBase_ISelection.h
src/ModuleBase/ModuleBase_ISelectionActivate.h [new file with mode: 0644]
src/ModuleBase/ModuleBase_IWorkshop.h
src/ModuleBase/ModuleBase_ListView.cpp [new file with mode: 0644]
src/ModuleBase/ModuleBase_ListView.h [new file with mode: 0644]
src/ModuleBase/ModuleBase_ModelWidget.cpp
src/ModuleBase/ModuleBase_ModelWidget.h
src/ModuleBase/ModuleBase_OperationFeature.cpp
src/ModuleBase/ModuleBase_ResultPrs.cpp
src/ModuleBase/ModuleBase_ResultPrs.h
src/ModuleBase/ModuleBase_Tools.cpp
src/ModuleBase/ModuleBase_Tools.h
src/ModuleBase/ModuleBase_ViewerPrs.cpp
src/ModuleBase/ModuleBase_WidgetFeatureSelector.cpp
src/ModuleBase/ModuleBase_WidgetFeatureSelector.h
src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp
src/ModuleBase/ModuleBase_WidgetMultiSelector.h
src/ModuleBase/ModuleBase_WidgetSelector.cpp
src/ModuleBase/ModuleBase_WidgetSelector.h
src/ModuleBase/ModuleBase_WidgetValidated.cpp
src/ModuleBase/ModuleBase_WidgetValidated.h
src/ModuleBase/ModuleBase_WidgetValidator.cpp
src/ModuleBase/ModuleBase_WidgetValidator.h
src/ParametersPlugin/ParametersPlugin_WidgetParamsMgr.cpp
src/PartSet/PartSet_ExternalObjectsMgr.cpp
src/PartSet/PartSet_ExternalObjectsMgr.h
src/PartSet/PartSet_ExternalPointsMgr.cpp
src/PartSet/PartSet_Filters.cpp
src/PartSet/PartSet_Filters.h
src/PartSet/PartSet_Module.cpp
src/PartSet/PartSet_Module.h
src/PartSet/PartSet_PreviewSketchPlane.cpp
src/PartSet/PartSet_SketcherMgr.cpp
src/PartSet/PartSet_SketcherMgr.h
src/PartSet/PartSet_SketcherReentrantMgr.cpp
src/PartSet/PartSet_SketcherReentrantMgr.h
src/PartSet/PartSet_Tools.cpp
src/PartSet/PartSet_Tools.h
src/PartSet/PartSet_WidgetFeaturePointSelector.cpp
src/PartSet/PartSet_WidgetFeaturePointSelector.h
src/PartSet/PartSet_WidgetMultiSelector.cpp
src/PartSet/PartSet_WidgetPoint2d.cpp
src/PartSet/PartSet_WidgetPoint2d.h
src/PartSet/PartSet_WidgetShapeSelector.cpp
src/PartSet/PartSet_WidgetShapeSelector.h
src/PartSet/PartSet_WidgetSketchCreator.cpp
src/PartSet/PartSet_WidgetSketchCreator.h
src/PartSet/PartSet_WidgetSketchLabel.cpp
src/PartSet/PartSet_WidgetSketchLabel.h
src/PythonAPI/examples/Platine.py
src/PythonAPI/model/build/__init__.py
src/PythonAPI/model/dump/DumpAssistant.py
src/PythonAPI/model/features/__init__.py
src/PythonAPI/model/services/__init__.py
src/PythonAPI/model/tests/tests.py
src/SHAPERGUI/SHAPERGUI.cpp
src/SamplePanelPlugin/CMakeLists.txt
src/SketchAPI/SketchAPI_Constraint.cpp
src/SketchAPI/SketchAPI_Mirror.cpp
src/SketchAPI/SketchAPI_Rotation.cpp
src/SketchAPI/SketchAPI_Sketch.cpp
src/SketchAPI/SketchAPI_Translation.cpp
src/SketchPlugin/CMakeLists.txt
src/SketchPlugin/SketchPlugin_Projection.cpp
src/SketchPlugin/SketchPlugin_Split.cpp
src/SketchPlugin/SketchPlugin_Split.h
src/SketchPlugin/SketchPlugin_Trim.cpp
src/SketchPlugin/SketchPlugin_Trim.h
src/SketchPlugin/Test/Test2341.py [new file with mode: 0644]
src/SketchPlugin/Test/TestConstraintDistanceBehavior.py
src/SketchPlugin/Test/TestDistanceDump.py [new file with mode: 0644]
src/SketchPlugin/Test/TestEdgesOrder.py [new file with mode: 0644]
src/SketchPlugin/Test/TestMovementComplex.py
src/SketchPlugin/plugin-Sketch.xml
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp
src/SketchSolver/SketchSolver_ConstraintMovement.cpp
src/SketcherPrs/SketcherPrs_SymbolPrs.cpp
src/XGUI/CMakeLists.txt
src/XGUI/XGUI_ActionsMgr.h
src/XGUI/XGUI_ActiveControlMgr.cpp [new file with mode: 0644]
src/XGUI/XGUI_ActiveControlMgr.h [new file with mode: 0644]
src/XGUI/XGUI_ActiveControlSelector.h [new file with mode: 0644]
src/XGUI/XGUI_ContextMenuMgr.cpp
src/XGUI/XGUI_ContextMenuMgr.h
src/XGUI/XGUI_DataModel.cpp
src/XGUI/XGUI_DataModel.h
src/XGUI/XGUI_Displayer.cpp
src/XGUI/XGUI_Displayer.h
src/XGUI/XGUI_FacesPanel.cpp [new file with mode: 0644]
src/XGUI/XGUI_FacesPanel.h [new file with mode: 0644]
src/XGUI/XGUI_FacesPanelSelector.cpp [new file with mode: 0644]
src/XGUI/XGUI_FacesPanelSelector.h [new file with mode: 0644]
src/XGUI/XGUI_ModuleConnector.cpp
src/XGUI/XGUI_ModuleConnector.h
src/XGUI/XGUI_ObjectsBrowser.cpp
src/XGUI/XGUI_ObjectsBrowser.h
src/XGUI/XGUI_OperationMgr.cpp
src/XGUI/XGUI_OperationMgr.h
src/XGUI/XGUI_PropertyPanel.cpp
src/XGUI/XGUI_PropertyPanel.h
src/XGUI/XGUI_PropertyPanelSelector.cpp [new file with mode: 0644]
src/XGUI/XGUI_PropertyPanelSelector.h [new file with mode: 0644]
src/XGUI/XGUI_SalomeConnector.h
src/XGUI/XGUI_Selection.cpp
src/XGUI/XGUI_Selection.h
src/XGUI/XGUI_SelectionActivate.cpp [new file with mode: 0644]
src/XGUI/XGUI_SelectionActivate.h [new file with mode: 0644]
src/XGUI/XGUI_SelectionFilterType.h [new file with mode: 0644]
src/XGUI/XGUI_SelectionMgr.cpp
src/XGUI/XGUI_SelectionMgr.h
src/XGUI/XGUI_Workshop.cpp
src/XGUI/XGUI_Workshop.h
src/XGUI/XGUI_WorkshopListener.cpp
src/XGUI/XGUI_pictures.qrc
src/XGUI/pictures/create_folder.png [new file with mode: 0644]
src/XGUI/pictures/eyeclosed.png
src/XGUI/pictures/eyemiclosed.png
src/XGUI/pictures/eyeopen.png
src/XGUI/pictures/features_folder.png [new file with mode: 0644]
src/XGUI/pictures/insert_folder_after.png [new file with mode: 0644]
src/XGUI/pictures/insert_folder_before.png [new file with mode: 0644]
src/XGUI/pictures/move_out_after.png [new file with mode: 0644]
src/XGUI/pictures/move_out_before.png [new file with mode: 0644]
src/XGUI/pictures/selection.png [new file with mode: 0644]
test.API/SHAPER/Transformations/TestTranslation_1.py
test.API/SHAPER/Transformations/TestTranslation_2.py
test.models/CSWA.py
test.models/angle30.py
test.models/bearing_puller.py
test.models/bobine_film_reel.py
test.models/bracket32.py
test.models/bushing.py
test.models/case24.py
test.models/clothespin.py
test.models/ecran.py
test.models/flange.py
test.models/gear.py
test.models/idler_plate.py
test.models/piece_02.py
test.models/piece_09.py
test.models/piece_12.py

index ea6768c3e439bcd25dba7d396722dd2f99441113..6ec8c65d5b9c1e789174d3997e76f3849543bd93 100644 (file)
@@ -27,7 +27,7 @@ IF(WIN32)
   CMAKE_POLICY(SET CMP0020 OLD) # disable automatic linking to qtmain.lib
 ENDIF(WIN32)
 
-SET (SHAPER_Version 2.9.1)
+SET (SHAPER_Version 2.10.0RC)
 
 SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeCommon" ${CMAKE_MODULE_PATH})
 
@@ -120,7 +120,6 @@ ADD_SUBDIRECTORY (src/PythonAPI)
 # High Level C++/Python API
 ADD_SUBDIRECTORY (src/ModelHighAPI)
 ADD_SUBDIRECTORY (src/BuildAPI)
-ADD_SUBDIRECTORY (src/ConnectorAPI)
 ADD_SUBDIRECTORY (src/ConstructionAPI)
 ADD_SUBDIRECTORY (src/ExchangeAPI)
 ADD_SUBDIRECTORY (src/FeaturesAPI)
@@ -130,6 +129,7 @@ ADD_SUBDIRECTORY (src/PartSetAPI)
 ADD_SUBDIRECTORY (src/PrimitivesAPI)
 ADD_SUBDIRECTORY (src/SketchAPI)
 ADD_SUBDIRECTORY (src/GDMLAPI)
+ADD_SUBDIRECTORY (src/ConnectorAPI)
 # Tests
 ADD_SUBDIRECTORY (test.API/SHAPER)
 
index 5156e2742d75a0a89d42f7b1b4ce5a4aba922cf7..a9c01420ab6a263fa518acca776c195e968200d3 100644 (file)
 %include "std_shared_ptr.i"
 
 // shared pointers
+%shared_ptr(BuildAPI_Compound)
+%shared_ptr(BuildAPI_CompSolid)
 %shared_ptr(BuildAPI_Edge)
 %shared_ptr(BuildAPI_Face)
+%shared_ptr(BuildAPI_Filling)
 %shared_ptr(BuildAPI_Shell)
+%shared_ptr(BuildAPI_Solid)
 %shared_ptr(BuildAPI_SubShapes)
 %shared_ptr(BuildAPI_Vertex)
 %shared_ptr(BuildAPI_Wire)
 
 // all supported interfaces
+%include "BuildAPI_Compound.h"
+%include "BuildAPI_CompSolid.h"
 %include "BuildAPI_Edge.h"
 %include "BuildAPI_Face.h"
+%include "BuildAPI_Filling.h"
 %include "BuildAPI_Shell.h"
+%include "BuildAPI_Solid.h"
 %include "BuildAPI_SubShapes.h"
 %include "BuildAPI_Vertex.h"
 %include "BuildAPI_Wire.h"
diff --git a/src/BuildAPI/BuildAPI_CompSolid.cpp b/src/BuildAPI/BuildAPI_CompSolid.cpp
new file mode 100644 (file)
index 0000000..fbe84fc
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "BuildAPI_CompSolid.h"
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Tools.h>
+
+//==================================================================================================
+BuildAPI_CompSolid::BuildAPI_CompSolid(const std::shared_ptr<ModelAPI_Feature>& theFeature)
+: ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+//==================================================================================================
+BuildAPI_CompSolid::BuildAPI_CompSolid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                             const std::list<ModelHighAPI_Selection>& theBaseObjects)
+: ModelHighAPI_Interface(theFeature)
+{
+  if(initialize()) {
+    setBase(theBaseObjects);
+  }
+}
+
+//==================================================================================================
+BuildAPI_CompSolid::~BuildAPI_CompSolid()
+{
+}
+
+//==================================================================================================
+void BuildAPI_CompSolid::setBase(const std::list<ModelHighAPI_Selection>& theBaseObjects)
+{
+  fillAttribute(theBaseObjects, mybaseObjects);
+  execute();
+}
+
+//==================================================================================================
+void BuildAPI_CompSolid::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  std::string aPartName = theDumper.name(aBase->document());
+
+  theDumper << aBase << " = model.addCompSolid(" << aPartName << ", "
+            << aBase->selectionList(BuildPlugin_CompSolid::BASE_OBJECTS_ID()) << ")" << std::endl;
+}
+
+//==================================================================================================
+CompSolidPtr addCompSolid(const std::shared_ptr<ModelAPI_Document>& thePart,
+                          const std::list<ModelHighAPI_Selection>& theBaseObjects)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(BuildAPI_CompSolid::ID());
+  return CompSolidPtr(new BuildAPI_CompSolid(aFeature, theBaseObjects));
+}
diff --git a/src/BuildAPI/BuildAPI_CompSolid.h b/src/BuildAPI/BuildAPI_CompSolid.h
new file mode 100644 (file)
index 0000000..c3652e5
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef BuildAPI_CompSolid_H_
+#define BuildAPI_CompSolid_H_
+
+#include "BuildAPI.h"
+
+#include <BuildPlugin_CompSolid.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Selection;
+
+/// \class BuildAPI_CompSolid
+/// \ingroup CPPHighAPI
+/// \brief Interface for CompSolid feature.
+class BuildAPI_CompSolid: public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  BUILDAPI_EXPORT
+  explicit BuildAPI_CompSolid(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values.
+  BUILDAPI_EXPORT
+  explicit BuildAPI_CompSolid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                         const std::list<ModelHighAPI_Selection>& theBaseObjects);
+
+  /// Destructor.
+  BUILDAPI_EXPORT
+  virtual ~BuildAPI_CompSolid();
+
+  INTERFACE_1(BuildPlugin_CompSolid::ID(),
+              baseObjects, BuildPlugin_CompSolid::BASE_OBJECTS_ID(),
+              ModelAPI_AttributeSelectionList, /** Base objects */)
+
+  /// Modify base attribute of the feature.
+  BUILDAPI_EXPORT
+  void setBase(const std::list<ModelHighAPI_Selection>& theBaseObjects);
+
+  /// Dump wrapped feature
+  BUILDAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+};
+
+/// Pointer on CompSolid object.
+typedef std::shared_ptr<BuildAPI_CompSolid> CompSolidPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create CompSolid feature.
+BUILDAPI_EXPORT
+CompSolidPtr addCompSolid(const std::shared_ptr<ModelAPI_Document>& thePart,
+                          const std::list<ModelHighAPI_Selection>& theBaseObjects);
+
+#endif // BuildAPI_CompSolid_H_
diff --git a/src/BuildAPI/BuildAPI_Compound.cpp b/src/BuildAPI/BuildAPI_Compound.cpp
new file mode 100644 (file)
index 0000000..5f03656
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "BuildAPI_Compound.h"
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Tools.h>
+
+//==================================================================================================
+BuildAPI_Compound::BuildAPI_Compound(const std::shared_ptr<ModelAPI_Feature>& theFeature)
+: ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+//==================================================================================================
+BuildAPI_Compound::BuildAPI_Compound(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                             const std::list<ModelHighAPI_Selection>& theBaseObjects)
+: ModelHighAPI_Interface(theFeature)
+{
+  if(initialize()) {
+    setBase(theBaseObjects);
+  }
+}
+
+//==================================================================================================
+BuildAPI_Compound::~BuildAPI_Compound()
+{
+}
+
+//==================================================================================================
+void BuildAPI_Compound::setBase(const std::list<ModelHighAPI_Selection>& theBaseObjects)
+{
+  fillAttribute(theBaseObjects, mybaseObjects);
+  execute();
+}
+
+//==================================================================================================
+void BuildAPI_Compound::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  std::string aPartName = theDumper.name(aBase->document());
+
+  theDumper << aBase << " = model.addCompound(" << aPartName << ", "
+            << aBase->selectionList(BuildPlugin_Compound::BASE_OBJECTS_ID()) << ")" << std::endl;
+}
+
+//==================================================================================================
+CompoundPtr addCompound(const std::shared_ptr<ModelAPI_Document>& thePart,
+                        const std::list<ModelHighAPI_Selection>& theBaseObjects)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(BuildAPI_Compound::ID());
+  return CompoundPtr(new BuildAPI_Compound(aFeature, theBaseObjects));
+}
diff --git a/src/BuildAPI/BuildAPI_Compound.h b/src/BuildAPI/BuildAPI_Compound.h
new file mode 100644 (file)
index 0000000..80daee6
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef BuildAPI_Compound_H_
+#define BuildAPI_Compound_H_
+
+#include "BuildAPI.h"
+
+#include <BuildPlugin_Compound.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Selection;
+
+/// \class BuildAPI_Compound
+/// \ingroup CPPHighAPI
+/// \brief Interface for Compound feature.
+class BuildAPI_Compound: public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  BUILDAPI_EXPORT
+  explicit BuildAPI_Compound(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values.
+  BUILDAPI_EXPORT
+  explicit BuildAPI_Compound(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                         const std::list<ModelHighAPI_Selection>& theBaseObjects);
+
+  /// Destructor.
+  BUILDAPI_EXPORT
+  virtual ~BuildAPI_Compound();
+
+  INTERFACE_1(BuildPlugin_Compound::ID(),
+              baseObjects, BuildPlugin_Compound::BASE_OBJECTS_ID(),
+              ModelAPI_AttributeSelectionList, /** Base objects */)
+
+  /// Modify base attribute of the feature.
+  BUILDAPI_EXPORT
+  void setBase(const std::list<ModelHighAPI_Selection>& theBaseObjects);
+
+  /// Dump wrapped feature
+  BUILDAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+};
+
+/// Pointer on Compound object.
+typedef std::shared_ptr<BuildAPI_Compound> CompoundPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create Compound feature.
+BUILDAPI_EXPORT
+CompoundPtr addCompound(const std::shared_ptr<ModelAPI_Document>& thePart,
+                        const std::list<ModelHighAPI_Selection>& theBaseObjects);
+
+#endif // BuildAPI_Compound_H_
diff --git a/src/BuildAPI/BuildAPI_Filling.cpp b/src/BuildAPI/BuildAPI_Filling.cpp
new file mode 100644 (file)
index 0000000..8951bd8
--- /dev/null
@@ -0,0 +1,180 @@
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "BuildAPI_Filling.h"
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Tools.h>
+
+BuildAPI_Filling::BuildAPI_Filling(const std::shared_ptr<ModelAPI_Feature>& theFeature)
+  : ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+BuildAPI_Filling::BuildAPI_Filling(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                   const std::list<ModelHighAPI_Selection>& theBaseObjects)
+  : ModelHighAPI_Interface(theFeature)
+{
+  if(initialize())
+    setBase(theBaseObjects);
+}
+
+BuildAPI_Filling::BuildAPI_Filling(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                   const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                                   const std::string& theOrientCorrection,
+                                   const int theMinDegree,
+                                   const int theMaxDegree,
+                                   const int theNbIter,
+                                   const double theTolerance2D,
+                                   const double theTolerance3D,
+                                   const bool theApproximate)
+  : ModelHighAPI_Interface(theFeature)
+{
+  if(initialize()) {
+    setOrientationMethod(theOrientCorrection);
+    setMinDegree(theMinDegree);
+    setMaxDegree(theMaxDegree);
+    setNbIterations(theNbIter);
+    setTolerance2d(theTolerance2D);
+    setTolerance3d(theTolerance3D);
+    setApproximation(theApproximate);
+    setAdvancedOptions();
+    setBase(theBaseObjects);
+  }
+}
+
+BuildAPI_Filling::~BuildAPI_Filling()
+{
+}
+
+void BuildAPI_Filling::execIfBaseNotEmpty()
+{
+  if (baseObjects()->size() > 0)
+    execute();
+}
+
+void BuildAPI_Filling::setBase(const std::list<ModelHighAPI_Selection>& theBaseObjects)
+{
+  fillAttribute(theBaseObjects, mybaseObjects);
+  execIfBaseNotEmpty();
+}
+
+void BuildAPI_Filling::setOrientationMethod(const std::string& theMethod)
+{
+  fillAttribute(theMethod, myorientationMethod);
+  if (theMethod != BuildPlugin_Filling::METHOD_DEFAULT())
+    setAdvancedOptions();
+  execIfBaseNotEmpty();
+}
+
+void BuildAPI_Filling::setMinDegree(const int theMinDegree)
+{
+  fillAttribute(theMinDegree, myminDegree);
+  if (theMinDegree != BuildPlugin_Filling::MINIMAL_DEGREE_DEFAULT())
+    setAdvancedOptions();
+  execIfBaseNotEmpty();
+}
+
+void BuildAPI_Filling::setMaxDegree(const int theMaxDegree)
+{
+  fillAttribute(theMaxDegree, mymaxDegree);
+  if (theMaxDegree != BuildPlugin_Filling::MAXIMAL_DEGREE_DEFAULT())
+    setAdvancedOptions();
+  execIfBaseNotEmpty();
+}
+
+void BuildAPI_Filling::setNbIterations(const int theNbIter)
+{
+  fillAttribute(theNbIter, mynbIterations);
+  if (theNbIter != BuildPlugin_Filling::NUMBER_OF_ITERATIONS_DEFAULT())
+    setAdvancedOptions();
+  execIfBaseNotEmpty();
+}
+
+void BuildAPI_Filling::setTolerance2d(const double theTol2d)
+{
+  fillAttribute(theTol2d, mytolerance2d);
+  if (theTol2d != BuildPlugin_Filling::TOLERANCE_2D_DEFAULT())
+    setAdvancedOptions();
+  execIfBaseNotEmpty();
+}
+
+void BuildAPI_Filling::setTolerance3d(const double theTol3d)
+{
+  fillAttribute(theTol3d, mytolerance3d);
+  if (theTol3d != BuildPlugin_Filling::TOLERANCE_3D_DEFAULT())
+    setAdvancedOptions();
+  execIfBaseNotEmpty();
+}
+
+void BuildAPI_Filling::setApproximation(const bool theApproximate)
+{
+  fillAttribute(theApproximate, myapproximate);
+  if (theApproximate != BuildPlugin_Filling::APPROXIMATION_DEFAULT())
+    setAdvancedOptions();
+  execIfBaseNotEmpty();
+}
+
+void BuildAPI_Filling::setAdvancedOptions()
+{
+  feature()->string(BuildPlugin_Filling::ADVANCED_OPTIONS_ID())->setValue("true");
+}
+
+void BuildAPI_Filling::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  std::string aPartName = theDumper.name(aBase->document());
+
+  theDumper << aBase << " = model.addFilling(" << aPartName << ", " << baseObjects();
+
+  if (!aBase->string(BuildPlugin_Filling::ADVANCED_OPTIONS_ID())->value().empty()) {
+    // dump options too,
+    theDumper << ", " << orientationMethod()
+              << ", " << minDegree() << ", " << maxDegree() << ", " << nbIterations()
+              << ", " << tolerance2d() << ", " << tolerance3d()
+              << ", " << approximate();
+  }
+  theDumper << ")" << std::endl;
+}
+
+//==================================================================================================
+
+FillingPtr addFilling(const std::shared_ptr<ModelAPI_Document>& thePart,
+                      const std::list<ModelHighAPI_Selection>& theBaseObjects)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(BuildAPI_Filling::ID());
+  return FillingPtr(new BuildAPI_Filling(aFeature, theBaseObjects));
+}
+
+FillingPtr addFilling(const std::shared_ptr<ModelAPI_Document>& thePart,
+                      const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                      const std::string& theOrientCorrection,
+                      const int theMinDegree,
+                      const int theMaxDegree,
+                      const int theNbIter,
+                      const double theTolerance2D,
+                      const double theTolerance3D,
+                      const bool theApproximate)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(BuildAPI_Filling::ID());
+  return FillingPtr(new BuildAPI_Filling(aFeature, theBaseObjects, theOrientCorrection,
+      theMinDegree, theMaxDegree, theNbIter, theTolerance2D, theTolerance3D, theApproximate));
+}
diff --git a/src/BuildAPI/BuildAPI_Filling.h b/src/BuildAPI/BuildAPI_Filling.h
new file mode 100644 (file)
index 0000000..8ccab1f
--- /dev/null
@@ -0,0 +1,141 @@
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef BuildAPI_Filling_H_
+#define BuildAPI_Filling_H_
+
+#include "BuildAPI.h"
+
+#include <BuildPlugin_Filling.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Selection;
+
+/// \class BuildAPI_Filling
+/// \ingroup CPPHighAPI
+/// \brief Interface for Filling feature.
+class BuildAPI_Filling : public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  BUILDAPI_EXPORT explicit BuildAPI_Filling(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with base objects.
+  BUILDAPI_EXPORT
+  explicit BuildAPI_Filling(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                            const std::list<ModelHighAPI_Selection>& theBaseObjects);
+
+  /// Constructor with values.
+  BUILDAPI_EXPORT
+  explicit BuildAPI_Filling(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                            const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                            const std::string& theOrientCorrection,
+                            const int theMinDegree,
+                            const int theMaxDegree,
+                            const int theNbIter,
+                            const double theTolerance2D,
+                            const double theTolerance3D,
+                            const bool theApproximate);
+
+  /// Destructor.
+  BUILDAPI_EXPORT virtual ~BuildAPI_Filling();
+
+  INTERFACE_8(BuildPlugin_Filling::ID(),
+              baseObjects, BuildPlugin_Filling::BASE_OBJECTS_ID(),
+                           ModelAPI_AttributeSelectionList,
+                           /** Base objects */,
+              orientationMethod, BuildPlugin_Filling::METHOD_ID(),
+                                 ModelAPI_AttributeString,
+                                 /** Method to keep edge orientaion */,
+              minDegree, BuildPlugin_Filling::MINIMAL_DEGREE_ID(),
+                         ModelAPI_AttributeInteger,
+                         /** Minimal degree */,
+              maxDegree, BuildPlugin_Filling::MAXIMAL_DEGREE_ID(),
+                         ModelAPI_AttributeInteger,
+                         /** Maximal degree */,
+              nbIterations, BuildPlugin_Filling::NUMBER_OF_ITERATIONS_ID(),
+                            ModelAPI_AttributeInteger,
+                            /** Number of iterations */,
+              tolerance2d, BuildPlugin_Filling::TOLERANCE_2D_ID(),
+                           ModelAPI_AttributeDouble,
+                           /** 2D tolerance */,
+              tolerance3d, BuildPlugin_Filling::TOLERANCE_3D_ID(),
+                           ModelAPI_AttributeDouble,
+                           /** 3D tolerance */,
+              approximate, BuildPlugin_Filling::APPROXIMATION_ID(),
+                           ModelAPI_AttributeBoolean,
+                           /** Approximate original edges */)
+
+  /// Modify base attribute of the feature.
+  BUILDAPI_EXPORT void setBase(const std::list<ModelHighAPI_Selection>& theBaseObjects);
+
+  /// Modify orientation method
+  BUILDAPI_EXPORT void setOrientationMethod(const std::string& theMethod);
+
+  /// Modify minimal degree of result B-spline
+  BUILDAPI_EXPORT void setMinDegree(const int theMinDegree);
+
+  /// Modify maximal degree of result B-spline
+  BUILDAPI_EXPORT void setMaxDegree(const int theMaxDegree);
+
+  /// Modify number of iterations
+  BUILDAPI_EXPORT void setNbIterations(const int theNbIter);
+
+  /// Set 2D tolerance
+  BUILDAPI_EXPORT void setTolerance2d(const double theTol2d);
+
+  /// Set 3D tolerance
+  BUILDAPI_EXPORT void setTolerance3d(const double theTol3d);
+
+  /// Set approximation flag
+  BUILDAPI_EXPORT void setApproximation(const bool theApproximate);
+
+  /// Dump wrapped feature
+  BUILDAPI_EXPORT virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+
+private:
+  void execIfBaseNotEmpty();
+  void setAdvancedOptions();
+};
+
+/// Pointer on Face object.
+typedef std::shared_ptr<BuildAPI_Filling> FillingPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create Filling feature.
+BUILDAPI_EXPORT FillingPtr addFilling(const std::shared_ptr<ModelAPI_Document>& thePart,
+                                      const std::list<ModelHighAPI_Selection>& theBaseObjects);
+
+/// \ingroup CPPHighAPI
+/// \brief Create Filling feature.
+BUILDAPI_EXPORT FillingPtr addFilling(
+      const std::shared_ptr<ModelAPI_Document>& thePart,
+      const std::list<ModelHighAPI_Selection>& theBaseObjects,
+      const std::string& theOrientCorrection,
+      const int theMinDegree = BuildPlugin_Filling::MINIMAL_DEGREE_DEFAULT(),
+      const int theMaxDegree = BuildPlugin_Filling::MAXIMAL_DEGREE_DEFAULT(),
+      const int theNbIter = BuildPlugin_Filling::NUMBER_OF_ITERATIONS_DEFAULT(),
+      const double theTolerance2D = BuildPlugin_Filling::TOLERANCE_2D_DEFAULT(),
+      const double theTolerance3D = BuildPlugin_Filling::TOLERANCE_3D_DEFAULT(),
+      const bool theApproximate = BuildPlugin_Filling::APPROXIMATION_DEFAULT());
+
+#endif // BuildAPI_Filling_H_
diff --git a/src/BuildAPI/BuildAPI_Solid.cpp b/src/BuildAPI/BuildAPI_Solid.cpp
new file mode 100644 (file)
index 0000000..a2c7892
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "BuildAPI_Solid.h"
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Tools.h>
+
+//==================================================================================================
+BuildAPI_Solid::BuildAPI_Solid(const std::shared_ptr<ModelAPI_Feature>& theFeature)
+: ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+//==================================================================================================
+BuildAPI_Solid::BuildAPI_Solid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                             const std::list<ModelHighAPI_Selection>& theBaseObjects)
+: ModelHighAPI_Interface(theFeature)
+{
+  if(initialize()) {
+    setBase(theBaseObjects);
+  }
+}
+
+//==================================================================================================
+BuildAPI_Solid::~BuildAPI_Solid()
+{
+}
+
+//==================================================================================================
+void BuildAPI_Solid::setBase(const std::list<ModelHighAPI_Selection>& theBaseObjects)
+{
+  fillAttribute(theBaseObjects, mybaseObjects);
+  execute();
+}
+
+//==================================================================================================
+void BuildAPI_Solid::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  std::string aPartName = theDumper.name(aBase->document());
+
+  theDumper << aBase << " = model.addSolid(" << aPartName << ", "
+            << aBase->selectionList(BuildPlugin_Solid::BASE_OBJECTS_ID()) << ")" << std::endl;
+}
+
+//==================================================================================================
+SolidPtr addSolid(const std::shared_ptr<ModelAPI_Document>& thePart,
+                  const std::list<ModelHighAPI_Selection>& theBaseObjects)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(BuildAPI_Solid::ID());
+  return SolidPtr(new BuildAPI_Solid(aFeature, theBaseObjects));
+}
diff --git a/src/BuildAPI/BuildAPI_Solid.h b/src/BuildAPI/BuildAPI_Solid.h
new file mode 100644 (file)
index 0000000..1ab0004
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef BuildAPI_Solid_H_
+#define BuildAPI_Solid_H_
+
+#include "BuildAPI.h"
+
+#include <BuildPlugin_Solid.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Selection;
+
+/// \class BuildAPI_Solid
+/// \ingroup CPPHighAPI
+/// \brief Interface for Solid feature.
+class BuildAPI_Solid: public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  BUILDAPI_EXPORT
+  explicit BuildAPI_Solid(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values.
+  BUILDAPI_EXPORT
+  explicit BuildAPI_Solid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                         const std::list<ModelHighAPI_Selection>& theBaseObjects);
+
+  /// Destructor.
+  BUILDAPI_EXPORT
+  virtual ~BuildAPI_Solid();
+
+  INTERFACE_1(BuildPlugin_Solid::ID(),
+              baseObjects, BuildPlugin_Solid::BASE_OBJECTS_ID(),
+              ModelAPI_AttributeSelectionList, /** Base objects */)
+
+  /// Modify base attribute of the feature.
+  BUILDAPI_EXPORT
+  void setBase(const std::list<ModelHighAPI_Selection>& theBaseObjects);
+
+  /// Dump wrapped feature
+  BUILDAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+};
+
+/// Pointer on Solid object.
+typedef std::shared_ptr<BuildAPI_Solid> SolidPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create Solid feature.
+BUILDAPI_EXPORT
+SolidPtr addSolid(const std::shared_ptr<ModelAPI_Document>& thePart,
+                  const std::list<ModelHighAPI_Selection>& theBaseObjects);
+
+#endif // BuildAPI_Solid_H_
index b0bddae3b31288f1eaf03c2023adbbee7653e438..616486f6446f4d6c81bb65ff709deb67d3618d6f 100644 (file)
 
   #include <ModelHighAPI_swig.h>
 
+  #include "BuildAPI_Compound.h"
+  #include "BuildAPI_CompSolid.h"
   #include "BuildAPI_Edge.h"
   #include "BuildAPI_Face.h"
+  #include "BuildAPI_Filling.h"
   #include "BuildAPI_Shell.h"
+  #include "BuildAPI_Solid.h"
   #include "BuildAPI_SubShapes.h"
   #include "BuildAPI_Vertex.h"
   #include "BuildAPI_Wire.h"
index 3ffcf78ccd22faee6a68abe8972a81ce8013cf68..2e03584043b04a1c3fe0f478f60c245893c9b80e 100644 (file)
@@ -22,18 +22,26 @@ INCLUDE(Common)
 
 SET(PROJECT_HEADERS
   BuildAPI.h
+  BuildAPI_Compound.h
+  BuildAPI_CompSolid.h
   BuildAPI_Edge.h
   BuildAPI_Face.h
+  BuildAPI_Filling.h
   BuildAPI_Shell.h
+  BuildAPI_Solid.h
   BuildAPI_SubShapes.h
   BuildAPI_Vertex.h
   BuildAPI_Wire.h
 )
 
 SET(PROJECT_SOURCES
+  BuildAPI_Compound.cpp
+  BuildAPI_CompSolid.cpp
   BuildAPI_Edge.cpp
   BuildAPI_Face.cpp
+  BuildAPI_Filling.cpp
   BuildAPI_Shell.cpp
+  BuildAPI_Solid.cpp
   BuildAPI_SubShapes.cpp
   BuildAPI_Vertex.cpp
   BuildAPI_Wire.cpp
diff --git a/src/BuildPlugin/BuildPlugin_CompSolid.cpp b/src/BuildPlugin/BuildPlugin_CompSolid.cpp
new file mode 100644 (file)
index 0000000..8b19e13
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "BuildPlugin_CompSolid.h"
+
+#include <GeomAlgoAPI_MakeShape.h>
+#include <ModelAPI_AttributeSelectionList.h>
+
+//=================================================================================================
+BuildPlugin_CompSolid::BuildPlugin_CompSolid()
+{
+}
+
+//=================================================================================================
+void BuildPlugin_CompSolid::initAttributes()
+{
+  data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
+}
+
+//=================================================================================================
+void BuildPlugin_CompSolid::execute()
+{
+  ListOfShape anOriginalShapes;
+  std::shared_ptr<GeomAlgoAPI_MakeShape> aVolumeMaker;
+  if (!build(anOriginalShapes, aVolumeMaker))
+    return;
+
+  GeomShapePtr aVolumeRes = aVolumeMaker->shape();
+
+  // check and process result of volume maker
+  GeomShapePtr aResShape = getSingleSubshape(aVolumeRes, GeomAPI_Shape::COMPSOLID);
+  if (!aResShape) // try to build a solid
+    aResShape = getSingleSubshape(aVolumeRes, GeomAPI_Shape::SOLID);
+
+  int anIndex = 0;
+  if (aResShape) {
+    storeResult(anOriginalShapes, aResShape, aVolumeMaker);
+    ++anIndex;
+  }
+  removeResults(anIndex);
+}
diff --git a/src/BuildPlugin/BuildPlugin_CompSolid.h b/src/BuildPlugin/BuildPlugin_CompSolid.h
new file mode 100644 (file)
index 0000000..e31865a
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef BuildPlugin_CompSolid_H_
+#define BuildPlugin_CompSolid_H_
+
+#include "BuildPlugin.h"
+#include "BuildPlugin_Solid.h"
+
+/// \class BuildPlugin_CompSolid
+/// \ingroup Plugins
+/// \brief Feature for creation of compsolid from solids or compsolids.
+class BuildPlugin_CompSolid: public BuildPlugin_Solid
+{
+public:
+  /// Use plugin manager for features creation
+  BuildPlugin_CompSolid();
+
+  /// Feature kind.
+  inline static const std::string& ID()
+  {
+    static const std::string MY_ID("CompSolid");
+    return MY_ID;
+  }
+
+  /// Attribute name of base objects.
+  inline static const std::string& BASE_OBJECTS_ID()
+  {
+    static const std::string MY_BASE_OBJECTS_ID("base_objects");
+    return MY_BASE_OBJECTS_ID;
+  }
+
+  /// \return the kind of a feature.
+  BUILDPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = BuildPlugin_CompSolid::ID();
+    return MY_KIND;
+  }
+
+  /// Request for initialization of data model of the feature: adding all attributes.
+  BUILDPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Creates a new part document if needed.
+  BUILDPLUGIN_EXPORT virtual void execute();
+};
+
+#endif
diff --git a/src/BuildPlugin/BuildPlugin_Compound.cpp b/src/BuildPlugin/BuildPlugin_Compound.cpp
new file mode 100644 (file)
index 0000000..4df84ee
--- /dev/null
@@ -0,0 +1,84 @@
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "BuildPlugin_Compound.h"
+
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_ResultBody.h>
+
+#include <GeomAlgoAPI_CompoundBuilder.h>
+
+
+//=================================================================================================
+BuildPlugin_Compound::BuildPlugin_Compound()
+{
+}
+
+//=================================================================================================
+void BuildPlugin_Compound::initAttributes()
+{
+  data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
+}
+
+//=================================================================================================
+void BuildPlugin_Compound::execute()
+{
+  // Get base objects list.
+  AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
+  if(!aSelectionList.get()) {
+    setError("Error: Could not get selection list.");
+    return;
+  }
+  if(aSelectionList->size() == 0) {
+    setError("Error: Empty selection list.");
+    return;
+  }
+
+  // Collect base shapes.
+  ListOfShape anOriginalShapes;
+  for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
+    AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
+    GeomShapePtr aShape = aSelection->value();
+    if (!aShape.get())
+      aShape = aSelection->context()->shape();
+    anOriginalShapes.push_back(aShape);
+  }
+
+  // Build compound.
+  GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(anOriginalShapes);
+  int anIndexToRemove = 0;
+  if (aCompound) {
+    ResultBodyPtr aResultBody = document()->createBody(data(), anIndexToRemove++);
+    aResultBody->store(aCompound);
+
+////    // Store faces
+////    std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubs = theAlgorithm->mapOfSubShapes();
+////    int aModifiedTag = 1;
+////    for(ListOfShape::const_iterator anIt = theOriginalShapes.cbegin();
+////        anIt != theOriginalShapes.cend(); ++anIt) {
+////      GeomShapePtr aShape = *anIt;
+////      aResultBody->loadAndOrientModifiedShapes(theAlgorithm.get(), aShape, GeomAPI_Shape::FACE,
+////          aModifiedTag, "Modified_Face", *aMapOfSubs.get(), false, true, true);
+////    }
+
+    setResult(aResultBody);
+  }
+  removeResults(anIndexToRemove);
+}
diff --git a/src/BuildPlugin/BuildPlugin_Compound.h b/src/BuildPlugin/BuildPlugin_Compound.h
new file mode 100644 (file)
index 0000000..5a01431
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef BuildPlugin_Compound_H_
+#define BuildPlugin_Compound_H_
+
+#include "BuildPlugin.h"
+
+#include <ModelAPI_Feature.h>
+
+/// \class BuildPlugin_Compound
+/// \ingroup Plugins
+/// \brief Feature for creation of compound from different kinds of shapes.
+class BuildPlugin_Compound: public ModelAPI_Feature
+{
+public:
+  /// Use plugin manager for features creation
+  BuildPlugin_Compound();
+
+  /// Feature kind.
+  inline static const std::string& ID()
+  {
+    static const std::string MY_ID("Compound");
+    return MY_ID;
+  }
+
+  /// Attribute name of base objects.
+  inline static const std::string& BASE_OBJECTS_ID()
+  {
+    static const std::string MY_BASE_OBJECTS_ID("base_objects");
+    return MY_BASE_OBJECTS_ID;
+  }
+
+  /// \return the kind of a feature.
+  BUILDPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = BuildPlugin_Compound::ID();
+    return MY_KIND;
+  }
+
+  /// Request for initialization of data model of the feature: adding all attributes.
+  BUILDPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Creates a new part document if needed.
+  BUILDPLUGIN_EXPORT virtual void execute();
+};
+
+#endif
index fb782101f4d6367061db8275806e8629b5531d22..391ea4bd908365dd7bfc51564660f58fe3686c1a 100644 (file)
@@ -59,6 +59,7 @@ void BuildPlugin_Face::execute()
 
   // Collect base shapes.
   ListOfShape anEdges;
+  ListOfShape anOriginalFaces;
   std::list< std::shared_ptr<GeomAPI_Dir> > aListOfNormals;
   for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
     AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
@@ -67,6 +68,12 @@ void BuildPlugin_Face::execute()
     if(!aShape.get()) {
       aShape = aContext;
     }
+    // keep selected faces "as is"
+    if (aShape->shapeType() == GeomAPI_Shape::FACE) {
+      anOriginalFaces.push_back(aShape);
+      continue;
+    }
+
     for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
       GeomShapePtr anEdge = anExp.current();
       anEdges.push_back(anEdge);
@@ -79,39 +86,13 @@ void BuildPlugin_Face::execute()
       aListOfNormals.push_back(aSketch->norm());
   }
 
-  // Get plane.
-  std::shared_ptr<GeomAPI_Pln> aPln = GeomAlgoAPI_ShapeTools::findPlane(anEdges);
-  std::shared_ptr<GeomAPI_Dir> aNormal = aPln->direction();
-  bool isReverse = !aListOfNormals.empty();
-  std::list< std::shared_ptr<GeomAPI_Dir> >::const_iterator aNormIt = aListOfNormals.begin();
-  for (; aNormIt != aListOfNormals.end() && isReverse; ++aNormIt)
-    if ((*aNormIt)->dot(aNormal) > 1.e-7)
-      isReverse = false;
-  if (isReverse) {
-    aNormal->reverse();
-    aPln = std::shared_ptr<GeomAPI_Pln>(new GeomAPI_Pln(aPln->location(), aNormal));
-  }
-
-  // Get faces.
+  // Build faces by edges.
   ListOfShape aFaces;
-  GeomAlgoAPI_SketchBuilder::createFaces(aPln->location(), aPln->xDirection(),
-                                         aPln->direction(), anEdges, aFaces);
-
-  // Get wires from faces.
-  ListOfShape aWires;
-  for(ListOfShape::const_iterator anIt = aFaces.cbegin(); anIt != aFaces.cend(); ++anIt) {
-    aWires.push_back(GeomAlgoAPI_ShapeTools::getFaceOuterWire(*anIt));
-    //for(GeomAPI_ShapeExplorer anExp(*anIt, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) {
-    //  if(anExp.current()->orientation() == GeomAPI_Shape::REVERSED) {
-    //    continue;
-    //  }
-    //  aWires.push_back(anExp.current());
-    //}
-  }
+  if (!anEdges.empty())
+    buildFacesByEdges(anEdges, aListOfNormals, aFaces);
 
-  // Make faces with holes.
-  aFaces.clear();
-  GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aPln->location(), aPln->direction(), aWires, aFaces);
+  // Add faces selected by user.
+  aFaces.insert(aFaces.end(), anOriginalFaces.begin(), anOriginalFaces.end());
 
   // Store result.
   int anIndex = 0;
@@ -136,3 +117,36 @@ void BuildPlugin_Face::execute()
 
   removeResults(anIndex);
 }
+
+void BuildPlugin_Face::buildFacesByEdges(
+    const ListOfShape& theEdges,
+    const std::list< std::shared_ptr<GeomAPI_Dir> >& theNormals,
+    ListOfShape& theFaces) const
+{
+  // Get plane.
+  std::shared_ptr<GeomAPI_Pln> aPln = GeomAlgoAPI_ShapeTools::findPlane(theEdges);
+  std::shared_ptr<GeomAPI_Dir> aNormal = aPln->direction();
+  bool isReverse = !theNormals.empty();
+  std::list< std::shared_ptr<GeomAPI_Dir> >::const_iterator aNormIt = theNormals.begin();
+  for (; aNormIt != theNormals.end() && isReverse; ++aNormIt)
+    if ((*aNormIt)->dot(aNormal) > 1.e-7)
+      isReverse = false;
+  if (isReverse) {
+    aNormal->reverse();
+    aPln = std::shared_ptr<GeomAPI_Pln>(new GeomAPI_Pln(aPln->location(), aNormal));
+  }
+
+  // Get faces.
+  GeomAlgoAPI_SketchBuilder::createFaces(aPln->location(), aPln->xDirection(),
+                                         aPln->direction(), theEdges, theFaces);
+
+  // Get wires from faces.
+  ListOfShape aWires;
+  for(ListOfShape::const_iterator anIt = theFaces.cbegin(); anIt != theFaces.cend(); ++anIt)
+    aWires.push_back(GeomAlgoAPI_ShapeTools::getFaceOuterWire(*anIt));
+
+  // Make faces with holes.
+  theFaces.clear();
+  GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aPln->location(), aPln->direction(),
+                                             aWires, theFaces);
+}
index f6c27632541bc2148c204562297a6b14887be027..633118eb7054da34dab7767efe72d3683bec9950 100644 (file)
@@ -25,6 +25,9 @@
 
 #include <ModelAPI_Feature.h>
 
+class GeomAPI_Dir;
+class GeomAPI_Shape;
+
 /// \class BuildPlugin_Face
 /// \ingroup Plugins
 /// \brief Feature for creation of face from sketch edges or existing wires.
@@ -60,6 +63,12 @@ public:
 
   /// Creates a new part document if needed.
   BUILDPLUGIN_EXPORT virtual void execute();
+
+private:
+  /// Create faces basing on the list of edges
+  void buildFacesByEdges(const std::list< std::shared_ptr<GeomAPI_Shape> >& theEdges,
+                         const std::list< std::shared_ptr<GeomAPI_Dir> >& theNormals,
+                         std::list< std::shared_ptr<GeomAPI_Shape> >& theFaces) const;
 };
 
 #endif
diff --git a/src/BuildPlugin/BuildPlugin_Filling.cpp b/src/BuildPlugin/BuildPlugin_Filling.cpp
new file mode 100644 (file)
index 0000000..7e2c884
--- /dev/null
@@ -0,0 +1,237 @@
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "BuildPlugin_Filling.h"
+
+#include <ModelAPI_AttributeBoolean.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_ResultBody.h>
+
+#include <GeomAlgoAPI_Copy.h>
+#include <GeomAlgoAPI_Filling.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+
+#include <GeomAPI_Pnt.h>
+#include <GeomAPI_ShapeExplorer.h>
+#include <GeomAPI_Wire.h>
+
+#include <cmath>
+
+struct FillingParameters
+{
+  std::string method;
+  int minDegree;
+  int maxDegree;
+  int nbIter;
+  double tol2D;
+  double tol3D;
+  bool isApprox;
+};
+
+
+//=================================================================================================
+BuildPlugin_Filling::BuildPlugin_Filling()
+{
+}
+
+//=================================================================================================
+void BuildPlugin_Filling::initAttributes()
+{
+  data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
+  data()->addAttribute(ADVANCED_OPTIONS_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(METHOD_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(MINIMAL_DEGREE_ID(), ModelAPI_AttributeInteger::typeId());
+  data()->addAttribute(MAXIMAL_DEGREE_ID(), ModelAPI_AttributeInteger::typeId());
+  data()->addAttribute(NUMBER_OF_ITERATIONS_ID(), ModelAPI_AttributeInteger::typeId());
+  data()->addAttribute(TOLERANCE_2D_ID(), ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(TOLERANCE_3D_ID(), ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(APPROXIMATION_ID(), ModelAPI_AttributeBoolean::typeId());
+
+  restoreDefaultParameters();
+  string(ADVANCED_OPTIONS_ID())->setValue("");
+}
+
+//=================================================================================================
+void BuildPlugin_Filling::execute()
+{
+  // get parameters of algorithm
+  FillingParameters aParameters;
+  aParameters.method = string(METHOD_ID())->value();
+  aParameters.minDegree = integer(MINIMAL_DEGREE_ID())->value();
+  aParameters.maxDegree = integer(MAXIMAL_DEGREE_ID())->value();
+  aParameters.nbIter = integer(NUMBER_OF_ITERATIONS_ID())->value();
+  aParameters.tol2D = real(TOLERANCE_2D_ID())->value();
+  aParameters.tol3D = real(TOLERANCE_3D_ID())->value();
+  aParameters.isApprox = boolean(APPROXIMATION_ID())->value();
+
+  if (aParameters.minDegree > aParameters.maxDegree) {
+    setError("Error: " + getKind() + " algorithm failed (max deg < min deg).");
+    return;
+  }
+
+  std::shared_ptr<GeomAlgoAPI_Filling> aFilling(
+      new GeomAlgoAPI_Filling(aParameters.minDegree, aParameters.maxDegree, aParameters.nbIter,
+                              aParameters.tol2D, aParameters.tol3D));
+
+  // get base objects list
+  AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
+  if (aSelectionList->size() <= 1)
+    return;
+
+  // collect base shapes
+  for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
+    AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
+    GeomEdgePtr anEdge = toEdge(aSelection->value(), aParameters.method);
+    if (!anEdge) {
+      myLastEdgeStartPoint = GeomPointPtr();
+      myLastEdgeEndPoint = GeomPointPtr();
+      return;
+    }
+    aFilling->add(anEdge);
+  }
+  myLastEdgeStartPoint = GeomPointPtr();
+  myLastEdgeEndPoint = GeomPointPtr();
+
+  // build result
+  aFilling->build(aParameters.isApprox);
+  if (isAlgorithmFailed(aFilling)) {
+    removeResults(0);
+    return;
+  }
+
+  /// store result
+  GeomShapePtr aCreatedFace = aFilling->shape();
+  ResultBodyPtr aResultBody = document()->createBody(data());
+  aResultBody->store(aCreatedFace);
+  // store edges
+  int anEdgeInd = 0;
+  for(GeomAPI_ShapeExplorer anExp(aCreatedFace, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
+    GeomShapePtr anEdge = anExp.current();
+    aResultBody->generated(anEdge, "Edge_" + std::to_string((long long)anEdgeInd), ++anEdgeInd);
+  }
+  setResult(aResultBody, 0);
+}
+
+bool BuildPlugin_Filling::isAlgorithmFailed(
+    const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgorithm)
+{
+  if (!theAlgorithm->isDone()) {
+    static const std::string aFeatureError = "Error: filling algorithm failed.";
+    setError(aFeatureError);
+    return true;
+  }
+  if (theAlgorithm->shape()->isNull()) {
+    static const std::string aShapeError = "Error: Resulting shape of filling is Null.";
+    setError(aShapeError);
+    return true;
+  }
+  if (!theAlgorithm->isValid()) {
+    std::string aFeatureError = "Error: Resulting shape of filling is not valid.";
+    setError(aFeatureError);
+    return true;
+  }
+  return false;
+}
+
+//=================================================================================================
+void BuildPlugin_Filling::attributeChanged(const std::string& theID)
+{
+  if (theID == ADVANCED_OPTIONS_ID() && string(ADVANCED_OPTIONS_ID())->value().empty()) {
+    // Advanced options flag just unchecked => restore default state of all parameters
+    restoreDefaultParameters();
+  }
+}
+
+//=================================================================================================
+GeomEdgePtr BuildPlugin_Filling::toEdge(const GeomShapePtr& theShape, const std::string& theMethod)
+{
+  GeomEdgePtr anEdge;
+  switch (theShape->shapeType()) {
+  case GeomAPI_Shape::EDGE:
+    anEdge = GeomEdgePtr(new GeomAPI_Edge(GeomAlgoAPI_Copy(theShape).shape()));
+    break;
+  case GeomAPI_Shape::WIRE:
+    anEdge = GeomAlgoAPI_ShapeTools::wireToEdge(
+        GeomWirePtr(new GeomAPI_Wire(theShape)));
+    break;
+  default:
+    break;
+  }
+
+  if (!anEdge || anEdge->empty()) {
+    static const std::string aFeatureError =
+        "Error: incorrect type of input feature (edges/wire are supported only).";
+    setError(aFeatureError);
+    return anEdge;
+  }
+
+  // correct edge orientation according to filling method
+  if (theMethod == Method::AUTO_CORRECT_ORIENTATION()) {
+    // check the distance to previous edge boundaries, reverse edge if necessary
+    GeomPointPtr aStartPnt = anEdge->firstPoint();
+    GeomPointPtr aEndPnt = anEdge->lastPoint();
+    if (anEdge->orientation() == GeomAPI_Shape::REVERSED) {
+      aStartPnt = anEdge->lastPoint();
+      aEndPnt = anEdge->firstPoint();
+    }
+    bool isReverse = false;
+    if (myLastEdgeStartPoint) {
+      double d1 = myLastEdgeStartPoint->distance(aStartPnt)
+                + myLastEdgeEndPoint->distance(aEndPnt);
+      double d2 = myLastEdgeStartPoint->distance(aEndPnt)
+                + myLastEdgeEndPoint->distance(aStartPnt);
+      if (fabs(d1 - d2) < 1.e-7) {
+        // undefined case => check distance to start point only
+        d1 = myLastEdgeStartPoint->distance(aStartPnt);
+        d2 = myLastEdgeStartPoint->distance(aEndPnt);
+      }
+      isReverse = d2 < d1;
+    }
+
+    if (isReverse) {
+      anEdge->reverse();
+      myLastEdgeStartPoint = aEndPnt;
+      myLastEdgeEndPoint = aStartPnt;
+    } else {
+      myLastEdgeStartPoint = aStartPnt;
+      myLastEdgeEndPoint = aEndPnt;
+    }
+  }
+  else if (theMethod == Method::USE_CURVE_INFORMATION()) {
+    // make all edges FORWARD to avoid reversing the curves by GeomAlgoAPI_Filling algorithm
+    anEdge->setOrientation(GeomAPI_Shape::FORWARD);
+  }
+  return anEdge;
+}
+
+//=================================================================================================
+void BuildPlugin_Filling::restoreDefaultParameters()
+{
+  string(METHOD_ID())->setValue(METHOD_DEFAULT());
+  integer(MINIMAL_DEGREE_ID())->setValue(MINIMAL_DEGREE_DEFAULT());
+  integer(MAXIMAL_DEGREE_ID())->setValue(MAXIMAL_DEGREE_DEFAULT());
+  integer(NUMBER_OF_ITERATIONS_ID())->setValue(NUMBER_OF_ITERATIONS_DEFAULT());
+  real(TOLERANCE_2D_ID())->setValue(TOLERANCE_2D_DEFAULT());
+  real(TOLERANCE_3D_ID())->setValue(TOLERANCE_3D_DEFAULT());
+  boolean(APPROXIMATION_ID())->setValue(APPROXIMATION_DEFAULT());
+}
diff --git a/src/BuildPlugin/BuildPlugin_Filling.h b/src/BuildPlugin/BuildPlugin_Filling.h
new file mode 100644 (file)
index 0000000..cb19f06
--- /dev/null
@@ -0,0 +1,182 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef BuildPlugin_Filling_H_
+#define BuildPlugin_Filling_H_
+
+#include "BuildPlugin.h"
+
+#include <ModelAPI_Feature.h>
+
+#include <memory>
+#include <string>
+
+class GeomAlgoAPI_MakeShape;
+class GeomAPI_Edge;
+class GeomAPI_Pnt;
+class GeomAPI_Shape;
+
+/// \class BuildPlugin_Filling
+/// \ingroup Plugins
+/// \brief Feature for creation of face from list of edges (1D objects).
+class BuildPlugin_Filling: public ModelAPI_Feature
+{
+public:
+  /// Use plugin manager for features creation
+  BuildPlugin_Filling();
+
+  /// Feature kind.
+  inline static const std::string& ID()
+  {
+    static const std::string MY_ID("Filling");
+    return MY_ID;
+  }
+
+  /// \return the kind of a feature.
+  BUILDPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = BuildPlugin_Filling::ID();
+    return MY_KIND;
+  }
+
+  /// Attribute name of base objects.
+  inline static const std::string& BASE_OBJECTS_ID()
+  {
+    static const std::string MY_BASE_OBJECTS_ID("base_objects");
+    return MY_BASE_OBJECTS_ID;
+  }
+
+  /// Attribute name of advanced options.
+  inline static const std::string& ADVANCED_OPTIONS_ID()
+  {
+    static const std::string MY_ADVANCED_OPTIONS_ID("advanced_options");
+    return MY_ADVANCED_OPTIONS_ID;
+  }
+
+  /// Attribute name of method of edge orientation.
+  inline static const std::string& METHOD_ID()
+  {
+    static const std::string MY_METHOD_ID("orientation");
+    return MY_METHOD_ID;
+  }
+
+  /// Supported methods for edge orientation correction
+  struct Method {
+    inline static const std::string& AUTO_CORRECT_ORIENTATION()
+    {
+      static const std::string MY_AUTO_CORRECT_ORIENTATION("auto_correct");
+      return MY_AUTO_CORRECT_ORIENTATION;
+    }
+    inline static const std::string& USE_CURVE_INFORMATION()
+    {
+      static const std::string MY_USE_CURVE_INFORMATION("curve_info");
+      return MY_USE_CURVE_INFORMATION;
+    }
+    inline static const std::string& USE_EDGES_ORIENTATION()
+    {
+      static const std::string MY_USE_EDGES_ORIENTATION("edge_orient");
+      return MY_USE_EDGES_ORIENTATION;
+    }
+  };
+
+  /// Attribute name of minimal degree.
+  inline static const std::string& MINIMAL_DEGREE_ID()
+  {
+    static const std::string MY_MINIMAL_DEGREE_ID("min_degree");
+    return MY_MINIMAL_DEGREE_ID;
+  }
+
+  /// Attribute name of maximal degree.
+  inline static const std::string& MAXIMAL_DEGREE_ID()
+  {
+    static const std::string MY_MAXIMAL_DEGREE_ID("max_degree");
+    return MY_MAXIMAL_DEGREE_ID;
+  }
+
+  /// Attribute name of number of iterations.
+  inline static const std::string& NUMBER_OF_ITERATIONS_ID()
+  {
+    static const std::string MY_NUMBER_OF_ITERATIONS_ID("nb_iter");
+    return MY_NUMBER_OF_ITERATIONS_ID;
+  }
+
+  /// Attribute name of 2D tolerance.
+  inline static const std::string& TOLERANCE_2D_ID()
+  {
+    static const std::string MY_TOLERANCE_2D_ID("tol_2d");
+    return MY_TOLERANCE_2D_ID;
+  }
+
+  /// Attribute name of 3D tolerance.
+  inline static const std::string& TOLERANCE_3D_ID()
+  {
+    static const std::string MY_TOLERANCE_3D_ID("tol_3d");
+    return MY_TOLERANCE_3D_ID;
+  }
+
+  /// Attribute name of approximation.
+  inline static const std::string& APPROXIMATION_ID()
+  {
+    static const std::string MY_APPROXIMATION_ID("approximation");
+    return MY_APPROXIMATION_ID;
+  }
+
+  /// Default value of the orientation
+  inline static const std::string& METHOD_DEFAULT() { return Method::AUTO_CORRECT_ORIENTATION(); }
+  /// Default value of minimal degree
+  inline static int MINIMAL_DEGREE_DEFAULT() { return 2; }
+  /// Default value of maximal degree
+  inline static int MAXIMAL_DEGREE_DEFAULT() { return 5; }
+  /// Default value of number of iterations
+  inline static int NUMBER_OF_ITERATIONS_DEFAULT() { return 0; }
+  /// Default value of 2D tolerance
+  inline static double TOLERANCE_2D_DEFAULT() { return 1.e-4; }
+  /// Default value of 3D tolerance
+  inline static double TOLERANCE_3D_DEFAULT() { return 1.e-4; }
+  /// Default value of the approximation attribute
+  inline static bool APPROXIMATION_DEFAULT() { return false; }
+
+  /// Request for initialization of data model of the feature: adding all attributes.
+  BUILDPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Creates a new part document if needed.
+  BUILDPLUGIN_EXPORT virtual void execute();
+
+  /// Called on change of any argument-attribute of this object.
+  /// \param[in] theID identifier of changed attribute.
+  BUILDPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+private:
+  /// Check the filling algorithm is failed
+  bool isAlgorithmFailed(const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgorithm);
+
+  /// Convert shape to edge according to construction method
+  std::shared_ptr<GeomAPI_Edge> toEdge(const std::shared_ptr<GeomAPI_Shape>& theShape,
+                                       const std::string& theMethod);
+
+  /// Update values of attributes by their default values
+  void restoreDefaultParameters();
+
+private:
+  std::shared_ptr<GeomAPI_Pnt> myLastEdgeStartPoint;
+  std::shared_ptr<GeomAPI_Pnt> myLastEdgeEndPoint;
+};
+
+#endif
index 8849b519ab7156dd87d467ad107f073a8e62327f..7915c14479ce4a13a0658632ff3882e8e557fe5d 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 #include <BuildPlugin_Wire.h>
 #include <BuildPlugin_Face.h>
 #include <BuildPlugin_Shell.h>
+#include <BuildPlugin_Solid.h>
+#include <BuildPlugin_CompSolid.h>
+#include <BuildPlugin_Compound.h>
 #include <BuildPlugin_SubShapes.h>
+#include <BuildPlugin_Filling.h>
 #include <BuildPlugin_Validators.h>
 
 // the only created instance of this plugin
@@ -48,6 +52,8 @@ BuildPlugin_Plugin::BuildPlugin_Plugin()
                               new BuildPlugin_ValidatorBaseForFace());
   aFactory->registerValidator("BuildPlugin_ValidatorSubShapesSelection",
                               new BuildPlugin_ValidatorSubShapesSelection());
+  aFactory->registerValidator("BuildPlugin_ValidatorFillingSelection",
+                              new BuildPlugin_ValidatorFillingSelection());
 
   // Register this plugin.
   ModelAPI_Session::get()->registerPlugin(this);
@@ -66,8 +72,16 @@ FeaturePtr BuildPlugin_Plugin::createFeature(std::string theFeatureID)
     return FeaturePtr(new BuildPlugin_Face());
   } else if(theFeatureID == BuildPlugin_Shell::ID()) {
     return FeaturePtr(new BuildPlugin_Shell());
+  } else if(theFeatureID == BuildPlugin_Solid::ID()) {
+    return FeaturePtr(new BuildPlugin_Solid());
+  } else if(theFeatureID == BuildPlugin_CompSolid::ID()) {
+    return FeaturePtr(new BuildPlugin_CompSolid());
+  } else if(theFeatureID == BuildPlugin_Compound::ID()) {
+    return FeaturePtr(new BuildPlugin_Compound());
   } else if(theFeatureID == BuildPlugin_SubShapes::ID()) {
     return FeaturePtr(new BuildPlugin_SubShapes());
+  } else if(theFeatureID == BuildPlugin_Filling::ID()) {
+    return FeaturePtr(new BuildPlugin_Filling());
   }
 
   // Feature of such kind is not found.
diff --git a/src/BuildPlugin/BuildPlugin_Solid.cpp b/src/BuildPlugin/BuildPlugin_Solid.cpp
new file mode 100644 (file)
index 0000000..1066c3f
--- /dev/null
@@ -0,0 +1,155 @@
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "BuildPlugin_Solid.h"
+
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_ResultBody.h>
+
+#include <GeomAPI_ShapeIterator.h>
+
+#include <GeomAlgoAPI_MakeVolume.h>
+
+//=================================================================================================
+BuildPlugin_Solid::BuildPlugin_Solid()
+{
+}
+
+//=================================================================================================
+void BuildPlugin_Solid::initAttributes()
+{
+  data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
+}
+
+//=================================================================================================
+void BuildPlugin_Solid::execute()
+{
+  ListOfShape anOriginalShapes;
+  std::shared_ptr<GeomAlgoAPI_MakeShape> aVolumeMaker;
+  if (!build(anOriginalShapes, aVolumeMaker))
+    return;
+
+  // check and process result of volume maker
+  GeomShapePtr aResShape = getSingleSubshape(aVolumeMaker->shape(), GeomAPI_Shape::SOLID);
+  int anIndex = 0;
+  if (aResShape) {
+    storeResult(anOriginalShapes, aResShape, aVolumeMaker);
+    ++anIndex;
+  }
+  removeResults(anIndex);
+}
+
+//=================================================================================================
+bool BuildPlugin_Solid::build(ListOfShape& theOriginalShapes,
+                              std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgorithm)
+{
+  // Get base objects list.
+  AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
+  if (!aSelectionList.get()) {
+    setError("Error: Could not get selection list.");
+    return false;
+  }
+  if (aSelectionList->size() == 0) {
+    setError("Error: Empty selection list.");
+    return false;
+  }
+
+  // Collect base shapes.
+  for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
+    AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
+    GeomShapePtr aShape = aSelection->value();
+    if (!aShape.get())
+      aShape = aSelection->context()->shape();
+    theOriginalShapes.push_back(aShape);
+  }
+
+  theAlgorithm =
+      std::shared_ptr<GeomAlgoAPI_MakeVolume>(new GeomAlgoAPI_MakeVolume(theOriginalShapes));
+  return !isAlgorithmFailed(theAlgorithm);
+}
+
+void BuildPlugin_Solid::storeResult(const ListOfShape& theOriginalShapes,
+                                    const GeomShapePtr& theResultShape,
+                                    const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgorithm)
+{
+  ResultBodyPtr aResultBody = document()->createBody(data());
+  aResultBody->store(theResultShape);
+
+  // Store faces
+  std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubs = theAlgorithm->mapOfSubShapes();
+  int aModifiedTag = 1;
+  for(ListOfShape::const_iterator anIt = theOriginalShapes.cbegin();
+      anIt != theOriginalShapes.cend(); ++anIt) {
+    GeomShapePtr aShape = *anIt;
+    aResultBody->loadAndOrientModifiedShapes(theAlgorithm.get(), aShape, GeomAPI_Shape::FACE,
+        aModifiedTag, "Modified_Face", *aMapOfSubs.get(), false, true, true);
+  }
+
+  setResult(aResultBody);
+}
+
+GeomShapePtr BuildPlugin_Solid::getSingleSubshape(const GeomShapePtr& theCompound,
+                                                  const GeomAPI_Shape::ShapeType theShapeType)
+{
+  if (theCompound->shapeType() == theShapeType)
+    return theCompound;
+  else if (theCompound->shapeType() == GeomAPI_Shape::COMPOUND) {
+    GeomAPI_ShapeIterator anIt(theCompound);
+    GeomShapePtr aFoundSub;
+    for (; anIt.more() && !aFoundSub; anIt.next()) {
+      aFoundSub = anIt.current();
+      if (aFoundSub->shapeType() != theShapeType)
+        return GeomShapePtr(); // not alone sub-shape
+    }
+    if (anIt.more()) {
+      std::string anError = "Error: unable to build a ";
+      switch (theShapeType) {
+      case GeomAPI_Shape::SOLID: anError += "solid"; break;
+      case GeomAPI_Shape::COMPSOLID: anError += "compsolid"; break;
+      default: anError += "subshape"; break;
+      }
+      setError(anError);
+    } else
+      return aFoundSub;
+  }
+  // not a solid
+  return GeomShapePtr();
+}
+
+bool BuildPlugin_Solid::isAlgorithmFailed(
+    const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgorithm)
+{
+  if (!theAlgorithm->isDone()) {
+    static const std::string aFeatureError = "Error: MakeVolume algorithm failed.";
+    setError(aFeatureError);
+    return true;
+  }
+  if (theAlgorithm->shape()->isNull()) {
+    static const std::string aShapeError = "Error: Resulting shape of MakeVolume is Null.";
+    setError(aShapeError);
+    return true;
+  }
+  if (!theAlgorithm->isValid()) {
+    std::string aFeatureError = "Error: Resulting shape of MakeVolume is not valid.";
+    setError(aFeatureError);
+    return true;
+  }
+  return false;
+}
diff --git a/src/BuildPlugin/BuildPlugin_Solid.h b/src/BuildPlugin/BuildPlugin_Solid.h
new file mode 100644 (file)
index 0000000..549ee49
--- /dev/null
@@ -0,0 +1,88 @@
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef BuildPlugin_Solid_H_
+#define BuildPlugin_Solid_H_
+
+#include "BuildPlugin.h"
+
+#include <GeomAPI_Shape.h>
+#include <ModelAPI_Feature.h>
+
+class GeomAlgoAPI_MakeShape;
+
+/// \class BuildPlugin_Solid
+/// \ingroup Plugins
+/// \brief Feature for creation of solid from faces or shells.
+class BuildPlugin_Solid: public ModelAPI_Feature
+{
+public:
+  /// Use plugin manager for features creation
+  BuildPlugin_Solid();
+
+  /// Feature kind.
+  inline static const std::string& ID()
+  {
+    static const std::string MY_ID("Solid");
+    return MY_ID;
+  }
+
+  /// Attribute name of base objects.
+  inline static const std::string& BASE_OBJECTS_ID()
+  {
+    static const std::string MY_BASE_OBJECTS_ID("base_objects");
+    return MY_BASE_OBJECTS_ID;
+  }
+
+  /// \return the kind of a feature.
+  BUILDPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = BuildPlugin_Solid::ID();
+    return MY_KIND;
+  }
+
+  /// Request for initialization of data model of the feature: adding all attributes.
+  BUILDPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Creates a new part document if needed.
+  BUILDPLUGIN_EXPORT virtual void execute();
+
+protected:
+  /// Build result
+  /// \param[out] theOriginalShapes list of original shapes
+  /// \param[out] theAlgorithm      algorithm to build result
+  /// \return \c true if algorithm finished without errors
+  bool build(ListOfShape& theOriginalShapes, std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgorithm);
+
+  /// Store result of algorithm
+  void storeResult(const ListOfShape& theOriginalShapes,
+                   const GeomShapePtr& theResultShape,
+                   const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgorithm);
+
+  /// Check the algorithm is failed
+  bool isAlgorithmFailed(const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgorithm);
+
+  /// Explode compound to get single shape of specified type
+  /// \return Empty shape if there is more than one shape in compound
+  GeomShapePtr getSingleSubshape(const GeomShapePtr& theCompound,
+                                 const GeomAPI_Shape::ShapeType theShapeType);
+};
+
+#endif
index 244ddb6e4f7ae9d0ed8ee89500e2c8e8b6c2b8a5..833536d400a170fd6f1d89cc6b12cab67d8e8baa 100644 (file)
@@ -112,12 +112,6 @@ bool BuildPlugin_ValidatorBaseForBuild::isValid(const AttributePtr& theAttribute
         continue;
       }
     }
-
-    if(!aShape->isEqual(aContextShape)) {
-      // Local selection on body does not allowed.
-      theError = "Selected shape is in the local selection. Only global selection is allowed.";
-      return false;
-    }
   }
 
   return true;
@@ -192,6 +186,9 @@ bool BuildPlugin_ValidatorBaseForFace::isValid(const std::shared_ptr<ModelAPI_Fe
     return false;
   }
 
+  bool hasEdgesOrWires = false;
+  bool hasFaces = false;
+
   // Collect base shapes.
   ListOfShape anEdges;
   for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
@@ -204,13 +201,23 @@ bool BuildPlugin_ValidatorBaseForFace::isValid(const std::shared_ptr<ModelAPI_Fe
       }
       aShape = aSelection->context()->shape();
     }
+    if (aShape->shapeType() == GeomAPI_Shape::FACE) {
+      // skip faces exploding
+      hasFaces = true;
+      continue;
+    }
+
     for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
+      hasEdgesOrWires = true;
       GeomShapePtr anEdge = anExp.current();
       anEdges.push_back(anEdge);
     }
   }
 
-  if(anEdges.empty()) {
+  if (hasFaces && hasEdgesOrWires) {
+    theError = "Faces and edges/wires should be selected together.";
+    return false;
+  } else if (hasEdgesOrWires && anEdges.empty()) {
     theError = "Objects are not selected.";
     return false;
   }
@@ -235,20 +242,22 @@ bool BuildPlugin_ValidatorBaseForFace::isValid(const std::shared_ptr<ModelAPI_Fe
     }
   }
 
-  // Check that they are planar.
-  std::shared_ptr<GeomAPI_Pln> aPln = GeomAlgoAPI_ShapeTools::findPlane(anEdges);
-  if(!aPln.get()) {
-    theError = "Selected object(s) should belong to only one plane.";
-    return false;
-  }
+  if (!anEdges.empty()) {
+    // Check that they are planar.
+    std::shared_ptr<GeomAPI_Pln> aPln = GeomAlgoAPI_ShapeTools::findPlane(anEdges);
+    if(!aPln.get()) {
+      theError = "Selected object(s) should belong to only one plane.";
+      return false;
+    }
 
-  // Check that selected objects have closed contours.
-  ListOfShape aFaces;
-  GeomAlgoAPI_SketchBuilder::createFaces(aPln->location(), aPln->xDirection(),
-                                         aPln->direction(), anEdges, aFaces);
-  if(aFaces.empty()) {
-    theError = "Selected objects do not generate closed contour.";
-    return false;
+    // Check that selected objects have closed contours.
+    ListOfShape aFaces;
+    GeomAlgoAPI_SketchBuilder::createFaces(aPln->location(), aPln->xDirection(),
+                                           aPln->direction(), anEdges, aFaces);
+    if(aFaces.empty()) {
+      theError = "Selected objects do not generate closed contour.";
+      return false;
+    }
   }
 
   return true;
@@ -359,3 +368,53 @@ bool BuildPlugin_ValidatorSubShapesSelection::isValid(const AttributePtr& theAtt
 
   return true;
 }
+
+
+//=================================================================================================
+bool BuildPlugin_ValidatorFillingSelection::isValid(const AttributePtr& theAttribute,
+                                                      const std::list<std::string>& theArguments,
+                                                      Events_InfoMessage& theError) const
+{
+  // Get base objects list.
+  if (theAttribute->attributeType() != ModelAPI_AttributeSelectionList::typeId()) {
+    std::string aMsg =
+      "Error: BuildPlugin_ValidatorFillingSelection does not support attribute type \""
+      "%1\"\n Only \"%2\" supported.";
+    Events_InfoMessage("BuildPlugin_Validators", aMsg).
+      arg(theAttribute->attributeType()).arg(ModelAPI_AttributeSelectionList::typeId()).send();
+    return false;
+  }
+  AttributeSelectionListPtr aSelectionList =
+    std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+  if (!aSelectionList.get()) {
+    theError = "Could not get selection list.";
+    return false;
+  }
+
+  FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
+
+  // Check selected shapes.
+  for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
+    AttributeSelectionPtr aSelectionAttrInList = aSelectionList->value(anIndex);
+    if (!aSelectionAttrInList.get()) {
+      theError = "Empty attribute in list.";
+      return false;
+    }
+
+    // Check shape exists.
+    GeomShapePtr aShapeInList = aSelectionAttrInList->value();
+    if (!aShapeInList.get()) {
+      theError = "Object has no shape";
+      return false;
+    }
+
+    // Check shape type.
+    GeomAPI_Shape::ShapeType aType = aShapeInList->shapeType();
+    if (aType != GeomAPI_Shape::EDGE && aType != GeomAPI_Shape::WIRE) {
+      theError = "Incorrect objects selected";
+      return false;
+    }
+  }
+
+  return true;
+}
index 522e3bb8361b470b1998d456c6e2df8b47b3673a..5f3be35daf884d20edcc659bfd054f3c2eca5dcd 100644 (file)
@@ -94,4 +94,19 @@ public:
                         Events_InfoMessage& theError) const;
 };
 
+/// \class BuildPlugin_ValidatorFillingSelection
+/// \ingroup Validators
+/// \brief A validator for selection of Filling feature.
+class BuildPlugin_ValidatorFillingSelection: public ModelAPI_AttributeValidator
+{
+public:
+  //! 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
index 9331922f701be1acfbbf302788d79d14d7370882..61497aa7c263af7709f0628dc3e52cad903c2a79 100644 (file)
@@ -37,7 +37,11 @@ SET(PROJECT_HEADERS
     BuildPlugin_Wire.h
     BuildPlugin_Face.h
     BuildPlugin_Shell.h
+    BuildPlugin_Solid.h
+    BuildPlugin_CompSolid.h
+    BuildPlugin_Compound.h
     BuildPlugin_SubShapes.h
+    BuildPlugin_Filling.h
     BuildPlugin_Validators.h
 )
 
@@ -48,7 +52,11 @@ SET(PROJECT_SOURCES
     BuildPlugin_Wire.cpp
     BuildPlugin_Face.cpp
     BuildPlugin_Shell.cpp
+    BuildPlugin_Solid.cpp
+    BuildPlugin_CompSolid.cpp
+    BuildPlugin_Compound.cpp
     BuildPlugin_SubShapes.cpp
+    BuildPlugin_Filling.cpp
     BuildPlugin_Validators.cpp
 )
 
@@ -59,7 +67,11 @@ SET(XML_RESOURCES
     wire_widget.xml
     face_widget.xml
     shell_widget.xml
+    solid_widget.xml
+    compsolid_widget.xml
+    compound_widget.xml
     subshapes_widget.xml
+    filling_widget.xml
 )
 
 SET(TEXT_RESOURCES
@@ -91,5 +103,11 @@ ADD_UNIT_TESTS(TestVertex.py
                TestWire.py
                TestFace.py
                TestShell.py
+               TestSolid.py
+               TestCompSolid.py
+               TestCompound.py
                TestSubShapes.py
+               TestFilling_ByEdges.py
+               TestFilling_ByWires.py
+               TestFilling_Mixed.py
                Test1920.py)
index 18323fefdf77d5535daee768ffe96f5491d44009..96f8eb6dcbb80fe919a7336f71c594deef7630e2 100644 (file)
@@ -44,7 +44,7 @@ model.do()
 Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_1r-SketchLine_3r-SketchLine_4r-SketchLine_5r")])
 Face_2 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_5f")])
 Translation_1 = model.addTranslation(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("FACE", "Face_2_1")], model.selection("EDGE", "PartSet/OY"), 100)
-Group_1 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Face_1_1/Translated_Edge_1"), model.selection("EDGE", "Face_1_1/Translated_Edge_2"), model.selection("EDGE", "Face_1_1/Translated_Edge_3"), model.selection("EDGE", "Face_1_1/Translated_Edge_4"), model.selection("EDGE", "Face_2_1/Translated_Edge_1"), model.selection("EDGE", "Face_2_1/Translated_Edge_2"), model.selection("EDGE", "Face_2_1/Translated_Edge_3"), model.selection("EDGE", "Face_2_1/Translated_Edge_4")])
+Group_1 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Translation_1_1/Translated_Edge_1"), model.selection("EDGE", "Translation_1_1/Translated_Edge_2"), model.selection("EDGE", "Translation_1_1/Translated_Edge_3"), model.selection("EDGE", "Translation_1_1/Translated_Edge_4"), model.selection("EDGE", "Translation_1_2/Translated_Edge_1"), model.selection("EDGE", "Translation_1_2/Translated_Edge_2"), model.selection("EDGE", "Translation_1_2/Translated_Edge_3"), model.selection("EDGE", "Translation_1_2/Translated_Edge_4")])
 aGroupFeature = Group_1.feature()
 aSelectionList = aGroupFeature.selectionList("group_list")
 model.end()
diff --git a/src/BuildPlugin/Test/TestCompSolid.py b/src/BuildPlugin/Test/TestCompSolid.py
new file mode 100644 (file)
index 0000000..824358d
--- /dev/null
@@ -0,0 +1,186 @@
+## Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+from SketchAPI import *
+from GeomAPI import GeomAPI_Shape
+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(40, 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, 0, 0, 40)
+SketchLine_3 = Sketch_1.addLine(0, 40, 40, 40)
+SketchLine_4 = Sketch_1.addLine(40, 40, 40, 0)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_2.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 40)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r")])
+Sketch_2 = model.addSketch(Part_1_doc, model.standardPlane("YOZ"))
+SketchLine_5 = Sketch_2.addLine(20, 0, 0, 0)
+SketchLine_6 = Sketch_2.addLine(0, 0, 0, 20)
+SketchLine_7 = Sketch_2.addLine(0, 20, 20, 20)
+SketchLine_8 = Sketch_2.addLine(20, 20, 20, 0)
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_6.result())
+SketchConstraintHorizontal_4 = Sketch_2.setHorizontal(SketchLine_7.result())
+SketchConstraintVertical_4 = Sketch_2.setVertical(SketchLine_8.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), False)
+SketchLine_9 = SketchProjection_2.createdFeature()
+SketchConstraintMiddle_1 = Sketch_2.setMiddlePoint(SketchLine_5.startPoint(), SketchLine_9.result())
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchAPI_Line(SketchLine_9).startPoint(), SketchLine_5.endPoint())
+SketchConstraintEqual_2 = Sketch_2.setEqual(SketchLine_5.result(), SketchLine_6.result())
+SketchLine_10 = Sketch_2.addLine(20, 20, 20, 40)
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_10.startPoint())
+SketchLine_11 = Sketch_2.addLine(20, 40, 0, 40)
+SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint())
+SketchLine_12 = Sketch_2.addLine(0, 40, 0, 20)
+SketchConstraintCoincidence_13 = Sketch_2.setCoincident(SketchLine_11.endPoint(), SketchLine_12.startPoint())
+SketchConstraintCoincidence_14 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_12.endPoint())
+SketchConstraintVertical_5 = Sketch_2.setVertical(SketchLine_10.result())
+SketchConstraintHorizontal_5 = Sketch_2.setHorizontal(SketchLine_11.result())
+SketchConstraintVertical_6 = Sketch_2.setVertical(SketchLine_12.result())
+SketchConstraintEqual_3 = Sketch_2.setEqual(SketchLine_6.result(), SketchLine_12.result())
+model.do()
+Face_2 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchLine_5r-SketchLine_6r-SketchLine_7r-SketchLine_8r")])
+AngularCopy_1 = model.addMultiRotation(Part_1_doc, [model.selection("FACE", "Face_2_1")], model.selection("EDGE", "PartSet/OZ"), 270, 2)
+Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "AngularCopy_1_1_1"), model.selection("FACE", "AngularCopy_1_1_2")])
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_7f-SketchLine_10f-SketchLine_11f-SketchLine_12f")], model.selection(), 40, 0)
+Sketch_3 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_13 = Sketch_3.addLine(40, 0, 20, 0)
+SketchLine_14 = Sketch_3.addLine(20, 0, 20, 40)
+SketchLine_15 = Sketch_3.addLine(20, 40, 40, 40)
+SketchLine_16 = Sketch_3.addLine(40, 40, 40, 0)
+SketchConstraintCoincidence_15 = Sketch_3.setCoincident(SketchLine_16.endPoint(), SketchLine_13.startPoint())
+SketchConstraintCoincidence_16 = Sketch_3.setCoincident(SketchLine_13.endPoint(), SketchLine_14.startPoint())
+SketchConstraintCoincidence_17 = Sketch_3.setCoincident(SketchLine_14.endPoint(), SketchLine_15.startPoint())
+SketchConstraintCoincidence_18 = Sketch_3.setCoincident(SketchLine_15.endPoint(), SketchLine_16.startPoint())
+SketchConstraintHorizontal_6 = Sketch_3.setHorizontal(SketchLine_13.result())
+SketchConstraintVertical_7 = Sketch_3.setVertical(SketchLine_14.result())
+SketchConstraintHorizontal_7 = Sketch_3.setHorizontal(SketchLine_15.result())
+SketchConstraintVertical_8 = Sketch_3.setVertical(SketchLine_16.result())
+SketchProjection_3 = Sketch_3.addProjection(model.selection("VERTEX", "Sketch_2/Vertex-SketchLine_5s-SketchLine_15s-SketchLine_8e-SketchLine_14e"), False)
+SketchPoint_2 = SketchProjection_3.createdFeature()
+SketchConstraintCoincidence_19 = Sketch_3.setCoincident(SketchLine_13.endPoint(), SketchAPI_Point(SketchPoint_2).coordinates())
+SketchProjection_4 = Sketch_3.addProjection(model.selection("VERTEX", "Sketch_2/Vertex-SketchLine_11s-SketchLine_10e"), False)
+SketchPoint_3 = SketchProjection_4.createdFeature()
+SketchConstraintCoincidence_20 = Sketch_3.setCoincident(SketchLine_14.endPoint(), SketchAPI_Point(SketchPoint_3).coordinates())
+SketchProjection_5 = Sketch_3.addProjection(model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_3s-SketchLine_2e"), False)
+SketchPoint_4 = SketchProjection_5.createdFeature()
+SketchConstraintCoincidence_21 = Sketch_3.setCoincident(SketchLine_13.startPoint(), SketchAPI_Point(SketchPoint_4).coordinates())
+model.do()
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_13r-SketchLine_14r-SketchLine_15r-SketchLine_16r")], model.selection(), 20, 0)
+Box_1 = model.addBox(Part_1_doc, 20, 20, 20)
+model.do()
+
+def createCompSolidStepByStep(theSelection, theExpectedType):
+    CompSolid = model.addCompSolid(Part_1_doc, [theSelection[0]])
+    aList = []
+    for selection, expected in zip(theSelection, theExpectedType):
+        aList.append(selection)
+        CompSolid.setBase(aList)
+        if expected == GeomAPI_Shape.SHAPE:
+            assert(len(CompSolid.results()) == 0), "FAILED: CompSolid should not be built"
+        else:
+            assert(len(CompSolid.results()) > 0), "FAILED: CompSolid is not built"
+            resultType = CompSolid.results()[0].resultSubShapePair()[0].shape().shapeType()
+            assert(resultType == expected), "FAILED: Result has unexpected type"
+    # remove solid if it is not built
+    if len(CompSolid.results()) == 0:
+        Part_1_doc.removeFeature(CompSolid.feature())
+        return None
+    return CompSolid
+
+# =============================================================================
+# Test 1. Build compsolid cointaining 2 solids
+# =============================================================================
+boundaries1 = [model.selection("FACE", "Face_1_1"),
+               model.selection("SHELL", "Shell_1_1"),
+               model.selection("FACE", "Sketch_3/Face-SketchLine_13r-SketchLine_14r-SketchLine_15r-SketchLine_16r"),
+               model.selection("FACE", "Extrusion_1_1/Generated_Face_4"),
+               model.selection("FACE", "Extrusion_2_1/Generated_Face_2"),
+               model.selection("FACE", "Extrusion_2_1/Generated_Face_3"),
+               model.selection("FACE", "Extrusion_2_1/Generated_Face_4"),
+               model.selection("FACE", "Extrusion_2_1/To_Face_1"),
+               model.selection("FACE", "Box_1_1/Front")]
+expectType1 = [GeomAPI_Shape.SHAPE,
+               GeomAPI_Shape.SHAPE,
+               GeomAPI_Shape.SHAPE,
+               GeomAPI_Shape.SHAPE,
+               GeomAPI_Shape.SHAPE,
+               GeomAPI_Shape.SHAPE,
+               GeomAPI_Shape.SHAPE,
+               GeomAPI_Shape.SOLID,
+               GeomAPI_Shape.COMPSOLID]
+CompSolid_1 = createCompSolidStepByStep(boundaries1, expectType1)
+
+model.checkBooleansResult(CompSolid_1, model, 1, [2], [2], [13], [54], [108])
+model.testHaveNamingSubshapes(CompSolid_1, model, Part_1_doc)
+
+# =============================================================================
+# Test 2. Build compsolid containing 3 solids
+# =============================================================================
+boundaries2 = [model.selection("FACE", "Face_1_1"),
+               model.selection("SHELL", "Shell_1_1"),
+               model.selection("FACE", "Sketch_3/Face-SketchLine_13r-SketchLine_14r-SketchLine_15r-SketchLine_16r"),
+               model.selection("FACE", "Extrusion_1_1/Generated_Face_4"),
+               model.selection("FACE", "Extrusion_1_1/Generated_Face_3"),
+               model.selection("FACE", "Extrusion_2_1/Generated_Face_3"),
+               model.selection("FACE", "Extrusion_2_1/Generated_Face_4"),
+               model.selection("FACE", "Extrusion_2_1/To_Face_1"),
+               model.selection("FACE", "Box_1_1/Front"),
+               model.selection("FACE", "Extrusion_2_1/Generated_Face_2"),
+               model.selection("SOLID", "Extrusion_1_1")]
+expectType2 = [GeomAPI_Shape.SHAPE,
+               GeomAPI_Shape.SHAPE,
+               GeomAPI_Shape.SHAPE,
+               GeomAPI_Shape.SHAPE,
+               GeomAPI_Shape.SHAPE,
+               GeomAPI_Shape.SHAPE,
+               GeomAPI_Shape.SHAPE,
+               GeomAPI_Shape.SHAPE,
+               GeomAPI_Shape.SOLID,
+               GeomAPI_Shape.COMPSOLID,
+               GeomAPI_Shape.COMPSOLID]
+CompSolid_2 = createCompSolidStepByStep(boundaries2, expectType2)
+
+model.checkBooleansResult(CompSolid_2, model, 1, [3], [3], [21], [88], [176])
+model.testHaveNamingSubshapes(CompSolid_2, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/BuildPlugin/Test/TestCompound.py b/src/BuildPlugin/Test/TestCompound.py
new file mode 100644 (file)
index 0000000..6a25a8e
--- /dev/null
@@ -0,0 +1,91 @@
+## Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+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(-19.49406233194174, -69.37451616542793, -72.71146724766345, -69.37451616542793)
+SketchLine_2 = Sketch_1.addLine(-72.71146724766345, -69.37451616542793, -72.71146724766345, -28.67067780808921)
+SketchLine_3 = Sketch_1.addLine(-72.71146724766345, -28.67067780808921, -19.49406233194174, -28.67067780808921)
+SketchLine_4 = Sketch_1.addLine(-19.49406233194174, -28.67067780808921, -19.49406233194174, -69.37451616542793)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchLine_5 = Sketch_1.addLine(16.67888107989752, -75.92151145213565, 19.40636912075787, -34.81908596556777)
+SketchPoint_1 = Sketch_1.addPoint(0.6128545881206371, -78.63973361497078)
+SketchCircle_1 = Sketch_1.addCircle(51.0302184611028, -58.25492948210744, 14.6764214847306)
+SketchCircle_2 = Sketch_1.addCircle(57.27434431552349, -55.3477547099222, 30.40870102508203)
+model.do()
+Vertex_1 = model.addVertex(Part_1_doc, [model.selection("VERTEX", "PartSet/Origin")])
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_5")])
+Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchCircle_2_2")])
+Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchCircle_1_2")])
+Sketch_2 = model.addSketch(Part_1_doc, model.standardPlane("YOZ"))
+SketchLine_6 = Sketch_2.addLine(73.69205241424749, 19.68979803478298, 29.86213888681927, 19.68979803478298)
+SketchLine_7 = Sketch_2.addLine(29.86213888681927, 19.68979803478298, 29.86213888681927, 46.16063196348271)
+SketchLine_8 = Sketch_2.addLine(29.86213888681927, 46.16063196348271, 73.69205241424749, 46.16063196348271)
+SketchLine_9 = Sketch_2.addLine(73.69205241424749, 46.16063196348271, 73.69205241424749, 19.68979803478298)
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_9.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_6.result())
+SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_7.result())
+SketchConstraintHorizontal_4 = Sketch_2.setHorizontal(SketchLine_8.result())
+SketchConstraintVertical_4 = Sketch_2.setVertical(SketchLine_9.result())
+model.do()
+Face_2 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchLine_6r-SketchLine_7r-SketchLine_8r-SketchLine_9r")])
+AngularCopy_1 = model.addMultiRotation(Part_1_doc, [model.selection("FACE", "Face_2_1")], model.selection("EDGE", "Sketch_2/Edge-SketchLine_6"), 120, 2)
+Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "AngularCopy_1_1_1"), model.selection("FACE", "AngularCopy_1_1_2")])
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 50)
+Box_2 = model.addBox(Part_1_doc, 10, 10, 10)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_2_1/Front"), 5, True)
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_2_1"), model.selection("FACE", "Plane_1")])
+Compound_1_objects = [model.selection("VERTEX", "Sketch_1/Vertex-SketchPoint_1"),
+                      model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"),
+                      model.selection("WIRE", "Sketch_1/Wire-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r"),
+                      model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r"),
+                      model.selection("VERTEX", "Vertex_1_1"),
+                      model.selection("EDGE", "Edge_1_1"),
+                      model.selection("WIRE", "Wire_1_1"),
+                      model.selection("FACE", "Face_1_1"),
+                      model.selection("SHELL", "Shell_1_1"),
+                      model.selection("SOLID", "Translation_1_1"),
+                      model.selection("COMPSOLID", "Partition_1_1")]
+Compound_1 = model.addCompound(Part_1_doc, Compound_1_objects)
+model.do()
+
+model.checkBooleansResult(Compound_1, model, 1, [11], [3], [22], [92], [186])
+
+model.end()
+
+assert(model.checkPythonDump())
index 98f6b478ba8027ba8458d6b51106384be60fb4f1..c64cae8e0fd86c69e61589cdf106b0c1af1ae39d 100644 (file)
@@ -75,5 +75,41 @@ aSession.finishOperation()
 # Test results
 assert (len(anEdgeFeature.results()) == aNumOfLines)
 
+# Test edge building on edge of another result
+aSession.startOperation()
+aBox = aPart.addFeature("Box")
+aBox.string("CreationMethod").setValue("BoxByDimensions")
+aBox.real("dx").setValue(50)
+aBox.real("dy").setValue(50)
+aBox.real("dz").setValue(50)
+aSession.finishOperation()
+aBoxResult = aBox.firstResult()
+aBoxShape = aBoxResult.shape()
+
+# Create edges
+aSession.startOperation()
+anEdgeFeature2 = aPart.addFeature("Edge")
+aBaseObjectsList = anEdgeFeature2.selectionList("base_objects")
+aShapeExplorer = GeomAPI_ShapeExplorer(aBoxShape, GeomAPI_Shape.EDGE)
+aShapes = []
+while aShapeExplorer.more():
+    # keep unique shapes only
+    aCurrent = aShapeExplorer.current()
+    isNewShape = True
+    for s in aShapes:
+        if s.isSame(aCurrent):
+            isNewShape = False
+            break
+    if isNewShape:
+        aShapes.append(aCurrent)
+    aShapeExplorer.next()
+
+for s in aShapes:
+    aBaseObjectsList.append(aBoxResult, s)
+aSession.finishOperation()
+
+# Test results
+assert (len(anEdgeFeature2.results()) == 12)
+
 from salome.shaper import model
 assert(model.checkPythonDump())
index f486817034c1faaa7a08296a66b08884a528eb4c..a88618c8f22e06a4a8ae1a7952741094be2c58e3 100644 (file)
@@ -35,6 +35,10 @@ aSession.finishOperation()
 aPartResult = modelAPI_ResultPart(aPartFeature.firstResult())
 aPart = aPartResult.partDoc()
 
+# =============================================================================
+# Test 1. Create face from edges of sketch
+# =============================================================================
+
 # Create a sketch
 aSession.startOperation()
 aSketchFeature = featureToCompositeFeature(aPart.addFeature("Sketch"))
@@ -83,5 +87,59 @@ aSession.finishOperation()
 # Test results
 assert (len(aFaceFeature.results()) > 0)
 
+# =============================================================================
+# Test 2. Create face from edges of solid
+# =============================================================================
+
+# Cylinder
+aSession.startOperation()
+aCylinder = aPart.addFeature("Cylinder")
+aCylinder.string("CreationMethod").setValue("Cylinder")
+aCylinder.selection("base_point").selectSubShape("VERTEX", "PartSet/Origin")
+aCylinder.selection("axis").selectSubShape("EDGE", "PartSet/OZ")
+aCylinder.real("radius").setValue(5)
+aCylinder.real("height").setValue(10)
+aSession.finishOperation()
+aCylinderResult = aCylinder.firstResult()
+aCylinderShape = aCylinderResult.shape()
+
+# Create face
+aSession.startOperation()
+aFaceFeature2 = aPart.addFeature("Face")
+aBaseObjectsList = aFaceFeature2.selectionList("base_objects")
+aBaseObjectsList.append("Cylinder_1_1/Face_1&Cylinder_1_1/Face_2", "EDGE")
+aSession.finishOperation()
+assert (len(aFaceFeature2.results()) > 0)
+
+# =============================================================================
+# Test 3. Create face from face of solid
+# =============================================================================
+
+aSession.startOperation()
+aFaceFeature3 = aPart.addFeature("Face")
+aBaseObjectsList = aFaceFeature3.selectionList("base_objects")
+aBaseObjectsList.append("Cylinder_1_1/Face_1", "FACE")
+aSession.finishOperation()
+assert (len(aFaceFeature3.results()) > 0)
+
+# =============================================================================
+# Test 4. Verify error is reported if selection of face feature is mixed (edges and face)
+# =============================================================================
+
+aSession.startOperation()
+aFaceFeature4 = aPart.addFeature("Face")
+aBaseObjectsList = aFaceFeature4.selectionList("base_objects")
+aShapeExplorer = GeomAPI_ShapeExplorer(aSketchShape, GeomAPI_Shape.EDGE)
+while aShapeExplorer.more():
+    aBaseObjectsList.append(aSketchResult, aShapeExplorer.current())
+    aShapeExplorer.next()
+aBaseObjectsList.append("Cylinder_1_1/Face_3", "FACE")
+aSession.finishOperation()
+assert (len(aFaceFeature4.results()) == 0)
+# remove failed feature
+aSession.startOperation()
+aPart.removeFeature(aFaceFeature4)
+aSession.finishOperation()
+
 from salome.shaper import model
 assert(model.checkPythonDump())
diff --git a/src/BuildPlugin/Test/TestFilling_ByEdges.py b/src/BuildPlugin/Test/TestFilling_ByEdges.py
new file mode 100644 (file)
index 0000000..08b3aea
--- /dev/null
@@ -0,0 +1,153 @@
+## Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+# Initialization of the test
+from ModelAPI import *
+from GeomDataAPI import *
+from GeomAlgoAPI import *
+from GeomAPI import *
+
+# Get document
+aSession = ModelAPI_Session.get()
+aDocument = aSession.moduleDocument()
+
+# Create a part
+aSession.startOperation()
+aPartFeature = aDocument.addFeature("Part")
+aSession.finishOperation()
+aPartResult = modelAPI_ResultPart(aPartFeature.firstResult())
+aPart = aPartResult.partDoc()
+
+# Create first edge in a sketch
+aSession.startOperation()
+aSketch1 = featureToCompositeFeature(aPart.addFeature("Sketch"))
+anOrigin = geomDataAPI_Point(aSketch1.attribute("Origin"))
+anOrigin.setValue(0, 0, 0)
+aDirX = geomDataAPI_Dir(aSketch1.attribute("DirX"))
+aDirX.setValue(1, 0, 0)
+aNorm = geomDataAPI_Dir(aSketch1.attribute("Norm"))
+aNorm.setValue(0, 0, 1)
+# an arc
+anArc = aSketch1.addFeature("SketchArc")
+anArcCenter = geomDataAPI_Point2D(anArc.attribute("center_point"))
+anArcCenter.setValue(1, 1)
+anArcStartPoint = geomDataAPI_Point2D(anArc.attribute("start_point"))
+anArcStartPoint.setValue(20, 5)
+anArcEndPoint = geomDataAPI_Point2D(anArc.attribute("end_point"))
+anArcEndPoint.setValue(5, 20)
+aSession.finishOperation()
+aSketch1Result = aSketch1.firstResult()
+
+# Create second edge in another sketch
+aSession.startOperation()
+aSketch2 = featureToCompositeFeature(aPart.addFeature("Sketch"))
+anOrigin = geomDataAPI_Point(aSketch2.attribute("Origin"))
+anOrigin.setValue(0, 0, 0)
+aDirX = geomDataAPI_Dir(aSketch2.attribute("DirX"))
+aDirX.setValue(1, 0, 0)
+aNorm = geomDataAPI_Dir(aSketch2.attribute("Norm"))
+aNorm.setValue(0, 0.7071067811865475, 0.7071067811865475)
+# a line
+aLine = aSketch2.addFeature("SketchLine")
+aLineStartPoint = geomDataAPI_Point2D(aLine.attribute("StartPoint"))
+aLineStartPoint.setValue(0, 0)
+aLineEndPoint = geomDataAPI_Point2D(aLine.attribute("EndPoint"))
+aLineEndPoint.setValue(20, 20)
+aSession.finishOperation()
+aSketch2Result = aSketch2.firstResult()
+# an edge
+aSession.startOperation()
+anEdge = aPart.addFeature("Edge")
+aBaseObjectsList = anEdge.selectionList("base_objects")
+aBaseObjectsList.append(aSketch2Result, aLine.lastResult().shape())
+aSession.finishOperation()
+
+# Create filling
+aSession.startOperation()
+aFillingFeature = aPart.addFeature("Filling")
+aBaseObjectsList = aFillingFeature.selectionList("base_objects")
+aBaseObjectsList.append(aSketch1Result, anArc.lastResult().shape())
+aSession.finishOperation()
+
+# =============================================================================
+# Test 1. Filling on one edge is failed (no result is built)
+# =============================================================================
+assert(len(aFillingFeature.results()) == 0)
+
+# =============================================================================
+# Test 2. Add another edge, filling should be completed
+# =============================================================================
+aSession.startOperation()
+aBaseObjectsList.append(anEdge.lastResult(), None)
+aSession.finishOperation()
+assert(len(aFillingFeature.results()) > 0)
+
+# =============================================================================
+# Test 3. Change parameters one-by-one and check validity of result
+# =============================================================================
+aSession.startOperation()
+aFillingFeature.string("advanced_options").setValue("true")
+aSession.finishOperation()
+orientations = ["auto_correct", "curve_info", "edge_orient"]
+tolerances = [0.0001, 0.001]
+for ori in orientations:
+  for minDeg in range(2, 4):
+    for maxDeg in range(5, 7):
+      for nbIter in range(0, 3, 2):
+        for tol2d in tolerances:
+          for tol3d in tolerances:
+            for approx in [False, True]:
+              aSession.startOperation()
+              aFillingFeature.string("orientation").setValue(ori)
+              aFillingFeature.integer("min_degree").setValue(minDeg)
+              aFillingFeature.integer("max_degree").setValue(maxDeg)
+              aFillingFeature.integer("nb_iter").setValue(nbIter)
+              aFillingFeature.real("tol_2d").setValue(tol2d)
+              aFillingFeature.real("tol_3d").setValue(tol3d)
+              aFillingFeature.boolean("approximation").setValue(approx)
+              aSession.finishOperation()
+              assert(len(aFillingFeature.results()) > 0), "Filling feature failed with parameters:\n  orientation={}\n  min deg={}\n  max deg={}\n  nb iter={}\n  tol 2d={}\n  tol 3d={}\n  approximation={}".format(ori, minDeg, maxDeg, nbIter, tol2d, tol3d, approx)
+
+# =============================================================================
+# Test 4. Discard parameters to default and add one more edge
+# =============================================================================
+aSession.startOperation()
+aFillingFeature.string("advanced_options").setValue("")
+aSession.finishOperation()
+# new arc
+aSession.startOperation()
+anArc2 = aSketch1.addFeature("SketchArc")
+anArc2Center = geomDataAPI_Point2D(anArc2.attribute("center_point"))
+anArc2Center.setValue(0, -5)
+anArc2StartPoint = geomDataAPI_Point2D(anArc2.attribute("start_point"))
+anArc2StartPoint.setValue(-20, -5)
+anArc2EndPoint = geomDataAPI_Point2D(anArc2.attribute("end_point"))
+anArc2EndPoint.setValue(20, -5)
+aSession.finishOperation()
+aSketch1Result = aSketch1.firstResult()
+# update filling
+aSession.startOperation()
+aPart.setCurrentFeature(aFillingFeature, True)
+aBaseObjectsList.append(aSketch1Result, anArc2.lastResult().shape())
+aSession.finishOperation()
+assert(len(aFillingFeature.results()) > 0)
+
+from salome.shaper import model
+assert(model.checkPythonDump())
diff --git a/src/BuildPlugin/Test/TestFilling_ByWires.py b/src/BuildPlugin/Test/TestFilling_ByWires.py
new file mode 100644 (file)
index 0000000..1529a3c
--- /dev/null
@@ -0,0 +1,151 @@
+## Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+# Initialization of the test
+from ModelAPI import *
+from GeomDataAPI import *
+from GeomAlgoAPI import *
+from GeomAPI import *
+
+# Get document
+aSession = ModelAPI_Session.get()
+aDocument = aSession.moduleDocument()
+
+# Create a part
+aSession.startOperation()
+aPartFeature = aDocument.addFeature("Part")
+aSession.finishOperation()
+aPartResult = modelAPI_ResultPart(aPartFeature.firstResult())
+aPart = aPartResult.partDoc()
+
+# Create first wire in a sketch
+aSession.startOperation()
+aSketch1 = featureToCompositeFeature(aPart.addFeature("Sketch"))
+anOrigin = geomDataAPI_Point(aSketch1.attribute("Origin"))
+anOrigin.setValue(0, 0, 0)
+aDirX = geomDataAPI_Dir(aSketch1.attribute("DirX"))
+aDirX.setValue(1, 0, 0)
+aNorm = geomDataAPI_Dir(aSketch1.attribute("Norm"))
+aNorm.setValue(0, 0, 1)
+# arc 1
+anArc1 = aSketch1.addFeature("SketchArc")
+anArcCenter = geomDataAPI_Point2D(anArc1.attribute("center_point"))
+anArcCenter.setValue(1, 1)
+anArcStartPoint = geomDataAPI_Point2D(anArc1.attribute("start_point"))
+anArcStartPoint.setValue(20, 5)
+anArcEndPoint = geomDataAPI_Point2D(anArc1.attribute("end_point"))
+anArcEndPoint.setValue(5, 20)
+# arc 2
+anArc2 = aSketch1.addFeature("SketchArc")
+anArcCenter = geomDataAPI_Point2D(anArc2.attribute("center_point"))
+anArcCenter.setValue(12.5, 12.5)
+anArcStartPoint = geomDataAPI_Point2D(anArc2.attribute("start_point"))
+anArcStartPoint.setValue(5, 20)
+anArcEndPoint = geomDataAPI_Point2D(anArc2.attribute("end_point"))
+anArcEndPoint.setValue(20, 5)
+aSession.finishOperation()
+aSketch1Result = aSketch1.firstResult()
+# a wire
+aSession.startOperation()
+aWire1 = aPart.addFeature("Wire")
+aBaseObjectsList = aWire1.selectionList("base_objects")
+aBaseObjectsList.append(aSketch1Result, anArc1.lastResult().shape())
+aBaseObjectsList.append(aSketch1Result, anArc2.lastResult().shape())
+aSession.finishOperation()
+
+# Create second wire in another sketch
+aSession.startOperation()
+aSketch2 = featureToCompositeFeature(aPart.addFeature("Sketch"))
+anOrigin = geomDataAPI_Point(aSketch2.attribute("Origin"))
+anOrigin.setValue(0, 0, 0)
+aDirX = geomDataAPI_Dir(aSketch2.attribute("DirX"))
+aDirX.setValue(1, 0, 0)
+aNorm = geomDataAPI_Dir(aSketch2.attribute("Norm"))
+aNorm.setValue(0, 0.7071067811865475, 0.7071067811865475)
+# line 1
+aLine1 = aSketch2.addFeature("SketchLine")
+aLineStartPoint = geomDataAPI_Point2D(aLine1.attribute("StartPoint"))
+aLineStartPoint.setValue(30, 0)
+aLineEndPoint = geomDataAPI_Point2D(aLine1.attribute("EndPoint"))
+aLineEndPoint.setValue(20, 20)
+# line 2
+aLine2 = aSketch2.addFeature("SketchLine")
+aLineStartPoint = geomDataAPI_Point2D(aLine2.attribute("StartPoint"))
+aLineStartPoint.setValue(20, 20)
+aLineEndPoint = geomDataAPI_Point2D(aLine2.attribute("EndPoint"))
+aLineEndPoint.setValue(20, 0)
+aSession.finishOperation()
+aSketch2Result = aSketch2.firstResult()
+# a wire
+aSession.startOperation()
+aWire2 = aPart.addFeature("Wire")
+aBaseObjectsList = aWire2.selectionList("base_objects")
+aBaseObjectsList.append(aSketch2Result, aLine1.lastResult().shape())
+aBaseObjectsList.append(aSketch2Result, aLine2.lastResult().shape())
+aSession.finishOperation()
+
+# Create filling
+aSession.startOperation()
+aFillingFeature = aPart.addFeature("Filling")
+aBaseObjectsList = aFillingFeature.selectionList("base_objects")
+aBaseObjectsList.append(aWire1.lastResult(), None)
+aSession.finishOperation()
+
+# =============================================================================
+# Test 1. Filling on one wire is failed (no result is built)
+# =============================================================================
+assert(len(aFillingFeature.results()) == 0)
+
+# =============================================================================
+# Test 2. Add another wire, filling should be completed
+# =============================================================================
+aSession.startOperation()
+aBaseObjectsList.append(aWire2.lastResult(), None)
+aSession.finishOperation()
+assert(len(aFillingFeature.results()) > 0)
+
+# =============================================================================
+# Test 3. Change parameters one-by-one and check validity of result
+# =============================================================================
+aSession.startOperation()
+aFillingFeature.string("advanced_options").setValue("true")
+aSession.finishOperation()
+orientations = ["auto_correct", "curve_info", "edge_orient"]
+tolerances = [0.0001, 0.001]
+for ori in orientations:
+  for minDeg in range(2, 4):
+    for maxDeg in range(5, 7):
+      for nbIter in range(0, 3, 2):
+        for tol2d in tolerances:
+          for tol3d in tolerances:
+            for approx in [False, True]:
+              aSession.startOperation()
+              aFillingFeature.string("orientation").setValue(ori)
+              aFillingFeature.integer("min_degree").setValue(minDeg)
+              aFillingFeature.integer("max_degree").setValue(maxDeg)
+              aFillingFeature.integer("nb_iter").setValue(nbIter)
+              aFillingFeature.real("tol_2d").setValue(tol2d)
+              aFillingFeature.real("tol_3d").setValue(tol3d)
+              aFillingFeature.boolean("approximation").setValue(approx)
+              aSession.finishOperation()
+              assert(len(aFillingFeature.results()) > 0), "Filling feature failed with parameters:\n  orientation={}\n  min deg={}\n  max deg={}\n  nb iter={}\n  tol 2d={}\n  tol 3d={}\n  approximation={}".format(ori, minDeg, maxDeg, nbIter, tol2d, tol3d, approx)
+
+from salome.shaper import model
+assert(model.checkPythonDump())
diff --git a/src/BuildPlugin/Test/TestFilling_Mixed.py b/src/BuildPlugin/Test/TestFilling_Mixed.py
new file mode 100644 (file)
index 0000000..c020982
--- /dev/null
@@ -0,0 +1,167 @@
+## Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+# Initialization of the test
+from ModelAPI import *
+from GeomDataAPI import *
+from GeomAlgoAPI import *
+from GeomAPI import *
+
+# Get document
+aSession = ModelAPI_Session.get()
+aDocument = aSession.moduleDocument()
+
+# Create a part
+aSession.startOperation()
+aPartFeature = aDocument.addFeature("Part")
+aSession.finishOperation()
+aPartResult = modelAPI_ResultPart(aPartFeature.firstResult())
+aPart = aPartResult.partDoc()
+
+# Create first edge in a sketch
+aSession.startOperation()
+aSketch1 = featureToCompositeFeature(aPart.addFeature("Sketch"))
+anOrigin = geomDataAPI_Point(aSketch1.attribute("Origin"))
+anOrigin.setValue(0, 0, 0)
+aDirX = geomDataAPI_Dir(aSketch1.attribute("DirX"))
+aDirX.setValue(1, 0, 0)
+aNorm = geomDataAPI_Dir(aSketch1.attribute("Norm"))
+aNorm.setValue(0, 0, 1)
+# an arc
+anArc = aSketch1.addFeature("SketchArc")
+anArcCenter = geomDataAPI_Point2D(anArc.attribute("center_point"))
+anArcCenter.setValue(1, 1)
+anArcStartPoint = geomDataAPI_Point2D(anArc.attribute("start_point"))
+anArcStartPoint.setValue(20, 5)
+anArcEndPoint = geomDataAPI_Point2D(anArc.attribute("end_point"))
+anArcEndPoint.setValue(5, 20)
+aSession.finishOperation()
+aSketch1Result = aSketch1.firstResult()
+
+# Create a wire in another sketch
+aSession.startOperation()
+aSketch2 = featureToCompositeFeature(aPart.addFeature("Sketch"))
+anOrigin = geomDataAPI_Point(aSketch2.attribute("Origin"))
+anOrigin.setValue(0, 0, 0)
+aDirX = geomDataAPI_Dir(aSketch2.attribute("DirX"))
+aDirX.setValue(1, 0, 0)
+aNorm = geomDataAPI_Dir(aSketch2.attribute("Norm"))
+aNorm.setValue(0, 0.7071067811865475, 0.7071067811865475)
+# line 1
+aLine1 = aSketch2.addFeature("SketchLine")
+aLineStartPoint = geomDataAPI_Point2D(aLine1.attribute("StartPoint"))
+aLineStartPoint.setValue(0, 0)
+aLineEndPoint = geomDataAPI_Point2D(aLine1.attribute("EndPoint"))
+aLineEndPoint.setValue(10, 10)
+# line 2
+aLine2 = aSketch2.addFeature("SketchLine")
+aLineStartPoint = geomDataAPI_Point2D(aLine2.attribute("StartPoint"))
+aLineStartPoint.setValue(10, 10)
+aLineEndPoint = geomDataAPI_Point2D(aLine2.attribute("EndPoint"))
+aLineEndPoint.setValue(30, 0)
+aSession.finishOperation()
+aSketch2Result = aSketch2.firstResult()
+# a wire
+aSession.startOperation()
+aWire = aPart.addFeature("Wire")
+aBaseObjectsList = aWire.selectionList("base_objects")
+aBaseObjectsList.append(aSketch2Result, aLine1.lastResult().shape())
+aBaseObjectsList.append(aSketch2Result, aLine2.lastResult().shape())
+aSession.finishOperation()
+
+# Create filling
+aSession.startOperation()
+aFillingFeature = aPart.addFeature("Filling")
+aBaseObjectsList = aFillingFeature.selectionList("base_objects")
+aBaseObjectsList.append(aSketch1Result, anArc.lastResult().shape())
+aSession.finishOperation()
+
+# =============================================================================
+# Test 1. Filling on one edge is failed (no result is built)
+# =============================================================================
+assert(len(aFillingFeature.results()) == 0)
+
+# =============================================================================
+# Test 2. Add a wire, filling should be completed
+# =============================================================================
+aSession.startOperation()
+aBaseObjectsList.append(aWire.lastResult(), None)
+aSession.finishOperation()
+assert(len(aFillingFeature.results()) > 0)
+
+# =============================================================================
+# Test 3. Change parameters one-by-one and check validity of result
+# =============================================================================
+aSession.startOperation()
+aFillingFeature.string("advanced_options").setValue("true")
+aSession.finishOperation()
+orientations = ["auto_correct", "curve_info", "edge_orient"]
+tolerances = [0.0001, 0.001]
+for ori in orientations:
+  for minDeg in range(2, 4):
+    for maxDeg in range(5, 7):
+      for nbIter in range(0, 3, 2):
+        for tol2d in tolerances:
+          for tol3d in tolerances:
+            for approx in [False, True]:
+              aSession.startOperation()
+              aFillingFeature.string("orientation").setValue(ori)
+              aFillingFeature.integer("min_degree").setValue(minDeg)
+              aFillingFeature.integer("max_degree").setValue(maxDeg)
+              aFillingFeature.integer("nb_iter").setValue(nbIter)
+              aFillingFeature.real("tol_2d").setValue(tol2d)
+              aFillingFeature.real("tol_3d").setValue(tol3d)
+              aFillingFeature.boolean("approximation").setValue(approx)
+              aSession.finishOperation()
+              assert(len(aFillingFeature.results()) > 0), "Filling feature failed with parameters:\n  orientation={}\n  min deg={}\n  max deg={}\n  nb iter={}\n  tol 2d={}\n  tol 3d={}\n  approximation={}".format(ori, minDeg, maxDeg, nbIter, tol2d, tol3d, approx)
+
+# =============================================================================
+# Test 4. Discard parameters to default and add one more edge
+# =============================================================================
+aSession.startOperation()
+aFillingFeature.string("advanced_options").setValue("")
+aSession.finishOperation()
+# new arc
+aSession.startOperation()
+anArc2 = aSketch1.addFeature("SketchArc")
+anArc2Center = geomDataAPI_Point2D(anArc2.attribute("center_point"))
+anArc2Center.setValue(0, -5)
+anArc2StartPoint = geomDataAPI_Point2D(anArc2.attribute("start_point"))
+anArc2StartPoint.setValue(-20, -5)
+anArc2EndPoint = geomDataAPI_Point2D(anArc2.attribute("end_point"))
+anArc2EndPoint.setValue(20, -5)
+aSession.finishOperation()
+aSketch1Result = aSketch1.firstResult()
+# an edge
+aSession.startOperation()
+aPart.setCurrentFeature(aWire, True)
+anEdge = aPart.addFeature("Edge")
+anEdgeObjectsList = anEdge.selectionList("base_objects")
+anEdgeObjectsList.append(aSketch1Result, anArc2.lastResult().shape())
+aSession.finishOperation()
+# update filling
+aSession.startOperation()
+aPart.setCurrentFeature(aFillingFeature, True)
+aBaseObjectsList.append(anEdge.lastResult(), None)
+aSession.finishOperation()
+assert(len(aFillingFeature.results()) > 0)
+
+from salome.shaper import model
+assert(model.checkPythonDump())
index 52d37b68bf223b1ea087d7a6a964b77e2841ccad..4b371b9728cd60f77a7f6694e2e483c682db0538 100644 (file)
@@ -98,5 +98,30 @@ aSession.finishOperation()
 # Test results
 assert (len(aShellFeature.results()) > 0)
 
+# Test shell building on set of faces from another result
+
+# Cylinder
+aSession.startOperation()
+aCylinder = aPart.addFeature("Cylinder")
+aCylinder.string("CreationMethod").setValue("Cylinder")
+aCylinder.selection("base_point").selectSubShape("VERTEX", "PartSet/Origin")
+aCylinder.selection("axis").selectSubShape("EDGE", "PartSet/OZ")
+aCylinder.real("radius").setValue(25)
+aCylinder.real("height").setValue(50)
+aSession.finishOperation()
+aCylinderResult = aCylinder.firstResult()
+aCylinderShape = aCylinderResult.shape()
+
+# Create shell
+aSession.startOperation()
+aShellFeature2 = aPart.addFeature("Shell")
+aBaseObjectsList = aShellFeature2.selectionList("base_objects")
+aBaseObjectsList.append("Cylinder_1_1/Face_1", "FACE")
+aBaseObjectsList.append("Cylinder_1_1/Face_3", "FACE")
+aSession.finishOperation()
+
+# Test results
+assert (len(aShellFeature2.results()) > 0)
+
 from salome.shaper import model
 assert(model.checkPythonDump())
diff --git a/src/BuildPlugin/Test/TestSolid.py b/src/BuildPlugin/Test/TestSolid.py
new file mode 100644 (file)
index 0000000..2c9672d
--- /dev/null
@@ -0,0 +1,162 @@
+## Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+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(40, 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, 0, 0, 40)
+SketchLine_3 = Sketch_1.addLine(0, 40, 40, 40)
+SketchLine_4 = Sketch_1.addLine(40, 40, 40, 0)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_2.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 40)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r")])
+Sketch_2 = model.addSketch(Part_1_doc, model.standardPlane("YOZ"))
+SketchLine_5 = Sketch_2.addLine(20, 0, 0, 0)
+SketchLine_6 = Sketch_2.addLine(0, 0, 0, 20)
+SketchLine_7 = Sketch_2.addLine(0, 20, 20, 20)
+SketchLine_8 = Sketch_2.addLine(20, 20, 20, 0)
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_6.result())
+SketchConstraintHorizontal_4 = Sketch_2.setHorizontal(SketchLine_7.result())
+SketchConstraintVertical_4 = Sketch_2.setVertical(SketchLine_8.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), False)
+SketchLine_9 = SketchProjection_2.createdFeature()
+SketchConstraintMiddle_1 = Sketch_2.setMiddlePoint(SketchLine_5.startPoint(), SketchLine_9.result())
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchAPI_Line(SketchLine_9).startPoint(), SketchLine_5.endPoint())
+SketchConstraintEqual_2 = Sketch_2.setEqual(SketchLine_5.result(), SketchLine_6.result())
+SketchLine_10 = Sketch_2.addLine(20, 20, 20, 40)
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_10.startPoint())
+SketchLine_11 = Sketch_2.addLine(20, 40, 0, 40)
+SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint())
+SketchLine_12 = Sketch_2.addLine(0, 40, 0, 20)
+SketchConstraintCoincidence_13 = Sketch_2.setCoincident(SketchLine_11.endPoint(), SketchLine_12.startPoint())
+SketchConstraintCoincidence_14 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_12.endPoint())
+SketchConstraintVertical_5 = Sketch_2.setVertical(SketchLine_10.result())
+SketchConstraintHorizontal_5 = Sketch_2.setHorizontal(SketchLine_11.result())
+SketchConstraintVertical_6 = Sketch_2.setVertical(SketchLine_12.result())
+SketchConstraintEqual_3 = Sketch_2.setEqual(SketchLine_6.result(), SketchLine_12.result())
+model.do()
+Face_2 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchLine_5r-SketchLine_6r-SketchLine_7r-SketchLine_8r")])
+AngularCopy_1 = model.addMultiRotation(Part_1_doc, [model.selection("FACE", "Face_2_1")], model.selection("EDGE", "PartSet/OZ"), 270, 2)
+Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "AngularCopy_1_1_1"), model.selection("FACE", "AngularCopy_1_1_2")])
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_7f-SketchLine_10f-SketchLine_11f-SketchLine_12f")], model.selection(), 40, 0)
+Sketch_3 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_13 = Sketch_3.addLine(40, 0, 20, 0)
+SketchLine_14 = Sketch_3.addLine(20, 0, 20, 40)
+SketchLine_15 = Sketch_3.addLine(20, 40, 40, 40)
+SketchLine_16 = Sketch_3.addLine(40, 40, 40, 0)
+SketchConstraintCoincidence_15 = Sketch_3.setCoincident(SketchLine_16.endPoint(), SketchLine_13.startPoint())
+SketchConstraintCoincidence_16 = Sketch_3.setCoincident(SketchLine_13.endPoint(), SketchLine_14.startPoint())
+SketchConstraintCoincidence_17 = Sketch_3.setCoincident(SketchLine_14.endPoint(), SketchLine_15.startPoint())
+SketchConstraintCoincidence_18 = Sketch_3.setCoincident(SketchLine_15.endPoint(), SketchLine_16.startPoint())
+SketchConstraintHorizontal_6 = Sketch_3.setHorizontal(SketchLine_13.result())
+SketchConstraintVertical_7 = Sketch_3.setVertical(SketchLine_14.result())
+SketchConstraintHorizontal_7 = Sketch_3.setHorizontal(SketchLine_15.result())
+SketchConstraintVertical_8 = Sketch_3.setVertical(SketchLine_16.result())
+SketchProjection_3 = Sketch_3.addProjection(model.selection("VERTEX", "Sketch_2/Vertex-SketchLine_5s-SketchLine_15s-SketchLine_8e-SketchLine_14e"), False)
+SketchPoint_2 = SketchProjection_3.createdFeature()
+SketchConstraintCoincidence_19 = Sketch_3.setCoincident(SketchLine_13.endPoint(), SketchAPI_Point(SketchPoint_2).coordinates())
+SketchProjection_4 = Sketch_3.addProjection(model.selection("VERTEX", "Sketch_2/Vertex-SketchLine_11s-SketchLine_10e"), False)
+SketchPoint_3 = SketchProjection_4.createdFeature()
+SketchConstraintCoincidence_20 = Sketch_3.setCoincident(SketchLine_14.endPoint(), SketchAPI_Point(SketchPoint_3).coordinates())
+SketchProjection_5 = Sketch_3.addProjection(model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_3s-SketchLine_2e"), False)
+SketchPoint_4 = SketchProjection_5.createdFeature()
+SketchConstraintCoincidence_21 = Sketch_3.setCoincident(SketchLine_13.startPoint(), SketchAPI_Point(SketchPoint_4).coordinates())
+model.do()
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_13r-SketchLine_14r-SketchLine_15r-SketchLine_16r")], model.selection(), 20, 0)
+Box_1 = model.addBox(Part_1_doc, 20, 20, 20)
+model.do()
+
+def createSolidStepByStep(theSelection, theExpected):
+    Solid = model.addSolid(Part_1_doc, [theSelection[0]])
+    aList = []
+    for selection, expected in zip(theSelection, theExpected):
+        aList.append(selection)
+        Solid.setBase(aList)
+        if expected:
+            assert(len(Solid.results()) > 0), "FAILED: Solid is not built"
+        else:
+            assert(len(Solid.results()) == 0), "FAILED: Solid should not be built"
+    # remove solid if it is not built
+    if len(Solid.results()) == 0:
+        Part_1_doc.removeFeature(Solid.feature())
+        return None
+    return Solid
+
+# =============================================================================
+# Test 1. Build solid from faces applicable for compsolid
+# =============================================================================
+boundaries1 = [model.selection("FACE", "Face_1_1"),
+               model.selection("SHELL", "Shell_1_1"),
+               model.selection("FACE", "Sketch_3/Face-SketchLine_13r-SketchLine_14r-SketchLine_15r-SketchLine_16r"),
+               model.selection("FACE", "Extrusion_1_1/Generated_Face_4"),
+               model.selection("FACE", "Extrusion_2_1/Generated_Face_2"),
+               model.selection("FACE", "Extrusion_2_1/Generated_Face_3"),
+               model.selection("FACE", "Extrusion_2_1/Generated_Face_4"),
+               model.selection("FACE", "Extrusion_2_1/To_Face_1"),
+               model.selection("FACE", "Box_1_1/Front")]
+expectSolid1 = [False, False, False, False, False, False, False, True, False]
+Solid_1 = createSolidStepByStep(boundaries1, expectSolid1)
+assert(Solid_1 is None)
+
+# =============================================================================
+# Test 2. Build correct solid
+# =============================================================================
+boundaries2 = [model.selection("FACE", "Face_1_1"),
+               model.selection("SHELL", "Shell_1_1"),
+               model.selection("FACE", "Sketch_3/Face-SketchLine_13r-SketchLine_14r-SketchLine_15r-SketchLine_16r"),
+               model.selection("FACE", "Extrusion_1_1/Generated_Face_4"),
+               model.selection("FACE", "Extrusion_1_1/Generated_Face_3"),
+               model.selection("FACE", "Extrusion_2_1/Generated_Face_3"),
+               model.selection("FACE", "Extrusion_2_1/Generated_Face_4"),
+               model.selection("FACE", "Extrusion_2_1/To_Face_1"),
+               model.selection("FACE", "Box_1_1/Front")]
+expectSolid2 = [False, False, False, False, False, False, False, False, True]
+Solid_2 = createSolidStepByStep(boundaries2, expectSolid2)
+
+model.checkBooleansResult(Solid_2, model, 1, [0], [1], [10], [44], [88])
+model.testHaveNamingSubshapes(Solid_2, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
index 46d5de5e914b94677abcbe5808178d0b9395f338..351a29017c2d4edc72362fd9819b06a34b7adc6c 100644 (file)
@@ -35,6 +35,10 @@ aSession.finishOperation()
 aPartResult = modelAPI_ResultPart(aPartFeature.firstResult())
 aPart = aPartResult.partDoc()
 
+# =============================================================================
+# Test 1. Create wire from edges of sketch
+# =============================================================================
+
 # Create a sketch
 aSession.startOperation()
 aSketchFeature = featureToCompositeFeature(aPart.addFeature("Sketch"))
@@ -85,6 +89,10 @@ assert (len(aWireFeature.results()) > 0)
 
 from salome.shaper import model
 
+# =============================================================================
+# Test 2. Complete contour by selecting only one edge
+# =============================================================================
+
 model.begin()
 partSet = model.moduleDocument()
 Part_1 = model.addPart(partSet)
@@ -107,4 +115,34 @@ Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-Sketc
 Wire_1.addContour()
 model.end()
 
+# =============================================================================
+# Test 3. Create wire from edges of solid
+# =============================================================================
+
+# Box
+aSession.startOperation()
+aBox = aPart.addFeature("Box")
+aBox.string("CreationMethod").setValue("BoxByDimensions")
+aBox.real("dx").setValue(20)
+aBox.real("dy").setValue(20)
+aBox.real("dz").setValue(20)
+aSession.finishOperation()
+aBoxResult = aBox.firstResult()
+aBoxShape = aBoxResult.shape()
+
+# Wire
+aSession.startOperation()
+aWireFeature2 = aPart.addFeature("Wire")
+aBaseObjectsList = aWireFeature2.selectionList("base_objects")
+aBaseObjectsList.append("Box_1_1/Front&Box_1_1/Bottom", "EDGE")
+aBaseObjectsList.append("Box_1_1/Front&Box_1_1/Right", "EDGE")
+aBaseObjectsList.append("Box_1_1/Right&Box_1_1/Top", "EDGE")
+aBaseObjectsList.append("Box_1_1/Back&Box_1_1/Top", "EDGE")
+aBaseObjectsList.append("Box_1_1/Back&Box_1_1/Left", "EDGE")
+aBaseObjectsList.append("Box_1_1/Left&Box_1_1/Bottom", "EDGE")
+aSession.finishOperation()
+
+# Test results
+assert (len(aWireFeature2.results()) == 1)
+
 assert(model.checkPythonDump())
diff --git a/src/BuildPlugin/compound_widget.xml b/src/BuildPlugin/compound_widget.xml
new file mode 100644 (file)
index 0000000..32efcf2
--- /dev/null
@@ -0,0 +1,29 @@
+<!--
+Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+See http:##www.salome-platform.org/ or
+email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+-->
+
+<source>
+  <multi_selector id="base_objects"
+                  label="Objects:"
+                  tooltip="Select any kind of objects."
+                  type_choice="vertices edges wires faces shells solids compsolids compounds"
+                  concealment="true">
+  </multi_selector>
+</source>
diff --git a/src/BuildPlugin/compsolid_widget.xml b/src/BuildPlugin/compsolid_widget.xml
new file mode 100644 (file)
index 0000000..ab3626a
--- /dev/null
@@ -0,0 +1,30 @@
+<!--
+Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+See http:##www.salome-platform.org/ or
+email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+-->
+
+<source>
+  <multi_selector id="base_objects"
+                  label="Solids and CompSolids:"
+                  tooltip="Select solids or compsolids."
+                  type_choice="faces shells solids compsolids"
+                  concealment="true">
+    <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="face,shell,solid,compsolid"/>
+  </multi_selector>
+</source>
index a472e1f3dc5093bc030884c1e9a424f6838887be..38bce738472b8dcb2fbea87b872afaa8a44468dc 100644 (file)
@@ -23,9 +23,9 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
   <multi_selector id="base_objects"
                   label="Segments and wires:"
                   tooltip="Select edges on sketch, edges or wires objects."
-                  type_choice="edges wires"
+                  type_choice="edges wires faces"
                   concealment="true">
-    <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="edge,wire"/>
+    <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="edge,wire,face"/>
   </multi_selector>
   <validator id="BuildPlugin_ValidatorBaseForFace" parameters="base_objects"/>
 </source>
diff --git a/src/BuildPlugin/filling_widget.xml b/src/BuildPlugin/filling_widget.xml
new file mode 100644 (file)
index 0000000..0ecb858
--- /dev/null
@@ -0,0 +1,48 @@
+<!--
+Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+See http:##www.salome-platform.org/ or
+email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+-->
+
+<source>
+  <multi_selector id="base_objects"
+                  label="Segments and wires:"
+                  tooltip="Select edges or wires."
+                  type_choice="edges wires"
+                  concealment="false">
+    <validator id="PartSet_DifferentObjects"/>
+    <validator id="BuildPlugin_ValidatorFillingSelection"/>
+  </multi_selector>
+  <optionalbox id="advanced_options" title="Advanced options">
+    <switch id="orientation" label="Orientation">
+      <case id="auto_correct" title="Auto-correct edges orientation"/>
+      <case id="curve_info" title="Use curve information"/>
+      <case id="edge_orient" title="Use edges orientation"/>
+    </switch>
+    <integervalue id="min_degree" label="Min deg" min="1" default="2">
+      <validator id="GeomValidators_LessOrEqual" parameters="max_degree"/>
+    </integervalue>
+    <integervalue id="max_degree" label="Max deg" min="1" default="5">
+      <validator id="GeomValidators_GreaterOrEqual" parameters="min_degree"/>
+    </integervalue>
+    <integervalue id="nb_iter" label="Nb iter" min="0" default="0"/>
+    <doublevalue id="tol_2d" label="Tol 2D" min="0" default="0.0001" step="0.0001"/>
+    <doublevalue id="tol_3d" label="Tol 3D" min="0" default="0.0001" step="0.0001"/>
+    <boolvalue id="approximation" label="Approximation"/>
+  </optionalbox>
+</source>
diff --git a/src/BuildPlugin/icons/feature_compound.png b/src/BuildPlugin/icons/feature_compound.png
new file mode 100644 (file)
index 0000000..800dc6f
Binary files /dev/null and b/src/BuildPlugin/icons/feature_compound.png differ
diff --git a/src/BuildPlugin/icons/feature_compsolid.png b/src/BuildPlugin/icons/feature_compsolid.png
new file mode 100644 (file)
index 0000000..6fdf0db
Binary files /dev/null and b/src/BuildPlugin/icons/feature_compsolid.png differ
diff --git a/src/BuildPlugin/icons/feature_filling.png b/src/BuildPlugin/icons/feature_filling.png
new file mode 100644 (file)
index 0000000..e8a46f6
Binary files /dev/null and b/src/BuildPlugin/icons/feature_filling.png differ
diff --git a/src/BuildPlugin/icons/feature_solid.png b/src/BuildPlugin/icons/feature_solid.png
new file mode 100644 (file)
index 0000000..84dca6b
Binary files /dev/null and b/src/BuildPlugin/icons/feature_solid.png differ
index e73d1da3cba123ee46e7e3da1376de9141c2e7b4..2d98507d676a89cf2005c2763b29f5d3a82b967e 100644 (file)
@@ -37,11 +37,25 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
       <feature id="Shell" title="Shell" tooltip ="Create a shell from faces or shells objects" icon="icons/Build/feature_shell.png">
         <source path="shell_widget.xml"/>
       </feature>
+      <feature id="Solid" title="Solid" tooltip ="Create a solid from faces or shells" icon="icons/Build/feature_solid.png">
+        <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">
+        <source path="compsolid_widget.xml"/>
+      </feature>
+      <feature id="Compound" title="Compound" tooltip ="Create a compound of objects" icon="icons/Build/feature_compound.png">
+        <source path="compound_widget.xml"/>
+      </feature>
     </group>
     <group id="Modify">
       <feature id="SubShapes" title="Sub-Shapes" tooltip ="Allows to add or to remove sub-shapes of the selected shape" icon="icons/Build/feature_subshapes.png">
         <source path="subshapes_widget.xml"/>
       </feature>
     </group>
-   </workbench>
+    <group id="Advanced">
+      <feature id="Filling" title="Filling" tooltip="Create face from list of edges" icon="icons/Build/feature_filling.png">
+        <source path="filling_widget.xml"/>
+      </feature>
+    </group>
+  </workbench>
 </plugin>
index d454678c6d68e77d116addcde33912ddc6ae031d..f5ad261073a40766de1b55d6f83899bd28b590a3 100644 (file)
@@ -23,8 +23,8 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
   <multi_selector id="base_objects"
                   label="Faces and shells:"
                   tooltip="Select faces or shells objects."
-                  type_choice="objects"
+                  type_choice="faces shells"
                   concealment="true">
-    <validator id="GeomValidators_ShapeType" parameters="face,shell"/>
+    <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="face,shell"/>
   </multi_selector>
 </source>
diff --git a/src/BuildPlugin/solid_widget.xml b/src/BuildPlugin/solid_widget.xml
new file mode 100644 (file)
index 0000000..f45b981
--- /dev/null
@@ -0,0 +1,30 @@
+<!--
+Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+See http:##www.salome-platform.org/ or
+email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+-->
+
+<source>
+  <multi_selector id="base_objects"
+                  label="Faces and shells:"
+                  tooltip="Select faces or shells."
+                  type_choice="faces shells"
+                  concealment="true">
+    <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="face,shell"/>
+  </multi_selector>
+</source>
index e7e400d37c13971ad91b57aa62f35f78fc2ea9d5..94989abb5fceed86e54c720da0056f891834f7c6 100644 (file)
@@ -968,7 +968,7 @@ void CollectionPlugin_WidgetField::onTableEdited(int theRow, int theCol)
 //**********************************************************************************
 void CollectionPlugin_WidgetField::onShapeTypeChanged(int theType)
 {
-  activateSelectionAndFilters(theType == 5? false:true);
+  updateSelectionModesAndFilters(theType == 5? false:true);
 
   AttributeSelectionListPtr aSelList =
     myFeature->data()->selectionList(CollectionPlugin_Field::SELECTED_ID());
index 298ba49dc35d742983889cc02721a6a54f4dcac3..0f06d1dfdf8676f54d427fed562080ee26e4f388 100644 (file)
@@ -31,7 +31,7 @@ Box_1 = model.addBox(Part_1_doc, 10, 10, 20)
 Plane_4 = model.addPlane(Part_1_doc, model.selection("VERTEX", "Box_1_1/Back&Box_1_1/Right&Box_1_1/Top"), model.selection("VERTEX", "Box_1_1/Front&Box_1_1/Left&Box_1_1/Top"), model.selection("VERTEX", "Box_1_1/Back&Box_1_1/Left&Box_1_1/Bottom"))
 Group_1 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "Box_1_1/Back&Box_1_1/Left&Box_1_1/Top")])
 Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1")])
-Remove_SubShapes_1 = model.addRemoveSubShapes(Part_1_doc, model.selection("COMPSOLID", "Box_1_1"))
+Remove_SubShapes_1 = model.addRemoveSubShapes(Part_1_doc, model.selection("COMPSOLID", "Partition_1_1"))
 Remove_SubShapes_1.setSubShapesToKeep([model.selection("SOLID", "Partition_1_1_2")])
 model.do()
 # move group
index 67c29091a713dae4df895b1b29294a669a3980e3..99f15351a6a1cf4bd93b4e31f59562950f0a4c4e 100644 (file)
@@ -88,9 +88,6 @@ INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/ConnectorAPI.py DESTINATION ${SHAPER_I
 
 # Tests
 IF(${HAVE_SALOME})
-  INCLUDE(UnitTest)
-
-  ADD_UNIT_TESTS(
-    TestExportToGEOM.py
-  )
+  ENABLE_TESTING()
+  ADD_SUBDIRECTORY(Test)
 ENDIF(${HAVE_SALOME})
diff --git a/src/ConnectorAPI/Test/CMakeLists.txt b/src/ConnectorAPI/Test/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..1506027
--- /dev/null
@@ -0,0 +1,59 @@
+# Copyright (C) 2013-2016  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(tests.set)
+
+SET(COMPONENT_NAME SHAPER)
+
+SET(SALOME_SHAPER_INSTALL_TESTS "${SHAPER_INSTALL_PYTHON_FILES}/test")
+SET(TEST_INSTALL_DIRECTORY ${SALOME_SHAPER_INSTALL_TESTS})
+
+# make test
+SET(SALOME_INSTALL_LIBS "lib/salome")
+# Adding KERNEL and GUI libraries to environment so that Salome launches correctly
+if (WIN32)
+  SALOME_ACCUMULATE_ENVIRONMENT(PATH NOCHECK ${KERNEL_ROOT_DIR}/${SALOME_INSTALL_LIBS})
+  SALOME_ACCUMULATE_ENVIRONMENT(PATH NOCHECK ${GUI_ROOT_DIR}/${SALOME_INSTALL_LIBS})
+else()
+  SALOME_ACCUMULATE_ENVIRONMENT(LD_LIBRARY_PATH NOCHECK ${KERNEL_ROOT_DIR}/${SALOME_INSTALL_LIBS})
+  SALOME_ACCUMULATE_ENVIRONMENT(LD_LIBRARY_PATH NOCHECK ${GUI_ROOT_DIR}/${SALOME_INSTALL_LIBS})
+endif()
+SALOME_GENERATE_TESTS_ENVIRONMENT(tests_env)
+
+
+# -B ${CMAKE_SOURCE_DIR}/doc/salome/examples/testme.py
+FOREACH(tfile ${TEST_NAMES})
+  SET(TEST_NAME ${COMPONENT_NAME}_${tfile})
+  ADD_TEST(NAME ${TEST_NAME}
+           COMMAND ${PYTHON_EXECUTABLE} -B ${CMAKE_CURRENT_SOURCE_DIR}/testme.py ${CMAKE_CURRENT_SOURCE_DIR}/${tfile}.py)
+  SET_TESTS_PROPERTIES(${TEST_NAME} PROPERTIES ENVIRONMENT "${tests_env}")
+  SET_TESTS_PROPERTIES(${TEST_NAME} PROPERTIES LABELS "${COMPONENT_NAME}")
+ENDFOREACH()
+
+# salome test
+FOREACH(tfile ${TEST_NAMES})
+  INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${tfile}.py
+          DESTINATION ${TEST_INSTALL_DIRECTORY})
+ENDFOREACH()
+
+INSTALL(FILES CTestTestfileInstall.cmake
+  DESTINATION ${TEST_INSTALL_DIRECTORY}
+  RENAME CTestTestfile.cmake)
+
+INSTALL(FILES tests.set DESTINATION ${TEST_INSTALL_DIRECTORY})
\ No newline at end of file
diff --git a/src/ConnectorAPI/Test/CTestTestfileInstall.cmake b/src/ConnectorAPI/Test/CTestTestfileInstall.cmake
new file mode 100644 (file)
index 0000000..92cde25
--- /dev/null
@@ -0,0 +1,31 @@
+# Copyright (C) 2016  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(tests.set)
+
+SET(COMPONENT_NAME SHAPER)
+SET(SALOME_TEST_DRIVER "$ENV{KERNEL_ROOT_DIR}/bin/salome/appliskel/salome_test_driver.py")
+SET(TIMEOUT        300)
+
+
+FOREACH(tfile ${TEST_NAMES} ${EXAMPLE_NAMES})
+  SET(TEST_NAME ${COMPONENT_NAME}_${tfile})
+  ADD_TEST(${TEST_NAME} python ${SALOME_TEST_DRIVER} ${TIMEOUT} ${tfile}.py)
+  SET_TESTS_PROPERTIES(${TEST_NAME} PROPERTIES LABELS "${COMPONENT_NAME}")
+ENDFOREACH()
index 90539fff4538db143ce5a578c12b91afb138d48d..0403f1e9ee713944d7b1cd3dd9ee0eb01253a263 100644 (file)
 ## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
 ##
 
+import salome
 from salome.shaper import model
 
-model.begin()
-partSet = model.moduleDocument()
-Part_1 = model.addPart(partSet)
-Part_1_doc = Part_1.document()
-Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
-SketchLine_1 = Sketch_1.addLine(0, 0, 0, 50)
-SketchLine_2 = Sketch_1.addLine(0, 50, 50, 50)
-SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
-SketchLine_3 = Sketch_1.addLine(50, 50, 50, 0)
-SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
-SketchLine_4 = Sketch_1.addLine(50, 0, 0, 0)
-SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
-SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
-SketchConstraintRigid_1 = Sketch_1.setFixed(SketchLine_1.startPoint())
-SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_1.result())
-SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_4.result(), 50)
-SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_1.result(), 50)
-SketchConstraintParallel_1 = Sketch_1.setParallel(SketchLine_1.result(), SketchLine_3.result())
-SketchConstraintParallel_2 = Sketch_1.setParallel(SketchLine_2.result(), SketchLine_4.result())
-SketchConstraintPerpendicular_1 = Sketch_1.setPerpendicular(SketchLine_1.result(), SketchLine_4.result())
-model.do()
-Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r")], model.selection(), 50, 0)
-model.end()
-
-model.exportToGEOM(Part_1_doc)
+from salome.geom import geomBuilder
+
+import os
+import tempfile
+
+salome.salome_init(0,1)
+geompy = geomBuilder.New(salome.myStudy)
+
+## Get the last object published in the GEOM section of the object browser
+def getLastGEOMShape():
+  sb = salome.myStudy.NewBuilder()
+  comp = salome.myStudy.FindComponent("GEOM")
+  obj = None
+  if comp:
+    iterator = salome.myStudy.NewChildIterator( comp )
+    sobj = None
+    while iterator.More():
+      sobj = iterator.Value()
+      iterator.Next()
+    if sobj:
+      obj = sobj.GetObject()
+  else:
+    raise Exception("GEOM component not found.")
+  return obj
+
+## Get the sub-object i of an object in the object browser
+# Numerotation starts at 1
+def getSubObject(obj, i):
+  ok, sub_sobj = salome.ObjectToSObject(obj).FindSubObject(i)
+  if not ok:
+    raise Exception("No child found at %i for %s"%(i, obj.GetName()))
+  sub_obj = sub_sobj.GetObject()
+  return sub_obj
+
+def dumpShaper(fileName):
+  model.begin()
+  dump=model.moduleDocument().addFeature("Dump")
+  dump.string("file_path").setValue(fileName)
+  dump.string("file_format").setValue("py")
+  model.do()
+  model.end()
+  pass
+
+def getTmpFileName(ext):
+  tempdir = tempfile.gettempdir()
+  tmp_file = tempfile.NamedTemporaryFile(suffix=".%s"%ext, prefix='shaper_', dir=tempdir, delete=False)
+  tmp_filename = tmp_file.name
+  return tmp_filename
+
+# Create 2 boxes
+# Create a group of faces
+# Create a field of faces
+# exportToGEOM
+# Check the result
+# Check the dump
+def testSeveralExportsToGEOM():
+
+  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)
+  Box_2 = model.addBox(Part_1_doc, 20, 20, 20)
+  Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), -10)
+  Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_1_1"), model.selection("SOLID", "Box_2_1")])
+  Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Partition_1_1_1/Modified_Face_2_2"), model.selection("FACE", "Box_2_1/Top")])
+  model.do()
+  model.end()
+
+  # First export to GEOM
+  model.exportToGEOM(Part_1_doc)
+
+  # Check that the GEOM object has 1 compsolid and 2 solids
+  geomObject_1 = getLastGEOMShape()
+  assert geompy.NumberOfSubShapes(geomObject_1, geompy.ShapeType["COMPSOLID"]) == 1
+  assert geompy.NumberOfSolids(geomObject_1) == 2
+
+  # Check that the group has 2 faces
+  geomGroup_1 = getSubObject(geomObject_1, 1)
+  assert geompy.NumberOfFaces(geomGroup_1) == 2
+
+  # Add a third box
+  Box_3 = model.addBox(Part_1_doc, 10, 10, 10)
+  Translation_2 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_3_1")], model.selection("EDGE", "PartSet/OX"), 20)
+
+  # Second export to GEOM
+  model.exportToGEOM(Part_1_doc)
+
+  # Check that the GEOM object has 3 solids
+  geomObject_2 = getLastGEOMShape()
+  assert geompy.NumberOfSolids(geomObject_2) == 3
+
+  # Dump the salome study (only CORBA modules, SHAPER dump is not in it)
+  tempdir = tempfile.gettempdir()
+  dumpFileGeomBase = "dump_test_geom"
+  dumpFileGeom = os.path.join(tempdir, "%s.py"%dumpFileGeomBase)
+  salome.myStudy.DumpStudy(tempdir, dumpFileGeomBase, True, False)
+
+  # Dump SHAPER
+  dumpFileShaper = os.path.join(tempdir, "dump_test_shaper.py")
+  dumpShaper(dumpFileShaper)
+
+  # Load SHAPER dump
+  execfile(dumpFileShaper)
+
+  # Load GEOM dump
+  execfile(dumpFileGeom)
+
+  # Clean files
+  files = [dumpFileGeom, dumpFileShaper]
+  for f in files:
+    os.remove(f)
+
+  pass
+
+
+
+if __name__ == '__main__':
+  testSeveralExportsToGEOM()
\ No newline at end of file
diff --git a/src/ConnectorAPI/Test/TestExportToGEOMAllGroupsAndFields.py b/src/ConnectorAPI/Test/TestExportToGEOMAllGroupsAndFields.py
new file mode 100644 (file)
index 0000000..6e81973
--- /dev/null
@@ -0,0 +1,208 @@
+## Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+# -*- coding: utf-8 -*-
+
+import os
+import tempfile
+
+import sys
+import salome
+
+salome.salome_init()
+theStudy = salome.myStudy
+
+from salome.shaper import model
+
+from salome.geom import geomBuilder
+geompy = geomBuilder.New(salome.myStudy)
+
+## Get the last object published in the GEOM section of the object browser
+def getLastGEOMShape():
+  sb = salome.myStudy.NewBuilder()
+  comp = salome.myStudy.FindComponent("GEOM")
+  obj = None
+  if comp:
+    iterator = salome.myStudy.NewChildIterator( comp )
+    sobj = None
+    while iterator.More():
+      sobj = iterator.Value()
+      iterator.Next()
+    if sobj:
+      obj = sobj.GetObject()
+  else:
+    raise Exception("GEOM component not found.")
+  return obj
+
+## Get the sub-object i of an object in the object browser
+# Numerotation starts at 1
+def getSubObject(obj, i):
+  ok, sub_sobj = salome.ObjectToSObject(obj).FindSubObject(i)
+  if not ok:
+    raise Exception("No child found at %i for %s"%(i, obj.GetName()))
+  sub_obj = sub_sobj.GetObject()
+  return sub_obj
+
+def dumpShaper(fileName):
+  model.begin()
+  dump=model.moduleDocument().addFeature("Dump")
+  dump.string("file_path").setValue(fileName)
+  dump.string("file_format").setValue("py")
+  model.do()
+  model.end()
+  pass
+
+def getTmpFileName(ext):
+  tempdir = tempfile.gettempdir()
+  tmp_file = tempfile.NamedTemporaryFile(suffix=".%s"%ext, prefix='shaper_', dir=tempdir, delete=False)
+  tmp_filename = tmp_file.name
+  return tmp_filename
+
+def testGroupsAndFieldsExportToGEOM():
+  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)
+  Box_2 = model.addBox(Part_1_doc, 20, 20, 20)
+  Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), -10)
+  Translation_1.result().setName("Translation_1_1")
+  Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Translation_1_1"), model.selection("SOLID", "Box_2_1")])
+  Partition_1.result().setName("Partition_1_1")
+  Box_3 = model.addBox(Part_1_doc, 10, 10, 10)
+  Translation_2 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_3_1")], model.selection("EDGE", "PartSet/OX"), 20)
+  Translation_2.result().setName("Translation_2_1")
+  Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Partition_1_1_1/Modified_Face_2_2"), model.selection("FACE", "Box_2_1/Top"), model.selection("FACE", "Translation_2_1/Translated_Face_1")])
+  Group_1.result().setName("faces_top")
+  Group_2 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Partition_1_1_1/Modified_Face_2_5&Partition_1_1_1/Modified_Face_2_3"), model.selection("EDGE", "Partition_1_1_2/Modified_Face_2_2&Partition_1_1_2/Modified_Face_2_1"), model.selection("EDGE", "Translation_2_1/Translated_Face_4&Translation_2_1/Translated_Face_2")])
+  Group_2.result().setName("edges_x")
+  Group_3 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "Translation_1_1/Translated_Face_6&Partition_1_1_1/Modified_Face_2_5&Partition_1_1_1/Modified_Face_2_3"), model.selection("VERTEX", "Translation_2_1/Translated_Face_5&Translation_2_1/Translated_Face_4&Translation_2_1/Translated_Face_2"), model.selection("VERTEX", "Translation_2_1/Translated_Face_5&Translation_2_1/Translated_Face_3&Translation_2_1/Translated_Face_2"), model.selection("VERTEX", "Translation_1_1/Translated_Face_6&Partition_1_1_1/Modified_Face_2_4&Partition_1_1_1/Modified_Face_2_3"), model.selection("VERTEX", "Partition_1_1_2/Modified_Face_2_3&Partition_1_1_2/Modified_Face_2_1&Box_2_1/Right"), model.selection("VERTEX", "Partition_1_1_2/Modified_Face_2_1&Box_2_1/Front&Box_2_1/Right"), model.selection("VERTEX", "Partition_1_1_1/Modified_Face_2_4&Partition_1_1_1/Modified_Face_2_3&Partition_1_1_1/Modified_Face_2_1"), model.selection("VERTEX", "Translation_2_1/Translated_Face_6&Translation_2_1/Translated_Face_3&Translation_2_1/Translated_Face_2")])
+  Group_3.result().setName("vertices_bottom")
+  Group_4 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Partition_1_1_1"), model.selection("SOLID", "Translation_2_1")])
+  Group_4.result().setName("solids_small")
+  Field_1 = model.addField(Part_1_doc, 1, "DOUBLE", 1, ["Comp 1"], [model.selection("SOLID", "Partition_1_1_1"), model.selection("SOLID", "Partition_1_1_2"), model.selection("SOLID", "Translation_2_1")])
+  Field_1.result().setName("Field_solids")
+  Field_1.addStep(0, 0, [[0], [1], [2], [3]])
+  Field_2 = model.addField(Part_1_doc, 1, "DOUBLE", 1, ["Comp 1"], [model.selection("FACE", "Partition_1_1_1/Modified_Face_2_3"), model.selection("FACE", "Partition_1_1_2/Modified_Face_2_1"), model.selection("FACE", "Translation_2_1/Translated_Face_2"), model.selection("FACE", "Partition_1_1_1/Modified_Face_2_2"), model.selection("FACE", "Box_2_1/Top"), model.selection("FACE", "Translation_2_1/Translated_Face_1")])
+  Field_2.result().setName("Field_faces")
+  Field_2.addStep(0, 0, [[0], [1], [1], [1], [2], [2], [2]])
+  Field_3 = model.addField(Part_1_doc, 1, "DOUBLE", 1, ["Comp 1"], [model.selection("EDGE", "Partition_1_1_1/Modified_Face_2_5&Partition_1_1_1/Modified_Face_2_3"), model.selection("EDGE", "Partition_1_1_2/Modified_Face_2_2&Partition_1_1_2/Modified_Face_2_1"), model.selection("EDGE", "Translation_2_1/Translated_Face_4&Translation_2_1/Translated_Face_2"), model.selection("EDGE", "Translation_1_1/Translated_Face_6&Partition_1_1_1/Modified_Face_2_3"), model.selection("EDGE", "Translation_2_1/Translated_Face_5&Translation_2_1/Translated_Face_2"), model.selection("EDGE", "Translation_2_1/Translated_Face_5&Translation_2_1/Translated_Face_1"), model.selection("EDGE", "Translation_1_1/Translated_Face_6&Partition_1_1_1/Modified_Face_2_2"), model.selection("EDGE", "Partition_1_1_2/Modified_Face_2_3&Box_2_1/Top"), model.selection("EDGE", "Box_2_1/Front&Box_2_1/Top"), model.selection("EDGE", "Partition_1_1_2/Modified_Face_2_2&Box_2_1/Top"), model.selection("EDGE", "Box_2_1/Top&Box_2_1/Right")])
+  Field_3.result().setName("Field_edges")
+  Field_3.addStep(0, 0, [[0], [1], [1], [1], [2], [2], [2], [2], [3], [3], [3], [3]])
+  Field_4 = model.addField(Part_1_doc, 1, "DOUBLE", 1, ["Comp 1"], [model.selection("VERTEX", "Translation_1_1/Translated_Face_6&Partition_1_1_1/Modified_Face_2_5&Partition_1_1_1/Modified_Face_2_3"), model.selection("VERTEX", "Translation_1_1/Translated_Face_6&Partition_1_1_1/Modified_Face_2_4&Partition_1_1_1/Modified_Face_2_3"), model.selection("VERTEX", "Translation_2_1/Translated_Face_5&Translation_2_1/Translated_Face_4&Translation_2_1/Translated_Face_2"), model.selection("VERTEX", "Translation_2_1/Translated_Face_5&Translation_2_1/Translated_Face_3&Translation_2_1/Translated_Face_2"), model.selection("VERTEX", "Translation_2_1/Translated_Face_6&Translation_2_1/Translated_Face_3&Translation_2_1/Translated_Face_2"), model.selection("VERTEX", "Partition_1_1_2/Modified_Face_2_1&Box_2_1/Front&Box_2_1/Right"), model.selection("VERTEX", "Partition_1_1_2/Modified_Face_2_3&Partition_1_1_2/Modified_Face_2_1&Box_2_1/Right"), model.selection("VERTEX", "Partition_1_1_1/Modified_Face_2_4&Partition_1_1_1/Modified_Face_2_3&Partition_1_1_1/Modified_Face_2_1"), model.selection("VERTEX", "Translation_1_1/Translated_Face_6&Partition_1_1_1/Modified_Face_2_2&Partition_1_1_1/Modified_Face_2_4"), model.selection("VERTEX", "Translation_1_1/Translated_Face_6&Partition_1_1_1/Modified_Face_2_5&Partition_1_1_1/Modified_Face_2_2"), model.selection("VERTEX", "Translation_2_1/Translated_Face_5&Translation_2_1/Translated_Face_4&Translation_2_1/Translated_Face_1"), model.selection("VERTEX", "Translation_2_1/Translated_Face_5&Translation_2_1/Translated_Face_3&Translation_2_1/Translated_Face_1"), model.selection("VERTEX", "Partition_1_1_2/Modified_Face_2_2&Partition_1_1_2/Modified_Face_2_3&Box_2_1/Top"), model.selection("VERTEX", "Partition_1_1_2/Modified_Face_2_3&Box_2_1/Top&Box_2_1/Right"), model.selection("VERTEX", "Partition_1_1_2/Modified_Face_2_2&Box_2_1/Front&Box_2_1/Top"), model.selection("VERTEX", "Box_2_1/Front&Box_2_1/Top&Box_2_1/Right")])
+  Field_4.result().setName("Field_vertices")
+  Field_4.addStep(0, 0, [[0], [1], [1], [1], [1], [1], [1], [1], [1], [2], [2], [2], [2], [3], [3], [3], [3]])
+  model.exportToGEOM(Part_1_doc)
+  model.do()
+  model.end()
+
+# check the groups content by the coordinates of a point on its sub-shapes
+def checkGroupByCoords(group, coords, tolerance=1e-7):
+  for coord in coords:
+    p = geompy.MakeVertex(*coord)
+    assert geompy.MinDistance(group, p) < tolerance
+  pass
+
+## Check the result imported in GEOM
+def checkResultInGEOM():
+  geomObject_1 = getLastGEOMShape()
+
+  group_1_GEOM = getSubObject(geomObject_1, 1)
+  assert group_1_GEOM.GetName() == 'faces_top'
+  assert geompy.NumberOfFaces(group_1_GEOM) == 3
+
+  # coordinates of the barycenters of the faces of Group_1
+  coords_1 = [[-5, 5, 10], [10, 10, 20], [25, 5, 10]]
+  checkGroupByCoords(group_1_GEOM, coords_1)
+
+  group_2_GEOM = getSubObject(geomObject_1, 2)
+  assert group_2_GEOM.GetName() == 'edges_x'
+  assert geompy.NumberOfEdges(group_2_GEOM) == 3
+
+  # coordinates of the barycenters of the edges of Group_2
+  coords_2 = [[-5, 0, 0], [10, 0, 0], [25, 0, 0]]
+  checkGroupByCoords(group_2_GEOM, coords_2)
+
+  group_3_GEOM = getSubObject(geomObject_1, 3)
+  assert group_3_GEOM.GetName() == 'vertices_bottom'
+  assert geompy.NumberOfSubShapes(group_3_GEOM, geompy.ShapeType["VERTEX"]) == 8
+
+  # coordinates of the points of of Group_3
+  coords_3 = [[-10, 0, 0], [-10, 10, 0], [0, 10, 0], [0, 20, 0], [20, 20, 0], [20, 10, 0], [30, 10, 0], [30, 0, 0]]
+  checkGroupByCoords(group_3_GEOM, coords_3)
+
+  group_4_GEOM = getSubObject(geomObject_1, 4)
+  assert group_4_GEOM.GetName() == 'solids_small'
+  assert geompy.NumberOfSolids(group_4_GEOM) == 2
+
+  # coordinates of the barycenters of the solids of Group_4
+  coords_4 = [[-5, 5, 5], [25, 5, 5]]
+  checkGroupByCoords(group_4_GEOM, coords_4)
+
+  field_1_GEOM = getSubObject(geomObject_1, 5)
+  assert field_1_GEOM.GetName() == 'Field_solids'
+  assert field_1_GEOM.GetStep(0).GetValues() == [1.0, 2.0, 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, 2.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 2.0, 0.0, 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, 2.0, 0.0, 2.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 3.0, 3.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 2.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() == [2.0, 1.0, 2.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 3.0, 3.0, 3.0, 1.0, 1.0, 3.0, 0.0, 0.0, 0.0, 1.0, 2.0, 1.0, 2.0, 1.0]
+
+  pass
+
+def checkDump():
+  # Dump the salome study (only CORBA modules, SHAPER dump is not in it)
+  tempdir = tempfile.gettempdir()
+  dumpFileGeomBase = "dump_test_geom"
+  dumpFileGeom = os.path.join(tempdir, "%s.py"%dumpFileGeomBase)
+  salome.myStudy.DumpStudy(tempdir, dumpFileGeomBase, True, False)
+
+  # Dump SHAPER
+  dumpFileShaper = os.path.join(tempdir, "dump_test_shaper.py")
+  dumpShaper(dumpFileShaper)
+
+  # Load SHAPER dump
+  execfile(dumpFileShaper)
+
+  # Load GEOM dump
+  execfile(dumpFileGeom)
+
+  # Clean files
+  files = [dumpFileGeom, dumpFileShaper]
+  for f in files:
+    os.remove(f)
+
+  pass
+
+if __name__ == '__main__':
+  # create 3 boxes with groups and fields
+  testGroupsAndFieldsExportToGEOM()
+  # check the result in GEOM
+  checkResultInGEOM()
+  # check that dump produces no error and can be reloaded
+  checkDump()
+  # check the result of the dump
+  checkResultInGEOM()
diff --git a/src/ConnectorAPI/Test/testme.py b/src/ConnectorAPI/Test/testme.py
new file mode 100755 (executable)
index 0000000..4a6e17a
--- /dev/null
@@ -0,0 +1,56 @@
+# Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+#
+# 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
+#
+
+#!/usr/bin/env python
+
+import unittest, sys, os
+
+class SalomeSession(object):
+    def __init__(self, script):
+        import runSalome
+        run_script = "runSalome.py"
+        if sys.platform == 'win32':
+            module_dir = os.getenv("KERNEL_ROOT_DIR")
+            if module_dir: run_script = os.path.join(module_dir, "bin", "salome", run_script)
+            pass
+        sys.argv  = [run_script]
+        sys.argv += ["--terminal"]
+        sys.argv += ["--modules=SHAPER,GEOM"]
+        sys.argv += ["%s" % script]
+        if sys.platform == 'win32':
+            main_module_path = sys.modules['__main__'].__file__
+            sys.modules['__main__'].__file__ = ''
+        clt, d = runSalome.main()
+        if sys.platform == 'win32':
+            sys.modules['__main__'].__file__ = main_module_path
+        return
+
+    def __del__(self):
+        port = os.getenv('NSPORT')
+        import killSalomeWithPort
+        killSalomeWithPort.killMyPort(port)
+        return
+    pass
+
+class MyTest(unittest.TestCase):
+    def testFunction(self):
+        SalomeSession(sys.argv[1])
+    pass
+
+unittest.main(argv=sys.argv[:1])
diff --git a/src/ConnectorAPI/Test/tests.set b/src/ConnectorAPI/Test/tests.set
new file mode 100644 (file)
index 0000000..c3126a3
--- /dev/null
@@ -0,0 +1,23 @@
+# Copyright (C) 2016  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
+#
+
+SET(TEST_NAMES
+  TestExportToGEOM
+  TestExportToGEOMAllGroupsAndFields
+)
index aaaab43c631fe3001dfbc0d59cb897eb52e910a0..b529eac7331c06227617369d2988bc853a0183c0 100644 (file)
 ## @package Plugins
 #  ExportFeature class definition
 
-import EventsAPI
 import ModelAPI
-import GeomAPI
-import GeomAlgoAPI
+import ExchangeAPI
 
 import salome
 from salome.geom import geomBuilder
 
-def getObjectIndex(theName):
-    aStudy = salome.myStudy
-    aId = 0
-    aObj = aStudy.FindObjectByName(theName, "GEOM")
-    while len(aObj) != 0:
-        aId = aId + 1
-        aName = theName + '_' + str(aId)
-        aObj = aStudy.FindObjectByName(aName, "GEOM")
-    return aId
+from salome.shaper import model
+
+import os
+
+def getTmpFileName(ext):
+    import tempfile
+    tempdir = tempfile.gettempdir()
+    tmp_file = tempfile.NamedTemporaryFile(suffix=".%s"%ext, prefix='shaper_', dir=tempdir, delete=False)
+    tmp_filename = tmp_file.name
+    if os.name == "nt":
+        tmp_filename.replace("\\", "/")
+    return tmp_filename
 
 ## @ingroup Plugins
 #  Feature to export all shapes and groups into the GEOM module
@@ -46,10 +47,7 @@ class ExportFeature(ModelAPI.ModelAPI_Feature):
     ## The constructor.
     def __init__(self):
         ModelAPI.ModelAPI_Feature.__init__(self)
-        ## Shape that will be exported (the compound if there are several exported bodies)
-        self.shape = None
-        ## BRep representation of the exported shape (a stream that will be sent to GEOM and converted to GEOM object)
-        self.brep = None
+        pass
 
     @staticmethod
     ## Export kind. Static.
@@ -60,7 +58,7 @@ class ExportFeature(ModelAPI.ModelAPI_Feature):
     def getKind(self):
         return ExportFeature.ID()
 
-    ## This feature is action: has no property pannel and executes immideately.
+    ## This feature is action: has no property pannel and executes immediately.
     def isAction(self):
         return True
 
@@ -68,222 +66,35 @@ class ExportFeature(ModelAPI.ModelAPI_Feature):
     def initAttributes(self):
       pass
 
-    ## Exports all bodies
-    def exportBodies(self):
-        global ShapeIndex
-        kResultBodyType = "Bodies"
-        aPartSize = self.Part.size(kResultBodyType)
-        if aPartSize == 0:
-            EventsAPI.Events_InfoMessage("ExportFeature","No results in the active document").send()
+    ## Export the results, groups and fields via XAO
+    def exportViaXAO(self):
+        tmpXAOFile = getTmpFileName("xao")
+        self.tmpXAOFile = tmpXAOFile
+        #print "Export to %s"%tmpXAOFile
+        exportXAO = ExchangeAPI.exportToXAO(self.Part, tmpXAOFile, "automatic_shaper_export_to_XAO")
+        if not os.path.exists(tmpXAOFile) or os.stat(tmpXAOFile).st_size == 0:
+            exportXAO.feature().setError("Error in exportToXAO. No XAO file has been created.")
             return
-
-        anObjList = [self.Part.object(kResultBodyType, idx) for idx in xrange(aPartSize)]
-        aShapesList = GeomAlgoAPI.ShapeList()
-        aName = ""
-        for idx, anObject in enumerate(anObjList):
-            aResult = ModelAPI.modelAPI_Result(anObject)
-            aBodyResult = ModelAPI.modelAPI_ResultBody(aResult)
-            if not aBodyResult:
-                continue
-            aShape = aBodyResult.shape()
-            if aShape is not None and not aShape.isNull():
-              aShapesList.append(aShape)
-              if len(aShapesList) == 1:
-                aName = aBodyResult.data().name()
-
-        # issue 1045: create compound if there are more than one shape
-        if len(aShapesList) > 1:
-          self.shape = GeomAlgoAPI.GeomAlgoAPI_CompoundBuilder.compound(aShapesList)
-          aName = "ShaperResults"
-        elif len(aShapesList) == 1:
-          self.shape = aShapesList[0]
-
-        # so, only one shape is always in the result
-        aDump = self.shape.getShapeStream()
-        # Load shape to SALOME Geom
-        aBrep = self.geompy.RestoreShape(aDump)
-
-        # Make unique name
-        aId = getObjectIndex(aName)
-        if aId != 0:
-            aName = aName + '_' + str(aId)
-
-        self.geompy.addToStudy(aBrep, aName)
-        self.brep = aBrep
-
-    ## Exports all groups
-    def exportGroups(self):
-        # iterate all features to find groups
-        aFeaturesNum = self.Part.size("Features")
-        groupIndex = 0
-        for anIndex in range(0, aFeaturesNum):
-            aFeature = self.Part.object("Features", anIndex)
-            aSelectionList = aFeature.data().selectionList("group_list")
-            # if a group has been found
-            if aSelectionList:
-                aFeature = ModelAPI.objectToFeature(aFeature)
-                if aFeature.firstResult() is not None:
-                  aName = aFeature.firstResult().data().name()
-                groupIndex = groupIndex + 1
-                self.createGroupFromList(aSelectionList, aName)
-
-    ## Returns a type of the shape in the old GEOM representation
-    def shapeType(self, shape):
-        if shape.isVertex():
-            return "VERTEX"
-        elif shape.isEdge():
-            return "EDGE"
-        elif shape.isFace():
-            return "FACE"
-
-        return "SOLID"
-
-    ## Creates a group by given list of selected objects and the name
-    #  @param theSelectionList: list of selected objects
-    #  @param theGroupName: name of the group to create
-    def createGroupFromList(self, theSelectionList, theGroupName):
-        # iterate on all selected entities of the group
-        # and get the corresponding ID
-        aSelectionNum = theSelectionList.size()
-        Ids = []
-        groupType = ""
-        for aSelIndex in range(0, aSelectionNum):
-            aSelection = theSelectionList.value(aSelIndex)
-            # issue 1326: bodies that are already concealed did not exported, so groups should not be invalid
-            aContext =  ModelAPI.modelAPI_Result(aSelection.context())
-            # chcking of concealment removed because of #1799, remark #13 "aContext.isConcealed()"
-            if aContext is None or aContext.isDisabled():
-                continue
-
-            anID = GeomAlgoAPI.GeomAlgoAPI_CompoundBuilder.id(self.shape, aSelection.value())
-            if anID == 0:
-                #it may be a compound of objects if movement of the group to the end
-                # splits the original element to several (issue 1146)
-                anExp = GeomAPI.GeomAPI_ShapeExplorer(aSelection.value(), GeomAPI.GeomAPI_Shape.SHAPE)
-                while anExp.more():
-                    anID = GeomAlgoAPI.GeomAlgoAPI_CompoundBuilder.id(self.shape, anExp.current())
-                    if anID != 0:
-                        Ids.append(anID)
-                        groupType = self.shapeType(anExp.current())
-                    anExp.next()
-            else:
-                Ids.append(anID)
-                groupType = self.shapeType(aSelection.value())
-
-        if len(Ids) <> 0:
-          aGroup = self.geompy.CreateGroup(self.brep, self.geompy.ShapeType[groupType])
-          self.geompy.UnionIDs(aGroup,Ids)
-          self.geompy.addToStudyInFather(self.brep, aGroup, theGroupName)
-
-    ## Exports all fields
-    def exportFields(self):
-        # iterate all features to find fields
-        aFeaturesNum = self.Part.size("Features")
-        fieldIndex = 0
-        for anIndex in range(0, aFeaturesNum):
-            aFeature = self.Part.object("Features", anIndex)
-            aSelectionList = aFeature.data().selectionList("selected")
-            # if a field has been found
-            if aSelectionList:
-                aFeature = ModelAPI.objectToFeature(aFeature)
-                if aFeature.firstResult() is not None:
-                  aName = aFeature.firstResult().data().name()
-                fieldIndex = fieldIndex + 1
-                self.createFieldFromFeature(aFeature, aName)
-
-    ## Returns a type of the shape type in the old GEOM representation
-    def selectionDim(self, theSelectionType):
-        selType=theSelectionType.lower() # more or less independed approach
-        if selType== "vertex":
-            return 0
-        if selType== "edge":
-            return 1
-        if selType== "face":
-            return 2
-        if selType== "solid":
-            return 3
-        return -1
-
-    ## Returns a type of the shape type in the GeomAPI_Shape representation
-    def geomAPISelectionDim(self, theSelectionType):
-        selType=theSelectionType.lower() # more or less independed approach
-        if selType== "vertex":
-            return GeomAPI.GeomAPI_Shape.VERTEX
-        if selType== "edge":
-            return GeomAPI.GeomAPI_Shape.EDGE
-        if selType== "face":
-            return GeomAPI.GeomAPI_Shape.FACE
-        if selType== "solid":
-            return GeomAPI.GeomAPI_Shape.SOLID
-        return GeomAPI.GeomAPI_Shape.SHAPE
-
-    ## Creates a field by the field feature and the name
-    #  @param theField: the field feature
-    #  @param theFieldName: name of the field to create
-    def createFieldFromFeature(self, theField, theFieldName):
-        # iterate on all selected entities of the field
-        # and get the corresponding ID
-        aTables = theField.tables("values")
-        aSelection = theField.selectionList("selected")
-
-        # set component names
-        aComps = theField.stringArray("components_names")
-        aCompNames = []
-        aCompNum = aComps.size()
-        for aCompIndex in range(0, aCompNum):
-          aCompNames.append(aComps.value(aCompIndex))
-
-        #if len(Ids) <> 0:
-        aDim = self.selectionDim(aSelection.selectionType())
-        aResField = self.geompy.CreateField(self.brep, theFieldName, aTables.type(), aDim, aCompNames)
-        #self.geompy.UnionIDs(theField,Ids)
-        self.geompy.addToStudyInFather(self.brep, aResField, theFieldName)
-
-        # set default values to all not filled sub-shapes (fields in GEOM support only full set of subs)
-        Ids={}
-        anExp = GeomAPI.GeomAPI_ShapeExplorer(self.shape, self.geomAPISelectionDim(aSelection.selectionType()))
-        while anExp.more():
-          anID = GeomAlgoAPI.GeomAlgoAPI_CompoundBuilder.id(self.shape, anExp.current())
-          if anID != 0:
-            Ids[anID]=anExp.current()
-          anExp.next()
-
-        SelectedIds={}
-        for aSelIndex in range(aSelection.size()):
-          selShape = aSelection.value(aSelIndex).value()
-          # searching for this shape in Ids
-          for a in Ids.items():
-            if (a[1].isSame(selShape)):
-              SelectedIds[a[0]] = aSelIndex
-
-        # values here are in the same order as in field
-        listOfValues = Ids.items()
-        listOfValues.sort()
-        # set steps
-        aStepsNum = aTables.tables()
-        for aStepIndex in range(0, aStepsNum):
-          aStamp = theField.intArray("stamps").value(aStepIndex)
-          aValues = []
-          for aValId in listOfValues:
-            aRow = 0 # default value if not from selection
-            if SelectedIds.has_key(aValId[0]): # take the value from the table
-              aRow = SelectedIds[aValId[0]] + 1 # plus one to avoid default string
-            aCols = aTables.columns()
-            for aCol in range(0, aCols):
-              aVal = aTables.valueStr(aRow, aCol, aStepIndex)
-              if aTables.type() == 0: # bool
-                if aVal == "True":
-                  aVal = True
-                else:
-                  aVal = False
-              elif aTables.type() == 1: # int
-                aVal = int(aVal)
-              elif aTables.type() == 2: # double
-                aVal = float(aVal)
-              aValues.append(aVal)
-          aStep = aResField.addStep(aStepIndex + 1, aStamp, aValues)
-          if aStep:
-            self.geompy.addToStudyInFather( aResField, aStep, aStep.GetName() )
+        imported, shape, subShapes, groups, fields = self.geompy.ImportXAO(tmpXAOFile)
+        self.geompy.addToStudy( shape, shape.GetName() )
+        # add sub-shapes and groups to the object browser
+        for obj in subShapes + groups:
+            name = obj.GetName()
+            self.geompy.addToStudyInFather(shape, obj, name)
+        # add fields to the object browser
+        for field in fields:
+            name = field.GetName()
+            self.geompy.addToStudyInFather(shape, field, name)
+            # add steps to the object browser
+            steps = field.getSteps()
+            for i_step in steps:
+                step = field.getStep(i_step)
+                i_stamp = step.GetStamp()
+                step_name = "Step %i %i"%(i_step, i_stamp)
+                self.geompy.addToStudyInFather( field, step, step_name )
+        # Remove the temporary file
+        os.remove(tmpXAOFile)
+        pass
 
     ## Exports all shapes and groups into the GEOM module.
     def execute(self):
@@ -296,8 +107,6 @@ class ExportFeature(ModelAPI.ModelAPI_Feature):
         salome.salome_init(0,1)
         self.geompy = geomBuilder.New(salome.myStudy)
 
-        # Export bodies and groups
-        self.exportBodies()
-        self.exportGroups()
-        self.exportFields()
+        self.exportViaXAO()
+
         pass
index 9a49e0b64fe7eeffcfe2032889765248fdace722..492479e5065ea40d9e929dfb58f4df4104880d7e 100644 (file)
 
 #include "ExchangeAPI_Export.h"
 //--------------------------------------------------------------------------------------
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Feature.h>
 #include <ModelHighAPI_Tools.h>
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Services.h>
 //--------------------------------------------------------------------------------------
-void exportToFile(const std::shared_ptr<ModelAPI_Document> & thePart,
+
+ExchangeAPI_Export::ExchangeAPI_Export(const std::shared_ptr<ModelAPI_Feature>& theFeature)
+: ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+/// Constructor with values for XAO export.
+ExchangeAPI_Export::ExchangeAPI_Export(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                              const std::string & theFilePath,
+                              const std::string & theAuthor,
+                              const std::string & theGeometryName)
+: ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+  fillAttribute("XAO", theFeature->string(ExchangePlugin_ExportFeature::EXPORT_TYPE_ID()));
+  fillAttribute(theFilePath, theFeature->string(ExchangePlugin_ExportFeature::XAO_FILE_PATH_ID()));
+  fillAttribute(theAuthor, theFeature->string(ExchangePlugin_ExportFeature::XAO_AUTHOR_ID()));
+  fillAttribute(theGeometryName,
+                theFeature->string(ExchangePlugin_ExportFeature::XAO_GEOMETRY_NAME_ID()));
+  fillAttribute("XAO", theFeature->string(ExchangePlugin_ExportFeature::FILE_FORMAT_ID()));
+  execute();
+  apply(); // finish operation to make sure the export is done on the current state of the history
+}
+
+/// Constructor with values for export in other formats than XAO.
+ExchangeAPI_Export::ExchangeAPI_Export(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                              const std::string & theFilePath,
+                              const std::list<ModelHighAPI_Selection> & theSelectionList,
+                              const std::string & theFileFormat)
+: ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+  fillAttribute("Regular", theFeature->string(ExchangePlugin_ExportFeature::EXPORT_TYPE_ID()));
+  fillAttribute(theFilePath, theFeature->string(ExchangePlugin_ExportFeature::FILE_PATH_ID()));
+  fillAttribute(theSelectionList,
+                theFeature->selectionList(ExchangePlugin_ExportFeature::SELECTION_LIST_ID()));
+  fillAttribute(theFileFormat, theFeature->string(ExchangePlugin_ExportFeature::FILE_FORMAT_ID()));
+  execute();
+  apply(); // finish operation to make sure the export is done on the current state of the history
+}
+
+ExchangeAPI_Export::~ExchangeAPI_Export()
+{
+}
+
+
+void ExchangeAPI_Export::dump(ModelHighAPI_Dumper& theDumper) const
+{
+
+  FeaturePtr aBase = feature();
+  const std::string& aDocName = theDumper.name(aBase->document());
+
+  theDumper << aBase << " = model.";
+
+  std::string exportType = aBase->string(ExchangePlugin_ExportFeature::EXPORT_TYPE_ID())->value();
+
+  if (exportType == "XAO") {
+    std::string tmpXAOFile =
+                aBase->string(ExchangePlugin_ExportFeature::XAO_FILE_PATH_ID())->value();
+    theDumper << "exportToXAO(" << aDocName << ", '" << tmpXAOFile << "'" ;
+    std::string theAuthor = aBase->string(ExchangePlugin_ExportFeature::XAO_AUTHOR_ID())->value();
+    if (! theAuthor.empty())
+      theDumper << ", '" << theAuthor << "'";
+    std::string theGeometryName =
+                aBase->string(ExchangePlugin_ExportFeature::XAO_GEOMETRY_NAME_ID())->value();
+    if (! theGeometryName.empty())
+      theDumper << ", '" << theGeometryName << "'";
+    theDumper << ")" << std::endl;
+  }
+  else {
+      theDumper << "exportToFile(" << aDocName << ", " <<
+          aBase->string(ExchangePlugin_ExportFeature::FILE_PATH_ID()) << ", " <<
+          aBase->selectionList(ExchangePlugin_ExportFeature::SELECTION_LIST_ID()) ;
+      std::string theFileFormat =
+                  aBase->string(ExchangePlugin_ExportFeature::FILE_FORMAT_ID())->value();
+      if (! theFileFormat.empty())
+        theDumper << ", '" << theFileFormat << "'";
+      theDumper << ")" << std::endl;
+  }
+}
+
+ExportPtr exportToFile(const std::shared_ptr<ModelAPI_Document> & thePart,
                   const std::string & theFilePath,
                   const std::list<ModelHighAPI_Selection> & theSelectionList,
                   const std::string & theFileFormat)
 {
+  apply(); // finish previous operation to make sure all previous operations are done
   std::shared_ptr<ModelAPI_Feature> aFeature =
     thePart->addFeature(ExchangePlugin_ExportFeature::ID());
-  fillAttribute("Regular", aFeature->string(ExchangePlugin_ExportFeature::EXPORT_TYPE_ID()));
-  fillAttribute(theFilePath, aFeature->string(ExchangePlugin_ExportFeature::FILE_PATH_ID()));
-  fillAttribute(theSelectionList,
-                aFeature->selectionList(ExchangePlugin_ExportFeature::SELECTION_LIST_ID()));
-  fillAttribute(theFileFormat, aFeature->string(ExchangePlugin_ExportFeature::FILE_FORMAT_ID()));
-  aFeature->execute();
+  return ExportPtr(new ExchangeAPI_Export(aFeature, theFilePath, theSelectionList, theFileFormat));
 }
 
-void exportToXAO(const std::shared_ptr<ModelAPI_Document> & thePart,
+ExportPtr exportToXAO(const std::shared_ptr<ModelAPI_Document> & thePart,
                  const std::string & theFilePath,
                  const std::string & theAuthor,
                  const std::string & theGeometryName)
 {
+  apply(); // finish previous operation to make sure all previous operations are done
   std::shared_ptr<ModelAPI_Feature> aFeature =
     thePart->addFeature(ExchangePlugin_ExportFeature::ID());
-  fillAttribute("XAO", aFeature->string(ExchangePlugin_ExportFeature::EXPORT_TYPE_ID()));
-  fillAttribute(theFilePath, aFeature->string(ExchangePlugin_ExportFeature::XAO_FILE_PATH_ID()));
-  fillAttribute(theAuthor, aFeature->string(ExchangePlugin_ExportFeature::XAO_AUTHOR_ID()));
-  fillAttribute(theGeometryName,
-                aFeature->string(ExchangePlugin_ExportFeature::XAO_GEOMETRY_NAME_ID()));
-  fillAttribute("XAO", aFeature->string(ExchangePlugin_ExportFeature::FILE_FORMAT_ID()));
-  aFeature->execute();
+  return ExportPtr(new ExchangeAPI_Export(aFeature, theFilePath, theAuthor, theGeometryName));
 }
 
 //--------------------------------------------------------------------------------------
index f10bf831c137ebd011efffdc12c14d1435cfea1f..a4b314836c0775554452e820a61094bf348f6b7f 100644 (file)
 //--------------------------------------------------------------------------------------
 class ModelHighAPI_Selection;
 //--------------------------------------------------------------------------------------
+
+
+/// \class ExchangeAPI_Export
+/// \ingroup CPPHighAPI
+/// \brief Interface for Export feature.
+class ExchangeAPI_Export: public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  EXCHANGEAPI_EXPORT
+  explicit ExchangeAPI_Export(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values for XAO export.
+  EXCHANGEAPI_EXPORT
+  explicit ExchangeAPI_Export(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                              const std::string & theFilePath,
+                              const std::string & theAuthor = std::string(),
+                              const std::string & theGeometryName = std::string());
+
+  /// Constructor with values for export in other formats than XAO.
+  EXCHANGEAPI_EXPORT
+  explicit ExchangeAPI_Export(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                              const std::string & theFilePath,
+                              const std::list<ModelHighAPI_Selection> & theSelectionList,
+                              const std::string & theFileFormat = std::string());
+
+  /// Destructor.
+  EXCHANGEAPI_EXPORT
+  virtual ~ExchangeAPI_Export();
+
+  INTERFACE_7(ExchangePlugin_ExportFeature::ID(),
+             exportType, ExchangePlugin_ExportFeature::EXPORT_TYPE_ID(),
+             ModelAPI_AttributeString, /** ExportType */,
+             filePath, ExchangePlugin_ExportFeature::FILE_PATH_ID(),
+             ModelAPI_AttributeString, /** file path */,
+             xaoFilePath, ExchangePlugin_ExportFeature::XAO_FILE_PATH_ID(),
+             ModelAPI_AttributeString, /** xao_file_path */,
+             fileFormat, ExchangePlugin_ExportFeature::FILE_FORMAT_ID(),
+             ModelAPI_AttributeString, /** file format */,
+             selectionList, ExchangePlugin_ExportFeature::SELECTION_LIST_ID(),
+             ModelAPI_AttributeString, /** selection list */,
+             xaoAuthor, ExchangePlugin_ExportFeature::XAO_AUTHOR_ID(),
+             ModelAPI_AttributeString, /** xao author */,
+             xaoGeometryName, ExchangePlugin_ExportFeature::XAO_GEOMETRY_NAME_ID(),
+             ModelAPI_AttributeString, /** xao geometry name */)
+
+  /// Dump wrapped feature
+  EXCHANGEAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+};
+
+/// Pointer on Export object
+typedef std::shared_ptr<ExchangeAPI_Export> ExportPtr;
+
 /**\ingroup CPPHighAPI
  * \brief Export to file
  */
 EXCHANGEAPI_EXPORT
-void exportToFile(const std::shared_ptr<ModelAPI_Document> & thePart,
+ExportPtr exportToFile(const std::shared_ptr<ModelAPI_Document> & thePart,
                   const std::string & theFilePath,
                   const std::list<ModelHighAPI_Selection> & theSelectionList,
                   const std::string & theFileFormat = std::string());
@@ -47,7 +101,7 @@ void exportToFile(const std::shared_ptr<ModelAPI_Document> & thePart,
  * \brief Export XAO
  */
 EXCHANGEAPI_EXPORT
-void exportToXAO(const std::shared_ptr<ModelAPI_Document> & thePart,
+ExportPtr exportToXAO(const std::shared_ptr<ModelAPI_Document> & thePart,
                  const std::string & theFilePath,
                  const std::string & theAuthor = std::string(),
                  const std::string & theGeometryName = std::string());
index 3c56a9476d31f0992209f0a0fe9f27b35e4129e9..6d95ce732e0c8ef6c937f3842b08e8f2515fa744 100644 (file)
@@ -79,7 +79,9 @@ INSTALL(FILES ${XML_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
 INSTALL(DIRECTORY icons/ DESTINATION ${SHAPER_INSTALL_XML_RESOURCES}/icons/Exchange)
 INSTALL(FILES ${TEXT_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
 
-ADD_UNIT_TESTS(TestImport.py TestExport.py)
+ADD_UNIT_TESTS(TestImport.py
+               TestExport.py
+               Test2290.py)
 
 SET(DATA_FILES
   solid.brep
index 0c78b27e19d564ea586603b39054585ecea74786..f4e30155fba5e4a1ac1fb363f58e64faa092b37e 100644 (file)
@@ -225,6 +225,7 @@ void ExchangePlugin_ExportFeature::exportXAO(const std::string& theFileName)
 
   // make shape for export from all results
   std::list<GeomShapePtr> aShapes;
+  std::list<ResultBodyPtr> aResults;
   int aBodyCount = document()->size(ModelAPI_ResultBody::group());
   for (int aBodyIndex = 0; aBodyIndex < aBodyCount; ++aBodyIndex) {
     ResultBodyPtr aResultBody =
@@ -233,6 +234,7 @@ void ExchangePlugin_ExportFeature::exportXAO(const std::string& theFileName)
     if (!aResultBody.get())
       continue;
     aShapes.push_back(aResultBody->shape());
+    aResults.push_back(aResultBody);
   }
   GeomShapePtr aShape = (aShapes.size() == 1)
       ? *aShapes.begin()
@@ -246,8 +248,13 @@ void ExchangePlugin_ExportFeature::exportXAO(const std::string& theFileName)
   }
 
   // geometry name
-
   std::string aGeometryName = string(ExchangePlugin_ExportFeature::XAO_GEOMETRY_NAME_ID())->value();
+  if (aGeometryName.empty() && aBodyCount == 1) {
+    // get the name from the first result
+    ResultBodyPtr aResultBody = *aResults.begin();
+    aGeometryName = aResultBody->data()->name();
+  }
+
   aXao.getGeometry()->setName(aGeometryName);
 
   // groups
@@ -276,7 +283,12 @@ void ExchangePlugin_ExportFeature::exportXAO(const std::string& theFileName)
       AttributeSelectionPtr aSelection = aSelectionList->value(aSelectionIndex);
 
       // complex conversion of reference id to element index
-      int aReferenceID = aSelection->Id();
+      // gives bad id in case the selection is done from python script
+      // => using GeomAlgoAPI_CompoundBuilder::id instead
+      // int aReferenceID_old = aSelection->Id();
+
+      int aReferenceID = GeomAlgoAPI_CompoundBuilder::id(aShape, aSelection->value());
+
       std::string aReferenceString = XAO::XaoUtils::intToString(aReferenceID);
       int anElementID =
         aXao.getGeometry()->getElementIndexByReference(aGroupDimension, aReferenceString);
@@ -335,7 +347,12 @@ void ExchangePlugin_ExportFeature::exportXAO(const std::string& theFileName)
             AttributeSelectionPtr aSelection = aSelectionList->value(aRow - 1);
 
             // complex conversion of reference id to element index
-            int aReferenceID = aSelection->Id();
+            // gives bad id in case the selection is done from python script
+            // => using GeomAlgoAPI_CompoundBuilder::id instead
+            //int aReferenceID_old = aSelection->Id();
+
+            int aReferenceID = GeomAlgoAPI_CompoundBuilder::id(aShape, aSelection->value());
+
             std::string aReferenceString = XAO::XaoUtils::intToString(aReferenceID);
             anElementID =
               aXao.getGeometry()->getElementIndexByReference(aFieldDimension, aReferenceString);
index 754198869b2ad4dec31224c4b724968bd8bb7315..f0866181c1e63d5c22a2b05ae1f5965a91a4419f 100644 (file)
@@ -105,12 +105,17 @@ public:
   /// Computes or recomputes the results
   EXCHANGEPLUGIN_EXPORT virtual void execute();
 
-  /// Reimplemented from ModelAPI_Feature::isMacro(). Returns true.
-  EXCHANGEPLUGIN_EXPORT virtual bool isMacro() const { return true; }
+  /// Reimplemented from ModelAPI_Feature::isMacro(). Returns false.
+  // Not a macro. Otherwise, the feature will be deleted after being executed
+  EXCHANGEPLUGIN_EXPORT virtual bool isMacro() const { return false; }
 
   /// Reimplemented from ModelAPI_Feature::isPreviewNeeded(). Returns false.
   EXCHANGEPLUGIN_EXPORT virtual bool isPreviewNeeded() const { return false; }
 
+  /// Do not put in history.
+  /// Since it is not a macro, it is not deleted, but we don't want to see it.
+  bool isInHistory()  { return false; }
+
 protected:
   /// Performs export of the file
   EXCHANGEPLUGIN_EXPORT void exportFile(const std::string& theFileName,
index 786a59d52570652c126285194881ea59cbfdb01c..1d2000236e6a885bdd2f9ddb0122c9651b0538e0 100644 (file)
@@ -34,15 +34,15 @@ std::list<std::string> ExchangePlugin_Tools::split(const std::string& theString,
 
 std::string ExchangePlugin_Tools::selectionType2xaoDimension(const std::string& theType)
 {
-  if (theType == "Vertices" || theType == "vertex")
+  if (theType == "Vertices" || theType == "vertex" || theType == "VERTEX")
     return "vertex";
-  else if (theType == "Edges" || theType == "edge")
+  else if (theType == "Edges" || theType == "edge" || theType == "EDGE")
     return "edge";
-  else if (theType == "Faces" || theType == "face")
+  else if (theType == "Faces" || theType == "face" || theType == "FACE")
     return "face";
-  else if (theType == "Solids" || theType == "solid")
+  else if (theType == "Solids" || theType == "solid" || theType == "SOLID")
     return "solid";
-  else if (theType == "Part" || theType == "part")
+  else if (theType == "Part" || theType == "part" || theType == "PART")
     return "part";
 
   return std::string();
index 0848d67148e91dbc26008ec41a0fc4aea8a26b8c..566bbdf0576e2d1af5d5c7464a496b2ee97b90b7 100644 (file)
@@ -413,5 +413,40 @@ So
       <element index="1"/>
     </group>
   </groups>
-  <fields count="0"/>
+  <fields count="1">
+    <field name="Field_1" type="double" dimension="face">
+      <components count="2">
+        <component column="0" name="temperatue"/>
+        <component column="1" name="porosity"/>
+      </components>
+      <steps count="1">
+        <step number="0" stamp="10">
+          <element index="0">
+            <value component="0">2</value>
+            <value component="1">5</value>
+          </element>
+          <element index="1">
+            <value component="0">3</value>
+            <value component="1">6</value>
+          </element>
+          <element index="2">
+            <value component="0">1</value>
+            <value component="1">4</value>
+          </element>
+          <element index="3">
+            <value component="0">1</value>
+            <value component="1">4</value>
+          </element>
+          <element index="4">
+            <value component="0">1</value>
+            <value component="1">4</value>
+          </element>
+          <element index="5">
+            <value component="0">1</value>
+            <value component="1">4</value>
+          </element>
+        </step>
+      </steps>
+    </field>
+  </fields>
 </XAO>
diff --git a/src/ExchangePlugin/Test/Test2290.py b/src/ExchangePlugin/Test/Test2290.py
new file mode 100644 (file)
index 0000000..5671cea
--- /dev/null
@@ -0,0 +1,39 @@
+## Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 5, 10, 10)
+Box_2 = model.addBox(Part_1_doc, 10, 50, 8)
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_2_1"), model.selection("SOLID", "Box_1_1")])
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Partition_1_1_3/Modified_Face_2_3"), model.selection("FACE", "Partition_1_1_1/Modified_Face_2_3")])
+model.do()
+# test export to XAO
+anExportFeature = Part_1_doc.addFeature("Export")
+anExportFeature.string("xao_file_path").setValue("Data/export2290.xao")
+anExportFeature.string("file_format").setValue("XAO")
+anExportFeature.string("ExportType").setValue("XAO")
+anExportFeature.string("xao_author").setValue("me")
+anExportFeature.string("xao_geometry_name").setValue("mygeom")
+model.end()
index d3f88a729dca44ca2232a419da8f9b39f04fad4f..696a2b0c270eafc0885326dca553db00e133ea42 100644 (file)
@@ -144,8 +144,8 @@ def testExportXAO():
     aSession.finishOperation()
 
     # Check exported file
-#    import filecmp
-#    assert filecmp.cmp("Data/export.xao", "Data/export_ref.xao")
+    import filecmp
+    assert filecmp.cmp("Data/export.xao", "Data/export_ref.xao")
 
 if __name__ == '__main__':
 #=========================================================================
index 791859eedd8d904a1846a1f271742ca1c1e91647..1c549224202d4f881ecb6d847c8bad37a59ac8b4 100644 (file)
@@ -25,6 +25,7 @@ SET(PROJECT_HEADERS
   FeaturesAPI_Boolean.h
   FeaturesAPI_Extrusion.h
   FeaturesAPI_ExtrusionBoolean.h
+  FeaturesAPI_Fillet.h
   FeaturesAPI_Intersection.h
   FeaturesAPI_MultiRotation.h
   FeaturesAPI_MultiTranslation.h
@@ -46,6 +47,7 @@ SET(PROJECT_SOURCES
   FeaturesAPI_Boolean.cpp
   FeaturesAPI_Extrusion.cpp
   FeaturesAPI_ExtrusionBoolean.cpp
+  FeaturesAPI_Fillet.cpp
   FeaturesAPI_Intersection.cpp
   FeaturesAPI_MultiRotation.cpp
   FeaturesAPI_MultiTranslation.cpp
index e77373949f43a83a4012c468cb321f6b38173e7e..62afc3e4889829499a60f6e0870b7319d3ffee73 100644 (file)
@@ -44,6 +44,7 @@
 %shared_ptr(FeaturesAPI_ExtrusionBoolean)
 %shared_ptr(FeaturesAPI_ExtrusionCut)
 %shared_ptr(FeaturesAPI_ExtrusionFuse)
+%shared_ptr(FeaturesAPI_Fillet)
 %shared_ptr(FeaturesAPI_Intersection)
 %shared_ptr(FeaturesAPI_MultiRotation)
 %shared_ptr(FeaturesAPI_MultiTranslation)
@@ -66,6 +67,7 @@
 %include "FeaturesAPI_Boolean.h"
 %include "FeaturesAPI_Extrusion.h"
 %include "FeaturesAPI_ExtrusionBoolean.h"
+%include "FeaturesAPI_Fillet.h"
 %include "FeaturesAPI_Intersection.h"
 %include "FeaturesAPI_MultiRotation.h"
 %include "FeaturesAPI_MultiTranslation.h"
diff --git a/src/FeaturesAPI/FeaturesAPI_Fillet.cpp b/src/FeaturesAPI/FeaturesAPI_Fillet.cpp
new file mode 100644 (file)
index 0000000..d69ed3d
--- /dev/null
@@ -0,0 +1,143 @@
+// Copyright (C) 2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "FeaturesAPI_Fillet.h"
+
+#include <ModelHighAPI_Double.h>
+#include <ModelHighAPI_Dumper.h>
+////#include <ModelHighAPI_Reference.h>
+#include <ModelHighAPI_Tools.h>
+
+FeaturesAPI_Fillet::FeaturesAPI_Fillet(const std::shared_ptr<ModelAPI_Feature>& theFeature)
+  : ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+FeaturesAPI_Fillet::FeaturesAPI_Fillet(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                       const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                                       const ModelHighAPI_Double& theRadius)
+  : ModelHighAPI_Interface(theFeature)
+{
+  if (initialize()) {
+    fillAttribute(FeaturesPlugin_Fillet::CREATION_METHOD_SINGLE_RADIUS(), mycreationMethod);
+    fillAttribute(theBaseObjects, mybaseObjects);
+    fillAttribute(theRadius, myradius);
+
+    execIfBaseNotEmpty();
+  }
+}
+
+FeaturesAPI_Fillet::FeaturesAPI_Fillet(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                       const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                                       const ModelHighAPI_Double& theRadius1,
+                                       const ModelHighAPI_Double& theRadius2)
+  : ModelHighAPI_Interface(theFeature)
+{
+  if (initialize()) {
+    fillAttribute(FeaturesPlugin_Fillet::CREATION_METHOD_VARYING_RADIUS(), mycreationMethod);
+    fillAttribute(theBaseObjects, mybaseObjects);
+    fillAttribute(theRadius1, mystartRadius);
+    fillAttribute(theRadius2, myendRadius);
+
+    execIfBaseNotEmpty();
+  }
+}
+
+FeaturesAPI_Fillet::~FeaturesAPI_Fillet()
+{
+}
+
+//==================================================================================================
+void FeaturesAPI_Fillet::setBase(const std::list<ModelHighAPI_Selection>& theBaseObjects)
+{
+  mybaseObjects->clear();
+  fillAttribute(theBaseObjects, mybaseObjects);
+
+  execIfBaseNotEmpty();
+}
+
+void FeaturesAPI_Fillet::setRadius(const ModelHighAPI_Double& theRadius)
+{
+  fillAttribute(FeaturesPlugin_Fillet::CREATION_METHOD_SINGLE_RADIUS(), mycreationMethod);
+  fillAttribute(theRadius, myradius);
+
+  execIfBaseNotEmpty();
+}
+
+void FeaturesAPI_Fillet::setRadius(const ModelHighAPI_Double& theRadius1,
+                                   const ModelHighAPI_Double& theRadius2)
+{
+  fillAttribute(FeaturesPlugin_Fillet::CREATION_METHOD_VARYING_RADIUS(), mycreationMethod);
+  fillAttribute(theRadius1, mystartRadius);
+  fillAttribute(theRadius2, myendRadius);
+
+  execIfBaseNotEmpty();
+}
+
+void FeaturesAPI_Fillet::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  const std::string& aDocName = theDumper.name(aBase->document());
+
+  AttributeSelectionListPtr anAttrObjects =
+    aBase->selectionList(FeaturesPlugin_Fillet::OBJECT_LIST_ID());
+
+  theDumper << aBase << " = model.addFillet(" << aDocName << ", " << anAttrObjects;
+
+  std::string aCreationMethod = aBase->string(FeaturesPlugin_Fillet::CREATION_METHOD())->value();
+
+  if(aCreationMethod == FeaturesPlugin_Fillet::CREATION_METHOD_SINGLE_RADIUS()) {
+    AttributeDoublePtr anAttrRadius = aBase->real(FeaturesPlugin_Fillet::RADIUS_ID());
+    theDumper << ", " << anAttrRadius;
+  } else if(aCreationMethod == FeaturesPlugin_Fillet::CREATION_METHOD_VARYING_RADIUS()) {
+    AttributeDoublePtr anAttrRadius1 = aBase->real(FeaturesPlugin_Fillet::START_RADIUS_ID());
+    AttributeDoublePtr anAttrRadius2 = aBase->real(FeaturesPlugin_Fillet::END_RADIUS_ID());
+    theDumper << ", " << anAttrRadius1 << ", " << anAttrRadius2;
+  }
+
+  theDumper << ")" << std::endl;
+}
+
+void FeaturesAPI_Fillet::execIfBaseNotEmpty()
+{
+  if (mybaseObjects->size() > 0)
+    execute();
+}
+
+
+//==================================================================================================
+
+FilletPtr addFillet(const std::shared_ptr<ModelAPI_Document>& thePart,
+                    const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                    const ModelHighAPI_Double& theRadius)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(FeaturesAPI_Fillet::ID());
+  return FilletPtr(new FeaturesAPI_Fillet(aFeature, theBaseObjects, theRadius));
+}
+
+FilletPtr addFillet(const std::shared_ptr<ModelAPI_Document>& thePart,
+                    const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                    const ModelHighAPI_Double& theRadius1,
+                    const ModelHighAPI_Double& theRadius2)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(FeaturesAPI_Fillet::ID());
+  return FilletPtr(new FeaturesAPI_Fillet(aFeature, theBaseObjects, theRadius1, theRadius2));
+}
diff --git a/src/FeaturesAPI/FeaturesAPI_Fillet.h b/src/FeaturesAPI/FeaturesAPI_Fillet.h
new file mode 100644 (file)
index 0000000..e622408
--- /dev/null
@@ -0,0 +1,116 @@
+// Copyright (C) 2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef FeaturesAPI_Fillet_H_
+#define FeaturesAPI_Fillet_H_
+
+#include "FeaturesAPI.h"
+
+#include <FeaturesPlugin_Fillet.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Double;
+class ModelHighAPI_Selection;
+
+/// \class FeaturesAPI_Fillet
+/// \ingroup CPPHighAPI
+/// \brief Interface for Fillet feature.
+class FeaturesAPI_Fillet: public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  FEATURESAPI_EXPORT
+  explicit FeaturesAPI_Fillet(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values.
+  FEATURESAPI_EXPORT
+  explicit FeaturesAPI_Fillet(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                              const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                              const ModelHighAPI_Double& theRadius);
+
+  /// Constructor with values.
+  FEATURESAPI_EXPORT
+  explicit FeaturesAPI_Fillet(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                              const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                              const ModelHighAPI_Double& theRadius1,
+                              const ModelHighAPI_Double& theRadius2);
+
+  /// Destructor.
+  FEATURESAPI_EXPORT
+  virtual ~FeaturesAPI_Fillet();
+
+  INTERFACE_5(FeaturesPlugin_Fillet::ID(),
+              creationMethod, FeaturesPlugin_Fillet::CREATION_METHOD(),
+                              ModelAPI_AttributeString,
+                              /** Creation method */,
+              baseObjects, FeaturesPlugin_Fillet::OBJECT_LIST_ID(),
+                           ModelAPI_AttributeSelectionList,
+                           /** Base objects */,
+              radius, FeaturesPlugin_Fillet::RADIUS_ID(),
+                      ModelAPI_AttributeDouble,
+                      /** Value of the fixed radius fillet */,
+              startRadius, FeaturesPlugin_Fillet::START_RADIUS_ID(),
+                           ModelAPI_AttributeDouble,
+                           /** Start radius of the varying radius fillet */,
+              endRadius, FeaturesPlugin_Fillet::END_RADIUS_ID(),
+                         ModelAPI_AttributeDouble,
+                         /** End radius of the varying radius fillet */)
+
+  /// Modify base objects of the fillet.
+  FEATURESAPI_EXPORT
+  void setBase(const std::list<ModelHighAPI_Selection>& theBaseObjects);
+
+  /// Modify fillet to have fixed radius
+  FEATURESAPI_EXPORT
+  void setRadius(const ModelHighAPI_Double& theRadius);
+
+  /// Modify fillet to have varying radius
+  FEATURESAPI_EXPORT
+  void setRadius(const ModelHighAPI_Double& theRadius1, const ModelHighAPI_Double& theRadius2);
+
+  /// Dump wrapped feature
+  FEATURESAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+
+private:
+  void execIfBaseNotEmpty();
+};
+
+/// Pointer on Fillet object.
+typedef std::shared_ptr<FeaturesAPI_Fillet> FilletPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create Fillet feature.
+FEATURESAPI_EXPORT
+FilletPtr addFillet(const std::shared_ptr<ModelAPI_Document>& thePart,
+                    const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                    const ModelHighAPI_Double& theRadius);
+
+/// \ingroup CPPHighAPI
+/// \brief Create Fillet feature.
+FEATURESAPI_EXPORT
+FilletPtr addFillet(const std::shared_ptr<ModelAPI_Document>& thePart,
+                    const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                    const ModelHighAPI_Double& theRadius1,
+                    const ModelHighAPI_Double& theRadius2);
+
+#endif // FeaturesAPI_Fillet_H_
index 9a6637c03bffd8aa6229af5ea5d4c5fd5523fccf..8b6ce0005d468d1366028a17764a6ba9a7fea3cd 100644 (file)
@@ -27,6 +27,7 @@
   #include "FeaturesAPI_Boolean.h"
   #include "FeaturesAPI_Extrusion.h"
   #include "FeaturesAPI_ExtrusionBoolean.h"
+  #include "FeaturesAPI_Fillet.h"
   #include "FeaturesAPI_Intersection.h"
   #include "FeaturesAPI_MultiRotation.h"
   #include "FeaturesAPI_MultiTranslation.h"
index d527286bb8f73fc659bddf2c70240d84f1ceef29..9a39487a9e57984efb183bed5d997d5c22f9b7d9 100644 (file)
@@ -51,6 +51,7 @@ SET(PROJECT_HEADERS
     FeaturesPlugin_Scale.h
     FeaturesPlugin_MultiTranslation.h
     FeaturesPlugin_MultiRotation.h
+    FeaturesPlugin_Fillet.h
 )
 
 SET(PROJECT_SOURCES
@@ -82,6 +83,7 @@ SET(PROJECT_SOURCES
     FeaturesPlugin_Scale.cpp
     FeaturesPlugin_MultiTranslation.cpp
     FeaturesPlugin_MultiRotation.cpp
+    FeaturesPlugin_Fillet.cpp
 )
 
 SET(XML_RESOURCES
@@ -106,6 +108,7 @@ SET(XML_RESOURCES
   scale_widget.xml
   multitranslation_widget.xml
   multirotation_widget.xml
+  fillet_widget.xml
 )
 
 SET(TEXT_RESOURCES
@@ -167,6 +170,54 @@ ADD_UNIT_TESTS(TestExtrusion.py
                TestPipe.py
                TestRecover.py
                TestRecover1798.py
+               TestFillEdgeVertex.py
+               TestFillEdgeEdge.py
+               TestFillEdgeEdgeIntersected.py
+               TestFillEdgeWire.py
+               TestFillEdgeFace.py
+               TestFillEdgeShell.py
+               TestFillEdgeSolid.py
+               TestFillEdgeSolidIntersected.py
+               TestFillWireVertex.py
+               TestFillWireEdge.py
+               TestFillWireWire.py
+               TestFillWireFace.py
+               TestFillWireShell.py
+               TestFillWireSolid.py
+               TestFillFaceVertex.py
+               TestFillFaceEdge.py
+               TestFillFaceEdgeInside.py
+               TestFillFaceEdgePerpendicular.py
+               TestFillFaceWire.py
+               TestFillFaceFace.py
+               TestFillFaceShell.py
+               TestFillFaceSolid.py
+               TestFillCompFaceSolid.py
+               TestFillShellVertex.py
+               TestFillShellEdge.py
+               TestFillShellConstrPlane.py
+               TestFillShellWire.py
+               TestFillShellFace.py
+               TestFillShellShell.py
+               TestFillShellSolid.py
+               TestFillSolid2ConstructionPlanes.py
+               TestFillSolidEdge.py
+               TestFillSolidFace.py
+               TestFillSolidCompFace.py
+               TestFillSolidShell.py
+               TestFillSolidCompShell.py
+               TestPartition2Faces.py
+               TestPartition2Solids.py
+               TestPartition2Wires.py
+               TestPartitionBox4Planes.py
+               TestPartitionEdgeSolid.py
+               TestPartitionFace2Solid.py
+#               TestPartitionFaceSolid.py
+               TestPartitionFaceWire.py
+               TestPartitionInclinedFaceSolid.py
+               TestPartitionWireFaceSolid.py
+               TestUnion4CurvedFaces.py
+               TestUnion4Faces.py
                Test1922.py
                Test1942.py
                Test1915.py
@@ -190,4 +241,5 @@ ADD_UNIT_TESTS(TestExtrusion.py
                Test2255.py
                Test2289.py
                Test2304.py
+               Test2377.py
 )
index 08af8844540ac2689460607338268b5610ccc36a..64072e62accc7b53a9543440a8e4cbe5483051db 100644 (file)
@@ -118,10 +118,14 @@ void FeaturesPlugin_Boolean::execute()
         aCompSolidsObjects[aContextShape].push_back(anObject);
       }
     } else {
-      if(anObject->shapeType() == GeomAPI_Shape::EDGE ||
-         anObject->shapeType() == GeomAPI_Shape::FACE) {
+      if(aType != BOOL_FILL
+        && (anObject->shapeType() == GeomAPI_Shape::EDGE
+          || anObject->shapeType() == GeomAPI_Shape::FACE))
+      {
         anEdgesAndFaces.push_back(anObject);
-      } else {
+      }
+      else
+      {
         anObjects.push_back(anObject);
       }
     }
@@ -136,8 +140,11 @@ void FeaturesPlugin_Boolean::execute()
       // It could be a construction plane.
       ResultPtr aContext = aToolAttr->context();
       aPlanes.push_back(aToolAttr->context()->shape());
-    } else if(aTool->shapeType() == GeomAPI_Shape::EDGE ||
-       aTool->shapeType() == GeomAPI_Shape::FACE) {
+    }
+    else if(aType != BOOL_FILL
+      && (aTool->shapeType() == GeomAPI_Shape::EDGE
+        || aTool->shapeType() == GeomAPI_Shape::FACE))
+    {
       anEdgesAndFaces.push_back(aTool);
     } else {
       aTools.push_back(aTool);
@@ -239,7 +246,9 @@ void FeaturesPlugin_Boolean::execute()
 
         aMakeShapeList.appendAlgo(aBoolAlgo);
 
-        if(GeomAlgoAPI_ShapeTools::volume(aResShape) > 1.e-27) {
+        if(GeomAlgoAPI_ShapeTools::volume(aResShape) > 1.e-27
+          || (aType != BOOL_CUT && aType != BOOL_COMMON))
+        {
           std::shared_ptr<ModelAPI_ResultBody> aResultBody =
             document()->createBody(data(), aResultIndex);
 
@@ -357,7 +366,9 @@ void FeaturesPlugin_Boolean::execute()
           aResultShape = aFillerAlgo->shape();
         }
 
-        if(GeomAlgoAPI_ShapeTools::volume(aResultShape) > 1.e-27) {
+        if(GeomAlgoAPI_ShapeTools::volume(aResultShape) > 1.e-27
+          || (aType != BOOL_CUT && aType != BOOL_COMMON))
+        {
           std::shared_ptr<ModelAPI_ResultBody> aResultBody =
             document()->createBody(data(), aResultIndex);
 
@@ -697,10 +708,11 @@ void FeaturesPlugin_Boolean::loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> t
     theResultBody->store(theResultShape, false);
   } else {
     const int aModifyTag = 1;
-    const int aDeletedTag = 2;
-    /// sub solids will be placed at labels 3, 4, etc. if result is compound of solids
-    const int aSubsolidsTag = 3;
-    const int anEdgesAndFacesTag = 10000;
+    const int aModifyEdgeTag = 2;
+    const int aModifyFaceTag = 3;
+    const int aDeletedTag = 4;
+    /// sub solids will be placed at labels 5, 6, etc. if result is compound of solids
+    const int aSubsolidsTag = 5;
 
     theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag);
 
@@ -708,8 +720,10 @@ void FeaturesPlugin_Boolean::loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> t
     const std::string aModEName = "Modified_Edge";
     const std::string aModFName = "Modified_Face";
 
+    theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::EDGE,
+      aModifyEdgeTag, aModEName, theMapOfShapes, false, theIsStoreAsGenerated, true);
     theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE,
-      aModifyTag, aModName, theMapOfShapes, false, theIsStoreAsGenerated, true);
+      aModifyFaceTag, aModFName, theMapOfShapes, false, theIsStoreAsGenerated, true);
     theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape,
                                      GeomAPI_Shape::FACE, aDeletedTag);
 
@@ -717,16 +731,12 @@ void FeaturesPlugin_Boolean::loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> t
     std::string aName;
     for(ListOfShape::const_iterator
         anIter = theTools.begin(); anIter != theTools.end(); anIter++) {
-      if((*anIter)->shapeType() == GeomAPI_Shape::EDGE) {
-        aTag = anEdgesAndFacesTag;
-        aName = aModEName;
-      }
-      else if((*anIter)->shapeType() == GeomAPI_Shape::FACE) {
-        aTag = anEdgesAndFacesTag;
+      if((*anIter)->shapeType() <= GeomAPI_Shape::FACE) {
+        aTag = aModifyFaceTag;
         aName = aModFName;
       } else {
-        aTag = aModifyTag;
-        aName = aModName;
+        aTag = aModifyEdgeTag;
+        aName = aModEName;
       }
       theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter,
         aName == aModEName ? GeomAPI_Shape::EDGE : GeomAPI_Shape::FACE,
diff --git a/src/FeaturesPlugin/FeaturesPlugin_Fillet.cpp b/src/FeaturesPlugin/FeaturesPlugin_Fillet.cpp
new file mode 100644 (file)
index 0000000..0df54c1
--- /dev/null
@@ -0,0 +1,231 @@
+// Copyright (C) 2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "FeaturesPlugin_Fillet.h"
+
+#include <ModelAPI_Data.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Tools.h>
+#include <ModelAPI_Validator.h>
+
+#include <GeomAlgoAPI_Fillet.h>
+#include <GeomAlgoAPI_MakeShapeList.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 single shape, return it
+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_Fillet::FeaturesPlugin_Fillet()
+{
+}
+
+void FeaturesPlugin_Fillet::initAttributes()
+{
+  data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId());
+  data()->addAttribute(START_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(END_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), END_RADIUS_ID());
+}
+
+
+void FeaturesPlugin_Fillet::execute()
+{
+  AttributeStringPtr aCreationMethod = string(CREATION_METHOD());
+  if (!aCreationMethod)
+    return;
+
+  GeomAPI_DataMapOfShapeMapOfShapes aSolidsAndSubs;
+
+  // getting objects and sort them accroding 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();
+    ResultCompSolidPtr aCtxOwner = ModelAPI_Tools::compSolidOwner(aContext);
+    GeomShapePtr aParent = aCtxOwner ? aCtxOwner->shape() : aContext->shape();
+    if (!aParent)
+      return;
+
+    ListOfShape anEdgesAndVertices;
+    collectSubs(anObject, anEdgesAndVertices, GeomAPI_Shape::EDGE);
+    collectSubs(anObject, anEdgesAndVertices, GeomAPI_Shape::VERTEX);
+    for (ListOfShape::iterator aEIt = anEdgesAndVertices.begin();
+         aEIt != anEdgesAndVertices.end(); ++aEIt)
+      aSolidsAndSubs.add(aParent, *aEIt);
+  }
+
+  bool isFixedRadius = true;
+  double aRadius1 = 0.0, aRadius2 = 0.0;
+  if (aCreationMethod->value() == CREATION_METHOD_SINGLE_RADIUS())
+    aRadius1 = real(RADIUS_ID())->value();
+  else {
+    aRadius1 = real(START_RADIUS_ID())->value();
+    aRadius2 = real(END_RADIUS_ID())->value();
+    isFixedRadius = false;
+  }
+
+  // Perform fillet operation
+  GeomAlgoAPI_MakeShapeList aMakeShapeList;
+  std::shared_ptr<GeomAlgoAPI_Fillet> aFilletBuilder;
+  int aResultIndex = 0;
+
+  GeomAPI_DataMapOfShapeMapOfShapes::iterator anIt = aSolidsAndSubs.begin();
+  for (; anIt != aSolidsAndSubs.end(); ++anIt) {
+    GeomShapePtr aSolid = anIt.first();
+    ListOfShape aFilletEdgesAndVertices = anIt.second();
+
+    ListOfShape aFilletEdges = selectEdges(aFilletEdgesAndVertices);
+    if (isFixedRadius)
+      aFilletBuilder.reset(new GeomAlgoAPI_Fillet(aSolid, aFilletEdges, aRadius1));
+    else
+      aFilletBuilder.reset(new GeomAlgoAPI_Fillet(aSolid, aFilletEdges, aRadius1, aRadius2));
+    if (isFailed(aFilletBuilder))
+      return;
+
+    GeomShapePtr aResult = unwrapCompound(aFilletBuilder->shape());
+    std::shared_ptr<ModelAPI_ResultBody> aResultBody =
+        document()->createBody(data(), aResultIndex);
+
+    loadNamingDS(aResultBody, aSolid, aFilletEdgesAndVertices, aResult, aFilletBuilder);
+    setResult(aResultBody, aResultIndex);
+    aResultIndex++;
+  }
+  removeResults(aResultIndex);
+}
+
+bool FeaturesPlugin_Fillet::isFailed(
+    const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgorithm)
+{
+  if (!theAlgorithm->isDone()) {
+    static const std::string aFeatureError = "Error: fillet algorithm failed.";
+    setError(aFeatureError);
+    return true;
+  }
+  if (theAlgorithm->shape()->isNull()) {
+    static const std::string aShapeError = "Error: Resulting shape of fillet is Null.";
+    setError(aShapeError);
+    return true;
+  }
+  if (!theAlgorithm->isValid()) {
+    std::string aFeatureError = "Error: Resulting shape of fillet is not valid.";
+    setError(aFeatureError);
+    return true;
+  }
+  return false;
+}
+
+void FeaturesPlugin_Fillet::loadNamingDS(
+    std::shared_ptr<ModelAPI_ResultBody> theResultBody,
+    const std::shared_ptr<GeomAPI_Shape> theBaseShape,
+    const ListOfShape& theFilletShapes,
+    const std::shared_ptr<GeomAPI_Shape> theResultShape,
+    const std::shared_ptr<GeomAlgoAPI_MakeShape>& theMakeShape)
+{
+  //load result
+  if(theBaseShape->isEqual(theResultShape)) {
+    theResultBody->store(theResultShape, false);
+    return;
+  }
+
+  std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfShapes = theMakeShape->mapOfSubShapes();
+
+  const int aDeletedTag = 1;
+  const int aModifyTag = 2;
+  const int aGeneratedTag = 3;
+  /// sub solids will be placed at labels 4, 5, etc. if result is compound of solids
+  const int aSubsolidsTag = 4;
+
+  theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag);
+  theResultBody->storeGenerated(theBaseShape, theResultShape);
+
+  const std::string aModFaceName = "Modified_Face";
+  const std::string aFilletFaceName = "Fillet_Face";
+
+  // Store modified faces
+  theResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), theBaseShape,
+      GeomAPI_Shape::FACE, aModifyTag, aModFaceName, *aMapOfShapes);
+
+  // Store new faces generated from edges and vertices
+  theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(), theBaseShape,
+      GeomAPI_Shape::EDGE, aGeneratedTag, aFilletFaceName, *aMapOfShapes);
+  theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(), theBaseShape,
+      GeomAPI_Shape::VERTEX, aGeneratedTag, aFilletFaceName, *aMapOfShapes);
+
+  // Deleted shapes
+  theResultBody->loadDeletedShapes(theMakeShape.get(), theBaseShape,
+                                   GeomAPI_Shape::EDGE, aDeletedTag);
+  theResultBody->loadDeletedShapes(theMakeShape.get(), theBaseShape,
+                                   GeomAPI_Shape::FACE, aDeletedTag);
+}
diff --git a/src/FeaturesPlugin/FeaturesPlugin_Fillet.h b/src/FeaturesPlugin/FeaturesPlugin_Fillet.h
new file mode 100644 (file)
index 0000000..d0aa712
--- /dev/null
@@ -0,0 +1,120 @@
+// Copyright (C) 2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef FeaturesPlugin_Fillet_H_
+#define FeaturesPlugin_Fillet_H_
+
+#include "FeaturesPlugin.h"
+
+#include <GeomAPI_Shape.h>
+
+#include <ModelAPI_Feature.h>
+
+class GeomAlgoAPI_MakeShape;
+class GeomAPI_DataMapOfShapeMapOfShapes;
+
+/// \class FeaturesPlugin_Fillet
+/// \ingroup Plugins
+/// \brief Feature for applying the Fillet operations on Solids.
+///        Supports fixed radius fillet and varying 2-radius fillet.
+class FeaturesPlugin_Fillet : public ModelAPI_Feature
+{
+public:
+  /// Feature kind.
+  inline static const std::string& ID()
+  {
+    static const std::string MY_ID("Fillet");
+    return MY_ID;
+  }
+
+  /// \return the kind of a feature.
+  FEATURESPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = FeaturesPlugin_Fillet::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_SINGLE_RADIUS()
+  {
+    static std::string MY_SINGLE_RADIUS("fixed_radius");
+    return MY_SINGLE_RADIUS;
+  }
+
+  inline static const std::string CREATION_METHOD_VARYING_RADIUS()
+  {
+    static std::string MY_VARYING_RADIUS("variable_radius");
+    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 start radius.
+  inline static const std::string& START_RADIUS_ID()
+  {
+    static const std::string MY_START_RADIUS_ID("radius1");
+    return MY_START_RADIUS_ID;
+  }
+
+  /// Attribute name of end radius.
+  inline static const std::string& END_RADIUS_ID()
+  {
+    static const std::string MY_END_RADIUS_ID("radius2");
+    return MY_END_RADIUS_ID;
+  }
+
+  /// Attribute name of a radius for fillet with fixed radius.
+  inline static const std::string& RADIUS_ID()
+  {
+    return START_RADIUS_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_Fillet();
+
+private:
+  /// Check algorithm is finished correctly and store error otherwise
+  bool isFailed(const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgorithm);
+
+  /// 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 ListOfShape& theFilletShapes,
+                    const std::shared_ptr<GeomAPI_Shape> theResultShape,
+                    const std::shared_ptr<GeomAlgoAPI_MakeShape>& theMakeShape);
+};
+
+#endif
index 32746de99dffb1d7e8e68ffbebc66b5633cfa45e..45af5b97c9b84cf36168ab0d9110ec27ec5321a2 100644 (file)
@@ -26,7 +26,7 @@ class FeaturesPlugin_MultiRotation : public ModelAPI_Feature
   /// Multi-rotation kind.
   inline static const std::string& ID()
   {
-    static const std::string MY_MULTIROTATION_ID("MultiRotation");
+    static const std::string MY_MULTIROTATION_ID("AngularCopy");
     return MY_MULTIROTATION_ID;
   }
 
index 480d89931f9a5a5d1c577bc1b94370ac11ab51d4..4edeb695f7432a0703e4e84d78c4432ebaae7ec3 100644 (file)
@@ -38,7 +38,7 @@ class FeaturesPlugin_MultiTranslation : public ModelAPI_Feature
   /// Multi-translation kind.
   inline static const std::string& ID()
   {
-    static const std::string MY_MULTITRANSLATION_ID("MultiTranslation");
+    static const std::string MY_MULTITRANSLATION_ID("LinearCopy");
     return MY_MULTITRANSLATION_ID;
   }
 
index 954a0fb3c6786f30618271f2d7055b038dd8eea9..b9760dc07027ad7c55a7d4a85171ae343ad62659 100644 (file)
@@ -24,6 +24,7 @@
 #include <FeaturesPlugin_Extrusion.h>
 #include <FeaturesPlugin_ExtrusionCut.h>
 #include <FeaturesPlugin_ExtrusionFuse.h>
+#include <FeaturesPlugin_Fillet.h>
 #include <FeaturesPlugin_Intersection.h>
 #include <FeaturesPlugin_MultiRotation.h>
 #include <FeaturesPlugin_MultiTranslation.h>
@@ -84,6 +85,8 @@ FeaturesPlugin_Plugin::FeaturesPlugin_Plugin()
                               new FeaturesPlugin_ValidatorUnionArguments);
   aFactory->registerValidator("FeaturesPlugin_ValidatorConcealedResult",
                               new FeaturesPlugin_ValidatorConcealedResult);
+  aFactory->registerValidator("FeaturesPlugin_ValidatorFilletSelection",
+                              new FeaturesPlugin_ValidatorFilletSelection);
 
   // register this plugin
   ModelAPI_Session::get()->registerPlugin(this);
@@ -131,6 +134,8 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(std::string theFeatureID)
     return FeaturePtr(new FeaturesPlugin_MultiTranslation);
   } else if (theFeatureID == FeaturesPlugin_MultiRotation::ID()) {
     return FeaturePtr(new FeaturesPlugin_MultiRotation);
+  } else if (theFeatureID == FeaturesPlugin_Fillet::ID()) {
+    return FeaturePtr(new FeaturesPlugin_Fillet);
   }
 
   // feature of such kind is not found
index 66bef610ccf6784882a93a7291050995f306fa57..76683a26fa5a866c2e57a40affcf19d468a82cdd 100644 (file)
@@ -166,6 +166,7 @@ void FeaturesPlugin_Union::execute()
     aMakeShapeList.appendAlgo(aFillerAlgo);
     aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
   }
+  // workaround: make copy to name edges correctly
 
   // Store result and naming.
   const int aModifyEdgeTag = 1;
@@ -173,17 +174,20 @@ void FeaturesPlugin_Union::execute()
   const int aDeletedTag = 3;
   /// sub solids will be placed at labels 4, 5 etc. if result is compound of solids
   const int aSubsolidsTag = 4;
-  const std::string aModName = "Modified";
+  const std::string aModEName = "Modified_Edge";
+  const std::string aModFName = "Modified_Face";
 
   std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data());
   aResultBody->storeModified(anObjects.front(), aShape, aSubsolidsTag);
 
   for(ListOfShape::const_iterator anIter = anObjects.begin(); anIter != anObjects.end(); ++anIter) {
     aResultBody->loadAndOrientModifiedShapes(&aMakeShapeList, *anIter, GeomAPI_Shape::EDGE,
-                                             aModifyEdgeTag, aModName, aMapOfShapes);
+                                             aModifyEdgeTag, aModEName, aMapOfShapes,
+                                             true, false, true);
     aResultBody->loadAndOrientModifiedShapes(&aMakeShapeList, *anIter, GeomAPI_Shape::FACE,
-                                             aModifyFaceTag, aModName, aMapOfShapes);
-    aResultBody->loadDeletedShapes(&aMakeShapeList, *anIter, GeomAPI_Shape::FACE, aDeletedTag);
+                                             aModifyFaceTag, aModFName, aMapOfShapes,
+                                             true, false, true);
+    //aResultBody->loadDeletedShapes(&aMakeShapeList, *anIter, GeomAPI_Shape::FACE, aDeletedTag);
   }
 
   setResult(aResultBody);
index 853037100234b21d18cd5330d293e58593c780bd..41fcdc65288f4bfb88ae06a93976034d32033a36 100644 (file)
@@ -629,32 +629,82 @@ bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAt
       return false;
     }
 
-    int aShapeType = aShape->shapeType();
+    GeomAPI_Shape::ShapeType aShapeType = aShape->shapeType();
+    std::set<GeomAPI_Shape::ShapeType> anAllowedTypes;
     if(anOperationType == FeaturesPlugin_Boolean::BOOL_FUSE) {
-      // Fuse operation. Allow to select edges, faces and solids.
-      if(aShapeType != GeomAPI_Shape::EDGE &&
-         aShapeType != GeomAPI_Shape::FACE &&
-         aShapeType != GeomAPI_Shape::SOLID &&
-         aShapeType != GeomAPI_Shape::COMPSOLID &&
-         aShapeType != GeomAPI_Shape::COMPOUND) {
-        theError = "Error: Selected shape has the wrong type.";
-        return false;
-      }
+      anAllowedTypes.insert(GeomAPI_Shape::EDGE);
+      anAllowedTypes.insert(GeomAPI_Shape::FACE);
+      anAllowedTypes.insert(GeomAPI_Shape::SOLID);
+      anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
+      anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
     } else if (anOperationType == FeaturesPlugin_Boolean::BOOL_FILL) {
-      if(aShapeType != GeomAPI_Shape::FACE &&
-         aShapeType != GeomAPI_Shape::SOLID &&
-         aShapeType != GeomAPI_Shape::COMPSOLID &&
-         aShapeType != GeomAPI_Shape::COMPOUND) {
-        theError = "Error: Selected shape has the wrong type.";
-        return false;
-      }
+      anAllowedTypes.insert(GeomAPI_Shape::VERTEX);
+      anAllowedTypes.insert(GeomAPI_Shape::EDGE);
+      anAllowedTypes.insert(GeomAPI_Shape::WIRE);
+      anAllowedTypes.insert(GeomAPI_Shape::FACE);
+      anAllowedTypes.insert(GeomAPI_Shape::SHELL);
+      anAllowedTypes.insert(GeomAPI_Shape::SOLID);
+      anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
+      anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
     } else {
-      if(aShapeType != GeomAPI_Shape::SOLID &&
-         aShapeType != GeomAPI_Shape::COMPSOLID &&
-         aShapeType != GeomAPI_Shape::COMPOUND) {
-        theError = "Error: Selected shape has the wrong type.";
-        return false;
-      }
+      anAllowedTypes.insert(GeomAPI_Shape::SOLID);
+      anAllowedTypes.insert(GeomAPI_Shape::COMPSOLID);
+      anAllowedTypes.insert(GeomAPI_Shape::COMPOUND);
+    }
+
+    if(anAllowedTypes.find(aShapeType) == anAllowedTypes.end()
+      || (aResultConstruction.get() && aShapeType != GeomAPI_Shape::FACE)) {
+      theError = "Error: Selected shape has the wrong type.";
+      return false;
+    }
+
+  }
+
+  return true;
+}
+
+//==================================================================================================
+bool FeaturesPlugin_ValidatorFilletSelection::isValid(const AttributePtr& theAttribute,
+                                                      const std::list<std::string>& theArguments,
+                                                      Events_InfoMessage& theError) const
+{
+  AttributeSelectionListPtr anAttrSelectionList =
+    std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+  if(!anAttrSelectionList.get()) {
+    theError =
+      "Error: This validator can only work with selection list attributes in \"Fillet\" feature.";
+    return false;
+  }
+
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
+  // Check all selected entities are sub-shapes of single solid
+  GeomShapePtr aBaseSolid;
+  for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
+    AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
+    if(!anAttrSelection.get()) {
+      theError = "Error: Empty attribute selection.";
+      return false;
+    }
+    ResultPtr aContext = anAttrSelection->context();
+    if(!aContext.get()) {
+      theError = "Error: Empty selection context.";
+      return false;
+    }
+
+    ResultCompSolidPtr aContextOwner = ModelAPI_Tools::compSolidOwner(aContext);
+    GeomShapePtr anOwner = aContextOwner.get() ? aContextOwner->shape() : aContext->shape();
+
+    if (anOwner->shapeType() != GeomAPI_Shape::SOLID &&
+        anOwner->shapeType() != GeomAPI_Shape::COMPSOLID) {
+      theError = "Error: Not all selected shapes are sub-shapes of solids";
+      return false;
+    }
+
+    if (!aBaseSolid)
+      aBaseSolid = anOwner;
+    else if (!aBaseSolid->isEqual(anOwner)) {
+      theError = "Error: Sub-shapes of different solids have been selected.";
+      return false;
     }
   }
 
@@ -846,6 +896,10 @@ bool FeaturesPlugin_ValidatorUnionSelection::isValid(const AttributePtr& theAttr
     bool isSameFound = false;
     AttributeSelectionPtr anAttrSelectionInList = aBaseObjectsAttrList->value(anIndex);
     ResultPtr aContext = anAttrSelectionInList->context();
+    if (!aContext.get()) {
+      theError = "Error: selection is invalid.";
+      return false;
+    }
 
     ResultConstructionPtr aConstruction =
       std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
index d8c0a091e1a1e6ae1c09c17d7ce2cad7ba754b25..62edcb2bf7fdf7fa8128a2f809a02cd117c6fea8 100644 (file)
@@ -152,6 +152,22 @@ public:
                        Events_InfoMessage& theError) const;
 };
 
+/// \class FeaturesPlugin_ValidatorFilletSelection
+/// \ingroup Validators
+/// \brief Validates selection for fillet operation.
+class FeaturesPlugin_ValidatorFilletSelection: public ModelAPI_AttributeValidator
+{
+public:
+  /// \return True if the attribute is valid. It checks whether the selection
+  /// is acceptable for boolean operation.
+  /// \param[in] theAttribute an attribute to check.
+  /// \param[in] theArguments a filter parameters.
+  /// \param[out] theError error message.
+  virtual bool isValid(const AttributePtr& theAttribute,
+                       const std::list<std::string>& theArguments,
+                       Events_InfoMessage& theError) const;
+};
+
 /// \class FeaturesPlugin_ValidatorPartitionSelection
 /// \ingroup Validators
 /// \brief Validates selection for partition.
index 4364f9ebf65708eb19890cbd3e4d2a7da3d10cd9..a9224658b368932c2b511a233b3e0ce5ab92831a 100644 (file)
@@ -97,38 +97,38 @@ SketchConstraintCoincidence_18 = Sketch_1.setCoincident(SketchPoint_12.coordinat
 model.do()
 Vertex_1 = model.addVertex(Part_1_doc, [model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_6s-SketchLine_5e"), model.selection("VERTEX", "Sketch_1/Vertex-SketchPoint_7"), model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_5s-SketchLine_4e"), model.selection("VERTEX", "Sketch_1/Vertex-SketchPoint_11"), model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_3s-SketchLine_2e"), model.selection("VERTEX", "Sketch_1/Vertex-SketchPoint_10"), model.selection("VERTEX", "Sketch_1/Vertex-SketchPoint_8"), model.selection("VERTEX", "Sketch_1/Vertex-SketchPoint_9"), model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_2s-SketchLine_1e"), model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_4s-SketchLine_3e"), model.selection("VERTEX", "Sketch_1/Vertex-SketchPoint_13"), model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_1s-SketchLine_6e"), model.selection("VERTEX", "Sketch_1/Vertex-SketchPoint_14"), model.selection("VERTEX", "Sketch_1/Vertex-SketchPoint_2"), model.selection("VERTEX", "Sketch_1/Vertex-SketchPoint_6"), model.selection("VERTEX", "Sketch_1/Vertex-SketchPoint_1"), model.selection("VERTEX", "Sketch_1/Vertex-SketchPoint_4"), model.selection("VERTEX", "Sketch_1/Vertex-SketchPoint_5")])
 Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("VERTEX", "Vertex_1_1"), model.selection("VERTEX", "Vertex_1_2"), model.selection("VERTEX", "Vertex_1_3"), model.selection("VERTEX", "Vertex_1_4"), model.selection("VERTEX", "Vertex_1_5"), model.selection("VERTEX", "Vertex_1_6"), model.selection("VERTEX", "Vertex_1_7"), model.selection("VERTEX", "Vertex_1_8"), model.selection("VERTEX", "Vertex_1_9"), model.selection("VERTEX", "Vertex_1_10"), model.selection("VERTEX", "Vertex_1_11"), model.selection("VERTEX", "Vertex_1_12"), model.selection("VERTEX", "Vertex_1_13"), model.selection("VERTEX", "Vertex_1_14"), model.selection("VERTEX", "Vertex_1_15"), model.selection("VERTEX", "Vertex_1_16"), model.selection("VERTEX", "Vertex_1_17"), model.selection("VERTEX", "Vertex_1_18")], model.selection("EDGE", "PartSet/OZ"), 100, 0)
-Plane_4 = model.addPlane(Part_1_doc, model.selection("VERTEX", "Vertex_1_12/To_Vertex_1"), model.selection("VERTEX", "Vertex_1_13/To_Vertex_1"), model.selection("VERTEX", "Vertex_1_3/To_Vertex_1"))
+Plane_4 = model.addPlane(Part_1_doc, model.selection("VERTEX", "Extrusion_1_12/To_Vertex_1"), model.selection("VERTEX", "Extrusion_1_13/To_Vertex_1"), model.selection("VERTEX", "Extrusion_1_3/To_Vertex_1"))
 Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
 SketchLine_7 = Sketch_2.addLine(-717.0963364993213, -45.06817090071282, -717.0963364993213, -180.9380775505473)
-SketchPoint_13 = Sketch_2.addPoint(model.selection("VERTEX", "Vertex_1_12/To_Vertex_1"))
+SketchPoint_13 = Sketch_2.addPoint(model.selection("VERTEX", "Extrusion_1_12/To_Vertex_1"))
 SketchPoint_13.setName("SketchPoint_15")
 SketchPoint_13.result().setName("SketchPoint_15")
 SketchConstraintCoincidence_19 = Sketch_2.setCoincident(SketchLine_7.startPoint(), SketchPoint_13.result())
-SketchPoint_14 = Sketch_2.addPoint(model.selection("VERTEX", "Vertex_1_1/To_Vertex_1"))
+SketchPoint_14 = Sketch_2.addPoint(model.selection("VERTEX", "Extrusion_1_1/To_Vertex_1"))
 SketchPoint_14.setName("SketchPoint_16")
 SketchPoint_14.result().setName("SketchPoint_16")
 SketchConstraintCoincidence_20 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchPoint_14.result())
 SketchLine_8 = Sketch_2.addLine(-717.0963364993213, -180.9380775505473, -102.0809741405142, -180.9380775505473)
 SketchConstraintCoincidence_21 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
-SketchPoint_15 = Sketch_2.addPoint(model.selection("VERTEX", "Vertex_1_3/To_Vertex_1"))
+SketchPoint_15 = Sketch_2.addPoint(model.selection("VERTEX", "Extrusion_1_3/To_Vertex_1"))
 SketchPoint_15.setName("SketchPoint_17")
 SketchPoint_15.result().setName("SketchPoint_17")
 SketchConstraintCoincidence_22 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchPoint_15.result())
 SketchLine_9 = Sketch_2.addLine(-102.0809741405142, -180.9380775505473, -102.0809741405142, 193.0685819822336)
 SketchConstraintCoincidence_23 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
-SketchPoint_16 = Sketch_2.addPoint(model.selection("VERTEX", "Vertex_1_10/To_Vertex_1"))
+SketchPoint_16 = Sketch_2.addPoint(model.selection("VERTEX", "Extrusion_1_10/To_Vertex_1"))
 SketchPoint_16.setName("SketchPoint_18")
 SketchPoint_16.result().setName("SketchPoint_18")
 SketchConstraintCoincidence_24 = Sketch_2.setCoincident(SketchLine_9.endPoint(), SketchPoint_16.result())
 SketchLine_10 = Sketch_2.addLine(-102.0809741405142, 193.0685819822336, -254.8675173043772, 193.0685819822336)
 SketchConstraintCoincidence_25 = Sketch_2.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint())
-SketchPoint_17 = Sketch_2.addPoint(model.selection("VERTEX", "Vertex_1_5/To_Vertex_1"))
+SketchPoint_17 = Sketch_2.addPoint(model.selection("VERTEX", "Extrusion_1_5/To_Vertex_1"))
 SketchPoint_17.setName("SketchPoint_19")
 SketchPoint_17.result().setName("SketchPoint_19")
 SketchConstraintCoincidence_26 = Sketch_2.setCoincident(SketchLine_10.endPoint(), SketchPoint_17.result())
 SketchLine_11 = Sketch_2.addLine(-254.8675173043772, 193.0685819822336, -254.8675173043772, -45.06817090071281)
 SketchConstraintCoincidence_27 = Sketch_2.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint())
-SketchPoint_18 = Sketch_2.addPoint(model.selection("VERTEX", "Vertex_1_9/To_Vertex_1"))
+SketchPoint_18 = Sketch_2.addPoint(model.selection("VERTEX", "Extrusion_1_9/To_Vertex_1"))
 SketchPoint_18.setName("SketchPoint_20")
 SketchPoint_18.result().setName("SketchPoint_20")
 SketchConstraintCoincidence_28 = Sketch_2.setCoincident(SketchLine_11.endPoint(), SketchPoint_18.result())
@@ -138,16 +138,16 @@ SketchConstraintCoincidence_30 = Sketch_2.setCoincident(SketchLine_7.startPoint(
 SketchConstraintCoincidence_31 = Sketch_2.setCoincident(SketchPoint_13.coordinates(), SketchLine_12.endPoint())
 SketchLine_13 = Sketch_2.addLine(-599.2405881202537, -45.06817090071282, -584.124830393487, -180.9380775505472)
 SketchConstraintCoincidence_32 = Sketch_2.setCoincident(SketchLine_13.startPoint(), SketchLine_12.result())
-SketchPoint_19 = Sketch_2.addPoint(model.selection("VERTEX", "Vertex_1_13/To_Vertex_1"))
+SketchPoint_19 = Sketch_2.addPoint(model.selection("VERTEX", "Extrusion_1_13/To_Vertex_1"))
 SketchPoint_19.setName("SketchPoint_21")
 SketchPoint_19.result().setName("SketchPoint_21")
 SketchConstraintCoincidence_33 = Sketch_2.setCoincident(SketchLine_13.endPoint(), SketchPoint_19.result())
 SketchLine_14 = Sketch_2.addLine(-356.1736770691994, -45.06817090071282, -342.6051560379917, -180.9380775505472)
-SketchPoint_20 = Sketch_2.addPoint(model.selection("VERTEX", "Vertex_1_15/To_Vertex_1"))
+SketchPoint_20 = Sketch_2.addPoint(model.selection("VERTEX", "Extrusion_1_15/To_Vertex_1"))
 SketchPoint_20.setName("SketchPoint_22")
 SketchPoint_20.result().setName("SketchPoint_22")
 SketchConstraintCoincidence_34 = Sketch_2.setCoincident(SketchLine_14.startPoint(), SketchPoint_20.result())
-SketchPoint_21 = Sketch_2.addPoint(model.selection("VERTEX", "Vertex_1_11/To_Vertex_1"))
+SketchPoint_21 = Sketch_2.addPoint(model.selection("VERTEX", "Extrusion_1_11/To_Vertex_1"))
 SketchPoint_21.setName("SketchPoint_23")
 SketchPoint_21.result().setName("SketchPoint_23")
 SketchConstraintCoincidence_35 = Sketch_2.setCoincident(SketchLine_14.endPoint(), SketchPoint_21.result())
@@ -161,7 +161,7 @@ Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-Sketc
 Face_2 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchLine_8f-SketchLine_12f-SketchLine_13f-SketchLine_14r")])
 Face_3 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchLine_8f-SketchLine_9f-SketchLine_12f-SketchLine_14f-SketchLine_15r")])
 Face_4 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchLine_9f-SketchLine_10f-SketchLine_11f-SketchLine_15f")])
-Partition_1 = model.addPartition(Part_1_doc, [model.selection("EDGE", "Vertex_1_1"), model.selection("EDGE", "Vertex_1_2"), model.selection("EDGE", "Vertex_1_3"), model.selection("EDGE", "Vertex_1_4"), model.selection("EDGE", "Vertex_1_5"), model.selection("EDGE", "Vertex_1_6"), model.selection("EDGE", "Vertex_1_7"), model.selection("EDGE", "Vertex_1_8"), model.selection("EDGE", "Vertex_1_9"), model.selection("EDGE", "Vertex_1_10"), model.selection("EDGE", "Vertex_1_11"), model.selection("EDGE", "Vertex_1_12"), model.selection("EDGE", "Vertex_1_13"), model.selection("EDGE", "Vertex_1_14"), model.selection("EDGE", "Vertex_1_15"), model.selection("EDGE", "Vertex_1_16"), model.selection("EDGE", "Vertex_1_17"), model.selection("EDGE", "Vertex_1_18"), model.selection("FACE", "Face_1_1"), model.selection("FACE", "Face_2_1"), model.selection("FACE", "Face_3_1"), model.selection("FACE", "Face_4_1")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("EDGE", "Extrusion_1_1"), model.selection("EDGE", "Extrusion_1_2"), model.selection("EDGE", "Extrusion_1_3"), model.selection("EDGE", "Extrusion_1_4"), model.selection("EDGE", "Extrusion_1_5"), model.selection("EDGE", "Extrusion_1_6"), model.selection("EDGE", "Extrusion_1_7"), model.selection("EDGE", "Extrusion_1_8"), model.selection("EDGE", "Extrusion_1_9"), model.selection("EDGE", "Extrusion_1_10"), model.selection("EDGE", "Extrusion_1_11"), model.selection("EDGE", "Extrusion_1_12"), model.selection("EDGE", "Extrusion_1_13"), model.selection("EDGE", "Extrusion_1_14"), model.selection("EDGE", "Extrusion_1_15"), model.selection("EDGE", "Extrusion_1_16"), model.selection("EDGE", "Extrusion_1_17"), model.selection("EDGE", "Extrusion_1_18"), model.selection("FACE", "Face_1_1"), model.selection("FACE", "Face_2_1"), model.selection("FACE", "Face_3_1"), model.selection("FACE", "Face_4_1")])
 model.end()
 PartitionFeature = Partition_1.feature()
 assert(len(PartitionFeature.results()) == 1)
index fedf186b2b0db66711ae62105d7c61b3e9e334ba..93272c18752581d0a4de093c5d518a8128ddfdc8 100644 (file)
@@ -181,7 +181,7 @@ Recover_1 = model.addRecover(Part_1_doc, Partition_1, [Revolution_1.result()])
 Plane_5 = model.addPlane(Part_1_doc, model.selection("EDGE", "PartSet/Axis_4"), model.selection("VERTEX", "PartSet/Point_2"), True)
 Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchArc_2_2"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_4"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_5"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_6"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_7"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_8"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_2")])
 Intersection_1 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Recover_1_1")], [model.selection("FACE", "Face_1_1")])
-Group_1 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "Recover_1_1/Modified_Vertex_2_1"), model.selection("VERTEX", "Recover_1_1/Generated_Vertex_2"), model.selection("VERTEX", "Recover_1_1/Modified_Vertex_6_1"), model.selection("VERTEX", "Recover_1_1/Modified_Vertex_4_1"), model.selection("VERTEX", "Recover_1_1/Generated_Vertex_3"), model.selection("VERTEX", "Recover_1_1/Generated_Vertex_1"), model.selection("VERTEX", "Recover_1_1/Modified_Vertex_1_1"), model.selection("VERTEX", "Recover_1_1/Generated_Vertex_4"), model.selection("VERTEX", "Recover_1_1/Modified_Vertex_3_1"), model.selection("VERTEX", "Recover_1_1/Modified_Vertex_7_1"), model.selection("VERTEX", "Recover_1_1/Modified_Vertex_5_1")])
+Group_1 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "Intersection_1_1/Modified_Vertex_2_1"), model.selection("VERTEX", "Intersection_1_1/Generated_Vertex_2"), model.selection("VERTEX", "Intersection_1_1/Modified_Vertex_6_1"), model.selection("VERTEX", "Intersection_1_1/Modified_Vertex_4_1"), model.selection("VERTEX", "Intersection_1_1/Generated_Vertex_3"), model.selection("VERTEX", "Intersection_1_1/Generated_Vertex_1"), model.selection("VERTEX", "Intersection_1_1/Modified_Vertex_1_1"), model.selection("VERTEX", "Intersection_1_1/Generated_Vertex_4"), model.selection("VERTEX", "Intersection_1_1/Modified_Vertex_3_1"), model.selection("VERTEX", "Intersection_1_1/Modified_Vertex_7_1"), model.selection("VERTEX", "Intersection_1_1/Modified_Vertex_5_1")])
 Group_2 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Intersection_1_1_7"), model.selection("EDGE", "Intersection_1_1_6"), model.selection("EDGE", "Intersection_1_1_3"), model.selection("EDGE", "Intersection_1_1_11"), model.selection("EDGE", "Intersection_1_1_5"), model.selection("EDGE", "Intersection_1_1_1"), model.selection("EDGE", "Intersection_1_1_4"), model.selection("EDGE", "Intersection_1_1_2"), model.selection("EDGE", "Intersection_1_1_10"), model.selection("EDGE", "Intersection_1_1_9"), model.selection("EDGE", "Intersection_1_1_8")])
 model.end()
 
index 8ac55527ffb0473eb98c92e906e3242153f15dd9..d025a0785c569201a8cd6a0b02a8351136881594 100644 (file)
@@ -55,7 +55,7 @@ SketchConstraintVertical_4 = Sketch_2.setVertical(SketchLine_8.result())
 model.do()
 Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_5f-SketchLine_6f-SketchLine_7f-SketchLine_8f")], model.selection(), 10, 110)
 Intersection_1 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], [model.selection("SOLID", "Extrusion_2_1")])
-Rotation_1 = model.addRotation(Part_1_doc, [model.selection("COMPOUND", "Extrusion_1_1")], model.selection("EDGE", "PartSet/OZ"), 45)
+Rotation_1 = model.addRotation(Part_1_doc, [model.selection("COMPOUND", "Intersection_1_1")], model.selection("EDGE", "PartSet/OZ"), 45)
 model.end()
 
 assert(model.checkPythonDump())
index 6d1aca8b6fa4c1c39e427e7381763b7e333151e0..8a98df7e97ba911ace53474ea0d8a316dee7599d 100644 (file)
@@ -40,9 +40,9 @@ model.do()
 Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchLine_2f-SketchLine_5r")], model.selection(), 100, 0)
 Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_3f-SketchLine_4f-SketchLine_5f")], model.selection(), 100, 0)
 Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], model.selection("EDGE", "PartSet/OX"), 50)
-Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_2_1")])
-Translation_2 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Extrusion_1_1")], model.selection("EDGE", "PartSet/OZ"), 50)
-Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Extrusion_1_1/Translated_Face_24"), model.selection("FACE", "Extrusion_1_1/Translated_Face_13"), model.selection("FACE", "Extrusion_1_1/Translated_Face_16"), model.selection("FACE", "Extrusion_1_1/Translated_Face_12"), model.selection("FACE", "Extrusion_1_1/Translated_Face_9"), model.selection("FACE", "Extrusion_1_1/Translated_Face_10"), model.selection("FACE", "Extrusion_1_1/Translated_Face_11"), model.selection("FACE", "Extrusion_1_1/Translated_Face_25"), model.selection("FACE", "Extrusion_1_1/Translated_Face_20"), model.selection("FACE", "Extrusion_1_1/Translated_Face_19"), model.selection("FACE", "Extrusion_1_1/Translated_Face_18"), model.selection("FACE", "Extrusion_1_1/Translated_Face_27"), model.selection("FACE", "Extrusion_1_1/Translated_Face_17"), model.selection("FACE", "Extrusion_1_1/Translated_Face_31"), model.selection("FACE", "Extrusion_1_1/Translated_Face_32"), model.selection("FACE", "Extrusion_1_1/Translated_Face_30"), model.selection("FACE", "Extrusion_1_1/Translated_Face_28"), model.selection("FACE", "Extrusion_1_1/Translated_Face_29"), model.selection("FACE", "Extrusion_1_1/Translated_Face_8"), model.selection("FACE", "Extrusion_1_1/Translated_Face_22"), model.selection("FACE", "Extrusion_1_1/Translated_Face_7"), model.selection("FACE", "Extrusion_1_1/Translated_Face_6"), model.selection("FACE", "Extrusion_1_1/Translated_Face_5"), model.selection("FACE", "Extrusion_1_1/Translated_Face_3"), model.selection("FACE", "Extrusion_1_1/Translated_Face_1"), model.selection("FACE", "Extrusion_1_1/Translated_Face_2"), model.selection("FACE", "Extrusion_1_1/Translated_Face_21"), model.selection("FACE", "Extrusion_1_1/Translated_Face_4"), model.selection("FACE", "Extrusion_1_1/Translated_Face_25"), model.selection("FACE", "Extrusion_1_1/Translated_Face_27"), model.selection("FACE", "Extrusion_1_1/Translated_Face_21"), model.selection("FACE", "Extrusion_1_1/Translated_Face_22"), model.selection("FACE", "Extrusion_1_1/Translated_Face_26"), model.selection("FACE", "Extrusion_1_1/Translated_Face_23"), model.selection("FACE", "Extrusion_1_1/Translated_Face_30"), model.selection("FACE", "Extrusion_1_1/Translated_Face_23"), model.selection("FACE", "Extrusion_1_1/Translated_Face_14"), model.selection("FACE", "Extrusion_1_1/Translated_Face_15")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Translation_1_1"), model.selection("SOLID", "Extrusion_2_1")])
+Translation_2 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Partition_1_1")], model.selection("EDGE", "PartSet/OZ"), 50)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Translation_2_1/Translated_Face_24"), model.selection("FACE", "Translation_2_1/Translated_Face_13"), model.selection("FACE", "Translation_2_1/Translated_Face_16"), model.selection("FACE", "Translation_2_1/Translated_Face_12"), model.selection("FACE", "Translation_2_1/Translated_Face_9"), model.selection("FACE", "Translation_2_1/Translated_Face_10"), model.selection("FACE", "Translation_2_1/Translated_Face_11"), model.selection("FACE", "Translation_2_1/Translated_Face_25"), model.selection("FACE", "Translation_2_1/Translated_Face_20"), model.selection("FACE", "Translation_2_1/Translated_Face_19"), model.selection("FACE", "Translation_2_1/Translated_Face_18"), model.selection("FACE", "Translation_2_1/Translated_Face_27"), model.selection("FACE", "Translation_2_1/Translated_Face_17"), model.selection("FACE", "Translation_2_1/Translated_Face_31"), model.selection("FACE", "Translation_2_1/Translated_Face_32"), model.selection("FACE", "Translation_2_1/Translated_Face_30"), model.selection("FACE", "Translation_2_1/Translated_Face_28"), model.selection("FACE", "Translation_2_1/Translated_Face_29"), model.selection("FACE", "Translation_2_1/Translated_Face_8"), model.selection("FACE", "Translation_2_1/Translated_Face_22"), model.selection("FACE", "Translation_2_1/Translated_Face_7"), model.selection("FACE", "Translation_2_1/Translated_Face_6"), model.selection("FACE", "Translation_2_1/Translated_Face_5"), model.selection("FACE", "Translation_2_1/Translated_Face_3"), model.selection("FACE", "Translation_2_1/Translated_Face_1"), model.selection("FACE", "Translation_2_1/Translated_Face_2"), model.selection("FACE", "Translation_2_1/Translated_Face_21"), model.selection("FACE", "Translation_2_1/Translated_Face_4"), model.selection("FACE", "Translation_2_1/Translated_Face_25"), model.selection("FACE", "Translation_2_1/Translated_Face_27"), model.selection("FACE", "Translation_2_1/Translated_Face_21"), model.selection("FACE", "Translation_2_1/Translated_Face_22"), model.selection("FACE", "Translation_2_1/Translated_Face_26"), model.selection("FACE", "Translation_2_1/Translated_Face_23"), model.selection("FACE", "Translation_2_1/Translated_Face_30"), model.selection("FACE", "Translation_2_1/Translated_Face_23"), model.selection("FACE", "Translation_2_1/Translated_Face_14"), model.selection("FACE", "Translation_2_1/Translated_Face_15")])
 #Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Translation_2_1_6/Translated_Face_1"), model.selection("FACE", "Translation_2_1_5/Translated_Face_1"), model.selection("FACE", "Translation_2_1_5/Translated_Face_4"), model.selection("FACE", "Translation_2_1_4/Translated_Face_4"), model.selection("FACE", "Translation_2_1_5/Translated_Face_3"), model.selection("FACE", "Translation_2_1_5/Translated_Face_2"), model.selection("FACE", "Translation_2_1_5/Translated_Face_5"), model.selection("FACE", "Translation_2_1_7/Translated_Face_5"), model.selection("FACE", "Translation_2_1_6/Translated_Face_5"), model.selection("FACE", "Translation_2_1_4/Translated_Face_1"), model.selection("FACE", "Translation_2_1_2/Translated_Face_2"), model.selection("FACE", "Translation_2_1_5/Translated_Face_5"), model.selection("FACE", "Translation_2_1_2/Translated_Face_1"), model.selection("FACE", "Translation_2_1_4/Translated_Face_5"), model.selection("FACE", "Translation_2_1_2/Translated_Face_3"), model.selection("FACE", "Translation_2_1_3/Translated_Face_5"), model.selection("FACE", "Translation_2_1_1/Translated_Face_3"), model.selection("FACE", "Translation_2_1_4/Translated_Face_2"), model.selection("FACE", "Translation_2_1_2/Translated_Face_3"), model.selection("FACE", "Translation_2_1_1/Translated_Face_4"), model.selection("FACE", "Translation_2_1_1/Translated_Face_1"), model.selection("FACE", "Translation_2_1_1/Translated_Face_2"), model.selection("FACE", "Translation_2_1_3/Translated_Face_4"), model.selection("FACE", "Translation_2_1_4/Translated_Face_3"), model.selection("FACE", "Translation_2_1_3/Translated_Face_5"), model.selection("FACE", "Translation_2_1_3/Translated_Face_2"), model.selection("FACE", "Translation_2_1_3/Translated_Face_3"), model.selection("FACE", "Translation_2_1_3/Translated_Face_1"), model.selection("FACE", "Translation_2_1_7/Translated_Face_3"), model.selection("FACE", "Translation_2_1_7/Translated_Face_5"), model.selection("FACE", "Translation_2_1_7/Translated_Face_4"), model.selection("FACE", "Translation_2_1_7/Translated_Face_1"), model.selection("FACE", "Translation_2_1_7/Translated_Face_2"), model.selection("FACE", "Translation_2_1_6/Translated_Face_4"), model.selection("FACE", "Translation_2_1_4/Translated_Face_5"), model.selection("FACE", "Translation_2_1_6/Translated_Face_5"), model.selection("FACE", "Translation_2_1_6/Translated_Face_2"), model.selection("FACE", "Translation_2_1_6/Translated_Face_3")])
 
 model.end()
index ef5cdc48eb916dd4fc36c8a606610c55944d3fd3..72c1b77f1298b988b0dac10bd0ad60e4e2d47378 100644 (file)
@@ -33,7 +33,7 @@ Part_1 = model.addPart(partSet)
 Part_1_doc = Part_1.document()
 Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "PartSet/Sketch_1/Edge-SketchLine_1"), model.selection("EDGE", "PartSet/Sketch_1/Edge-SketchLine_2"), model.selection("EDGE", "PartSet/Sketch_1/Edge-SketchLine_3")])
 Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Wire_1_1")], model.selection(), 100, 0)
-Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Wire_1_1/Generated_Face_3"), model.selection("FACE", "Wire_1_1/Generated_Face_2"), model.selection("FACE", "Wire_1_1/Generated_Face_1")])
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Extrusion_1_1/Generated_Face_3"), model.selection("FACE", "Extrusion_1_1/Generated_Face_2"), model.selection("FACE", "Extrusion_1_1/Generated_Face_1")])
 model.do()
 model.end()
 
index 855ae61e1abf747502e96142b3db086f1f85b7ea..fc260d3309b9ea995759aa44a97db55d3337dcdf 100644 (file)
@@ -34,7 +34,7 @@ SketchCircle_3 = Sketch_2.addCircle(-41.97827733564338, 89.35676702647821, 6.102
 model.do()
 Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchCircle_2_2f"), model.selection("FACE", "Sketch_2/Face-SketchCircle_3_2f")], model.selection(), 10, 0)
 Boolean_1 = model.addSmash(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], [model.selection("SOLID", "Extrusion_2_1"), model.selection("SOLID", "Extrusion_2_2")])
-Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Extrusion_2_2/To_Face_1"), model.selection("FACE", "Extrusion_2_2/From_Face_1"), model.selection("FACE", "Extrusion_2_2/Generated_Face_1"), model.selection("FACE", "Extrusion_2_1/From_Face_1"), model.selection("FACE", "Boolean_1_1_1/Modified_1"), model.selection("FACE", "_Extrusion_1_1/From_Face_1"), model.selection("FACE", "_Extrusion_1_1/Generated_Face_1"), model.selection("FACE", "Extrusion_2_2/From_Face_1"), model.selection("FACE", "Extrusion_2_1/Generated_Face_1"), model.selection("FACE", "Extrusion_2_1/From_Face_1"), model.selection("FACE", "Extrusion_2_1/To_Face_1")])
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Extrusion_2_2/To_Face_1"), model.selection("FACE", "Extrusion_2_2/From_Face_1"), model.selection("FACE", "Extrusion_2_2/Generated_Face_1"), model.selection("FACE", "Extrusion_2_1/From_Face_1"), model.selection("FACE", "Boolean_1_1_1/Modified_Face_1"), model.selection("FACE", "Extrusion_1_1/From_Face_1"), model.selection("FACE", "Extrusion_1_1/Generated_Face_1"), model.selection("FACE", "Extrusion_2_2/From_Face_1"), model.selection("FACE", "Extrusion_2_1/Generated_Face_1"), model.selection("FACE", "Extrusion_2_1/From_Face_1"), model.selection("FACE", "Extrusion_2_1/To_Face_1")])
 model.do()
 model.end()
 
index 54e1020c31fa4780b9978153f57762b38512ff70..c32cd440b1ae8ed65e5f405a3d8a6f348eb7dc46 100644 (file)
@@ -29,9 +29,9 @@ SketchCircle_1 = Sketch_1.addCircle(-150, 80, 100)
 model.do()
 Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchCircle_1_2")])
 Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Face_1_1")], model.selection("EDGE", "PartSet/OZ"), 360, 0)
-Group_1 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Face_1_1/Base_Edge_1")])
-Group_2 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Face_1_1/Lateral_Edge_1")])
-Group_3 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "Face_1_1/Lateral_Edge_1&Face_1_1/Base_Edge_1")])
+Group_1 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Revolution_1_1/Base_Edge_1")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Revolution_1_1/Lateral_Edge_1")])
+Group_3 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "Revolution_1_1/Lateral_Edge_1&Revolution_1_1/Base_Edge_1")])
 model.end()
 
 # check that resulting group selection is valid
index bab4cc8ba57f36153a915d809d509ffe1375a3a5..48ce24cd719bbd0c10cd01a1535dbe32f4322f2a 100644 (file)
@@ -129,21 +129,17 @@ Face_5 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_3/Wire-Sketc
 MultiTranslation_1 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Face_5_1")], model.selection("EDGE", "Sketch_1/Edge-SketchLine_9"), "length_assemblage", 4, model.selection("EDGE", "PartSet/OY"), "length_assemblage", 2)
 Recover_1 = model.addRecover(Part_1_doc, MultiTranslation_1, [Face_5.result()])
 Translation_1 = model.addTranslation(Part_1_doc, [model.selection("FACE", "Recover_1_1")], model.selection("VERTEX", "Sketch_3/Vertex-SketchPoint_1-SketchLine_12s-SketchLine_11e"), model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_6s-SketchLine_5e"))
-Translation_1.result().setName("Translation_1_1")
 MultiTranslation_2 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Translation_1_1")], model.selection("EDGE", "PartSet/OX"), "length_assemblage", 4, model.selection("EDGE", "PartSet/OY"), "length_assemblage", 2)
 Recover_2 = model.addRecover(Part_1_doc, MultiTranslation_1, [Face_5.result()])
 Translation_2 = model.addTranslation(Part_1_doc, [model.selection("FACE", "Recover_2_1")], model.selection("VERTEX", "Sketch_3/Vertex-SketchPoint_1-SketchLine_12s-SketchLine_11e"), model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_4s-SketchLine_3e"))
-Translation_2.result().setName("Translation_2_1")
 MultiTranslation_3 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Translation_2_1")], model.selection("EDGE", "PartSet/OX"), "length_assemblage", 4)
 Recover_3 = model.addRecover(Part_1_doc, MultiTranslation_1, [Face_5.result()])
-Translation_3 = model.addTranslation(Part_1_doc, [model.selection("FACE", "Recover_3_1")], model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_9s-SketchLine_7e"), model.selection("VERTEX", "Translation_2_1/Translated_Edge_1_4&Translation_2_1/Translated_Edge_1_1"))
-Translation_3.result().setName("Translation_3_1")
+Translation_3 = model.addTranslation(Part_1_doc, [model.selection("FACE", "Recover_3_1")], model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_9s-SketchLine_7e"), model.selection("VERTEX", "LinearCopy_3_1/Translated_Edge_1_4&LinearCopy_3_1/Translated_Edge_1_1"))
 MultiTranslation_4 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Translation_3_1")], model.selection("EDGE", "PartSet/OX"), "length_assemblage", 3)
 Recover_4 = model.addRecover(Part_1_doc, MultiTranslation_1, [Face_5.result()])
 Translation_4 = model.addTranslation(Part_1_doc, [model.selection("FACE", "Recover_4_1")], model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_9s-SketchLine_7e"), model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_1s-SketchLine_10s"))
-Translation_4.result().setName("Translation_4_1")
 MultiTranslation_5 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Translation_4_1")], model.selection("EDGE", "PartSet/OX"), "length_assemblage", 2)
-Partition_2 = model.addPartition(Part_1_doc, [model.selection("COMPOUND", "Face_1_1"), model.selection("COMPOUND", "Face_5_1"), model.selection("COMPOUND", "Translation_1_1"), model.selection("COMPOUND", "Translation_2_1"), model.selection("COMPOUND", "Translation_3_1"), model.selection("COMPOUND", "Translation_4_1")])
+Partition_2 = model.addPartition(Part_1_doc, [model.selection("COMPOUND", "Partition_1_1"), model.selection("COMPOUND", "LinearCopy_1_1"), model.selection("COMPOUND", "LinearCopy_2_1"), model.selection("COMPOUND", "LinearCopy_3_1"), model.selection("COMPOUND", "LinearCopy_4_1"), model.selection("COMPOUND", "LinearCopy_5_1")])
 model.end()
 
 # check that partition constructed correctly
index be0c82b1dae52502a740d1952bff408aa2d5d6c0..c178e45ab6e5a74c8f21cb6c301ca77285661698 100644 (file)
@@ -39,7 +39,7 @@ SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchArc_1.startPoint(),
 model.do()
 Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchArc_1_2f-SketchLine_2f")], model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), 360, 0)
 Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Revolution_1_1")], model.selection("EDGE", "PartSet/OY"), 150)
-Group_1 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "Revolution_1_1/Translated_Vertex_1"), model.selection("VERTEX", "Revolution_1_1/Translated_Vertex_2")])
+Group_1 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "Translation_1_1/Translated_Vertex_1"), model.selection("VERTEX", "Translation_1_1/Translated_Vertex_2")])
 model.end()
 
 # check that resulting group selection is valid, names exist and different
index 6312d5989862ab61ad062469593e83d70e2adfaf..92193a3a5dc60c0862c855a8e02c4426fa96859c 100644 (file)
@@ -46,7 +46,7 @@ Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-Sketc
 Wire_2 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchCircle_1_2")])
 Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Wire_1_1")])
 Face_2 = model.addFace(Part_1_doc, [model.selection("WIRE", "Wire_2_1")])
-Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Wire_1_1"), model.selection("FACE", "Wire_2_1")], model.selection(), 50, 0)
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("FACE", "Face_2_1")], model.selection(), 50, 0)
 Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "PartSet/YOZ"))
 SketchLine_5 = Sketch_2.addLine(49.62901186301215, 25.3130971701971, 39.15939470736273, 25.3130971701971)
 SketchLine_6 = Sketch_2.addLine(39.15939470736273, 25.3130971701971, 39.15939470736273, 38.96586914453801)
@@ -61,7 +61,7 @@ SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_6.result())
 SketchConstraintHorizontal_4 = Sketch_2.setHorizontal(SketchLine_7.result())
 SketchConstraintVertical_4 = Sketch_2.setVertical(SketchLine_8.result())
 model.do()
-ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_5r-SketchLine_6r-SketchLine_7r-SketchLine_8r")], model.selection(), 50, 50, [model.selection("SOLID", "Wire_1_1"), model.selection("SOLID", "Wire_2_1")])
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_5r-SketchLine_6r-SketchLine_7r-SketchLine_8r")], model.selection(), 50, 50, [model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_1_2")])
 model.do()
 model.end()
 
index 7597676a7e2c8a0c481543909c424845f079bb7b..90675d37ee7b3e55bb1be7354093e9338da7818a 100644 (file)
@@ -49,7 +49,7 @@ Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-Sketc
 Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Wire_1_1")], model.selection(), 10, 0)
 model.do()
 
-model.testHaveNamingVertices(Extrusion_1, model, Part_1_doc)
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
 
 model.end()
 
diff --git a/src/FeaturesPlugin/Test/Test2377.py b/src/FeaturesPlugin/Test/Test2377.py
new file mode 100644 (file)
index 0000000..9457daa
--- /dev/null
@@ -0,0 +1,53 @@
+## Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-1.039451114922807, 35.51457975986278, -38.45969125214407, -21.30874785591767)
+SketchLine_2 = Sketch_1.addLine(-38.45969125214407, -21.30874785591767, 46.08233276157804, -21.30874785591767)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(46.08233276157804, -21.30874785591767, -1.039451114922807, 35.51457975986278)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchLine_2f-SketchLine_3f")], model.selection(), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_3"))
+SketchCircle_1 = Sketch_2.addCircle(-10.74792845018279, -51.46099937127247, 20.55678647017868)
+model.do()
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/OX"), model.selection("FACE", "PartSet/YOZ"), 0, model.selection(), 0)
+model.do()
+model.end()
+
+from GeomAPI import  GeomAPI_Shape
+
+model.testNbResults(Extrusion_2, 1)
+model.testNbSubResults(Extrusion_2, [0])
+model.testNbSubShapes(Extrusion_2, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_2, GeomAPI_Shape.FACE, [3])
+model.testNbSubShapes(Extrusion_2, GeomAPI_Shape.EDGE, [6])
+model.testNbSubShapes(Extrusion_2, GeomAPI_Shape.VERTEX, [12])
+model.testResultsVolumes(Extrusion_2, [36480.150452606350881978869438171])
+
+assert(model.checkPythonDump())
index dbc2670078209d7186d9d1449c318acf48c0ddf1..eeb22406402956a5b299d6f40175f0e17548a016 100644 (file)
@@ -52,8 +52,10 @@ SketchConstraintVertical_4 = Sketch_1.setVertical(SketchLine_8.result())
 model.do()
 Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), 100, 0)
 Boolean_1 = model.addFill(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1_2")], [model.selection("FACE", "PartSet/YOZ")])
-Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Boolean_1_1_4/Modified_3"), model.selection("FACE", "Boolean_1_1_4/Modified_Face_1"), model.selection("FACE", "_Extrusion_1_1/Generated_Face_9"), model.selection("FACE", "Boolean_1_1_4/Modified_2"), model.selection("FACE", "Boolean_1_1_4/Modified_4"), model.selection("FACE", "Boolean_1_1_4/Modified_1"), model.selection("FACE", "Boolean_1_1_4/Modified_3"), model.selection("FACE", "_Extrusion_1_1/Generated_Face_6"), model.selection("FACE", "Boolean_1_1_3/Modified_3"), model.selection("FACE", "_Extrusion_1_1/Generated_Face_7"), model.selection("FACE", "_Extrusion_1_1/Generated_Face_9"), model.selection("FACE", "Boolean_1_1_1/Modified_1"), model.selection("FACE", "_Extrusion_1_1/Generated_Face_5"), model.selection("FACE", "Boolean_1_1_4/Modified_4"), model.selection("FACE", "Boolean_1_1_1/Modified_2"), model.selection("FACE", "Boolean_1_1_3/Modified_4"), model.selection("FACE", "_Extrusion_1_1/Generated_Face_12"), model.selection("FACE", "_Extrusion_1_1/Generated_Face_11"), model.selection("FACE", "Boolean_1_1_3/Modified_3"), model.selection("FACE", "Boolean_1_1_3/Modified_2"), model.selection("FACE", "Boolean_1_1_3/Modified_1"), model.selection("FACE", "_Extrusion_1_1/Generated_Face_4"), model.selection("FACE", "Boolean_1_1_3/Modified_4"), model.selection("FACE", "Boolean_1_1_4/Modified_Face_1"), model.selection("FACE", "_Extrusion_1_1/Generated_Face_4"), model.selection("FACE", "_Extrusion_1_1/To_Face_3"), model.selection("FACE", "_Extrusion_1_1/Generated_Face_3"), model.selection("FACE", "_Extrusion_1_1/Generated_Face_2"), model.selection("FACE", "_Extrusion_1_1/From_Face_3"), model.selection("FACE", "_Extrusion_1_1/Generated_Face_1")])
 model.do()
+
+model.testHaveNamingSubshapes(Boolean_1, model, Part_1_doc)
+
 model.end()
 
 from GeomAPI import  GeomAPI_Shape
diff --git a/src/FeaturesPlugin/Test/TestFillCompFaceSolid.py b/src/FeaturesPlugin/Test/TestFillCompFaceSolid.py
new file mode 100644 (file)
index 0000000..1fc5413
--- /dev/null
@@ -0,0 +1,63 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "L", "10")
+model.addParameter(Part_1_doc, "Shift", "5")
+Box_1 = model.addBox(Part_1_doc, "L", "L", "L")
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Bottom"), "Shift", True)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchArc_1 = Sketch_1.addArc(0, 0, 11.4564392373896, -5, 0, -12.5, True)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchArc_1.center())
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_1 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.result())
+SketchLine_2 = Sketch_1.addLine(11.4564392373896, -5, 0, 5)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(0, 5, 0, -12.5)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchArc_1.endPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_1.result())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], "L+Shift/2")
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_2.startPoint(), 5)
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_3.startPoint(), "Shift", True)
+model.do()
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), "Shift", True)
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchArc_1_2f-SketchLine_2f-SketchLine_3f")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("FACE", "Face_1_1")], [model.selection("FACE", "Plane_2")])
+Boolean_2 = model.addFill(Part_1_doc, [model.selection("COMPOUND", "Boolean_1_1")], [model.selection("SOLID", "Box_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_2, model, 1, [6], [0], [6], [22], [44])
+model.testHaveNamingSubshapes(Boolean_2, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillEdgeEdge.py b/src/FeaturesPlugin/Test/TestFillEdgeEdge.py
new file mode 100644 (file)
index 0000000..1ea55e4
--- /dev/null
@@ -0,0 +1,48 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-43.24383164005806, 13.92597968069667, 63.17997097242381, 62.8867924528302)
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_2 = Sketch_2.addLine(-21.12944291883177, 24.09981691608177, 39.13933236574746, 51.82677414066782)
+SketchProjection_1 = Sketch_2.addProjection(model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), False)
+SketchLine_3 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_2.setCoincident(SketchLine_2.startPoint(), SketchLine_3.result())
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.result())
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_1")])
+Edge_2 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_2")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("EDGE", "Edge_1_1")], [model.selection("EDGE", "Edge_2_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1,model,1,[3],[0],[0],[3],[6])
+model.testHaveNamingSubshapes(Boolean_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillEdgeEdgeIntersected.py b/src/FeaturesPlugin/Test/TestFillEdgeEdgeIntersected.py
new file mode 100644 (file)
index 0000000..4efa527
--- /dev/null
@@ -0,0 +1,44 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_1 = Sketch_1.addLine(-54.08747895500726, -7.310347750362856, 54.27191756168357, 63.68373962264153)
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_2 = Sketch_2.addLine(-42.46271611030479, 53.71965718432511, 14.83075791001449, -51.73354862119014)
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_1")])
+Edge_2 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_2")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("EDGE", "Edge_1_1")], [model.selection("EDGE", "Edge_2_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1,model,1,[2],[0],[0],[2],[4])
+model.testHaveNamingSubshapes(Boolean_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillEdgeFace.py b/src/FeaturesPlugin/Test/TestFillEdgeFace.py
new file mode 100644 (file)
index 0000000..2ed0082
--- /dev/null
@@ -0,0 +1,51 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_1 = Sketch_1.addLine(-65.15998142235124, 15.60729985486212, 25.76227082728593, 71.65526357039188)
+SketchLine_2 = Sketch_1.addLine(25.76227082728593, 71.65526357039188, 74.75234281567489, -47.08338548621191)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(74.75234281567489, -47.08338548621191, 13.30716777939044, -81.12733381712628)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(13.30716777939044, -81.12733381712628, -65.15998142235124, 15.60729985486212)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_4.endPoint())
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_3"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_4")])
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r"))
+SketchLine_5 = Sketch_2.addLine(-53.77011318694006, -47.84888937635935, 60.89888292381829, 36.13719175945)
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_5")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("EDGE", "Edge_1_1")], [model.selection("FACE", "Face_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1, model, 1, [3], [0], [0], [3], [6])
+model.testHaveNamingSubshapes(Boolean_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillEdgeShell.py b/src/FeaturesPlugin/Test/TestFillEdgeShell.py
new file mode 100644 (file)
index 0000000..9b9b7ad
--- /dev/null
@@ -0,0 +1,59 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from 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("YOZ"))
+SketchArc_1 = Sketch_1.addArc(28.24683132290313, 24.84281403912743, 0, 50, 56.77054208906745, 0, False)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.result(), SketchArc_1.endPoint())
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_2.result())
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchArc_1.startPoint(), SketchAPI_Line(SketchLine_1).startPoint(), 50)
+SketchArc_2 = Sketch_1.addArc(38.14157263904823, 16.22495851193372, 56.77054208906745, 0, 34.15529753265601, 40.60522496371553, False)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchArc_2.startPoint())
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchArc_1.results()[1], SketchArc_2.results()[1])
+model.do()
+Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchArc_1_2"), model.selection("EDGE", "Sketch_1/Edge-SketchArc_2_2")])
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Wire_1_1")], model.selection(), 70, 0)
+Shell_1 = model.addShell(Part_1_doc, [model.selection("SHELL", "Extrusion_1_1")])
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/YOZ"), 30, False)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchLine_3 = Sketch_2.addLine(-64.49168769733997, 17.16789081864163, 146.7677170722727, 22.9901626941168)
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_3")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("EDGE", "Edge_1_1")], [model.selection("SHELL", "Shell_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1, model, 1, [3], [0], [0], [3], [6])
+model.testHaveNamingSubshapes(Boolean_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillEdgeSolid.py b/src/FeaturesPlugin/Test/TestFillEdgeSolid.py
new file mode 100644 (file)
index 0000000..756de0a
--- /dev/null
@@ -0,0 +1,47 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Box_1_1/Front"))
+SketchLine_1 = Sketch_1.addLine(4, 10, 7, 0)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "Box_1_1/Front&Box_1_1/Top"), False)
+SketchLine_2 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_2.result())
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "Box_1_1/Front&Box_1_1/Bottom"), False)
+SketchLine_3 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_3.result())
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_1")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("EDGE", "Edge_1_1")], [model.selection("SOLID", "Box_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1, model, 1, [0], [0], [0], [1], [2])
+model.testHaveNamingSubshapes(Boolean_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillEdgeSolidIntersected.py b/src/FeaturesPlugin/Test/TestFillEdgeSolidIntersected.py
new file mode 100644 (file)
index 0000000..89c93d7
--- /dev/null
@@ -0,0 +1,48 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Cone_1 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10, 5, 10)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Cone_1_1/Face_3"), 5, True)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchLine_1 = Sketch_1.addLine(-8.679188755740876, 4.967059748203267, 8.679188755740878, -4.967059748203268)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintMiddle_1 = Sketch_1.setMiddlePoint(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 20)
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_1")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("EDGE", "Edge_1_1")], [model.selection("SOLID", "Cone_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1, model, 1, [3], [0], [0], [3], [6])
+model.testHaveNamingSubshapes(Boolean_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillEdgeVertex.py b/src/FeaturesPlugin/Test/TestFillEdgeVertex.py
new file mode 100644 (file)
index 0000000..f98ebaa
--- /dev/null
@@ -0,0 +1,47 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Point_1 = model.addPoint(Part_1_doc, 10, 10, 0)
+Vertex_1 = model.addVertex(Part_1_doc, [model.selection("VERTEX", "Point_1")])
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-27.61369370623992, 41.69872643310781, 64.30052615729069, -35.76145957046036)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "Point_1"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.result(), SketchAPI_Point(SketchPoint_1).coordinates())
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_1")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("EDGE", "Edge_1_1")], [model.selection("VERTEX", "Vertex_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1,model,1,[2],[0],[0],[2],[4])
+model.testHaveNamingSubshapes(Boolean_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillEdgeWire.py b/src/FeaturesPlugin/Test/TestFillEdgeWire.py
new file mode 100644 (file)
index 0000000..150ddb9
--- /dev/null
@@ -0,0 +1,51 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_1 = Sketch_1.addLine(-67.57764876632801, 2.198838896952097, 88.39332365747461, 44.12336719883891)
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_2 = Sketch_2.addLine(-40.60522496371553, -29.75761973875181, -38.84615384615385, 66.99129172714079)
+SketchLine_3 = Sketch_2.addLine(-38.84615384615385, 66.99129172714079, 50.86647314949202, 73.4412191582003)
+SketchConstraintCoincidence_1 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_2.addLine(50.86647314949202, 73.4412191582003, 55.26415094339622, -34.15529753265602)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_2.addLine(55.26415094339622, -34.15529753265602, -40.60522496371553, -29.75761973875181)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_2.startPoint())
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_1")])
+Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_5"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_2"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_3"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_4")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("EDGE", "Edge_1_1")], [model.selection("WIRE", "Wire_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1, model, 1, [3], [0], [0], [3], [6])
+model.testHaveNamingSubshapes(Boolean_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillFaceEdge.py b/src/FeaturesPlugin/Test/TestFillFaceEdge.py
new file mode 100644 (file)
index 0000000..33a1d21
--- /dev/null
@@ -0,0 +1,51 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_1 = Sketch_1.addLine(-65.15998142235124, 15.60729985486212, 25.76227082728593, 71.65526357039188)
+SketchLine_2 = Sketch_1.addLine(25.76227082728593, 71.65526357039188, 74.75234281567489, -47.08338548621191)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(74.75234281567489, -47.08338548621191, 13.30716777939044, -81.12733381712628)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(13.30716777939044, -81.12733381712628, -65.15998142235124, 15.60729985486212)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_4.endPoint())
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_3"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_4")])
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r"))
+SketchLine_5 = Sketch_2.addLine(-53.77011318694006, -47.84888937635935, 60.89888292381829, 36.13719175945)
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_5")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("FACE", "Face_1_1")], [model.selection("EDGE", "Edge_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1,model,1,[2],[0],[2],[8],[16])
+model.testHaveNamingSubshapes(Boolean_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillFaceEdgeInside.py b/src/FeaturesPlugin/Test/TestFillFaceEdgeInside.py
new file mode 100644 (file)
index 0000000..18a6866
--- /dev/null
@@ -0,0 +1,54 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchArc_1 = Sketch_1.addArc(-31.22351233671988, 15.68505079825835, -49.40058055152394, 17.44412191582002, -17.30100145268062, 27.5029960835475, True)
+SketchLine_1 = Sketch_1.addLine(-17.30100145268062, 27.5029960835475, -6.596516690856308, -20.66908563134978)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.startPoint())
+SketchLine_2 = Sketch_1.addLine(-6.596516690856308, -20.66908563134978, -34.74165457184325, -28.87808417997097)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(-34.74165457184325, -28.87808417997097, -49.40058055152394, 17.44412191582002)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_3.endPoint())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Sketch_1/Face-SketchArc_1_2f-SketchLine_1r-SketchLine_2r-SketchLine_3r"))
+SketchLine_4 = Sketch_2.addLine(-17.59187701681758, -17.53169787967194, -23.97073271029336, 4.338664497959301)
+SketchProjection_1 = Sketch_2.addProjection(model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), False)
+SketchLine_5 = SketchProjection_1.createdFeature()
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_4.result(), SketchLine_5.result())
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_4")])
+Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_3"), model.selection("EDGE", "Sketch_1/Edge-SketchArc_1_2"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_1")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("FACE", "Face_1_1")], [model.selection("EDGE", "Edge_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1,model,1,[0],[0],[1],[5],[10])
+model.testHaveNamingSubshapes(Boolean_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillFaceEdgePerpendicular.py b/src/FeaturesPlugin/Test/TestFillFaceEdgePerpendicular.py
new file mode 100644 (file)
index 0000000..f0a751b
--- /dev/null
@@ -0,0 +1,55 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-27.76647174128943, 72.31029012920524, 42.2686420251427, 59.94944420697596)
+SketchLine_2 = Sketch_1.addLine(42.2686420251427, 59.94944420697596, 59.0507718766223, 21.43074552356853)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(59.0507718766223, 21.43074552356853, 56.1909608273397, -69.919416180974)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(56.1909608273397, -69.919416180974, -29.91225626113892, -65.09334567012574)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(-29.91225626113892, -65.09334567012574, -57.18321726979322, -2.500460309588558)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_1.addLine(-57.18321726979322, -2.500460309588558, -27.76647174128943, 72.31029012920524)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_1.startPoint())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_7 = Sketch_2.addLine(24.33758278426026, -52.48127186534471, 29.40566289183227, 59.45054433956496)
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_7")])
+Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_6"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_5"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_4"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_3"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_2")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("FACE", "Face_1_1")], [model.selection("EDGE", "Edge_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1,model,1,[0],[0],[1],[6],[13])
+model.testHaveNamingSubshapes(Boolean_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillFaceFace.py b/src/FeaturesPlugin/Test/TestFillFaceFace.py
new file mode 100644 (file)
index 0000000..03cefe9
--- /dev/null
@@ -0,0 +1,68 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+from SketchAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "R", "50")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-49.81325699578132, 35.39936274902501, 0, 8.200436015051352)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_2 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.result())
+SketchLine_3 = Sketch_1.addLine(0, 8.200436015051352, 49.94978427678259, 33.32234621934526)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_3.startPoint())
+SketchArc_1 = Sketch_1.addArc(0, 31.08202242513997, 49.94978427678259, 33.32234621934526, -49.81325699578132, 35.39936274902501, False)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchArc_1.endPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchArc_1.center(), SketchLine_2.result())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], "R")
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_4 = Sketch_2.addLine(31.79164821526215, 49.99496405877289, 8.200436015051352, 0)
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_3s-SketchLine_1e"), False)
+SketchPoint_1 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchPoint_1.result())
+SketchLine_5 = Sketch_2.addLine(8.200436015051352, 0, 27.24680168984479, -49.85269382803262)
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchProjection_3 = Sketch_2.addProjection(model.selection("VERTEX", "Sketch_1/Vertex-SketchArc_1"), False)
+SketchPoint_2 = SketchProjection_3.createdFeature()
+SketchArc_2 = Sketch_2.addArc(31.08202242513997, 1.147024884467139e-021, 27.24680168984479, -49.85269382803262, 31.79164821526215, 49.99496405877289, False)
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchPoint_2.result(), SketchArc_2.center())
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchArc_2.startPoint())
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchArc_2.endPoint(), SketchLine_4.startPoint())
+SketchConstraintRadius_2 = Sketch_2.setRadius(SketchArc_2.results()[1], "R")
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_1f-SketchLine_3f-SketchArc_1_2f")])
+Face_2 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchLine_4f-SketchLine_5f-SketchArc_2_2f")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("FACE", "Face_1_1")], [model.selection("FACE", "Face_2_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1, model, 1, [2], [0], [2], [6], [12])
+model.testHaveNamingSubshapes(Boolean_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillFaceShell.py b/src/FeaturesPlugin/Test/TestFillFaceShell.py
new file mode 100644 (file)
index 0000000..bd37796
--- /dev/null
@@ -0,0 +1,112 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "D", "50")
+model.addParameter(Part_1_doc, "L", "30")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0, 28.78679656440358, 21.21320343559643, 50)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_2 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_2.result())
+SketchLine_3 = Sketch_1.addLine(21.21320343559643, 50, 0, 71.21320343559643)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_2.result())
+SketchLine_4 = Sketch_1.addLine(0, 71.21320343559643, -21.21320343559642, 50)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(-21.21320343559642, 50, 0, 28.78679656440358)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_5.endPoint())
+SketchLine_6 = Sketch_1.addLine(-21.21320343559642, 50, 21.21320343559643, 50)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_6.endPoint())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Line(SketchLine_2).startPoint(), SketchLine_6.result(), "D", True)
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), "L")
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintEqual_2 = Sketch_1.setEqual(SketchLine_3.result(), SketchLine_4.result())
+SketchConstraintEqual_3 = Sketch_1.setEqual(SketchLine_4.result(), SketchLine_5.result())
+SketchConstraintPerpendicular_1 = Sketch_1.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_2.createdFeature()
+SketchLine_7 = Sketch_2.addLine(50, -39.61510263929618, 50, 43.87280058651025)
+SketchLine_7.setName("SketchLine_8")
+SketchLine_7.result().setName("SketchLine_8")
+SketchLine_7.setAuxiliary(True)
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_7.result())
+SketchConstraintDistance_2 = Sketch_2.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_7.result(), "D", True)
+SketchLine_8 = Sketch_2.addLine(57.5, 0, 65, -10.81485284151855)
+SketchLine_8.setName("SketchLine_9")
+SketchLine_8.result().setName("SketchLine_9")
+SketchProjection_3 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_9 = SketchProjection_3.createdFeature()
+SketchLine_9.setName("SketchLine_10")
+SketchLine_9.result().setName("SketchLine_10")
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_8.startPoint(), SketchLine_9.result())
+SketchLine_10 = Sketch_2.addLine(65, -10.81485284151855, 65, 11.50710132369052)
+SketchLine_10.setName("SketchLine_11")
+SketchLine_10.result().setName("SketchLine_11")
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_10.startPoint())
+SketchLine_11 = Sketch_2.addLine(65, 11.50710132369052, 50, 11.50710132369052)
+SketchLine_11.setName("SketchLine_12")
+SketchLine_11.result().setName("SketchLine_12")
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint())
+SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchLine_11.endPoint(), SketchLine_7.result())
+SketchConstraintDistance_3 = Sketch_2.setDistance(SketchLine_8.startPoint(), SketchLine_7.result(), "L/4", True)
+SketchConstraintDistance_4 = Sketch_2.setDistance(SketchLine_8.endPoint(), SketchLine_7.result(), "L/2", True)
+SketchConstraintDistance_5 = Sketch_2.setDistance(SketchLine_10.endPoint(), SketchLine_7.result(), "L/2", True)
+SketchConstraintHorizontal_1 = Sketch_2.setHorizontal(SketchLine_11.result())
+SketchConstraintMirror_1_objects = [SketchLine_8.result(), SketchLine_10.result(), SketchLine_11.result()]
+SketchConstraintMirror_1 = Sketch_2.addMirror(SketchLine_7.result(), SketchConstraintMirror_1_objects)
+[SketchLine_12, SketchLine_13, SketchLine_14] = SketchConstraintMirror_1.mirrored()
+SketchLine_14.setName("SketchLine_15")
+SketchLine_14.result().setName("SketchLine_15")
+SketchLine_13.setName("SketchLine_14")
+SketchLine_13.result().setName("SketchLine_14")
+SketchLine_12.setName("SketchLine_13")
+SketchLine_12.result().setName("SketchLine_13")
+SketchLine_15 = Sketch_2.addLine(42.5, 0, 57.5, 0)
+SketchLine_15.setName("SketchLine_16")
+SketchLine_15.result().setName("SketchLine_16")
+SketchConstraintCoincidence_13 = Sketch_2.setCoincident(SketchAPI_Line(SketchLine_12).startPoint(), SketchLine_15.startPoint())
+SketchConstraintCoincidence_14 = Sketch_2.setCoincident(SketchLine_15.endPoint(), SketchLine_8.startPoint())
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_1f-SketchLine_5f-SketchLine_6r")])
+Face_2 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_3f-SketchLine_4f-SketchLine_6f")])
+Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("FACE", "Face_2_1")])
+Face_3 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchLine_9f-SketchLine_11f-SketchLine_12f-SketchLine_13r-SketchLine_14r-SketchLine_15r-SketchLine_16f")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("FACE", "Face_3_1")], [model.selection("SHELL", "Shell_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1, model, 1, [3], [0], [3], [14], [28])
+model.testHaveNamingSubshapes(Boolean_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillFaceSolid.py b/src/FeaturesPlugin/Test/TestFillFaceSolid.py
new file mode 100644 (file)
index 0000000..d5cf717
--- /dev/null
@@ -0,0 +1,61 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "L", "10")
+model.addParameter(Part_1_doc, "Shift", "5")
+Box_1 = model.addBox(Part_1_doc, "L", "L", "L")
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Bottom"), "Shift", True)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchArc_1 = Sketch_1.addArc(0, 0, 11.4564392373896, -5, 0, -12.5, True)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchArc_1.center())
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_1 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.result())
+SketchLine_2 = Sketch_1.addLine(11.4564392373896, -5, 0, 5)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(0, 5, 0, -12.5)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchArc_1.endPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_1.result())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], "L+Shift/2")
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_2.startPoint(), 5)
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_3.startPoint(), "Shift", True)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchArc_1_2f-SketchLine_2f-SketchLine_3f")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("FACE", "Face_1_1")], [model.selection("SOLID", "Box_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1, model, 1, [4], [0], [4], [15], [30])
+model.testHaveNamingSubshapes(Boolean_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillFaceVertex.py b/src/FeaturesPlugin/Test/TestFillFaceVertex.py
new file mode 100644 (file)
index 0000000..7229746
--- /dev/null
@@ -0,0 +1,53 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Point_2 = model.addPoint(Part_1_doc, 22, 33, 0)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(80.77068214804063, 60.54136429608128, -35.9143686502177, 60.54136429608128)
+SketchLine_2 = Sketch_1.addLine(-35.9143686502177, 60.54136429608128, -35.9143686502177, -37.67343976777939)
+SketchLine_3 = Sketch_1.addLine(-35.9143686502177, -37.67343976777939, 80.77068214804063, -37.67343976777939)
+SketchLine_4 = Sketch_1.addLine(80.77068214804063, -37.67343976777939, 80.77068214804063, 60.54136429608128)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_4"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_3"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_2")])
+Vertex_1 = model.addVertex(Part_1_doc, [model.selection("VERTEX", "Point_1")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("FACE", "Face_1_1")], [model.selection("VERTEX", "Vertex_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1,model,1,[0],[0],[1],[4],[9])
+model.testHaveNamingSubshapes(Boolean_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillFaceWire.py b/src/FeaturesPlugin/Test/TestFillFaceWire.py
new file mode 100644 (file)
index 0000000..a796dda
--- /dev/null
@@ -0,0 +1,64 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "R", "50")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-49.81325699578132, 35.39936274902501, 0, 8.200436015051352)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_2 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.result())
+SketchLine_3 = Sketch_1.addLine(0, 8.200436015051352, 49.94978427678259, 33.32234621934526)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_3.startPoint())
+SketchArc_1 = Sketch_1.addArc(0, 31.08202242513997, 49.94978427678259, 33.32234621934526, -49.81325699578132, 35.39936274902501, False)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchArc_1.endPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchArc_1.center(), SketchLine_2.result())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], "R")
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_4 = Sketch_2.addLine(-42.38833891077762, 73.71572760627062, -18.23994072168525, 7.835320880296757)
+SketchLine_5 = Sketch_2.addLine(-18.23994072168525, 7.835320880296757, 13.89341696052619, 27.33089138697832)
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_2.addLine(13.89341696052619, 27.33089138697832, 39.39985877388298, 9.747860956493145)
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchLine_7 = Sketch_2.addLine(39.39985877388298, 9.747860956493145, 38.20105433548567, 71.93732104572752)
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchLine_8 = Sketch_2.addLine(38.20105433548567, 71.93732104572752, -42.38833891077762, 73.71572760627062)
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_4.startPoint(), SketchLine_8.endPoint())
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_1f-SketchLine_3f-SketchArc_1_2f")])
+Wire_1 = model.addWire(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchLine_4f-SketchLine_5f-SketchLine_6f-SketchLine_7f-SketchLine_8f")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("FACE", "Face_1_1")], [model.selection("WIRE", "Wire_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1, model, 1, [5], [0], [5], [21], [42])
+model.testHaveNamingSubshapes(Boolean_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillShellConstrPlane.py b/src/FeaturesPlugin/Test/TestFillShellConstrPlane.py
new file mode 100644 (file)
index 0000000..86c1da0
--- /dev/null
@@ -0,0 +1,54 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from 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("YOZ"))
+SketchArc_1 = Sketch_1.addArc(28.24683132290313, 24.84281403912743, 0, 50, 56.77054208906745, 0, False)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.result(), SketchArc_1.endPoint())
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_2.result())
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchArc_1.startPoint(), SketchAPI_Line(SketchLine_1).startPoint(), 50)
+SketchArc_2 = Sketch_1.addArc(38.14157263904823, 16.22495851193372, 56.77054208906745, 0, 34.15529753265601, 40.60522496371553, False)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchArc_2.startPoint())
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchArc_1.results()[1], SketchArc_2.results()[1])
+model.do()
+Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchArc_1_2"), model.selection("EDGE", "Sketch_1/Edge-SketchArc_2_2")])
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Wire_1_1")], model.selection(), 70, 0)
+Shell_1 = model.addShell(Part_1_doc, [model.selection("SHELL", "Extrusion_1_1")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("SHELL", "Shell_1_1")], [model.selection("FACE", "PartSet/XOZ")])
+model.do()
+
+model.checkBooleansResult(Boolean_1,model,1,[0],[0],[3],[12],[24])
+model.testHaveNamingSubshapes(Boolean_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillShellEdge.py b/src/FeaturesPlugin/Test/TestFillShellEdge.py
new file mode 100644 (file)
index 0000000..207cc21
--- /dev/null
@@ -0,0 +1,59 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from 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("YOZ"))
+SketchArc_1 = Sketch_1.addArc(28.24683132290313, 24.84281403912743, 0, 50, 56.77054208906745, 0, False)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.result(), SketchArc_1.endPoint())
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_2.result())
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchArc_1.startPoint(), SketchAPI_Line(SketchLine_1).startPoint(), 50)
+SketchArc_2 = Sketch_1.addArc(38.14157263904823, 16.22495851193372, 56.77054208906745, 0, 34.15529753265601, 40.60522496371553, False)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchArc_2.startPoint())
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchArc_1.results()[1], SketchArc_2.results()[1])
+model.do()
+Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchArc_1_2"), model.selection("EDGE", "Sketch_1/Edge-SketchArc_2_2")])
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Wire_1_1")], model.selection(), 70, 0)
+Shell_1 = model.addShell(Part_1_doc, [model.selection("SHELL", "Extrusion_1_1")])
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/YOZ"), 30, False)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchLine_3 = Sketch_2.addLine(-64.49168769733997, 17.16789081864163, 146.7677170722727, 22.9901626941168)
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_3")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("SHELL", "Shell_1_1")], [model.selection("EDGE", "Edge_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1,model,1,[0],[0],[2],[8],[18])
+model.testHaveNamingSubshapes(Boolean_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillShellFace.py b/src/FeaturesPlugin/Test/TestFillShellFace.py
new file mode 100644 (file)
index 0000000..1ece54f
--- /dev/null
@@ -0,0 +1,106 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "D", "50")
+model.addParameter(Part_1_doc, "L", "30")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-6, 29.93619865618197, 18, 47.93619865618197)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_2 = SketchProjection_1.createdFeature()
+SketchLine_3 = Sketch_1.addLine(18, 47.93619865618197, 0, 71.93619865618197)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_2.result())
+SketchLine_4 = Sketch_1.addLine(0, 71.93619865618197, -24, 53.93619865618197)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(-24, 53.93619865618197, -6, 29.93619865618197)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_5.endPoint())
+SketchLine_6 = Sketch_1.addLine(-24, 53.93619865618197, 18, 47.93619865618197)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_6.endPoint())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Line(SketchLine_2).startPoint(), SketchLine_6.result(), "D", True)
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), "L")
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintEqual_2 = Sketch_1.setEqual(SketchLine_3.result(), SketchLine_4.result())
+SketchConstraintEqual_3 = Sketch_1.setEqual(SketchLine_4.result(), SketchLine_5.result())
+SketchConstraintPerpendicular_1 = Sketch_1.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchLine_5.endPoint(), SketchLine_2.result(), "L/5", True)
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_2.createdFeature()
+SketchLine_7 = Sketch_2.addLine(50, -39.61510263929618, 50, 43.87280058651025)
+SketchLine_7.setName("SketchLine_8")
+SketchLine_7.result().setName("SketchLine_8")
+SketchLine_7.setAuxiliary(True)
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_7.result())
+SketchConstraintDistance_3 = Sketch_2.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_7.result(), "D", True)
+SketchLine_8 = Sketch_2.addLine(50, -3.170182618622045, 80, -14.17077918941143)
+SketchLine_8.setName("SketchLine_9")
+SketchLine_8.result().setName("SketchLine_9")
+SketchLine_9 = Sketch_2.addLine(80, -14.17077918941143, 64.99999999999999, 12.18920647716607)
+SketchLine_9.setName("SketchLine_11")
+SketchLine_9.result().setName("SketchLine_11")
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchConstraintCoincidence_8.setName("SketchConstraintCoincidence_9")
+SketchLine_10 = Sketch_2.addLine(64.99999999999999, 12.18920647716607, 50, 12.18920647716607)
+SketchLine_10.setName("SketchLine_12")
+SketchLine_10.result().setName("SketchLine_12")
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint())
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_10.endPoint(), SketchLine_7.result())
+SketchConstraintDistance_4 = Sketch_2.setDistance(SketchLine_8.endPoint(), SketchLine_7.result(), "L", True)
+SketchConstraintDistance_5 = Sketch_2.setDistance(SketchLine_9.endPoint(), SketchLine_7.result(), "L/2", True)
+SketchConstraintHorizontal_1 = Sketch_2.setHorizontal(SketchLine_10.result())
+SketchConstraintMirror_1_objects = [SketchLine_8.result(), SketchLine_9.result(), SketchLine_10.result()]
+SketchConstraintMirror_1 = Sketch_2.addMirror(SketchLine_7.result(), SketchConstraintMirror_1_objects)
+[SketchLine_11, SketchLine_12, SketchLine_13] = SketchConstraintMirror_1.mirrored()
+SketchLine_13.setName("SketchLine_15")
+SketchLine_13.result().setName("SketchLine_15")
+SketchLine_12.setName("SketchLine_14")
+SketchLine_12.result().setName("SketchLine_14")
+SketchLine_11.setName("SketchLine_13")
+SketchLine_11.result().setName("SketchLine_13")
+SketchProjection_3 = Sketch_2.addProjection(model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_4s-SketchLine_3e"), False)
+SketchPoint_2 = SketchProjection_3.createdFeature()
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_9.result())
+SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchLine_8.startPoint(), SketchLine_7.result())
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_1f-SketchLine_5f-SketchLine_6r")])
+Face_2 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_3f-SketchLine_4f-SketchLine_6f")])
+Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("FACE", "Face_2_1")])
+Face_3 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchLine_9f-SketchLine_11f-SketchLine_12f-SketchLine_13r-SketchLine_14r-SketchLine_15r")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("SHELL", "Shell_1_1")], [model.selection("FACE", "Face_3_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1, model, 1, [0], [0], [4], [13], [26])
+model.testHaveNamingSubshapes(Boolean_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillShellShell.py b/src/FeaturesPlugin/Test/TestFillShellShell.py
new file mode 100644 (file)
index 0000000..f5cd97d
--- /dev/null
@@ -0,0 +1,90 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "D", "50")
+model.addParameter(Part_1_doc, "L", "30")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-10, 32.04672553984553, 15.61552812808831, 47.66225366793383)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_2 = SketchProjection_1.createdFeature()
+SketchLine_3 = Sketch_1.addLine(15.61552812808831, 47.66225366793383, -4.988916520257207e-021, 73.27778179602213)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_2.result())
+SketchLine_4 = Sketch_1.addLine(-4.988916520257207e-021, 73.27778179602213, -25.61552812810082, 57.66225366792627)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(-25.61552812810082, 57.66225366792627, -10, 32.04672553984553)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_5.endPoint())
+SketchLine_6 = Sketch_1.addLine(-25.61552812810082, 57.66225366792627, 15.61552812808831, 47.66225366793383)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_6.endPoint())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Line(SketchLine_2).startPoint(), SketchLine_6.result(), "D", True)
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), "L")
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintEqual_2 = Sketch_1.setEqual(SketchLine_3.result(), SketchLine_4.result())
+SketchConstraintEqual_3 = Sketch_1.setEqual(SketchLine_4.result(), SketchLine_5.result())
+SketchConstraintPerpendicular_1 = Sketch_1.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchLine_5.endPoint(), SketchLine_2.result(), "L/3", True)
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_7 = Sketch_2.addLine(50, 15.56025031353752, 50, -15.54016280334104)
+SketchLine_8 = Sketch_2.addLine(50, -15.54016280334104, 36.52981427174974, 0)
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_9 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_9.result())
+SketchLine_10 = Sketch_2.addLine(36.52981427174974, 0, 50, 15.56025031353752)
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_10.startPoint())
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_7.startPoint(), SketchLine_10.endPoint())
+SketchLine_11 = Sketch_2.addLine(50, 15.56025031353752, 73.27778179602213, 0)
+SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchLine_7.startPoint(), SketchLine_11.startPoint())
+SketchProjection_3 = Sketch_2.addProjection(model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_4s-SketchLine_3e"), False)
+SketchPoint_1 = SketchProjection_3.createdFeature()
+SketchConstraintCoincidence_13 = Sketch_2.setCoincident(SketchLine_11.endPoint(), SketchPoint_1.result())
+SketchLine_12 = Sketch_2.addLine(73.27778179602213, 0, 50, -15.54016280334104)
+SketchConstraintCoincidence_14 = Sketch_2.setCoincident(SketchLine_11.endPoint(), SketchLine_12.startPoint())
+SketchConstraintCoincidence_15 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_12.endPoint())
+SketchConstraintDistance_3 = Sketch_2.setDistance(SketchAPI_Line(SketchLine_9).startPoint(), SketchLine_7.result(), "D", True)
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_7.result())
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_1f-SketchLine_5f-SketchLine_6r")])
+Face_2 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_3f-SketchLine_4f-SketchLine_6f")])
+Face_3 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchLine_7r-SketchLine_8r-SketchLine_10r")])
+Face_4 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchLine_7f-SketchLine_11r-SketchLine_12r")])
+Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("FACE", "Face_2_1")])
+Shell_2 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_3_1"), model.selection("FACE", "Face_4_1")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("SHELL", "Shell_1_1")], [model.selection("SHELL", "Shell_2_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1, model, 1, [0], [0], [4], [15], [30])
+model.testHaveNamingSubshapes(Boolean_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillShellSolid.py b/src/FeaturesPlugin/Test/TestFillShellSolid.py
new file mode 100644 (file)
index 0000000..c1e57f1
--- /dev/null
@@ -0,0 +1,64 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "L", "10")
+model.addParameter(Part_1_doc, "Shift", "5")
+Box_1 = model.addBox(Part_1_doc, "L", "L", "L")
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Bottom"), "Shift", True)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchArc_1 = Sketch_1.addArc(0, 0, 11.4564392373896, -5, 0, -12.5, True)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchArc_1.center())
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_1 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.result())
+SketchLine_2 = Sketch_1.addLine(11.4564392373896, -5, 0, 5)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(0, 5, 0, -12.5)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchArc_1.endPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_1.result())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], "L+Shift/2")
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_2.startPoint(), 5)
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_3.startPoint(), "Shift", True)
+model.do()
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), "Shift", True)
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchArc_1_2f-SketchLine_2f-SketchLine_3f")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("FACE", "Face_1_1")], [model.selection("FACE", "Plane_2")])
+Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "Boolean_1_1_2"), model.selection("FACE", "Boolean_1_1_1")])
+Boolean_2 = model.addFill(Part_1_doc, [model.selection("SHELL", "Shell_1_1")], [model.selection("SOLID", "Box_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_2, model, 1, [0], [0], [6], [22], [44])
+model.testHaveNamingSubshapes(Boolean_2, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillShellVertex.py b/src/FeaturesPlugin/Test/TestFillShellVertex.py
new file mode 100644 (file)
index 0000000..389376a
--- /dev/null
@@ -0,0 +1,52 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from 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"))
+SketchArc_1 = Sketch_1.addArc(9.761379814097372, -58.25586643592183, 0, 0, -48.40807467084933, -47.99209154562215, False)
+SketchArc_2 = Sketch_1.addArc(-12.6706171814691, -54.29782746957817, -48.40807467084933, -47.99209154562215, 12.46009047944227, -80.47750863283412, False)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchArc_2.startPoint())
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchArc_1.results()[1], SketchArc_2.results()[1])
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchAPI_Point(SketchPoint_1).coordinates())
+model.do()
+Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchArc_1_2"), model.selection("EDGE", "Sketch_1/Edge-SketchArc_2_2")])
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Wire_1_1")], model.selection(), 50, 0)
+Shell_1 = model.addShell(Part_1_doc, [model.selection("SHELL", "Extrusion_1_1")])
+Point_2 = model.addPoint(Part_1_doc, 0, 0, 10)
+Vertex_1 = model.addVertex(Part_1_doc, [model.selection("VERTEX", "Point_1")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("SHELL", "Shell_1_1")], [model.selection("VERTEX", "Vertex_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1,model,1,[0],[0],[2],[9],[18])
+model.testHaveNamingSubshapes(Boolean_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillShellWire.py b/src/FeaturesPlugin/Test/TestFillShellWire.py
new file mode 100644 (file)
index 0000000..017eb7e
--- /dev/null
@@ -0,0 +1,86 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "D", "50")
+model.addParameter(Part_1_doc, "L", "30")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0, 28.78679656440358, 21.21320343559643, 50)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_2 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_2.result())
+SketchLine_3 = Sketch_1.addLine(21.21320343559643, 50, 0, 71.21320343559643)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_2.result())
+SketchLine_4 = Sketch_1.addLine(0, 71.21320343559643, -21.21320343559642, 50)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(-21.21320343559642, 50, 0, 28.78679656440358)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_5.endPoint())
+SketchLine_6 = Sketch_1.addLine(-21.21320343559642, 50, 21.21320343559643, 50)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_6.endPoint())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Line(SketchLine_2).startPoint(), SketchLine_6.result(), "D", True)
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), "L")
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintEqual_2 = Sketch_1.setEqual(SketchLine_3.result(), SketchLine_4.result())
+SketchConstraintEqual_3 = Sketch_1.setEqual(SketchLine_4.result(), SketchLine_5.result())
+SketchConstraintPerpendicular_1 = Sketch_1.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_7 = Sketch_2.addLine(-14.33356820392057, 60, 15.66643179607943, 60)
+SketchLine_8 = Sketch_2.addLine(15.66643179607943, 60, 15.66643179607943, 30)
+SketchLine_9 = Sketch_2.addLine(15.66643179607943, 30, -14.33356820392057, 30)
+SketchLine_10 = Sketch_2.addLine(-14.33356820392057, 30, -14.33356820392057, 60)
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_10.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint())
+SketchConstraintHorizontal_1 = Sketch_2.setHorizontal(SketchLine_7.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_8.result())
+SketchConstraintHorizontal_2 = Sketch_2.setHorizontal(SketchLine_9.result())
+SketchConstraintVertical_2 = Sketch_2.setVertical(SketchLine_10.result())
+SketchConstraintLength_2 = Sketch_2.setLength(SketchLine_9.result(), "L")
+SketchConstraintLength_3 = Sketch_2.setLength(SketchLine_8.result(), "L")
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_2.createdFeature()
+SketchConstraintDistance_2 = Sketch_2.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_9.result(), "L", True)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_1f-SketchLine_5f-SketchLine_6r")])
+Face_2 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_3f-SketchLine_4f-SketchLine_6f")])
+Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("FACE", "Face_2_1")])
+Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_7"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_8"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_9"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_10")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("SHELL", "Shell_1_1")], [model.selection("WIRE", "Wire_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1, model, 1, [0], [0], [8], [30], [60])
+model.testHaveNamingSubshapes(Boolean_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillSolid2ConstructionPlanes.py b/src/FeaturesPlugin/Test/TestFillSolid2ConstructionPlanes.py
new file mode 100644 (file)
index 0000000..ad6e9c9
--- /dev/null
@@ -0,0 +1,37 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Cone_1 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10, 5, 10)
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("SOLID", "Cone_1_1")], [model.selection("FACE", "PartSet/YOZ"), model.selection("FACE", "PartSet/XOZ")])
+model.do()
+
+model.checkBooleansResult(Boolean_1,model,1,[4],[4],[20],[72],[144])
+model.testHaveNamingSubshapes(Boolean_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillSolidCompFace.py b/src/FeaturesPlugin/Test/TestFillSolidCompFace.py
new file mode 100644 (file)
index 0000000..759c501
--- /dev/null
@@ -0,0 +1,63 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "L", "10")
+model.addParameter(Part_1_doc, "Shift", "12")
+Box_1 = model.addBox(Part_1_doc, "L", "L", "L")
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Bottom"), "L/2", True)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchArc_1 = Sketch_1.addArc(0, 0, 11.4564392373896, -5, 0, -12.5, True)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchArc_1.center())
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_1 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.result())
+SketchLine_2 = Sketch_1.addLine(11.4564392373896, -5, 0, 5)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(0, 5, 0, -12.5)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchArc_1.endPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_1.result())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], "L+Shift/2")
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_2.startPoint(), "Shift/3")
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_3.startPoint(), "Shift", True)
+model.do()
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), "Shift/3", True)
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchArc_1_2f-SketchLine_2f-SketchLine_3f")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("FACE", "Face_1_1")], [model.selection("FACE", "Plane_2")])
+Boolean_2 = model.addFill(Part_1_doc, [model.selection("SOLID", "Box_1_1")], [model.selection("COMPOUND", "Boolean_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_2, model, 1, [2], [2], [14], [60], [120])
+model.testHaveNamingSubshapes(Boolean_2, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillSolidCompShell.py b/src/FeaturesPlugin/Test/TestFillSolidCompShell.py
new file mode 100644 (file)
index 0000000..8e965a5
--- /dev/null
@@ -0,0 +1,65 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "L", "10")
+model.addParameter(Part_1_doc, "Shift", "12")
+Box_1 = model.addBox(Part_1_doc, "L", "L", "L")
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Bottom"), "L/2", True)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchArc_1 = Sketch_1.addArc(0, 0, 11.4564392373896, -5, 0, -12.5, True)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchArc_1.center())
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_1 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.result())
+SketchLine_2 = Sketch_1.addLine(11.4564392373896, -5, 0, 5)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(0, 5, 0, -12.5)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchArc_1.endPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_1.result())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], "L+Shift/2")
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_2.startPoint(), "Shift/3")
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_3.startPoint(), "Shift", True)
+model.do()
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), "Shift/3", True)
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchArc_1_2f-SketchLine_2f-SketchLine_3f")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("FACE", "Face_1_1")], [model.selection("FACE", "Plane_2")])
+Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "Boolean_1_1_2"), model.selection("FACE", "Boolean_1_1_1")])
+MultiTranslation_1 = model.addMultiTranslation(Part_1_doc, [model.selection("SHELL", "Shell_1_1")], model.selection("EDGE", "PartSet/OZ"), 1, 3)
+Boolean_2 = model.addFill(Part_1_doc, [model.selection("SOLID", "Box_1_1")], [model.selection("COMPOUND", "LinearCopy_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_2, model, 1, [4], [4], [30], [132], [264])
+model.testHaveNamingSubshapes(Boolean_2, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillSolidEdge.py b/src/FeaturesPlugin/Test/TestFillSolidEdge.py
new file mode 100644 (file)
index 0000000..79c4a11
--- /dev/null
@@ -0,0 +1,47 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Box_1_1/Front"))
+SketchLine_1 = Sketch_1.addLine(4, 10, 7, 0)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "Box_1_1/Front&Box_1_1/Top"), False)
+SketchLine_2 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_2.result())
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "Box_1_1/Front&Box_1_1/Bottom"), False)
+SketchLine_3 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_3.result())
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_1")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("SOLID", "Box_1_1")], [model.selection("EDGE", "Edge_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1, model, 1, [0], [1], [7], [30], [60])
+model.testHaveNamingSubshapes(Boolean_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillSolidFace.py b/src/FeaturesPlugin/Test/TestFillSolidFace.py
new file mode 100644 (file)
index 0000000..f0fe20d
--- /dev/null
@@ -0,0 +1,61 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "L", "10")
+model.addParameter(Part_1_doc, "Shift", "12")
+Box_1 = model.addBox(Part_1_doc, "L", "L", "L")
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Bottom"), "L/2", True)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchArc_1 = Sketch_1.addArc(0, 0, 11.4564392373896, -5, 0, -12.5, True)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchArc_1.center())
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_1 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.result())
+SketchLine_2 = Sketch_1.addLine(11.4564392373896, -5, 0, 5)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(0, 5, 0, -12.5)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchArc_1.endPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_1.result())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], "L+Shift/2")
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_2.startPoint(), "Shift/3")
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_3.startPoint(), "Shift", True)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchArc_1_2f-SketchLine_2f-SketchLine_3f")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("SOLID", "Box_1_1")], [model.selection("FACE", "Face_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1, model, 1, [2], [2], [12], [48], [96])
+model.testHaveNamingSubshapes(Boolean_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillSolidShell.py b/src/FeaturesPlugin/Test/TestFillSolidShell.py
new file mode 100644 (file)
index 0000000..6cf9389
--- /dev/null
@@ -0,0 +1,64 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "L", "10")
+model.addParameter(Part_1_doc, "Shift", "12")
+Box_1 = model.addBox(Part_1_doc, "L", "L", "L")
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Bottom"), "L/2", True)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchArc_1 = Sketch_1.addArc(0, 0, 11.4564392373896, -5, 0, -12.5, True)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchArc_1.center())
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_1 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.result())
+SketchLine_2 = Sketch_1.addLine(11.4564392373896, -5, 0, 5)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(0, 5, 0, -12.5)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchArc_1.endPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_1.result())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], "L+Shift/2")
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_2.startPoint(), "Shift/3")
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_3.startPoint(), "Shift", True)
+model.do()
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), "Shift/3", True)
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchArc_1_2f-SketchLine_2f-SketchLine_3f")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("FACE", "Face_1_1")], [model.selection("FACE", "Plane_2")])
+Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "Boolean_1_1_2"), model.selection("FACE", "Boolean_1_1_1")])
+Boolean_2 = model.addFill(Part_1_doc, [model.selection("SOLID", "Box_1_1")], [model.selection("SHELL", "Shell_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_2, model, 1, [2], [2], [14], [60], [120])
+model.testHaveNamingSubshapes(Boolean_2, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillWireEdge.py b/src/FeaturesPlugin/Test/TestFillWireEdge.py
new file mode 100644 (file)
index 0000000..c5b9824
--- /dev/null
@@ -0,0 +1,51 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_1 = Sketch_1.addLine(-67.57764876632801, 2.198838896952097, 88.39332365747461, 44.12336719883891)
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_2 = Sketch_2.addLine(-40.60522496371553, -29.75761973875181, -38.84615384615385, 66.99129172714079)
+SketchLine_3 = Sketch_2.addLine(-38.84615384615385, 66.99129172714079, 50.86647314949202, 73.4412191582003)
+SketchConstraintCoincidence_1 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_2.addLine(50.86647314949202, 73.4412191582003, 55.26415094339622, -34.15529753265602)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_2.addLine(55.26415094339622, -34.15529753265602, -40.60522496371553, -29.75761973875181)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_2.startPoint())
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_1")])
+Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_5"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_2"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_3"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_4")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("WIRE", "Wire_1_1")], [model.selection("EDGE", "Edge_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1,model,1,[0],[0],[0],[6],[12])
+model.testHaveNamingSubshapes(Boolean_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillWireFace.py b/src/FeaturesPlugin/Test/TestFillWireFace.py
new file mode 100644 (file)
index 0000000..3800f08
--- /dev/null
@@ -0,0 +1,70 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "R", "50")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-49.81325699578132, 35.39936274902501, 0, 8.200436015051352)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_2 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.result())
+SketchLine_3 = Sketch_1.addLine(0, 8.200436015051352, 49.94978427678259, 33.32234621934526)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_3.startPoint())
+SketchArc_1 = Sketch_1.addArc(0, 31.08202242513997, 49.94978427678259, 33.32234621934526, -49.81325699578132, 35.39936274902501, False)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchArc_1.endPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchArc_1.center(), SketchLine_2.result())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], "R")
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_4 = Sketch_2.addLine(29.74624907439609, 30.07487215963349, 31.08202242513997, 0)
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "Sketch_1/Vertex-SketchArc_1"), False)
+SketchPoint_1 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchPoint_1.result())
+SketchLine_5 = Sketch_2.addLine(31.08202242513997, 0, 45.45797599933665, 0)
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchProjection_3 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_6 = SketchProjection_3.createdFeature()
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.result())
+SketchLine_7 = Sketch_2.addLine(45.45797599933665, 0, 45.83553599350717, -22.747645239555)
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_7.startPoint())
+SketchLine_8 = Sketch_2.addLine(45.83553599350717, -22.747645239555, 70.40999925541598, 30.039147749218)
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchLine_9 = Sketch_2.addLine(70.40999925541598, 30.039147749218, 29.74624907439609, 30.07487215963349)
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchLine_4.startPoint(), SketchLine_9.endPoint())
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_1f-SketchLine_3f-SketchArc_1_2f")])
+Wire_1 = model.addWire(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchLine_4f-SketchLine_5f-SketchLine_7f-SketchLine_8f-SketchLine_9f")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("WIRE", "Wire_1_1")], [model.selection("FACE", "Face_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1, model, 1, [0], [0], [0], [6], [12])
+model.testHaveNamingSubshapes(Boolean_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillWireShell.py b/src/FeaturesPlugin/Test/TestFillWireShell.py
new file mode 100644 (file)
index 0000000..d83f035
--- /dev/null
@@ -0,0 +1,112 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "D", "50")
+model.addParameter(Part_1_doc, "L", "30")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0, 28.78679656440358, 21.21320343559643, 50)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_2 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_2.result())
+SketchLine_3 = Sketch_1.addLine(21.21320343559643, 50, 0, 71.21320343559643)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_2.result())
+SketchLine_4 = Sketch_1.addLine(0, 71.21320343559643, -21.21320343559642, 50)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(-21.21320343559642, 50, 0, 28.78679656440358)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_5.endPoint())
+SketchLine_6 = Sketch_1.addLine(-21.21320343559642, 50, 21.21320343559643, 50)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_6.endPoint())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Line(SketchLine_2).startPoint(), SketchLine_6.result(), "D", True)
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), "L")
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintEqual_2 = Sketch_1.setEqual(SketchLine_3.result(), SketchLine_4.result())
+SketchConstraintEqual_3 = Sketch_1.setEqual(SketchLine_4.result(), SketchLine_5.result())
+SketchConstraintPerpendicular_1 = Sketch_1.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_2.createdFeature()
+SketchLine_7 = Sketch_2.addLine(50, -39.61510263929618, 50, 43.87280058651025)
+SketchLine_7.setName("SketchLine_8")
+SketchLine_7.result().setName("SketchLine_8")
+SketchLine_7.setAuxiliary(True)
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_7.result())
+SketchConstraintDistance_2 = Sketch_2.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_7.result(), "D", True)
+SketchLine_8 = Sketch_2.addLine(57.5, 0, 65, -10.81485284151855)
+SketchLine_8.setName("SketchLine_9")
+SketchLine_8.result().setName("SketchLine_9")
+SketchProjection_3 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_9 = SketchProjection_3.createdFeature()
+SketchLine_9.setName("SketchLine_10")
+SketchLine_9.result().setName("SketchLine_10")
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_8.startPoint(), SketchLine_9.result())
+SketchLine_10 = Sketch_2.addLine(65, -10.81485284151855, 65, 11.50710132369052)
+SketchLine_10.setName("SketchLine_11")
+SketchLine_10.result().setName("SketchLine_11")
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_10.startPoint())
+SketchLine_11 = Sketch_2.addLine(65, 11.50710132369052, 50, 11.50710132369052)
+SketchLine_11.setName("SketchLine_12")
+SketchLine_11.result().setName("SketchLine_12")
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint())
+SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchLine_11.endPoint(), SketchLine_7.result())
+SketchConstraintDistance_3 = Sketch_2.setDistance(SketchLine_8.startPoint(), SketchLine_7.result(), "L/4", True)
+SketchConstraintDistance_4 = Sketch_2.setDistance(SketchLine_8.endPoint(), SketchLine_7.result(), "L/2", True)
+SketchConstraintDistance_5 = Sketch_2.setDistance(SketchLine_10.endPoint(), SketchLine_7.result(), "L/2", True)
+SketchConstraintHorizontal_1 = Sketch_2.setHorizontal(SketchLine_11.result())
+SketchConstraintMirror_1_objects = [SketchLine_8.result(), SketchLine_10.result(), SketchLine_11.result()]
+SketchConstraintMirror_1 = Sketch_2.addMirror(SketchLine_7.result(), SketchConstraintMirror_1_objects)
+[SketchLine_12, SketchLine_13, SketchLine_14] = SketchConstraintMirror_1.mirrored()
+SketchLine_14.setName("SketchLine_15")
+SketchLine_14.result().setName("SketchLine_15")
+SketchLine_13.setName("SketchLine_14")
+SketchLine_13.result().setName("SketchLine_14")
+SketchLine_12.setName("SketchLine_13")
+SketchLine_12.result().setName("SketchLine_13")
+SketchLine_15 = Sketch_2.addLine(42.5, 0, 57.5, 0)
+SketchLine_15.setName("SketchLine_16")
+SketchLine_15.result().setName("SketchLine_16")
+SketchConstraintCoincidence_13 = Sketch_2.setCoincident(SketchAPI_Line(SketchLine_12).startPoint(), SketchLine_15.startPoint())
+SketchConstraintCoincidence_14 = Sketch_2.setCoincident(SketchLine_15.endPoint(), SketchLine_8.startPoint())
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_1f-SketchLine_5f-SketchLine_6r")])
+Face_2 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_3f-SketchLine_4f-SketchLine_6f")])
+Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("FACE", "Face_2_1")])
+Wire_1 = model.addWire(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchLine_9f-SketchLine_11f-SketchLine_12f-SketchLine_13r-SketchLine_14r-SketchLine_15r-SketchLine_16f")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("WIRE", "Wire_1_1")], [model.selection("SHELL", "Shell_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1, model, 1, [0], [0], [0], [10], [20])
+model.testHaveNamingSubshapes(Boolean_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillWireSolid.py b/src/FeaturesPlugin/Test/TestFillWireSolid.py
new file mode 100644 (file)
index 0000000..f2998dc
--- /dev/null
@@ -0,0 +1,61 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "L", "10")
+model.addParameter(Part_1_doc, "Shift", "5")
+Box_1 = model.addBox(Part_1_doc, "L", "L", "L")
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Bottom"), "Shift", True)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchArc_1 = Sketch_1.addArc(0, 0, 11.4564392373896, -5, 0, -12.5, True)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchArc_1.center())
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_1 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.result())
+SketchLine_2 = Sketch_1.addLine(11.4564392373896, -5, 0, 5)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(0, 5, 0, -12.5)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchArc_1.endPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_1.result())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], "L+Shift/2")
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_2.startPoint(), 5)
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_3.startPoint(), "Shift", True)
+model.do()
+Wire_1 = model.addWire(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchArc_1_2f-SketchLine_2f-SketchLine_3f")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("WIRE", "Wire_1_1")], [model.selection("SOLID", "Box_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1, model, 1, [0], [0], [0], [9], [18])
+model.testHaveNamingSubshapes(Boolean_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillWireVertex.py b/src/FeaturesPlugin/Test/TestFillWireVertex.py
new file mode 100644 (file)
index 0000000..928dac1
--- /dev/null
@@ -0,0 +1,52 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from SketchAPI import *
+
+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, 10, 10, 0)
+Vertex_1 = model.addVertex(Part_1_doc, [model.selection("VERTEX", "Point_1")])
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-27.43492861072797, 41.55044273324706, 64.29883100829633, -35.76346801736826)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "Point_1"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.result(), SketchAPI_Point(SketchPoint_1).coordinates())
+SketchLine_2 = Sketch_1.addLine(64.5972559141328, -34.82170453629492, 63.39686648861513, 69.37209759863701)
+SketchLine_3 = Sketch_1.addLine(63.39686648861513, 69.37209759863701, -27.43492861072797, 41.55044273324706)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_1.result())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+model.do()
+Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_3")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("WIRE", "Wire_1_1")], [model.selection("VERTEX", "Vertex_1_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1,model,1,[0],[0],[0],[4],[8])
+model.testHaveNamingSubshapes(Boolean_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillWireWire.py b/src/FeaturesPlugin/Test/TestFillWireWire.py
new file mode 100644 (file)
index 0000000..7bf2f0a
--- /dev/null
@@ -0,0 +1,67 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "R", "50")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-49.81325699578132, 35.39936274902501, 0, 8.200436015051352)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_2 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.result())
+SketchLine_3 = Sketch_1.addLine(0, 8.200436015051352, 49.94978427678259, 33.32234621934526)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_3.startPoint())
+SketchArc_1 = Sketch_1.addArc(0, 31.08202242513997, 49.94978427678259, 33.32234621934526, -49.81325699578132, 35.39936274902501, False)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchArc_1.endPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchArc_1.center(), SketchLine_2.result())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], "R")
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_4 = Sketch_2.addLine(31.79164821526215, 49.99496405877289, 8.200436015051352, 0)
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_3s-SketchLine_1e"), False)
+SketchPoint_1 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchPoint_1.result())
+SketchLine_5 = Sketch_2.addLine(8.200436015051352, 0, 27.24680168984479, -49.85269382803262)
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchProjection_3 = Sketch_2.addProjection(model.selection("VERTEX", "Sketch_1/Vertex-SketchArc_1"), False)
+SketchPoint_2 = SketchProjection_3.createdFeature()
+SketchArc_2 = Sketch_2.addArc(31.08202242513997, 1.147024884467139e-021, 27.24680168984479, -49.85269382803262, 31.79164821526215, 49.99496405877289, False)
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchPoint_2.result(), SketchArc_2.center())
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchArc_2.startPoint())
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchArc_2.endPoint(), SketchLine_4.startPoint())
+SketchConstraintRadius_2 = Sketch_2.setRadius(SketchArc_2.results()[1], "R")
+model.do()
+Wire_1 = model.addWire(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_1f-SketchLine_3f-SketchArc_1_2f")])
+Wire_2 = model.addWire(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchLine_4f-SketchLine_5f-SketchArc_2_2f")])
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("WIRE", "Wire_1_1")], [model.selection("WIRE", "Wire_2_1")])
+model.do()
+
+model.checkBooleansResult(Boolean_1, model, 1, [0], [0], [0], [4], [8])
+model.testHaveNamingSubshapes(Boolean_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestFillet.py b/src/FeaturesPlugin/Test/TestFillet.py
new file mode 100644 (file)
index 0000000..49831b3
--- /dev/null
@@ -0,0 +1,134 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+"""
+      TestFillet.py
+      Unit test of FeaturesPlugin_Fillet class
+"""
+
+from ModelAPI 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")
+aPoint.real("x").setValue(20)
+aPoint.real("y").setValue(5)
+aPoint.real("z").setValue(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 fillet with fixed radius
+#=========================================================================
+aSession.startOperation()
+aFillet1 = aPart.addFeature("Fillet")
+aFillet1.string("creation_method").setValue("fixed_radius")
+anObjects = aFillet1.selectionList("main_objects")
+anObjects.append("Box_1_1/Left&Box_1_1/Top", "edge")
+aFillet1.real("radius1").setValue(3)
+aSession.finishOperation()
+assert(aFillet1.error() == ""), "FAILED: Fillet reports error \"{}\"".format(aFillet1.error())
+
+#=========================================================================
+# Test 2. Change fillet type
+#=========================================================================
+aSession.startOperation()
+aFillet1.string("creation_method").setValue("variable_radius")
+aFillet1.real("radius1").setValue(5)
+aFillet1.real("radius2").setValue(1)
+aSession.finishOperation()
+assert(aFillet1.error() == ""), "FAILED: Fillet reports error \"{}\"".format(aFillet1.error())
+
+#=========================================================================
+# Test 3. Check fillet reports error if selected entities from different solids
+#=========================================================================
+aSession.startOperation()
+aFillet2 = aPart.addFeature("Fillet")
+aFillet2.string("creation_method").setValue("fixed_radius")
+anObjects = aFillet2.selectionList("main_objects")
+anObjects.append("Cylinder_1_1/Face_2", "face")
+anObjects.append("_Box_1_1/Right", "face")
+aFillet2.real("radius1").setValue(2)
+aSession.finishOperation()
+assert(aFillet2.error() != ""), "FAILED: Fillet does not report error"
+
+#=========================================================================
+# Test 4. Fix the error
+#=========================================================================
+aSession.startOperation()
+anObjects.removeLast()
+aSession.finishOperation()
+assert(aFillet2.error() == ""), "FAILED: Fillet reports error \"{}\"".format(aFillet1.error())
+
+#=========================================================================
+# Test 5. Check fillet reports error on smoothly connected edges
+#=========================================================================
+aSession.startOperation()
+aFillet3 = aPart.addFeature("Fillet")
+aFillet3.string("creation_method").setValue("fixed_radius")
+aFillet3.selectionList("main_objects").append("Cylinder_1_1/Modified_Face_1", "face")
+aFillet3.real("radius1").setValue(3)
+aSession.finishOperation()
+assert(aFillet3.lastResult() is None), "FAILED: Fillet should not produce a result"
+
+#=========================================================================
+# Test 6. Remove last fillet feature
+#=========================================================================
+aSession.startOperation()
+aPart.removeFeature(aFillet3)
+aSession.finishOperation()
+
+#=========================================================================
+# End of test
+#=========================================================================
+
+from salome.shaper import model
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestPartition2Faces.py b/src/FeaturesPlugin/Test/TestPartition2Faces.py
new file mode 100644 (file)
index 0000000..2df969a
--- /dev/null
@@ -0,0 +1,55 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(55.40972222222221, 31.70277777777777, -46.71249999999999, 31.70277777777777)
+SketchLine_2 = Sketch_1.addLine(-46.71249999999999, 31.70277777777777, -46.71249999999999, -45.44999999999999)
+SketchLine_3 = Sketch_1.addLine(-46.71249999999999, -45.44999999999999, 55.40972222222221, -45.44999999999999)
+SketchLine_4 = Sketch_1.addLine(55.40972222222221, -45.44999999999999, 55.40972222222221, 31.70277777777777)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_2.addCircle(64.38749999999999, 45.44999999999999, 41.86298795836804)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_4"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_3"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_2")])
+Face_2 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchCircle_1_2")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("FACE", "Face_2_1")])
+model.do()
+
+model.checkBooleansResult(Partition_1,model,1,[3],[0],[3],[12],[24])
+model.testHaveNamingSubshapes(Partition_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestPartition2Solids.py b/src/FeaturesPlugin/Test/TestPartition2Solids.py
new file mode 100644 (file)
index 0000000..6f24049
--- /dev/null
@@ -0,0 +1,69 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+from GeomAPI import GeomAPI_Shape
+
+model.begin()
+#Create part
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+#Create Sketch_1 - closed polyline from 5 segments
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_1 = Sketch_1.addLine(-43.90694444444443, 28.05555555555554, 19.21805555555554, 72.66388888888889)
+SketchLine_2 = Sketch_1.addLine(19.21805555555554, 72.66388888888889, 82.06249999999999, -36.19166666666666)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(82.06249999999999, -36.19166666666666, 19.4986111111111, -81.3611111111111)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(19.4986111111111, -81.3611111111111, -45.87083333333333, -45.44999999999999)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(-45.87083333333333, -45.44999999999999, -43.90694444444443, 28.05555555555554)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_5.endPoint())
+model.do()
+#Create Extrusion_1 on Sketch_1
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r-SketchLine_5r")], model.selection(), 100, 0)
+#Create Sketch_2 from 5 segments
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_3"))
+SketchLine_6 = Sketch_2.addLine(74.07000206783135, -18.10965884648514, 62.37497281453477, -31.70853007124862)
+SketchLine_7 = Sketch_2.addLine(62.37497281453477, -31.70853007124862, 37.35304976096997, -31.43655264675337)
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchLine_8 = Sketch_2.addLine(37.35304976096997, -31.43655264675337, 25.65802050767337, -1.791013376768974)
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchLine_9 = Sketch_2.addLine(25.65802050767337, -1.791013376768974, 69.44638585141178, 6.640286782584385)
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchLine_10 = Sketch_2.addLine(69.44638585141178, 6.640286782584385, 74.07000206783135, -18.10965884648514)
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint())
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_6.startPoint(), SketchLine_10.endPoint())
+model.do()
+#Create Extrusion_2 on Sketch_2
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_6r-SketchLine_7r-SketchLine_8r-SketchLine_9r-SketchLine_10r")], model.selection(), 10, 160)
+#Create Partition on objects Extrusion_1 and Extrusion_2
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_2_1")])
+model.do()
+
+model.checkBooleansResult(Partition_1,model,1,[4],[4],[33],[150],[300])
+model.testHaveNamingSubshapes(Partition_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestPartition2Wires.py b/src/FeaturesPlugin/Test/TestPartition2Wires.py
new file mode 100644 (file)
index 0000000..cf0552a
--- /dev/null
@@ -0,0 +1,62 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_1 = Sketch_1.addLine(-59.3375, 27.49444444444443, -20.05972222222222, 71.26111111111109)
+SketchLine_2 = Sketch_1.addLine(-20.05972222222222, 71.26111111111109, 31.5625, 60.31944444444444)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(31.5625, 60.31944444444444, 48.95694444444444, -41.52222222222221)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(48.95694444444444, -41.52222222222221, -7.434722222222216, -63.6861111111111)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(-7.434722222222216, -63.6861111111111, -12.20416666666666, 3.0861111111111)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_1.addLine(-12.20416666666666, 3.0861111111111, -59.3375, 27.49444444444443)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_1.startPoint())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchArc_1 = Sketch_2.addArc(-25.27347239223771, 29.23826809458483, -58.42699662355402, 67.59234514649975, 1.894762451441686, -13.56451698932517, False)
+SketchLine_7 = Sketch_2.addLine(-58.42699662355402, 67.59234514649975, 66.71130562210065, 43.53978835123107)
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchArc_1.startPoint(), SketchLine_7.startPoint())
+SketchLine_8 = Sketch_2.addLine(66.71130562210065, 43.53978835123107, 30.30743587791019, -67.62202818906478)
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchLine_9 = Sketch_2.addLine(30.30743587791019, -67.62202818906478, 1.894762451441686, -13.56451698932518)
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchArc_1.endPoint(), SketchLine_9.endPoint())
+model.do()
+Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_7"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_8"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_9"), model.selection("EDGE", "Sketch_2/Edge-SketchArc_1_2")])
+Wire_2 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_3"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_4"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_5"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_6")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("WIRE", "Wire_2_1"), model.selection("WIRE", "Wire_1_1")])
+model.do()
+
+model.checkBooleansResult(Partition_1,model,1,[2],[0],[0],[22],[44])
+model.testHaveNamingSubshapes(Partition_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestPartitionBox4Planes.py b/src/FeaturesPlugin/Test/TestPartitionBox4Planes.py
new file mode 100644 (file)
index 0000000..1a7a0e8
--- /dev/null
@@ -0,0 +1,41 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 100, 100, 400)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOY"), 100, False)
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Plane_1"), 100, False)
+Plane_6 = model.addPlane(Part_1_doc, model.selection("FACE", "Plane_2"), 100, False)
+Plane_7 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/YOZ"), 50, False)
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2"), model.selection("FACE", "Plane_3"), model.selection("FACE", "Plane_4"), model.selection("SOLID", "Box_1_1")])
+model.do()
+
+model.checkBooleansResult(Partition_1,model,1,[8],[8],[48],[192],[384])
+model.testHaveNamingSubshapes(Partition_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestPartitionEdgeSolid.py b/src/FeaturesPlugin/Test/TestPartitionEdgeSolid.py
new file mode 100644 (file)
index 0000000..3482667
--- /dev/null
@@ -0,0 +1,43 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Cone_1 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10, 5, 10)
+Point_1 = model.addPoint(Part_1_doc, 4, 5, 11)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("EDGE", "PartSet/OX"), model.selection("VERTEX", "Point_1"), False)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchLine_1 = Sketch_1.addLine(1.156555510724249, 12.03812858614785, 0.5812800089239156, -4.87167684997945)
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_1")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Cone_1_1"), model.selection("EDGE", "Edge_1_1")])
+model.do()
+
+model.checkBooleansResult(Partition_1,model,1,[3],[1],[3],[9],[20])
+model.testHaveNamingSubshapes(Partition_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestPartitionFace2Solid.py b/src/FeaturesPlugin/Test/TestPartitionFace2Solid.py
new file mode 100644 (file)
index 0000000..eec995b
--- /dev/null
@@ -0,0 +1,89 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+from SketchAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchArc_1 = Sketch_1.addArc(0, -23.6272731038225, 7.84836794507966, 9.071298990348682, 0, 10, False)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.result(), SketchArc_1.center())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.result(), SketchArc_1.endPoint())
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_2 = SketchProjection_2.createdFeature()
+SketchArc_2 = Sketch_1.addArc(5.671059039631239, 0, 7.84836794507966, 9.071298990348682, 15, 0, True)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.result(), SketchArc_2.center())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchArc_2.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_2.result(), SketchArc_2.endPoint())
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchArc_1.results()[1], SketchArc_2.results()[1])
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Line(SketchLine_2).startPoint(), SketchArc_2.endPoint(), 15, True)
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchAPI_Line(SketchLine_2).startPoint(), SketchArc_1.endPoint(), 10, True)
+SketchConstraintMirror_1 = Sketch_1.addMirror(SketchLine_2.result(), [SketchArc_2.results()[1], SketchArc_1.results()[1]])
+[SketchArc_3, SketchArc_4] = SketchConstraintMirror_1.mirrored()
+SketchConstraintMirror_2_objects = [SketchArc_1.results()[1], SketchArc_2.results()[1], SketchArc_3.results()[1], SketchArc_4.results()[1]]
+SketchConstraintMirror_2 = Sketch_1.addMirror(SketchLine_1.result(), SketchConstraintMirror_2_objects)
+[SketchArc_5, SketchArc_6, SketchArc_7, SketchArc_8] = SketchConstraintMirror_2.mirrored()
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), 12, 12)
+
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face_1"))
+SketchLine_3 = Sketch_2.addLine(7.498934040825037, 4.111344571723496, -7.530337532973568, 4.111344571723496)
+SketchLine_4 = Sketch_2.addLine(-7.530337532973568, 4.111344571723496, -7.530337532973568, -4.489390918751097)
+SketchLine_5 = Sketch_2.addLine(-7.530337532973568, -4.489390918751097, 7.498934040825037, -4.489390918751097)
+SketchLine_6 = Sketch_2.addLine(7.498934040825037, -4.489390918751097, 7.498934040825037, 4.111344571723496)
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintHorizontal_1 = Sketch_2.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_4.result())
+SketchConstraintHorizontal_2 = Sketch_2.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_2 = Sketch_2.setVertical(SketchLine_6.result())
+SketchCircle_1 = Sketch_2.addCircle(-0.133117930244568, 0.08984026389066591, 1.099112071963378)
+model.do()
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_6f-SketchCircle_1_2r")], model.selection(), model.selection(), 5, model.selection(), 10)
+
+Sketch_3 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_7 = Sketch_3.addLine(21.55890075100801, 30.21822825485694, -17.43219636481839, 31.63011070278906)
+SketchLine_8 = Sketch_3.addLine(-17.43219636481839, 31.63011070278906, -12.33809712604348, -45.93749869468675)
+SketchConstraintCoincidence_10 = Sketch_3.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchLine_9 = Sketch_3.addLine(-12.33809712604348, -45.93749869468675, 30.10255255530162, -25.9120009302625)
+SketchConstraintCoincidence_11 = Sketch_3.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchLine_10 = Sketch_3.addLine(30.10255255530162, -25.9120009302625, 21.55890075100801, 30.21822825485694)
+SketchConstraintCoincidence_12 = Sketch_3.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint())
+SketchConstraintCoincidence_13 = Sketch_3.setCoincident(SketchLine_7.startPoint(), SketchLine_10.endPoint())
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_3/Edge-SketchLine_7"), model.selection("EDGE", "Sketch_3/Edge-SketchLine_8"), model.selection("EDGE", "Sketch_3/Edge-SketchLine_9"), model.selection("EDGE", "Sketch_3/Edge-SketchLine_10")])
+
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("SOLID", "Extrusion_2_1"), model.selection("SOLID", "Extrusion_1_1")])
+model.do()
+
+model.checkBooleansResult(Partition_1,model,1,[2],[4],[42],[198],[396])
+model.testHaveNamingSubshapes(Partition_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestPartitionFaceSolid.py b/src/FeaturesPlugin/Test/TestPartitionFaceSolid.py
new file mode 100644 (file)
index 0000000..3135905
--- /dev/null
@@ -0,0 +1,74 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_1 = Sketch_1.addLine(29.00299588076832, 85.46917598420691, 38.5336063380206, 85.46917598420691)
+SketchLine_2 = Sketch_1.addLine(38.5336063380206, 85.46917598420691, 51.24108694769031, 59.52473640613128)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(51.24108694769031, 59.52473640613128, 51.24108694769031, 20.87281621838598)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(51.24108694769031, 20.87281621838598, 74.53813473208469, 20.87281621838598)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(74.53813473208469, 20.87281621838598, 74.53813473208469, 7.635857249980032)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_1.addLine(74.53813473208469, 7.635857249980032, 29.00299588076832, 7.635857249980032)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchLine_7 = Sketch_1.addLine(29.00299588076832, 7.635857249980032, 29.00299588076832, 85.46917598420691)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_7.endPoint())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_7.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_3.result())
+SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_5.result())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_6.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_4.result())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_1.result())
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r-SketchLine_5r-SketchLine_6r-SketchLine_7r")], model.selection("EDGE", "PartSet/OZ"), 180, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Revolution_1_1/To_Face_1"))
+SketchLine_8 = Sketch_2.addLine(61.72045613220821, 51.92790864086226, -64.56856594464165, 51.92790864086226)
+SketchLine_9 = Sketch_2.addLine(-64.56856594464165, 51.92790864086226, -64.56856594464165, -5.323114700643004)
+SketchLine_10 = Sketch_2.addLine(-64.56856594464165, -5.323114700643004, 61.72045613220821, -5.323114700643004)
+SketchLine_11 = Sketch_2.addLine(61.72045613220821, -5.323114700643004, 61.72045613220821, 51.92790864086226)
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_11.endPoint(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint())
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint())
+SketchConstraintHorizontal_4 = Sketch_2.setHorizontal(SketchLine_8.result())
+SketchConstraintVertical_4 = Sketch_2.setVertical(SketchLine_9.result())
+SketchConstraintHorizontal_5 = Sketch_2.setHorizontal(SketchLine_10.result())
+SketchConstraintVertical_5 = Sketch_2.setVertical(SketchLine_11.result())
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_8"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_11"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_10"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_9")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Revolution_1_1"), model.selection("FACE", "Face_1_1")])
+model.do()
+
+model.checkBooleansResult(Partition_1,model,1,[4],[1],[16],[82],[164])
+model.testHaveNamingSubshapes(Partition_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestPartitionFaceWire.py b/src/FeaturesPlugin/Test/TestPartitionFaceWire.py
new file mode 100644 (file)
index 0000000..2245856
--- /dev/null
@@ -0,0 +1,65 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchArc_1 = Sketch_1.addArc(-27.59408640325028, 19.28272273466096, -69.22045455254333, 36.34312971236017, -20.39867310978187, 63.6903576534723, True)
+SketchLine_1 = Sketch_1.addLine(-20.39867310978187, 63.6903576534723, 50.06261173489778, 52.27344552622073)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.startPoint())
+SketchLine_2 = Sketch_1.addLine(50.06261173489778, 52.27344552622073, 61.51017441860466, -50.20639534883721)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(61.51017441860466, -50.20639534883721, -40.37063953488371, -58.72093023255813)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(-40.37063953488371, -58.72093023255813, -8.587370006050145, 0.9678324888285939)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(-8.587370006050145, 0.9678324888285939, -69.22045455254333, 36.34312971236017)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_5.endPoint())
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchLine_1.result(), SketchArc_1.results()[1])
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchArc_2 = Sketch_2.addArc(25.75044090453202, 23.87245760846999, -31.39978593836629, 46.7325483456293, 20.55274339063303, 85.20528827247816, True)
+SketchLine_6 = Sketch_2.addLine(20.55274339063303, 85.20528827247816, 74.86874397491491, -32.65992894423484)
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchArc_2.endPoint(), SketchLine_6.startPoint())
+SketchLine_7 = Sketch_2.addLine(74.86874397491491, -32.65992894423484, 9.995513504597909, -67.56790534016733)
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchLine_8 = Sketch_2.addLine(9.995513504597909, -67.56790534016733, -36.0335881148175, -7.328477046301525)
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchLine_9 = Sketch_2.addLine(-36.0335881148175, -7.328477046301525, -31.39978593836629, 46.7325483456293)
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchArc_2.startPoint(), SketchLine_9.endPoint())
+model.do()
+Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchArc_1_2"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_3"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_4"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_5")])
+Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_9"), model.selection("EDGE", "Sketch_2/Edge-SketchArc_2_2"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_6"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_7"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_8")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("WIRE", "Wire_1_1")])
+model.do()
+
+model.checkBooleansResult(Partition_1,model,1,[6],[0],[5],[39],[78])
+model.testHaveNamingSubshapes(Partition_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestPartitionInclinedFaceSolid.py b/src/FeaturesPlugin/Test/TestPartitionInclinedFaceSolid.py
new file mode 100644 (file)
index 0000000..4d9856a
--- /dev/null
@@ -0,0 +1,57 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchCircle_1 = Sketch_1.addCircle(-18.11540697674418, -21.53002906976744, 69.96519983648402)
+SketchCircle_2 = Sketch_1.addCircle(-18.11540697674418, -21.53002906976744, 31.60961705559024)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchCircle_1.center(), SketchCircle_2.center())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f-SketchCircle_2_2r")], model.selection(), 100, 0)
+Point_2 = model.addPoint(Part_1_doc, 100, 40, 80)
+Point_3 = model.addPoint(Part_1_doc, 100, -40, 80)
+Point_4 = model.addPoint(Part_1_doc, 20, 40, -80)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("VERTEX", "Point_1"), model.selection("VERTEX", "Point_2"), model.selection("VERTEX", "Point_3"))
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchLine_1 = Sketch_2.addLine(98.50650093667804, 100.9440062780326, 111.3990833103819, -44.73923695837706)
+SketchLine_2 = Sketch_2.addLine(111.3990833103819, -44.73923695837706, -130.2032518739455, -87.67357443122384)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(-130.2032518739455, -87.67357443122384, -102.5665996005733, 115.6113578178721)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_2.addLine(-102.5665996005733, 115.6113578178721, 98.50650093667804, 100.9440062780326)
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_4.endPoint())
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_4"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_1"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_2"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_3")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1"), model.selection("FACE", "Face_1_1")])
+model.do()
+
+model.checkBooleansResult(Partition_1,model,1,[3],[2],[10],[30],[60])
+model.testHaveNamingSubshapes(Partition_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestPartitionWireFaceSolid.py b/src/FeaturesPlugin/Test/TestPartitionWireFaceSolid.py
new file mode 100644 (file)
index 0000000..b45a245
--- /dev/null
@@ -0,0 +1,60 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Torus_1 = model.addTorus(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 15, 3)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_1 = Sketch_1.addLine(-6.378039652249388, 16.497623739925, 8.984305600666083, -24.54329369827008)
+SketchLine_2 = Sketch_1.addLine(8.984305600666083, -24.54329369827008, 36.73713621773835, -5.929982231235201)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(36.73713621773835, -5.929982231235201, 19.18554250372658, 21.11854572580065)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(19.18554250372658, 21.11854572580065, -6.378039652249388, 16.497623739925)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_4.endPoint())
+SketchCircle_1 = Sketch_1.addCircle(14.49765103937751, 9.678507230150521, 3.831444106492329)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_4"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_3"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), model.selection("EDGE", "Sketch_1/Edge-SketchCircle_1_2")])
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_5 = Sketch_2.addLine(-15.11211565655763, 11.99814589971457, -14.79635576556081, -11.77064279967296)
+SketchLine_6 = Sketch_2.addLine(-14.79635576556081, -11.77064279967296, -3.043616368139293, -11.46189011940212)
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchLine_7 = Sketch_2.addLine(-3.043616368139293, -11.46189011940212, -3.922197168000547, 15.83568871823551)
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchLine_8 = Sketch_2.addLine(-3.922197168000547, 15.83568871823551, -15.11211565655763, 11.99814589971457)
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_5.startPoint(), SketchLine_8.endPoint())
+model.do()
+Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_8"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_5"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_6"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_7")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("SOLID", "Torus_1_1"), model.selection("WIRE", "Wire_1_1")])
+model.do()
+
+model.checkBooleansResult(Partition_1,model,1,[3],[1],[4],[22],[46])
+model.testHaveNamingSubshapes(Partition_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestUnion4CurvedFaces.py b/src/FeaturesPlugin/Test/TestUnion4CurvedFaces.py
new file mode 100644 (file)
index 0000000..da123a8
--- /dev/null
@@ -0,0 +1,50 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchArc_1 = Sketch_1.addArc(0, 0, 14.26163338647443, -11.82948087533604, 14.26163338647443, 11.82948087533609, False)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchArc_1.center())
+SketchLine_1 = Sketch_1.addLine(14.26163338647443, -11.82948087533604, 14.26163338647443, 11.82948087533609)
+SketchLine_1.setAuxiliary(True)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.endPoint())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_1.result())
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchArc_1_2")])
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("EDGE", "Edge_1_1")], model.selection("EDGE", "PartSet/OY"), 200, 0)
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("FACE", "PartSet/XOZ"), model.selection("FACE", "Revolution_1_1")])
+Union_1 = model.addUnion(Part_1_doc, [model.selection("FACE", "Partition_1_1_1"), model.selection("FACE", "Partition_1_1_2")])
+model.do()
+
+model.checkBooleansResult(Union_1,model,1,[0],[0],[1],[4],[8])
+model.testHaveNamingSubshapes(Union_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestUnion4Faces.py b/src/FeaturesPlugin/Test/TestUnion4Faces.py
new file mode 100644 (file)
index 0000000..7557083
--- /dev/null
@@ -0,0 +1,66 @@
+## Copyright (C) 2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-44.48110465116279, 12.33139534883721, -38.60901162790698, 48.15116279069767)
+SketchLine_2 = Sketch_1.addLine(-38.60901162790698, 48.15116279069767, 16.88226744186047, 78.68604651162791)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(16.88226744186047, 78.68604651162791, 48.29796511627906, 10.86337209302326)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(48.29796511627906, 10.86337209302326, 31.85610465116278, -38.16860465116279)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(31.85610465116278, -38.16860465116279, -44.48110465116279, 12.33139534883721)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_1.startPoint())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r-SketchLine_5r"))
+SketchLine_6 = Sketch_2.addLine(31.85610465116278, -38.16860465116279, -40.43276493886778, -56.03425756438362)
+SketchProjection_1 = Sketch_2.addProjection(model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_5s-SketchLine_4e"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_6.startPoint(), SketchPoint_1.result())
+SketchLine_7 = Sketch_2.addLine(-40.43276493886778, -56.03425756438362, -115.5003601973775, -26.06900348999911)
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchLine_8 = Sketch_2.addLine(-115.5003601973775, -26.06900348999911, -106.2327558444751, 34.47934494896344)
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchLine_9 = Sketch_2.addLine(-106.2327558444751, 34.47934494896344, -44.48110465116279, 12.33139534883721)
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_1s-SketchLine_5e"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_9.endPoint(), SketchPoint_2.result())
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_3"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_4"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_5")])
+Face_2 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_9"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_5"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_6"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_7"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_8")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("FACE", "Face_2_1"), model.selection("FACE", "Face_1_1"), model.selection("FACE", "PartSet/YOZ")])
+Union_1 = model.addUnion(Part_1_doc, [model.selection("FACE", "Partition_1_1_1"), model.selection("FACE", "Partition_1_1_3"), model.selection("FACE", "Partition_1_1_4")])
+model.do()
+
+model.checkBooleansResult(Union_1,model,1,[2],[0],[2],[13],[26])
+#model.testHaveNamingSubshapes(Union_1,model,Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
index a5c4e919502f7e567b52fe6a6fe68be3c39914e9..015c1d0e5ecf409bcd4ed3915749fcdbdb73aca3 100644 (file)
@@ -34,7 +34,7 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
     label="Main objects"
     icon=""
     tooltip="Select objects"
-    type_choice="solids compsolids edges faces"
+    type_choice="vertices edges wires faces shells solids compsolids"
     use_choice="false"
     concealment="true">
     <validator id="PartSet_DifferentObjects"/>
@@ -44,7 +44,7 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
     label="Tool objects"
     icon=""
     tooltip="Select tools"
-    type_choice="solids compsolids edges faces"
+    type_choice="vertices edges wires faces shells solids compsolids"
     use_choice="false"
     concealment="true" >
     <validator id="PartSet_DifferentObjects"/>
diff --git a/src/FeaturesPlugin/fillet_widget.xml b/src/FeaturesPlugin/fillet_widget.xml
new file mode 100644 (file)
index 0000000..1ccb5bc
--- /dev/null
@@ -0,0 +1,76 @@
+<!--
+Copyright (C) 2017  CEA/DEN, EDF R&D
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+See http:##www.salome-platform.org/ or
+email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+-->
+
+<source>
+  <toolbox id="creation_method">
+    <box id="fixed_radius"
+         title="Fixed radius"
+         tooltip="Fillet with fixed radius"
+         icon="icons/Features/fillet_fixed_radius.png">
+      <multi_selector id="main_objects"
+                      label="Faces or/and edges"
+                      icon=""
+                      tooltip="Select objects"
+                      type_choice="edges faces"
+                      use_choice="false"
+                      concealment="true">
+        <validator id="PartSet_DifferentObjects"/>
+        <validator id="FeaturesPlugin_ValidatorFilletSelection"/>
+      </multi_selector>
+      <doublevalue id="radius1"
+                   label="Radius"
+                   tooltip="Fillet radius."
+                   min="0"
+                   default="2">
+        <validator id="GeomValidators_Positive"/>
+      </doublevalue>
+    </box>
+    <box id="variable_radius"
+         title="Varying radius"
+         tooltip="Fillet with varying radius"
+         icon="icons/Features/fillet_var_radius.png">
+      <multi_selector id="main_objects"
+                      label="Faces or/and edges"
+                      icon=""
+                      tooltip="Select objects"
+                      type_choice="edges faces"
+                      use_choice="false"
+                      concealment="true">
+        <validator id="PartSet_DifferentObjects"/>
+        <validator id="FeaturesPlugin_ValidatorFilletSelection"/>
+      </multi_selector>
+      <doublevalue id="radius1"
+                   label="Start radius"
+                   tooltip="Fillet radius at start point."
+                   min="0"
+                   default="2">
+        <validator id="GeomValidators_Positive"/>
+      </doublevalue>
+      <doublevalue id="radius2"
+                   label="End radius"
+                   tooltip="Fillet radius at end point."
+                   min="0"
+                   default="2">
+        <validator id="GeomValidators_Positive"/>
+      </doublevalue>
+    </box>
+  </toolbox>
+</source>
diff --git a/src/FeaturesPlugin/icons/fillet.png b/src/FeaturesPlugin/icons/fillet.png
new file mode 100644 (file)
index 0000000..3b5a982
Binary files /dev/null and b/src/FeaturesPlugin/icons/fillet.png differ
diff --git a/src/FeaturesPlugin/icons/fillet_fixed_radius.png b/src/FeaturesPlugin/icons/fillet_fixed_radius.png
new file mode 100644 (file)
index 0000000..0897bde
Binary files /dev/null and b/src/FeaturesPlugin/icons/fillet_fixed_radius.png differ
diff --git a/src/FeaturesPlugin/icons/fillet_var_radius.png b/src/FeaturesPlugin/icons/fillet_var_radius.png
new file mode 100644 (file)
index 0000000..56e4a78
Binary files /dev/null and b/src/FeaturesPlugin/icons/fillet_var_radius.png differ
index 298723427364fc02046e55c5d8f173c59e17625d..88c1c02908bff6ea939f6287c325168571af6078 100644 (file)
@@ -80,6 +80,11 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
         <source path="recover_widget.xml"/>
       </feature>
     </group>
+    <group id="Fillet">
+      <feature id="Fillet" title="Fillet" tooltip="Perform fillet on face or edge" icon="icons/Features/fillet.png" auto_preview="true">
+        <source path="fillet_widget.xml"/>
+      </feature>
+    </group>
   </workbench>
   <workbench id="Part">
     <group id="Movement">
@@ -95,10 +100,10 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
       <feature id="Symmetry" title="Symmetry" tooltip="Perform symmetry with respect to a point, an axis or a plane" icon="icons/Features/symmetry.png">
         <source path="symmetry_widget.xml"/>
       </feature>
-      <feature id="MultiTranslation" title="MultiTranslation" tooltip="Perform multi-translation objects" icon="icons/Features/multitranslation.png">
+      <feature id="LinearCopy" title="Linear copy" tooltip="Perform copy and translate" icon="icons/Features/multitranslation.png">
         <source path="multitranslation_widget.xml"/>
       </feature>
-      <feature id="MultiRotation" title="MultiRotation" tooltip="Perform multi-rotation objects" icon="icons/Features/multirotation.png">
+      <feature id="AngularCopy" title="Angular Copy" tooltip="Perform copy and rotate" icon="icons/Features/multirotation.png">
         <source path="multirotation_widget.xml"/>
       </feature>
     </group>
index d5132057c681ba2403233e98076ec0c0d364d2a4..a7497c0dc511501d449e667aa10c8c486263b47e 100644 (file)
@@ -24,7 +24,8 @@
 #include <NCollection_Map.hxx>
 #include <TopoDS_Shape.hxx>
 
-#define MY_MAP implPtr<NCollection_DataMap<TopoDS_Shape, NCollection_Map<TopoDS_Shape> > >()
+typedef NCollection_DataMap<TopoDS_Shape, NCollection_Map<TopoDS_Shape> > MAP;
+#define MY_MAP implPtr<MAP>()
 
 //=================================================================================================
 GeomAPI_DataMapOfShapeMapOfShapes::GeomAPI_DataMapOfShapeMapOfShapes()
@@ -113,3 +114,158 @@ int GeomAPI_DataMapOfShapeMapOfShapes::size() const
 {
   return MY_MAP->Size();
 }
+
+
+//=================================================================================================
+//   iterator implementation
+//=================================================================================================
+
+class IteratorImpl : public GeomAPI_DataMapOfShapeMapOfShapes::iterator
+{
+public:
+  IteratorImpl() {}
+
+  IteratorImpl(const MAP::Iterator& theIterator)
+    : myIterator(theIterator)
+  {}
+
+  IteratorImpl(const std::shared_ptr<IteratorImpl>& theIterator)
+  {
+    mySelf = theIterator;
+  }
+
+  bool operator==(const std::shared_ptr<IteratorImpl>& theOther) const
+  {
+    if (theOther)
+      return theOther->myIterator.IsEqual(myIterator);
+
+    // theOther is end iterator => check the current iterator is not at the end
+    return !myIterator.More();
+  }
+
+  virtual iterator& operator++()
+  {
+    myIterator.Next();
+    return *this;
+  }
+  virtual iterator operator++(int)
+  {
+    std::shared_ptr<IteratorImpl> aSelf = std::dynamic_pointer_cast<IteratorImpl>(mySelf);
+    std::shared_ptr<IteratorImpl> aCopy(new IteratorImpl(aSelf->myIterator));
+    myIterator.Next();
+    return IteratorImpl(aCopy);
+  }
+
+  virtual key_type first() const
+  {
+    if (mySelf)
+      return iterator::first();
+
+    GeomShapePtr aShape(new GeomAPI_Shape);
+    aShape->setImpl(new TopoDS_Shape(myIterator.Key()));
+    return aShape;
+  }
+
+  virtual mapped_type second() const
+  {
+    if (mySelf)
+      return iterator::second();
+
+    ListOfShape anItems;
+    const NCollection_Map<TopoDS_Shape>& aMap = myIterator.Value();
+    for(NCollection_Map<TopoDS_Shape>::Iterator anIt(aMap); anIt.More(); anIt.Next()) {
+      std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape);
+      aShape->setImpl(new TopoDS_Shape(anIt.Value()));
+      anItems.push_back(aShape);
+    }
+    return anItems;
+  }
+
+private:
+  MAP::Iterator myIterator;
+};
+
+
+GeomAPI_DataMapOfShapeMapOfShapes::iterator::iterator()
+{
+}
+
+GeomAPI_DataMapOfShapeMapOfShapes::iterator::iterator(
+    const GeomAPI_DataMapOfShapeMapOfShapes::iterator& theOther)
+  : mySelf(theOther.mySelf)
+{
+}
+
+const GeomAPI_DataMapOfShapeMapOfShapes::iterator&
+    GeomAPI_DataMapOfShapeMapOfShapes::iterator::operator=(
+      const GeomAPI_DataMapOfShapeMapOfShapes::iterator& theOther)
+{
+  mySelf = theOther.mySelf;
+  return *this;
+}
+
+bool GeomAPI_DataMapOfShapeMapOfShapes::iterator::operator==(const iterator& theOther) const
+{
+  std::shared_ptr<IteratorImpl> aSelf = std::dynamic_pointer_cast<IteratorImpl>(mySelf);
+  std::shared_ptr<IteratorImpl> aSelfOther =
+      std::dynamic_pointer_cast<IteratorImpl>(theOther.mySelf);
+
+  return aSelf ? aSelf->operator==(aSelfOther)
+                : (aSelfOther ? aSelfOther->operator==(aSelf) : true);
+}
+
+bool GeomAPI_DataMapOfShapeMapOfShapes::iterator::operator!=(const iterator& theOther) const
+{
+  return !operator==(theOther);
+}
+
+GeomAPI_DataMapOfShapeMapOfShapes::iterator&
+    GeomAPI_DataMapOfShapeMapOfShapes::iterator::operator++()
+{
+  mySelf->operator++();
+  return *this;
+}
+
+GeomAPI_DataMapOfShapeMapOfShapes::iterator
+    GeomAPI_DataMapOfShapeMapOfShapes::iterator::operator++(int)
+{
+  return ++(*mySelf);
+}
+
+GeomAPI_DataMapOfShapeMapOfShapes::iterator::key_type
+    GeomAPI_DataMapOfShapeMapOfShapes::iterator::first() const
+{
+  return mySelf->first();
+}
+
+GeomAPI_DataMapOfShapeMapOfShapes::iterator::mapped_type
+    GeomAPI_DataMapOfShapeMapOfShapes::iterator::second() const
+{
+  return mySelf->second();
+}
+
+
+
+GeomAPI_DataMapOfShapeMapOfShapes::iterator GeomAPI_DataMapOfShapeMapOfShapes::begin()
+{
+  MAP::Iterator anIt(*MY_MAP);
+  std::shared_ptr<IteratorImpl> anIter(new IteratorImpl(anIt));
+  return IteratorImpl(anIter);
+}
+
+GeomAPI_DataMapOfShapeMapOfShapes::const_iterator GeomAPI_DataMapOfShapeMapOfShapes::begin() const
+{
+  MAP::Iterator anIt(*MY_MAP);
+  std::shared_ptr<IteratorImpl> anIter(new IteratorImpl(anIt));
+  return IteratorImpl(anIter);
+}
+
+GeomAPI_DataMapOfShapeMapOfShapes::iterator GeomAPI_DataMapOfShapeMapOfShapes::end()
+{
+  return IteratorImpl(std::shared_ptr<IteratorImpl>());
+}
+
+GeomAPI_DataMapOfShapeMapOfShapes::const_iterator GeomAPI_DataMapOfShapeMapOfShapes::end() const
+{
+  return IteratorImpl(std::shared_ptr<IteratorImpl>());
+}
index 9e631c861ebacdeaa0751971773dd328133aa25f..395abae3444c6cba1c40305d8be7a2d38a3d6da8 100644 (file)
@@ -64,6 +64,40 @@ public:
 
   /// \return size of map.
   GEOMAPI_EXPORT int size() const;
+
+public:
+  class iterator
+  {
+  public:
+    typedef GeomShapePtr key_type;
+    typedef ListOfShape  mapped_type;
+    typedef std::pair<GeomShapePtr, ListOfShape> value_type;
+
+  public:
+    GEOMAPI_EXPORT iterator();
+    GEOMAPI_EXPORT iterator(const iterator&);
+    GEOMAPI_EXPORT const iterator& operator=(const iterator&);
+
+    GEOMAPI_EXPORT bool operator==(const iterator&) const;
+    GEOMAPI_EXPORT bool operator!=(const iterator&) const;
+
+    GEOMAPI_EXPORT virtual iterator& operator++();
+    GEOMAPI_EXPORT virtual iterator  operator++(int);
+
+    GEOMAPI_EXPORT virtual key_type first() const;
+    GEOMAPI_EXPORT virtual mapped_type second() const;
+
+  protected:
+    std::shared_ptr<iterator> mySelf;
+  };
+
+  typedef iterator const_iterator;
+
+  GEOMAPI_EXPORT iterator begin();
+  GEOMAPI_EXPORT const_iterator begin() const;
+
+  GEOMAPI_EXPORT iterator end();
+  GEOMAPI_EXPORT const_iterator end() const;
 };
 
 #endif
index f9b01ceb6359f76219384ba4ef34f759fb39c38a..9b2b5d959e822ce1a6cc600802fd050f312edd90 100644 (file)
@@ -103,6 +103,12 @@ bool GeomAPI_Shape::isEdge() const
   return !aShape.IsNull() && aShape.ShapeType() == TopAbs_EDGE;
 }
 
+bool GeomAPI_Shape::isWire() const
+{
+  const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
+  return !aShape.IsNull() && aShape.ShapeType() == TopAbs_WIRE;
+}
+
 bool GeomAPI_Shape::isFace() const
 {
   const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
@@ -425,6 +431,11 @@ void GeomAPI_Shape::setOrientation(const GeomAPI_Shape::Orientation theOrientati
   }
 }
 
+void GeomAPI_Shape::reverse()
+{
+  MY_SHAPE->Reverse();
+}
+
 bool GeomAPI_Shape::isSubShape(const std::shared_ptr<GeomAPI_Shape> theShape,
                                const bool theCheckOrientation) const
 {
index 7a1f999971e30bd9078319421b3a6b80215c648a..51cd414c8b637044ad26813678e8d076026fe7f2 100644 (file)
@@ -78,6 +78,10 @@ public:
   GEOMAPI_EXPORT
   virtual bool isEdge() const;
 
+  /// Returns whether the shape is a wire
+  GEOMAPI_EXPORT
+  virtual bool isWire() const;
+
   /// Returns whether the shape is a face
   GEOMAPI_EXPORT
   virtual bool isFace() const;
@@ -123,6 +127,9 @@ public:
   /// Sets the shape orientation.
   GEOMAPI_EXPORT virtual void setOrientation(const Orientation theOrientation);
 
+  /// Reverse shape
+  GEOMAPI_EXPORT virtual void reverse();
+
   /// \return true if passed shape is a sub-shape of this shape.
   /// \param theShape shape to search.
   /// \param theCheckOrientation if false, returns true even if orientation of shape differs
index 039be40a873ffb450f9b7ad609a0b1bffd9c2453..e750f3ac59270b32f64ac6c65de31e72a9ec8bfa 100644 (file)
@@ -33,3 +33,11 @@ GeomAPI_Wire::GeomAPI_Wire()
 
   this->setImpl(aWire);
 }
+
+//==================================================================================================
+GeomAPI_Wire::GeomAPI_Wire(const std::shared_ptr<GeomAPI_Shape>& theShape)
+{
+  if (!theShape->isNull() && theShape->isWire()) {
+    setImpl(new TopoDS_Shape(theShape->impl<TopoDS_Shape>()));
+  }
+}
index 837039d4c15cc1473ceae00fb560bf35e80ac324..888e9b19c4165e2853fa7a1291118ebf62e3b5a1 100644 (file)
@@ -31,7 +31,11 @@ class GeomAPI_Wire: public GeomAPI_Shape
 public:
   /// Makes an undefined Wire.
   GEOMAPI_EXPORT GeomAPI_Wire();
+
+  /// Creation of wire by the wire-shape
+  GEOMAPI_EXPORT GeomAPI_Wire(const std::shared_ptr<GeomAPI_Shape>& theShape);
 };
 
-#endif
+typedef std::shared_ptr<GeomAPI_Wire> GeomWirePtr;
 
+#endif
index aa563452be9c29f5aa92b63c8de5e1b16c97aab6..81c0d1f0f422b740224e1c9b8013d78a52bdcc11 100644 (file)
@@ -74,6 +74,9 @@ SET(PROJECT_HEADERS
     GeomAlgoAPI_Scale.h
     GeomAlgoAPI_Circ2dBuilder.h
     GeomAlgoAPI_UnifySameDomain.h
+    GeomAlgoAPI_Fillet.h
+    GeomAlgoAPI_SortListOfShapes.h
+    GeomAlgoAPI_Filling.h
 )
 
 SET(PROJECT_SOURCES
@@ -126,6 +129,9 @@ SET(PROJECT_SOURCES
     GeomAlgoAPI_Scale.cpp
     GeomAlgoAPI_Circ2dBuilder.cpp
     GeomAlgoAPI_UnifySameDomain.cpp
+    GeomAlgoAPI_Fillet.cpp
+    GeomAlgoAPI_SortListOfShapes.cpp
+    GeomAlgoAPI_Filling.cpp
 )
 
 SET(PROJECT_LIBRARIES
@@ -140,6 +146,7 @@ SET(PROJECT_LIBRARIES
     ${CAS_TKBRep}
     ${CAS_TKCAF}
     ${CAS_TKCAF}
+    ${CAS_TKFillet}
     ${CAS_TKLCAF}
     ${CAS_TKPrim}
     ${CAS_TKSTEP}
index 775b64122d3707e1ddc438cca8acb1384c30ff24..71c5a05db255f81b91df106cb17bac1aff6e8704 100644 (file)
@@ -94,6 +94,7 @@
 %include "GeomAlgoAPI_ShapeAPI.h"
 %include "GeomAlgoAPI_Copy.h"
 %include "GeomAlgoAPI_Symmetry.h"
+%include "GeomAlgoAPI_Box.h"
 
 %typemap(out) std::list< std::shared_ptr< GeomAPI_Shape > >::value_type & {
   $result = SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<GeomAPI_Shape>(*$1)), $descriptor(std::shared_ptr<GeomAPI_Shape> *), SWIG_POINTER_OWN | 0 );
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Fillet.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Fillet.cpp
new file mode 100644 (file)
index 0000000..b3d510c
--- /dev/null
@@ -0,0 +1,86 @@
+// Copyright (C) 2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "GeomAlgoAPI_Fillet.h"
+
+#include <BRepFilletAPI_MakeFillet.hxx>
+
+//=================================================================================================
+GeomAlgoAPI_Fillet::GeomAlgoAPI_Fillet(const GeomShapePtr& theBaseSolid,
+                                       const ListOfShape&  theFilletEdges,
+                                       const double        theFilletRadius)
+{
+  build(theBaseSolid, theFilletEdges, theFilletRadius);
+}
+
+//=================================================================================================
+GeomAlgoAPI_Fillet::GeomAlgoAPI_Fillet(const GeomShapePtr& theBaseSolid,
+                                       const ListOfShape&  theFilletEdges,
+                                       const double        theStartRadius,
+                                       const double        theEndRadius)
+{
+  if (theEndRadius < 0.)
+    return;
+  build(theBaseSolid, theFilletEdges, theStartRadius, theEndRadius);
+}
+
+//=================================================================================================
+void GeomAlgoAPI_Fillet::build(const GeomShapePtr& theBaseSolid,
+                               const ListOfShape&  theFilletEdges,
+                               const double        theStartRadius,
+                               const double        theEndRadius)
+{
+  if (!theBaseSolid || theFilletEdges.empty() || theStartRadius < 0.)
+    return;
+
+  // create fillet builder
+  BRepFilletAPI_MakeFillet* aFilletBuilder =
+      new BRepFilletAPI_MakeFillet(theBaseSolid->impl<TopoDS_Shape>());
+  setImpl(aFilletBuilder);
+  setBuilderType(OCCT_BRepBuilderAPI_MakeShape);
+
+  // assign filleting edges
+  for (ListOfShape::const_iterator anIt = theFilletEdges.begin();
+       anIt != theFilletEdges.end(); ++anIt) {
+    if ((*anIt)->isEdge())
+      aFilletBuilder->Add( (*anIt)->impl<TopoDS_Edge>() );
+  }
+
+  // assign fillet radii for each contour of filleting edges
+  bool isFixedRadius = theEndRadius < 0.;
+  int aNbContours = aFilletBuilder->NbContours();
+  for (int ind = 1; ind <= aNbContours; ++ind) {
+    if (isFixedRadius)
+      aFilletBuilder->SetRadius(theStartRadius, ind, 1);
+    else
+      aFilletBuilder->SetRadius(theStartRadius, theEndRadius, ind, 1);
+  }
+
+  // build and get result
+  aFilletBuilder->Build();
+  if (!aFilletBuilder->IsDone())
+    return;
+  const TopoDS_Shape& aResult = aFilletBuilder->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_Fillet.h b/src/GeomAlgoAPI/GeomAlgoAPI_Fillet.h
new file mode 100644 (file)
index 0000000..56648cd
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright (C) 2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef GeomAlgoAPI_Fillet_H_
+#define GeomAlgoAPI_Fillet_H_
+
+#include <GeomAlgoAPI.h>
+#include <GeomAlgoAPI_MakeShape.h>
+
+#include <GeomAPI_Shape.h>
+
+/// \class GeomAlgoAPI_Fillet
+/// \ingroup DataAlgo
+/// \brief Perform fillet
+class GeomAlgoAPI_Fillet : public GeomAlgoAPI_MakeShape
+{
+public:
+  /// Run fillet operation with fixed radius.
+  /// \param theBaseSolid    a changing solid
+  /// \param theFilletEdges  list of edges the fillet is performed on
+  /// \param theFilletRadius radius of the fillet
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_Fillet(const GeomShapePtr& theBaseSolid,
+                                        const ListOfShape&  theFilletEdges,
+                                        const double        theFilletRadius);
+
+  /// Run fillet operation with variable radius.
+  /// \param theBaseSolid    a changing solid
+  /// \param theFilletEdges  list of edges the fillet is performed on
+  /// \param theStartRadius  start radius of the fillet
+  /// \param theEndRadius    end radius of the fillet
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_Fillet(const GeomShapePtr& theBaseSolid,
+                                        const ListOfShape&  theFilletEdges,
+                                        const double        theStartRadius,
+                                        const double        theEndRadius);
+
+private:
+  /// Perform fillet operation.
+  /// If theEndRadius is less than 0., the fixed radius fillet will be built.
+  /// \param theBaseSolid    a changing solid
+  /// \param theFilletEdges  list of edges the fillet is performed on
+  /// \param theStartRadius  start radius of the fillet
+  /// \param theEndRadius    end radius of the fillet
+  void build(const GeomShapePtr& theBaseSolid,
+             const ListOfShape&  theFilletEdges,
+             const double        theStartRadius,
+             const double        theEndRadius = -1.0);
+};
+
+#endif
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Filling.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Filling.cpp
new file mode 100644 (file)
index 0000000..338409a
--- /dev/null
@@ -0,0 +1,191 @@
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "GeomAlgoAPI_Filling.h"
+
+#include <BRep_Tool.hxx>
+#include <BRepBuilderAPI_MakeFace.hxx>
+#include <Geom_BSplineCurve.hxx>
+#include <Geom_BSplineSurface.hxx>
+#include <Geom_TrimmedCurve.hxx>
+#include <GeomAPI_PointsToBSplineSurface.hxx>
+#include <GeomFill_AppSurf.hxx>
+#include <GeomFill_Line.hxx>
+#include <GeomFill_SectionGenerator.hxx>
+#include <Precision.hxx>
+#include <ShapeFix_Face.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+
+static void edgesToCurves(const std::list<GeomEdgePtr>& theEdges,
+                          std::list<Handle(Geom_Curve)>& theCurves)
+{
+  for (std::list<GeomEdgePtr>::const_iterator anIt = theEdges.begin();
+       anIt != theEdges.end(); ++anIt) {
+    const TopoDS_Edge& anEdge = (*anIt)->impl<TopoDS_Edge>();
+    if (BRep_Tool::Degenerated(anEdge))
+      continue;
+
+    double aFirst, aLast;
+    Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
+
+    aCurve = new Geom_TrimmedCurve(aCurve, aFirst, aLast);
+    if (anEdge.Orientation() == TopAbs_REVERSED)
+      aCurve->Reverse();
+
+    theCurves.push_back(aCurve);
+  }
+}
+
+
+GeomAlgoAPI_Filling::GeomAlgoAPI_Filling(const int theMinDegree,
+                                         const int theMaxDegree,
+                                         const int theNbIter,
+                                         const double theTol2D,
+                                         const double theTol3D)
+  : myMinDegree(theMinDegree),
+    myMaxDegree(theMaxDegree),
+    myNbIter(theNbIter),
+    myTol2D(theTol2D),
+    myTol3D(theTol3D)
+{
+}
+
+void GeomAlgoAPI_Filling::add(const GeomEdgePtr theEdge)
+{
+  myConstraints.push_back(theEdge);
+}
+
+void GeomAlgoAPI_Filling::build(bool isApproximate)
+{
+  if (myConstraints.size() <= 1) // not enough edges
+    return;
+
+  if (isApproximate)
+    buildByControlPoints();
+  else
+    buildByEdges();
+}
+
+void GeomAlgoAPI_Filling::buildByEdges()
+{
+  GeomFill_SectionGenerator aSection;
+
+  // obtain section curves
+  std::list<Handle(Geom_Curve)> aCurves;
+  edgesToCurves(myConstraints, aCurves);
+  for (std::list<Handle(Geom_Curve)>::iterator anIt = aCurves.begin();
+       anIt != aCurves.end(); ++anIt)
+    aSection.AddCurve(*anIt);
+
+  // a 'tolerance' is used to compare 2 knots
+  aSection.Perform(Precision::PConfusion());
+  Handle(GeomFill_Line) aLine = new GeomFill_Line((int)aCurves.size());
+
+  // perform filling by sections
+  GeomFill_AppSurf anAppSurf(myMinDegree, myMaxDegree, myTol3D, myTol2D, myNbIter);
+  anAppSurf.Perform(aLine, aSection);
+  if (!anAppSurf.IsDone())
+    return;
+
+  // build calculated surface
+  Standard_Integer UDegree, VDegree, NbUPoles, NbVPoles, NbUKnots, NbVKnots;
+  anAppSurf.SurfShape(UDegree, VDegree, NbUPoles, NbVPoles, NbUKnots, NbVKnots);
+  Handle(Geom_BSplineSurface) GBS = new Geom_BSplineSurface(
+    anAppSurf.SurfPoles(), anAppSurf.SurfWeights(), anAppSurf.SurfUKnots(), anAppSurf.SurfVKnots(),
+    anAppSurf.SurfUMults(), anAppSurf.SurfVMults(), anAppSurf.UDegree(), anAppSurf.VDegree());
+
+  if (GBS.IsNull())
+    return;
+
+  // store result
+  TopoDS_Face aFace = BRepBuilderAPI_MakeFace(GBS, Precision::Confusion());
+  std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
+  aShape->setImpl(new TopoDS_Shape(aFace));
+  setShape(aShape);
+  setDone(true);
+}
+
+static Handle(Geom_Curve) removeTrim(const Handle(Geom_Curve)& theCurve)
+{
+  Handle(Geom_Curve) aCurve = theCurve;
+  Handle(Geom_TrimmedCurve) aTC = Handle(Geom_TrimmedCurve)::DownCast(aCurve);
+  while (!aTC.IsNull()) {
+    aCurve = aTC->BasisCurve();
+    aTC = Handle(Geom_TrimmedCurve)::DownCast(aCurve);
+  }
+  return aCurve;
+}
+
+void GeomAlgoAPI_Filling::buildByControlPoints()
+{
+  // obtain section curves
+  std::list<Handle(Geom_Curve)> aCurves;
+  edgesToCurves(myConstraints, aCurves);
+
+  // compute maximal number of poles in B-spline curves
+  int aMaxPoles = 0;
+  std::list<Handle(Geom_Curve)>::iterator anIt = aCurves.begin();
+  for (; anIt != aCurves.end(); ++anIt) {
+    Handle(Geom_BSplineCurve) aBC = Handle(Geom_BSplineCurve)::DownCast(removeTrim(*anIt));
+    if (!aBC.IsNull())
+      aMaxPoles = Max(aMaxPoles, aBC->NbPoles());
+  }
+
+  // prepare array of points for creation bspline surface
+  // size of this array: by U parameter - number of curves,
+  // by V parameter - determ using MaxNbPoles but it's
+  // value must be between 21(min) and 101(max)
+  int aNbSections = (int) aCurves.size();
+  int aNbPntInSection = Max(21, 2 * aMaxPoles - 1);
+  TColgp_Array2OfPnt aPoints(1, aNbSections, 1, aNbPntInSection);
+  anIt = aCurves.begin();
+  for (int i = 1; anIt != aCurves.end(); ++i, ++anIt) {
+    Handle(Geom_Curve) aC = *anIt;
+    double fp = aC->FirstParameter();
+    double lp = aC->LastParameter();
+    double dp = (lp - fp) / (aNbPntInSection - 1);
+
+    gp_Pnt aPnt;
+    for (int j = 0; j < aNbPntInSection; j++) {
+      aC->D0(fp + dp * j, aPnt);
+      aPoints.SetValue(i, j+1, aPnt);
+    }
+  }
+
+  // convert a grid of points to B-spline surface
+  GeomAPI_PointsToBSplineSurface aPTB(aPoints, myMinDegree, myMaxDegree, GeomAbs_C2, myTol3D);
+  Handle(Geom_BSplineSurface) aBS = aPTB.Surface();
+  if (aBS.IsNull())
+    return;
+
+  // fix face orientation
+  TopoDS_Face aFace = BRepBuilderAPI_MakeFace(aBS, Precision::Confusion());
+  Handle(ShapeFix_Face) aFix = new ShapeFix_Face(aFace);
+  aFix->Perform();
+  aFix->FixOrientation();
+  aFace = aFix->Face();
+
+  // store result
+  std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
+  aShape->setImpl(new TopoDS_Shape(aFace));
+  setShape(aShape);
+  setDone(true);
+}
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Filling.h b/src/GeomAlgoAPI/GeomAlgoAPI_Filling.h
new file mode 100644 (file)
index 0000000..99275bf
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef GeomAlgoAPI_Filling_H_
+#define GeomAlgoAPI_Filling_H_
+
+#include <GeomAlgoAPI.h>
+#include <GeomAlgoAPI_MakeShape.h>
+
+#include <GeomAPI_Edge.h>
+
+/// \class GeomAlgoAPI_Filling
+/// \ingroup DataAlgo
+/// \brief Perform building face by the set of edges/wires
+class GeomAlgoAPI_Filling : public GeomAlgoAPI_MakeShape
+{
+public:
+  /// \brief Construct filling operation by the parameters.
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_Filling(const int theMinDegree = 2,
+                                         const int theMaxDegree = 5,
+                                         const int theNbIter    = 0,
+                                         const double theTol2D = 1.e-4,
+                                         const double theTol3D = 1.e-4);
+
+  /// \brief Add an edge to constrain filling (the result face should pass through the edge)
+  GEOMALGOAPI_EXPORT void add(const GeomEdgePtr theEdge);
+
+  /// \brief Perform filling operation
+  /// \param isApproximate approximate curves before building a face
+  GEOMALGOAPI_EXPORT void build(bool isApproximate = false);
+
+private:
+  /// \brief Perform filling using the given edges
+  void buildByEdges();
+
+  /// \brief Perform filling by a set of points calculated on each edge
+  void buildByControlPoints();
+
+private:
+  int myMinDegree;
+  int myMaxDegree;
+  int myNbIter;
+  double myTol2D;
+  double myTol3D;
+  std::list<GeomEdgePtr> myConstraints;
+};
+
+#endif
index 0dc7ef9a777572eee9370915a64d495d6c52c0c4..c942dd1cb4bb102c3e648fcf0ad134d3c73827e5 100644 (file)
@@ -68,7 +68,7 @@ void GeomAlgoAPI_MakeVolume::build(const ListOfShape& theFaces)
 #ifdef USE_OCCT_720
   aVolumeMaker->SetAvoidInternalShapes(true);
 #endif
-  aVolumeMaker->SetGlue(BOPAlgo_GlueShift);
+  aVolumeMaker->SetGlue(BOPAlgo_GlueOff);
 
   // building and getting result
   aVolumeMaker->Perform();
index 9b61619a30c2624525a9fee8cf5489fd9e9379b2..95a3440720ba5d7060db63a7a2d57e83df7abb54 100644 (file)
@@ -40,7 +40,7 @@ GeomAlgoAPI_PaveFiller::GeomAlgoAPI_PaveFiller(const ListOfShape& theListOfShape
 void GeomAlgoAPI_PaveFiller::build(const ListOfShape& theListOfShape,
                                    const bool theIsMakeCompSolids)
 {
-  BOPAlgo_PaveFiller aPaveFiller;
+  BOPAlgo_PaveFiller* aPaveFiller = new BOPAlgo_PaveFiller;
   BOPCol_ListOfShape aListOfShape;
   for(ListOfShape::const_iterator
     anIt = theListOfShape.cbegin(); anIt != theListOfShape.cend(); anIt++) {
@@ -53,13 +53,13 @@ void GeomAlgoAPI_PaveFiller::build(const ListOfShape& theListOfShape,
       aListOfShape.Append(aShape);
     }
   }
-  aPaveFiller.SetArguments(aListOfShape);
-  aPaveFiller.Perform();
+  aPaveFiller->SetArguments(aListOfShape);
+  aPaveFiller->Perform();
 #ifdef USE_OCCT_720
-  if (aPaveFiller.HasErrors())
+  if (aPaveFiller->HasErrors())
     return;
 #else
-  Standard_Integer iErr = aPaveFiller.ErrorStatus();
+  Standard_Integer iErr = aPaveFiller->ErrorStatus();
   if(iErr) {
     return;
   }
@@ -69,7 +69,7 @@ void GeomAlgoAPI_PaveFiller::build(const ListOfShape& theListOfShape,
   this->setImpl(aBuilder);
   this->setBuilderType(OCCT_BOPAlgo_Builder);
   aBuilder->SetArguments(aListOfShape);
-  aBuilder->PerformWithFiller(aPaveFiller);
+  aBuilder->PerformWithFiller(*aPaveFiller);
 #ifdef USE_OCCT_720
   if (aBuilder->HasErrors())
     return;
index 4276537f0c3aaa7842429f55d2811ba834d20bd4..91cd80630e72a880f58b88e2d0a4bd4f3eb0003a 100644 (file)
@@ -150,13 +150,13 @@ void GeomAlgoAPI_Prism::build(const GeomShapePtr&                theBaseShape,
   GeomShapePtr aBasePlane;
   const bool isBoundingShapesSet = theFromShape.get() || theToShape.get();
   BRepBuilderAPI_FindPlane aFindPlane(aBaseShape);
-  if(theDirection.get()) {
+  if ((aBaseShape.ShapeType() == TopAbs_VERTEX || aBaseShape.ShapeType() == TopAbs_EDGE)
+      && theDirection.get())
+  {
     aBaseDir = theDirection;
     aDirVec = theDirection->impl<gp_Dir>();
   } else {
-    if(aBaseShape.ShapeType() == TopAbs_VERTEX
-        || aBaseShape.ShapeType() == TopAbs_EDGE
-        || aFindPlane.Found() == Standard_False) {
+    if(aFindPlane.Found() == Standard_False) {
       return;
     }
 
index fd854afb74009ba5ea90e2adfdfd31eeaece85ed..60b9fe4531168004468d09c66bee1393db19ca88 100644 (file)
 #include <GeomAPI_Face.h>
 #include <GeomAPI_Pln.h>
 #include <GeomAPI_Pnt.h>
+#include <GeomAPI_Wire.h>
 
 #include <Bnd_Box.hxx>
 #include <BOPTools.hxx>
 #include <BRep_Builder.hxx>
 #include <BRepAdaptor_Curve.hxx>
+#include <BRepAlgo.hxx>
 #include <BRepAlgo_FaceRestrictor.hxx>
 #include <BRepBndLib.hxx>
 #include <BRepBuilderAPI_FindPlane.hxx>
@@ -953,3 +955,17 @@ std::shared_ptr<GeomAPI_Dir> GeomAlgoAPI_ShapeTools::buildDirFromAxisAndShape(
                                                     aCentreOfMassPoint.Z()-aPoint.Z()));
   return aDir;
 }
+
+//==================================================================================================
+std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_ShapeTools::wireToEdge(
+      const std::shared_ptr<GeomAPI_Wire>& theWire)
+{
+  GeomEdgePtr anEdge;
+  if (theWire) {
+    const TopoDS_Wire& aWire = theWire->impl<TopoDS_Wire>();
+    TopoDS_Edge aNewEdge = BRepAlgo::ConcatenateWireC0(aWire);
+    anEdge = GeomEdgePtr(new GeomAPI_Edge);
+    anEdge->setImpl(new TopoDS_Edge(aNewEdge));
+  }
+  return anEdge;
+}
index 7745c4011f5640a6053f3b7635eda575dcbf3866..42f87c8626ce40d8725329917da8a7305cc5d41c 100644 (file)
@@ -36,6 +36,7 @@ class GeomAPI_Face;
 class GeomAPI_PlanarEdges;
 class GeomAPI_Pln;
 class GeomAPI_Pnt;
+class GeomAPI_Wire;
 class GeomDataAPI_Point2D;
 class ModelAPI_Object;
 
@@ -174,6 +175,10 @@ public:
   GEOMALGOAPI_EXPORT static std::shared_ptr<GeomAPI_Dir> buildDirFromAxisAndShape(
                                     const std::shared_ptr<GeomAPI_Shape> theBaseShape,
                                     const std::shared_ptr<GeomAPI_Ax1> theAxis);
+
+  /// \brief Reapproximate a wire to build a single edge
+  GEOMALGOAPI_EXPORT static std::shared_ptr<GeomAPI_Edge> wireToEdge(
+      const std::shared_ptr<GeomAPI_Wire>& theWire);
 };
 
 #endif
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_SortListOfShapes.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_SortListOfShapes.cpp
new file mode 100644 (file)
index 0000000..f75b9ae
--- /dev/null
@@ -0,0 +1,180 @@
+// Copyright (C) 2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "GeomAlgoAPI_SortListOfShapes.h"
+
+#include <Bnd_Box.hxx>
+#include <Bnd_Box2d.hxx>
+#include <BRep_Tool.hxx>
+#include <BRepBndLib.hxx>
+#include <BRepTools.hxx>
+#include <gp_Pnt.hxx>
+#include <Precision.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+
+#include <algorithm>
+#include <map>
+
+class CompareShapes
+{
+  std::map<TopoDS_TShape*, Bnd_Box> myShapes;
+  std::map<TopoDS_TShape*, Bnd_Box2d> myUVBounds;
+
+  bool compareEdges(const GeomShapePtr& theLHS, const GeomShapePtr& theRHS)
+  {
+    const TopoDS_Edge& aLHSEdge = TopoDS::Edge(theLHS->impl<TopoDS_Shape>());
+    const TopoDS_Edge& aRHSEdge = TopoDS::Edge(theRHS->impl<TopoDS_Shape>());
+
+    double aLF, aLE, aRF, aRE;
+    Handle(Geom_Curve) aLHSCurve = BRep_Tool::Curve(aLHSEdge, aLF, aLE);
+    Handle(Geom_Curve) aRHSCurve = BRep_Tool::Curve(aRHSEdge, aRF, aRE);
+
+    if (aLHSCurve == aRHSCurve) {
+      // compare by first parameter
+      if (isLessWithTol(aLF, aRF, Precision::PConfusion()))
+        return true;
+      else if (isLessWithTol(aRF, aLF, Precision::PConfusion()))
+        return false;
+      // compare by last parameter
+      return isLessWithTol(aLE, aRE, Precision::PConfusion());
+    }
+    // different underlying curves => compare bounding boxe
+    return compareByBoundingBox(theLHS, theRHS);
+  }
+
+  bool compareFaces(const GeomShapePtr& theLHS, const GeomShapePtr& theRHS)
+  {
+    const TopoDS_Face& aLHSFace = TopoDS::Face(theLHS->impl<TopoDS_Shape>());
+    const TopoDS_Face& aRHSFace = TopoDS::Face(theRHS->impl<TopoDS_Shape>());
+
+    Handle(Geom_Surface) aLHSSurf = BRep_Tool::Surface(aLHSFace);
+    Handle(Geom_Surface) aRHSSurf = BRep_Tool::Surface(aRHSFace);
+
+    if (aLHSSurf == aRHSSurf) {
+      // compare parametric space for faces on the same surface
+      Bnd_Box2d aLHSBox = boundingBoxUV(aLHSFace);
+      Bnd_Box2d aRHSBox = boundingBoxUV(aRHSFace);
+
+      double aLHSBB[4], aRHSBB[4];
+      aLHSBox.Get(aLHSBB[0], aLHSBB[1], aLHSBB[2], aLHSBB[3]);
+      aRHSBox.Get(aRHSBB[0], aRHSBB[1], aRHSBB[2], aRHSBB[3]);
+      for (int anIndex = 0; anIndex < 4; ++anIndex) {
+        if (isLessWithTol(aLHSBB[anIndex], aRHSBB[anIndex], Precision::PConfusion()))
+          return true;
+        else if (isLessWithTol(aRHSBB[anIndex], aLHSBB[anIndex], Precision::PConfusion()))
+          return false;
+      }
+      // equal parametric boxes
+      return false;
+    }
+    // different underlying surfaces => compare bounding boxes
+    return compareByBoundingBox(theLHS, theRHS);
+  }
+
+  bool compareByBoundingBox(const GeomShapePtr& theLHS, const GeomShapePtr& theRHS)
+  {
+    Bnd_Box aLHSBox = boundingBox(theLHS);
+    Bnd_Box aRHSBox = boundingBox(theRHS);
+
+    gp_Pnt aLHSMin = aLHSBox.CornerMin();
+    gp_Pnt aLHSMax = aLHSBox.CornerMax();
+
+    gp_Pnt aRHSMin = aRHSBox.CornerMin();
+    gp_Pnt aRHSMax = aRHSBox.CornerMax();
+
+    if (isLess(aLHSMin, aRHSMin))
+      return true;
+    else if (isLess(aRHSMin, aLHSMin))
+      return false;
+
+    return isLess(aLHSMax, aRHSMax);
+  }
+
+  bool isLessWithTol(const double theLHS, const double theRHS, const double theTolerance)
+  {
+    return theLHS + theTolerance < theRHS;
+  }
+
+  bool isLess(const gp_Pnt& theLHS, const gp_Pnt& theRHS)
+  {
+    for (int anIndex = 1; anIndex <= 3; ++anIndex) {
+      if (isLessWithTol(theLHS.Coord(anIndex), theRHS.Coord(anIndex), Precision::Confusion()))
+        return true;
+      else if (isLessWithTol(theRHS.Coord(anIndex), theLHS.Coord(anIndex), Precision::Confusion()))
+        return false;
+    }
+    // equal points
+    return false;
+  }
+
+  Bnd_Box boundingBox(const GeomShapePtr& theShape)
+  {
+    const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
+    TopoDS_TShape* aS = aShape.TShape().get();
+    std::map<TopoDS_TShape*, Bnd_Box>::iterator aFound = myShapes.find(aS);
+    if (aFound == myShapes.end()) {
+      Bnd_Box aBB;
+      BRepBndLib::Add(aShape, aBB);
+      myShapes[aS] = aBB;
+      aFound = myShapes.find(aS);
+    }
+    return aFound->second;
+  }
+
+  Bnd_Box2d boundingBoxUV(const TopoDS_Face& theFace)
+  {
+    TopoDS_TShape* aFacePtr = theFace.TShape().get();
+    std::map<TopoDS_TShape*, Bnd_Box2d>::iterator aFound = myUVBounds.find(aFacePtr);
+    if (aFound == myUVBounds.end()) {
+      Bnd_Box2d aBB;
+      BRepTools::AddUVBounds(theFace, aBB);
+      myUVBounds[aFacePtr] = aBB;
+      aFound = myUVBounds.find(aFacePtr);
+    }
+    return aFound->second;
+  }
+
+public:
+  // Verify theLHS is less than theRHS
+  bool operator() (const GeomShapePtr& theLHS, const GeomShapePtr& theRHS)
+  {
+    if (theLHS->shapeType() == theRHS->shapeType()) {
+      // edges and faces are compared by geometric properties
+      if (theLHS->shapeType() == GeomAPI_Shape::EDGE)
+        return compareEdges(theLHS, theRHS);
+      else if (theLHS->shapeType() == GeomAPI_Shape::FACE)
+        return compareFaces(theLHS, theRHS);
+      // all other comparisons are made by bounding boxes
+      return compareByBoundingBox(theLHS, theRHS);
+    }
+
+    // shapes of different types are compared by the type
+    return theLHS->shapeType() < theRHS->shapeType();
+  }
+};
+
+
+void GeomAlgoAPI_SortListOfShapes::sort(ListOfShape& theShapes)
+{
+  CompareShapes aComparator;
+  theShapes.sort(aComparator);
+}
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_SortListOfShapes.h b/src/GeomAlgoAPI/GeomAlgoAPI_SortListOfShapes.h
new file mode 100644 (file)
index 0000000..0159b81
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright (C) 2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef GeomAlgoAPI_SortListOfShapes_H_
+#define GeomAlgoAPI_SortListOfShapes_H_
+
+#include "GeomAlgoAPI.h"
+
+#include <GeomAPI_Shape.h>
+
+/// \class GeomAlgoAPI_SortListOfShapes
+/// \ingroup DataAlgo
+/// \brief Performs sorting of shapes according to geometric properties.
+class GeomAlgoAPI_SortListOfShapes
+{
+ public:
+   /// \brief Sorts list of shapes in accordance with their geometric properties.
+   /// \param[in/out] theShapes list of shapes.
+   GEOMALGOAPI_EXPORT static void sort(ListOfShape& theShapes);
+};
+
+#endif
index 92bed77b3f47d050ad541238a79e000e765c2661..3b343b2926f792021ec168c46ce8dc59e0c782ea 100644 (file)
@@ -38,6 +38,7 @@ SET(PROJECT_HEADERS
     GeomValidators_Different.h
     GeomValidators_IntersectionSelection.h
     GeomValidators_MinObjectsSelected.h
+    GeomValidators_ValueOrder.h
 )
 
 SET(PROJECT_SOURCES
@@ -57,6 +58,7 @@ SET(PROJECT_SOURCES
     GeomValidators_Different.cpp
     GeomValidators_IntersectionSelection.cpp
     GeomValidators_MinObjectsSelected.cpp
+    GeomValidators_ValueOrder.cpp
 )
 
 SET(PROJECT_LIBRARIES
diff --git a/src/GeomValidators/GeomValidators_ValueOrder.cpp b/src/GeomValidators/GeomValidators_ValueOrder.cpp
new file mode 100644 (file)
index 0000000..0365438
--- /dev/null
@@ -0,0 +1,132 @@
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "GeomValidators_ValueOrder.h"
+
+#include <Config_PropManager.h>
+#include <Events_InfoMessage.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+
+static double attributeValue(AttributePtr theAttr)
+{
+  AttributeIntegerPtr anIntAttr = std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(theAttr);
+  if (anIntAttr)
+    return (double)anIntAttr->value();
+  AttributeDoublePtr aDoubleAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttr);
+  if (aDoubleAttr)
+    return aDoubleAttr->value();
+  return 0.0;
+}
+
+static bool isGreaterOrEqual(AttributePtr theFirstArg, AttributePtr theSecondArg)
+{
+  if (theFirstArg && theFirstArg->isInitialized() &&
+      theSecondArg && theSecondArg->isInitialized())
+    return attributeValue(theFirstArg) >= attributeValue(theSecondArg);
+  return false;
+}
+
+static bool isLessOrEqual(AttributePtr theFirstArg, AttributePtr theSecondArg)
+{
+  if (theFirstArg && theFirstArg->isInitialized() &&
+      theSecondArg && theSecondArg->isInitialized())
+    return attributeValue(theFirstArg) <= attributeValue(theSecondArg);
+  return false;
+}
+
+// Check the attributes are satisfy theCompare function
+static bool isValidOrder(const AttributePtr& theAttribute,
+                         const std::list<std::string>& theArguments,
+                         Events_InfoMessage& theError,
+                         bool (*theCompare)(AttributePtr, AttributePtr))
+{
+  std::string anAttrType = theAttribute->attributeType();
+  if (anAttrType != ModelAPI_AttributeDouble::typeId() &&
+      anAttrType != ModelAPI_AttributeInteger::typeId()) {
+    theError = "Unsupported attribute type (integer or double applicable)";
+    return false;
+  }
+
+  FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
+  if (!anOwner) {
+    theError = "Attribute without owner";
+    return false;
+  }
+
+  for (std::list<std::string>::const_iterator anIt = theArguments.begin();
+       anIt != theArguments.end(); ++anIt) {
+    // check the argument links to the attribute of the current feature
+    AttributePtr aCurAttr = anOwner->attribute(*anIt);
+    if (!aCurAttr) {
+      theError = "Arguments should be names of attributes of current feature";
+      return false;
+    }
+
+    // compare values
+    if (!(*theCompare)(theAttribute, aCurAttr)) {
+      theError = "Attributes have incorrect order";
+      return false;
+    }
+  }
+
+  return true;
+}
+
+
+
+/// Global instance for validators factory
+GeomValidators_GreaterOrEqual MY_GEQ_INSTANCE;
+GeomValidators_LessOrEqual MY_LEQ_INSTANCE;
+
+GeomValidators_GreaterOrEqual::GeomValidators_GreaterOrEqual()
+{
+  // this validator is registered in the factory on this library loading
+  SessionPtr aMgr = ModelAPI_Session::get();
+  ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
+  aFactory->registerValidator("GeomValidators_GreaterOrEqual", this);
+}
+
+bool GeomValidators_GreaterOrEqual::isValid(const AttributePtr& theAttribute,
+                                            const std::list<std::string>& theArguments,
+                                            Events_InfoMessage& theError) const
+{
+  return isValidOrder(theAttribute, theArguments, theError, &isGreaterOrEqual);
+}
+
+
+
+GeomValidators_LessOrEqual::GeomValidators_LessOrEqual()
+{
+  // this validator is registered in the factory on this library loading
+  SessionPtr aMgr = ModelAPI_Session::get();
+  ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
+  aFactory->registerValidator("GeomValidators_LessOrEqual", this);
+}
+
+bool GeomValidators_LessOrEqual::isValid(const AttributePtr& theAttribute,
+                                         const std::list<std::string>& theArguments,
+                                         Events_InfoMessage& theError) const
+{
+  return isValidOrder(theAttribute, theArguments, theError, &isLessOrEqual);
+}
diff --git a/src/GeomValidators/GeomValidators_ValueOrder.h b/src/GeomValidators/GeomValidators_ValueOrder.h
new file mode 100644 (file)
index 0000000..f4dd4fb
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright (C) 2017-20xx  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef GeomValidators_ValueOrder_H
+#define GeomValidators_ValueOrder_H
+
+#include <GeomValidators.h>
+#include <ModelAPI_AttributeValidator.h>
+
+/**
+ * Validates that the integer/double attribute is greater or equal to another attribute values
+ */
+class GeomValidators_GreaterOrEqual : public ModelAPI_AttributeValidator
+{
+public:
+  //! Constructor for only one instance per application: will register the validator
+  GeomValidators_GreaterOrEqual();
+  //! returns true if attribute is valid
+  //! \param[in] theAttribute the checked attribute
+  //! \param[in] theArguments arguments of the attribute
+  //! \param[out] theError error message.
+  GEOMVALIDATORS_EXPORT virtual bool isValid(const AttributePtr& theAttribute,
+                                             const std::list<std::string>& theArguments,
+                                             Events_InfoMessage& theError) const;
+
+};
+
+/**
+ * Validates that the integer/double attribute is less or equal to another attribute values
+ */
+class GeomValidators_LessOrEqual : public ModelAPI_AttributeValidator
+{
+public:
+  //! Constructor for only one instance per application: will register the validator
+  GeomValidators_LessOrEqual();
+  //! returns true if attribute is valid
+  //! \param[in] theAttribute the checked attribute
+  //! \param[in] theArguments arguments of the attribute
+  //! \param[out] theError error message.
+  GEOMVALIDATORS_EXPORT virtual bool isValid(const AttributePtr& theAttribute,
+                                             const std::list<std::string>& theArguments,
+                                             Events_InfoMessage& theError) const;
+
+};
+
+#endif
index c29cca22998cc6c335de633a089f0a77f9eb0baa..418186066fb26bca5498a1b3cdcba2db87d0e602 100644 (file)
@@ -35,6 +35,7 @@
 #include <ModelAPI_CompositeFeature.h>
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
 #include <Events_InfoMessage.h>
 #include <GeomAPI_Edge.h>
 #include <GeomAPI_Vertex.h>
@@ -658,7 +659,7 @@ void Model_AttributeSelection::selectBody(
     bool isFound = false;
     TopExp_Explorer anExp(aNewContext, aNewSub.ShapeType());
     for(; anExp.More(); anExp.Next()) {
-      if (anExp.Current().IsEqual(aNewSub)) {
+      if (anExp.Current().IsSame(aNewSub)) {
         isFound = true;
         break;
       }
@@ -864,6 +865,68 @@ void Model_AttributeSelection::selectSubShape(
           }
         }
       }
+      // if compsolid is context, try to take sub-solid as context: like in GUI and scripts
+      if (aCont.get() && aShapeToBeSelected.get()) {
+        ResultCompSolidPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aCont);
+        if (aComp && aComp->numberOfSubs()) {
+          for(int aSubNum = 0; aSubNum < aComp->numberOfSubs(); aSubNum++) {
+            ResultPtr aSub = aComp->subResult(aSubNum);
+            if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aShapeToBeSelected)) {
+              aCont = aSub;
+              break;
+            }
+          }
+        }
+      }
+      // try to find the latest active result that must be used instead of the selected
+      // to set the active context (like in GUI selection), not concealed one
+      bool aFindNewContext = true;
+      while(aFindNewContext && aCont.get() && aShapeToBeSelected.get()) {
+        aFindNewContext = false;
+        const std::set<AttributePtr>& aRefs = aCont->data()->refsToMe();
+        std::set<AttributePtr>::const_iterator aRef = aRefs.begin();
+        for(; !aFindNewContext && aRef != aRefs.end(); aRef++) {
+          if (!aRef->get() || !(*aRef)->owner().get())
+            continue;
+          // concealed attribute only
+          FeaturePtr aRefFeat = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRef)->owner());
+          if (!ModelAPI_Session::get()->validators()->isConcealed(
+                  aRefFeat->getKind(), (*aRef)->id()))
+            continue;
+          // search the feature result that contains sub-shape selected
+          std::list<std::shared_ptr<ModelAPI_Result> > aResults;
+
+          // take all sub-results or one result
+          const std::list<std::shared_ptr<ModelAPI_Result> >& aFResults = aRefFeat->results();
+          std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aFResults.begin();
+          for (; aRIter != aFResults.cend(); aRIter++) {
+            // iterate sub-bodies of compsolid
+            ResultCompSolidPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*aRIter);
+            if (aComp.get() && aComp->numberOfSubs() > 0) {
+              int aNumSub = aComp->numberOfSubs();
+              for(int a = 0; a < aNumSub; a++) {
+                aResults.push_back(aComp->subResult(a));
+              }
+            } else {
+              aResults.push_back(*aRIter);
+            }
+          }
+          std::list<std::shared_ptr<ModelAPI_Result> >::iterator aResIter = aResults.begin();
+          for(; aResIter != aResults.end(); aResIter++) {
+            if (!aResIter->get() || !(*aResIter)->data()->isValid() || (*aResIter)->isDisabled())
+              continue;
+            GeomShapePtr aShape = (*aResIter)->shape();
+            if (aShape.get() && aShape->isSubShape(aShapeToBeSelected, false)) {
+              aCont = *aResIter; // found new context (produced from this) with same subshape
+              //if (!aShape->isSubShape(aShapeToBeSelected, true)) // take context orientation
+              //  aShapeToBeSelected->setOrientation();
+              aFindNewContext = true; // continue searching futher
+              break;
+            }
+          }
+        }
+      }
+
       if (aCenterType != NOT_CENTER) {
         if (!aShapeToBeSelected->isEdge())
           continue;
@@ -1078,40 +1141,50 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr<Model_Document>
 {
   std::set<ResultPtr> aResults; // to avoid duplicates, new context, null if deleted
   TopTools_ListOfShape aResContShapes;
-  TNaming_SameShapeIterator aModifIter(theContShape, theAccessLabel);
-  for(; aModifIter.More(); aModifIter.Next()) {
-    TDF_Label anObjLab = aModifIter.Label().Father();
-    ResultPtr aModifierObj = std::dynamic_pointer_cast<ModelAPI_Result>
-      (theDoc->objects()->object(anObjLab));
-    if (!aModifierObj.get()) {
-      // #2241: shape may be sub-element of new object, not main (shell created from faces)
-      if (!anObjLab.IsRoot())
-        aModifierObj = std::dynamic_pointer_cast<ModelAPI_Result>
-        (theDoc->objects()->object(anObjLab.Father()));
-      if (!aModifierObj.get())
+  // iterate context and shape, but also if it is sub-shape of main shape, check also it
+  TopTools_ListOfShape aContextList;
+  aContextList.Append(theContShape);
+  if (theContext.get()) {
+    ResultPtr aComposite = ModelAPI_Tools::compSolidOwner(theContext);
+    if (aComposite.get() && aComposite->shape().get() && !aComposite->shape()->isNull())
+      aContextList.Append(aComposite->shape()->impl<TopoDS_Shape>());
+  }
+  for(TopTools_ListOfShape::Iterator aContIter(aContextList); aContIter.More(); aContIter.Next()) {
+    TNaming_SameShapeIterator aModifIter(aContIter.ChangeValue(), theAccessLabel);
+    for(; aModifIter.More(); aModifIter.Next()) {
+      TDF_Label anObjLab = aModifIter.Label().Father();
+      ResultPtr aModifierObj = std::dynamic_pointer_cast<ModelAPI_Result>
+        (theDoc->objects()->object(anObjLab));
+      if (!aModifierObj.get()) {
+        // #2241: shape may be sub-element of new object, not main (shell created from faces)
+        if (!anObjLab.IsRoot())
+          aModifierObj = std::dynamic_pointer_cast<ModelAPI_Result>
+          (theDoc->objects()->object(anObjLab.Father()));
+        if (!aModifierObj.get())
+          continue;
+      }
+      FeaturePtr aModifierFeat = theDoc->feature(aModifierObj);
+      if (!aModifierFeat.get())
         continue;
-    }
-    FeaturePtr aModifierFeat = theDoc->feature(aModifierObj);
-    if (!aModifierFeat.get())
-      continue;
-    FeaturePtr aThisFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
-    if (aModifierFeat == aThisFeature || theDoc->objects()->isLater(aModifierFeat, aThisFeature))
-      continue; // the modifier feature is later than this, so, should not be used
-    FeaturePtr aCurrentModifierFeat = theDoc->feature(theContext);
-    if (aCurrentModifierFeat == aModifierFeat ||
-      theDoc->objects()->isLater(aCurrentModifierFeat, aModifierFeat))
-      continue; // the current modifier is later than the found, so, useless
-    Handle(TNaming_NamedShape) aNewNS;
-    aModifIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNewNS);
-    if (aNewNS->Evolution() == TNaming_MODIFY || aNewNS->Evolution() == TNaming_GENERATED) {
-      aResults.insert(aModifierObj);
-      //TNaming_Iterator aPairIter(aNewNS);
-      //aResContShapes.Append(aPairIter.NewShape());
-      aResContShapes.Append(aModifierObj->shape()->impl<TopoDS_Shape>());
-    } else if (aNewNS->Evolution() == TNaming_DELETE) { // a shape was deleted => result is empty
-      aResults.insert(ResultPtr());
-    } else { // not-precessed modification => don't support it
-      continue;
+      FeaturePtr aThisFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
+      if (aModifierFeat == aThisFeature || theDoc->objects()->isLater(aModifierFeat, aThisFeature))
+        continue; // the modifier feature is later than this, so, should not be used
+      FeaturePtr aCurrentModifierFeat = theDoc->feature(theContext);
+      if (aCurrentModifierFeat == aModifierFeat ||
+        theDoc->objects()->isLater(aCurrentModifierFeat, aModifierFeat))
+        continue; // the current modifier is later than the found, so, useless
+      Handle(TNaming_NamedShape) aNewNS;
+      aModifIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNewNS);
+      if (aNewNS->Evolution() == TNaming_MODIFY || aNewNS->Evolution() == TNaming_GENERATED) {
+        aResults.insert(aModifierObj);
+        //TNaming_Iterator aPairIter(aNewNS);
+        //aResContShapes.Append(aPairIter.NewShape());
+        aResContShapes.Append(aModifierObj->shape()->impl<TopoDS_Shape>());
+      } else if (aNewNS->Evolution() == TNaming_DELETE) { // a shape was deleted => result is empty
+        aResults.insert(ResultPtr());
+      } else { // not-precessed modification => don't support it
+        continue;
+      }
     }
   }
   if (aResults.empty())
index 24acebc1736d86712342fb8787224d2df1ec5291..d17fb8bd6424573b95794572ae72b03796f42b79 100755 (executable)
@@ -49,6 +49,7 @@
 #include <BRep_Tool.hxx>
 #include <GeomAPI_Shape.h>
 #include <GeomAlgoAPI_MakeShape.h>
+#include <GeomAlgoAPI_SortListOfShapes.h>
 #include <Config_PropManager.h>
 // DEB
 //#include <TCollection_AsciiString.hxx>
@@ -284,7 +285,8 @@ TNaming_Builder* Model_BodyBuilder::builder(const int theTag)
   std::map<int, TNaming_Builder*>::iterator aFind = myBuilders.find(theTag);
   if (aFind == myBuilders.end()) {
     std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
-    myBuilders[theTag] = new TNaming_Builder(aData->shapeLab().FindChild(theTag));
+    myBuilders[theTag] = new TNaming_Builder(
+      theTag == 0 ? aData->shapeLab() : aData->shapeLab().FindChild(theTag));
     aFind = myBuilders.find(theTag);
   }
   return aFind->second;
@@ -368,6 +370,35 @@ void Model_BodyBuilder::loadDeletedShapes (GeomAlgoAPI_MakeShape* theMS,
   }
 }
 
+// Keep only the shapes with minimal shape type
+static void keepTopLevelShapes(ListOfShape& theShapes, const TopoDS_Shape& theRoot,
+  const GeomShapePtr& theResultShape = GeomShapePtr())
+{
+  GeomAPI_Shape::ShapeType aKeepShapeType = GeomAPI_Shape::SHAPE;
+  ListOfShape::iterator anIt = theShapes.begin();
+  while (anIt != theShapes.end()) {
+    TopoDS_Shape aNewShape = (*anIt)->impl<TopoDS_Shape>();
+    if (theRoot.IsSame(aNewShape) || (theResultShape &&
+        (!theResultShape->isSubShape(*anIt, false) || theResultShape->isSame(*anIt)))) {
+      ListOfShape::iterator aRemoveIt = anIt++;
+      theShapes.erase(aRemoveIt);
+    } else {
+      GeomAPI_Shape::ShapeType aType = (*anIt)->shapeType();
+      if (aType < aKeepShapeType) {
+        // found a shape with lesser shape type => remove all previous shapes
+        aKeepShapeType = aType;
+        theShapes.erase(theShapes.begin(), anIt);
+        ++anIt;
+      } else if (aType > aKeepShapeType) {
+        // shapes with greater shape type should be removed from the list
+        ListOfShape::iterator aRemoveIt = anIt++;
+        theShapes.erase(aRemoveIt);
+      } else
+        ++anIt;
+    }
+  }
+}
+
 void Model_BodyBuilder::loadAndOrientModifiedShapes (
   GeomAlgoAPI_MakeShape* theMS,
   std::shared_ptr<GeomAPI_Shape>  theShapeIn,
@@ -391,11 +422,18 @@ void Model_BodyBuilder::loadAndOrientModifiedShapes (
     const TopoDS_Shape& aRoot = aShapeExplorer.Current ();
     if (!aView.Add(aRoot)) continue;
     if (TNaming_Tool::NamedShape(aRoot, builder(theTag)->NamedShape()->Label()).IsNull())
-      continue; // there is no sence to write history is old shape does not persented in document
+      continue; // there is no sense to write history if old shape does not exist in the document
     ListOfShape aList;
     std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
     aRShape->setImpl((new TopoDS_Shape(aRoot)));
     theMS->modified(aRShape, aList);
+    if (!theIsStoreSeparate)
+      keepTopLevelShapes(aList, aRoot, aResultShape);
+    // sort the list of images before naming
+    GeomAlgoAPI_SortListOfShapes::sort(aList);
+
+    // to trace situation where several objects are produced by one parent (#2317)
+    int aSameParentShapes = -1;
     std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator
       anIt = aList.begin(), aLast = aList.end();
     for (; anIt != aLast; anIt++) {
@@ -406,26 +444,67 @@ void Model_BodyBuilder::loadAndOrientModifiedShapes (
       }
       GeomShapePtr aGeomNewShape(new GeomAPI_Shape());
       aGeomNewShape->setImpl(new TopoDS_Shape(aNewShape));
-      if(!aRoot.IsSame(aNewShape) && aResultShape->isSubShape(aGeomNewShape, false)) {
+      if(!aRoot.IsSame(aNewShape) && aResultShape->isSubShape(aGeomNewShape, false) &&
+         !aResultShape->isSame(*anIt)) { // to avoid put of same shape on main label and sub
+        int aBuilderTag = aTag;
+        if (!theIsStoreSeparate)
+          aSameParentShapes++;
+
+        static const int THE_ANCHOR_TAG = 100000;
+        int aCurShapeType = (int)((*anIt)->shapeType());
+        bool needSuffix = false; // suffix for the name based on the shape type
+        if (aSameParentShapes > 0) { // store in other label
+          aBuilderTag = THE_ANCHOR_TAG - aSameParentShapes * 10 - aCurShapeType;
+          needSuffix = true;
+        } else if (aCurShapeType != theKindOfShape) {
+          // modified shape has different type => set another tag
+          // to avoid shapes of different types on the same label
+          aBuilderTag = THE_ANCHOR_TAG - aCurShapeType;
+          needSuffix = true;
+        }
+        std::string aSuffix;
+        if (needSuffix) {
+          switch (aCurShapeType) {
+          case GeomAPI_Shape::VERTEX: aSuffix = "_v"; break;
+          case GeomAPI_Shape::EDGE:   aSuffix = "_e"; break;
+          case GeomAPI_Shape::FACE:   aSuffix = "_f"; break;
+          default: break;
+          }
+        }
+
         if(theIsStoreAsGenerated) {
           // Here we store shapes as generated, to avoid problem when one parent shape produce
           // several child shapes. In this case naming could not determine which shape to select.
-          builder(aTag)->Generated(aRoot,aNewShape);
+          builder(aBuilderTag)->Generated(aRoot, aNewShape);
         } else {
-          builder(aTag)->Modify(aRoot,aNewShape);
+          builder(aBuilderTag)->Modify(aRoot, aNewShape);
         }
         if(isBuilt) {
-          if(theIsStoreSeparate) {
+          aStream.str(std::string());
+          aStream.clear();
+          aStream << theName;
+          if(theIsStoreSeparate)
+             aStream << "_" << anIndex++;
+
+          if (aSameParentShapes > 0) {
             aStream.str(std::string());
             aStream.clear();
-            aStream << theName << "_" << anIndex++;
-            aName = aStream.str();
+            aStream << aName << "_" << aSameParentShapes << "divided";
           }
-          buildName(aTag, aName);
+
+          aStream << aSuffix;
+          buildName(aBuilderTag, aStream.str());
         }
         if(theIsStoreSeparate) {
           aTag++;
         }
+      } else if (aResultShape->isSame(*anIt)) {
+        // keep the modification evolution on the root level (2241 - history propagation issue)
+        if(theIsStoreAsGenerated) {
+          builder(0)->Generated(aRoot, aNewShape);
+        } else {
+          builder(0)->Modify(aRoot, aNewShape);
+        }
       }
     }
   }
@@ -446,12 +525,13 @@ void Model_BodyBuilder::loadAndOrientGeneratedShapes (
   for (; aShapeExplorer.More(); aShapeExplorer.Next ()) {
     const TopoDS_Shape& aRoot = aShapeExplorer.Current ();
     if (!aView.Add(aRoot)) continue;
-    if (TNaming_Tool::NamedShape(aRoot, builder(theTag)->NamedShape()->Label()).IsNull())
-      continue; // there is no sence to write history is old shape does not persented in document
+    //if (TNaming_Tool::NamedShape(aRoot, builder(theTag)->NamedShape()->Label()).IsNull())
+    //  continue; // there is no sense to write history if old shape does not exist in the document
     ListOfShape aList;
     std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
     aRShape->setImpl((new TopoDS_Shape(aRoot)));
     theMS->generated(aRShape, aList);
+    keepTopLevelShapes(aList, aRoot);
     std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator
       anIt = aList.begin(), aLast = aList.end();
     for (; anIt != aLast; anIt++) {
index 9911a796463fe41ec18cfc94fa6e9e22b048003b..89c13889236960a1df1aa188276a5521d97b0302 100644 (file)
@@ -58,6 +58,7 @@
 #include <TDataStd_Name.hxx>
 #include <TDataStd_AsciiString.hxx>
 #include <TDataStd_IntegerArray.hxx>
+#include <TDataStd_UAttribute.hxx>
 #include <TDF_AttributeIterator.hxx>
 #include <TDF_ChildIterator.hxx>
 #include <TDF_RelocationTable.hxx>
@@ -75,6 +76,9 @@ static const int kFlagInHistory = 0;
 static const int kFlagDisplayed = 1;
 //                             2 - is deleted (for results) or not
 static const int kFlagDeleted = 2;
+// TDataStd_Integer - 0 if the name of the object is generated automatically,
+//                    otherwise the name is defined by user
+Standard_GUID kUSER_DEFINED_NAME("9c694d18-a83c-4a56-bc9b-8020628a8244");
 
 // invalid data
 const static std::shared_ptr<ModelAPI_Data> kInvalid(new Model_Data());
@@ -127,8 +131,11 @@ void Model_Data::setName(const std::string& theName)
     isModified = true;
   } else {
     isModified = !aName->Get().IsEqual(theName.c_str());
-    if (isModified)
+    if (isModified) {
       aName->Set(theName.c_str());
+      // name is changed, thus special attribute is set
+      TDataStd_UAttribute::Set(myLab, kUSER_DEFINED_NAME);
+    }
   }
   if (mySendAttributeUpdated && isModified)
     ModelAPI_ObjectRenamedMessage::send(myObject, anOldName, theName, this);
@@ -141,6 +148,11 @@ void Model_Data::setName(const std::string& theName)
 #endif
 }
 
+bool Model_Data::hasUserDefinedName() const
+{
+  return myLab.IsAttribute(kUSER_DEFINED_NAME);
+}
+
 AttributePtr Model_Data::addAttribute(const std::string& theID, const std::string theAttrType)
 {
   AttributePtr aResult;
@@ -468,9 +480,9 @@ void Model_Data::eraseBackReferences()
     aRes->setIsConcealed(false);
 }
 
-void Model_Data::removeBackReference(FeaturePtr theFeature, std::string theAttrID)
+void Model_Data::removeBackReference(ObjectPtr theObject, std::string theAttrID)
 {
-  AttributePtr anAttribute = theFeature->data()->attribute(theAttrID);
+  AttributePtr anAttribute = theObject->data()->attribute(theAttrID);
   removeBackReference(anAttribute);
 }
 
@@ -492,10 +504,7 @@ void Model_Data::removeBackReference(AttributePtr theAttr)
 void Model_Data::addBackReference(FeaturePtr theFeature, std::string theAttrID,
    const bool theApplyConcealment)
 {
-  // it is possible to add the same attribute twice: may be last time the owner was not Stable...
-  AttributePtr anAttribute = theFeature->data()->attribute(theAttrID);
-  if (myRefsToMe.find(anAttribute) == myRefsToMe.end())
-    myRefsToMe.insert(theFeature->data()->attribute(theAttrID));
+  addBackReference(ObjectPtr(theFeature), theAttrID);
 
   if (theApplyConcealment &&  theFeature->isStable() &&
       ModelAPI_Session::get()->validators()->isConcealed(theFeature->getKind(), theAttrID)) {
@@ -510,6 +519,14 @@ void Model_Data::addBackReference(FeaturePtr theFeature, std::string theAttrID,
   }
 }
 
+void Model_Data::addBackReference(ObjectPtr theObject, std::string theAttrID)
+{
+  // it is possible to add the same attribute twice: may be last time the owner was not Stable...
+  AttributePtr anAttribute = theObject->data()->attribute(theAttrID);
+  if (myRefsToMe.find(anAttribute) == myRefsToMe.end())
+    myRefsToMe.insert(anAttribute);
+}
+
 void Model_Data::updateConcealmentFlag()
 {
   std::set<AttributePtr>::iterator aRefsIter = myRefsToMe.begin();
index 186cfefc2a353a030c9df47d881a6b8140a4d3c2..8d12bc4d32a53f8ec81dec7a9b5d98aaec7262f2 100644 (file)
@@ -36,6 +36,7 @@
 #include <ModelAPI_AttributeIntArray.h>
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Feature.h>
+#include <ModelAPI_Folder.h>
 #include <ModelAPI_Object.h>
 
 #include <TDF_Label.hxx>
@@ -103,6 +104,8 @@ class Model_Data : public ModelAPI_Data
   MODEL_EXPORT virtual std::string name();
   /// Defines the name of the feature visible by the user in the object browser
   MODEL_EXPORT virtual void setName(const std::string& theName);
+  /// Return \c true if the object has been renamed by the user
+  MODEL_EXPORT virtual bool hasUserDefinedName() const;
   /// Returns the attribute that references to another document
   MODEL_EXPORT virtual std::shared_ptr<ModelAPI_AttributeDocRef> document(const std::string& theID);
   /// Returns the attribute that contains real value with double precision
@@ -271,7 +274,7 @@ private:
   /// Removes a back reference (with identifier which attribute references to this object)
   /// \param theFeature feature referenced to this
   /// \param theAttrID identifier of the attribute that is references from theFeature to this
-  void removeBackReference(FeaturePtr theFeature, std::string theAttrID);
+  void removeBackReference(ObjectPtr theObject, std::string theAttrID);
   /// Removes a back reference (by the attribute)
   /// \param theAttr the referenced attribute
   void removeBackReference(AttributePtr theAttr);
@@ -281,6 +284,10 @@ private:
   /// \param theApplyConcealment applies consealment flag changes
   void addBackReference(FeaturePtr theFeature, std::string theAttrID,
     const bool theApplyConcealment = true);
+  /// Adds a back reference to an object
+  /// \param theObject object referenced to this
+  /// \param theAttrID identifier of the attribute that is references from theFolder to this
+  void addBackReference(ObjectPtr theObject, std::string theAttrID);
 
   /// Makes the concealment flag up to date for this object-owner.
   MODEL_EXPORT virtual void updateConcealmentFlag();
@@ -303,11 +310,15 @@ private:
 /// Without concealment change, it will be done later, on synchronization.
 #define ADD_BACK_REF(TARGET) \
   if (TARGET.get() != NULL) { \
+    std::shared_ptr<Model_Data> aTargetData = \
+        std::dynamic_pointer_cast<Model_Data>((TARGET)->data()); \
     FeaturePtr anAttributeOwnerFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner()); \
-    if (anAttributeOwnerFeature.get()) { \
-      std::shared_ptr<Model_Data> aTargetData = std::dynamic_pointer_cast<Model_Data>( \
-        (TARGET)->data()); \
+    if (anAttributeOwnerFeature.get()) \
       aTargetData->addBackReference(anAttributeOwnerFeature, id(), false); \
+    else { \
+      FolderPtr anAttributeOwnerFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(owner()); \
+      if (anAttributeOwnerFolder.get()) \
+        aTargetData->addBackReference(ObjectPtr(anAttributeOwnerFolder), id()); \
     } \
   }
 
@@ -315,11 +326,15 @@ private:
 /// Without concealment change, it will be done later, on synchronization.
 #define REMOVE_BACK_REF(TARGET) \
   if (TARGET.get() != NULL) { \
+    std::shared_ptr<Model_Data> aTargetData = \
+        std::dynamic_pointer_cast<Model_Data>((TARGET)->data()); \
     FeaturePtr anAttOwnerFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner()); \
-    if (anAttOwnerFeature.get()) { \
-      std::shared_ptr<Model_Data> aTargetData = std::dynamic_pointer_cast<Model_Data>( \
-        (TARGET)->data()); \
+    if (anAttOwnerFeature.get()) \
       aTargetData->removeBackReference(anAttOwnerFeature, id()); \
+    else { \
+      FolderPtr anAttributeOwnerFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(owner()); \
+      if (anAttributeOwnerFolder.get()) \
+        aTargetData->removeBackReference(ObjectPtr(anAttributeOwnerFolder), id()); \
     } \
   }
 
index e11f26faa5ebb62378031c1a75745267a7512f9d..f37533c07150b781100ada7f8fd1dd8bc598063b 100755 (executable)
@@ -925,7 +925,7 @@ FeaturePtr Model_Document::addFeature(std::string theID, const bool theMakeCurre
       int aSubs = aComp->numberOfSubs(false);
       for(int a = 0; a < aSubs; a++) {
         FeaturePtr aSub = aComp->subFeature(a, false);
-        if (myObjs->isLater(aSub, aCurrent)) {
+        if (aSub && myObjs->isLater(aSub, aCurrent)) {
           isModified =  true;
           aCurrent = aSub;
         }
@@ -1031,9 +1031,11 @@ std::shared_ptr<Model_Document> Model_Document::subDoc(int theDocID)
     Model_Application::getApplication()->document(theDocID));
 }
 
-ObjectPtr Model_Document::object(const std::string& theGroupID, const int theIndex)
+ObjectPtr Model_Document::object(const std::string& theGroupID,
+                                 const int theIndex,
+                                 const bool theAllowFolder)
 {
-  return myObjs->object(theGroupID, theIndex);
+  return myObjs->object(theGroupID, theIndex, theAllowFolder);
 }
 
 std::shared_ptr<ModelAPI_Object> Model_Document::objectByName(
@@ -1042,16 +1044,17 @@ std::shared_ptr<ModelAPI_Object> Model_Document::objectByName(
   return myObjs->objectByName(theGroupID, theName);
 }
 
-const int Model_Document::index(std::shared_ptr<ModelAPI_Object> theObject)
+const int Model_Document::index(std::shared_ptr<ModelAPI_Object> theObject,
+                                const bool theAllowFolder)
 {
-  return myObjs->index(theObject);
+  return myObjs->index(theObject, theAllowFolder);
 }
 
-int Model_Document::size(const std::string& theGroupID)
+int Model_Document::size(const std::string& theGroupID, const bool theAllowFolder)
 {
   if (myObjs == 0) // may be on close
     return 0;
-  return myObjs->size(theGroupID);
+  return myObjs->size(theGroupID, theAllowFolder);
 }
 
 std::shared_ptr<ModelAPI_Feature> Model_Document::currentFeature(const bool theVisible)
@@ -1255,6 +1258,51 @@ std::shared_ptr<ModelAPI_ResultParameter> Model_Document::createParameter(
   return myObjs->createParameter(theFeatureData, theIndex);
 }
 
+std::shared_ptr<ModelAPI_Folder> Model_Document::addFolder(
+    std::shared_ptr<ModelAPI_Feature> theAddBefore)
+{
+  return myObjs->createFolder(theAddBefore);
+}
+
+void Model_Document::removeFolder(std::shared_ptr<ModelAPI_Folder> theFolder)
+{
+  if (theFolder)
+    myObjs->removeFolder(theFolder);
+}
+
+std::shared_ptr<ModelAPI_Folder> Model_Document::findFolderAbove(
+      const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures)
+{
+  return myObjs->findFolder(theFeatures, false);
+}
+
+std::shared_ptr<ModelAPI_Folder> Model_Document::findFolderBelow(
+      const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures)
+{
+  return myObjs->findFolder(theFeatures, true);
+}
+
+std::shared_ptr<ModelAPI_Folder> Model_Document::findContainingFolder(
+      const std::shared_ptr<ModelAPI_Feature>& theFeature,
+      int& theIndexInFolder)
+{
+  return myObjs->findContainingFolder(theFeature, theIndexInFolder);
+}
+
+bool Model_Document::moveToFolder(
+      const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
+      const std::shared_ptr<ModelAPI_Folder>& theFolder)
+{
+  return myObjs->moveToFolder(theFeatures, theFolder);
+}
+
+bool Model_Document::removeFromFolder(
+      const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
+      const bool theBefore)
+{
+  return myObjs->removeFromFolder(theFeatures, theBefore);
+}
+
 std::shared_ptr<ModelAPI_Feature> Model_Document::feature(
     const std::shared_ptr<ModelAPI_Result>& theResult)
 {
@@ -1383,6 +1431,13 @@ TDF_Label Model_Document::findNamingName(std::string theName, ResultPtr theConte
               return aName->Label();
             }
           }
+          // check also "this" label
+          Handle(TDataStd_Name) aName;
+          if (aLabIter->FindAttribute(TDataStd_Name::GetID(), aName)) {
+            if (aName->Get() == aSubName) {
+              return aName->Label();
+            }
+          }
         }
       }
     }
@@ -1489,6 +1544,11 @@ std::list<std::shared_ptr<ModelAPI_Feature> > Model_Document::allFeatures()
   return myObjs->allFeatures();
 }
 
+std::list<std::shared_ptr<ModelAPI_Object> > Model_Document::allObjects()
+{
+  return myObjs->allObjects();
+}
+
 void Model_Document::setActive(const bool theFlag)
 {
   if (theFlag != myIsActive) {
index b6358eb4f18f44a03bd781f75483020d3e404a25..0f6b32ed6e8093863a453ecf130ee42d200155d7 100644 (file)
@@ -122,8 +122,10 @@ class Model_Document : public ModelAPI_Document
 
   //! Returns the object index in the group. Object must be visible. Otherwise returns -1.
   //! \param theObject object of this document
+  //! \param theAllowFolder take into account grouping feature by folders
   //! \returns index started from zero, or -1 if object is invisible or belongs to another document
-  MODEL_EXPORT virtual const int index(std::shared_ptr<ModelAPI_Object> theObject);
+  MODEL_EXPORT virtual const int index(std::shared_ptr<ModelAPI_Object> theObject,
+                                       const bool theAllowFolder = false);
 
   //! Internal sub-document by ID
   MODEL_EXPORT virtual std::shared_ptr<Model_Document> subDoc(int theDocID);
@@ -137,10 +139,15 @@ class Model_Document : public ModelAPI_Document
   //! Returns the feature in the group by the index (started from zero)
   //! \param theGroupID group that contains a feature
   //! \param theIndex zero-based index of feature in the group
-  MODEL_EXPORT virtual ObjectPtr object(const std::string& theGroupID, const int theIndex);
+  //! \param theAllowFolder take into account grouping feature by folders
+  MODEL_EXPORT virtual ObjectPtr object(const std::string& theGroupID,
+                                        const int theIndex,
+                                        const bool theAllowFolder = false);
 
   //! Returns the number of features in the group
-  MODEL_EXPORT virtual int size(const std::string& theGroupID);
+  //! \param theGroupID group of objects
+  //! \param theAllowFolder take into account grouping feature by folders
+  MODEL_EXPORT virtual int size(const std::string& theGroupID, const bool theAllowFolder = false);
 
   //! Returns the feature that is currently edited in this document, normally
   //! this is the latest created feature
@@ -199,6 +206,47 @@ class Model_Document : public ModelAPI_Document
   MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Feature>
     feature(const std::shared_ptr<ModelAPI_Result>& theResult);
 
+  //! Creates a folder (group of the features in the object browser)
+  //! \param theAddBefore a feature, the folder is added before
+  //!                     (if empty, the folder is added after the last feature)
+  MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Folder> addFolder(
+      std::shared_ptr<ModelAPI_Feature> theAddBefore = std::shared_ptr<ModelAPI_Feature>());
+  //! Removes the folder from the document (all features in the folder will be kept).
+  MODEL_EXPORT virtual void removeFolder(std::shared_ptr<ModelAPI_Folder> theFolder);
+  //! Search a folder above the list of features applicable to store them
+  //! (it means the list of features stored in the folder should be consequential)
+  //! \return Empty pointer if there is no applicable folder
+  MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Folder> findFolderAbove(
+      const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures);
+  //! Search a folder below the list of features applicable to store them
+  //! (it means the list of features stored in the folder should be consequential)
+  //! \return Empty pointer if there is no applicable folder
+  MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Folder> findFolderBelow(
+      const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures);
+  //! Search a folder containing the given feature.
+  //! Addtionally calculates a zero-based index of the feature in this folder.
+  //! \param theFeature feature to search
+  //! \param theIndexInFolder zero-based index in the folder or -1 if the feature is top-level.
+  //! \return the folder containing the feature or empty pointer if the feature is top-level.
+  MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Folder> findContainingFolder(
+      const std::shared_ptr<ModelAPI_Feature>& theFeature,
+      int& theIndexInFolder);
+  //! Add a list of features to the folder. The correctness of the adding is not performed
+  //! (such checks have been done in corresponding find.. method).
+  //! \return \c true if the movement is successfull
+  MODEL_EXPORT virtual bool moveToFolder(
+      const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
+      const std::shared_ptr<ModelAPI_Folder>& theFolder);
+  //! Remove features from the folder
+  //! \param theFeatures list of features to be removed
+  //! \param theBefore   extract features before the folder (this parameter is applicable only
+  //!                    when all features in the folder are taking out,
+  //!                    in other cases the direction is taken automatically)
+  //! \return \c true if the features have been moved out
+  MODEL_EXPORT virtual bool removeFromFolder(
+      const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
+      const bool theBefore = true);
+
   ///! Returns true if parametric updater need to execute feature on recomputartion
   ///! On abort, undo or redo it is not necessary: results in document are updated automatically
   bool executeFeatures() {return myExecuteFeatures;}
@@ -224,6 +272,10 @@ class Model_Document : public ModelAPI_Document
   ///! history. Not very fast method, for calling once, not in big cycles.
   MODEL_EXPORT virtual std::list<std::shared_ptr<ModelAPI_Feature> > allFeatures();
 
+  //! Returns all objects of the document including the hidden features which are not in
+  //! history. Not very fast method, for calling once, not in big cycles.
+  MODEL_EXPORT virtual std::list<std::shared_ptr<ModelAPI_Object> > allObjects();
+
   /// Returns the global identifier of the current transaction (needed for the update algo)
   MODEL_EXPORT virtual int transactionID();
   /// Increases the transaction ID
index 17c62335760b13c2b0b1f26e037b2ef1a1b9f565..2dc014a406498d6077eb29483cb308e9ff457e3c 100644 (file)
 #include <TDF_LabelMap.hxx>
 #include <TDF_ListIteratorOfLabelList.hxx>
 
+static const std::string& groupNameFoldering(const std::string& theGroupID,
+                                             const bool theAllowFolder)
+{
+  if (theAllowFolder) {
+    static const std::string anOutOfFolderName = std::string("__") + ModelAPI_Feature::group();
+    static const std::string aDummyName;
+    return theGroupID == ModelAPI_Feature::group() ? anOutOfFolderName : aDummyName;
+  }
+  return theGroupID;
+}
+
+// Check theFeature is a first or last feature in folder and return this folder
+static FolderPtr inFolder(const FeaturePtr& theFeature, const std::string& theFolderAttr)
+{
+  const std::set<AttributePtr>& aRefs = theFeature->data()->refsToMe();
+  for (std::set<AttributePtr>::iterator anIt = aRefs.begin(); anIt != aRefs.end(); ++anIt) {
+    if ((*anIt)->id() != theFolderAttr)
+      continue;
+
+    ObjectPtr anOwner = (*anIt)->owner();
+    FolderPtr aFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(anOwner);
+    if (aFolder.get())
+      return aFolder;
+  }
+  return FolderPtr();
+}
+
+
 static const int TAG_OBJECTS = 2;  // tag of the objects sub-tree (features, results)
 
 // feature sub-labels
@@ -92,6 +120,15 @@ Model_Objects::~Model_Objects()
     aFeature->erase();
     myFeatures.UnBind(aFeaturesIter.Key());
   }
+  while (!myFolders.IsEmpty()) {
+    NCollection_DataMap<TDF_Label, ObjectPtr>::Iterator aFoldersIter(myFolders);
+    ObjectPtr aFolder = aFoldersIter.Value();
+    static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+    ModelAPI_EventCreator::get()->sendDeleted(myDoc, ModelAPI_Folder::group());
+    ModelAPI_EventCreator::get()->sendUpdated(aFolder, EVENT_DISP);
+    aFolder->erase();
+    myFolders.UnBind(aFoldersIter.Key());
+  }
   myHistory.clear();
   aLoop->activateFlushes(isActive);
   // erase update, because features are destroyed and update should not performed for them anywhere
@@ -139,12 +176,16 @@ void Model_Objects::addFeature(FeaturePtr theFeature, const FeaturePtr theAfterT
     // store feature in the features array: before "initData" because in macro features
     // in initData it creates new features, appeared later than this
     TDF_Label aPrevFeateureLab;
+    FolderPtr aParentFolder;
     if (theAfterThis.get()) { // searching for the previous feature label
       std::shared_ptr<Model_Data> aPrevData =
         std::dynamic_pointer_cast<Model_Data>(theAfterThis->data());
       if (aPrevData.get()) {
         aPrevFeateureLab = aPrevData->label().Father();
       }
+      // check if the previous feature is the last feature in a folder,
+      // then the folder should be updated to contain additional feature
+      aParentFolder = inFolder(theAfterThis, ModelAPI_Folder::LAST_FEATURE_ID());
     }
     AddToRefArray(aFeaturesLab, aFeatureLab, aPrevFeateureLab);
 
@@ -162,6 +203,12 @@ void Model_Objects::addFeature(FeaturePtr theFeature, const FeaturePtr theAfterT
     // must be after binding to the map because of "Box" macro feature that
     // creates other features in "initData"
     initData(theFeature, aFeatureLab, TAG_FEATURE_ARGUMENTS);
+    // put feature to the end of folder if it is added while
+    // the history line is set to the last feature from the folder
+    if (aParentFolder) {
+      aParentFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID())->setValue(theFeature);
+      updateHistory(ModelAPI_Folder::group());
+    }
     // event: feature is added, mist be before "initData" to update OB correctly on Duplicate:
     // first new part, then the content
     static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
@@ -260,6 +307,8 @@ void Model_Objects::removeFeature(FeaturePtr theFeature)
         aComposite->removeFeature(theFeature);
       }
     }
+    // remove feature from folder
+    removeFromFolder(std::list<FeaturePtr>(1, theFeature));
     // this must be before erase since theFeature erasing removes all information about
     // the feature results and groups of results
     // To reproduce: create sketch, extrusion, remove sketch => constructions tree is not updated
@@ -367,9 +416,8 @@ void Model_Objects::clearHistory(ObjectPtr theObj)
 {
   if (theObj.get()) {
     const std::string aGroup = theObj->groupName();
-    std::map<std::string, std::vector<ObjectPtr> >::iterator aHIter = myHistory.find(aGroup);
-    if (aHIter != myHistory.end())
-      myHistory.erase(aHIter); // erase from map => this means that it is not synchronized
+    updateHistory(aGroup);
+
     if (theObj->groupName() == ModelAPI_Feature::group()) { // clear results group of the feature
       FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
       std::string aResultGroup = featureResultGroup(aFeature);
@@ -387,9 +435,12 @@ void Model_Objects::createHistory(const std::string& theGroupID)
 {
   std::map<std::string, std::vector<ObjectPtr> >::iterator aHIter = myHistory.find(theGroupID);
   if (aHIter == myHistory.end()) {
-    std::vector<ObjectPtr> aResult = std::vector<ObjectPtr>();
+    std::vector<ObjectPtr> aResult;
+    std::vector<ObjectPtr> aResultOutOfFolder;
+    FeaturePtr aLastFeatureInFolder;
     // iterate the array of references and get feature by feature from the array
     bool isFeature = theGroupID == ModelAPI_Feature::group();
+    bool isFolder = theGroupID == ModelAPI_Folder::group();
     Handle(TDataStd_ReferenceArray) aRefs;
     if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
       for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) {
@@ -401,6 +452,9 @@ void Model_Objects::createHistory(const std::string& theGroupID)
           if (isFeature) { // here may be also disabled features
             if (!isSub && aFeature->isInHistory()) {
               aResult.push_back(aFeature);
+              // the feature is out of the folders
+              if (aLastFeatureInFolder.get() == NULL)
+                aResultOutOfFolder.push_back(aFeature);
             }
           } else if (!aFeature->isDisabled()) { // iterate all results of not-disabled feature
             // construction results of sub-features should not be in the tree
@@ -418,12 +472,40 @@ void Model_Objects::createHistory(const std::string& theGroupID)
               }
             }
           }
+
+          // the feature closes the folder, so the next features will be treated as out-of-folder
+          if (aLastFeatureInFolder.get() && aLastFeatureInFolder == aFeature)
+            aLastFeatureInFolder = FeaturePtr();
+
+        } else {
+          // it may be a folder
+          ObjectPtr aFolder = folder(aRefs->Value(a));
+          if (aFolder.get()) {
+            // store folder information for the Features group only
+            if (isFeature || isFolder) {
+              aResult.push_back(aFolder);
+              if (!isFolder)
+                aResultOutOfFolder.push_back(aFolder);
+            }
+
+            // get the last feature in the folder
+            AttributeReferencePtr aLastFeatAttr =
+                aFolder->data()->reference(ModelAPI_Folder::LAST_FEATURE_ID());
+            if (aLastFeatAttr)
+              aLastFeatureInFolder = ModelAPI_Feature::feature(aLastFeatAttr->value());
+          }
         }
       }
     }
     // to be sure that isConcealed did not update the history (issue 1089) during the iteration
-    if (myHistory.find(theGroupID) == myHistory.end())
+    if (myHistory.find(theGroupID) == myHistory.end()) {
       myHistory[theGroupID] = aResult;
+
+      // store the features placed out of any folder
+      const std::string& anOutOfFolderGroupID = groupNameFoldering(theGroupID, true);
+      if (!anOutOfFolderGroupID.empty())
+        myHistory[anOutOfFolderGroupID] = aResultOutOfFolder;
+    }
   }
 }
 
@@ -435,8 +517,21 @@ void Model_Objects::updateHistory(const std::shared_ptr<ModelAPI_Object> theObje
 void Model_Objects::updateHistory(const std::string theGroup)
 {
   std::map<std::string, std::vector<ObjectPtr> >::iterator aHIter = myHistory.find(theGroup);
-  if (aHIter != myHistory.end())
+  if (aHIter != myHistory.end()) {
     myHistory.erase(aHIter); // erase from map => this means that it is not synchronized
+
+    // erase history for the group of objects placed out of any folder
+    const std::string& anOutOfFolderGroupID = groupNameFoldering(theGroup, true);
+    if (!anOutOfFolderGroupID.empty())
+      myHistory.erase(anOutOfFolderGroupID);
+  }
+}
+
+ObjectPtr Model_Objects::folder(TDF_Label theLabel) const
+{
+  if (myFolders.IsBound(theLabel))
+    return myFolders.Find(theLabel);
+  return ObjectPtr();
 }
 
 FeaturePtr Model_Objects::feature(TDF_Label theLabel) const
@@ -489,12 +584,18 @@ ObjectPtr Model_Objects::object(TDF_Label theLabel)
   return FeaturePtr();  // not found
 }
 
-ObjectPtr Model_Objects::object(const std::string& theGroupID, const int theIndex)
+ObjectPtr Model_Objects::object(const std::string& theGroupID,
+                                const int theIndex,
+                                const bool theAllowFolder)
 {
   if (theIndex == -1)
     return ObjectPtr();
   createHistory(theGroupID);
-  return myHistory[theGroupID][theIndex];
+  const std::string& aGroupID = groupNameFoldering(theGroupID, theAllowFolder);
+  const std::vector<ObjectPtr>& aVec = myHistory[theGroupID];
+  //if (aVec.size() <= theIndex)
+  //  return aVec[aVec.size() - 1]; // too high index requested (to avoid crash in #2360)
+  return aGroupID.empty() ? myHistory[theGroupID][theIndex] : myHistory[aGroupID][theIndex];
 }
 
 std::shared_ptr<ModelAPI_Object> Model_Objects::objectByName(
@@ -538,10 +639,19 @@ std::shared_ptr<ModelAPI_Object> Model_Objects::objectByName(
   return ObjectPtr();
 }
 
-const int Model_Objects::index(std::shared_ptr<ModelAPI_Object> theObject)
+const int Model_Objects::index(std::shared_ptr<ModelAPI_Object> theObject,
+                               const bool theAllowFolder)
 {
   std::string aGroup = theObject->groupName();
+  // treat folder as feature
+  if (aGroup == ModelAPI_Folder::group())
+    aGroup = ModelAPI_Feature::group();
   createHistory(aGroup);
+
+  // get the group of features out of folder (if enabled)
+  if (theAllowFolder && !groupNameFoldering(aGroup, theAllowFolder).empty())
+    aGroup = groupNameFoldering(aGroup, theAllowFolder);
+
   std::vector<ObjectPtr>& allObjs = myHistory[aGroup];
   std::vector<ObjectPtr>::iterator anObjIter = allObjs.begin(); // iterate to search object
   for(int anIndex = 0; anObjIter != allObjs.end(); anObjIter++, anIndex++) {
@@ -552,10 +662,11 @@ const int Model_Objects::index(std::shared_ptr<ModelAPI_Object> theObject)
   return -1;
 }
 
-int Model_Objects::size(const std::string& theGroupID)
+int Model_Objects::size(const std::string& theGroupID, const bool theAllowFolder)
 {
   createHistory(theGroupID);
-  return int(myHistory[theGroupID].size());
+  const std::string& aGroupID = groupNameFoldering(theGroupID, theAllowFolder);
+  return aGroupID.empty() ? int(myHistory[theGroupID].size()) : int(myHistory[aGroupID].size());
 }
 
 void Model_Objects::allResults(const std::string& theGroupID, std::list<ResultPtr>& theResults)
@@ -587,6 +698,13 @@ TDF_Label Model_Objects::featuresLabel() const
   return myMain.FindChild(TAG_OBJECTS);
 }
 
+static std::string composeName(const std::string& theFeatureKind, const int theIndex)
+{
+  std::stringstream aNameStream;
+  aNameStream << theFeatureKind << "_" << theIndex;
+  return aNameStream.str();
+}
+
 void Model_Objects::setUniqueName(FeaturePtr theFeature)
 {
   if (!theFeature->data()->name().empty())
@@ -600,9 +718,7 @@ void Model_Objects::setUniqueName(FeaturePtr theFeature)
       aNumObjects++;
   }
   // generate candidate name
-  std::stringstream aNameStream;
-  aNameStream << theFeature->getKind() << "_" << aNumObjects + 1;
-  aName = aNameStream.str();
+  aName = composeName(theFeature->getKind(), aNumObjects + 1);
   // check this is unique, if not, increase index by 1
   for (aFIter.Initialize(myFeatures); aFIter.More();) {
     FeaturePtr aFeature = aFIter.Value();
@@ -617,9 +733,7 @@ void Model_Objects::setUniqueName(FeaturePtr theFeature)
 
     if (isSameName) {
       aNumObjects++;
-      std::stringstream aNameStream;
-      aNameStream << theFeature->getKind() << "_" << aNumObjects + 1;
-      aName = aNameStream.str();
+      aName = composeName(theFeature->getKind(), aNumObjects + 1);
       // reinitialize iterator to make sure a new name is unique
       aFIter.Initialize(myFeatures);
     } else
@@ -628,6 +742,28 @@ void Model_Objects::setUniqueName(FeaturePtr theFeature)
   theFeature->data()->setName(aName);
 }
 
+void Model_Objects::setUniqueName(FolderPtr theFolder)
+{
+  if (!theFolder->name().empty())
+    return; // name is already defined
+
+  int aNbFolders = myFolders.Size();
+  std::string aName = composeName(ModelAPI_Folder::ID(), aNbFolders);
+
+  // check the uniqueness of the name
+  NCollection_DataMap<TDF_Label, ObjectPtr>::Iterator anIt(myFolders);
+  while (anIt.More()) {
+    if (anIt.Value()->data()->name() == aName) {
+      aName = composeName(ModelAPI_Folder::ID(), aNbFolders);
+      // reinitialize iterator to make sure a new name is unique
+      anIt.Initialize(myFolders);
+    } else
+      anIt.Next();
+  }
+
+  theFolder->data()->setName(aName);
+}
+
 void Model_Objects::initData(ObjectPtr theObj, TDF_Label theLab, const int theTag)
 {
   std::shared_ptr<Model_Data> aData(new Model_Data);
@@ -638,6 +774,10 @@ void Model_Objects::initData(ObjectPtr theObj, TDF_Label theLab, const int theTa
   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
   if (aFeature.get()) {
     setUniqueName(aFeature);  // must be before "initAttributes" because duplicate part uses name
+  } else { // is it a folder?
+    FolderPtr aFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(theObj);
+    if (aFolder)
+      setUniqueName(aFolder);
   }
   theObj->initAttributes();
 }
@@ -675,21 +815,28 @@ void Model_Objects::synchronizeFeatures(
     TDF_Label& aFeatureLab = anUpdatedIter.Value();
     while(aFeatureLab.Depth() > 3)
       aFeatureLab = aFeatureLab.Father();
-    if (myFeatures.IsBound(aFeatureLab))
+    if (myFeatures.IsBound(aFeatureLab) || myFolders.IsBound(aFeatureLab))
       anUpdatedMap.Add(aFeatureLab);
   }
 
   // update all objects by checking are they on labels or not
-  std::set<FeaturePtr> aNewFeatures, aKeptFeatures;
+  std::set<ObjectPtr> aNewFeatures, aKeptFeatures;
   TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
   for (; aLabIter.More(); aLabIter.Next()) {
     TDF_Label aFeatureLabel = aLabIter.Value()->Label();
-    FeaturePtr aFeature;
-    if (!myFeatures.IsBound(aFeatureLabel)) {  // a new feature is inserted
+    if (!myFeatures.IsBound(aFeatureLabel) && !myFolders.IsBound(aFeatureLabel)) {
+      // a new feature or folder is inserted
+
+      std::string aFeatureID = TCollection_AsciiString(Handle(TDataStd_Comment)::DownCast(
+                               aLabIter.Value())->Get()).ToCString();
+      bool isFolder = aFeatureID == ModelAPI_Folder::ID();
+
+      std::shared_ptr<Model_Session> aSession =
+          std::dynamic_pointer_cast<Model_Session>(ModelAPI_Session::get());
+
       // create a feature
-      aFeature = std::dynamic_pointer_cast<Model_Session>(ModelAPI_Session::get())->createFeature(
-        TCollection_AsciiString(Handle(TDataStd_Comment)::DownCast(aLabIter.Value())->Get())
-        .ToCString(), anOwner);
+      ObjectPtr aFeature = isFolder ? ObjectPtr(new ModelAPI_Folder)
+                                    : ObjectPtr(aSession->createFeature(aFeatureID, anOwner));
       if (!aFeature.get()) {
         // somethig is wrong, most probably, the opened document has invalid structure
         Events_InfoMessage("Model_Objects", "Invalid type of object in the document").send();
@@ -698,7 +845,10 @@ void Model_Objects::synchronizeFeatures(
       }
       aFeature->init();
       // this must be before "setData" to redo the sketch line correctly
-      myFeatures.Bind(aFeatureLabel, aFeature);
+      if (isFolder)
+        myFolders.Bind(aFeatureLabel, aFeature);
+      else
+        myFeatures.Bind(aFeatureLabel, std::dynamic_pointer_cast<ModelAPI_Feature>(aFeature));
       aNewFeatures.insert(aFeature);
       initData(aFeature, aFeatureLabel, TAG_FEATURE_ARGUMENTS);
       updateHistory(aFeature);
@@ -706,18 +856,25 @@ void Model_Objects::synchronizeFeatures(
       // event: model is updated
       ModelAPI_EventCreator::get()->sendUpdated(aFeature, aCreateEvent);
     } else {  // nothing is changed, both iterators are incremented
-      aFeature = myFeatures.Find(aFeatureLabel);
-      aKeptFeatures.insert(aFeature);
+      ObjectPtr anObject;
+      FeaturePtr aFeature;
+      if (myFeatures.Find(aFeatureLabel, aFeature)) {
+        aKeptFeatures.insert(aFeature);
+        anObject = aFeature;
+      } else
+        if (myFolders.Find(aFeatureLabel, anObject))
+          aKeptFeatures.insert(anObject);
+
       if (anUpdatedMap.Contains(aFeatureLabel)) {
         if (!theOpen) { // on abort/undo/redo reinitialize attributes if something is changed
           std::list<std::shared_ptr<ModelAPI_Attribute> > anAttrs =
-            aFeature->data()->attributes("");
+            anObject->data()->attributes("");
           std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
           for(; anAttr != anAttrs.end(); anAttr++)
             (*anAttr)->reinit();
         }
-        ModelAPI_EventCreator::get()->sendUpdated(aFeature, anUpdateEvent);
-        if (aFeature->getKind() == "Parameter") {
+        ModelAPI_EventCreator::get()->sendUpdated(anObject, anUpdateEvent);
+        if (aFeature && aFeature->getKind() == "Parameter") {
           // if parameters are changed, update the results (issue 937)
           const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
           std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
@@ -756,6 +913,26 @@ void Model_Objects::synchronizeFeatures(
     } else
       aFIter.Next();
   }
+  // verify folders are checked: if not => is was removed
+  for (NCollection_DataMap<TDF_Label, ObjectPtr>::Iterator aFldIt(myFolders);
+       aFldIt.More(); aFldIt.Next()) {
+    ObjectPtr aCurObj = aFldIt.Value();
+    if (aKeptFeatures.find(aCurObj) == aKeptFeatures.end() &&
+        aNewFeatures.find(aCurObj) == aNewFeatures.end()) {
+      ModelAPI_EventCreator::get()->sendDeleted(myDoc, ModelAPI_Folder::group());
+      // results of this feature must be redisplayed (hided)
+      // redisplay also removed feature (used for sketch and AISObject)
+      ModelAPI_EventCreator::get()->sendUpdated(aCurObj, aRedispEvent);
+      updateHistory(aCurObj);
+      aCurObj->erase();
+
+      // unbind after the "erase" call: on abort sketch
+      // is removes sub-objects that corrupts aFIter
+      myFolders.UnBind(aFldIt.Key());
+      // reinitialize iterator because unbind may corrupt the previous order in the map
+      aFldIt.Initialize(myFolders);
+    }
+  }
 
   if (theUpdateReferences) {
     synchronizeBackRefs();
@@ -813,7 +990,10 @@ void Model_Objects::synchronizeBackRefsForObject(const std::set<AttributePtr>& t
   for(; aNewIter != theNewRefs.end(); aNewIter++) {
     if (aData->refsToMe().find(*aNewIter) == aData->refsToMe().end()) {
       FeaturePtr aRefFeat = std::dynamic_pointer_cast<ModelAPI_Feature>((*aNewIter)->owner());
-      aData->addBackReference(aRefFeat, (*aNewIter)->id());
+      if (aRefFeat)
+        aData->addBackReference(aRefFeat, (*aNewIter)->id());
+      else // add back reference to a folder
+        aData->addBackReference((*aNewIter)->owner(), (*aNewIter)->id());
     }
   }
   if (theNewRefs.size() != aData->refsToMe().size()) { // some back ref must be removed
@@ -852,6 +1032,29 @@ void Model_Objects::synchronizeBackRefsForObject(const std::set<AttributePtr>& t
   aData->updateConcealmentFlag();
 }
 
+static void collectReferences(std::shared_ptr<ModelAPI_Data> theData,
+                              std::map<ObjectPtr, std::set<AttributePtr> >& theRefs)
+{
+  if (theData.get()) {
+    std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
+    theData->referencesToObjects(aRefs);
+    std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator aRefsIt = aRefs.begin();
+    for(; aRefsIt != aRefs.end(); aRefsIt++) {
+      std::list<ObjectPtr>::iterator aRefTo = aRefsIt->second.begin();
+      for(; aRefTo != aRefsIt->second.end(); aRefTo++) {
+        if (*aRefTo) {
+          std::map<ObjectPtr, std::set<AttributePtr> >::iterator aFound = theRefs.find(*aRefTo);
+          if (aFound == theRefs.end()) {
+            theRefs[*aRefTo] = std::set<AttributePtr>();
+            aFound = theRefs.find(*aRefTo);
+          }
+          aFound->second.insert(theData->attribute(aRefsIt->first));
+        }
+      }
+    }
+  }
+}
+
 void Model_Objects::synchronizeBackRefs()
 {
   // collect all back references in the separated container: to update everything at once,
@@ -862,25 +1065,12 @@ void Model_Objects::synchronizeBackRefs()
   NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFeatures(myFeatures);
   for(; aFeatures.More(); aFeatures.Next()) {
     FeaturePtr aFeature = aFeatures.Value();
-    std::shared_ptr<Model_Data> aFData = std::dynamic_pointer_cast<Model_Data>(aFeature->data());
-    if (aFData.get()) {
-      std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
-      aFData->referencesToObjects(aRefs);
-      std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator aRefsIt = aRefs.begin();
-      for(; aRefsIt != aRefs.end(); aRefsIt++) {
-        std::list<ObjectPtr>::iterator aRefTo = aRefsIt->second.begin();
-        for(; aRefTo != aRefsIt->second.end(); aRefTo++) {
-          if (*aRefTo) {
-            std::map<ObjectPtr, std::set<AttributePtr> >::iterator aFound = allRefs.find(*aRefTo);
-            if (aFound == allRefs.end()) {
-              allRefs[*aRefTo] = std::set<AttributePtr>();
-              aFound = allRefs.find(*aRefTo);
-            }
-            aFound->second.insert(aFeature->data()->attribute(aRefsIt->first));
-          }
-        }
-      }
-    }
+    collectReferences(aFeature->data(), allRefs);
+  }
+  NCollection_DataMap<TDF_Label, ObjectPtr>::Iterator aFolders(myFolders);
+  for(; aFolders.More(); aFolders.Next()) {
+    ObjectPtr aFolder = aFolders.Value();
+    collectReferences(aFolder->data(), allRefs);
   }
   // second iteration: just compare back-references with existing in features and results
   for(aFeatures.Initialize(myFeatures); aFeatures.More(); aFeatures.Next()) {
@@ -960,8 +1150,10 @@ bool Model_Objects::hasCustomName(DataPtr theFeatureData,
     return false;
   }
 
-  theParentName = ModelAPI_Tools::getDefaultName(theResult, theResultIndex);
-  return true;
+  std::pair<std::string, bool> aName = ModelAPI_Tools::getDefaultName(theResult, theResultIndex);
+  if (aName.second)
+    theParentName = aName.first;
+  return aName.second;
 }
 
 void Model_Objects::storeResult(std::shared_ptr<ModelAPI_Data> theFeatureData,
@@ -974,7 +1166,11 @@ void Model_Objects::storeResult(std::shared_ptr<ModelAPI_Data> theFeatureData,
   if (theResult->data()->name().empty()) {
     // if was not initialized, generate event and set a name
     std::string aNewName = theFeatureData->name();
-    if (!hasCustomName(theFeatureData, theResult, theResultIndex, aNewName)) {
+    if (hasCustomName(theFeatureData, theResult, theResultIndex, aNewName)) {
+      // if the name of result is user-defined, then, at first time, assign name of the result
+      // by empty string to be sure that corresponding flag in the data model is set
+      theResult->data()->setName("");
+    } else {
       std::stringstream aName;
       aName << aNewName;
       // if there are several results (issue #899: any number of result),
@@ -1111,6 +1307,431 @@ std::shared_ptr<ModelAPI_ResultParameter> Model_Objects::createParameter(
   return aResult;
 }
 
+std::shared_ptr<ModelAPI_Folder> Model_Objects::createFolder(
+    const std::shared_ptr<ModelAPI_Feature>& theBeforeThis)
+{
+  FolderPtr aFolder(new ModelAPI_Folder);
+  if (!aFolder)
+    return aFolder;
+
+  TDF_Label aFeaturesLab = featuresLabel();
+  TDF_Label aFolderLab = aFeaturesLab.NewChild();
+  // store feature in the features array: before "initData" because in macro features
+  // in initData it creates new features, appeared later than this
+  TDF_Label aPrevFeatureLab;
+  if (theBeforeThis.get()) { // searching for the previous feature label
+    std::shared_ptr<Model_Data> aPrevData =
+        std::dynamic_pointer_cast<Model_Data>(theBeforeThis->data());
+    if (aPrevData.get()) {
+      aPrevFeatureLab = nextLabel(aPrevData->label().Father(), true);
+    }
+  } else { // find the label of the last feature
+    Handle(TDataStd_ReferenceArray) aRefs;
+    if (aFeaturesLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs))
+      aPrevFeatureLab = aRefs->Value(aRefs->Upper());
+  }
+  AddToRefArray(aFeaturesLab, aFolderLab, aPrevFeatureLab);
+
+  // keep the feature ID to restore document later correctly
+  TDataStd_Comment::Set(aFolderLab, ModelAPI_Folder::ID().c_str());
+  myFolders.Bind(aFolderLab, aFolder);
+  // must be before the event sending: for OB the feature is already added
+  updateHistory(ModelAPI_Folder::group());
+  updateHistory(ModelAPI_Feature::group());
+
+  // must be after binding to the map because of "Box" macro feature that
+  // creates other features in "initData"
+  initData(aFolder, aFolderLab, TAG_FEATURE_ARGUMENTS);
+  // event: folder is added, must be before "initData" to update OB correctly on Duplicate:
+  // first new part, then the content
+  static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
+  ModelAPI_EventCreator::get()->sendUpdated(aFolder, anEvent);
+
+  return aFolder;
+}
+
+void Model_Objects::removeFolder(std::shared_ptr<ModelAPI_Folder> theFolder)
+{
+  std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theFolder->data());
+  if (!aData.get() || !aData->isValid())
+    return;
+
+  // this must be before erase since theFolder erasing removes all information about it
+  clearHistory(theFolder);
+  // erase fields
+  theFolder->erase();
+
+  TDF_Label aFolderLabel = aData->label().Father();
+  if (myFolders.IsBound(aFolderLabel))
+    myFolders.UnBind(aFolderLabel);
+
+  static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  ModelAPI_EventCreator::get()->sendUpdated(theFolder, EVENT_DISP);
+  // erase all attributes under the label of feature
+  aFolderLabel.ForgetAllAttributes();
+  // remove it from the references array
+  RemoveFromRefArray(featuresLabel(), aFolderLabel);
+  // event: feature is deleted
+  ModelAPI_EventCreator::get()->sendDeleted(theFolder->document(), ModelAPI_Folder::group());
+  updateHistory(ModelAPI_Folder::group());
+  updateHistory(ModelAPI_Feature::group());
+}
+
+// Returns one of the limiting features of the list
+static FeaturePtr limitingFeature(std::list<FeaturePtr>& theFeatures, const bool isLast)
+{
+  FeaturePtr aFeature;
+  if (isLast) {
+    aFeature = theFeatures.back();
+    theFeatures.pop_back();
+  } else {
+    aFeature = theFeatures.front();
+    theFeatures.pop_front();
+  }
+  return aFeature;
+}
+
+// Verify the feature is sub-element in composite feature or it is not used in the history
+static bool isSkippedFeature(FeaturePtr theFeature)
+{
+  bool isSub = ModelAPI_Tools::compositeOwner(theFeature).get() != NULL;
+  return isSub || (theFeature && !theFeature->isInHistory());
+}
+
+std::shared_ptr<ModelAPI_Folder> Model_Objects::findFolder(
+      const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
+      const bool theBelow)
+{
+  if (theFeatures.empty())
+    return FolderPtr(); // nothing to move
+
+  TDF_Label aFeaturesLab = featuresLabel();
+  Handle(TDataStd_ReferenceArray) aRefs;
+  if (!aFeaturesLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs))
+    return FolderPtr(); // no reference array (something is wrong)
+
+  std::list<std::shared_ptr<ModelAPI_Feature> > aFeatures = theFeatures;
+  std::shared_ptr<ModelAPI_Feature> aLimitingFeature = limitingFeature(aFeatures, theBelow);
+
+  std::shared_ptr<Model_Data> aData =
+      std::static_pointer_cast<Model_Data>(aLimitingFeature->data());
+  if (!aData || !aData->isValid())
+    return FolderPtr(); // invalid feature
+
+  // label of the first feature in the list for fast searching
+  TDF_Label aFirstFeatureLabel = aData->label().Father();
+
+  // find a folder above the features and
+  // check the given features represent a sequential list of objects following the folder
+  FolderPtr aFoundFolder;
+  TDF_Label aLastFeatureInFolder;
+  int aRefIndex = aRefs->Lower();
+  for(; aRefIndex <= aRefs->Upper(); ++aRefIndex) { // iterate all existing features
+    TDF_Label aCurLabel = aRefs->Value(aRefIndex);
+    if (IsEqual(aCurLabel, aFirstFeatureLabel))
+      break; // no need to continue searching
+
+    // searching the folder below, just continue to search last feature from the list
+    if (theBelow)
+      continue;
+
+    // if feature is in sub-component, skip it
+    FeaturePtr aCurFeature = feature(aCurLabel);
+    if (isSkippedFeature(aCurFeature))
+      continue;
+
+    if (!aLastFeatureInFolder.IsNull()) {
+      if (IsEqual(aCurLabel, aLastFeatureInFolder))
+        aLastFeatureInFolder.Nullify(); // the last feature in the folder is achived
+      continue;
+    }
+
+    aFoundFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(folder(aCurLabel));
+    if (aFoundFolder) {
+      AttributeReferencePtr aLastFeatAttr =
+          aFoundFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID());
+      if (aLastFeatAttr) {
+        // setup iterating inside a folder to find last feature
+        ObjectPtr aLastFeature = aLastFeatAttr->value();
+        if (aLastFeature) {
+          aData = std::static_pointer_cast<Model_Data>(aLastFeature->data());
+          if (aData && aData->isValid())
+            aLastFeatureInFolder = aData->label().Father();
+        }
+      }
+    }
+  }
+
+  if (theBelow && aRefIndex < aRefs->Upper()) {
+    TDF_Label aLabel;
+    // skip following features which are sub-components or not in history
+    for (int anIndex = aRefIndex + 1; anIndex <= aRefs->Upper(); ++anIndex) {
+      aLabel = aRefs->Value(anIndex);
+      FeaturePtr aCurFeature = feature(aLabel);
+      if (!isSkippedFeature(aCurFeature))
+        break;
+    }
+    // check the next object is a folder
+    aFoundFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(folder(aLabel));
+  }
+
+  if (!aLastFeatureInFolder.IsNull() || // the last feature of the folder above is not found
+      !aFoundFolder)
+    return FolderPtr();
+
+  // check the given features are sequential list
+  int aStep = theBelow ? -1 : 1;
+  for (aRefIndex += aStep;
+       !aFeatures.empty() && aRefIndex >= aRefs->Lower() && aRefIndex <= aRefs->Upper();
+       aRefIndex += aStep) {
+    TDF_Label aCurLabel = aRefs->Value(aRefIndex);
+    // if feature is in sub-component, skip it
+    FeaturePtr aCurFeature = feature(aCurLabel);
+    if (isSkippedFeature(aCurFeature))
+      continue;
+
+    aLimitingFeature = limitingFeature(aFeatures, theBelow);
+    if (!aCurFeature->data()->isEqual(aLimitingFeature->data()))
+      return FolderPtr(); // not a sequential list
+  }
+
+  return aFoundFolder;
+}
+
+bool Model_Objects::moveToFolder(
+      const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
+      const std::shared_ptr<ModelAPI_Folder>& theFolder)
+{
+  if (theFeatures.empty() || !theFolder)
+    return false;
+
+  // labels for the folder and last feature in the list
+  TDF_Label aFolderLabel, aLastFeatureLabel;
+  std::shared_ptr<Model_Data> aData =
+      std::static_pointer_cast<Model_Data>(theFolder->data());
+  if (aData && aData->isValid())
+    aFolderLabel = aData->label().Father();
+  aData = std::static_pointer_cast<Model_Data>(theFeatures.back()->data());
+  if (aData && aData->isValid())
+    aLastFeatureLabel = aData->label().Father();
+
+  if (aFolderLabel.IsNull() || aLastFeatureLabel.IsNull())
+    return false;
+
+  AttributeReferencePtr aFirstFeatAttr =
+      theFolder->reference(ModelAPI_Folder::FIRST_FEATURE_ID());
+  AttributeReferencePtr aLastFeatAttr =
+      theFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID());
+  bool initFirstAttr = !aFirstFeatAttr->value().get();
+  bool initLastAttr  = !aLastFeatAttr->value().get();
+
+  // check the folder is below the list of features
+  bool isFolderBelow = false;
+  TDF_Label aFeaturesLab = featuresLabel();
+  Handle(TDataStd_ReferenceArray) aRefs;
+  if (!aFeaturesLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs))
+    return false; // no reference array (something is wrong)
+  for (int aRefIndex = aRefs->Lower(); aRefIndex <= aRefs->Upper(); ++aRefIndex) {
+    TDF_Label aCurLabel = aRefs->Value(aRefIndex);
+    if (aCurLabel == aFolderLabel)
+      break; // folder is above the features
+    else if (aCurLabel == aLastFeatureLabel) {
+      isFolderBelow = true;
+      break;
+    }
+  }
+
+  if (isFolderBelow) {
+    aData = std::static_pointer_cast<Model_Data>(theFeatures.front()->data());
+    if (!aData || !aData->isValid())
+      return false;
+    TDF_Label aPrevFeatureLabel = aData->label().Father();
+    // label of the feature before the first feature in the list
+    for (int aRefIndex = aRefs->Lower(); aRefIndex <= aRefs->Upper(); ++aRefIndex)
+      if (aPrevFeatureLabel == aRefs->Value(aRefIndex)) {
+        if (aRefIndex == aRefs->Lower())
+          aPrevFeatureLabel.Nullify();
+        else
+          aPrevFeatureLabel = aRefs->Value(aRefIndex - 1);
+        break;
+      }
+
+    // move the folder in the list of references before the first feature
+    RemoveFromRefArray(aFeaturesLab, aFolderLabel);
+    AddToRefArray(aFeaturesLab, aFolderLabel, aPrevFeatureLabel);
+    // update first feature of the folder
+    initFirstAttr = true;
+  } else {
+    // update last feature of the folder
+    initLastAttr = true;
+  }
+
+  if (initFirstAttr)
+    aFirstFeatAttr->setValue(theFeatures.front());
+  if (initLastAttr)
+    aLastFeatAttr->setValue(theFeatures.back());
+
+  updateHistory(ModelAPI_Feature::group());
+  return true;
+}
+
+static FolderPtr isExtractionCorrect(const FolderPtr& theFirstFeatureFolder,
+                                     const FolderPtr& theLastFeatureFolder,
+                                     bool& isExtractBefore)
+{
+  if (theFirstFeatureFolder.get()) {
+    if (theLastFeatureFolder.get())
+      return theFirstFeatureFolder == theLastFeatureFolder ? theFirstFeatureFolder : FolderPtr();
+    else
+      isExtractBefore = true;
+    return theFirstFeatureFolder;
+  } else if (theLastFeatureFolder.get()) {
+    isExtractBefore = false;
+    return theLastFeatureFolder;
+  }
+  // no folder found
+  return FolderPtr();
+}
+
+bool Model_Objects::removeFromFolder(
+      const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
+      const bool theBefore)
+{
+  if (theFeatures.empty())
+    return false;
+
+  FolderPtr aFirstFeatureFolder =
+      inFolder(theFeatures.front(), ModelAPI_Folder::FIRST_FEATURE_ID());
+  FolderPtr aLastFeatureFolder =
+      inFolder(theFeatures.back(),  ModelAPI_Folder::LAST_FEATURE_ID());
+
+  bool isExtractBeforeFolder = theBefore;
+  FolderPtr aFoundFolder =
+      isExtractionCorrect(aFirstFeatureFolder, aLastFeatureFolder, isExtractBeforeFolder);
+  if (!aFoundFolder)
+    return false; // list of features cannot be extracted
+
+  // references of the current folder
+  ObjectPtr aFolderStartFeature;
+  ObjectPtr aFolderEndFeature;
+  if (aFirstFeatureFolder != aLastFeatureFolder) {
+    aFolderStartFeature = aFoundFolder->reference(ModelAPI_Folder::FIRST_FEATURE_ID())->value();
+    aFolderEndFeature   = aFoundFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID())->value();
+  }
+
+  FeaturePtr aFeatureToFind = isExtractBeforeFolder ? theFeatures.back() : theFeatures.front();
+  std::shared_ptr<Model_Data> aData =
+      std::static_pointer_cast<Model_Data>(aFeatureToFind->data());
+  if (!aData || !aData->isValid())
+    return false;
+  TDF_Label aLabelToFind = aData->label().Father();
+
+  // search the label in the list of references
+  TDF_Label aFeaturesLab = featuresLabel();
+  Handle(TDataStd_ReferenceArray) aRefs;
+  if (!aFeaturesLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs))
+    return false; // no reference array (something is wrong)
+  int aRefIndex = aRefs->Lower();
+  for (; aRefIndex <= aRefs->Upper(); ++aRefIndex)
+    if (aRefs->Value(aRefIndex) == aLabelToFind)
+      break;
+
+  // update folder position
+  if (isExtractBeforeFolder) {
+    aData = std::dynamic_pointer_cast<Model_Data>(aFoundFolder->data());
+    TDF_Label aFolderLabel = aData->label().Father();
+    TDF_Label aPrevFeatureLabel = aRefs->Value(aRefIndex);
+    // update start reference of the folder
+    if (aFolderStartFeature.get()) {
+      FeaturePtr aNewStartFeature;
+      do { // skip all features placed in the composite features
+        aPrevFeatureLabel = aRefs->Value(aRefIndex++);
+        aNewStartFeature =
+            aRefIndex <= aRefs->Upper() ? feature(aRefs->Value(aRefIndex)) : FeaturePtr();
+      } while (aNewStartFeature && isSkippedFeature(aNewStartFeature));
+      aFolderStartFeature = aNewStartFeature;
+    }
+    // move the folder in the list of references after the last feature from the list
+    RemoveFromRefArray(aFeaturesLab, aFolderLabel);
+    AddToRefArray(aFeaturesLab, aFolderLabel, aPrevFeatureLabel);
+  } else {
+    // update end reference of the folder
+    if (aFolderEndFeature.get()) {
+      FeaturePtr aNewEndFeature;
+      do { // skip all features placed in the composite features
+        --aRefIndex;
+        aNewEndFeature =
+            aRefIndex >= aRefs->Lower() ? feature(aRefs->Value(aRefIndex)) : FeaturePtr();
+      } while (aNewEndFeature && isSkippedFeature(aNewEndFeature));
+      aFolderEndFeature = aNewEndFeature;
+    }
+  }
+
+  // update folder references
+  aFoundFolder->reference(ModelAPI_Folder::FIRST_FEATURE_ID())->setValue(aFolderStartFeature);
+  aFoundFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID())->setValue(aFolderEndFeature);
+
+  updateHistory(ModelAPI_Feature::group());
+  return true;
+}
+
+FolderPtr Model_Objects::findContainingFolder(const FeaturePtr& theFeature, int& theIndexInFolder)
+{
+  // search the label in the list of references
+  TDF_Label aFeaturesLab = featuresLabel();
+  Handle(TDataStd_ReferenceArray) aRefs;
+  if (!aFeaturesLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs))
+    return FolderPtr(); // no reference array (something is wrong)
+
+  std::shared_ptr<Model_Data> aData =
+      std::static_pointer_cast<Model_Data>(theFeature->data());
+  if (!aData || !aData->isValid())
+    return FolderPtr();
+  TDF_Label aLabelToFind = aData->label().Father();
+
+  theIndexInFolder = -1;
+  FolderPtr aFoundFolder;
+  TDF_Label aLastFeatureLabel;
+
+  for (int aRefIndex = aRefs->Lower(); aRefIndex <= aRefs->Upper(); ++aRefIndex) {
+    TDF_Label aCurLabel = aRefs->Value(aRefIndex);
+    if (isSkippedFeature(feature(aCurLabel)))
+      continue;
+
+    if (aFoundFolder)
+      ++theIndexInFolder;
+
+    if (aCurLabel == aLabelToFind) // the feature is reached
+      return aFoundFolder;
+
+    if (!aFoundFolder) {
+      // if the current label refers to a folder, feel all necessary data
+      aFoundFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(folder(aCurLabel));
+      if (aFoundFolder) {
+        theIndexInFolder = -1;
+
+        AttributeReferencePtr aLastRef =
+            aFoundFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID());
+        if (aLastRef->value()) {
+          aData = std::static_pointer_cast<Model_Data>(aLastRef->value()->data());
+          if (aData && aData->isValid())
+            aLastFeatureLabel = aData->label().Father();
+        } else // folder is empty
+          aFoundFolder = FolderPtr();
+      }
+    } else if (aLastFeatureLabel == aCurLabel) {
+      // folder is finished, clear all stored data
+      theIndexInFolder = -1;
+      aFoundFolder = FolderPtr();
+    }
+  }
+
+  // folder is not found
+  theIndexInFolder = -1;
+  return FolderPtr();
+}
+
+
 std::shared_ptr<ModelAPI_Feature> Model_Objects::feature(
     const std::shared_ptr<ModelAPI_Result>& theResult)
 {
@@ -1247,23 +1868,38 @@ ResultPtr Model_Objects::findByName(const std::string theName)
   return aResult;
 }
 
+TDF_Label Model_Objects::nextLabel(TDF_Label theCurrent, const bool theReverse)
+{
+  Handle(TDataStd_ReferenceArray) aRefs;
+  if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+    for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) { // iterate all existing features
+      TDF_Label aCurLab = aRefs->Value(a);
+      if (aCurLab.IsEqual(theCurrent)) {
+        a += theReverse ? -1 : 1;
+        if (a >= aRefs->Lower() && a <= aRefs->Upper())
+          return aRefs->Value(a);
+        break; // finish iiteration: it's last feature
+      }
+    }
+  }
+  return TDF_Label();
+}
+
 FeaturePtr Model_Objects::nextFeature(FeaturePtr theCurrent, const bool theReverse)
 {
   std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theCurrent->data());
   if (aData.get() && aData->isValid()) {
     TDF_Label aFeatureLabel = aData->label().Father();
-    Handle(TDataStd_ReferenceArray) aRefs;
-    if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
-      for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) { // iterate all existing features
-        TDF_Label aCurLab = aRefs->Value(a);
-        if (aCurLab.IsEqual(aFeatureLabel)) {
-          a += theReverse ? -1 : 1;
-          if (a >= aRefs->Lower() && a <= aRefs->Upper())
-            return feature(aRefs->Value(a));
-          break; // finish iiteration: it's last feature
-        }
-      }
-    }
+    do {
+      TDF_Label aNextLabel = nextLabel(aFeatureLabel, theReverse);
+      if (aNextLabel.IsNull())
+        break; // last or something is wrong
+      FeaturePtr aFound = feature(aNextLabel);
+      if (aFound)
+        return aFound; // the feature is found
+      // if the next label is a folder, skip it
+      aFeatureLabel = folder(aNextLabel).get() ? aNextLabel : TDF_Label();
+    } while (!aFeatureLabel.IsNull());
   }
   return FeaturePtr(); // not found, last, or something is wrong
 }
@@ -1311,6 +1947,22 @@ bool Model_Objects::isLater(FeaturePtr theLater, FeaturePtr theCurrent) const
   return false; // not found, or something is wrong
 }
 
+std::list<std::shared_ptr<ModelAPI_Object> > Model_Objects::allObjects()
+{
+  std::list<std::shared_ptr<ModelAPI_Object> > aResult;
+  Handle(TDataStd_ReferenceArray) aRefs;
+  if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+    for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) {
+      ObjectPtr anObject = object(aRefs->Value(a));
+      if (!anObject.get()) // is it a folder?
+        anObject = folder(aRefs->Value(a));
+      if (anObject.get())
+        aResult.push_back(anObject);
+    }
+  }
+  return aResult;
+}
+
 std::list<std::shared_ptr<ModelAPI_Feature> > Model_Objects::allFeatures()
 {
   std::list<std::shared_ptr<ModelAPI_Feature> > aResult;
index 57e02fa3492b539851d737261a4cd394acdf4270..856d3c90b12f87cb96a40e91ada6c4dec8ac0327 100644 (file)
@@ -24,6 +24,7 @@
 #include <Model.h>
 #include <ModelAPI_Document.h>
 #include <ModelAPI_Feature.h>
+#include <ModelAPI_Folder.h>
 #include <ModelAPI_Result.h>
 #include <ModelAPI_ResultParameter.h>
 
@@ -90,16 +91,23 @@ class Model_Objects
 
   //! Returns the object index in the group. Object must be visible. Otherwise returns -1.
   //! \param theObject object of this document
+  //! \param theAllowFolder take into account grouping feature by folders
   //! \returns index started from zero, or -1 if object is invisible or belongs to another document
-  const int index(std::shared_ptr<ModelAPI_Object> theObject);
+  const int index(std::shared_ptr<ModelAPI_Object> theObject,
+                  const bool theAllowFolder = false);
 
   //! Returns the feature in the group by the index (started from zero)
   //! \param theGroupID group that contains a feature
   //! \param theIndex zero-based index of feature in the group
-  ObjectPtr object(const std::string& theGroupID, const int theIndex);
+  //! \param theAllowFolder take into account grouping feature by folders
+  ObjectPtr object(const std::string& theGroupID,
+                   const int theIndex,
+                   const bool theAllowFolder = false);
 
   //! Returns the number of features in the group
-  int size(const std::string& theGroupID);
+  //! \param theGroupID group of objects
+  //! \param theAllowFolder take into account grouping feature by folders
+  int size(const std::string& theGroupID, const bool theAllowFolder = false);
 
   //! Returns all (and disabled) results of the given type.
   //! Not fast method (iterates all features).
@@ -141,6 +149,41 @@ class Model_Objects
   std::shared_ptr<ModelAPI_Feature>
     feature(const std::shared_ptr<ModelAPI_Result>& theResult);
 
+  /// Creates a folder (group of the features in the object browser)
+  std::shared_ptr<ModelAPI_Folder> createFolder(
+      const std::shared_ptr<ModelAPI_Feature>& theBeforeThis);
+  //! Removes the folder from the document (all features in the folder will be kept).
+  void removeFolder(std::shared_ptr<ModelAPI_Folder> theFolder);
+  //! Search a folder applicable for the list of features
+  //! (it means the list of features stored in the folder should be consequential)
+  //! \param theFeatures list of features to be added to folder
+  //! \param theBelow    search the folder below the features (if \c false, search above)
+  //! \return Empty pointer if there is no applicable folder
+  std::shared_ptr<ModelAPI_Folder> findFolder(
+      const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
+      const bool theBelow);
+  //! Search a folder containing the given feature.
+  //! Addtionally calculates a zero-based index of the feature in this folder.
+  //! \param theFeature feature to search
+  //! \param theIndexInFolder zero-based index in the folder or -1 if the feature is top-level.
+  //! \return the folder containing the feature or empty pointer if the feature is top-level.
+  std::shared_ptr<ModelAPI_Folder> findContainingFolder(
+      const std::shared_ptr<ModelAPI_Feature>& theFeature,
+      int& theIndexInFolder);
+  //! Add a list of features to the folder. The correctness of the adding is not performed
+  //! (such checks have been done in corresponding find.. method).
+  //! \return \c true if the movement is successfull
+  bool moveToFolder(const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
+                    const std::shared_ptr<ModelAPI_Folder>& theFolder);
+  //! Remove features from the folder
+  //! \param theFeatures list of features to be removed
+  //! \param theBefore   extract features before the folder (this parameter is applicable only
+  //!                    when all features in the folder are taking out,
+  //!                    in other cases the direction is taken automatically)
+  //! \return \c true if the features have been moved out
+  bool removeFromFolder(const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
+                        const bool theBefore = true);
+
   //! Sets the owner of this manager
   void setOwner(DocumentPtr theDoc);
 
@@ -159,6 +202,9 @@ class Model_Objects
   //! feature type + "_" + index
   void setUniqueName(FeaturePtr theFeature);
 
+  //! Initializes the foldet with an unique name ("Folder_" + index)
+  void setUniqueName(FolderPtr theFolder);
+
   //! Synchronizes myFeatures list with the updated document
   //! \param theUpdated list of labels that are marked as modified, so featrues must be also
   //! \param theUpdateReferences causes the update of back-references
@@ -214,6 +260,11 @@ class Model_Objects
   /// Returns true if theLater is in history of features creation later than theCurrent
   bool isLater(FeaturePtr theLater, FeaturePtr theCurrent) const;
 
+  /// Returns the next or previous label
+  /// \param theCurrent given label
+  /// \param theReverse if it is true, iterates in reverced order (next becomes previous)
+  TDF_Label nextLabel(TDF_Label theCurrent, const bool theReverse = false);
+
   /// Returns the result group identifier of the given feature (for this at least one result must
   /// be created before)
   std::string featureResultGroup(FeaturePtr theFeature);
@@ -222,6 +273,10 @@ class Model_Objects
   //! history. Not very fast method, for calling once, not in big cycles.
   std::list<std::shared_ptr<ModelAPI_Feature> > allFeatures();
 
+  //! Returns all objects of the document including the hidden features which are not in
+  //! history. Not very fast method, for calling once, not in big cycles.
+  std::list<std::shared_ptr<ModelAPI_Object> > allObjects();
+
   //! synchronises back references for the given object basing on the collected data
   void synchronizeBackRefsForObject(
     const std::set<std::shared_ptr<ModelAPI_Attribute>>& theNewRefs, ObjectPtr theObject);
@@ -236,6 +291,9 @@ class Model_Objects
                      int theResultIndex,
                      std::string& theParentName) const;
 
+  /// Return object representing a folder or empty pointer
+  ObjectPtr folder(TDF_Label theLabel) const;
+
  private:
   TDF_Label myMain; ///< main label of the data storage
 
@@ -245,6 +303,9 @@ class Model_Objects
   /// For optimization mapped by labels
   NCollection_DataMap<TDF_Label, FeaturePtr> myFeatures;
 
+  /// Managed folders
+  NCollection_DataMap<TDF_Label, ObjectPtr> myFolders;
+
   /// Map from group id to the array that contains all objects located in history.
   /// Each array is updated by demand from scratch, by browing all the features in the history.
   std::map<std::string, std::vector<ObjectPtr> > myHistory;
index 4962932bfe818400699161dfd0739184f385f08c..127507249a61b7fa02d5fbc3cd17719f253643b1 100644 (file)
@@ -267,9 +267,36 @@ std::string fullName(CompositeFeaturePtr theComposite, const TopoDS_Shape& theSu
 }
 
 // stores shape and name on sub-label of the main stored shape
-static void saveSubName(TDF_Label& theLab, const bool isSelectionMode, const TopoDS_Shape& aSub,
+static void saveSubName(CompositeFeaturePtr theComposite,
+  TDF_Label& theLab, const bool isSelectionMode, TopoDS_Shape aSub,
   std::shared_ptr<Model_Document> theDoc, std::string theFullName)
 {
+  // trying to store the edge of composite result, not sketch sub as it is
+  if (aSub.ShapeType() == TopAbs_EDGE) {
+    ResultPtr aRes = theComposite->firstResult();
+    ResultConstructionPtr aConstr = std::dynamic_pointer_cast<Model_ResultConstruction>(aRes);
+    if (aConstr.get()) {
+      Standard_Real aSubFirst, aSubLast;
+      TopoDS_Edge aSubEdge = TopoDS::Edge(aSub);
+      Handle(Geom_Curve) aSubCurve = BRep_Tool::Curve(aSubEdge, aSubFirst, aSubLast);
+      for(int aFaceIndex = 0; aFaceIndex < aConstr->facesNum(); aFaceIndex++) {
+        GeomShapePtr aGFace = aConstr->face(aFaceIndex);
+        TopoDS_Shape aFace = aGFace->impl<TopoDS_Shape>();
+        for(TopExp_Explorer anExp(aFace, TopAbs_EDGE); anExp.More(); anExp.Next()) {
+          TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current());
+          Standard_Real aFirst, aLast;
+          Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
+          if (aCurve == aSubCurve &&
+              ((fabs(aFirst - aSubFirst) < 1.e-9 &&  fabs(aLast - aSubLast) < 1.e-9)) ||
+              (fabs(aFirst - aSubLast) < 1.e-9 &&  fabs(aLast - aSubFirst) < 1.e-9)) {
+            aSub = anEdge;
+            break;
+          }
+        }
+      }
+    }
+  }
+
   TNaming_Builder aBuilder(theLab);
   if (isSelectionMode)
     aBuilder.Select(aSub, aSub);
@@ -447,7 +474,8 @@ int Model_ResultConstruction::select(const std::shared_ptr<GeomAPI_Shape>& theSu
                     TDF_Label aSubLab = aLab.FindChild(anID);
                     TDF_Label aShapeSubLab = aLab.FindChild(aSubLabId++);
                     std::string aFullNameSub = fullName(aComposite, anEdge);
-                    saveSubName(aShapeSubLab, isSelectionMode, anEdge, aMyDoc, aFullNameSub);
+                    saveSubName(aComposite,
+                      aShapeSubLab, isSelectionMode, anEdge, aMyDoc, aFullNameSub);
 
                     int anOrient = Model_SelectionNaming::edgeOrientation(aSubShape, anEdge);
                     if (anOrient != 0) {
@@ -463,7 +491,8 @@ int Model_ResultConstruction::select(const std::shared_ptr<GeomAPI_Shape>& theSu
                     TopoDS_Vertex aV = TopoDS::Vertex(anEdgeExp.Current());
                     TDF_Label aShapeSubLab = aLab.FindChild(aSubLabId++);
                     std::string aFullNameSub = fullName(aComposite, aV);
-                    saveSubName(aShapeSubLab, isSelectionMode, aV, aMyDoc, aFullNameSub);
+                    saveSubName(aComposite,
+                      aShapeSubLab, isSelectionMode, aV, aMyDoc, aFullNameSub);
                 }
               }
             }
index 6de12da8d0ad49553c9819a2ae402c9ae9bc86fa..8c794c3dcde8d39521997822d8df98a6ba0d8904 100644 (file)
@@ -47,6 +47,7 @@
 #include <TNaming_Tool.hxx>
 #include <TNaming_NamedShape.hxx>
 #include <TNaming_Localizer.hxx>
+#include <TNaming_SameShapeIterator.hxx>
 #include <TDataStd_Name.hxx>
 #include <TColStd_MapOfTransient.hxx>
 #include <algorithm>
@@ -61,6 +62,41 @@ Model_SelectionNaming::Model_SelectionNaming(TDF_Label theSelectionLab)
   myLab = theSelectionLab;
 }
 
+// searches named shape by the shape in the given document (identified by the label)
+// tries to find s shape nearest to the context-label
+static Handle(TNaming_NamedShape) shapeToNS(const TDF_Label theLabAccess,
+  const TopoDS_Shape& theShape, const TDF_Label& theContextLab)
+{
+  Handle(TNaming_NamedShape) aResult;
+  if (!TNaming_Tool::HasLabel(theLabAccess, theShape)) // no shape in the document
+    return aResult;
+  int aContextLabDepth = theContextLab.IsNull() ? 100 : theContextLab.Depth();
+  TNaming_SameShapeIterator aNSIter(theShape, theLabAccess);
+  for(; aNSIter.More(); aNSIter.Next()) {
+    TDF_Label aLabel = aNSIter.Label();
+    Handle(TNaming_NamedShape) aNS;
+    if (aLabel.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+      if (aNS->Evolution() != TNaming_SELECTED && aNS->Evolution() != TNaming_DELETE) {
+        // check this is new shape in this named shape
+        bool aIsNew = false;
+        for(TNaming_Iterator aNSIter(aNS); aNSIter.More(); aNSIter.Next())
+          if (!aNSIter.NewShape().IsNull() && aNSIter.NewShape().IsSame(theShape))
+            aIsNew = true;
+        if (!aIsNew)
+          continue;
+        // check this is the context-shape
+        while(aLabel.Depth() > aContextLabDepth)
+          aLabel = aLabel.Father();
+        if (aLabel.IsEqual(theContextLab))
+          return aNS;
+        if (aResult.IsNull()) // take the first, otherwise it will get shapes from results, etc
+          aResult = aNS; // keep some result anyway - if there are no context labels return any
+      }
+    }
+  }
+  return aResult;
+}
+
 std::string Model_SelectionNaming::getShapeName(
   std::shared_ptr<Model_Document> theDoc, const TopoDS_Shape& theShape,
   ResultPtr& theContext, const bool theAnotherDoc, const bool theWholeContext)
@@ -70,13 +106,14 @@ std::string Model_SelectionNaming::getShapeName(
   // (it was in BodyBuilder, but did not work on Result rename)
   bool isNeedContextName = theContext->shape().get() != NULL;
   // check if the subShape is already in DF
-  Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(theShape, myLab);
+  std::shared_ptr<Model_Data> aData =
+    std::dynamic_pointer_cast<Model_Data>(theContext->data());
+  TDF_Label aContextDataLab(aData.get() && aData->isValid() ? aData->label() : TDF_Label());
+  Handle(TNaming_NamedShape) aNS = shapeToNS(myLab, theShape, aContextDataLab);
   Handle(TDataStd_Name) anAttr;
   if(!aNS.IsNull() && !aNS->IsEmpty()) { // in the document
     if(aNS->Label().FindAttribute(TDataStd_Name::GetID(), anAttr)) {
-      std::shared_ptr<Model_Data> aData =
-        std::dynamic_pointer_cast<Model_Data>(theContext->data());
-      if (isNeedContextName && aData && aData->label().IsEqual(aNS->Label())) {
+      if (isNeedContextName && aData && aContextDataLab.IsEqual(aNS->Label())) {
         // do nothing because this context name will be added later in this method
       } else {
         aName = TCollection_AsciiString(anAttr->Get()).ToCString();
@@ -355,6 +392,10 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext,
           break;
         int n = aList.Extent();
         bool isByFaces = n >= 3;
+        if (isByFaces) { // check that by faces vertex is identified uniquly (2317)
+          TopoDS_Shape aVertex = findCommonShape(TopAbs_VERTEX, aList);
+          isByFaces = !aVertex.IsNull() && aVertex.ShapeType() == TopAbs_VERTEX;
+        }
         if(!isByFaces) { // open topology case or Compound case => via edges
           TopTools_IndexedDataMapOfShapeListOfShape aMap;
           TopExp::MapShapesAndAncestors(aContext, TopAbs_VERTEX, TopAbs_EDGE, aMap);
@@ -844,7 +885,16 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType,
             aFaceContext = aDoc->findByName(aContName, *it, anUniqueContext);
           }
         }
-        const TopoDS_Shape aFace = findFaceByName(*it, aDoc, aFaceContext, anUniqueContext);
+        TopoDS_Shape aFace = findFaceByName(*it, aDoc, aFaceContext, anUniqueContext);
+        if (aFace.IsNull() && aFaceContext.get() &&
+            aFaceContext->groupName() == ModelAPI_ResultConstruction::group() ) {
+          // search the construction sub-elements for the intersection if they are in the tree
+          size_t aSlash = it->find("/");
+          if (aSlash != std::string::npos) {
+            std::string aSubShapeName = it->substr(aSlash + 1);
+            aFace = findFaceByName(aSubShapeName, aDoc, aFaceContext, true);
+          }
+        }
         if(!aFace.IsNull())
           aList.Append(aFace);
       }
@@ -853,7 +903,7 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType,
   }
   // in case of construction, there is no registered names for all sub-elements,
   // even for the main element; so, trying to find them by name (without "&" intersections)
-  if (aN < 2) {
+  if (aSelection.IsNull() && aN < 2) {
     size_t aConstrNamePos = aSubShapeName.find("/");
     bool isFullName = aConstrNamePos == std::string::npos;
     std::string anEmpty, aContrName = aContName;
index 092bb88a0aef868751259bae3889e33090ee3c72..aa0b87e0ce66083fec1b5cf8caf75cd63307291e 100644 (file)
@@ -51,6 +51,7 @@ SET(PROJECT_HEADERS
     ModelAPI_Expression.h
     ModelAPI_Feature.h
     ModelAPI_FeatureValidator.h
+    ModelAPI_Folder.h
     ModelAPI_IReentrant.h
     ModelAPI_Object.h
     ModelAPI_Plugin.h
@@ -94,6 +95,7 @@ SET(PROJECT_SOURCES
     ModelAPI_Expression.cpp
     ModelAPI_Feature.cpp
     ModelAPI_FeatureValidator.cpp
+    ModelAPI_Folder.cpp
     ModelAPI_IReentrant.cpp
     ModelAPI_Object.cpp
     ModelAPI_Plugin.cpp
@@ -187,4 +189,8 @@ ADD_UNIT_TESTS(TestConstants.py
                TestCustomName_Rename.py
                TestCustomName_RotateGroup.py
                TestCustomName_Translation.py
+               TestFolder_Create.py
+               TestFolder_Update.py
+               TestFolder_Remove.py
+               TestFolder_Stability.py
 )
index 7c0466cdb0152f1ac71ea99f8dd0f5af10bec3b4..61403edf66643f8052bee4eda00678c645211761 100644 (file)
@@ -51,6 +51,7 @@
 %feature("director") ModelAPI_Feature;
 %feature("director") ModelAPI_CompositeFeature;
 %feature("director") ModelAPI_Data;
+%feature("director") ModelAPI_Folder;
 
 // shared pointers
 // For ModelAPI_ResultConstruction.shape()
@@ -62,6 +63,7 @@
 %shared_ptr(ModelAPI_Feature)
 %shared_ptr(ModelAPI_CompositeFeature)
 %shared_ptr(ModelAPI_Data)
+%shared_ptr(ModelAPI_Folder)
 %shared_ptr(ModelAPI_Attribute)
 %shared_ptr(ModelAPI_AttributeDocRef)
 %shared_ptr(ModelAPI_AttributeDouble)
   }
 }
 
+%apply int& OUTPUT {int& theIndexInFolder};
+
 // all supported interfaces
 %include "ModelAPI_Entity.h"
 %include "ModelAPI_Document.h"
 %include "ModelAPI_ResultParameter.h"
 %include "ModelAPI_Tools.h"
 %include "ModelAPI_ResultCompSolid.h"
+%include "ModelAPI_Folder.h"
 
 // std::list -> []
 %template(StringList) std::list<std::string>;
@@ -167,6 +172,7 @@ template<class T1, class T2> std::shared_ptr<T1> shared_ptr_cast(std::shared_ptr
 %template(featureToCompositeFeature) shared_ptr_cast<ModelAPI_CompositeFeature, ModelAPI_Feature>;
 %template(objectToFeature) shared_ptr_cast<ModelAPI_Feature, ModelAPI_Object>;
 %template(objectToResult) shared_ptr_cast<ModelAPI_Result, ModelAPI_Object>;
+%template(objectToFolder) shared_ptr_cast<ModelAPI_Folder, ModelAPI_Object>;
 %template(compositeFeatureToFeature) shared_ptr_cast<ModelAPI_Feature, ModelAPI_CompositeFeature>;
 
 %template(modelAPI_Result) shared_ptr_cast<ModelAPI_Result, ModelAPI_Object>;
index e1848123e782d42e57cbd8095417128b887fd79a..2fc8fbfc8fec35a6997faf2119930bcc8b9885fc 100644 (file)
@@ -74,9 +74,10 @@ class MODELAPI_EXPORT ModelAPI_Data
 
   /// Returns the name of the feature visible by the user in the object browser
   virtual std::string name() = 0;
-
   /// Defines the name of the feature visible by the user in the object browser
   virtual void setName(const std::string& theName) = 0;
+  /// Return \c true if the object has been renamed by the user
+  virtual bool hasUserDefinedName() const = 0;
 
   /// Returns the attribute that references to another document
   virtual std::shared_ptr<ModelAPI_AttributeDocRef> document(const std::string& theID) = 0;
index 24d7c4c4bde7c58e1c4120108947845c2fe3f194..e234aefe5a45721b42e061dde2a01a58b0e4702b 100644 (file)
@@ -31,6 +31,7 @@
 #include <set>
 
 class ModelAPI_Feature;
+class ModelAPI_Folder;
 class ModelAPI_Object;
 class ModelAPI_Result;
 class ModelAPI_ResultConstruction;
@@ -89,8 +90,10 @@ public:
   //! Returns the object in the group by the index (started from zero)
   //! \param theGroupID group that contains an object
   //! \param theIndex zero-based index of feature in the group
+  //! \param theAllowFolder take into account grouping feature by folders
   virtual std::shared_ptr<ModelAPI_Object> object(const std::string& theGroupID,
-                                                    const int theIndex) = 0;
+                                                  const int theIndex,
+                                                  const bool theAllowFolder = false) = 0;
 
   //! Returns the first found object in the group by the object name
   //! \param theGroupID group that contains an object
@@ -101,11 +104,15 @@ public:
 
   //! Returns the object index in the group. Object must be visible. Otherwise returns -1.
   //! \param theObject object of this document
+  //! \param theAllowFolder take into account grouping feature by folders
   //! \returns index started from zero, or -1 if object is invisible or belongs to another document
-  virtual const int index(std::shared_ptr<ModelAPI_Object> theObject) = 0;
+  virtual const int index(std::shared_ptr<ModelAPI_Object> theObject,
+                          const bool theAllowFolder = false) = 0;
 
   //! Returns the number of objects in the group of objects
-  virtual int size(const std::string& theGroupID) = 0;
+  //! \param theGroupID group of objects
+  //! \param theAllowFolder take into account grouping feature by folders
+  virtual int size(const std::string& theGroupID, const bool theAllowFolder = false) = 0;
 
   //! Returns the feature that is currently edited in this document, normally
   //! this is the latest created feature
@@ -170,6 +177,50 @@ public:
   //! history. Not very fast method, for calling once, not in big cycles.
   virtual std::list<std::shared_ptr<ModelAPI_Feature> > allFeatures() = 0;
 
+  //! Returns all objects of the document including the hidden features which are not in
+  //! history. Not very fast method, for calling once, not in big cycles.
+  virtual std::list<std::shared_ptr<ModelAPI_Object> > allObjects() = 0;
+
+  //! Creates a folder (group of the features in the object browser)
+  //! \param theAddBefore a feature, the folder is added before
+  //!                     (if empty, the folder is added after the last feature)
+  virtual std::shared_ptr<ModelAPI_Folder> addFolder(
+      std::shared_ptr<ModelAPI_Feature> theAddBefore = std::shared_ptr<ModelAPI_Feature>()) = 0;
+  //! Removes the folder from the document (all features in the folder will be kept).
+  virtual void removeFolder(std::shared_ptr<ModelAPI_Folder> theFolder) = 0;
+  //! Search a folder above the list of features applicable to store them
+  //! (it means the list of features stored in the folder should be consequential)
+  //! \return Empty pointer if there is no applicable folder
+  virtual std::shared_ptr<ModelAPI_Folder> findFolderAbove(
+      const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures) = 0;
+  //! Search a folder below the list of features applicable to store them
+  //! (it means the list of features stored in the folder should be consequential)
+  //! \return Empty pointer if there is no applicable folder
+  virtual std::shared_ptr<ModelAPI_Folder> findFolderBelow(
+      const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures) = 0;
+  //! Search a folder containing the given feature.
+  //! Addtionally calculates a zero-based index of the feature in this folder.
+  //! \param theFeature feature to search
+  //! \param theIndexInFolder zero-based index in the folder or -1 if the feature is top-level.
+  //! \return the folder containing the feature or empty pointer if the feature is top-level.
+  virtual std::shared_ptr<ModelAPI_Folder> findContainingFolder(
+      const std::shared_ptr<ModelAPI_Feature>& theFeature,
+      int& theIndexInFolder) = 0;
+  //! Add a list of features to the folder. The correctness of the adding is not performed
+  //! (such checks have been done in corresponding find.. method).
+  //! \return \c true if the movement is successfull
+  virtual bool moveToFolder(const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
+                            const std::shared_ptr<ModelAPI_Folder>& theFolder) = 0;
+  //! Remove features from the folder
+  //! \param theFeatures list of features to be removed
+  //! \param theBefore   extract features before the folder (this parameter is applicable only
+  //!                    when all features in the folder are taking out,
+  //!                    in other cases the direction is taken automatically)
+  //! \return \c true if the features have been moved out
+  virtual bool removeFromFolder(
+      const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
+      const bool theBefore = true) = 0;
+
   //! Informs the document that it becomes active and some actions must be performed
   virtual void setActive(const bool theFlag) = 0;
   //! Returns true if this document is currently active
diff --git a/src/ModelAPI/ModelAPI_Folder.cpp b/src/ModelAPI/ModelAPI_Folder.cpp
new file mode 100644 (file)
index 0000000..1cc97cb
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "ModelAPI_Folder.h"
+
+#include <ModelAPI_AttributeReference.h>
+
+ModelAPI_Folder::ModelAPI_Folder()
+{
+}
+
+ModelAPI_Folder::~ModelAPI_Folder()
+{
+}
+
+void ModelAPI_Folder::init()
+{
+}
+
+void ModelAPI_Folder::initAttributes()
+{
+  data()->addAttribute(FIRST_FEATURE_ID(), ModelAPI_AttributeReference::typeId());
+  data()->addAttribute(LAST_FEATURE_ID(),  ModelAPI_AttributeReference::typeId());
+}
+
+void ModelAPI_Folder::execute()
+{
+}
diff --git a/src/ModelAPI/ModelAPI_Folder.h b/src/ModelAPI/ModelAPI_Folder.h
new file mode 100644 (file)
index 0000000..b89fd87
--- /dev/null
@@ -0,0 +1,105 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef ModelAPI_Folder_H_
+#define ModelAPI_Folder_H_
+
+#include <ModelAPI.h>
+#include <ModelAPI_Object.h>
+
+/**\class ModelAPI_Folder
+ * \ingroup DataModel
+ * \brief Folder feature (groups the features).
+ */
+class ModelAPI_Folder : public ModelAPI_Object
+{
+public:
+  MODELAPI_EXPORT ModelAPI_Folder();
+  /// To virtually destroy the fields of successors
+  MODELAPI_EXPORT virtual ~ModelAPI_Folder();
+
+  /// Folder feature ID
+  static const std::string& ID()
+  {
+    static const std::string MY_FOLDER_ID("Folder");
+    return MY_FOLDER_ID;
+  }
+
+  /// Returns the group identifier of all features
+  inline static std::string group()
+  {
+    static std::string MY_GROUP = "Folders";
+    return MY_GROUP;
+  }
+
+  /// Returns the group identifier of this result
+  virtual std::string groupName()
+  {
+    return group();
+  }
+
+  /// Attribute referring first feature in the folder
+  static const std::string& FIRST_FEATURE_ID()
+  {
+    static const std::string MY_FIRST_FEATURE_ID("first_feature");
+    return MY_FIRST_FEATURE_ID;
+  }
+
+  /// Attribute referring last feature in the folder
+  static const std::string& LAST_FEATURE_ID()
+  {
+    static const std::string MY_LAST_FEATURE_ID("last_feature");
+    return MY_LAST_FEATURE_ID;
+  }
+
+  /// Request for initialization of data model of the object: adding all attributes
+  MODELAPI_EXPORT virtual void initAttributes();
+
+  /// Computes or recomputes the results
+  MODELAPI_EXPORT virtual void execute();
+
+  /// Returns the feature is disabled or not.
+  virtual bool isDisabled()
+  { return false; }
+
+  //
+  // Helper methods, aliases for data()->method()
+  // -----------------------------------------------------------------------------------------------
+  /// Returns the name stored in the attribute
+  inline std::string name()
+  {
+    return data()->name();
+  }
+  /// Returns the reference attribute by the identifier
+  inline std::shared_ptr<ModelAPI_AttributeReference> reference(const std::string& theID)
+  {
+    return data()->reference(theID);
+  }
+
+protected:
+  /// This method is called just after creation of the object: it must initialize
+  /// all fields, normally initialized in the constructor
+  MODELAPI_EXPORT virtual void init();
+};
+
+//! Pointer on a folder object
+typedef std::shared_ptr<ModelAPI_Folder> FolderPtr;
+
+#endif
index f22b73c23c1ce295cf320d64d933fa12440a4992..1e57d36b76113351ad2aff3d4c04837c88fd2837 100755 (executable)
@@ -382,6 +382,7 @@ bool removeFeaturesAndReferences(const std::set<FeaturePtr>& theFeatures,
   return ModelAPI_Tools::removeFeatures(aFeatures, false);
 }
 
+//***********************************************************************
 bool removeFeatures(const std::set<FeaturePtr>& theFeatures,
                     const bool theFlushRedisplay)
 {
@@ -406,6 +407,7 @@ bool removeFeatures(const std::set<FeaturePtr>& theFeatures,
   return true;
 }
 
+//***********************************************************************
 // Fills the references list by all references of the feature from the references map.
 // This is a recusive method to find references by next found feature in the map of references.
 // \param theFeature a feature to find references
@@ -623,8 +625,9 @@ void getConcealedResults(const FeaturePtr& theFeature,
   }
 }
 
-std::string getDefaultName(const std::shared_ptr<ModelAPI_Result>& theResult,
-                           const int theResultIndex)
+std::pair<std::string, bool> getDefaultName(
+    const std::shared_ptr<ModelAPI_Result>& theResult,
+    const int theResultIndex)
 {
   typedef std::list< std::pair < std::string, std::list<ObjectPtr> > > ListOfReferences;
 
@@ -646,7 +649,7 @@ std::string getDefaultName(const std::shared_ptr<ModelAPI_Result>& theResult,
       if (aCompSolidRes == *anIt)
         break;
     aDefaultName << "_" << (aCompSolidResultIndex + 1) << "_" << (theResultIndex + 1);
-    return aDefaultName.str();
+    return std::pair<std::string, bool>(aDefaultName.str(), false);
   }
 
   DataPtr aData = anOwner->data();
@@ -693,7 +696,11 @@ std::string getDefaultName(const std::shared_ptr<ModelAPI_Result>& theResult,
       ResultCompSolidPtr aParentCompSolid = ModelAPI_Tools::compSolidOwner(anObjRes);
       if (aParentCompSolid)
         anObjRes = aParentCompSolid;
-      return anObjRes->data()->name();
+
+      // return name of reference result only if it has been renamed by the user,
+      // in other case compose a default name
+      if (anObjRes->data()->hasUserDefinedName())
+        return std::pair<std::string, bool>(anObjRes->data()->name(), true);
     }
   }
 
@@ -704,7 +711,7 @@ std::string getDefaultName(const std::shared_ptr<ModelAPI_Result>& theResult,
   // add unique prefix starting from second
   if (theResultIndex > 0 || theResult->groupName() == ModelAPI_ResultBody::group())
     aDefaultName << "_" << theResultIndex + 1;
-  return aDefaultName.str();
+  return std::pair<std::string, bool>(aDefaultName.str(), false);
 }
 
 } // namespace ModelAPI_Tools
index 1a2db5e05b2ecc979215b76d11979e245c3f2ba4..e7c297b30840755b4e7fb3692acb853ec69c70f5 100755 (executable)
@@ -188,9 +188,12 @@ MODELAPI_EXPORT void getConcealedResults(const std::shared_ptr<ModelAPI_Feature>
                                    std::list<std::shared_ptr<ModelAPI_Result> >& theResults);
 
 /*! Return the default name of the result according the the features it depends.
+ *  Return also whether the name is get from the concealing result of parent object
+ *  (means that concealing result has user-defined name).
  */
-MODELAPI_EXPORT std::string getDefaultName(const std::shared_ptr<ModelAPI_Result>& theResult,
-                                           const int theResultIndex);
+MODELAPI_EXPORT std::pair<std::string, bool> getDefaultName(
+    const std::shared_ptr<ModelAPI_Result>& theResult,
+    const int theResultIndex);
 }
 
 #endif
index 470b8e3d46370fb71390c05a79a13674b1dcca3f..e9d740ce076c8dedb9bd0c6e5a909c048cd52d8f 100644 (file)
@@ -60,6 +60,7 @@
   #include "ModelAPI_ResultField.h"
   #include "ModelAPI_Tools.h"
   #include "ModelAPI_ResultCompSolid.h"
+  #include "ModelAPI_Folder.h"
 
   #include <memory>
   #include <string>
index ef0f8c564e011606b8f3e6684eb9aa04d9e38b02..b9e7e44aef748229899c90e02e484b0fb4643e82 100755 (executable)
@@ -155,13 +155,13 @@ def check_owner(selection, topology_type, feature):
   aSession.abortOperation()
 
 # check faces
-check_owner("_Extrusion_1_1/Generated_Face_1", "face", aBox)
-check_owner("Extrusion_3_1/Modified_3", "face", aBox)
-check_owner("Extrusion_1_1/Modified_1", "face", aHoleExt)
-check_owner("Extrusion_3_1/Modified_2", "face", aTower)
+check_owner("Extrusion_1_1/Generated_Face_1", "face", aBox)
+check_owner("Boolean_2_1/Modified_Face_3", "face", aBox)
+check_owner("Boolean_1_1/Modified_Face_1", "face", aHoleExt)
+check_owner("Boolean_2_1/Modified_Face_2", "face", aTower)
 # check edges without ambiguity
-check_owner("Extrusion_3_1/Modified_3&_Extrusion_1_1/Generated_Face_2", "edge", aBox)
-check_owner("Extrusion_3_1/Modified_2&_Extrusion_3_1/To_Face_1", "edge", aTower)
+check_owner("Boolean_2_1/Modified_Face_3&Extrusion_1_1/Generated_Face_2", "edge", aBox)
+check_owner("Boolean_2_1/Modified_Face_2&Extrusion_3_1/To_Face_1_1", "edge", aTower)
 
 # check the connected topology method: solid is not a compound of connected topology
 assert(aFuse.firstResult().shape().isConnectedTopology() == False)
index 431f7300d10ecd8a6a7ced984063650190976512..8418bdc89bf762d073b2768ab3ce4e1982cfb223 100644 (file)
@@ -79,8 +79,8 @@ model.do()
 #=========================================================================
 # Make a cylindrical hole using one of the produced faces
 #=========================================================================
-ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [], model.selection(), model.selection(), 0, model.selection("FACE", "_Extrusion_1_1/Generated_Face_2"), 0, [model.selection("SOLID", "Extrusion_1_1")])
-Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Modfied_4"))
+ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [], model.selection(), model.selection(), 0, model.selection("FACE", "Extrusion_1_1/Generated_Face_2"), 0, [model.selection("SOLID", "ExtrusionCut_1_1")])
+Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_1_1/Modfied_3"))
 SketchCircle_1 = Sketch_3.addCircle(143.412751420315, -228.52745656314, 32.158435160764)
 ExtrusionCut_2.setNestedSketch(Sketch_3)
 
@@ -92,8 +92,8 @@ Part_1.document().setCurrentFeature(ExtrusionCut_1.feature(), True)
 #=========================================================================
 # Modify the cylindrical hole base face by another groove in the history before the hole is created
 #=========================================================================
-ExtrusionCut_3 = model.addExtrusionCut(Part_1_doc, [], model.selection(), model.selection(), 0, model.selection("FACE", "__Extrusion_1_1/Generated_Face_3"), -50, [model.selection("SOLID", "Extrusion_1_1")])
-Sketch_4 = model.addSketch(Part_1_doc, model.selection("FACE", "__Extrusion_1_1/Generated_Face_1"))
+ExtrusionCut_3 = model.addExtrusionCut(Part_1_doc, [], model.selection(), model.selection(), 0, model.selection("FACE", "Extrusion_1_1/Generated_Face_1"), -50, [model.selection("SOLID", "ExtrusionCut_1_1")])
+Sketch_4 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_3"))
 SketchLine_9 = Sketch_4.addLine(-176.701443076057, -151.212050129331, -91.83965287802501, -151.212050129331)
 SketchLine_10 = Sketch_4.addLine(-91.83965287802501, -151.212050129331, -91.83965287802501, -84.473709256573)
 SketchLine_11 = Sketch_4.addLine(-91.83965287802501, -84.473709256573, -176.701443076057, -84.473709256573)
@@ -125,6 +125,6 @@ import ModelAPI
 
 assert(ModelAPI.ModelAPI_Session.get().validators().validate(Sketch_4.feature()))
 assert(ModelAPI.ModelAPI_Session.get().validators().validate(ExtrusionCut_2.feature()))
-assert(Sketch_3.feature().selection("External").namingName() == "_Extrusion_1_1/Modfied_4")
+assert(Sketch_3.feature().selection("External").namingName() == "ExtrusionCut_3_1/Modfied_5")
 
 assert(model.checkPythonDump())
index f332784e26f1084a3f47ebaeca9f037c0776867e..daf3d34731eeb2e6ef43b24a0d864e34d9bc0b09 100644 (file)
@@ -66,7 +66,7 @@ Sketch_1.result().setName("tutu")
 Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "tutu/Face-SketchLine_1f-SketchLine_3f-SketchArc_1_2f-SketchArc_2_2f")], model.selection(), 10, 0)
 Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "tutu/Edge-SketchLine_2")])
 Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("EDGE", "Edge_1_1")], model.selection("EDGE", "PartSet/OZ"), 100, 0)
-Group_1 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "Edge_1_1/Generated_Edge_2&Edge_1_1/To_Edge_1"), model.selection("VERTEX", "Edge_1_1/Generated_Edge_1&Edge_1_1/To_Edge_1")])
+Group_1 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "Extrusion_2_1/Generated_Edge_2&Extrusion_2_1/To_Edge_1"), model.selection("VERTEX", "Extrusion_2_1/Generated_Edge_1&Extrusion_2_1/To_Edge_1")])
 model.end()
 
 # check that resulting group selection is valid
index 0926071b411a39f5574b4cc39a7d44986d6ab46a..666faafe6201e4475e107743f0fea6cb39750f72 100644 (file)
@@ -55,10 +55,10 @@ SketchConstraintHorizontal_2 = Sketch_3.setHorizontal(SketchLine_3.result())
 SketchConstraintVertical_2 = Sketch_3.setVertical(SketchLine_4.result())
 model.do()
 Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_2"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_3"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_4"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_1")])
-Extrusion_4 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchCircle_2_2f")], model.selection(), model.selection("FACE", "_Extrusion_2_1/From_Face_1"), 0, model.selection(), 0)
+Extrusion_4 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchCircle_2_2f")], model.selection(), model.selection("FACE", "Extrusion_2_1/From_Face_1"), 0, model.selection(), 0)
 Boolean_2 = model.addCut(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], [model.selection("SOLID", "Extrusion_4_1")])
-Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_2_1"), model.selection("FACE", "Face_1_1")])
-Remove_SubShapes_1 = model.addRemoveSubShapes(Part_1_doc, model.selection("COMPOUND", "Extrusion_1_1"))
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Boolean_1_1"), model.selection("SOLID", "Boolean_2_1"), model.selection("FACE", "Face_1_1")])
+Remove_SubShapes_1 = model.addRemoveSubShapes(Part_1_doc, model.selection("COMPOUND", "Partition_1_1"))
 Remove_SubShapes_1.setSubShapesToKeep([model.selection("COMPSOLID", "Partition_1_1_1")])
 model.end()
 
index dd5e5f8694c59b07eb34c221463c36216f277c4d..319ce2d0969b155af4bd14f7884cfc13f156f96b 100644 (file)
@@ -122,21 +122,17 @@ Face_5 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_3/Wire-Sketc
 MultiTranslation_1 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Face_5_1")], model.selection("EDGE", "PartSet/OX"), "l", 4, model.selection("EDGE", "PartSet/OY"), "l", 2)
 Recover_1 = model.addRecover(Part_1_doc, MultiTranslation_1, [Face_5.result()])
 Translation_1 = model.addTranslation(Part_1_doc, [model.selection("FACE", "Recover_1_1")], model.selection("VERTEX", "Face_4_1/Edge_6&Face_4_1/Edge_7"), model.selection("VERTEX", "Face_4_1/Edge_4&Face_4_1/Edge_5"))
-Translation_1.result().setName("Translation_1_1")
 MultiTranslation_2 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Translation_1_1")], model.selection("EDGE", "PartSet/OX"), "l", 4, model.selection("EDGE", "PartSet/OY"), "l", 2)
 Recover_2 = model.addRecover(Part_1_doc, MultiTranslation_1, [Face_5.result()])
 Translation_2 = model.addTranslation(Part_1_doc, [model.selection("FACE", "Recover_2_1")], model.selection("VERTEX", "Face_4_1/Edge_6&Face_4_1/Edge_7"), model.selection("VERTEX", "Face_4_1/Edge_2&Face_4_1/Edge_3"))
-Translation_2.result().setName("Translation_2_1")
 MultiTranslation_3 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Translation_2_1")], model.selection("EDGE", "PartSet/OX"), "l", 4)
 Recover_3 = model.addRecover(Part_1_doc, MultiTranslation_1, [Face_5.result()])
-Translation_3 = model.addTranslation(Part_1_doc, [model.selection("FACE", "Recover_3_1")], model.selection("VERTEX", "Face_4_1/Edge_6&Face_4_1/Edge_7"), model.selection("VERTEX", "Translation_2_1/Translated_Edge_1_4&Translation_2_1/Translated_Edge_1_3"))
-Translation_3.result().setName("Translation_3_1")
+Translation_3 = model.addTranslation(Part_1_doc, [model.selection("FACE", "Recover_3_1")], model.selection("VERTEX", "Face_4_1/Edge_6&Face_4_1/Edge_7"), model.selection("VERTEX", "LinearCopy_3_1/Translated_Edge_1_4&LinearCopy_3_1/Translated_Edge_1_3"))
 MultiTranslation_4 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Translation_3_1")], model.selection("EDGE", "PartSet/OX"), "l", 3)
 Recover_4 = model.addRecover(Part_1_doc, MultiTranslation_1, [Face_5.result()])
 Translation_4 = model.addTranslation(Part_1_doc, [model.selection("FACE", "Recover_4_1")], model.selection("VERTEX", "Face_4_1/Edge_6&Face_4_1/Edge_7"), model.selection("VERTEX", "Face_4_1/Edge_1&Face_4_1/Edge_9"))
-Translation_4.result().setName("Translation_4_1")
 MultiTranslation_5 = model.addMultiTranslation(Part_1_doc, [model.selection("FACE", "Translation_4_1")], model.selection("EDGE", "PartSet/OX"), "l", 2)
-Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "MultiTranslation_4_1_2"), model.selection("FACE", "MultiTranslation_1_1_8"), model.selection("FACE", "MultiTranslation_1_1_4"), model.selection("FACE", "MultiTranslation_1_1_3"), model.selection("FACE", "MultiTranslation_1_1_6"), model.selection("FACE", "MultiTranslation_1_1_2"), model.selection("FACE", "MultiTranslation_1_1_7"), model.selection("FACE", "MultiTranslation_2_1_3"), model.selection("FACE", "MultiTranslation_3_1_4"), model.selection("FACE", "MultiTranslation_2_1_8"), model.selection("FACE", "MultiTranslation_2_1_4"), model.selection("FACE", "MultiTranslation_2_1_7"), model.selection("FACE", "MultiTranslation_4_1_3"), model.selection("FACE", "MultiTranslation_1_1_1"), model.selection("FACE", "MultiTranslation_5_1_2"), model.selection("FACE", "MultiTranslation_4_1_1"), model.selection("FACE", "MultiTranslation_5_1_1"), model.selection("FACE", "MultiTranslation_3_1_3"), model.selection("FACE", "MultiTranslation_3_1_2"), model.selection("FACE", "MultiTranslation_3_1_1"), model.selection("FACE", "MultiTranslation_2_1_6"), model.selection("FACE", "MultiTranslation_2_1_2"), model.selection("FACE", "MultiTranslation_2_1_5"), model.selection("FACE", "MultiTranslation_2_1_1"), model.selection("FACE", "MultiTranslation_1_1_5")])
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "LinearCopy_4_1_2"), model.selection("FACE", "LinearCopy_1_1_8"), model.selection("FACE", "LinearCopy_1_1_4"), model.selection("FACE", "LinearCopy_1_1_3"), model.selection("FACE", "LinearCopy_1_1_6"), model.selection("FACE", "LinearCopy_1_1_2"), model.selection("FACE", "LinearCopy_1_1_7"), model.selection("FACE", "LinearCopy_2_1_3"), model.selection("FACE", "LinearCopy_3_1_4"), model.selection("FACE", "LinearCopy_2_1_8"), model.selection("FACE", "LinearCopy_2_1_4"), model.selection("FACE", "LinearCopy_2_1_7"), model.selection("FACE", "LinearCopy_4_1_3"), model.selection("FACE", "LinearCopy_1_1_1"), model.selection("FACE", "LinearCopy_5_1_2"), model.selection("FACE", "LinearCopy_4_1_1"), model.selection("FACE", "LinearCopy_5_1_1"), model.selection("FACE", "LinearCopy_3_1_3"), model.selection("FACE", "LinearCopy_3_1_2"), model.selection("FACE", "LinearCopy_3_1_1"), model.selection("FACE", "LinearCopy_2_1_6"), model.selection("FACE", "LinearCopy_2_1_2"), model.selection("FACE", "LinearCopy_2_1_5"), model.selection("FACE", "LinearCopy_2_1_1"), model.selection("FACE", "LinearCopy_1_1_5")])
 Group_1.setName("Group_3")
 Group_1.result().setName("assemblages")
 Group_2 = model.addGroup(Part_1_doc, [model.selection("FACE", "Face_2_1"), model.selection("FACE", "Face_3_7"), model.selection("FACE", "Face_3_5"), model.selection("FACE", "Face_3_3"), model.selection("FACE", "Face_3_4"), model.selection("FACE", "Face_3_1"), model.selection("FACE", "Face_3_2"), model.selection("FACE", "Face_3_6"), model.selection("FACE", "Face_3_11"), model.selection("FACE", "Face_3_10"), model.selection("FACE", "Face_3_8"), model.selection("FACE", "Face_3_9"), model.selection("FACE", "Face_3_12")])
@@ -147,10 +143,9 @@ Group_3 = model.addGroup(Part_1_doc, [model.selection("FACE", "Face_4_1")])
 Group_3.setName("Group_2")
 Group_3.result().setName("acier")
 Group_3.result().setColor(170, 85, 0)
-Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "MultiTranslation_1_1_1"), model.selection("FACE", "MultiTranslation_1_1_2"), model.selection("FACE", "MultiTranslation_1_1_3"), model.selection("FACE", "MultiTranslation_1_1_4"), model.selection("FACE", "MultiTranslation_1_1_5"), model.selection("FACE", "MultiTranslation_1_1_6"), model.selection("FACE", "MultiTranslation_1_1_7"), model.selection("FACE", "MultiTranslation_2_1_4"), model.selection("FACE", "MultiTranslation_2_1_5"), model.selection("FACE", "MultiTranslation_2_1_6"), model.selection("FACE", "MultiTranslation_2_1_7"), model.selection("FACE", "MultiTranslation_2_1_8"), model.selection("FACE", "MultiTranslation_2_1_1"), model.selection("FACE", "MultiTranslation_2_1_2"), model.selection("FACE", "MultiTranslation_2_1_3"), model.selection("FACE", "MultiTranslation_3_1_4"), model.selection("FACE", "MultiTranslation_3_1_3"), model.selection("FACE", "MultiTranslation_3_1_2"), model.selection("FACE", "MultiTranslation_3_1_1"), model.selection("FACE", "MultiTranslation_4_1_1"), model.selection("FACE", "MultiTranslation_4_1_2"), model.selection("FACE", "MultiTranslation_4_1_3"), model.selection("FACE", "MultiTranslation_5_1_1"), model.selection("FACE", "MultiTranslation_5_1_2"), model.selection("FACE", "MultiTranslation_1_1_8")])
-Shell_1.result().setName("Shell_1_1")
+Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "LinearCopy_1_1_1"), model.selection("FACE", "LinearCopy_1_1_2"), model.selection("FACE", "LinearCopy_1_1_3"), model.selection("FACE", "LinearCopy_1_1_4"), model.selection("FACE", "LinearCopy_1_1_5"), model.selection("FACE", "LinearCopy_1_1_6"), model.selection("FACE", "LinearCopy_1_1_7"), model.selection("FACE", "LinearCopy_2_1_4"), model.selection("FACE", "LinearCopy_2_1_5"), model.selection("FACE", "LinearCopy_2_1_6"), model.selection("FACE", "LinearCopy_2_1_7"), model.selection("FACE", "LinearCopy_2_1_8"), model.selection("FACE", "LinearCopy_2_1_1"), model.selection("FACE", "LinearCopy_2_1_2"), model.selection("FACE", "LinearCopy_2_1_3"), model.selection("FACE", "LinearCopy_3_1_4"), model.selection("FACE", "LinearCopy_3_1_3"), model.selection("FACE", "LinearCopy_3_1_2"), model.selection("FACE", "LinearCopy_3_1_1"), model.selection("FACE", "LinearCopy_4_1_1"), model.selection("FACE", "LinearCopy_4_1_2"), model.selection("FACE", "LinearCopy_4_1_3"), model.selection("FACE", "LinearCopy_5_1_1"), model.selection("FACE", "LinearCopy_5_1_2"), model.selection("FACE", "LinearCopy_1_1_8")])
 Partition_1 = model.addPartition(Part_1_doc, [model.selection("FACE", "Face_3_1"), model.selection("FACE", "Face_3_2"), model.selection("FACE", "Face_4_1"), model.selection("FACE", "Face_2_1"), model.selection("FACE", "Face_1_1"), model.selection("FACE", "Face_3_5"), model.selection("FACE", "Face_3_3"), model.selection("FACE", "Face_3_4"), model.selection("FACE", "Face_3_7"), model.selection("FACE", "Face_3_6"), model.selection("FACE", "Face_3_8"), model.selection("FACE", "Face_3_9"), model.selection("FACE", "Face_3_10"), model.selection("FACE", "Face_3_11"), model.selection("FACE", "Face_3_12"), model.selection("SHELL", "Shell_1_1")])
-Remove_SubShapes_1 = model.addRemoveSubShapes(Part_1_doc, model.selection("COMPOUND", "Face_3_1"))
+Remove_SubShapes_1 = model.addRemoveSubShapes(Part_1_doc, model.selection("COMPOUND", "Partition_1_1"))
 Remove_SubShapes_1.setSubShapesToKeep([model.selection("FACE", "Partition_1_1_2"), model.selection("FACE", "Partition_1_1_3"), model.selection("FACE", "Partition_1_1_4"), model.selection("FACE", "Partition_1_1_5"), model.selection("FACE", "Partition_1_1_6"), model.selection("FACE", "Partition_1_1_7"), model.selection("FACE", "Partition_1_1_8"), model.selection("FACE", "Partition_1_1_9")])
 model.end()
 
@@ -161,19 +156,20 @@ Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
 Part_1_doc.moveFeature(Group_3.feature(), Group_2.feature())
 model.end()
 
-# check that group 2 is correct, but Group_1 and Group_3 elements are removed (because shell is removed)
+# check that group 2 is correct (some subs are removed), but Group_1 and Group_3 elements are removed (because shell is removed)
 from ModelAPI import *
 aFactory = ModelAPI_Session.get().validators()
 
-assert(Group_1.groupList().size() != 0)
-for a in range(Group_1.groupList().size()):
-  assert(len(Group_1.groupList().value(a).namingName()) == 0)
+assert(Group_2.groupList().size() != 0)
+for a in range(Group_2.groupList().size()):
+  if not Group_1.groupList().value(a).context() is None:
+    assert(len(Group_1.groupList().value(a).namingName()) == 0)
 
-assert(aFactory.validate(Group_3.feature()))
-assert(Group_3.groupList().size() != 0)
-for a in range(Group_3.groupList().size()):
-  assert(Group_3.groupList().value(a).value().shapeTypeStr() == "FACE")
-  assert(len(Group_3.groupList().value(a).namingName()) > 0)
+#assert(aFactory.validate(Group_3.feature()))
+#assert(Group_3.groupList().size() != 0)
+#for a in range(Group_3.groupList().size()):
+#  assert(Group_3.groupList().value(a).value().shapeTypeStr() == "FACE")
+#  assert(len(Group_3.groupList().value(a).namingName()) > 0)
 
 # for Group in [Group_1, Group_2, Group_3]:
 #   if Group == Group_2:
index fb24a174622eddd7dda1bf349d0eae29e01231b1..5eb24bc40250c3a57b256c2e5c2e74e53ace80f2 100644 (file)
@@ -62,8 +62,8 @@ SketchConstraintHorizontal_4 = Sketch_2.setHorizontal(SketchLine_7.result())
 SketchConstraintVertical_4 = Sketch_2.setVertical(SketchLine_8.result())
 SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
 SketchPoint_2 = SketchProjection_2.createdFeature()
-SketchConstraintDistanceVertical_1 = Sketch_2.setVerticalDistance(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_7.endPoint(), -5)
-SketchConstraintDistanceHorizontal_1 = Sketch_2.setHorizontalDistance(SketchLine_8.startPoint(), SketchAPI_Point(SketchPoint_2).coordinates(), -10)
+SketchConstraintDistanceVertical_1 = Sketch_2.setVerticalDistance(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_7.endPoint(), 5)
+SketchConstraintDistanceHorizontal_1 = Sketch_2.setHorizontalDistance(SketchLine_8.startPoint(), SketchAPI_Point(SketchPoint_2).coordinates(), 10)
 SketchConstraintLength_3 = Sketch_2.setLength(SketchLine_8.result(), 60)
 SketchConstraintLength_4 = Sketch_2.setLength(SketchLine_7.result(), 40)
 model.do()
index 831f49fadc6513f64a92fa31cfb13bafbbf7d5c9..7da2b0e44bfe9b9a8a6134164098b2cf60c8f061 100644 (file)
@@ -52,9 +52,9 @@ SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_6.endPoint(),
 SketchConstraintPerpendicular_1 = Sketch_1.setPerpendicular(SketchLine_5.result(), SketchLine_6.result())
 SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_3.result(), SketchLine_4.result())
 SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_2.result(), 80)
-SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_6.startPoint(), SketchLine_1.endPoint(), -20)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_6.startPoint(), SketchLine_1.endPoint(), 20)
 SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_5.endPoint(), SketchLine_1.startPoint(), 15)
-SketchConstraintDistanceVertical_2 = Sketch_1.setVerticalDistance(SketchLine_6.endPoint(), SketchLine_1.startPoint(), -50)
+SketchConstraintDistanceVertical_2 = Sketch_1.setVerticalDistance(SketchLine_6.endPoint(), SketchLine_1.startPoint(), 50)
 model.do()
 Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), 50, 0)
 Extrusion_1.result().setName("compsolid")
index d4fb33a3077429a35fbc77e42706fb42e378d8c1..211275e52be47ee2348d664d9f4a279dc38701ef 100644 (file)
@@ -47,7 +47,7 @@ SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), 40)
 SketchCircle_1 = Sketch_1.addCircle(30, 70, 20)
 SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 20)
 SketchConstraintDistance_1 = Sketch_1.setDistance(SketchCircle_1.center(), SketchLine_3.result(), 30, True)
-SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchCircle_1.center(), SketchLine_2.startPoint(), -30)
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchCircle_1.center(), SketchLine_2.startPoint(), 30)
 SketchLine_5 = Sketch_1.addLine(12.50000000006628, -45.31088913249455, 30, -15)
 SketchLine_6 = Sketch_1.addLine(30, -15, 47.50000000006629, -45.31088913249455)
 SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
@@ -58,7 +58,7 @@ SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_5.result(), SketchLine_7.
 SketchConstraintEqual_2 = Sketch_1.setEqual(SketchLine_5.result(), SketchLine_6.result())
 SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_7.result())
 SketchConstraintLength_3 = Sketch_1.setLength(SketchLine_7.result(), 35)
-SketchConstraintDistanceHorizontal_2 = Sketch_1.setHorizontalDistance(SketchLine_5.endPoint(), SketchLine_2.startPoint(), -30)
+SketchConstraintDistanceHorizontal_2 = Sketch_1.setHorizontalDistance(SketchLine_5.endPoint(), SketchLine_2.startPoint(), 30)
 SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_5.endPoint(), SketchLine_2.startPoint(), 15)
 model.do()
 Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r")], model.selection(), 10, 0)
@@ -84,8 +84,8 @@ SketchConstraintLength_4 = Sketch_2.setLength(SketchLine_10.result(), 20)
 SketchConstraintLength_5 = Sketch_2.setLength(SketchLine_9.result(), 130)
 SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "box/Generated_Face_3&box/Generated_Face_2&box/From_Face_1"), False)
 SketchPoint_2 = SketchProjection_2.createdFeature()
-SketchConstraintDistanceVertical_2 = Sketch_2.setVerticalDistance(SketchLine_8.endPoint(), SketchAPI_Point(SketchPoint_2).coordinates(), -30)
-SketchConstraintDistanceHorizontal_3 = Sketch_2.setHorizontalDistance(SketchLine_8.endPoint(), SketchAPI_Point(SketchPoint_2).coordinates(), -25)
+SketchConstraintDistanceVertical_2 = Sketch_2.setVerticalDistance(SketchLine_8.endPoint(), SketchAPI_Point(SketchPoint_2).coordinates(), 30)
+SketchConstraintDistanceHorizontal_3 = Sketch_2.setHorizontalDistance(SketchLine_8.endPoint(), SketchAPI_Point(SketchPoint_2).coordinates(), 25)
 model.do()
 Extrusion_4 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_8f-SketchLine_9f-SketchLine_10f-SketchLine_11f")], model.selection(), 5, 15)
 Extrusion_4.result().setName("cut_tool")
diff --git a/src/ModelAPI/Test/TestFolder_Create.py b/src/ModelAPI/Test/TestFolder_Create.py
new file mode 100644 (file)
index 0000000..ad96314
--- /dev/null
@@ -0,0 +1,105 @@
+## Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+from ModelAPI import *
+
+__updated__ = "2017-11-22"
+
+#=========================================================================
+# Test 1. Check the Folder is created in PartSet
+#=========================================================================
+aSession = ModelAPI_Session.get()
+aPartSetDoc = aSession.activeDocument()
+
+aSession.startOperation()
+aPoint0 = aPartSetDoc.addFeature("Point")
+aPoint0Data = aPoint0.data()
+assert(aPoint0Data is not None)
+aPoint0Data.real("x").setValue(0.)
+aPoint0Data.real("y").setValue(0.)
+aPoint0Data.real("z").setValue(0.)
+aPoint0Data.string("creation_method").setValue("by_xyz")
+aSession.finishOperation()
+
+aSession.startOperation()
+aPoint1 = aPartSetDoc.addFeature("Point")
+aPoint1Data = aPoint1.data()
+assert(aPoint1Data is not None)
+aPoint1Data.real("x").setValue(0.)
+aPoint1Data.real("y").setValue(0.)
+aPoint1Data.real("z").setValue(0.)
+aPoint1Data.string("creation_method").setValue("by_xyz")
+aSession.finishOperation()
+
+assert(aPartSetDoc.size("Features") == 2), "Wrong number of features: {}".format(aPartSetDoc.size("Features"))
+
+# Folder before the feature
+aSession.startOperation()
+aFolder1 = aPartSetDoc.addFolder(aPoint1)
+aSession.finishOperation()
+
+assert(aPartSetDoc.size("Folders") == 1), "Wrong number of folders: {}".format(aPartSetDoc.size("Folders"))
+assert(aPartSetDoc.size("Features") == 3), "Wrong number of features: {}".format(aPartSetDoc.size("Features"))
+FOLDER_NAME_EXPECTED = "Folder_1"
+assert(aFolder1.name() == FOLDER_NAME_EXPECTED), "Actual name '{}', expected '{}'".format(aFolder1.name(), FOLDER_NAME_EXPECTED)
+
+## Folder at the end of features list
+#aSession.startOperation()
+#aPartSetDoc.addFolder()
+#aSession.finishOperation()
+#assert(aPartSetDoc.size("Folders") == 2)
+
+#=========================================================================
+# Test 2. Check the Folder is created in a Part
+#=========================================================================
+aSession.startOperation()
+aPart = aSession.moduleDocument().addFeature("Part")
+aSession.finishOperation()
+
+# check part is a last feature
+aFeaturesList = aSession.moduleDocument().allObjects()
+aLast = aFeaturesList[len(aFeaturesList)-1]
+assert(aLast.data().isEqual(aPart.data())), "Part is not a last object in the list"
+
+# add point and a folder before it
+aPartDoc = aSession.activeDocument()
+aSession.startOperation()
+aPoint2 = aPartDoc.addFeature("Point")
+aPoint2Data = aPoint2.data()
+assert(aPoint2Data is not None)
+aPoint2Data.real("x").setValue(0.)
+aPoint2Data.real("y").setValue(0.)
+aPoint2Data.real("z").setValue(0.)
+aPoint2Data.string("creation_method").setValue("by_xyz")
+aSession.finishOperation()
+
+assert(aPartDoc.size("Features") == 1), "Wrong number of features: {}".format(aPartDoc.size("Features"))
+
+aSession.startOperation()
+aFolder2 = aPartDoc.addFolder(aPoint2)
+aSession.finishOperation()
+
+assert(aPartDoc.size("Folders") == 1), "Wrong number of folders: {}".format(aPartDoc.size("Folders"))
+assert(aPartDoc.size("Features") == 2), "Wrong number of features: {}".format(aPartDoc.size("Features"))
+FOLDER_NAME_EXPECTED = "Folder_1"
+assert(aFolder2.name() == FOLDER_NAME_EXPECTED), "Actual name '{}', expected '{}'".format(aFolder2.name(), FOLDER_NAME_EXPECTED)
diff --git a/src/ModelAPI/Test/TestFolder_Remove.py b/src/ModelAPI/Test/TestFolder_Remove.py
new file mode 100644 (file)
index 0000000..6e78b58
--- /dev/null
@@ -0,0 +1,154 @@
+## Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+from ModelAPI import *
+
+__updated__ = "2017-11-24"
+
+aSession = ModelAPI_Session.get()
+
+
+def newPoint(theDocument, theX, theY, theZ):
+    aSession.startOperation()
+    aPoint = theDocument.addFeature("Point")
+    aPointData = aPoint.data()
+    assert(aPointData is not None)
+    aPointData.real("x").setValue(theX)
+    aPointData.real("y").setValue(theY)
+    aPointData.real("z").setValue(theZ)
+    aPointData.string("creation_method").setValue("by_xyz")
+    aSession.finishOperation()
+    return aPoint
+
+
+#=========================================================================
+# Prepare some features and folders
+#=========================================================================
+aSession.startOperation()
+aPart = aSession.moduleDocument().addFeature("Part")
+aSession.finishOperation()
+
+# add points
+aPartDoc = aSession.activeDocument()
+aPoint1 = newPoint(aPartDoc,  0.,  0., 0.)
+aPoint2 = newPoint(aPartDoc, 10.,  0., 0.)
+aPoint3 = newPoint(aPartDoc, 10., 10., 0.)
+aPoint4 = newPoint(aPartDoc,  0., 10., 0.)
+
+# add folders
+aSession.startOperation()
+aFolder1 = aPartDoc.addFolder(aPoint2)
+aSession.finishOperation()
+aSession.startOperation()
+aFolder2 = aPartDoc.addFolder(aPoint2)
+aSession.finishOperation()
+aSession.startOperation()
+aFolder3 = aPartDoc.addFolder(aPoint3)
+aSession.finishOperation()
+
+# place points into folders
+toFolder = FeatureList()
+toFolder.append(aPoint1)
+
+aSession.startOperation()
+aFolder = aPartDoc.findFolderBelow(toFolder)
+assert(aFolder is not None)
+isAdded = aPartDoc.moveToFolder(toFolder, aFolder)
+aSession.finishOperation()
+assert(isAdded)
+
+toFolder = FeatureList()
+toFolder.append(aPoint3)
+toFolder.append(aPoint4)
+
+aSession.startOperation()
+aFolder = aPartDoc.findFolderAbove(toFolder)
+assert(aFolder is not None)
+isAdded = aPartDoc.moveToFolder(toFolder, aFolder)
+aSession.finishOperation()
+assert(isAdded)
+
+NB_FEATURES_FULL = 7
+NB_FEATURES_OUT  = 4
+
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+assert(aPartDoc.index(aFolder1, True) == 0), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder1, True))
+assert(aPartDoc.index(aFolder2, True) == 1), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder2, True))
+assert(aPartDoc.index(aFolder3, True) == 3), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3, True))
+
+assert(aPartDoc.index(aPoint1, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint1, True))
+assert(aPartDoc.index(aPoint2, True) ==  2), "Wrong index of the point: {}".format(aPartDoc.index(aPoint2, True))
+assert(aPartDoc.index(aPoint3, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint3, True))
+assert(aPartDoc.index(aPoint4, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint4, True))
+
+
+#=========================================================================
+# Test 1. Remove empty folder
+#=========================================================================
+aSession.startOperation()
+aPartDoc.removeFolder(aFolder2)
+aSession.finishOperation()
+
+NB_FEATURES_FULL -= 1
+NB_FEATURES_OUT  -= 1
+
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+assert(aPartDoc.index(aFolder1, True) == 0), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder1, True))
+assert(aPartDoc.index(aFolder2, True) == -1), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder2, True))
+assert(aPartDoc.index(aFolder3, True) == 2), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3, True))
+
+assert(aPartDoc.index(aPoint1, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint1, True))
+assert(aPartDoc.index(aPoint2, True) ==  1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint2, True))
+assert(aPartDoc.index(aPoint3, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint3, True))
+assert(aPartDoc.index(aPoint4, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint4, True))
+
+
+#=========================================================================
+# Test 2. Remove non-empty folder
+#=========================================================================
+aSession.startOperation()
+aPartDoc.removeFolder(aFolder3)
+aSession.finishOperation()
+
+NB_FEATURES_FULL -= 1
+NB_FEATURES_OUT  += 1
+
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+assert(aPartDoc.index(aFolder1, True) == 0), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder1, True))
+assert(aPartDoc.index(aFolder2, True) == -1), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder2, True))
+assert(aPartDoc.index(aFolder3, True) == -1), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3, True))
+
+assert(aPartDoc.index(aPoint1, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint1, True))
+assert(aPartDoc.index(aPoint2, True) ==  1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint2, True))
+assert(aPartDoc.index(aPoint3, True) ==  2), "Wrong index of the point: {}".format(aPartDoc.index(aPoint3, True))
+assert(aPartDoc.index(aPoint4, True) ==  3), "Wrong index of the point: {}".format(aPartDoc.index(aPoint4, True))
+
+
+from salome.shaper import model
+assert(model.checkPythonDump())
diff --git a/src/ModelAPI/Test/TestFolder_Sketch.py b/src/ModelAPI/Test/TestFolder_Sketch.py
new file mode 100644 (file)
index 0000000..bf6768a
--- /dev/null
@@ -0,0 +1,187 @@
+## Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+"""
+    Test checks adding sketch into a folder
+"""
+
+from ModelAPI import *
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+Sketch_0 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_0.addLine(10, -10, 10, 10)
+model.do()
+
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_1.addCircle(50, 50, 25)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchCircle_1_2f")], model.selection(), 50, 0)
+
+Sketch_2 = model.addSketch(Part_1_doc, model.standardPlane("XOY"))
+SketchCircle_2 = Sketch_2.addCircle(100, -100, 50)
+model.do()
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_3")], model.selection(), 10, 0)
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), 0, 10, [model.selection("SOLID", "Extrusion_2_1")])
+Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_2_1/To_Face_1"))
+SketchProjection_1 = Sketch_3.addProjection(model.selection("VERTEX", "Extrusion_2_1/Generated_Face_1&Extrusion_2_1/To_Face_1__cc"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_3 = Sketch_3.addCircle(100, -100, 25)
+SketchConstraintCoincidence_1 = Sketch_3.setCoincident(SketchPoint_1.result(), SketchCircle_3.center())
+ExtrusionCut_1.setNestedSketch(Sketch_3)
+model.do()
+model.end()
+
+
+aSession = ModelAPI_Session.get()
+aPartDoc = aSession.activeDocument()
+
+#=========================================================================
+# Test 1. Sketch and extrusion could be added to the folder above
+#=========================================================================
+aSession.startOperation()
+Folder_1 = aPartDoc.addFolder(Sketch_1.feature())
+aSession.finishOperation()
+
+NB_FEATURES_FULL = 7
+NB_FEATURES_OUT  = 7
+# full number of features
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+# number of features outside the folder
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+toFolder = FeatureList()
+toFolder.append(Sketch_1.feature())
+toFolder.append(Extrusion_1.feature())
+
+# move features to the folder
+aSession.startOperation()
+aFolder = aPartDoc.findFolderAbove(toFolder)
+assert(aFolder is not None and aFolder.data().isEqual(Folder_1.data()))
+isAdded = aPartDoc.moveToFolder(toFolder, aFolder)
+aSession.finishOperation()
+assert(isAdded)
+NB_FEATURES_OUT -= 2
+# full number of features
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+# number of features outside the folder
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+# check the index of the sketch in the folder
+aFound = aPartDoc.findContainingFolder(Sketch_1.feature())
+assert(aFound[0].data().isEqual(aFolder.data()))
+assert(aFound[1] == 0)
+# check the index of the extrusion in the folder
+aFound = aPartDoc.findContainingFolder(Extrusion_1.feature())
+assert(aFound[0].data().isEqual(aFolder.data()))
+assert(aFound[1] == 1)
+
+
+#=========================================================================
+# Test 2. Sketch could be added to the folder below
+#=========================================================================
+aSession.startOperation()
+Folder_2 = aPartDoc.addFolder(Extrusion_2.feature())
+aSession.finishOperation()
+
+NB_FEATURES_FULL += 1
+NB_FEATURES_OUT  += 1
+# full number of features
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+# number of features outside the folder
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+toFolder = FeatureList()
+toFolder.append(Sketch_2.feature())
+
+# move feature to the folder
+aSession.startOperation()
+aFolder = aPartDoc.findFolderBelow(toFolder)
+assert(aFolder is not None and aFolder.data().isEqual(Folder_2.data()))
+isAdded = aPartDoc.moveToFolder(toFolder, aFolder)
+aSession.finishOperation()
+assert(isAdded)
+NB_FEATURES_OUT -= 1
+# full number of features
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+# number of features outside the folder
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+# check the index of the sketch in the folder
+aFound = aPartDoc.findContainingFolder(Sketch_2.feature())
+assert(aFound[0].data().isEqual(aFolder.data()))
+assert(aFound[1] == 0)
+
+
+#=========================================================================
+# Test 3. Sketch could be removed from the folder
+#=========================================================================
+fromFolder = FeatureList()
+fromFolder.append(Sketch_1.feature())
+
+aSession.startOperation()
+isMovedOut = aPartDoc.removeFromFolder(fromFolder)
+aSession.finishOperation()
+assert(isMovedOut)
+assert(aPartDoc.index(Sketch_1.feature(), True) == 1), "Wrong index of the {}: {}".format(Sketch_1.feature().name(), aPartDoc.index(Sketch_1.feature(), True))
+NB_FEATURES_OUT += 1
+# full number of features
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+# number of features outside the folder
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+
+#=========================================================================
+# Test 4. Add 2 sketches to the folder below
+#=========================================================================
+
+toFolder = FeatureList()
+toFolder.append(Sketch_0.feature())
+toFolder.append(Sketch_1.feature())
+
+# move features to the folder
+aSession.startOperation()
+aFolder = aPartDoc.findFolderBelow(toFolder)
+assert(aFolder is not None and aFolder.data().isEqual(Folder_1.data()))
+isAdded = aPartDoc.moveToFolder(toFolder, aFolder)
+aSession.finishOperation()
+assert(isAdded)
+NB_FEATURES_OUT -= 2
+# full number of features
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+# number of features outside the folder
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+# check the index of the sketch in the folder
+aFound = aPartDoc.findContainingFolder(Sketch_0.feature())
+assert(aFound[0].data().isEqual(aFolder.data()))
+assert(aFound[1] == 0)
+# check the index of the extrusion in the folder
+aFound = aPartDoc.findContainingFolder(Sketch_1.feature())
+assert(aFound[0].data().isEqual(aFolder.data()))
+assert(aFound[1] == 1)
+
+
+from salome.shaper import model
+assert(model.checkPythonDump())
diff --git a/src/ModelAPI/Test/TestFolder_Stability.py b/src/ModelAPI/Test/TestFolder_Stability.py
new file mode 100644 (file)
index 0000000..e6cdbe8
--- /dev/null
@@ -0,0 +1,94 @@
+## Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+#=========================================================================
+# Test checks stability of the foldering mechanism due to incorrect input parameters
+#=========================================================================
+from ModelAPI import *
+
+__updated__ = "2017-11-23"
+
+aSession = ModelAPI_Session.get()
+
+
+def newPoint(theDocument, theX, theY, theZ):
+    aSession.startOperation()
+    aPoint = theDocument.addFeature("Point")
+    aPointData = aPoint.data()
+    assert(aPointData is not None)
+    aPointData.real("x").setValue(theX)
+    aPointData.real("y").setValue(theY)
+    aPointData.real("z").setValue(theZ)
+    aPointData.string("creation_method").setValue("by_xyz")
+    aSession.finishOperation()
+    return aPoint
+
+
+#=========================================================================
+# Initialization of the model
+#=========================================================================
+aSession.startOperation()
+aPart = aSession.moduleDocument().addFeature("Part")
+aSession.finishOperation()
+
+# add point and a folder before it
+aPartDoc = aSession.activeDocument()
+aPoint1 = newPoint(aPartDoc, 0., 0., 0.)
+
+aSession.startOperation()
+aFolder1 = aPartDoc.addFolder(aPoint1)
+aSession.finishOperation()
+
+NB_FEATURES_FULL = 2
+NB_FEATURES_OUT  = 2
+
+assert(aPartDoc.size("Folders") == 1), "Wrong number of folders: {}".format(aPartDoc.size("Folders"))
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}".format(aPartDoc.size("Features"))
+
+#=========================================================================
+# Test 1. Check number of features out of folder
+#         and absense of the crash while getting size of incorrect group
+#=========================================================================
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+assert(aPartDoc.size("Construction", True) == 1), "Wrong size: {}".format(aPartDoc.size("Construction", True))
+
+#=========================================================================
+# Test 2. Add a feature to the folder and check number of features once again
+#=========================================================================
+toFolder = FeatureList()
+toFolder.append(aPoint1)
+
+aSession.startOperation()
+aFolder2 = aPartDoc.addFolder(aPoint1)
+aSession.finishOperation()
+
+NB_FEATURES_FULL += 1
+NB_FEATURES_OUT  += 1
+
+aSession.startOperation()
+aFolder = aPartDoc.findFolderAbove(toFolder)
+assert(aFolder is not None)
+isAdded = aPartDoc.moveToFolder(toFolder, aFolder)
+aSession.finishOperation()
+assert(isAdded)
+
+NB_FEATURES_OUT -= 1
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+assert(aPartDoc.size("Construction", True) == 1), "Wrong size: {}".format(aPartDoc.size("Construction", True))
diff --git a/src/ModelAPI/Test/TestFolder_Update.py b/src/ModelAPI/Test/TestFolder_Update.py
new file mode 100644 (file)
index 0000000..3940625
--- /dev/null
@@ -0,0 +1,382 @@
+## Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+from ModelAPI import *
+
+__updated__ = "2017-11-23"
+
+aSession = ModelAPI_Session.get()
+
+
+def newPoint(theDocument, theX, theY, theZ):
+    aSession.startOperation()
+    aPoint = theDocument.addFeature("Point")
+    aPointData = aPoint.data()
+    assert(aPointData is not None)
+    aPointData.real("x").setValue(theX)
+    aPointData.real("y").setValue(theY)
+    aPointData.real("z").setValue(theZ)
+    aPointData.string("creation_method").setValue("by_xyz")
+    aSession.finishOperation()
+    return aPoint
+
+
+#=========================================================================
+# Test 1. Add a point into a folder above
+#=========================================================================
+aSession.startOperation()
+aPart = aSession.moduleDocument().addFeature("Part")
+aSession.finishOperation()
+
+# add point and a folder before it
+aPartDoc = aSession.activeDocument()
+aPoint1 = newPoint(aPartDoc, 0., 0., 0.)
+
+aSession.startOperation()
+aFolder1 = aPartDoc.addFolder(aPoint1)
+aSession.finishOperation()
+
+NB_FEATURES_FULL = 2
+NB_FEATURES_OUT  = 2
+
+assert(aPartDoc.size("Folders") == 1), "Wrong number of folders: {}".format(aPartDoc.size("Folders"))
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}".format(aPartDoc.size("Features"))
+FOLDER_NAME_EXPECTED = "Folder_1"
+assert(aFolder1.name() == FOLDER_NAME_EXPECTED), "Actual name '{}', expected '{}'".format(aFolder1.name(), FOLDER_NAME_EXPECTED)
+
+toFolder = FeatureList()
+toFolder.append(aPoint1)
+
+# move point to the folder
+aSession.startOperation()
+aFolder = aPartDoc.findFolderAbove(toFolder)
+assert(aFolder is not None)
+isAdded = aPartDoc.moveToFolder(toFolder, aFolder)
+aSession.finishOperation()
+assert(isAdded)
+NB_FEATURES_OUT -= 1
+# full number of features
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+# number of features outside the folder
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+# check the index of the point in the folder
+aFound = aPartDoc.findContainingFolder(aPoint1)
+assert(aFound[0].data().isEqual(aFolder1.data()))
+assert(aFound[1] == 0)
+
+#=========================================================================
+# Test 2. Add a point, check it is added to a folder, then move it out
+#=========================================================================
+aPoint2 = newPoint(aPartDoc, 10., 0., 0.)
+
+NB_FEATURES_FULL += 1
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+fromFolder = FeatureList()
+fromFolder.append(aPoint2)
+
+aSession.startOperation()
+isMovedOut = aPartDoc.removeFromFolder(fromFolder)
+aSession.finishOperation()
+assert(isMovedOut)
+
+NB_FEATURES_OUT += 1
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+#=========================================================================
+# Test 3. Add a point into a folder below
+#=========================================================================
+aPoint3 = newPoint(aPartDoc, 10., 10., 0.)
+
+NB_FEATURES_FULL += 1
+NB_FEATURES_OUT += 1
+
+# add a folder
+aSession.startOperation()
+aFolder2 = aPartDoc.addFolder(aPoint3)
+aSession.finishOperation()
+
+NB_FEATURES_FULL += 1
+NB_FEATURES_OUT += 1
+
+assert(aPartDoc.size("Folders") == 2), "Wrong number of folders: {}".format(aPartDoc.size("Folders"))
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+toFolder = FeatureList()
+toFolder.append(aPoint2)
+
+# move point to the folder
+aSession.startOperation()
+aFolder = aPartDoc.findFolderBelow(toFolder)
+assert(aFolder is not None)
+isAdded = aPartDoc.moveToFolder(toFolder, aFolder)
+aSession.finishOperation()
+assert(isAdded)
+
+NB_FEATURES_OUT -= 1
+
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+# check the index of the point in the folder
+aFound = aPartDoc.findContainingFolder(aPoint2)
+assert(aFound[0].data().isEqual(aFolder2.data()))
+assert(aFound[1] == 0)
+aFound = aPartDoc.findContainingFolder(aPoint3)
+assert(aFound == -1)
+
+#=========================================================================
+# Test 4. Add several points into a folder
+#=========================================================================
+aPoint4 = newPoint(aPartDoc, 0., 10., 0.)
+
+NB_FEATURES_FULL += 1
+NB_FEATURES_OUT += 1
+
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+# index without respect to foldering
+assert(aPartDoc.index(aPoint4) == 5), "Wrong index of the point: {}".format(aPartDoc.index(aPoint4))
+# index according to folders
+assert(aPartDoc.index(aPoint4, True) == 3), "Wrong index of the point: {}".format(aPartDoc.index(aPoint4, True))
+
+# add a folder
+aSession.startOperation()
+aFolder3 = aPartDoc.addFolder(aPoint3)
+aSession.finishOperation()
+
+NB_FEATURES_FULL += 1
+NB_FEATURES_OUT += 1
+
+assert(aPartDoc.size("Folders") == 3), "Wrong number of folders: {}".format(aPartDoc.size("Folders"))
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+# index without respect to foldering
+assert(aPartDoc.index(aFolder3) == 4), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3))
+assert(aPartDoc.index(aPoint4) == 6), "Wrong index of the point: {}".format(aPartDoc.index(aPoint4))
+# index according to folders
+assert(aPartDoc.index(aFolder3, True) == 2), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3, True))
+assert(aPartDoc.index(aPoint4, True) == 4), "Wrong index of the point: {}".format(aPartDoc.index(aPoint4, True))
+
+toFolder = FeatureList()
+toFolder.append(aPoint3)
+toFolder.append(aPoint4)
+
+# move point to the folder
+aSession.startOperation()
+aFolder = aPartDoc.findFolderAbove(toFolder)
+assert(aFolder is not None)
+isAdded = aPartDoc.moveToFolder(toFolder, aFolder)
+aSession.finishOperation()
+assert(isAdded)
+
+NB_FEATURES_OUT -= 2
+
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+# index without respect to foldering
+assert(aPartDoc.index(aFolder3) == 4), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3))
+assert(aPartDoc.index(aPoint3) == 5), "Wrong index of the point: {}".format(aPartDoc.index(aPoint3))
+assert(aPartDoc.index(aPoint4) == 6), "Wrong index of the point: {}".format(aPartDoc.index(aPoint4))
+# index according to folders
+assert(aPartDoc.index(aFolder3, True) == 2), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3, True))
+assert(aPartDoc.index(aPoint3, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint3, True))
+assert(aPartDoc.index(aPoint4, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint4, True))
+
+# check the index of the point in the folder
+aFound = aPartDoc.findContainingFolder(aPoint3)
+assert(aFound[0].data().isEqual(aFolder3.data()))
+assert(aFound[1] == 0)
+aFound = aPartDoc.findContainingFolder(aPoint4)
+assert(aFound[0].data().isEqual(aFolder3.data()))
+assert(aFound[1] == 1)
+
+aPoint5 = newPoint(aPartDoc, 0., 0., 10.)
+fromFolder = FeatureList()
+fromFolder.append(aPoint5)
+
+aSession.startOperation()
+isMovedOut = aPartDoc.removeFromFolder(fromFolder)
+aSession.finishOperation()
+assert(isMovedOut)
+
+# add more points to the folder to move them out
+aPoint6 = newPoint(aPartDoc, 10., 0., 10.)
+aPoint7 = newPoint(aPartDoc, 10., 10., 10.)
+aPoint8 = newPoint(aPartDoc, 0., 10., 10.)
+
+toFolder = FeatureList()
+toFolder.append(aPoint5)
+toFolder.append(aPoint6)
+toFolder.append(aPoint7)
+toFolder.append(aPoint8)
+
+# move point to the folder
+aSession.startOperation()
+aFolder = aPartDoc.findFolderAbove(toFolder)
+assert(aFolder is not None)
+isAdded = aPartDoc.moveToFolder(toFolder, aFolder)
+aSession.finishOperation()
+assert(isAdded)
+
+NB_FEATURES_FULL += 4
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+assert(aPartDoc.index(aPoint5, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint5, True))
+assert(aPartDoc.index(aPoint6, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint6, True))
+assert(aPartDoc.index(aPoint7, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint7, True))
+assert(aPartDoc.index(aPoint8, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint8, True))
+
+assert(aFolder3.reference("first_feature").value() is not None)
+assert(aFolder3.reference("last_feature").value() is not None)
+
+#=========================================================================
+# Test 5. Remove a point from a folder before it
+#=========================================================================
+fromFolder = FeatureList()
+fromFolder.append(aPoint3)
+
+aSession.startOperation()
+isMovedOut = aPartDoc.removeFromFolder(fromFolder)
+aSession.finishOperation()
+assert(isMovedOut)
+
+NB_FEATURES_OUT += 1
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+assert(aPartDoc.index(aPoint3, True) == 2), "Wrong index of the point: {}".format(aPartDoc.index(aPoint3, True))
+assert(aPartDoc.index(aFolder3, True) == 3), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3, True))
+
+assert(aFolder3.reference("first_feature").value() is not None)
+assert(aFolder3.reference("last_feature").value() is not None)
+
+#=========================================================================
+# Test 6. Remove a point from a folder after it
+#=========================================================================
+fromFolder = FeatureList()
+fromFolder.append(aPoint8)
+
+aSession.startOperation()
+isMovedOut = aPartDoc.removeFromFolder(fromFolder)
+aSession.finishOperation()
+assert(isMovedOut)
+
+NB_FEATURES_OUT += 1
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+assert(aPartDoc.index(aPoint8, True) == 4), "Wrong index of the point: {}".format(aPartDoc.index(aPoint8, True))
+assert(aPartDoc.index(aFolder3, True) == 3), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3, True))
+
+assert(aFolder3.reference("first_feature").value() is not None)
+assert(aFolder3.reference("last_feature").value() is not None)
+
+#=========================================================================
+# Test 7. Try to remove several points which are not start nor end in a folder
+#=========================================================================
+fromFolder = FeatureList()
+fromFolder.append(aPoint5)
+fromFolder.append(aPoint6)
+
+aSession.startOperation()
+isMovedOut = aPartDoc.removeFromFolder(fromFolder)
+aSession.finishOperation()
+assert(isMovedOut is False)
+
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+assert(aPartDoc.index(aFolder3, True) == 3), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3, True))
+assert(aPartDoc.index(aPoint5, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint5, True))
+assert(aPartDoc.index(aPoint6, True) == -1), "Wrong index of the point: {}".format(aPartDoc.index(aPoint6, True))
+assert(aPartDoc.index(aPoint8, True) == 4), "Wrong index of the point: {}".format(aPartDoc.index(aPoint8, True))
+
+assert(aFolder3.reference("first_feature").value() is not None)
+assert(aFolder3.reference("last_feature").value() is not None)
+
+#=========================================================================
+# Test 8. Remove several points from a folder after it
+#=========================================================================
+fromFolder = FeatureList()
+fromFolder.append(aPoint6)
+fromFolder.append(aPoint7)
+
+aSession.startOperation()
+isMovedOut = aPartDoc.removeFromFolder(fromFolder)
+aSession.finishOperation()
+assert(isMovedOut)
+
+NB_FEATURES_OUT += 2
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+assert(aPartDoc.index(aFolder3, True) == 3), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3, True))
+assert(aPartDoc.index(aPoint6, True) == 4), "Wrong index of the point: {}".format(aPartDoc.index(aPoint6, True))
+assert(aPartDoc.index(aPoint7, True) == 5), "Wrong index of the point: {}".format(aPartDoc.index(aPoint7, True))
+assert(aPartDoc.index(aPoint8, True) == 6), "Wrong index of the point: {}".format(aPartDoc.index(aPoint8, True))
+
+assert(aFolder3.reference("first_feature").value() is not None)
+assert(aFolder3.reference("last_feature").value() is not None)
+
+#=========================================================================
+# Test 9. Remove all remaining points from a folder after it
+#=========================================================================
+fromFolder = FeatureList()
+fromFolder.append(aPoint4)
+fromFolder.append(aPoint5)
+
+aSession.startOperation()
+isMovedOut = aPartDoc.removeFromFolder(fromFolder, False)
+aSession.finishOperation()
+assert(isMovedOut)
+
+NB_FEATURES_OUT += 2
+assert(aPartDoc.size("Features") == NB_FEATURES_FULL), "Wrong number of features: {}, expected: {}".format(aPartDoc.size("Features"), NB_FEATURES_FULL)
+assert(aPartDoc.size("Features", True) == NB_FEATURES_OUT), "Wrong number of features outside a folder: {}, expected: {}".format(aPartDoc.size("Features", True), NB_FEATURES_OUT)
+
+assert(aPartDoc.index(aFolder3, True) == 3), "Wrong index of the folder: {}".format(aPartDoc.index(aFolder3, True))
+assert(aPartDoc.index(aPoint4, True) == 4), "Wrong index of the point: {}".format(aPartDoc.index(aPoint4, True))
+assert(aPartDoc.index(aPoint5, True) == 5), "Wrong index of the point: {}".format(aPartDoc.index(aPoint5, True))
+assert(aPartDoc.index(aPoint6, True) == 6), "Wrong index of the point: {}".format(aPartDoc.index(aPoint6, True))
+assert(aPartDoc.index(aPoint7, True) == 7), "Wrong index of the point: {}".format(aPartDoc.index(aPoint7, True))
+assert(aPartDoc.index(aPoint8, True) == 8), "Wrong index of the point: {}".format(aPartDoc.index(aPoint8, True))
+
+# folder is empty
+assert(aFolder3.reference("first_feature").value() is None)
+assert(aFolder3.reference("last_feature").value() is None)
+# remove empty folder
+aSession.startOperation()
+aPartDoc.removeFolder(aFolder3)
+aSession.finishOperation()
+
+from salome.shaper import model
+assert(model.checkPythonDump())
index f33878dcfc911ac0280a69afbd78c9b747784af4..9c0cfb10c7dabc5f3fe155efa7986b9f92d606f8 100644 (file)
@@ -33,6 +33,7 @@ SET(PROJECT_HEADERS
   ModelHighAPI_Services.h
   ModelHighAPI_Tools.h
   ModelHighAPI_FeatureStore.h
+  ModelHighAPI_Folder.h
 )
 
 SET(PROJECT_SOURCES
@@ -46,6 +47,7 @@ SET(PROJECT_SOURCES
   ModelHighAPI_Services.cpp
   ModelHighAPI_Tools.cpp
   ModelHighAPI_FeatureStore.cpp
+  ModelHighAPI_Folder.cpp
 )
 
 SET(PROJECT_LIBRARIES
index 7010d848143a09e50c63e061a6426e09b2fa5984..0b49cf05c46f9696caef19d8b3a333fd61b969ad 100644 (file)
@@ -57,6 +57,7 @@
 
 // shared pointers
 %shared_ptr(ModelHighAPI_Interface)
+%shared_ptr(ModelHighAPI_Folder)
 
 // typemaps
 
 %include "ModelHighAPI_Dumper.h"
 %include "ModelHighAPI_Integer.h"
 %include "ModelHighAPI_Interface.h"
+%include "ModelHighAPI_Folder.h"
 %include "ModelHighAPI_RefAttr.h"
 %include "ModelHighAPI_Reference.h"
 %include "ModelHighAPI_Selection.h"
index b7211a4c76e21747ceb3fac65e280cb85ce70762..89546d145200f2a34446018bd4e34e5201c14e50 100644 (file)
@@ -46,6 +46,7 @@
 #include <ModelAPI_Document.h>
 #include <ModelAPI_Entity.h>
 #include <ModelAPI_Feature.h>
+#include <ModelAPI_Folder.h>
 #include <ModelAPI_Result.h>
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_ResultCompSolid.h>
@@ -95,6 +96,9 @@ void ModelHighAPI_Dumper::clear(bool bufferOnly)
     myFeatureCount.clear();
     while (!myEntitiesStack.empty())
       myEntitiesStack.pop();
+
+    myPostponed.clear();
+    myDumpPostponedInProgress = false;
   }
 }
 
@@ -124,14 +128,26 @@ const std::string& ModelHighAPI_Dumper::name(const EntityPtr& theEntity,
     return aFound->second.myCurrentName;
 
   // entity is not found, store it
-  std::string aName;
+  std::string aName, aKind;
   bool isDefaultName = false;
+  bool isSaveNotDumped = theSaveNotDumped;
   std::ostringstream aDefaultName;
   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theEntity);
   if (aFeature) {
     aName = aFeature->name();
-    const std::string& aKind = aFeature->getKind();
-    DocumentPtr aDoc = aFeature->document();
+    aKind = aFeature->getKind();
+  } else {
+    FolderPtr aFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(theEntity);
+    if (aFolder) {
+      aName = aFolder->data()->name();
+      aKind = ModelAPI_Folder::ID();
+      isSaveNotDumped = false;
+    }
+  }
+
+  ObjectPtr anObject = std::dynamic_pointer_cast<ModelAPI_Object>(theEntity);
+  if (anObject) {
+    DocumentPtr aDoc = anObject->document();
     int& aNbFeatures = myFeatureCount[aDoc][aKind];
     aNbFeatures += 1;
 
@@ -164,7 +180,7 @@ const std::string& ModelHighAPI_Dumper::name(const EntityPtr& theEntity,
   }
 
   myNames[theEntity] = EntityName(aDefaultName.str(), aName, isDefaultName);
-  if (theSaveNotDumped)
+  if (isSaveNotDumped)
     myNotDumpedEntities.insert(theEntity);
 
   // store names of results
@@ -198,7 +214,8 @@ void ModelHighAPI_Dumper::saveResultNames(const FeaturePtr& theFeature)
   const std::list<ResultPtr>& aResults = theFeature->results();
   std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
   for (int i = 0; aResIt != aResults.end(); ++aResIt, ++i) {
-    std::string aDefaultName = ModelAPI_Tools::getDefaultName(*aResIt, i);
+    std::pair<std::string, bool> aName = ModelAPI_Tools::getDefaultName(*aResIt, i);
+    std::string aDefaultName = aName.first;
     std::string aResName = (*aResIt)->data()->name();
 
     bool isUserDefined = !(isFeatureDefaultName && aDefaultName == aResName);
@@ -213,7 +230,8 @@ void ModelHighAPI_Dumper::saveResultNames(const FeaturePtr& theFeature)
       for (int j = 0; j < aNbSubs; ++j) {
         ResultPtr aSub = aCompSolid->subResult(j);
         std::string aSubName = aSub->data()->name();
-        aDefaultName = ModelAPI_Tools::getDefaultName(aSub, j);
+        aName = ModelAPI_Tools::getDefaultName(aSub, j);
+        aDefaultName = aName.first;
 
         bool isUserDefinedSubName = isUserDefined || aDefaultName != aSubName;
         myNames[aSub] = EntityName(aSubName,
@@ -238,19 +256,33 @@ bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_Document>& theD
 bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_Document>& theDoc)
 {
   bool isOk = true;
-  std::list<FeaturePtr> aFeatures = theDoc->allFeatures();
-  std::list<FeaturePtr>::const_iterator aFeatIt = aFeatures.begin();
+  std::list<ObjectPtr> anObjects = theDoc->allObjects();
+  std::list<ObjectPtr>::const_iterator anObjIt = anObjects.begin();
   // firstly, dump all parameters
-  for (; aFeatIt != aFeatures.end(); ++ aFeatIt)
-    dumpParameter(*aFeatIt);
+  for (; anObjIt != anObjects.end(); ++ anObjIt) {
+    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anObjIt);
+    if (aFeature)
+      dumpParameter(aFeature);
+  }
   // dump all other features
-  for (aFeatIt = aFeatures.begin(); aFeatIt != aFeatures.end(); ++aFeatIt) {
-    CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aFeatIt);
+  for (anObjIt = anObjects.begin(); anObjIt != anObjects.end(); ++anObjIt) {
+    CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*anObjIt);
     if (aCompFeat) // iteratively process composite features
       isOk = process(aCompFeat) && isOk;
-    else if (!isDumped(*aFeatIt)) // dump common feature
-      dumpFeature(*aFeatIt);
+    else if (!isDumped(EntityPtr(*anObjIt))) {
+      // dump folder
+      FolderPtr aFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(*anObjIt);
+      if (aFolder)
+        dumpFolder(aFolder);
+      else {
+        FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anObjIt);
+        if (aFeature) // dump common feature
+          dumpFeature(aFeature);
+      }
+    }
   }
+  // dump folders if any
+  dumpPostponed(true);
   return isOk;
 }
 
@@ -260,7 +292,7 @@ bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_CompositeFeatur
   // increase composite features stack
   ++gCompositeStackDepth;
   // dump composite itself
-  if (!isDumped(theComposite) || isForce)
+  if (!isDumped(EntityPtr(theComposite)) || isForce)
     dumpFeature(FeaturePtr(theComposite), isForce);
 
   // sub-part is processed independently, because it provides separate document
@@ -297,6 +329,8 @@ bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_CompositeFeatur
   // decrease composite features stack
   --gCompositeStackDepth;
 
+  // dump folders if any
+  dumpPostponed(true);
   return isOk;
 }
 
@@ -310,7 +344,7 @@ bool ModelHighAPI_Dumper::processSubs(
   int aNbSubs = theComposite->numberOfSubs();
   for (int anIndex = 0; anIndex < aNbSubs; ++anIndex) {
     FeaturePtr aFeature = theComposite->subFeature(anIndex);
-    if (isDumped(aFeature))
+    if (isDumped(EntityPtr(aFeature)))
       continue;
 
     isSubDumped = true;
@@ -335,9 +369,48 @@ bool ModelHighAPI_Dumper::processSubs(
   // dump "setName" for composite feature
   if (isDumpSetName)
     dumpEntitySetName();
+  // dump folders if any
+  dumpPostponed(true);
   return isOk;
 }
 
+void ModelHighAPI_Dumper::postpone(const EntityPtr& theEntity)
+{
+  // keep the name
+  name(theEntity, false);
+  myPostponed.push_back(theEntity);
+}
+
+void ModelHighAPI_Dumper::dumpPostponed(bool theDumpFolders)
+{
+  if (myDumpPostponedInProgress)
+    return;
+
+  myDumpPostponedInProgress = true;
+  // make a copy of postponed entities, because the list will be updated
+  // if some features are not able to be dumped
+  std::list<EntityPtr> aPostponedCopy = myPostponed;
+  myPostponed.clear();
+
+  // iterate over postponed entities and try to dump them
+  std::list<EntityPtr>::const_iterator anIt = aPostponedCopy.begin();
+  for (; anIt != aPostponedCopy.end(); ++anIt) {
+    FolderPtr aFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(*anIt);
+    if (aFolder) {
+      if (theDumpFolders)
+        dumpFolder(aFolder);
+      else
+        myPostponed.push_back(*anIt);
+    }
+    else {
+      FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anIt);
+      if (aFeature)
+        dumpFeature(aFeature);
+    }
+  }
+  myDumpPostponedInProgress = false;
+}
+
 void ModelHighAPI_Dumper::dumpSubFeatureNameAndColor(const std::string theSubFeatureGet,
                                                      const FeaturePtr& theSubFeature)
 {
@@ -472,7 +545,30 @@ bool ModelHighAPI_Dumper::isDumped(const EntityPtr& theEntity) const
 {
   EntityNameMap::const_iterator aFound = myNames.find(theEntity);
   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theEntity);
-  return aFound != myNames.end() || myFeaturesToSkip.find(aFeature) != myFeaturesToSkip.end();
+  return (aFound != myNames.end() && aFound->second.myIsDumped) ||
+         myFeaturesToSkip.find(aFeature) != myFeaturesToSkip.end();
+}
+
+bool ModelHighAPI_Dumper::isDumped(const AttributeRefAttrPtr& theRefAttr) const
+{
+  FeaturePtr aFeature;
+  if (theRefAttr->isObject())
+    aFeature = ModelAPI_Feature::feature(theRefAttr->object());
+  else
+    aFeature = ModelAPI_Feature::feature(theRefAttr->attr()->owner());
+  return aFeature && isDumped(EntityPtr(aFeature));
+}
+
+bool ModelHighAPI_Dumper::isDumped(const AttributeRefListPtr& theRefList) const
+{
+  std::list<ObjectPtr> aRefs = theRefList->list();
+  std::list<ObjectPtr>::iterator anIt = aRefs.begin();
+  for (; anIt != aRefs.end(); ++anIt) {
+    FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
+    if (aFeature && !isDumped(EntityPtr(aFeature)))
+      return false;
+  }
+  return true;
 }
 
 bool ModelHighAPI_Dumper::isDefaultColor(const ResultPtr& theResult) const
@@ -659,6 +755,12 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
   return *this;
 }
 
+ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const FolderPtr& theFolder)
+{
+  myDumpBuffer << name(theFolder);
+  return *this;
+}
+
 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const FeaturePtr& theEntity)
 {
   myDumpBuffer << name(theEntity);
@@ -873,36 +975,56 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
     const std::shared_ptr<ModelAPI_AttributeSelectionList>& theAttrSelList)
 {
-  myDumpBuffer << "[";
+  static const int aThreshold = 2;
+  // if number of elements in the list if greater than a threshold,
+  // dump it in a separate line with specific name
+  std::string aDumped = myDumpBuffer.str();
 
-  GeomShapePtr aShape;
-  std::string aShapeTypeStr;
+  if (aDumped.empty() || theAttrSelList->size() <= aThreshold) {
+    myDumpBuffer << "[";
 
-  bool isAdded = false;
+    GeomShapePtr aShape;
+    std::string aShapeTypeStr;
 
-  for(int anIndex = 0; anIndex < theAttrSelList->size(); ++anIndex) {
-    AttributeSelectionPtr anAttribute = theAttrSelList->value(anIndex);
-    aShape = anAttribute->value();
-    if(!aShape.get()) {
-      ResultPtr aContext = anAttribute->context();
-      if (aContext.get())
-        aShape = aContext->shape();
-    }
+    bool isAdded = false;
 
-    if(!aShape.get()) {
-      continue;
-    }
+    for(int anIndex = 0; anIndex < theAttrSelList->size(); ++anIndex) {
+      AttributeSelectionPtr anAttribute = theAttrSelList->value(anIndex);
+      aShape = anAttribute->value();
+      if(!aShape.get()) {
+        ResultPtr aContext = anAttribute->context();
+        if (aContext.get())
+          aShape = aContext->shape();
+      }
 
-    if(isAdded) {
-      myDumpBuffer << ", ";
-    } else {
-      isAdded = true;
+      if(!aShape.get()) {
+        continue;
+      }
+
+      if(isAdded) {
+        myDumpBuffer << ", ";
+      } else {
+        isAdded = true;
+      }
+      myDumpBuffer << "model.selection(\"" <<
+        aShape->shapeTypeStr() << "\", \"" << anAttribute->namingName() << "\")";
     }
-    myDumpBuffer << "model.selection(\"" <<
-      aShape->shapeTypeStr() << "\", \"" << anAttribute->namingName() << "\")";
-  }
 
-  myDumpBuffer << "]";
+    myDumpBuffer << "]";
+  } else {
+    // clear buffer and store list "as is"
+    myDumpBuffer.str("");
+    *this << theAttrSelList;
+    // save buffer and clear it again
+    std::string aDumpedList = myDumpBuffer.str();
+    myDumpBuffer.str("");
+    // obtain name of list
+    FeaturePtr anOwner = ModelAPI_Feature::feature(theAttrSelList->owner());
+    std::string aListName = name(anOwner) + "_objects";
+    // store all previous data
+    myDumpBuffer << aListName << " = " << aDumpedList << std::endl
+                 << aDumped << aListName;
+  }
   return *this;
 }
 
@@ -945,7 +1067,7 @@ ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper,
           isCopy = aCopyAttr.get() && aCopyAttr->value();
         }
       }
-    } while (isCopy);
+    } while (isCopy && !theDumper.myEntitiesStack.empty());
   }
 
   // store all not-dumped entities first
@@ -972,7 +1094,7 @@ ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper,
           if ((*aRefIt)->id() == "ProjectedFeature")
           { // process projection only
             FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
-            if (anOwner && !theDumper.isDumped(anOwner))
+            if (anOwner && !theDumper.isDumped(EntityPtr(anOwner)))
               theDumper.dumpFeature(anOwner, true);
           }
       }
@@ -986,5 +1108,8 @@ ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper,
   // then store currently dumped string
   theDumper.myFullDump << aBufCopy;
 
+  // now, store all postponed features
+  theDumper.dumpPostponed();
+
   return theDumper;
 }
index c2fe0cd54de1bb6734d24f182989a7007e7ac565..c034cf3011e4635ac44b2abe54ce1cac3892c2af 100644 (file)
@@ -54,12 +54,14 @@ class ModelAPI_CompositeFeature;
 class ModelAPI_Document;
 class ModelAPI_Entity;
 class ModelAPI_Feature;
+class ModelAPI_Folder;
 class ModelAPI_Object;
 class ModelAPI_Result;
 
 typedef std::shared_ptr<ModelAPI_Document> DocumentPtr;
 typedef std::shared_ptr<ModelAPI_Entity>   EntityPtr;
 typedef std::shared_ptr<ModelAPI_Feature>  FeaturePtr;
+typedef std::shared_ptr<ModelAPI_Folder>   FolderPtr;
 typedef std::shared_ptr<ModelAPI_Result>   ResultPtr;
 
 /**\class ModelHighAPI_Dumper
@@ -116,6 +118,13 @@ public:
   virtual void dumpParameter(const FeaturePtr& theFeature) = 0;
   /// Dump given feature
   virtual void dumpFeature(const FeaturePtr& theFeature, const bool theForce = false) = 0;
+  /// Dump folder
+  virtual void dumpFolder(const FolderPtr& theFolder) = 0;
+
+  /// Set feature postponed until all its dependencies are not dumped.
+  /// The name of the feature is stored anyway.
+  MODELHIGHAPI_EXPORT
+  void postpone(const EntityPtr& theEntity);
 
   /// Set a feature that should not be dumped anyway
   MODELHIGHAPI_EXPORT
@@ -203,6 +212,10 @@ public:
   MODELHIGHAPI_EXPORT
   ModelHighAPI_Dumper& operator<<(const FeaturePtr& theEntity);
 
+  /// Dump folder
+  MODELHIGHAPI_EXPORT
+  ModelHighAPI_Dumper& operator<<(const FolderPtr& theFolder);
+
   /// Dump result
   MODELHIGHAPI_EXPORT
   ModelHighAPI_Dumper& operator<<(const ResultPtr& theResult);
@@ -244,6 +257,16 @@ public:
   /// clear list of not dumped entities
   MODELHIGHAPI_EXPORT void clearNotDumped();
 
+  /// Check the entity is already dumped
+  MODELHIGHAPI_EXPORT
+  bool isDumped(const EntityPtr& theEntity) const;
+  /// Check theRefAttr is already dumped
+  MODELHIGHAPI_EXPORT
+  bool isDumped(const std::shared_ptr<ModelAPI_AttributeRefAttr>& theRefAttr) const;
+  /// Check all objects in theRefList are already dumped
+  MODELHIGHAPI_EXPORT
+  bool isDumped(const std::shared_ptr<ModelAPI_AttributeRefList>& theRefList) const;
+
 protected:
   /// Dump "setName" command if last entity had user-defined name
   MODELHIGHAPI_EXPORT void dumpEntitySetName();
@@ -266,9 +289,6 @@ private:
   bool processSubs(const std::shared_ptr<ModelAPI_CompositeFeature>& theComposite,
                    bool theDumpModelDo = false);
 
-  /// Check the entity is already dumped
-  bool isDumped(const EntityPtr& theEntity) const;
-
   /// Stores names of results for the given feature
   void saveResultNames(const FeaturePtr& theFeature);
 
@@ -281,6 +301,9 @@ private:
   /// Check the result feature has default transparency
   bool isDefaultTransparency(const ResultPtr& theResult) const;
 
+  /// Dump postponed entities
+  void dumpPostponed(bool theDumpFolders = false);
+
 private:
   struct EntityName {
     std::string myCurrentName; ///< default name of current feature
@@ -329,11 +352,15 @@ private:
   /// features which should not be dumped (like coincidence and tangency created by tangent arc)
   std::set<FeaturePtr> myFeaturesToSkip;
 
+  std::list<EntityPtr> myPostponed; ///< list of postponed entities (sketch constraints or folders)
+  bool myDumpPostponedInProgress; ///< processing postponed is in progress
+
 protected:
-   /// list of entities, used by other features but not dumped yet
+  /// list of entities, used by other features but not dumped yet
   std::set<EntityPtr> myNotDumpedEntities;
 
   friend class SketchAPI_Sketch;
+  friend class ModelHighAPI_Folder;
 };
 
 #endif
index 97f65b4777012ade15dbb4499fd0e116e2667b39..995cb344f47ea8d4cd6c9fef688a929d0ac63bec 100644 (file)
 #define PRECISION 6
 #define TOLERANCE (1.e-7)
 
-ModelHighAPI_FeatureStore::ModelHighAPI_FeatureStore(FeaturePtr theFeature) {
-  storeData(theFeature->data(), myAttrs);
-  // iterate results to store
-  std::list<ResultPtr> allResults;
-  ModelAPI_Tools::allResults(theFeature, allResults);
-  std::list<ResultPtr>::iterator aRes = allResults.begin();
-  for(; aRes != allResults.end(); aRes++) {
-    std::map<std::string, std::string> aResDump;
-    storeData((*aRes)->data(), aResDump);
-    myRes.push_back(aResDump);
+ModelHighAPI_FeatureStore::ModelHighAPI_FeatureStore(ObjectPtr theObject) {
+  storeData(theObject->data(), myAttrs);
+
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
+  if (aFeature) {
+    // iterate results to store
+    std::list<ResultPtr> allResults;
+    ModelAPI_Tools::allResults(aFeature, allResults);
+    std::list<ResultPtr>::iterator aRes = allResults.begin();
+    for(; aRes != allResults.end(); aRes++) {
+      std::map<std::string, std::string> aResDump;
+      storeData((*aRes)->data(), aResDump);
+      myRes.push_back(aResDump);
+    }
   }
 }
 
-std::string ModelHighAPI_FeatureStore::compare(FeaturePtr theFeature) {
-  std::string anError = compareData(theFeature->data(), myAttrs);
+std::string ModelHighAPI_FeatureStore::compare(ObjectPtr theObject) {
+  std::string anError = compareData(theObject->data(), myAttrs);
   if (!anError.empty()) {
-    return "Features '" + theFeature->name() + "' differ:" + anError;
-  }
-  std::list<ResultPtr> allResults;
-  ModelAPI_Tools::allResults(theFeature, allResults);
-  std::list<ResultPtr>::iterator aRes = allResults.begin();
-  std::list<std::map<std::string, std::string> >::iterator aResIter = myRes.begin();
-  for(; aRes != allResults.end() && aResIter != myRes.end(); aRes++, aResIter++) {
-    anError = compareData((*aRes)->data(), *aResIter);
-    if (!anError.empty())
-      return "Results of feature '" + theFeature->name() + "' '" + (*aRes)->data()->name() +
-      "' differ:" + anError;
-  }
-  if (aRes != allResults.end()) {
-    return "Current model has more results '" + (*aRes)->data()->name() + "'";
+    return "Features '" + theObject->data()->name() + "' differ:" + anError;
   }
-  if (aResIter != myRes.end()) {
-    return "Original model had more results '" + (*aResIter)["__name__"] + "'";
+
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
+  if (aFeature) {
+    std::list<ResultPtr> allResults;
+    ModelAPI_Tools::allResults(aFeature, allResults);
+    std::list<ResultPtr>::iterator aRes = allResults.begin();
+    std::list<std::map<std::string, std::string> >::iterator aResIter = myRes.begin();
+    for(; aRes != allResults.end() && aResIter != myRes.end(); aRes++, aResIter++) {
+      anError = compareData((*aRes)->data(), *aResIter);
+      if (!anError.empty())
+        return "Results of feature '" + aFeature->name() + "' '" + (*aRes)->data()->name() +
+        "' differ:" + anError;
+    }
+    if (aRes != allResults.end()) {
+      return "Current model has more results '" + (*aRes)->data()->name() + "'";
+    }
+    if (aResIter != myRes.end()) {
+      return "Original model had more results '" + (*aResIter)["__name__"] + "'";
+    }
   }
   return ""; // ok
 }
index 7970b179984db722d38c75effb7ce89f7edd3d6d..32bea8a3bcb5553f6bb49913ad5de3f190f82311 100644 (file)
 #include <string>
 #include <memory>
 
-class ModelAPI_Feature;
+class ModelAPI_Object;
 class ModelAPI_Data;
 class GeomAPI_Shape;
 class ModelAPI_Attribute;
 
-typedef std::shared_ptr<ModelAPI_Feature>  FeaturePtr;
-typedef std::shared_ptr<ModelAPI_Attribute>  AttributePtr;
+typedef std::shared_ptr<ModelAPI_Object>    ObjectPtr;
+typedef std::shared_ptr<ModelAPI_Attribute> AttributePtr;
 
 /**\class ModelHighAPI_FeatureStore
  * \ingroup CPPHighAPI
@@ -49,9 +49,9 @@ public:
   // unused constructor for the map container needs
   ModelHighAPI_FeatureStore() {}
   // constructor that initializes this object by feature to store
-  ModelHighAPI_FeatureStore(FeaturePtr theFeature);
+  ModelHighAPI_FeatureStore(ObjectPtr theObject);
   // compares the stored feature information with the given feature
-  std::string compare(FeaturePtr theFeature);
+  std::string compare(ObjectPtr theObject);
 
 private:
   /// stores the information about all attributes of data in map
diff --git a/src/ModelHighAPI/ModelHighAPI_Folder.cpp b/src/ModelHighAPI/ModelHighAPI_Folder.cpp
new file mode 100644 (file)
index 0000000..ef62474
--- /dev/null
@@ -0,0 +1,103 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "ModelHighAPI_Folder.h"
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Reference.h>
+#include <ModelHighAPI_Tools.h>
+
+#include <ModelAPI_AttributeReference.h>
+#include <ModelAPI_Document.h>
+
+//--------------------------------------------------------------------------------------
+
+ModelHighAPI_Folder::ModelHighAPI_Folder(const std::shared_ptr<ModelAPI_Folder> & theFolder)
+  : ModelHighAPI_Interface(FeaturePtr()),
+    myFolder(theFolder)
+{
+  initialize();
+}
+
+ModelHighAPI_Folder::~ModelHighAPI_Folder()
+{
+}
+
+bool ModelHighAPI_Folder::initialize()
+{
+  if (!myFolder) {
+    throwException(ID() + " exception: The folder is NULL.");
+    return false;
+  }
+
+  myFirstFeature = myFolder->reference(ModelAPI_Folder::FIRST_FEATURE_ID());
+  if (!myFirstFeature)
+    return false;
+  myAttrGetter[ModelAPI_Folder::FIRST_FEATURE_ID()] = "firstFeature";
+
+  myLastFeature = myFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID());
+  if (!myLastFeature)
+    return false;
+  myAttrGetter[ModelAPI_Folder::LAST_FEATURE_ID()] = "lastFeature";
+
+  return true;
+}
+
+void ModelHighAPI_Folder::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  const std::string& aDocName = theDumper.name(myFolder->document());
+
+  AttributeReferencePtr aStartRef = myFolder->reference(ModelAPI_Folder::FIRST_FEATURE_ID());
+  AttributeReferencePtr aEndRef   = myFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID());
+
+  // do not dump empty folders
+  if (!aEndRef->value())
+    return;
+
+  // Dump folder when its features have been already dumped.
+  // Otherwise, store the folder postponed.
+  if (theDumper.isDumped(EntityPtr(aEndRef->value())))
+    theDumper << myFolder << " = model.addFolder(" << aDocName << ", "
+              << aStartRef << ", " << aEndRef << ")" << std::endl;
+  else
+    theDumper.postpone(myFolder);
+}
+
+//--------------------------------------------------------------------------------------
+
+std::shared_ptr<ModelHighAPI_Folder> addFolder(const std::shared_ptr<ModelAPI_Document>& theDoc)
+{
+  std::shared_ptr<ModelAPI_Folder> aFolder = theDoc->addFolder();
+  return std::shared_ptr<ModelHighAPI_Folder>(new ModelHighAPI_Folder(aFolder));
+}
+
+std::shared_ptr<ModelHighAPI_Folder> addFolder(const std::shared_ptr<ModelAPI_Document>& theDoc,
+                                               const ModelHighAPI_Reference& theFirstFeature,
+                                               const ModelHighAPI_Reference& theLastFeature)
+{
+  std::shared_ptr<ModelAPI_Folder> aFolder = theDoc->addFolder(theFirstFeature.feature());
+
+  AttributeReferencePtr aFirstFeatAttr = aFolder->reference(ModelAPI_Folder::FIRST_FEATURE_ID());
+  fillAttribute(theFirstFeature.feature(), aFirstFeatAttr);
+
+  AttributeReferencePtr aLastFeatAttr = aFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID());
+  fillAttribute(theLastFeature.feature(), aLastFeatAttr);
+
+  return std::shared_ptr<ModelHighAPI_Folder>(new ModelHighAPI_Folder(aFolder));
+}
diff --git a/src/ModelHighAPI/ModelHighAPI_Folder.h b/src/ModelHighAPI/ModelHighAPI_Folder.h
new file mode 100644 (file)
index 0000000..8128df0
--- /dev/null
@@ -0,0 +1,87 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef SRC_MODELHIGHAPI_MODELHIGHAPI_FOLDER_H_
+#define SRC_MODELHIGHAPI_MODELHIGHAPI_FOLDER_H_
+
+//--------------------------------------------------------------------------------------
+#include <ModelHighAPI_Interface.h>
+
+#include <ModelAPI_Folder.h>
+
+#include <memory>
+//--------------------------------------------------------------------------------------
+class ModelAPI_AttributeReference;
+class ModelAPI_Document;
+class ModelHighAPI_Reference;
+//--------------------------------------------------------------------------------------
+/**\class ModelHighAPI_Folder
+ * \ingroup CPPHighAPI
+ * \brief Class for filling ModelAPI_Folder
+ */
+class ModelHighAPI_Folder : public ModelHighAPI_Interface
+{
+public:
+  /// Constructor for a folder
+  MODELHIGHAPI_EXPORT
+  explicit ModelHighAPI_Folder(const std::shared_ptr<ModelAPI_Folder>& theFolder);
+  /// Destructor
+  MODELHIGHAPI_EXPORT virtual ~ModelHighAPI_Folder();
+
+  static std::string ID() { return ModelAPI_Folder::ID(); }
+  virtual std::string getID() { return ID(); }
+
+  /// First feature reference
+  std::shared_ptr<ModelAPI_AttributeReference> firstFeature() const
+  { return myFirstFeature; }
+
+  /// Last feature reference
+  std::shared_ptr<ModelAPI_AttributeReference> lastFeature() const
+  { return myLastFeature; }
+
+  /// Dump wrapped feature
+  MODELHIGHAPI_EXPORT virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+
+protected:
+  bool initialize();
+
+private:
+  std::shared_ptr<ModelAPI_Folder> myFolder;
+
+  std::shared_ptr<ModelAPI_AttributeReference> myFirstFeature;
+  std::shared_ptr<ModelAPI_AttributeReference> myLastFeature;
+};
+
+//--------------------------------------------------------------------------------------
+/**\ingroup CPPHighAPI
+ * \brief Create empty Folder feature
+ */
+MODELHIGHAPI_EXPORT
+std::shared_ptr<ModelHighAPI_Folder> addFolder(const std::shared_ptr<ModelAPI_Document>& theDoc);
+
+/**\ingroup CPPHighAPI
+ * \brief Create Folder feature
+ */
+MODELHIGHAPI_EXPORT
+std::shared_ptr<ModelHighAPI_Folder> addFolder(const std::shared_ptr<ModelAPI_Document>& theDoc,
+                                               const ModelHighAPI_Reference& theFirstFeature,
+                                               const ModelHighAPI_Reference& theLastFeature);
+//--------------------------------------------------------------------------------------
+#endif /* SRC_MODELHIGHAPI_MODELHIGHAPI_FOLDER_H_ */
index d03130b59b2f0b01c2b934f22457d97eb10ea545..b8415681e9ae09efc9b040f3be52023a74e8b32c 100644 (file)
@@ -338,47 +338,54 @@ std::string storeFeatures(const std::string& theDocName, DocumentPtr theDoc,
      }
   }
   // store the model features information: iterate all features
-  int aFeaturesCount = 0; // stores the number of compared features for this document to compate
+  int anObjectsCount = 0; // stores the number of compared features for this document to compate
   std::set<std::string> aProcessed; // processed features names (that are in the current document)
-  std::list<FeaturePtr> allFeatures = theDoc->allFeatures();
-  std::list<FeaturePtr>::iterator allIter = allFeatures.begin();
-  for(; allIter != allFeatures.end(); allIter++) {
-    FeaturePtr aFeat = *allIter;
+
+  // process all objects (features and folders)
+  std::list<ObjectPtr> allObjects = theDoc->allObjects();
+  std::list<ObjectPtr>::iterator allIter = allObjects.begin();
+  for(; allIter != allObjects.end(); allIter++) {
+    ObjectPtr anObject = *allIter;
     if (theCompare) {
       std::map<std::string, ModelHighAPI_FeatureStore>::iterator
-        aFeatFind = aDocFind->second.find(aFeat->name());
-      if (aFeatFind == aDocFind->second.end()) {
-        return "Document '" + theDocName + "' feature '" + aFeat->name() + "' not found";
+        anObjFind = aDocFind->second.find(anObject->data()->name());
+      if (anObjFind == aDocFind->second.end()) {
+        return "Document '" + theDocName + "' feature '" + anObject->data()->name() + "' not found";
       }
-      std::string anError = aFeatFind->second.compare(aFeat);
+      std::string anError = anObjFind->second.compare(anObject);
       if (!anError.empty()) {
         anError = "Document " + theDocName + " " + anError;
         return anError;
       }
-      aFeaturesCount++;
-      aProcessed.insert(aFeat->name());
+      anObjectsCount++;
+      aProcessed.insert(anObject->data()->name());
     } else {
-      theStore[theDocName][aFeat->name()] = ModelHighAPI_FeatureStore(aFeat);
+      theStore[theDocName][anObject->data()->name()] = ModelHighAPI_FeatureStore(anObject);
     }
-    // iterate all results of this feature
-    std::list<ResultPtr> allResults;
-    ModelAPI_Tools::allResults(aFeat, allResults);
-    std::list<ResultPtr>::iterator aRes = allResults.begin();
-    for(; aRes != allResults.end(); aRes++) {
-      // recoursively store features of sub-documents
-      if ((*aRes)->groupName() == ModelAPI_ResultPart::group()) {
-        DocumentPtr aDoc = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aRes)->partDoc();
-        if (aDoc.get()) {
-          std::string anError = storeFeatures((*aRes)->data()->name(), aDoc, theStore, theCompare);
-          if (!anError.empty())
-            return anError;
+
+    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
+    if (aFeature) {
+      // iterate all results of this feature
+      std::list<ResultPtr> allResults;
+      ModelAPI_Tools::allResults(aFeature, allResults);
+      std::list<ResultPtr>::iterator aRes = allResults.begin();
+      for(; aRes != allResults.end(); aRes++) {
+        // recoursively store features of sub-documents
+        if ((*aRes)->groupName() == ModelAPI_ResultPart::group()) {
+          DocumentPtr aDoc = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aRes)->partDoc();
+          if (aDoc.get()) {
+            std::string anError =
+                storeFeatures((*aRes)->data()->name(), aDoc, theStore, theCompare);
+            if (!anError.empty())
+              return anError;
+          }
         }
       }
     }
   }
   // checks the number of compared features
   if (theCompare) {
-    if (aDocFind->second.size() != aFeaturesCount) {
+    if (aDocFind->second.size() != anObjectsCount) {
       // search for disappeared feature
       std::string aLostName;
       std::map<std::string, ModelHighAPI_FeatureStore>::iterator aLostIter;
index 4a0bf71da8fb2f312f8107b8bcea6aeb054911fb..fb7b26c8fda35d6e85f860929692cdbf2cd54cf9 100644 (file)
@@ -28,6 +28,7 @@
   #include "ModelHighAPI.h"
   #include "ModelHighAPI_Double.h"
   #include "ModelHighAPI_Dumper.h"
+  #include "ModelHighAPI_Folder.h"
   #include "ModelHighAPI_Integer.h"
   #include "ModelHighAPI_Interface.h"
   #include "ModelHighAPI_Macro.h"
index a849fa00f9409e444d6683f3df9fa21a46a274f9..3e8fc7d4bce53a2b352f7f47d45bad5943ca46d8 100644 (file)
@@ -33,6 +33,7 @@ SET(PROJECT_HEADERS
   ModuleBase.h
   ModuleBase_ActionInfo.h
   ModuleBase_ActionType.h
+  ModuleBase_BRepOwner.h
   ModuleBase_Definitions.h
   ModuleBase_DoubleSpinBox.h
   ModuleBase_Events.h
@@ -44,11 +45,13 @@ SET(PROJECT_HEADERS
   ModuleBase_IPrefMgr.h
   ModuleBase_IPropertyPanel.h
   ModuleBase_ISelection.h
+  ModuleBase_ISelectionActivate.h
   ModuleBase_IViewWindow.h
   ModuleBase_IViewer.h
   ModuleBase_IWidgetCreator.h
   ModuleBase_IWorkshop.h
   ModuleBase_LabelValue.h
+  ModuleBase_ListView.h
   ModuleBase_ModelWidget.h
   ModuleBase_Operation.h
   ModuleBase_OperationAction.h
@@ -94,6 +97,8 @@ SET(PROJECT_HEADERS
   ModuleBase_IconFactory.h
   ModuleBase_Dialog.h
   ModuleBase_ModelDialogWidget.h
+  ModuleBase_ActionParameter.h
+  ModuleBase_ActionIntParameter.h
   ModuleBase_ChoiceCtrl.h
   ModuleBase_WidgetNameEdit.h
 )
@@ -108,6 +113,7 @@ SET(PROJECT_MOC_HEADERS
   ModuleBase_IViewer.h
   ModuleBase_IWorkshop.h
   ModuleBase_LabelValue.h
+  ModuleBase_ListView.h
   ModuleBase_ModelDialogWidget.h
   ModuleBase_ModelWidget.h
   ModuleBase_Operation.h
@@ -146,6 +152,7 @@ SET(PROJECT_MOC_HEADERS
 
 SET(PROJECT_SOURCES
   ModuleBase_ActionInfo.cpp
+  ModuleBase_BRepOwner.cpp
   ModuleBase_DoubleSpinBox.cpp
   ModuleBase_Filter.cpp
   ModuleBase_FilterValidated.cpp
@@ -160,6 +167,7 @@ SET(PROJECT_SOURCES
   ModuleBase_IWidgetCreator.cpp
   ModuleBase_IWorkshop.cpp
   ModuleBase_LabelValue.cpp
+  ModuleBase_ListView.cpp
   ModuleBase_ModelWidget.cpp
   ModuleBase_Operation.cpp
   ModuleBase_OperationAction.cpp
diff --git a/src/ModuleBase/ModuleBase_ActionIntParameter.h b/src/ModuleBase/ModuleBase_ActionIntParameter.h
new file mode 100644 (file)
index 0000000..a49b909
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef ModuleBase_ActionIntParameter_H_
+#define ModuleBase_ActionIntParameter_H_
+
+#include "ModuleBase_ActionParameter.h"
+
+class ModuleBase_ActionIntParameter : public ModuleBase_ActionParameter
+{
+public:
+  ModuleBase_ActionIntParameter(int theVal):ModuleBase_ActionParameter(), myVal(theVal) {}
+
+  int value() const { return myVal; }
+
+private:
+  int myVal;
+};
+
+typedef std::shared_ptr<ModuleBase_ActionIntParameter> ActionIntParamPtr;
+
+#endif
\ No newline at end of file
diff --git a/src/ModuleBase/ModuleBase_ActionParameter.h b/src/ModuleBase/ModuleBase_ActionParameter.h
new file mode 100644 (file)
index 0000000..d24e6e1
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef ModuleBase_ActionParameter_H_
+#define ModuleBase_ActionParameter_H_
+
+#include <memory>
+
+class ModuleBase_ActionParameter
+{
+public:
+  /// Destuctor is added in order to virtualize the class
+  virtual ~ModuleBase_ActionParameter() {}
+};
+
+typedef std::shared_ptr<ModuleBase_ActionParameter> ActionParamPtr;
+
+#endif
\ No newline at end of file
index 864c5e64acb38314756689195ca504aaddc7ec63..5a12e0efd232b2ee738200a0dac93bfa9cbad38c 100644 (file)
 #ifndef ModuleBase_ActionType_H_
 #define ModuleBase_ActionType_H_
 
-#include <ModuleBase.h>
-
 /*!
  * Structure to describe widget processed types of actions.
  */
-enum MODULEBASE_EXPORT ModuleBase_ActionType
+enum ModuleBase_ActionType
 {
   ActionEnter,
   ActionEscape,
   ActionDelete,
+  ActionSelection,
   ActionUndo,
   ActionRedo
 };
diff --git a/src/ModuleBase/ModuleBase_BRepOwner.cpp b/src/ModuleBase/ModuleBase_BRepOwner.cpp
new file mode 100644 (file)
index 0000000..1c13dcf
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "ModuleBase_BRepOwner.h"
+
+IMPLEMENT_STANDARD_RTTIEXT(ModuleBase_BRepOwner, StdSelect_BRepOwner);
diff --git a/src/ModuleBase/ModuleBase_BRepOwner.h b/src/ModuleBase/ModuleBase_BRepOwner.h
new file mode 100644 (file)
index 0000000..b0dade4
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef ModuleBase_BRepOwner_H
+#define ModuleBase_BRepOwner_H
+
+#include "ModuleBase.h"
+
+#include <Standard_DefineHandle.hxx>
+#include <StdSelect_BRepOwner.hxx>
+
+#include <QMap>
+
+DEFINE_STANDARD_HANDLE(ModuleBase_BRepOwner, StdSelect_BRepOwner)
+
+/**
+* \ingroup GUI
+* A redefinition of standard BRep Owner in order to provide specific selection
+* of CompSolid objects. This owner is created only for selection mode TopAbs_COMPSOLID
+*/
+class ModuleBase_BRepOwner: public StdSelect_BRepOwner
+{
+public:
+  /// Constructor
+  /// \param aShape an owner shape
+  /// \param aPriority drawig priority
+  /// \param ComesFromDecomposition decomposition flag
+  ModuleBase_BRepOwner(const TopoDS_Shape& aShape,
+    const Standard_Integer aPriority = 0,
+    const Standard_Boolean ComesFromDecomposition = Standard_False)
+    : StdSelect_BRepOwner(aShape, aPriority, ComesFromDecomposition) {}
+
+  /// Highlight the presentation with the given color
+  /// \param aPM a presentations manager
+  /// \param theStyle a style of presentation
+  /// \param theMode a drawing mode
+  virtual void HilightWithColor (const Handle(PrsMgr_PresentationManager3d)& aPM,
+    const Handle(Graphic3d_HighlightStyle)& theStyle, const Standard_Integer theMode = 0)
+  {
+    Selectable()->HilightOwnerWithColor(aPM, theStyle, this);
+  }
+
+  DEFINE_STANDARD_RTTIEXT(ModuleBase_BRepOwner, StdSelect_BRepOwner)
+};
+
+#endif
\ No newline at end of file
index 927cfdc26906686bf0d2782e51384ba8639c06b8..058fe4761978f2e216f2debe4f9d8ac30c97d1ca 100755 (executable)
@@ -32,6 +32,8 @@
 #include <GeomAPI_Shape.h>
 #include <GeomAPI_ICustomPrs.h>
 
+#include <SelectMgr_ListOfFilter.hxx>
+
 #include <QString>
 #include <QObject>
 #include <QMap>
@@ -77,12 +79,6 @@ class MODULEBASE_EXPORT ModuleBase_IModule : public QObject
 
   virtual ~ModuleBase_IModule() {}
 
-  /// Add default selection filters of the module to the current viewer
-  virtual void activateSelectionFilters() {}
-
-  /// Remove default selection filters of the module from the current viewer
-  virtual void deactivateSelectionFilters() {}
-
   /// Stores the current selection
   virtual void storeSelection() {}
 
@@ -235,8 +231,24 @@ class MODULEBASE_EXPORT ModuleBase_IModule : public QObject
   virtual void activeSelectionModes(QIntList& theModes) {}
 
   /// Appends specific selection modes for the module to the list of types
-  /// \param theTypes a selection modes to be extended
-  virtual void customSubShapesSelectionModes(QIntList& theTypes) {}
+  /// \param theModesType combination of available selection filters
+  /// \param theModes a selection modes to be extended
+  virtual void moduleSelectionModes(int theModesType, QIntList& theModes) = 0;
+
+  /// Appends into container of filters module filters corresponded to the modes type
+  /// \param theFilterTypes container of available selection filters
+  /// \param theSelectionFilters [out] container to be extend by elements
+  virtual void moduleSelectionFilters(const QIntList& theFilterTypes,
+                                      SelectMgr_ListOfFilter& theSelectionFilters) = 0;
+
+  /// Returns types of registered module selection filters
+  /// \param theSelectionFilters [out] container of type value
+  virtual QIntList selectionFilters() { return QIntList(); }
+
+  /// Returns selection filter
+  /// \param theType selection filter type
+  /// \param theFilter instance of filter
+  virtual Handle(SelectMgr_Filter) selectionFilter(const int theType) = 0;
 
   /// Return true if the custom presentation is activated
   /// \param theFlag a flag of level of customization, which means that only part of sub-elements
index e2b1010ac167448905bd116c3c781c33b6ba9a70..446e0e59bb44c35bdfa67c983e6d51060787cc86 100644 (file)
@@ -100,7 +100,7 @@ signals:
 
   /// The signal about the widget activation
   /// \param theWidget the activated widget
-  void widgetActivated(ModuleBase_ModelWidget* theWidget);
+  //void widgetActivated(ModuleBase_ModelWidget* theWidget);
 
   /// Emited when there is no next widget
   /// \param thePreviousAttributeID an attribute key of the previous active widget
@@ -117,7 +117,6 @@ public slots:
   /**
   * Makes the given widget active, highlights it and removes
   * highlighting from the previous active widget
-  * emits widgetActivated(theWidget) signal
   * \param theWidget which has to be activated
   * \param theEmitSignal a flag to prohibit signal emit
   */
index b4324ef697f007a00eff17fd83f47f5c89f647a9..c185729fe9aa220e64ef7fd478321527788ab18e 100644 (file)
 class ModuleBase_ViewerPrs;
 class SelectMgr_EntityOwner;
 
-/**
-* \ingroup GUI
-* A class which provides access to selection.
-* A selection can be obtained as from a viewer as from Object browser in various forms
-*/
+/// \ingroup GUI
+/// A class which provides access to selection.
+/// A selection can be obtained as from a viewer as from Object browser in various forms
 class ModuleBase_ISelection
 {
  public:
@@ -71,50 +69,36 @@ class ModuleBase_ISelection
   virtual void fillPresentation(std::shared_ptr<ModuleBase_ViewerPrs>& thePrs,
                                 const Handle(SelectMgr_EntityOwner)& theOwner) const = 0;
 
-  /**
-   * Returns list of features currently selected in object browser
-   */
+  /// Returns list of features currently selected in object browser
   virtual QObjectPtrList selectedObjects() const = 0;
 
-  /// Set selected objects list
-  virtual void setSelectedObjects( const QObjectPtrList& ) const = 0;
-
-  /**
-   * Returns list of currently selected results
-   */
+  /// Returns list of currently selected results
   virtual QObjectPtrList selectedPresentations() const = 0;
 
-  //! Returns list of currently selected QModelIndexes
+  /// Returns list of currently selected QModelIndexes
   virtual QModelIndexList selectedIndexes() const = 0;
 
-  //! Returns list of currently selected AIS objects
-  //! \param theList returning list of selected AIS objects
-  virtual void selectedAISObjects(AIS_ListOfInteractive& theList) const = 0;
-
-  //! Returns list of currently selected QModelIndexes
-  virtual ObjectPtr getSelectableObject(const Handle(SelectMgr_EntityOwner)& theOwner) const = 0;
-
-  //! Return the shape from the viewer presentation.
-  //! If the shape is equal to the shape of selected object, it returns an empty shape
-  //! \param thePrs a selected object
-  //! \return a shape
+  /// Return the shape from the viewer presentation.
+  /// If the shape is equal to the shape of selected object, it returns an empty shape
+  /// \param thePrs a selected object
+  /// \return a shape
   MODULEBASE_EXPORT ResultPtr getResult(const std::shared_ptr<ModuleBase_ViewerPrs>& thePrs);
 
-  //! Return the shape from the viewer presentation.
-  //! If the shape is equal to the shape of selected object, it returns an empty shape
-  //! \param thePrs a selected object
-  //! \return a shape
+  /// Return the shape from the viewer presentation.
+  /// If the shape is equal to the shape of selected object, it returns an empty shape
+  /// \param thePrs a selected object
+  /// \return a shape
   MODULEBASE_EXPORT GeomShapePtr getShape(const std::shared_ptr<ModuleBase_ViewerPrs>& thePrs);
 
-  //! Return the IO from the viewer presentation.
-  //! \param thePrs a selected object
-  //! \return an interactive object
+  /// Return the IO from the viewer presentation.
+  /// \param thePrs a selected object
+  /// \return an interactive object
   virtual MODULEBASE_EXPORT
     Handle(AIS_InteractiveObject) getIO(const std::shared_ptr<ModuleBase_ViewerPrs>& thePrs) = 0;
 
-  //! Wraps the object list into the viewer prs list
-  //! \param theObjects a list of objects
-  //! \return a list of prs, where only object is not empty
+  /// Wraps the object list into the viewer prs list
+  /// \param theObjects a list of objects
+  /// \return a list of prs, where only object is not empty
   static MODULEBASE_EXPORT QList<std::shared_ptr<ModuleBase_ViewerPrs>> getViewerPrs(
                                                        const QObjectPtrList& theObjects);
 
@@ -122,6 +106,10 @@ class ModuleBase_ISelection
   /// owner with the qual vertex stays in the list.
   static MODULEBASE_EXPORT void filterSelectionOnEqualPoints
                                       (QList<std::shared_ptr<ModuleBase_ViewerPrs>>& theSelected);
+protected:
+  /// Returns list of currently selected QModelIndexes
+  virtual ObjectPtr getSelectableObject(const Handle(SelectMgr_EntityOwner)& theOwner) const = 0;
+
 private:
   /// Find vertex shape build by a Brep owner of the presentation if it exists
   /// \param thePrs a viewer presentation
diff --git a/src/ModuleBase/ModuleBase_ISelectionActivate.h b/src/ModuleBase/ModuleBase_ISelectionActivate.h
new file mode 100644 (file)
index 0000000..c730d7b
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef ModuleBase_ISelectionActivate_H
+#define ModuleBase_ISelectionActivate_H
+
+#include "ModuleBase.h"
+
+#include "ModuleBase_IWorkshop.h"
+
+#include <SelectMgr_ListOfFilter.hxx>
+
+class ModuleBase_ModelWidget;
+
+
+/// \ingroup GUI
+/// A class which provides interface of activation/deactivate selection modes
+/// and using selection filters.
+class ModuleBase_ISelectionActivate
+{
+public:
+  /// Constructor
+  ModuleBase_ISelectionActivate(ModuleBase_IWorkshop* theWorkshop) : myWorkshop(theWorkshop) {}
+
+  /// Destructor
+  ~ModuleBase_ISelectionActivate() {}
+
+  /// Updates active selection modes in the viewer depending on the application state
+  MODULEBASE_EXPORT virtual void updateSelectionModes() = 0;
+
+  /// Updates active selection filters in the viewer depending on the application state
+  MODULEBASE_EXPORT virtual void updateSelectionFilters() = 0;
+
+  /// Activates parameter filters in the workshop, deactivate active out of the container
+  /// Please find a possibility to use updateSelectionFilters instead of direct call this method.
+  /// \param theSelectionFilters a filtes
+  MODULEBASE_EXPORT virtual void activateSelectionFilters
+    (const SelectMgr_ListOfFilter& theSelectionFilters) = 0;
+
+protected:
+  ModuleBase_IWorkshop* myWorkshop; ///< active workshop
+};
+
+#endif
index 77d9314d74d6b7d1d6d10096153bbdb97d82186b..e9a4d2c350b788ee8249c6cc19500ec370f2bba4 100644 (file)
@@ -37,6 +37,7 @@ class ModuleBase_IViewer;
 class ModuleBase_IPropertyPanel;
 class ModuleBase_IErrorMgr;
 class ModuleBase_Operation;
+class ModuleBase_ISelectionActivate;
 class ModuleBase_ViewerPrs;
 class QMainWindow;
 
@@ -58,16 +59,6 @@ Q_OBJECT
   /// Return current selection instance
   virtual ModuleBase_ISelection* selection() const = 0;
 
-  /// Activate sub-shapes selection (opens local context)
-  /// Types has to be defined according to TopAbs_ShapeEnum
-  virtual void activateSubShapesSelection(const QIntList& theTypes) = 0;
-
-  /// Activate objects in the module selection modes(opens local context)
-  virtual void activateModuleSelectionModes() = 0;
-
-  /// Deactivate sub-shapes selection (closes local context)
-  virtual void deactivateSubShapesSelection() = 0;
-
   //! Returns instance of loaded module
   virtual ModuleBase_IModule* module() const = 0;
 
@@ -84,6 +75,9 @@ Q_OBJECT
   /// \return a filter
   Handle(ModuleBase_FilterValidated) validatorFilter();
 
+  /// A selection activate in 3D View handler
+  virtual ModuleBase_ISelectionActivate* selectionActivate() const = 0;
+
   //! Returns currently active operation
   virtual ModuleBase_Operation* currentOperation() const = 0;
 
diff --git a/src/ModuleBase/ModuleBase_ListView.cpp b/src/ModuleBase/ModuleBase_ListView.cpp
new file mode 100644 (file)
index 0000000..03a884d
--- /dev/null
@@ -0,0 +1,182 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "ModuleBase_ListView.h"
+#include "ModuleBase_Tools.h"
+
+#include <QAction>
+#include <QApplication>
+#include <QClipboard>
+#include <QListWidget>
+#include <QWidget>
+
+#ifndef WIN32
+#include <QResizeEvent>
+#include <QTimer>
+#endif
+
+const int ATTRIBUTE_SELECTION_INDEX_ROLE = Qt::UserRole + 1;
+
+/**
+* Customization of a List Widget to make it to be placed on full width of container
+*/
+class CustomListWidget : public QListWidget
+{
+public:
+  /// Constructor
+  /// \param theParent a parent widget
+  CustomListWidget(QWidget* theParent)
+    : QListWidget(theParent)
+  {
+  }
+
+  /// Redefinition of virtual method
+  virtual QSize        sizeHint() const
+  {
+    int aHeight = 2*QFontMetrics(font()).height();
+    QSize aSize = QListWidget::sizeHint();
+    return QSize(aSize.width(), aHeight);
+  }
+
+  /// Redefinition of virtual method
+  virtual QSize        minimumSizeHint() const
+  {
+    int aHeight = 4/*2*/*QFontMetrics(font()).height();
+    QSize aSize = QListWidget::minimumSizeHint();
+    return QSize(aSize.width(), aHeight);
+  }
+
+#ifndef WIN32
+// The code is necessary only for Linux because
+//it can not update viewport on widget resize
+protected:
+  void resizeEvent(QResizeEvent* theEvent)
+  {
+    QListWidget::resizeEvent(theEvent);
+    QTimer::singleShot(5, viewport(), SLOT(repaint()));
+  }
+#endif
+};
+
+//********************************************************************
+ModuleBase_ListView::ModuleBase_ListView(QWidget* theParent, const QString& theObjectName,
+  const QString& theToolTip)
+{
+  myListControl = new CustomListWidget(theParent);
+
+  myListControl->setObjectName(theObjectName);
+  myListControl->setToolTip(theToolTip);
+  myListControl->setSelectionMode(QAbstractItemView::ExtendedSelection);
+
+  myCopyAction = ModuleBase_Tools::createAction(QIcon(":pictures/copy.png"), tr("Copy"),
+                          theParent, this, SLOT(onCopyItem()));
+  myCopyAction->setShortcut(QKeySequence::Copy);
+  myCopyAction->setEnabled(false);
+  myListControl->addAction(myCopyAction);
+
+  myDeleteAction = ModuleBase_Tools::createAction(QIcon(":pictures/delete.png"), tr("Delete"),
+                          theParent, this, SIGNAL(deleteActionClicked()));
+  myDeleteAction->setEnabled(false);
+  myListControl->addAction(myDeleteAction);
+
+  myListControl->setContextMenuPolicy(Qt::ActionsContextMenu);
+  connect(myListControl, SIGNAL(itemSelectionChanged()), SLOT(onListSelection()));
+}
+
+//********************************************************************
+void ModuleBase_ListView::addItem(const QString& theTextValue, const int theIndex)
+{
+  QListWidgetItem* anItem = new QListWidgetItem(theTextValue, myListControl);
+  anItem->setData(ATTRIBUTE_SELECTION_INDEX_ROLE, theIndex);
+  myListControl->addItem(anItem);
+}
+
+//********************************************************************
+void ModuleBase_ListView::getSelectedIndices(std::set<int>& theIndices)
+{
+  QList<QListWidgetItem*> aItems = myListControl->selectedItems();
+  foreach(QListWidgetItem* anItem, aItems) {
+    int anIndex = anItem->data(ATTRIBUTE_SELECTION_INDEX_ROLE).toInt();
+    if (theIndices.find(anIndex) == theIndices.end())
+      theIndices.insert(anIndex);
+  }
+}
+
+//********************************************************************
+void ModuleBase_ListView::removeSelectedItems()
+{
+  QList<QListWidgetItem*> aItems = myListControl->selectedItems();
+  foreach(QListWidgetItem* anItem, aItems)
+    myListControl->takeItem(myListControl->row(anItem));
+}
+
+//********************************************************************
+void ModuleBase_ListView::removeItems(std::set<int>& theIndices)
+{
+  QList<QListWidgetItem*> aItems;
+  for (int i = 0; i < myListControl->count(); i++) {
+    QListWidgetItem* anItem = myListControl->item(i);
+    int anIndex = anItem->data(ATTRIBUTE_SELECTION_INDEX_ROLE).toInt();
+    if (theIndices.find(anIndex) != theIndices.end())
+      aItems.append(anItem);
+  }
+  foreach(QListWidgetItem* anItem, aItems)
+    myListControl->takeItem(myListControl->row(anItem));
+}
+
+//********************************************************************
+void ModuleBase_ListView::restoreSelection(const QModelIndexList& theIndices)
+{
+  int aRows = myListControl->model()->rowCount();
+  if (aRows > 0) {
+    foreach(QModelIndex aIndex, theIndices) {
+      if (aIndex.row() < aRows)
+        myListControl->selectionModel()->select(aIndex, QItemSelectionModel::Select);
+      else {
+        QModelIndex aIdx = myListControl->model()->index(aRows - 1, 0);
+        myListControl->selectionModel()->select(aIdx, QItemSelectionModel::Select);
+      }
+    }
+  }
+}
+
+//********************************************************************
+void ModuleBase_ListView::onCopyItem()
+{
+  QList<QListWidgetItem*> aItems = myListControl->selectedItems();
+  QString aRes;
+  foreach(QListWidgetItem* aItem, aItems) {
+    if (!aRes.isEmpty())
+      aRes += "\n";
+    aRes += aItem->text();
+  }
+  if (!aRes.isEmpty()) {
+    QClipboard* aClipboard = QApplication::clipboard();
+    aClipboard->setText(aRes);
+  }
+}
+
+//********************************************************************
+void ModuleBase_ListView::onListSelection()
+{
+  QList<QListWidgetItem*> aItems = myListControl->selectedItems();
+  myCopyAction->setEnabled(!aItems.isEmpty());
+  myDeleteAction->setEnabled(!aItems.isEmpty());
+}
\ No newline at end of file
diff --git a/src/ModuleBase/ModuleBase_ListView.h b/src/ModuleBase/ModuleBase_ListView.h
new file mode 100644 (file)
index 0000000..27c2262
--- /dev/null
@@ -0,0 +1,95 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef ModuleBase_ListView_H_
+#define ModuleBase_ListView_H_
+
+#include "ModuleBase.h"
+
+#include <QModelIndex>
+#include <QObject>
+
+#include <set>
+
+class QAction;
+class QListWidget;
+class QWidget;
+
+/**
+* \ingroup GUI
+* An extension of QListWidget to provide Undo/Redo functionality
+*/
+class MODULEBASE_EXPORT ModuleBase_ListView : public QObject
+{
+Q_OBJECT
+
+public:
+  /// Constructor
+  ModuleBase_ListView(QWidget* theParent = 0, const QString& theObjectName = QString(),
+    const QString& theToolTip = QString());
+  /// Destructor
+  virtual ~ModuleBase_ListView() {}
+
+  /// Returns current control
+  /// \return list view instance
+  QListWidget* getControl() const { return myListControl; }
+
+  /// Adds a new list widget item to the end of the list and connect it to the given index
+  /// \param theTextValue value visualized in the view
+  /// \param theIndex an item internal index
+  void addItem(const QString& theTextValue, const int theIndex);
+
+  /// Returns list of internal list view item indices
+  /// \param theIndices an output container for indices
+  void getSelectedIndices(std::set<int>& theIndices);
+
+  /// Removes selected items from the list widget
+  void removeSelectedItems();
+
+  /// Remove items contain parameter indices
+  /// \param theIndices an indices
+  void removeItems(std::set<int>& theIndices);
+
+  /// Set selected items if possible
+  /// \param theIndices container of indices to be selected
+  void restoreSelection(const QModelIndexList& theIndices);
+
+  /// Update enable/disable state of context menu actions
+  void updateActionsStatus();
+
+protected slots:
+  /// Slot for copy command in a list pop-up menu
+  void onCopyItem();
+
+  /// Slot is called on selection of list of selected items
+  void onListSelection();
+
+signals:
+  /// Signal about delete action click
+  void deleteActionClicked();
+
+protected:
+  QListWidget* myListControl; ///< List control
+
+  QAction* myCopyAction; ///< A copy action for pop-up menu in a list control
+  QAction* myDeleteAction; ///< A delete action for pop-up menu in a list control
+};
+
+#endif
index ff4f88a9dc1b875f95a3f3ce23a1505da7afa2b2..50c7734d280c69e7af1b38b516efb322c6be5353 100644 (file)
@@ -49,6 +49,7 @@
 //#define DEBUG_WIDGET_INSTANCE
 //#define DEBUG_ENABLE_SKETCH_INPUT_FIELDS
 
+//**************************************************************
 ModuleBase_ModelWidget::ModuleBase_ModelWidget(QWidget* theParent,
                                                const Config_WidgetAPI* theData)
     : QWidget(theParent),
@@ -85,6 +86,7 @@ ModuleBase_ModelWidget::ModuleBase_ModelWidget(QWidget* theParent,
   connect(this, SIGNAL(valuesModified()), this, SLOT(onWidgetValuesModified()));
 }
 
+//**************************************************************
 ModuleBase_ModelWidget::~ModuleBase_ModelWidget()
 {
 #ifdef DEBUG_WIDGET_INSTANCE
@@ -92,6 +94,7 @@ ModuleBase_ModelWidget::~ModuleBase_ModelWidget()
 #endif
 }
 
+//**************************************************************
 bool ModuleBase_ModelWidget::reset()
 {
   bool aResult = resetCustom();
@@ -101,11 +104,29 @@ bool ModuleBase_ModelWidget::reset()
   return aResult;
 }
 
+//**************************************************************
 bool ModuleBase_ModelWidget::isInitialized(ObjectPtr theObject) const
 {
   return theObject->data()->attribute(attributeID())->isInitialized();
 }
 
+//**************************************************************
+void ModuleBase_ModelWidget::selectionModes(int& theModuleSelectionModes, QIntList& theModes)
+{
+  theModuleSelectionModes = -1;
+  if (myWidgetValidator)
+    myWidgetValidator->selectionModes(theModuleSelectionModes, theModes);
+}
+
+//**************************************************************
+void ModuleBase_ModelWidget::selectionFilters(QIntList& theModuleSelectionFilters,
+                                              SelectMgr_ListOfFilter& theSelectionFilters)
+{
+  if (myWidgetValidator)
+    myWidgetValidator->selectionFilters(theModuleSelectionFilters, theSelectionFilters);
+}
+
+//**************************************************************
 bool ModuleBase_ModelWidget::isValueEnabled() const
 {
   bool anEnabled = true;
@@ -124,12 +145,14 @@ bool ModuleBase_ModelWidget::isValueEnabled() const
   return anEnabled;
 }
 
+//**************************************************************
 void ModuleBase_ModelWidget::processValueState()
 {
   if (myState == ModifiedInPP || myState == ModifiedInViewer)
     storeValue();
 }
 
+//**************************************************************
 Events_InfoMessage ModuleBase_ModelWidget::getValueStateError() const
 {
   Events_InfoMessage aMessage;
@@ -157,6 +180,7 @@ Events_InfoMessage ModuleBase_ModelWidget::getValueStateError() const
   return aMessage;
 }
 
+//**************************************************************
 QString ModuleBase_ModelWidget::getError(const bool theValueStateChecked) const
 {
   QString anError;
@@ -194,6 +218,7 @@ QString ModuleBase_ModelWidget::getError(const bool theValueStateChecked) const
   return anError;
 }
 
+//**************************************************************
 void ModuleBase_ModelWidget::enableFocusProcessing()
 {
   QList<QWidget*> aMyControls = getControls();
@@ -203,6 +228,7 @@ void ModuleBase_ModelWidget::enableFocusProcessing()
   }
 }
 
+//**************************************************************
 void ModuleBase_ModelWidget::setHighlighted(bool isHighlighted)
 {
   QList<QWidget*> aWidgetList = getControls();
@@ -217,6 +243,7 @@ void ModuleBase_ModelWidget::setHighlighted(bool isHighlighted)
   }
 }
 
+//**************************************************************
 void ModuleBase_ModelWidget::setFeature(const FeaturePtr& theFeature, const bool theToStoreValue,
                                         const bool isUpdateFlushed)
 {
@@ -234,6 +261,7 @@ void ModuleBase_ModelWidget::setFeature(const FeaturePtr& theFeature, const bool
   myFlushUpdateBlocked = false;
 }
 
+//**************************************************************
 bool ModuleBase_ModelWidget::focusTo()
 {
 #ifdef DEBUG_WIDGET_INSTANCE
@@ -252,6 +280,7 @@ bool ModuleBase_ModelWidget::focusTo()
   return isFocusAccepted;
 }
 
+//**************************************************************
 void ModuleBase_ModelWidget::activate()
 {
 #ifdef DEBUG_WIDGET_INSTANCE
@@ -265,13 +294,10 @@ void ModuleBase_ModelWidget::activate()
     if (anAttribute.get() != NULL && !anAttribute->isInitialized())
       initializeValueByActivate();
   }
-
-  if (myWidgetValidator)
-    myWidgetValidator->activateFilters(true);
-
   activateCustom();
 }
 
+//**************************************************************
 void ModuleBase_ModelWidget::deactivate()
 {
 #ifdef DEBUG_WIDGET_INSTANCE
@@ -280,9 +306,10 @@ void ModuleBase_ModelWidget::deactivate()
   myIsValueStateBlocked = false;
   myState = Stored;
   if (myWidgetValidator)
-    myWidgetValidator->activateFilters(false);
+    myWidgetValidator->clearValidatedCash();
 }
 
+//**************************************************************
 void ModuleBase_ModelWidget::initializeValueByActivate()
 {
   if (isComputedDefault()) {
@@ -295,6 +322,7 @@ void ModuleBase_ModelWidget::initializeValueByActivate()
   }
 }
 
+//**************************************************************
 QWidget* ModuleBase_ModelWidget::getControlAcceptingFocus(const bool isFirst)
 {
   QWidget* aControl = 0;
@@ -317,11 +345,13 @@ QWidget* ModuleBase_ModelWidget::getControlAcceptingFocus(const bool isFirst)
   return aControl;
 }
 
+//**************************************************************
 void ModuleBase_ModelWidget::setDefaultValue(const std::string& theValue)
 {
   myDefaultValue = theValue;
 }
 
+//**************************************************************
 bool ModuleBase_ModelWidget::storeValue()
 {
   setValueState(Stored);
@@ -348,6 +378,8 @@ bool ModuleBase_ModelWidget::storeValue()
   return isDone;
 }
 #ifdef DEBUG_VALUE_STATE
+
+//**************************************************************
 std::string getDebugInfo(const ModuleBase_ModelWidget::ValueState& theState)
 {
   std::string anInfo;
@@ -360,8 +392,9 @@ std::string getDebugInfo(const ModuleBase_ModelWidget::ValueState& theState)
   }
   return anInfo;
 }
-
 #endif
+
+//**************************************************************
 ModuleBase_ModelWidget::ValueState ModuleBase_ModelWidget::setValueState
                                          (const ModuleBase_ModelWidget::ValueState& theState)
 {
@@ -379,6 +412,7 @@ ModuleBase_ModelWidget::ValueState ModuleBase_ModelWidget::setValueState
   return aState;
 }
 
+//**************************************************************
 bool ModuleBase_ModelWidget::blockValueState(const bool theBlocked)
 {
   bool isBlocked = myIsValueStateBlocked;
@@ -386,6 +420,7 @@ bool ModuleBase_ModelWidget::blockValueState(const bool theBlocked)
   return isBlocked;
 }
 
+//**************************************************************
 bool ModuleBase_ModelWidget::restoreValue()
 {
   emit beforeValuesRestored();
@@ -395,6 +430,7 @@ bool ModuleBase_ModelWidget::restoreValue()
   return isDone;
 }
 
+//**************************************************************
 void ModuleBase_ModelWidget::updateObject(ObjectPtr theObject)
 {
   if (!myFlushUpdateBlocked) {
@@ -406,6 +442,7 @@ void ModuleBase_ModelWidget::updateObject(ObjectPtr theObject)
   }
 }
 
+//**************************************************************
 bool ModuleBase_ModelWidget::canProcessAction(ModuleBase_ActionType theActionType,
                                               bool& isActionEnabled)
 {
@@ -414,6 +451,7 @@ bool ModuleBase_ModelWidget::canProcessAction(ModuleBase_ActionType theActionTyp
     case ActionEnter: return false;
     case ActionEscape: return false;
     case ActionDelete: return true;
+    case ActionSelection: return true;
     case ActionUndo:
     case ActionRedo:
     default:
@@ -421,7 +459,9 @@ bool ModuleBase_ModelWidget::canProcessAction(ModuleBase_ActionType theActionTyp
   }
 }
 
-bool ModuleBase_ModelWidget::processAction(ModuleBase_ActionType theActionType)
+//**************************************************************
+bool ModuleBase_ModelWidget::processAction(ModuleBase_ActionType theActionType,
+                                           const ActionParamPtr& theParam)
 {
   switch (theActionType) {
     case ActionEnter:
@@ -430,6 +470,8 @@ bool ModuleBase_ModelWidget::processAction(ModuleBase_ActionType theActionType)
       return processEscape();
     case ActionDelete:
       return processDelete();
+    case ActionSelection:
+      processSelection();
     case ActionUndo:
     case ActionRedo:
     default:
@@ -437,16 +479,19 @@ bool ModuleBase_ModelWidget::processAction(ModuleBase_ActionType theActionType)
   }
 }
 
+//**************************************************************
 bool ModuleBase_ModelWidget::processEnter()
 {
   return false;
 }
 
+//**************************************************************
 bool ModuleBase_ModelWidget::processEscape()
 {
   return false;
 }
 
+//**************************************************************
 bool ModuleBase_ModelWidget::processDelete()
 {
   // we consider that model objects eats delete key in order to
@@ -454,6 +499,13 @@ bool ModuleBase_ModelWidget::processDelete()
   return true;
 }
 
+//**************************************************************
+bool ModuleBase_ModelWidget::processSelection()
+{
+  return false;
+}
+
+//**************************************************************
 bool ModuleBase_ModelWidget::eventFilter(QObject* theObject, QEvent *theEvent)
 {
   QWidget* aWidget = qobject_cast<QWidget*>(theObject);
index b72edb9c64075ef909889ebd41d6524f4c5bc4d0..2e215404f25d7d713a78f515e5d1b748c1ac0c19 100644 (file)
 
 #include <ModuleBase.h>
 #include <ModuleBase_ActionType.h>
+#include <ModuleBase_Definitions.h>
 #include <ModuleBase_OperationFeature.h>
+#include <ModuleBase_ActionInfo.h>
+#include <ModuleBase_ActionParameter.h>
 #include <ModelAPI_Feature.h>
 
+#include <SelectMgr_ListOfFilter.hxx>
+
 #include <QWidget>
 
 #include <memory>
@@ -81,6 +86,17 @@ Q_OBJECT
   /// \return the boolean result
   bool isInitialized(ObjectPtr theObject) const;
 
+  /// Fills given container with selection modes if the widget has it
+  /// \param [out] theModuleSelectionModes module additional modes, -1 means all default modes
+  /// \param [out] theModes a container of modes
+  virtual void selectionModes(int& theModuleSelectionModes, QIntList& theModes);
+
+  /// Appends into container of workshop selection filters
+  /// \param [out] theModuleSelectionFilters module additional modes, -1 means all default modes
+  /// \param [out] theSelectionFilters selection filters
+  virtual void selectionFilters(QIntList& theModuleSelectionFilters,
+                                SelectMgr_ListOfFilter& theSelectionFilters);
+
   /// Returns true, if default value of the widget should be computed
   /// on operation's execute, like radius for circle's constraint (can not be zero)
   bool isComputedDefault() const { return myIsComputedDefault; }
@@ -184,6 +200,14 @@ Q_OBJECT
   /// The method called when widget is deactivated
   virtual void deactivate();
 
+  /// Opportunity to do something after the active widget of the property panel changed
+  virtual void updateAfterDeactivation() {}
+  /// Opportunity to do something after the active widget of the property panel changed
+  virtual void updateAfterActivation() {}
+
+  /// The method called if widget should be activated always
+  virtual bool needToBeActiated() { return false; }
+
   /// Returns list of widget controls
   /// \return a control list
   virtual QList<QWidget*> getControls() const = 0;
@@ -247,7 +271,13 @@ Q_OBJECT
   virtual bool canProcessAction(ModuleBase_ActionType theActionType, bool& isActionEnabled);
 
   /// Returns true if the event is processed. The default implementation is empty, returns false.
-  virtual bool processAction(ModuleBase_ActionType theActionType);
+  virtual bool processAction(ModuleBase_ActionType theActionType,
+                             const ActionParamPtr& theParam = ActionParamPtr());
+
+  /// Returns list of accessible actions for Undo/Redo commands. By default it returns empty list.
+  /// \param theActionType type of action. It can be ActionUndo or ActionRedo.
+  virtual QList<ActionInfo> actionsList(ModuleBase_ActionType theActionType) const
+  { return QList<ActionInfo>(); }
 
   /// Sends Update and Redisplay for the given object
   /// \param theObj is updating object
@@ -357,7 +387,10 @@ protected:
   //// Returns true if the event is processed. The default implementation is empty, returns false.
   virtual bool processDelete();
 
-protected slots:
+  /// Returns true if envent is processed. It applyes workshop selection for the widget attribute.
+  virtual bool processSelection();
+
+  protected slots:
   /// Processing of values changed in model widget by store the current value to the feature
   void onWidgetValuesChanged();
 
index 3b3cfc82db32ffba4b130efe30a9109ccf1acf43..b04e209830ec3d40ec4d09cf757a6f5b26d21212 100755 (executable)
@@ -368,12 +368,12 @@ bool ModuleBase_OperationFeature::commit()
 
     afterCommitOperation();
 #ifdef DEBUG_OPERATION_START
-  qDebug("ModuleBase_OperationFeature::commit -- end : IMPOSSIBLE to commit");
+  qDebug("ModuleBase_OperationFeature::commit -- end");
 #endif
     return true;
   }
 #ifdef DEBUG_OPERATION_START
-  qDebug("ModuleBase_OperationFeature::commit -- end");
+  qDebug("ModuleBase_OperationFeature::commit -- end : IMPOSSIBLE to commit");
 #endif
   return false;
 }
index 907fd6a6098ffb50752defe12d7ff04ddbc2d987..6dd875f779274996ee88f9b2b3a478d38e76de77 100755 (executable)
 //
 
 #include "ModuleBase_ResultPrs.h"
-#include "ModuleBase_Tools.h"
+
+#include <GeomAPI_PlanarEdges.h>
 
 #include <ModelAPI_Events.h>
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_ResultCompSolid.h>
-#include <GeomAPI_PlanarEdges.h>
+
+#include "ModuleBase_Tools.h"
+#include "ModuleBase_BRepOwner.h"
 
 #include <Events_InfoMessage.h>
 #include <Events_Loop.h>
 
+#include <AIS_ColoredDrawer.hxx>
+#include <AIS_InteractiveContext.hxx>
+#include <AIS_Selection.hxx>
+#include <BOPTools_AlgoTools3D.hxx>
 #include <BRep_Builder.hxx>
+#include <Graphic3d_AspectMarker3d.hxx>
 #include <Prs3d_Drawer.hxx>
 #include <Prs3d.hxx>
 #include <Prs3d_PointAspect.hxx>
 #include <Prs3d_IsoAspect.hxx>
-#include <TopoDS_Builder.hxx>
-#include <TopoDS.hxx>
+#include <Prs3d_ShadingAspect.hxx>
 #include <SelectMgr_SequenceOfOwner.hxx>
 #include <SelectMgr_EntityOwner.hxx>
 #include <SelectMgr_SelectionManager.hxx>
 #include <StdPrs_WFShape.hxx>
+#include <StdPrs_ShadedShape.hxx>
 #include <StdSelect_BRepSelectionTool.hxx>
-#include <AIS_InteractiveContext.hxx>
-#include <AIS_Selection.hxx>
 #include <TColStd_ListIteratorOfListOfInteger.hxx>
-#include <Graphic3d_AspectMarker3d.hxx>
 #include <TopExp_Explorer.hxx>
-
-IMPLEMENT_STANDARD_RTTIEXT(ModuleBase_BRepOwner, StdSelect_BRepOwner);
+#include <TopoDS.hxx>
+#include <TopoDS_Builder.hxx>
 
 //*******************************************************************************************
 
@@ -56,8 +61,10 @@ IMPLEMENT_STANDARD_RTTIEXT(ModuleBase_ResultPrs, ViewerData_AISShape);
 
 
 
+//********************************************************************
 ModuleBase_ResultPrs::ModuleBase_ResultPrs(ResultPtr theResult)
-  : ViewerData_AISShape(TopoDS_Shape()), myResult(theResult), myAdditionalSelectionPriority(0)
+  : ViewerData_AISShape(TopoDS_Shape()), myResult(theResult), myAdditionalSelectionPriority(0),
+  myTransparency(1)
 {
   std::shared_ptr<GeomAPI_Shape> aShapePtr = ModelAPI_Tools::shape(theResult);
   TopoDS_Shape aShape = aShapePtr->impl<TopoDS_Shape>();
@@ -72,14 +79,94 @@ ModuleBase_ResultPrs::ModuleBase_ResultPrs(ResultPtr theResult)
   ResultCompSolidPtr aCompSolid = ModelAPI_Tools::compSolidOwner(myResult);
   SetAutoHilight(aCompSolid.get() == NULL);
 
+  myHiddenSubShapesDrawer = new AIS_ColoredDrawer (myDrawer);
+  Handle(Prs3d_ShadingAspect) aShadingAspect = new Prs3d_ShadingAspect();
+  aShadingAspect->SetMaterial(Graphic3d_NOM_BRASS); //default value of context material
+  myHiddenSubShapesDrawer->SetShadingAspect(aShadingAspect);
+
   ModuleBase_Tools::setPointBallHighlighting(this);
 }
 
+//********************************************************************
 void ModuleBase_ResultPrs::setAdditionalSelectionPriority(const int thePriority)
 {
   myAdditionalSelectionPriority = thePriority;
 }
 
+//********************************************************************
+void ModuleBase_ResultPrs::SetColor (const Quantity_Color& theColor)
+{
+  ViewerData_AISShape::SetColor(theColor);
+  myHiddenSubShapesDrawer->ShadingAspect()->SetColor (theColor, myCurrentFacingModel);
+}
+
+//********************************************************************
+bool ModuleBase_ResultPrs::setSubShapeHidden(const NCollection_List<TopoDS_Shape>& theShapes)
+{
+  bool isModified = false;
+
+  TopoDS_Compound aCompound;
+  BRep_Builder aBBuilder;
+  aBBuilder.MakeCompound (aCompound);
+  // restore hidden shapes if there are not the shapes in parameter container
+  NCollection_List<TopoDS_Shape> aVisibleSubShapes;
+  for (NCollection_List<TopoDS_Shape>::Iterator aHiddenIt(myHiddenSubShapes); aHiddenIt.More();
+       aHiddenIt.Next()) {
+    if (!theShapes.Contains(aHiddenIt.Value()))
+      aVisibleSubShapes.Append(aHiddenIt.Value());
+    else
+      aBBuilder.Add (aCompound, aHiddenIt.Value());
+  }
+  isModified = !aVisibleSubShapes.IsEmpty();
+  for (NCollection_List<TopoDS_Shape>::Iterator aVisibleIt(aVisibleSubShapes); aVisibleIt.More();
+       aVisibleIt.Next())
+    myHiddenSubShapes.Remove(aVisibleIt.Value());
+
+  // append hidden shapes into internal container if there are not these shapes
+  for (NCollection_List<TopoDS_Shape>::Iterator aShapeIt(theShapes); aShapeIt.More();
+    aShapeIt.Next())
+  {
+    if (aShapeIt.Value().ShapeType() != TopAbs_FACE) // only face shape can be hidden
+      continue;
+
+    if (!myHiddenSubShapes.Contains(aShapeIt.Value())) {
+      myHiddenSubShapes.Append(aShapeIt.Value());
+      aBBuilder.Add (aCompound, aShapeIt.Value());
+      isModified = true;
+    }
+  }
+  myHiddenCompound = aCompound;
+  return isModified;
+}
+
+//********************************************************************
+bool ModuleBase_ResultPrs::hasSubShapeVisible(
+  const NCollection_List<TopoDS_Shape>& theShapesToSkip)
+{
+  TopoDS_Compound aCompound;
+  BRep_Builder aBuilder;
+  aBuilder.MakeCompound (aCompound);
+  NCollection_List<TopoDS_Shape> aShapesToSkip;
+  aShapesToSkip.Append(myHiddenSubShapes);
+  for (NCollection_List<TopoDS_Shape>::Iterator anIt(theShapesToSkip); anIt.More(); anIt.Next())
+    aShapesToSkip.Append(anIt.Value());
+
+  collectSubShapes(aBuilder, aCompound, myOriginalShape, aShapesToSkip);
+  return !BOPTools_AlgoTools3D::IsEmptyShape(aCompound);
+}
+
+//********************************************************************
+bool ModuleBase_ResultPrs::setHiddenSubShapeTransparency(double theTransparency)
+{
+  if (myTransparency == theTransparency || theTransparency > 1 || theTransparency < 0)
+    return false;
+
+  myTransparency = theTransparency;
+  myHiddenSubShapesDrawer->ShadingAspect()->SetTransparency (theTransparency, myCurrentFacingModel);
+  return true;
+}
+
+//********************************************************************
 void ModuleBase_ResultPrs::Compute(
           const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
           const Handle(Prs3d_Presentation)& thePresentation,
@@ -89,13 +176,32 @@ void ModuleBase_ResultPrs::Compute(
   bool aReadyToDisplay = aShapePtr.get();
   if (aReadyToDisplay) {
     myOriginalShape = aShapePtr->impl<TopoDS_Shape>();
-    if (!myOriginalShape.IsNull())
-      Set(myOriginalShape);
+    if (myHiddenSubShapes.IsEmpty() || myOriginalShape.ShapeType() > TopAbs_FACE ) {
+      if (!myOriginalShape.IsNull())
+        Set(myOriginalShape);
+    }
+    else { // convert shape into SHELL
+      TopoDS_Compound aCompound;
+      BRep_Builder aBuilder;
+      aBuilder.MakeCompound (aCompound);
+      collectSubShapes(aBuilder, aCompound, myOriginalShape, myHiddenSubShapes);
+      bool isEmptyShape = BOPTools_AlgoTools3D::IsEmptyShape(aCompound);
+      Set(aCompound);
+      if (isEmptyShape)
+        aReadyToDisplay = false;
+    }
   }
   // change deviation coefficient to provide more precise circle
   //ModuleBase_Tools::setDefaultDeviationCoefficient(myResult, Attributes());
   AIS_Shape::Compute(thePresentationManager, thePresentation, theMode);
 
+  // visualize hidden sub-shapes transparent
+  if (myTransparency < 1 && !myHiddenSubShapes.IsEmpty())
+  {
+    StdPrs_ShadedShape::Add (thePresentation, myHiddenCompound, myHiddenSubShapesDrawer);
+    aReadyToDisplay = true;
+  }
+
   if (!aReadyToDisplay) {
     Events_InfoMessage("ModuleBase_ResultPrs",
                        "An empty AIS presentation: ModuleBase_ResultPrs").send();
@@ -104,6 +210,46 @@ void ModuleBase_ResultPrs::Compute(
   }
 }
 
+//********************************************************************
+void ModuleBase_ResultPrs::collectSubShapes(BRep_Builder& theBuilder,
+  TopoDS_Shape& theCompound, const TopoDS_Shape& theShape,
+  const NCollection_List<TopoDS_Shape>& theHiddenSubShapes)
+{
+  switch (theShape.ShapeType()) {
+    case TopAbs_COMPOUND: {
+      for (TopoDS_Iterator aChildIter (theShape); aChildIter.More(); aChildIter.Next())
+        collectSubShapes(theBuilder, theCompound, aChildIter.Value(), theHiddenSubShapes);
+    }
+    break;
+    case TopAbs_SOLID:
+    case TopAbs_SHELL: {
+      for (TopExp_Explorer anExp (theShape, TopAbs_FACE); anExp.More(); anExp.Next()) {
+        collectSubShapes(theBuilder, theCompound, anExp.Current(), theHiddenSubShapes);
+      }
+    }
+    break;
+    case TopAbs_WIRE: {
+      for (TopExp_Explorer anExp (theShape, TopAbs_EDGE); anExp.More(); anExp.Next()) {
+        collectSubShapes(theBuilder, theCompound, anExp.Current(), theHiddenSubShapes);
+      }
+    }
+    break;
+    case TopAbs_FACE: {
+      if (theHiddenSubShapes.Contains(theShape))
+        return; // remove hidden shape
+      theBuilder.Add(theCompound, theShape);
+    }
+    break;
+    case TopAbs_EDGE:
+    case TopAbs_VERTEX: {
+      theBuilder.Add(theCompound, theShape);
+    }
+    default:
+      break;
+  }
+}
+
+//********************************************************************
 void ModuleBase_ResultPrs::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
                                             const Standard_Integer theMode)
 {
@@ -169,6 +315,7 @@ void ModuleBase_ResultPrs::ComputeSelection(const Handle(SelectMgr_Selection)& a
   }
 }
 
+//********************************************************************
 bool ModuleBase_ResultPrs::appendVertexSelection(const Handle(SelectMgr_Selection)& aSelection,
                                                  const Standard_Integer theMode)
 {
@@ -196,6 +343,7 @@ bool ModuleBase_ResultPrs::appendVertexSelection(const Handle(SelectMgr_Selectio
   return false;
 }
 
+//********************************************************************
 void ModuleBase_ResultPrs::HilightSelected(const Handle(PrsMgr_PresentationManager3d)& thePM,
                                            const SelectMgr_SequenceOfOwner& theOwners)
 {
@@ -222,6 +370,7 @@ void ModuleBase_ResultPrs::HilightSelected(const Handle(PrsMgr_PresentationManag
   }
 }
 
+//********************************************************************
 void ModuleBase_ResultPrs::HilightOwnerWithColor(const Handle(PrsMgr_PresentationManager3d)& thePM,
                                                  const Handle(Graphic3d_HighlightStyle)& theStyle,
                                                  const Handle(SelectMgr_EntityOwner)& theOwner)
index d9a0da37c2f1ad9d9916fb74eba139b389fcc8f8..f3c42bc9e43a007c9c16131cba51b3a8846e9b49 100644 (file)
 
 #include <ModelAPI_Result.h>
 
+#include <BRep_Builder.hxx>
+#include <NCollection_List.hxx>
 #include <ViewerData_AISShape.hxx>
 #include <Standard_DefineHandle.hxx>
-#include <StdSelect_BRepOwner.hxx>
+#include <TopoDS_Compound.hxx>
 
 #include <QMap>
 
-DEFINE_STANDARD_HANDLE(ModuleBase_BRepOwner, StdSelect_BRepOwner)
-
-/**
-* \ingroup GUI
-* A redefinition of standard BRep Owner in order to provide specific selection
-* of CompSolid objects. This owner is created only for selection mode TopAbs_COMPSOLID
-*/
-class ModuleBase_BRepOwner: public StdSelect_BRepOwner
-{
-public:
-  /// Constructor
-  /// \param aShape an owner shape
-  /// \param aPriority drawig priority
-  /// \param ComesFromDecomposition decomposition flag
-  ModuleBase_BRepOwner(const TopoDS_Shape& aShape,
-    const Standard_Integer aPriority = 0,
-    const Standard_Boolean ComesFromDecomposition = Standard_False)
-    : StdSelect_BRepOwner(aShape, aPriority, ComesFromDecomposition) {}
-
-  /// Highlight the presentation with the given color
-  /// \param aPM a presentations manager
-  /// \param theStyle a style of presentation
-  /// \param theMode a drawing mode
-  virtual void HilightWithColor (const Handle(PrsMgr_PresentationManager3d)& aPM,
-    const Handle(Graphic3d_HighlightStyle)& theStyle, const Standard_Integer theMode = 0)
-  {
-    Selectable()->HilightOwnerWithColor(aPM, theStyle, this);
-  }
-
-  DEFINE_STANDARD_RTTIEXT(ModuleBase_BRepOwner, StdSelect_BRepOwner)
-};
-
-
+class AIS_ColoredDrawer;
+class AIS_InteractiveContext;
 
 DEFINE_STANDARD_HANDLE(ModuleBase_ResultPrs, ViewerData_AISShape)
 
@@ -110,7 +81,30 @@ public:
   /// \param thePriority a new priority value
   Standard_EXPORT void setAdditionalSelectionPriority(const int thePriority);
 
+  //! Updates color of sub shape drawer
+  Standard_EXPORT virtual void SetColor (const Quantity_Color& theColor);
+
+  /// Change presentation to have given shape hidden.
+  /// It suports FACE type of the shape to be hidden.
+  /// If presentation type is greater than FACE, the SHELL with be shown with the FACE hidden
+  /// It is possible to hide more than one FACE by calling the method with given FACES
+  /// Visual state of the face is controlled by the second parameter
+  /// \param theShapes a container of shape objects
+  /// \returns true if the presentation is changed, or false (if for example it was hidden)
+  Standard_EXPORT bool setSubShapeHidden(const NCollection_List<TopoDS_Shape>& theShapes);
+
+  /// Returns true if there are no hidden sub shapes or original shape has at least one not hidden
+  /// \param theShapesToSkip container of shape to be hidden in the presentation (faces)
+  /// \return boolean value
+  Standard_EXPORT bool hasSubShapeVisible(const NCollection_List<TopoDS_Shape>& theShapesToSkip);
+
+  /// Set transparency of hidden sub shapes: if value is 1, shapes are entirely hidden
+  /// \param theTransparency transparency value
+  /// \return false if parameter is out of [0, 1]
+  Standard_EXPORT bool setHiddenSubShapeTransparency(double theTransparency);
+
   DEFINE_STANDARD_RTTIEXT(ModuleBase_ResultPrs, ViewerData_AISShape)
+
 protected:
   /// Redefinition of virtual function
   Standard_EXPORT virtual void Compute(
@@ -131,12 +125,30 @@ private:
   bool appendVertexSelection(const Handle(SelectMgr_Selection)& aSelection,
                              const Standard_Integer theMode);
 
+  /// Creates compound of vertices, edges and faces.
+  /// If the shape is COMPOUND, iterate by sub-shapes.
+  /// If the shape is SOLID/SHEL, explore shape by FACES,
+  /// If the shape is WIRE, explore shape by EDGES
+  /// \param theBuilder result compound builder
+  /// \param theCompound the result shape
+  /// \param theShape the processed shape
+  /// \param theHiddenSubShapes container of shapes to be skipped (faces)
+  void collectSubShapes(BRep_Builder& theBuilder, TopoDS_Shape& theCompound,
+    const TopoDS_Shape& theShape, const NCollection_List<TopoDS_Shape>& theHiddenSubShapes);
+
+private:
   /// Reference to result object
   ResultPtr myResult;
 
   /// Original shape of the result object
   TopoDS_Shape myOriginalShape;
 
+  /// Container of original Shape sub shape to be hidden and not selectable
+  NCollection_List<TopoDS_Shape> myHiddenSubShapes;
+  TopoDS_Compound myHiddenCompound; /// compound of hidden sub shapes
+  double myTransparency; ///< transparency of hidden shapes, where 0 - there is no transparency
+  Handle(AIS_ColoredDrawer) myHiddenSubShapesDrawer; ///< drawer for hidden sub shapes
+
   /// selection priority that will be added to the standard
   /// selection priority of the selection entity
   int myAdditionalSelectionPriority;
index dbf0f252b4d8461e7697f871ab242ea101f22b11..bd3c855cc0b8628317c957ba05a751613bc25d9b 100755 (executable)
@@ -27,6 +27,7 @@
 #include <ModuleBase_IModule.h>
 #include <ModuleBase_IconFactory.h>
 #include <ModuleBase_ResultPrs.h>
+#include <ModuleBase_ViewerPrs.h>
 
 #include <ModelAPI_Attribute.h>
 #include <ModelAPI_AttributeRefAttr.h>
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Events.h>
+#include <ModelAPI_Folder.h>
 
 #include <ModelGeomAlgo_Point2D.h>
 
+#include <StdSelect_BRepOwner.hxx>
 #include <TopoDS_Iterator.hxx>
 
 #include <GeomDataAPI_Point2D.h>
@@ -372,20 +375,24 @@ int shapeType(const QString& theType)
 }
 
 void checkObjects(const QObjectPtrList& theObjects, bool& hasResult, bool& hasFeature,
-                  bool& hasParameter, bool& hasCompositeOwner, bool& hasResultInHistory)
+                  bool& hasParameter, bool& hasCompositeOwner, bool& hasResultInHistory,
+                  bool& hasFolder)
 {
   hasResult = false;
   hasFeature = false;
   hasParameter = false;
   hasCompositeOwner = false;
   hasResultInHistory = false;
+  hasFolder = false;
   foreach(ObjectPtr aObj, theObjects) {
     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
+    FolderPtr aFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(aObj);
     ResultParameterPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aResult);
 
     hasResult |= (aResult.get() != NULL);
     hasFeature |= (aFeature.get() != NULL);
+    hasFolder |= (aFolder.get() != NULL);
     hasParameter |= (aConstruction.get() != NULL);
     if (hasFeature)
       hasCompositeOwner |= (ModelAPI_Tools::compositeOwner(aFeature) != NULL);
@@ -395,7 +402,7 @@ void checkObjects(const QObjectPtrList& theObjects, bool& hasResult, bool& hasFe
       hasResultInHistory = aFeature.get() && aFeature->isInHistory();
     }
 
-    if (hasFeature && hasResult  && hasParameter && hasCompositeOwner)
+    if (hasFeature && hasResult  && hasParameter && hasCompositeOwner && hasFeature)
       break;
   }
 }
@@ -511,6 +518,18 @@ TopAbs_ShapeEnum getCompoundSubType(const TopoDS_Shape& theShape)
   return aShapeType;
 }
 
+TopoDS_Shape getSelectedShape(const std::shared_ptr<ModuleBase_ViewerPrs>& thePrs)
+{
+  if (thePrs->shape().get())
+    return thePrs->shape()->impl<TopoDS_Shape>();
+
+  Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast(thePrs->owner());
+  if (!anOwner.IsNull())
+    return anOwner->Shape();
+
+  return TopoDS_Shape();
+}
+
 void getParameters(QStringList& theParameters)
 {
   theParameters.clear();
@@ -1039,10 +1058,26 @@ void convertToFeatures(const QObjectPtrList& theObjects, std::set<FeaturePtr>& t
     if (!aFeature.get() && anObject->groupName() == ModelAPI_ResultParameter::group()) {
       aFeature = ModelAPI_Feature::feature(anObject);
     }
-    theFeatures.insert(aFeature);
+    if (aFeature.get())
+      theFeatures.insert(aFeature);
   }
 }
 
+//**************************************************************
+void convertToFolders(const QObjectPtrList& theObjects,
+                                         std::set<FolderPtr>& theFolders)
+{
+  QObjectPtrList::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();
+  for(; anIt != aLast; anIt++) {
+    ObjectPtr anObject = *anIt;
+    FolderPtr aFeature = std::dynamic_pointer_cast<ModelAPI_Folder>(anObject);
+    if (aFeature.get())
+      theFolders.insert(aFeature);
+  }
+}
+
+
+//**************************************************************
 QString translate(const Events_InfoMessage& theMessage)
 {
   QString aMessage;
index 0c46f52dcea7bd3ea01ae2ca95829d1571146226..0cd2ed2dc815842b1185cb53b6e01cb8b30c24ac 100755 (executable)
@@ -26,6 +26,7 @@
 
 #include <ModelAPI_Attribute.h>
 #include <ModelAPI_Feature.h>
+#include <ModelAPI_Folder.h>
 
 #include <TopAbs_ShapeEnum.hxx>
 #include <TopoDS_Shape.hxx>
@@ -44,9 +45,10 @@ class QWidget;
 class QLayout;
 class QDoubleSpinBox;
 class QAction;
+class ModuleBase_IWorkshop;
 class ModuleBase_ParamIntSpinBox;
 class ModuleBase_ParamSpinBox;
-class ModuleBase_IWorkshop;
+class ModuleBase_ViewerPrs;
 
 class GeomAPI_Shape;
 
@@ -176,9 +178,10 @@ MODULEBASE_EXPORT bool isSubResult(ObjectPtr theObject);
 /// \param hasParameter will be set to true if list contains Parameter objects
 /// \param hasCompositeOwner will be set to true if list contains Sub-Feature objects
 /// \param hasResultInHistory will be set to true if one of result is in history
+/// \param hasFolder will be set to true if one of folder is in the list
 MODULEBASE_EXPORT void checkObjects(const QObjectPtrList& theObjects, bool& hasResult,
                            bool& hasFeature, bool& hasParameter, bool& hasCompositeOwner,
-                           bool& hasResultInHistory);
+                           bool& hasResultInHistory, bool& hasFolder);
 
 /// Sets the default coeffient into the driver calculated accordingly the shape type.
 /// It provides 1.e-4 for results of construction type
@@ -210,6 +213,12 @@ MODULEBASE_EXPORT ObjectPtr getObject(const AttributePtr& theAttribute);
 /// \param theObj an object
 MODULEBASE_EXPORT TopAbs_ShapeEnum getCompoundSubType(const TopoDS_Shape& theShape);
 
+/// Returns either presentation shape or shape of BREP owner if it is casted to it
+/// \param thePrs selection presentation
+/// \return shape
+MODULEBASE_EXPORT TopoDS_Shape getSelectedShape(
+  const std::shared_ptr<ModuleBase_ViewerPrs>& thePrs);
+
 /// Returns list of parameters accessible in the active part and partset
 /// \theParameters a list of parameter names
 MODULEBASE_EXPORT void getParameters(QStringList& theParameters);
@@ -331,6 +340,13 @@ void MODULEBASE_EXPORT convertToFeatures(const QObjectPtrList& theObjects,
                                          std::set<FeaturePtr>& theFeatures);
 
 
+/// Converts a list of objects to set of folders.
+/// \param theObjects a list of objects
+/// \param theFeatures an out conteiner of features
+void MODULEBASE_EXPORT convertToFolders(const QObjectPtrList& theObjects,
+                                         std::set<FolderPtr>& theFolders);
+
+
 /// Returns translation from the given data.
 /// If translation is not exists then it returns a string
 /// from the info data without translation
index 3eaa15c2c0086b93b1949fd52736d07bcfd0a229..3d4d446e616c5057711b2f7ec1a3583dd3f62816 100644 (file)
@@ -21,6 +21,7 @@
 #include "ModuleBase_ViewerPrs.h"
 
 #include <ModuleBase_ResultPrs.h>
+#include <StdSelect_BRepOwner.hxx>
 
 ModuleBase_ViewerPrs::ModuleBase_ViewerPrs(ObjectPtr theResult,
                                            const GeomShapePtr& theShape,
index 285fbe76563742ed741668300b553a85bb323903..aeebdfa1e81af6de738978d89718fdc9d12e942b 100644 (file)
@@ -110,26 +110,16 @@ bool ModuleBase_WidgetFeatureSelector::setSelectionCustom(const ModuleBase_Viewe
 }
 
 //********************************************************************
-void ModuleBase_WidgetFeatureSelector::deactivate()
+void ModuleBase_WidgetFeatureSelector::selectionModes(int& theModuleSelectionModes,
+                                                      QIntList& theModes)
 {
-  ModuleBase_ModelWidget::deactivate();
-  disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
-  activateFilters(false);
-  myWorkshop->deactivateSubShapesSelection();
+  theModuleSelectionModes = -1;
+  theModes.push_back(ModuleBase_ResultPrs::Sel_Result);
 }
 
 //********************************************************************
 void ModuleBase_WidgetFeatureSelector::activateCustom()
 {
-  connect(myWorkshop, SIGNAL(selectionChanged()), this,
-          SLOT(onSelectionChanged()), Qt::UniqueConnection);
-
-  activateFilters(true);
-
-  QIntList aShapeTypes;
-  aShapeTypes.push_back(ModuleBase_ResultPrs::Sel_Result);
-  myWorkshop->activateSubShapesSelection(aShapeTypes);
-
   // Restore selection in the viewer by the attribute selection list
   // it should be postponed to have current widget as active to validate restored selection
   //static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION);
@@ -219,13 +209,15 @@ bool ModuleBase_WidgetFeatureSelector::isValidInFilters(const ModuleBase_ViewerP
 }
 
 //********************************************************************
-void ModuleBase_WidgetFeatureSelector::onSelectionChanged()
+bool ModuleBase_WidgetFeatureSelector::processSelection()
 {
   QList<ModuleBase_ViewerPrsPtr> aSelected = myWorkshop->selection()->getSelected(
                                                               ModuleBase_ISelection::AllControls);
 
   bool isDone = setSelection(aSelected, true/*false*/);
   updateOnSelectionChanged(isDone);
+
+  return isDone;
 }
 
 //********************************************************************
index 606fc1dad25d6b0be52f3e903404c5a819a39697..f4166d35b66277c75e66d779677c04a31482f160 100644 (file)
@@ -68,6 +68,11 @@ Q_OBJECT
   virtual bool setSelection(QList<std::shared_ptr<ModuleBase_ViewerPrs>>& theValues,
                             const bool theToValidate);
 
+  /// Fills given container with selection modes if the widget has it
+  /// \param [out] theModuleSelectionModes module additional modes, -1 means all default modes
+  /// \param theModes [out] a container of modes
+  virtual void selectionModes(int& theModuleSelectionModes, QIntList& theModes);
+
   /// Returns list of widget controls
   /// \return a control list
   virtual QList<QWidget*> getControls() const;
@@ -76,9 +81,6 @@ Q_OBJECT
   /// \param thePrs a selected owner
   virtual bool setSelectionCustom(const std::shared_ptr<ModuleBase_ViewerPrs>& thePrs);
 
-  /// The method called when widget is deactivated
-  virtual void deactivate();
-
 protected:
   /// The method called when widget is activated
   virtual void activateCustom();
@@ -104,9 +106,9 @@ protected:
   /// \param theDone a state whether the selection is set
   virtual void updateOnSelectionChanged(const bool theDone);
 
-protected slots:
-  /// Called on selection changed event
-  virtual void onSelectionChanged();
+protected:
+  /// Returns true if envent is processed.
+  virtual bool processSelection();
 
   //----------- Class members -------------
 protected:
index e59721ff6a18463d13a9fe7b528017b1a77f22d0..48df5b61bb2a5110692ae7320075bb9bae2fcb3a 100755 (executable)
 //
 
 #include <ModuleBase_WidgetMultiSelector.h>
-#include <ModuleBase_WidgetShapeSelector.h>
+
+#include <ModuleBase_ActionIntParameter.h>
+#include <ModuleBase_Definitions.h>
+#include <ModuleBase_Events.h>
+#include <ModuleBase_IconFactory.h>
+#include <ModuleBase_IModule.h>
 #include <ModuleBase_ISelection.h>
-#include <ModuleBase_IWorkshop.h>
+#include <ModuleBase_ISelectionActivate.h>
 #include <ModuleBase_IPropertyPanel.h>
 #include <ModuleBase_IViewer.h>
+#include <ModuleBase_IWorkshop.h>
+#include <ModuleBase_ListView.h>
 #include <ModuleBase_Tools.h>
-#include <ModuleBase_Definitions.h>
-#include <ModuleBase_IModule.h>
 #include <ModuleBase_ViewerPrs.h>
-#include <ModuleBase_IconFactory.h>
-#include <ModuleBase_Events.h>
+#include <ModuleBase_WidgetShapeSelector.h>
 #include <ModuleBase_ChoiceCtrl.h>
 
 #include <ModelAPI_Data.h>
@@ -49,7 +53,6 @@
 #include <QString>
 #include <QComboBox>
 #include <QEvent>
-#include <QAction>
 #include <QApplication>
 #include <QClipboard>
 #include <QTimer>
 #include <memory>
 #include <string>
 
-const int ATTRIBUTE_SELECTION_INDEX_ROLE = Qt::UserRole + 1;
-
 //#define DEBUG_UNDO_REDO
 
-/**
-* Customization of a List Widget to make it to be placed on full width of container
-*/
-class CustomListWidget : public QListWidget
-{
-public:
-  /// Constructor
-  /// \param theParent a parent widget
-  CustomListWidget( QWidget* theParent )
-    : QListWidget( theParent )
-  {
-  }
-
-  /// Redefinition of virtual method
-  virtual QSize        sizeHint() const
-  {
-    int aHeight = 2*QFontMetrics( font() ).height();
-    QSize aSize = QListWidget::sizeHint();
-    return QSize( aSize.width(), aHeight );
-  }
-
-  /// Redefinition of virtual method
-  virtual QSize        minimumSizeHint() const
-  {
-    int aHeight = 4/*2*/*QFontMetrics( font() ).height();
-    QSize aSize = QListWidget::minimumSizeHint();
-    return QSize( aSize.width(), aHeight );
-  }
-
-#ifndef WIN32
-// The code is necessary only for Linux because
-//it can not update viewport on widget resize
-protected:
-  void resizeEvent(QResizeEvent* theEvent)
-  {
-    QListWidget::resizeEvent(theEvent);
-    QTimer::singleShot(5, viewport(), SLOT(repaint()));
-  }
-#endif
-};
-
 #ifdef DEBUG_UNDO_REDO
 void printHistoryInfo(const QString& theMethodName, int theCurrentHistoryIndex,
   QList<QList<std::shared_ptr<ModuleBase_ViewerPrs> > > theSelectedHistoryValues)
@@ -181,33 +141,18 @@ ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParen
   }
 
   QString aToolTip = QString::fromStdString(theData->widgetTooltip());
-  myListControl = new CustomListWidget(this);
   QString anObjName = QString::fromStdString(attributeID());
-  myListControl->setObjectName(anObjName);
-  myListControl->setToolTip(aToolTip);
-  myListControl->setSelectionMode(QAbstractItemView::ExtendedSelection);
+  myListView = new ModuleBase_ListView(this, anObjName, aToolTip);
+  connect(myListView->getControl(), SIGNAL(itemSelectionChanged()), SLOT(onListSelection()));
+  connect(myListView, SIGNAL(deleteActionClicked()), SLOT(onDeleteItem()));
 
-  aMainLay->addWidget(myListControl, 2, 0, 1, -1);
+  aMainLay->addWidget(myListView->getControl(), 2, 0, 1, -1);
   aMainLay->setRowStretch(2, 1);
   //aMainLay->addWidget(new QLabel(this)); //FIXME(sbh)???
   //aMainLay->setRowMinimumHeight(3, 20);
   //this->setLayout(aMainLay);
   connect(myTypeCtrl, SIGNAL(valueChanged(int)), this, SLOT(onSelectionTypeChanged()));
 
-  myCopyAction = ModuleBase_Tools::createAction(QIcon(":pictures/copy.png"), tr("Copy"),
-                          myWorkshop->desktop(), this, SLOT(onCopyItem()));
-  myCopyAction->setShortcut(QKeySequence::Copy);
-  myCopyAction->setEnabled(false);
-  myListControl->addAction(myCopyAction);
-
-  myDeleteAction = ModuleBase_Tools::createAction(QIcon(":pictures/delete.png"), tr("Delete"),
-                          myWorkshop->desktop(), this, SLOT(onDeleteItem()));
-  myDeleteAction->setEnabled(false);
-  myListControl->addAction(myDeleteAction);
-
-  myListControl->setContextMenuPolicy(Qt::ActionsContextMenu);
-  connect(myListControl, SIGNAL(itemSelectionChanged()), SLOT(onListSelection()));
-
   myIsNeutralPointClear = theData->getBooleanAttribute("clear_in_neutral_point", true);
 }
 
@@ -223,7 +168,6 @@ void ModuleBase_WidgetMultiSelector::activateCustom()
   myWorkshop->module()->activateCustomPrs(myFeature,
                             ModuleBase_IModule::CustomizeHighlightedObjects, true);
   clearSelectedHistory();
-  myWorkshop->updateCommandStatus();
 }
 
 //********************************************************************
@@ -233,6 +177,19 @@ void ModuleBase_WidgetMultiSelector::deactivate()
 
   myWorkshop->module()->deactivateCustomPrs(ModuleBase_IModule::CustomizeHighlightedObjects, true);
   clearSelectedHistory();
+}
+
+//********************************************************************
+void ModuleBase_WidgetMultiSelector::updateAfterDeactivation()
+{
+  // restore previous Undo/Redo workshop state
+  myWorkshop->updateCommandStatus();
+}
+
+//********************************************************************
+void ModuleBase_WidgetMultiSelector::updateAfterActivation()
+{
+  // fill Undo/Redo actions with current information
   myWorkshop->updateCommandStatus();
 }
 
@@ -365,21 +322,26 @@ bool ModuleBase_WidgetMultiSelector::canProcessAction(ModuleBase_ActionType theA
     }
     break;
     default:
+      aCanProcess = ModuleBase_WidgetSelector::canProcessAction(theActionType, isActionEnabled);
     break;
   }
   return aCanProcess;
 }
 
 //********************************************************************
-bool ModuleBase_WidgetMultiSelector::processAction(ModuleBase_ActionType theActionType)
+bool ModuleBase_WidgetMultiSelector::processAction(ModuleBase_ActionType theActionType,
+                                                   const ActionParamPtr& theParam)
 {
   switch (theActionType) {
     case ActionUndo:
     case ActionRedo: {
+      ActionIntParamPtr aParam =
+        std::dynamic_pointer_cast<ModuleBase_ActionIntParameter>(theParam);
+      int aNb = aParam->value();
       if (theActionType == ActionUndo)
-        myCurrentHistoryIndex--;
+        myCurrentHistoryIndex -= aNb;
       else
-        myCurrentHistoryIndex++;
+        myCurrentHistoryIndex += aNb;
       QList<ModuleBase_ViewerPrsPtr> aSelected = mySelectedHistoryValues[myCurrentHistoryIndex];
       // equal vertices should not be used here
       ModuleBase_ISelection::filterSelectionOnEqualPoints(aSelected);
@@ -395,17 +357,10 @@ bool ModuleBase_WidgetMultiSelector::processAction(ModuleBase_ActionType theActi
       return true;
     }
     default:
-      return ModuleBase_ModelWidget::processAction(theActionType);
+      return ModuleBase_ModelWidget::processAction(theActionType, theParam);
   }
 }
 
-//********************************************************************
-bool ModuleBase_WidgetMultiSelector::activateSelectionAndFilters(bool toActivate)
-{
-  myWorkshop->updateCommandStatus(); // update enable state of Undo/Redo application actions
-  return ModuleBase_WidgetSelector::activateSelectionAndFilters(toActivate);
-}
-
 //********************************************************************
 bool ModuleBase_WidgetMultiSelector::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs)
 {
@@ -443,7 +398,7 @@ bool ModuleBase_WidgetMultiSelector::processDelete()
   std::set<int> anAttributeIds;
   getSelectedAttributeIndices(anAttributeIds);
 
-  QModelIndexList aIndexes = myListControl->selectionModel()->selectedIndexes();
+  QModelIndexList anIndices = myListView->getControl()->selectionModel()->selectedIndexes();
 
   // refill attribute by the items which indices are not in the list of ids
   bool aDone = false;
@@ -480,17 +435,8 @@ bool ModuleBase_WidgetMultiSelector::processDelete()
   }
 
   // Restore selection
-  int aRows = myListControl->model()->rowCount();
-  if (aRows > 0) {
-    foreach(QModelIndex aIndex, aIndexes) {
-      if (aIndex.row() < aRows)
-        myListControl->selectionModel()->select(aIndex, QItemSelectionModel::Select);
-      else {
-        QModelIndex aIdx = myListControl->model()->index(aRows - 1, 0);
-        myListControl->selectionModel()->select(aIdx, QItemSelectionModel::Select);
-      }
-    }
-  }
+  myListView->restoreSelection(anIndices);
+
   appendSelectionInHistory();
   return aDone;
 }
@@ -499,14 +445,20 @@ bool ModuleBase_WidgetMultiSelector::processDelete()
 QList<QWidget*> ModuleBase_WidgetMultiSelector::getControls() const
 {
   QList<QWidget*> result;
-  result << myListControl;
+  result << myListView->getControl();
   return result;
 }
 
 //********************************************************************
 void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
 {
-  activateSelectionAndFilters(true);
+  // Clear current selection in order to avoid updating of object browser with obsolete indexes
+  // which can appear because of results deletetion after changing a type of selection
+  QList<ModuleBase_ViewerPrsPtr> aEmptyList;
+  myWorkshop->setSelected(aEmptyList);
+
+  updateSelectionModesAndFilters(true);
+  myWorkshop->selectionActivate()->updateSelectionModes();
 
   if (!myFeature)
     return;
@@ -550,7 +502,7 @@ void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
 }
 
 //********************************************************************
-void ModuleBase_WidgetMultiSelector::onSelectionChanged()
+bool ModuleBase_WidgetMultiSelector::processSelection()
 {
   if (!myIsNeutralPointClear) {
     QList<ModuleBase_ViewerPrsPtr> aSelected = getFilteredSelected();
@@ -562,13 +514,14 @@ void ModuleBase_WidgetMultiSelector::onSelectionChanged()
         static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION);
         ModelAPI_EventCreator::get()->sendUpdated(myFeature, anEvent);
         Events_Loop::loop()->flush(anEvent);
-        return;
+        return true;
       }
     }
   }
   appendFirstSelectionInHistory();
-  ModuleBase_WidgetSelector::onSelectionChanged();
+  bool aDone = ModuleBase_WidgetSelector::processSelection();
   appendSelectionInHistory();
+  return aDone;
 }
 
 void ModuleBase_WidgetMultiSelector::appendFirstSelectionInHistory()
@@ -613,7 +566,7 @@ void ModuleBase_WidgetMultiSelector::updateFocus()
 {
   // Set focus to List control in order to make possible
   // to use Tab key for transfer the focus to next widgets
-  ModuleBase_Tools::setFocus(myListControl,
+  ModuleBase_Tools::setFocus(myListView->getControl(),
                              "ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()");
 }
 
@@ -670,12 +623,11 @@ void ModuleBase_WidgetMultiSelector::setCurrentShapeType(const int theShapeType)
   foreach (QString aShapeTypeName, myShapeTypes) {
     int aRefType = ModuleBase_Tools::shapeType(aShapeTypeName);
     if(aRefType == theShapeType && idx != myTypeCtrl->value()) {
-      bool aWasActivated = activateSelectionAndFilters(false);
+      updateSelectionModesAndFilters(false);
       bool isBlocked = myTypeCtrl->blockSignals(true);
       myTypeCtrl->setValue(idx);
       myTypeCtrl->blockSignals(isBlocked);
-      if (aWasActivated)
-        activateSelectionAndFilters(true);
+      updateSelectionModesAndFilters(true);
       break;
     }
     idx++;
@@ -692,7 +644,7 @@ QList<ModuleBase_ViewerPrsPtr> ModuleBase_WidgetMultiSelector::getAttributeSelec
 //********************************************************************
 void ModuleBase_WidgetMultiSelector::updateSelectionList()
 {
-  myListControl->clear();
+  myListView->getControl()->clear();
 
   DataPtr aData = myFeature->data();
   AttributePtr anAttribute = aData->attribute(attributeID());
@@ -701,9 +653,7 @@ void ModuleBase_WidgetMultiSelector::updateSelectionList()
     AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID());
     for (int i = 0; i < aSelectionListAttr->size(); i++) {
       AttributeSelectionPtr aAttr = aSelectionListAttr->value(i);
-      QListWidgetItem* anItem = new QListWidgetItem(aAttr->namingName().c_str(), myListControl);
-      anItem->setData(ATTRIBUTE_SELECTION_INDEX_ROLE, i);
-      myListControl->addItem(anItem);
+      myListView->addItem(aAttr->namingName().c_str(), i);
     }
   }
   else if (aType == ModelAPI_AttributeRefList::typeId()) {
@@ -711,10 +661,7 @@ void ModuleBase_WidgetMultiSelector::updateSelectionList()
     for (int i = 0; i < aRefListAttr->size(); i++) {
       ObjectPtr anObject = aRefListAttr->object(i);
       if (anObject.get()) {
-        QListWidgetItem* anItem = new QListWidgetItem(anObject->data()->name().c_str(),
-                                                      myListControl);
-        anItem->setData(ATTRIBUTE_SELECTION_INDEX_ROLE, i);
-        myListControl->addItem(anItem);
+        myListView->addItem(anObject->data()->name().c_str(), i);
       }
     }
   }
@@ -733,14 +680,12 @@ void ModuleBase_WidgetMultiSelector::updateSelectionList()
           aName = anObject->data()->name().c_str();
         }
       }
-      QListWidgetItem* anItem = new QListWidgetItem(aName, myListControl);
-      anItem->setData(ATTRIBUTE_SELECTION_INDEX_ROLE, i);
-      myListControl->addItem(anItem);
+      myListView->addItem(aName, i);
     }
   }
 
   // We have to call repaint because sometimes the List control is not updated
-  myListControl->repaint();
+  myListView->getControl()->repaint();
 }
 
 //********************************************************************
@@ -768,29 +713,13 @@ void ModuleBase_WidgetMultiSelector::clearSelection()
 
   QList<ModuleBase_ViewerPrsPtr> anEmptyList;
   // This method will call Selection changed event which will call onSelectionChanged
-  // To clear mySelection, myListControl and storeValue()
+  // To clear mySelection, myListView and storeValue()
   // So, we don't need to call it
   myWorkshop->setSelected(anEmptyList);
 
   myIsNeutralPointClear = isClearInNeutralPoint;
 }
 
-//********************************************************************
-void ModuleBase_WidgetMultiSelector::onCopyItem()
-{
-  QList<QListWidgetItem*> aItems = myListControl->selectedItems();
-  QString aRes;
-  foreach(QListWidgetItem* aItem, aItems) {
-    if (!aRes.isEmpty())
-      aRes += "\n";
-    aRes += aItem->text();
-  }
-  if (!aRes.isEmpty()) {
-    QClipboard *clipboard = QApplication::clipboard();
-    clipboard->setText(aRes);
-  }
-}
-
 //********************************************************************
 void ModuleBase_WidgetMultiSelector::onDeleteItem()
 {
@@ -800,10 +729,6 @@ void ModuleBase_WidgetMultiSelector::onDeleteItem()
 //********************************************************************
 void ModuleBase_WidgetMultiSelector::onListSelection()
 {
-  QList<QListWidgetItem*> aItems = myListControl->selectedItems();
-  myCopyAction->setEnabled(!aItems.isEmpty());
-  myDeleteAction->setEnabled(!aItems.isEmpty());
-
   myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeHighlightedObjects,
                                         true);
 }
@@ -811,12 +736,7 @@ void ModuleBase_WidgetMultiSelector::onListSelection()
 //********************************************************************
 void ModuleBase_WidgetMultiSelector::getSelectedAttributeIndices(std::set<int>& theAttributeIds)
 {
-  QList<QListWidgetItem*> aItems = myListControl->selectedItems();
-  foreach(QListWidgetItem* anItem, aItems) {
-    int anIndex = anItem->data(ATTRIBUTE_SELECTION_INDEX_ROLE).toInt();
-    if (theAttributeIds.find(anIndex) == theAttributeIds.end())
-      theAttributeIds.insert(anIndex);
-  }
+  myListView->getSelectedIndices(theAttributeIds);
 }
 
 void ModuleBase_WidgetMultiSelector::convertIndicesToViewerSelection(std::set<int> theAttributeIds,
@@ -1002,3 +922,47 @@ bool ModuleBase_WidgetMultiSelector::findInSelection(const ObjectPtr& theObject,
   }
   return aFound;
 }
+
+QList<ActionInfo>
+  ModuleBase_WidgetMultiSelector::actionsList(ModuleBase_ActionType theActionType) const
+{
+  QList<ActionInfo> aList;
+  if (myCurrentHistoryIndex > -1) {
+    int i = 0;
+    QString aTitle("Selection %1 items");
+    QString aTit("Selection %1 item");
+    QIcon aIcon(":pictures/selection.png");
+    int aNb;
+    switch (theActionType) {
+    case ActionUndo:
+      i = 1;
+      while (i <= myCurrentHistoryIndex) {
+        aNb = mySelectedHistoryValues.at(i).count();
+        if (aNb == 1) {
+          ActionInfo aInfo(aIcon, aTit.arg(aNb));
+          aList.insert(0, aInfo);
+        } else {
+          ActionInfo aInfo(aIcon, aTitle.arg(aNb));
+          aList.insert(0, aInfo);
+        }
+        i++;
+      }
+      break;
+    case ActionRedo:
+      i = mySelectedHistoryValues.length() - 1;
+      while (i > myCurrentHistoryIndex) {
+        aNb = mySelectedHistoryValues.at(i).count();
+        if (aNb == 1) {
+          ActionInfo aInfo(aIcon, aTit.arg(mySelectedHistoryValues.at(i).count()));
+          aList.insert(0, aInfo);
+        } else {
+          ActionInfo aInfo(aIcon, aTitle.arg(mySelectedHistoryValues.at(i).count()));
+          aList.insert(0, aInfo);
+        }
+        i--;
+      }
+      break;
+    }
+  }
+  return aList;
+}
\ No newline at end of file
index c8dcdf66ffa3fa42e18e427209b2ca25b50c1201..be8bfee91b49e97f17b64547ae34905ea152ba91 100755 (executable)
 #include <QMap>
 
 class QWidget;
-class QListWidget;
 //class QComboBox;
+class ModuleBase_ListView;
 class ModuleBase_IWorkshop;
-class QAction;
 class ModuleBase_ChoiceCtrl;
 
-
 /**
 * \ingroup GUI
 * Implementation of widget for shapes selection. This widget provides selection of several shapes.
@@ -78,6 +76,12 @@ class MODULEBASE_EXPORT ModuleBase_WidgetMultiSelector : public ModuleBase_Widge
   /// The methiod called when widget is deactivated
   virtual void deactivate();
 
+  /// Update Undo/Redo actions state
+  virtual void updateAfterDeactivation();
+
+  /// Update Undo/Redo actions state
+  virtual void updateAfterActivation();
+
   /// Set the given wrapped value to the current widget
   /// This value should be processed in the widget according to the needs
   /// \param theValues the wrapped selection values
@@ -95,29 +99,28 @@ class MODULEBASE_EXPORT ModuleBase_WidgetMultiSelector : public ModuleBase_Widge
   virtual bool canProcessAction(ModuleBase_ActionType theActionType, bool& isActionEnabled);
 
   /// Returns true if the event is processed. The default implementation is empty, returns false.
-  virtual bool processAction(ModuleBase_ActionType theActionType);
-
-  /// Activate or deactivate selection and selection filters
-  /// \return true if the selection filter of the widget is activated in viewer context
-  virtual bool activateSelectionAndFilters(bool toActivate);
+  virtual bool processAction(ModuleBase_ActionType theActionType,
+                             const ActionParamPtr& theParam = ActionParamPtr());
 
   /// Checks the widget validity. By default, it returns true.
   /// \param thePrs a selected presentation in the view
   /// \return a boolean value
   virtual bool isValidSelectionCustom(const std::shared_ptr<ModuleBase_ViewerPrs>& thePrs);
 
+  /// Returns list of accessible actions for Undo/Redo commands. By default it returns empty list.
+  /// \param theActionType type of action. It can be ActionUndo or ActionRedo.
+  virtual QList<ActionInfo> actionsList(ModuleBase_ActionType theActionType) const;
+
 public slots:
   /// Slot is called on selection type changed
   void onSelectionTypeChanged();
 
-  /// Slot which is called on selection event. Redefined to process XML state about
-  /// clear selection in neutral point
-  virtual void onSelectionChanged();
+protected:
+  /// Returns true if envent is processed.
+  /// Redefined to process XML state about clear selection in neutral point
+  virtual bool processSelection();
 
 protected slots:
-  /// Slot for copy command in a list pop-up menu
-  void onCopyItem();
-
   /// Slot for delete command in a list pop-up menu
   void onDeleteItem();
 
@@ -216,26 +219,15 @@ protected:
                             ModuleBase_IWorkshop* theWorkshop);
 
 protected:
-  /// List control
-  QListWidget* myListControl;
+  ModuleBase_ListView* myListView; ///< List control
+
+  bool myIsUseChoice; ///< A flag to store use_choice parameter state
 
-  QStringList myShapeTypes;
+  QStringList myShapeTypes; ///< List of Shape types defined in XML
 
   /// Control for types
   ModuleBase_ChoiceCtrl* myTypeCtrl;
 
-  /// Provides correspondance between Result object and its shape
-  typedef QPair<ResultPtr, GeomShapePtr> GeomSelection;
-
-  /// A copy action for pop-up menu in a list control
-  QAction* myCopyAction;
-
-  /// A delete action for pop-up menu in a list control
-  QAction* myDeleteAction;
-
-  /// A flag to store use_choice parameter state
-  bool myIsUseChoice;
-
   /// A flag to clear selection by click in empty place in the viewer
   bool myIsNeutralPointClear;
 
index bb4bbc4a110d0ce01d5f04feb28cb47c018878c3..673f0e18cbdab9425c7f00bc80b65445019c9e6f 100755 (executable)
 
 #include <ModuleBase_WidgetSelector.h>
 
+#include <ModuleBase_Events.h>
+#include <ModuleBase_IModule.h>
 #include <ModuleBase_ISelection.h>
+#include <ModuleBase_ISelectionActivate.h>
 #include <ModuleBase_IWorkshop.h>
-#include <ModuleBase_Tools.h>
 #include <ModuleBase_Operation.h>
 #include <ModuleBase_OperationDescription.h>
-#include <ModuleBase_WidgetFactory.h>
-#include <ModuleBase_IModule.h>
 #include <ModuleBase_ResultPrs.h>
+#include <ModuleBase_Tools.h>
 #include <ModuleBase_ViewerPrs.h>
-#include <ModuleBase_Events.h>
+#include <ModuleBase_WidgetFactory.h>
 
-#include <ModelAPI_ResultConstruction.h>
-#include <ModelAPI_Events.h>
 #include <ModelAPI_AttributeSelection.h>
 #include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_Events.h>
+#include <ModelAPI_ResultConstruction.h>
 
 #include <TopoDS_Iterator.hxx>
 
@@ -61,7 +62,7 @@ void ModuleBase_WidgetSelector::getGeomSelection(const ModuleBase_ViewerPrsPtr&
 }
 
 //********************************************************************
-void ModuleBase_WidgetSelector::onSelectionChanged()
+bool ModuleBase_WidgetSelector::processSelection()
 {
   QList<ModuleBase_ViewerPrsPtr> aSelected = getFilteredSelected();
   // equal vertices should not be used here
@@ -69,6 +70,8 @@ void ModuleBase_WidgetSelector::onSelectionChanged()
 
   bool isDone = setSelection(aSelected, true/*false*/);
   updateOnSelectionChanged(isDone);
+
+  return isDone;
 }
 
 //********************************************************************
@@ -162,26 +165,27 @@ bool ModuleBase_WidgetSelector::acceptSubShape(const GeomShapePtr& theShape,
 }
 
 //********************************************************************
-bool ModuleBase_WidgetSelector::activateSelectionAndFilters(bool toActivate)
+void ModuleBase_WidgetSelector::selectionModes(int& theModuleSelectionModes, QIntList& theModes)
+{
+  theModuleSelectionModes = -1;
+  theModes.append(getShapeTypes());
+}
+
+//********************************************************************
+void ModuleBase_WidgetSelector::updateSelectionModesAndFilters(bool toActivate)
 {
   updateSelectionName();
 
-  if (toActivate) {
-    myWorkshop->activateSubShapesSelection(getShapeTypes());
-  } else {
-    myWorkshop->deactivateSubShapesSelection();
-  }
-  return activateFilters(toActivate);
+  myWorkshop->selectionActivate()->updateSelectionFilters();
+  myWorkshop->selectionActivate()->updateSelectionModes();
+
+  if (!toActivate)
+    clearValidatedCash();
 }
 
 //********************************************************************
 void ModuleBase_WidgetSelector::activateCustom()
 {
-  connect(myWorkshop, SIGNAL(selectionChanged()), this,
-          SLOT(onSelectionChanged()), Qt::UniqueConnection);
-
-  activateSelectionAndFilters(true);
-
   // Restore selection in the viewer by the attribute selection list
   // it should be postponed to have current widget as active to validate restored selection
   static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION);
@@ -219,10 +223,7 @@ bool ModuleBase_WidgetSelector::setSelectionCustom(const ModuleBase_ViewerPrsPtr
 //********************************************************************
 void ModuleBase_WidgetSelector::deactivate()
 {
-  ModuleBase_ModelWidget::deactivate();
-  disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
-  activateSelectionAndFilters(false);
-
+  ModuleBase_WidgetValidated::deactivate();
   /// clear temporary cash
   AttributePtr anAttribute = attribute();
   if (!anAttribute.get())
index f6d0275787382d43876bf895226f668721fd1452..fee235ad001f6692aa031124b09b638e2ef16f70 100755 (executable)
@@ -54,12 +54,16 @@ Q_OBJECT
 
   virtual ~ModuleBase_WidgetSelector();
 
+  /// Fills given container with selection modes if the widget has it
+  /// \param [out] theModuleSelectionModes module additional modes, -1 means all default modes
+  /// \param [out] theModes a container of modes
+  virtual void selectionModes(int& theModuleSelectionModes, QIntList& theModes);
+
   /// Defines if it is supposed that the widget should interact with the viewer.
   virtual bool isViewerSelector() { return true; }
 
   /// Activate or deactivate selection and selection filters
-  /// \return true if the selection filter of the widget is activated in viewer context
-  virtual bool activateSelectionAndFilters(bool toActivate);
+  virtual void updateSelectionModesAndFilters(bool toActivate);
 
   /// Checks the widget validity. By default, it returns true.
   /// \param thePrs a selected presentation in the view
@@ -78,11 +82,10 @@ Q_OBJECT
   /// a shape. If the attribute do not uses the shape, it is empty
   virtual QList<std::shared_ptr<ModuleBase_ViewerPrs>> getAttributeSelection() const;
 
-protected slots:
-  /// Slot which is called on selection event
-  virtual void onSelectionChanged();
-
 protected:
+  /// Returns true if envent is processed. The default implementation is empty, returns false.
+  virtual bool processSelection();
+
   /// Emits model changed info, updates the current control by selection change
   /// \param theDone a state whether the selection is set
   virtual void updateOnSelectionChanged(const bool theDone);
index 11ce866e315a1f4041b013b53f520b9ee4b7211a..e60685b0cc5e2758cfd8b573ef25502d3aa1dc81 100644 (file)
 //
 
 #include <ModuleBase_WidgetValidated.h>
+#include <ModuleBase_IModule.h>
 #include <ModuleBase_IViewer.h>
 #include <ModuleBase_IWorkshop.h>
 #include <ModuleBase_ISelection.h>
+#include <ModuleBase_ISelectionActivate.h>
 #include <ModuleBase_WidgetSelectorStore.h>
 #include <ModuleBase_ViewerPrs.h>
 
@@ -64,6 +66,12 @@ ObjectPtr ModuleBase_WidgetValidated::findPresentedObject(const AISObjectPtr& th
   return myPresentedObject;
 }
 
+//********************************************************************
+void ModuleBase_WidgetValidated::deactivate()
+{
+  clearValidatedCash();
+}
+
 //********************************************************************
 void ModuleBase_WidgetValidated::clearValidatedCash()
 {
@@ -115,8 +123,13 @@ bool ModuleBase_WidgetValidated::isValidInFilters(const ModuleBase_ViewerPrsPtr&
     // the widget validator filter should be active, but during check by preselection
     // it is not yet activated, so we need to activate/deactivate it manually
     bool isActivated = isFilterActivated();
-    if (!isActivated)
-      activateFilters(true);
+    if (!isActivated) {
+      QIntList aModuleSelectionFilters = myWorkshop->module()->selectionFilters();
+      SelectMgr_ListOfFilter aSelectionFilters;
+      selectionFilters(aModuleSelectionFilters, aSelectionFilters);
+      /// after validation, the selection filters should be restored
+      myWorkshop->selectionActivate()->activateSelectionFilters(aSelectionFilters);
+    }
 
     Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
     if (!aContext.IsNull()) {
@@ -128,7 +141,11 @@ bool ModuleBase_WidgetValidated::isValidInFilters(const ModuleBase_ViewerPrsPtr&
       }
     }
     if (!isActivated)
-      activateFilters(false);
+    {
+      // reset filters set in activateSelectionFilters above
+      myWorkshop->selectionActivate()->updateSelectionFilters();
+      clearValidatedCash();
+    }
   }
 
   // removes created owner
@@ -218,6 +235,7 @@ bool ModuleBase_WidgetValidated::isValidAttribute(const AttributePtr& theAttribu
   return aFactory->validate(theAttribute, aValidatorID, anError);
 }
 
+//********************************************************************
 bool ModuleBase_WidgetValidated::isFilterActivated() const
 {
   bool isActivated = false;
@@ -228,21 +246,11 @@ bool ModuleBase_WidgetValidated::isFilterActivated() const
   return aViewer->hasSelectionFilter(aSelFilter);
 }
 
-bool ModuleBase_WidgetValidated::activateFilters(const bool toActivate)
+//********************************************************************
+void ModuleBase_WidgetValidated::selectionFilters(QIntList& theModuleSelectionFilters,
+                                                  SelectMgr_ListOfFilter& theSelectionFilters)
 {
-  ModuleBase_IViewer* aViewer = myWorkshop->viewer();
-
-  Handle(SelectMgr_Filter) aSelFilter = myWorkshop->validatorFilter();
-  bool aHasSelectionFilter = aViewer->hasSelectionFilter(aSelFilter);
-
-  if (toActivate)
-    aViewer->addSelectionFilter(aSelFilter);
-  else {
-    aViewer->removeSelectionFilter(aSelFilter);
-    clearValidatedCash();
-  }
-
-  return aHasSelectionFilter;
+  theSelectionFilters.Append(myWorkshop->validatorFilter());
 }
 
 //********************************************************************
index bd01429ed0b05ccc5e2facfefe3318aac088cba0..afff4dc673c2ead7658c88abc83d9d6a461f50b6 100644 (file)
@@ -73,6 +73,9 @@ class MODULEBASE_EXPORT ModuleBase_WidgetValidated : public ModuleBase_ModelWidg
   //! Returns data object by AIS
   ObjectPtr findPresentedObject(const AISObjectPtr& theAIS) const;
 
+  /// The method called when widget is deactivated
+  virtual void deactivate();
+
   //! Clear all validated cash in the widget
   void clearValidatedCash();
 
@@ -80,6 +83,12 @@ class MODULEBASE_EXPORT ModuleBase_WidgetValidated : public ModuleBase_ModelWidg
   /// \return boolean value
   bool isFilterActivated() const;
 
+  /// Appends into container of workshop selection filters
+  /// \param [out] theModuleSelectionFilters module additional modes, -1 means all default modes
+  /// \param [out] selection filters
+  virtual void selectionFilters(QIntList& theModuleSelectionFilters,
+                                SelectMgr_ListOfFilter& theSelectionFilters);
+
   /// Block the model flush of update and intialization of attribute
   /// \param theAttribute an attribute of blocking
   /// \param theFeature a feature
@@ -148,11 +157,6 @@ protected:
   /// \return a list of presentations
   QList<std::shared_ptr<ModuleBase_ViewerPrs>> getFilteredSelected();
 
-  /// It obtains selection filters from the workshop and activates them in the active viewer
-  /// \param toActivate a flag about activation or deactivation the filters
-  /// \return true if the selection filter of the widget is activated in viewer context
-  bool activateFilters(const bool toActivate);
-
   /// Block the model flush of update and intialization of attribute
   /// \param theAttribute an attribute of blocking
   /// \param theToBlock flag whether the model is blocked or unblocked
index 874a0f4859e9da22262477ebea03d2389265a3a1..8953db0b58970d99368ee0445692551f2adc273f 100755 (executable)
@@ -39,6 +39,13 @@ ModuleBase_WidgetValidator::~ModuleBase_WidgetValidator()
   delete myAttributeStore;
 }
 
+//********************************************************************
+void ModuleBase_WidgetValidator::selectionFilters(QIntList& theModuleSelectionFilters,
+                                                  SelectMgr_ListOfFilter& theSelectionFilters)
+{
+  theSelectionFilters.Append(myWorkshop->validatorFilter());
+}
+
 //********************************************************************
 bool ModuleBase_WidgetValidator::isValidSelection(const ModuleBase_ViewerPrsPtr& theValue)
 {
@@ -52,23 +59,6 @@ bool ModuleBase_WidgetValidator::isValidSelection(const ModuleBase_ViewerPrsPtr&
   return aValid;
 }
 
-bool ModuleBase_WidgetValidator::activateFilters(const bool toActivate)
-{
-  ModuleBase_IViewer* aViewer = myWorkshop->viewer();
-
-  Handle(SelectMgr_Filter) aSelFilter = myWorkshop->validatorFilter();
-  bool aHasSelectionFilter = aViewer->hasSelectionFilter(aSelFilter);
-
-  if (toActivate)
-    aViewer->addSelectionFilter(aSelFilter);
-  else {
-    aViewer->removeSelectionFilter(aSelFilter);
-    clearValidatedCash();
-  }
-
-  return aHasSelectionFilter;
-}
-
 void ModuleBase_WidgetValidator::storeAttributeValue(const AttributePtr& theAttribute)
 {
   myIsInValidate = true;
index 97e852d59ca2c106c50b25ee4b95bce1a687b470..8c7c927a9362e4ce3deaf512171bf929af8033be 100755 (executable)
 #ifndef ModuleBase_WidgetValidator_H_
 #define ModuleBase_WidgetValidator_H_
 
-#include <ModuleBase.h>
+#include "ModuleBase.h"
+
+#include "ModuleBase_Definitions.h"
+
+#include <SelectMgr_ListOfFilter.hxx>
 
 #include <QList>
 #include <memory>
@@ -47,6 +51,17 @@ class MODULEBASE_EXPORT ModuleBase_WidgetValidator
                              ModuleBase_IWorkshop* theWorkshop);
   virtual ~ModuleBase_WidgetValidator();
 
+  /// Fills given container with selection modes if the widget has it
+  /// \param [out] theModuleSelectionModes module additional modes, -1 means all default modes
+  /// \param theModes [out] a container of modes
+  virtual void selectionModes(int& theModuleSelectionModes, QIntList& theModes) {}
+
+  /// Appends into container of workshop selection filters
+  /// \param [out] theModuleSelectionFilters module additional modes, -1 means all default modes
+  /// \param [out] selection filters
+  virtual void selectionFilters(QIntList& theModuleSelectionFilters,
+                                SelectMgr_ListOfFilter& theSelectionFilters);
+
   /// Returns true if the validation is activated
   bool isInValidate() const { return myIsInValidate; }
 
@@ -58,11 +73,6 @@ class MODULEBASE_EXPORT ModuleBase_WidgetValidator
   /// \return a boolean value
   virtual bool isValidSelection(const std::shared_ptr<ModuleBase_ViewerPrs>& theValue);
 
-  /// It obtains selection filters from the workshop and activates them in the active viewer
-  /// \param toActivate a flag about activation or deactivation the filters
-  /// \return true if the selection filter of the widget is activated in viewer context
-  bool activateFilters(const bool toActivate);
-
     /// Creates a backup of the current values of the attribute
   /// It should be realized in the specific widget because of different
   /// parameters of the current attribute
@@ -82,14 +92,14 @@ class MODULEBASE_EXPORT ModuleBase_WidgetValidator
   /// \return true if all validators return that the attribute is valid
   bool isValidAttribute(const std::shared_ptr<ModelAPI_Attribute>& theAttribute) const;
 
+  //! Clear all validated cash in the widget
+  void clearValidatedCash();
+
 private:
   /// Returns true if the workshop validator filter has been already activated
   /// \return boolean value
   bool isFilterActivated() const;
 
-  //! Clear all validated cash in the widget
-  void clearValidatedCash();
-
   /// Gets the validity state of the presentation in an internal map.
   /// Returns true if the valid state of value is stored
   /// \param theValue a viewer presentation
@@ -106,7 +116,7 @@ protected:
   /// Reference to workshop
   ModuleBase_ModelWidget* myModelWidget; ///< the current widget to be validated
   ModuleBase_IWorkshop* myWorkshop; ///< the active workshop
-  ModuleBase_WidgetSelectorStore* myAttributeStore; //< store/restore attribute values
+  ModuleBase_WidgetSelectorStore* myAttributeStore; ///< store/restore attribute values
 
   /// cash of valid selection presentations
   QList<std::shared_ptr<ModuleBase_ViewerPrs>> myValidPrs;
index cebd78a43dae2f0407f18aea9ffe63608a60a9ec..96e10edb14c720706a7f03058c5e5c9059301d4f 100644 (file)
@@ -311,7 +311,7 @@ void ParametersPlugin_WidgetParamsMgr::updateParametersFeatures()
   int aNbFeatures = aDoc->numInternalFeatures();
   for (int i = 0; i < aNbFeatures; i++) {
     aParamFeature = aDoc->internalFeature(i);
-    if (aParamFeature->getKind() == ParametersPlugin_Parameter::ID()) {
+    if (aParamFeature && aParamFeature->getKind() == ParametersPlugin_Parameter::ID()) {
       myParametersList.append(aParamFeature);
     }
   }
index 793940ccab1e13b733d4cef8ba3c6ab6a40a1d2d..d2df7c96db9bc2c761e8249b0bb72736a6c45a6c 100755 (executable)
@@ -19,6 +19,8 @@
 //
 
 #include "PartSet_ExternalObjectsMgr.h"
+
+#include "PartSet_CenterPrs.h"
 #include "PartSet_Tools.h"
 
 #include <XGUI_Workshop.h>
@@ -83,12 +85,40 @@ ObjectPtr PartSet_ExternalObjectsMgr::externalObject(const ObjectPtr& theSelecte
   return aSelectedObject;
 }
 
+ObjectPtr PartSet_ExternalObjectsMgr::externalCenterObject(const ModuleBase_ViewerPrsPtr& thePrs,
+                                                           const CompositeFeaturePtr& theSketch,
+                                                           const bool theTemporary)
+{
+  if (!thePrs.get() || thePrs->interactive().IsNull())
+    return ObjectPtr();
+
+  Handle(PartSet_CenterPrs) aAIS = Handle(PartSet_CenterPrs)::DownCast(thePrs->interactive());
+  if (aAIS.IsNull())
+    return ObjectPtr();
+
+  gp_Pnt aPntComp = aAIS->Component()->Pnt();
+  GeomVertexPtr aVertPtr(new GeomAPI_Vertex(aPntComp.X(), aPntComp.Y(), aPntComp.Z()));
+  TopoDS_Shape aShape = aVertPtr->impl<TopoDS_Shape>();
+
+  ResultPtr aSelectedObject =
+    PartSet_Tools::findFixedObjectByExternal(aShape, aAIS->object(), theSketch);
+  if (!aSelectedObject.get())
+  {
+    FeaturePtr aCreatedFeature;
+    aSelectedObject = PartSet_Tools::createFixedByExternalCenter(aAIS->object(), aAIS->edge(),
+      aAIS->centerType(), theSketch, theTemporary, aCreatedFeature);
+    if (aCreatedFeature.get() && theTemporary)
+        myExternalObjectValidated = aCreatedFeature;
+  }
+  return aSelectedObject;
+}
+
 void PartSet_ExternalObjectsMgr::getGeomSelection(const ModuleBase_ViewerPrsPtr& thePrs,
-                                                   ObjectPtr& theObject,
-                                                   GeomShapePtr& theShape,
-                                                   ModuleBase_IWorkshop* theWorkshop,
-                                                   const CompositeFeaturePtr& theSketch,
-                                                   const bool isInValidate)
+                                                  ObjectPtr& theObject,
+                                                  GeomShapePtr& theShape,
+                                                  ModuleBase_IWorkshop* theWorkshop,
+                                                  const CompositeFeaturePtr& theSketch,
+                                                  const bool isInValidate)
 {
   FeaturePtr aSelectedFeature = ModelAPI_Feature::feature(theObject);
   std::shared_ptr<SketchPlugin_Feature> aSPFeature =
@@ -110,6 +140,9 @@ void PartSet_ExternalObjectsMgr::getGeomSelection(const ModuleBase_ViewerPrsPtr&
         if (aShape.get() != NULL && !aShape->isNull())
           anExternalObject =
             externalObject(theObject, aShape, theSketch, isInValidate);
+        if (!anExternalObject.get()) {
+          anExternalObject = externalCenterObject(thePrs, theSketch, isInValidate);
+        }
       }
       else { /// use objects of found selection
         anExternalObject = theObject;
index d506047e75ac185ba235c8a63a61b11a3757ec9c..59d0141584376fcebb1bc2e3132782859e4473ef 100755 (executable)
@@ -74,6 +74,15 @@ class PARTSET_EXPORT PartSet_ExternalObjectsMgr
   ObjectPtr externalObject(const ObjectPtr& theSelectedObject, const GeomShapePtr& theShape,
                            const CompositeFeaturePtr& theSketch, const bool theTemporary = false);
 
+  /// Finds or create and external object by selected circle center (PartSet_CenterPrs)
+  /// \param thePrs a selection
+  /// \param theSketch a current sketch
+  /// \param theTemporary the created external object is temporary, execute is not performed for it
+  /// \return the object
+  ObjectPtr externalCenterObject(const std::shared_ptr<ModuleBase_ViewerPrs>& thePrs,
+                                 const CompositeFeaturePtr& theSketch,
+                                 const bool theTemporary);
+
   // Removes the external presentation from the model
   /// \param theSketch a current sketch
   /// \param theFeature a current feature
index 0f9babdae75ef5377962558fc8b69dc8076b16a0..3de84434e2dd3942e87e923eca84b6aa602c5bf9 100644 (file)
@@ -40,6 +40,7 @@
 #include <XGUI_Tools.h>
 #include <XGUI_Displayer.h>
 #include <XGUI_Workshop.h>
+#include <XGUI_SelectionActivate.h>
 #include <XGUI_SelectionMgr.h>
 
 PartSet_ExternalPointsMgr::PartSet_ExternalPointsMgr(ModuleBase_IWorkshop* theWorkshop,
@@ -179,7 +180,8 @@ void PartSet_ExternalPointsMgr::updateCenterPresentations()
       myPresentations[aPrs->object()] = aList;
     foreach(AISObjectPtr anAIS, aList) {
       aDisplayer->displayAIS(anAIS, false);
-      aDisplayer->activateAIS(anAIS->impl<Handle(AIS_InteractiveObject)>(), TopAbs_VERTEX, false);
+      aWorkshop->selectionActivate()->activateAIS(anAIS->impl<Handle(AIS_InteractiveObject)>(),
+        TopAbs_VERTEX, false);
     }
   }
 }
index afe4fbbda47d0090db276282818800f086cda5f5..b827302b13559d7d18611103c452ef697e84c006 100644 (file)
@@ -86,6 +86,42 @@ Standard_Boolean PartSet_GlobalFilter::IsOk(const Handle(SelectMgr_EntityOwner)&
   return aValid;
 }
 
+IMPLEMENT_STANDARD_RTTIEXT(PartSet_ResultGroupNameFilter, SelectMgr_Filter);
+
+void PartSet_ResultGroupNameFilter::setGroupNames(const std::set<std::string>& theGroupNames)
+{
+  myGroupNames = theGroupNames;
+}
+
+Standard_Boolean PartSet_ResultGroupNameFilter::IsOk(
+  const Handle(SelectMgr_EntityOwner)& theOwner) const
+{
+  std::shared_ptr<GeomAPI_AISObject> aAISObj = AISObjectPtr(new GeomAPI_AISObject());
+  if (theOwner->HasSelectable()) {
+    Handle(AIS_InteractiveObject) aAisObj =
+      Handle(AIS_InteractiveObject)::DownCast(theOwner->Selectable());
+    if (!aAisObj.IsNull()) {
+      aAISObj->setImpl(new Handle(AIS_InteractiveObject)(aAisObj));
+    }
+  }
+  ObjectPtr anObject = myWorkshop->findPresentedObject(aAISObj);
+  if (!anObject.get())
+    return true;
+
+  ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
+  // result of parts belongs to PartSet document and can be selected only when PartSet
+  //  is active in order to do not select the result of the active part.
+  if (!aResult.get())
+    return true;
+
+  std::string aGroupName = aResult->groupName();// == ModelAPI_ResultPart::group()) {
+  if (myGroupNames.find(aGroupName) != myGroupNames.end())
+    return false; // the object of the filtered type is found
+
+  return true;
+}
+
+
 IMPLEMENT_STANDARD_RTTIEXT(PartSet_CirclePointFilter, SelectMgr_Filter);
 
 Standard_Boolean
index 5c24462388dff4de104997bc53610f7b9809e25d..2ceafe51793fcce958f7819096463e81b0a78a6d 100644 (file)
@@ -23,6 +23,8 @@
 
 #include <ModuleBase_ViewerFilters.h>
 
+#include <set>
+#include <string>
 
 /**
 * \class PartSet_GlobalFilter
@@ -46,6 +48,31 @@ public:
   DEFINE_STANDARD_RTTIEXT(PartSet_GlobalFilter, ModuleBase_ShapeDocumentFilter)
 };
 
+/// \class PartSet_ResultGroupNameFilter
+/// \ingroup Modules
+/// A class which filters results with groupName() result in filter parameters
+DEFINE_STANDARD_HANDLE(PartSet_ResultGroupNameFilter, SelectMgr_Filter);
+class PartSet_ResultGroupNameFilter: public SelectMgr_Filter
+{
+public:
+  /// Constructor
+  /// \param theWorkshop a pointer to workshop
+  PartSet_ResultGroupNameFilter(ModuleBase_IWorkshop* theWorkshop)
+    : SelectMgr_Filter(), myWorkshop(theWorkshop) {}
+
+  void setGroupNames(const std::set<std::string>& theGroupNames);
+
+  /// Returns True if selected presentation can be selected
+  /// \param theOwner an owner of the persentation
+  Standard_EXPORT virtual Standard_Boolean
+    IsOk(const Handle(SelectMgr_EntityOwner)& theOwner) const;
+
+  DEFINE_STANDARD_RTTIEXT(PartSet_ResultGroupNameFilter, SelectMgr_Filter)
+
+private:
+  ModuleBase_IWorkshop* myWorkshop;
+  std::set<std::string> myGroupNames;
+};
 
 /// \class PartSet_CirclePointFilter
 /// \ingroup GUI
index a4ec9046ec616feadceae2148caa2ef1629215ee..a1086076715eff6389bff1c8f3e77601688fbfd1 100755 (executable)
@@ -51,6 +51,7 @@
 #include <ModuleBase_IViewer.h>
 #include <ModuleBase_IViewWindow.h>
 #include <ModuleBase_IPropertyPanel.h>
+#include <ModuleBase_ISelectionActivate.h>
 #include <ModuleBase_WidgetChoice.h>
 #include <ModuleBase_WidgetEditor.h>
 #include <ModuleBase_WidgetValidated.h>
 #include <GeomDataAPI_Point.h>
 #include <GeomDataAPI_Dir.h>
 
-#include <XGUI_Displayer.h>
-#include <XGUI_Workshop.h>
-#include <XGUI_OperationMgr.h>
-#include <XGUI_PropertyPanel.h>
-#include <XGUI_ModuleConnector.h>
+#include <XGUI_ActiveControlMgr.h>
+#include <XGUI_ActiveControlSelector.h>
+#include <XGUI_ActionsMgr.h>
 #include <XGUI_ContextMenuMgr.h>
-#include <XGUI_Tools.h>
-#include <XGUI_ObjectsBrowser.h>
-#include <XGUI_SelectionMgr.h>
+#include <XGUI_CustomPrs.h>
 #include <XGUI_DataModel.h>
+#include <XGUI_Displayer.h>
 #include <XGUI_ErrorMgr.h>
-#include <XGUI_CustomPrs.h>
+#include <XGUI_FacesPanelSelector.h>
+#include <XGUI_ModuleConnector.h>
+#include <XGUI_ObjectsBrowser.h>
+#include <XGUI_OperationMgr.h>
+#include <XGUI_PropertyPanel.h>
 #include <XGUI_SelectionMgr.h>
-#include <XGUI_ActionsMgr.h>
+#include <XGUI_Tools.h>
+#include <XGUI_Workshop.h>
 
 #include <SketchPlugin_ConstraintAngle.h>
 #include <SketchPlugin_ConstraintLength.h>
@@ -141,6 +144,7 @@ extern "C" PARTSET_EXPORT ModuleBase_IModule* createModule(ModuleBase_IWorkshop*
   return new PartSet_Module(theWshop);
 }
 
+//******************************************************
 PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop)
 : ModuleBase_IModule(theWshop),
   myVisualLayerId(0),
@@ -169,8 +173,13 @@ PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop)
   Events_Loop* aLoop = Events_Loop::loop();
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_DOCUMENT_CHANGED));
 
-  mySelectionFilters.Append(new PartSet_GlobalFilter(myWorkshop));
-  mySelectionFilters.Append(new PartSet_FilterInfinite(myWorkshop));
+  registerSelectionFilter(SF_GlobalFilter, new PartSet_GlobalFilter(myWorkshop));
+  registerSelectionFilter(SF_FilterInfinite, new PartSet_FilterInfinite(myWorkshop));
+  Handle(PartSet_ResultGroupNameFilter) aCRFilter = new PartSet_ResultGroupNameFilter(myWorkshop);
+  std::set<std::string> aCRGroupNames;
+  aCRGroupNames.insert(ModelAPI_ResultConstruction::group());
+  aCRFilter->setGroupNames(aCRGroupNames);
+  registerSelectionFilter(SF_ResultGroupNameFilter, aCRFilter);
 
   setDefaultConstraintShown();
 
@@ -189,13 +198,20 @@ PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop)
   Config_PropManager::registerProp("Visualization", "sketch_preview_plane",
                           "Color of sketch plane", Config_Prop::Color,
                           PartSet_CustomPrs::OPERATION_SKETCH_PLANE());
+
+  Config_PropManager::registerProp("Visualization", "hidden_face_transparency",
+                                   "Hidden faces transparency",
+                                   Config_Prop::Double,
+                                   "0.8");
 }
 
+//******************************************************
 PartSet_Module::~PartSet_Module()
 {
-  SelectMgr_ListIteratorOfListOfFilter aIt(mySelectionFilters);
-  for (; aIt.More(); aIt.Next()) {
-    Handle(SelectMgr_Filter) aFilter = aIt.Value();
+  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();
   }
@@ -203,26 +219,7 @@ PartSet_Module::~PartSet_Module()
   delete myOverconstraintListener;
 }
 
-void PartSet_Module::activateSelectionFilters()
-{
-  SelectMgr_ListIteratorOfListOfFilter aIt(mySelectionFilters);
-  for (; aIt.More(); aIt.Next()) {
-    Handle(SelectMgr_Filter) aFilter = aIt.Value();
-    if (!aFilter.IsNull())
-      myWorkshop->viewer()->addSelectionFilter(aFilter);
-  }
-}
-
-void PartSet_Module::deactivateSelectionFilters()
-{
-  SelectMgr_ListIteratorOfListOfFilter aIt(mySelectionFilters);
-  for (; aIt.More(); aIt.Next()) {
-    Handle(SelectMgr_Filter) aFilter = aIt.Value();
-    if (!aFilter.IsNull())
-      myWorkshop->viewer()->removeSelectionFilter(aFilter);
-  }
-}
-
+//******************************************************
 void PartSet_Module::storeSelection()
 {
   // cash is used only to restore selection, so it should be filled in storeSelection and
@@ -231,6 +228,7 @@ void PartSet_Module::storeSelection()
   sketchMgr()->storeSelection(PartSet_SketcherMgr::ST_SelectType, myCurrentSelection);
 }
 
+//******************************************************
 void PartSet_Module::restoreSelection()
 {
   // cash is used only to restore selection, so it should be filled in storeSelection and
@@ -239,6 +237,7 @@ void PartSet_Module::restoreSelection()
   myCurrentSelection.clear();
 }
 
+//******************************************************
 void PartSet_Module::registerValidators()
 {
   //Registering of validators
@@ -267,12 +266,14 @@ void PartSet_Module::registerValidators()
   aFactory->registerValidator("PartSet_ProjectionSelection", new PartSet_ProjectionSelection);
 }
 
+//******************************************************
 void PartSet_Module::connectToPropertyPanel(ModuleBase_ModelWidget* theWidget,
                                             const bool isToConnect)
 {
   mySketchMgr->connectToPropertyPanel(theWidget, isToConnect);
 }
 
+//******************************************************
 void PartSet_Module::operationCommitted(ModuleBase_Operation* theOperation)
 {
   if (sketchMgr()->isNestedSketchOperation(theOperation)) {
@@ -296,6 +297,7 @@ void PartSet_Module::operationCommitted(ModuleBase_Operation* theOperation)
   }
 }
 
+//******************************************************
 void PartSet_Module::operationAborted(ModuleBase_Operation* theOperation)
 {
   /// Restart sketcher operations automatically
@@ -305,6 +307,7 @@ void PartSet_Module::operationAborted(ModuleBase_Operation* theOperation)
     overconstraintListener()->setActive(false);
 }
 
+//******************************************************
 void PartSet_Module::operationStarted(ModuleBase_Operation* theOperation)
 {
   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
@@ -392,6 +395,7 @@ void PartSet_Module::operationStarted(ModuleBase_Operation* theOperation)
   }
 }
 
+//******************************************************
 void PartSet_Module::updateSketcherOnStart(ModuleBase_Operation* theOperation)
 {
   if (PartSet_SketcherMgr::isSketchOperation(theOperation)) {
@@ -402,6 +406,7 @@ void PartSet_Module::updateSketcherOnStart(ModuleBase_Operation* theOperation)
   }
 }
 
+//******************************************************
 void PartSet_Module::updatePresentationsOnStart(ModuleBase_Operation* theOperation)
 {
   ModuleBase_OperationFeature* aFOperation =
@@ -412,6 +417,7 @@ void PartSet_Module::updatePresentationsOnStart(ModuleBase_Operation* theOperati
   }
 }
 
+//******************************************************
 void PartSet_Module::operationResumed(ModuleBase_Operation* theOperation)
 {
   ModuleBase_IModule::operationResumed(theOperation);
@@ -424,6 +430,7 @@ void PartSet_Module::operationResumed(ModuleBase_Operation* theOperation)
   }
 }
 
+//******************************************************
 void PartSet_Module::operationStopped(ModuleBase_Operation* theOperation)
 {
   bool isModifiedArgs = myCustomPrs->deactivate(ModuleBase_IModule::CustomizeArguments, false);
@@ -450,6 +457,7 @@ void PartSet_Module::operationStopped(ModuleBase_Operation* theOperation)
   }
 }
 
+//******************************************************
 ModuleBase_Operation* PartSet_Module::currentOperation() const
 {
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
@@ -457,6 +465,7 @@ ModuleBase_Operation* PartSet_Module::currentOperation() const
   return anOpMgr->currentOperation();
 }
 
+//******************************************************
 bool PartSet_Module::canUndo() const
 {
   bool aCanUndo = false;
@@ -469,6 +478,7 @@ bool PartSet_Module::canUndo() const
   return aCanUndo;
 }
 
+//******************************************************
 bool PartSet_Module::canRedo() const
 {
   bool aCanRedo = false;
@@ -481,6 +491,7 @@ bool PartSet_Module::canRedo() const
   return aCanRedo;
 }
 
+//******************************************************
 bool PartSet_Module::canApplyAction(const ObjectPtr& theObject, const QString& theActionId) const
 {
   bool aValid = true;
@@ -496,18 +507,21 @@ bool PartSet_Module::canApplyAction(const ObjectPtr& theObject, const QString& t
   return aValid;
 }
 
+//******************************************************
 bool PartSet_Module::canEraseObject(const ObjectPtr& theObject) const
 {
   // the sketch manager put the restriction to the objects erase
   return mySketchMgr->canEraseObject(theObject);
 }
 
+//******************************************************
 bool PartSet_Module::canDisplayObject(const ObjectPtr& theObject) const
 {
   // the sketch manager put the restriction to the objects display
   return mySketchMgr->canDisplayObject(theObject);
 }
 
+//******************************************************
 bool PartSet_Module::canUsePreselection(const QString& thePreviousOperationKind,
                                         const QString& theStartedOperationKind)
 {
@@ -522,6 +536,7 @@ bool PartSet_Module::canUsePreselection(const QString& thePreviousOperationKind,
   mySketchMgr->processHiddenObject(theObjects);
 }*/
 
+//******************************************************
 bool PartSet_Module::canActivateSelection(const ObjectPtr& theObject) const
 {
   bool aCanActivate = ModuleBase_IModule::canActivateSelection(theObject);
@@ -539,6 +554,7 @@ bool PartSet_Module::canActivateSelection(const ObjectPtr& theObject) const
   return aCanActivate;
 }
 
+//******************************************************
 bool PartSet_Module::addViewerMenu(const QMap<QString, QAction*>& theStdActions,
                                    QWidget* theParent,
                                    QMap<int, QAction*>& theMenuActions) const
@@ -546,11 +562,13 @@ bool PartSet_Module::addViewerMenu(const QMap<QString, QAction*>& theStdActions,
   return myMenuMgr->addViewerMenu(theStdActions, theParent, theMenuActions);
 }
 
+//******************************************************
 void PartSet_Module::updateViewerMenu(const QMap<QString, QAction*>& theStdActions)
 {
   myMenuMgr->updateViewerMenu(theStdActions);
 }
 
+//******************************************************
 bool PartSet_Module::isActionEnableStateFixed(const int theActionId) const
 {
   bool isEnabledFixed = false;
@@ -560,6 +578,7 @@ bool PartSet_Module::isActionEnableStateFixed(const int theActionId) const
   return isEnabledFixed;
 }
 
+//******************************************************
 QString PartSet_Module::getFeatureError(const FeaturePtr& theFeature)
 {
   QString anError = ModuleBase_IModule::getFeatureError(theFeature);
@@ -569,6 +588,7 @@ QString PartSet_Module::getFeatureError(const FeaturePtr& theFeature)
   return anError;
 }
 
+//******************************************************
 void PartSet_Module::grantedOperationIds(ModuleBase_Operation* theOperation,
                                          QStringList& theIds) const
 {
@@ -580,21 +600,94 @@ void PartSet_Module::grantedOperationIds(ModuleBase_Operation* theOperation,
   }
 }
 
+//******************************************************
 void PartSet_Module::activeSelectionModes(QIntList& theModes)
 {
-  theModes.clear();
   if (mySketchMgr->activeSketch().get())
-    PartSet_SketcherMgr::sketchSelectionModes(theModes);
+    PartSet_SketcherMgr::sketchSelectionModes(mySketchMgr->activeSketch(), theModes);
+  else
+    theModes = XGUI_Tools::workshop(myWorkshop)->viewerSelectionModes();
+}
+
+//******************************************************
+void PartSet_Module::moduleSelectionModes(int theModesType, QIntList& theModes)
+{
+  customSubShapesSelectionModes(theModes);
+  //theModes.append(XGUI_Tools::workshop(myWorkshop)->viewerSelectionModes());
+  //myWorkshop->module()->activeSelectionModes(theModes);
+}
+
+//******************************************************
+void PartSet_Module::moduleSelectionFilters(const QIntList& theFilterTypes,
+                                            SelectMgr_ListOfFilter& theSelectionFilters)
+{
+  bool isSketchActive = mySketchMgr->activeSketch().get();
+
+  std::map<XGUI_SelectionFilterType, Handle(SelectMgr_Filter)>::const_iterator aFiltersIt =
+    mySelectionFilters.begin();
+  for (; aFiltersIt != mySelectionFilters.end(); aFiltersIt++) {
+    int aFilterType = aFiltersIt->first;
+    // do not add not participating filters in given parameters
+    if (!theFilterTypes.contains(aFilterType))
+      continue;
+
+    // using sketch filters only if sketch operation is active
+    if (!isSketchActive &&
+        mySketchMgr->sketchSelectionFilter((XGUI_SelectionFilterType)aFilterType))
+      continue;
+
+    // using filtering of construction results only from faces panel
+    if (aFilterType == SF_ResultGroupNameFilter)
+      continue;
+
+    theSelectionFilters.Append(aFiltersIt->second);
+  }
 }
 
-void PartSet_Module::customSubShapesSelectionModes(QIntList& theTypes)
+//******************************************************
+QIntList PartSet_Module::selectionFilters()
 {
-  if (theTypes.contains(TopAbs_FACE))
-    theTypes.append(SketcherPrs_Tools::Sel_Sketch_Face);
-  if (theTypes.contains(TopAbs_WIRE))
-    theTypes.append(SketcherPrs_Tools::Sel_Sketch_Wire);
+  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)
+{
+  if (theModes.contains(TopAbs_FACE))
+    theModes.append(SketcherPrs_Tools::Sel_Sketch_Face);
+  if (theModes.contains(TopAbs_WIRE))
+    theModes.append(SketcherPrs_Tools::Sel_Sketch_Wire);
+
+  if (mySketchMgr->activeSketch().get())
+    PartSet_SketcherMgr::sketchSelectionModes(mySketchMgr->activeSketch(), theModes);
+}
+
+//******************************************************
 void PartSet_Module::getGeomSelection(const std::shared_ptr<ModuleBase_ViewerPrs>& theSelected,
                                       ObjectPtr& theObject, AttributePtr& theAttribute)
 {
@@ -606,11 +699,13 @@ void PartSet_Module::getGeomSelection(const std::shared_ptr<ModuleBase_ViewerPrs
   theObject = anObject;
 }
 
+//******************************************************
 bool PartSet_Module::isMouseOverWindow()
 {
   return mySketchMgr->isMouseOverWindow();
 }
 
+//******************************************************
 bool PartSet_Module::isSketchNeutralPointActivated() const
 {
   bool isNeutralPoint = true;
@@ -622,20 +717,23 @@ bool PartSet_Module::isSketchNeutralPointActivated() const
   return isNeutralPoint;
 }
 
+//******************************************************
 void PartSet_Module::closeDocument()
 {
   myActivePartIndex = QModelIndex();
 }
 
+//******************************************************
 void PartSet_Module::clearViewer()
 {
   myCustomPrs->clearPrs();
 
   XGUI_Workshop* aWorkshop = getWorkshop();
   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
-  aDisplayer->deactivateSelectionFilters();
+  aDisplayer->deactivateSelectionFilters(false);
 }
 
+//******************************************************
 void PartSet_Module::propertyPanelDefined(ModuleBase_Operation* theOperation)
 {
   ModuleBase_OperationFeature* aFOperation =
@@ -649,6 +747,7 @@ void PartSet_Module::propertyPanelDefined(ModuleBase_Operation* theOperation)
     aPanel->activateWidget(aPanel->modelWidgets().first());
 }
 
+//******************************************************
 bool PartSet_Module::createWidgets(ModuleBase_Operation* theOperation,
                                    QList<ModuleBase_ModelWidget*>& theWidgets) const
 {
@@ -701,6 +800,7 @@ bool PartSet_Module::createWidgets(ModuleBase_Operation* theOperation,
   return aProcessed;
 }
 
+//******************************************************
 void PartSet_Module::onSelectionChanged()
 {
   ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
@@ -734,6 +834,7 @@ void PartSet_Module::onSelectionChanged()
   }
 }
 
+//******************************************************
 void PartSet_Module::onKeyRelease(ModuleBase_IViewWindow* theWnd, QKeyEvent* theEvent)
 {
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
@@ -741,6 +842,7 @@ void PartSet_Module::onKeyRelease(ModuleBase_IViewWindow* theWnd, QKeyEvent* the
   anOpMgr->onKeyReleased(theWnd->viewPort(), theEvent);
 }
 
+//******************************************************
 ModuleBase_ModelWidget* PartSet_Module::createWidgetByType(const std::string& theType,
                                                            QWidget* theParent,
                                                            Config_WidgetAPI* theWidgetApi)
@@ -799,6 +901,7 @@ ModuleBase_ModelWidget* PartSet_Module::createWidgetByType(const std::string& th
   return aWgt;
 }
 
+//******************************************************
 ModuleBase_ModelWidget* PartSet_Module::activeWidget() const
 {
   ModuleBase_ModelWidget* anActiveWidget = 0;
@@ -814,6 +917,7 @@ ModuleBase_ModelWidget* PartSet_Module::activeWidget() const
   return anActiveWidget;
 }
 
+//******************************************************
 bool PartSet_Module::deleteObjects()
 {
   bool isProcessed = false;
@@ -887,17 +991,20 @@ bool PartSet_Module::deleteObjects()
   return isProcessed;
 }
 
+//******************************************************
 void PartSet_Module::editFeature(FeaturePtr theFeature)
 {
   storeConstraintsState(theFeature->getKind());
   ModuleBase_IModule::editFeature(theFeature);
 }
 
+//******************************************************
 bool PartSet_Module::canCommitOperation() const
 {
   return true;
 }
 
+//******************************************************
 void PartSet_Module::launchOperation(const QString& theCmdId, const bool& isStartAfterCommitOnly)
 {
   myIsOperationIsLaunched = true;
@@ -909,6 +1016,7 @@ void PartSet_Module::launchOperation(const QString& theCmdId, const bool& isStar
   myIsOperationIsLaunched = false;
 }
 
+//******************************************************
 void PartSet_Module::storeConstraintsState(const std::string& theFeatureKind)
 {
   if (myWorkshop->currentOperation() &&
@@ -919,6 +1027,7 @@ void PartSet_Module::storeConstraintsState(const std::string& theFeatureKind)
   }
 }
 
+//******************************************************
 void PartSet_Module::updateConstraintsState(const std::string& theFeatureKind)
 {
   if (PartSet_SketcherMgr::constraintsIdList().contains(theFeatureKind.c_str()) ||
@@ -931,6 +1040,7 @@ void PartSet_Module::updateConstraintsState(const std::string& theFeatureKind)
   }
 }
 
+//******************************************************
 void PartSet_Module::onObjectDisplayed(ObjectPtr theObject, AISObjectPtr theAIS)
 {
   Handle(AIS_InteractiveObject) anAIS = theAIS->impl<Handle(AIS_InteractiveObject)>();
@@ -949,10 +1059,12 @@ void PartSet_Module::onObjectDisplayed(ObjectPtr theObject, AISObjectPtr theAIS)
       if (!aCons.IsNull())
       aToUseZLayer = true;
     }
-    aCtx->SetZLayer(anAIS, myVisualLayerId);
+    if (aToUseZLayer)
+      aCtx->SetZLayer(anAIS, myVisualLayerId);
   }
 }
 
+//******************************************************
 void PartSet_Module::onBeforeObjectErase(ObjectPtr theObject, AISObjectPtr theAIS)
 {
   // this is obsolete
@@ -962,6 +1074,7 @@ void PartSet_Module::onBeforeObjectErase(ObjectPtr theObject, AISObjectPtr theAI
   //  myCustomPrs->redisplay(theObject, false);
 }
 
+//******************************************************
 void PartSet_Module::onViewTransformed(int theTrsfType)
 {
   // Set length of arrows constant in pixel size
@@ -1021,11 +1134,13 @@ void PartSet_Module::onViewTransformed(int theTrsfType)
   }
 }
 
+//******************************************************
 bool PartSet_Module::isCustomPrsActivated(const ModuleBase_CustomizeFlag& theFlag) const
 {
   return myCustomPrs->isActive(theFlag);
 }
 
+//******************************************************
 void PartSet_Module::activateCustomPrs(const FeaturePtr& theFeature,
                                        const ModuleBase_CustomizeFlag& theFlag,
                                        const bool theUpdateViewer)
@@ -1033,12 +1148,14 @@ void PartSet_Module::activateCustomPrs(const FeaturePtr& theFeature,
   myCustomPrs->activate(theFeature, theFlag, theUpdateViewer);
 }
 
+//******************************************************
 void PartSet_Module::deactivateCustomPrs(const ModuleBase_CustomizeFlag& theFlag,
                                          const bool theUpdateViewer)
 {
   myCustomPrs->deactivate(theFlag, theUpdateViewer);
 }
 
+//******************************************************
 bool PartSet_Module::customisePresentation(ResultPtr theResult, AISObjectPtr thePrs,
                                            std::shared_ptr<GeomAPI_ICustomPrs> theCustomPrs)
 {
@@ -1063,6 +1180,7 @@ bool PartSet_Module::customisePresentation(ResultPtr theResult, AISObjectPtr the
   return aCustomized;
 }
 
+//******************************************************
 bool PartSet_Module::afterCustomisePresentation(std::shared_ptr<ModelAPI_Result> theResult,
                                                 AISObjectPtr thePrs,
                                                 GeomCustomPrsPtr theCustomPrs)
@@ -1105,6 +1223,7 @@ bool PartSet_Module::afterCustomisePresentation(std::shared_ptr<ModelAPI_Result>
   return aCustomized;
 }
 
+//******************************************************
 bool PartSet_Module::customizeObject(ObjectPtr theObject, const ModuleBase_CustomizeFlag& theFlag,
                                      const bool theUpdateViewer)
 {
@@ -1115,6 +1234,7 @@ bool PartSet_Module::customizeObject(ObjectPtr theObject, const ModuleBase_Custo
   return isRedisplayed;
 }
 
+//******************************************************
 void PartSet_Module::customizeObjectBrowser(QWidget* theObjectBrowser)
 {
   XGUI_ObjectsBrowser* aOB = dynamic_cast<XGUI_ObjectsBrowser*>(theObjectBrowser);
@@ -1132,6 +1252,7 @@ void PartSet_Module::customizeObjectBrowser(QWidget* theObjectBrowser)
   }
 }
 
+//******************************************************
 void PartSet_Module::onActiveDocPopup(const QPoint& thePnt)
 {
   SessionPtr aMgr = ModelAPI_Session::get();
@@ -1147,12 +1268,13 @@ void PartSet_Module::onActiveDocPopup(const QPoint& thePnt)
   aMenu.exec(aHeader->mapToGlobal(thePnt));
 }
 
+//******************************************************
 Handle(AIS_InteractiveObject) PartSet_Module::createPresentation(const ResultPtr& theResult)
 {
   return mySketchMgr->createPresentation(theResult);
 }
 
-
+//******************************************************
 ObjectPtr PartSet_Module::findPresentedObject(const AISObjectPtr& theAIS) const
 {
   ObjectPtr anObject;
@@ -1175,6 +1297,7 @@ ObjectPtr PartSet_Module::findPresentedObject(const AISObjectPtr& theAIS) const
   return anObject;
 }
 
+//******************************************************
 bool PartSet_Module::canBeShaded(Handle(AIS_InteractiveObject) theAIS) const
 {
   bool aCanBeShaged = true;
@@ -1186,6 +1309,7 @@ bool PartSet_Module::canBeShaded(Handle(AIS_InteractiveObject) theAIS) const
   return aCanBeShaged;
 }
 
+//******************************************************
 void PartSet_Module::addObjectBrowserMenu(QMenu* theMenu) const
 {
   QObjectPtrList aObjects = myWorkshop->selection()->selectedObjects();
@@ -1198,8 +1322,9 @@ void PartSet_Module::addObjectBrowserMenu(QMenu* theMenu) const
   bool hasParameter = false;
   bool hasCompositeOwner = false;
   bool hasResultInHistory = false;
+  bool hasFolder = false;
   ModuleBase_Tools::checkObjects(aObjects, hasResult, hasFeature, hasParameter,
-                                  hasCompositeOwner, hasResultInHistory);
+                                  hasCompositeOwner, hasResultInHistory, hasFolder);
 
   ModuleBase_Operation* aCurrentOp = myWorkshop->currentOperation();
   if (aSelected == 1) {
@@ -1244,6 +1369,7 @@ void PartSet_Module::addObjectBrowserMenu(QMenu* theMenu) const
   }
 }
 
+//******************************************************
 #define EXPAND_PARENT(OBJ) \
 QModelIndex aObjIndex = aDataModel->objectIndex(OBJ); \
 if (aObjIndex.isValid()) { \
@@ -1253,7 +1379,7 @@ if (aObjIndex.isValid()) { \
     aTreeView->setExpanded(aParent, true); \
 }
 
-
+//******************************************************
 void PartSet_Module::processEvent(const std::shared_ptr<Events_Message>& theMessage)
 {
   if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) {
@@ -1340,6 +1466,7 @@ void PartSet_Module::processEvent(const std::shared_ptr<Events_Message>& theMess
   }
 }
 
+//******************************************************
 void PartSet_Module::onTreeViewDoubleClick(const QModelIndex& theIndex)
 {
   if (myWorkshop->currentOperation()) // Do not change activation of parts if an operation active
@@ -1376,7 +1503,7 @@ void PartSet_Module::onTreeViewDoubleClick(const QModelIndex& theIndex)
   }
 }
 
-
+//******************************************************
 void PartSet_Module::onViewCreated(ModuleBase_IViewWindow*)
 {
   // z layer is created for all started operations in order to visualize operation AIS presentation
@@ -1404,16 +1531,8 @@ void PartSet_Module::onViewCreated(ModuleBase_IViewWindow*)
   }
   // if there is an active operation with validated widget,
   // the filters of this widget should be activated in the created view
-  ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
-  if (aOperation) {
-    ModuleBase_ModelWidget* anActiveWidget = activeWidget();
-    if (anActiveWidget) {
-      ModuleBase_WidgetSelector* aWSelector =
-        dynamic_cast<ModuleBase_WidgetSelector*>(anActiveWidget);
-      if (aWSelector)
-        aWSelector->activateSelectionAndFilters(true);
-    }
-  }
+  myWorkshop->selectionActivate()->updateSelectionFilters();
+  myWorkshop->selectionActivate()->updateSelectionModes();
 }
 
 //******************************************************
@@ -1422,6 +1541,7 @@ void PartSet_Module::widgetStateChanged(int thePreviousState)
   mySketchMgr->widgetStateChanged(thePreviousState);
 }
 
+//******************************************************
 bool PartSet_Module::processEnter(const std::string& thePreviousAttributeID)
 {
   return mySketchReentrantMgr->processEnter(thePreviousAttributeID);
index 4a70c942f511760ce05a93907663a9707df3424b..70de7236d9c54db8df08983fa3336f5394bff575 100755 (executable)
@@ -24,6 +24,7 @@
 #include "PartSet.h"
 #include "PartSet_Tools.h"
 #include "PartSet_OverconstraintListener.h"
+#include "XGUI_SelectionFilterType.h"
 #include "PartSet_SketcherMgr.h"
 
 #include <ModuleBase_IModule.h>
 //#include <StdSelect_FaceFilter.hxx>
 #include <TopoDS_Shape.hxx>
 #include <SelectMgr_ListOfFilter.hxx>
+#include <SelectMgr_Filter.hxx>
 
 #include <QMap>
 #include <QMenu>
 #include <QObject>
 #include <QModelIndex>
 
-#include <string>
-
+#include <map>
 #include <memory>
+#include <string>
 
 class ModuleBase_Operation;
 class ModuleBase_IViewWindow;
@@ -84,11 +86,6 @@ public:
   PartSet_Module(ModuleBase_IWorkshop* theWshop);
   virtual ~PartSet_Module();
 
-  // Add default selection filters of the module to the current viewer
-  virtual void activateSelectionFilters();
-  // Remove default selection filters of the module from the current viewer
-  virtual void deactivateSelectionFilters();
-
   // Stores the current selection
   virtual void storeSelection();
 
@@ -223,8 +220,30 @@ public:
   virtual void activeSelectionModes(QIntList& theModes);
 
   /// Appends specific selection modes for the module to the list of types
-  /// \param theTypes a selection modes to be extended
-  virtual void customSubShapesSelectionModes(QIntList& theTypes);
+  /// \param theModesType combination of available selection filters
+  /// \param theModes a selection modes to be extended
+  virtual void moduleSelectionModes(int theModesType, QIntList& theModes);
+
+  /// Appends into container of filters module filters corresponded to the modes type
+  /// \param theFilterTypes container of available selection filters
+  /// \param theSelectionFilters [out] container to be extend by elements
+  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
@@ -411,6 +430,10 @@ protected slots:
   void onChoiceChanged(ModuleBase_ModelWidget* theWidget, int theIndex);
 
 protected:
+  /// Appends specific selection modes for the module to the list of types
+  /// \param theModes a selection modes to be extended
+  virtual void customSubShapesSelectionModes(QIntList& theModes);
+
   /// Sets the constraints states in internal map. If the feature kind is a dimensional constraint
   /// other dimensions are shown.
   /// \param theFeatureKindId a feature kind
@@ -450,7 +473,7 @@ protected:
 
 private:
   bool myIsOperationIsLaunched; /// state of application between launch and stop operation
-  SelectMgr_ListOfFilter mySelectionFilters;
+  std::map<XGUI_SelectionFilterType, Handle(SelectMgr_Filter)> mySelectionFilters;
 
   PartSet_SketcherMgr* mySketchMgr;
   PartSet_SketcherReentrantMgr* mySketchReentrantMgr;
index f0f614bb0f4ec9d7dccc2037b878fa7b1f784433..afd0e268cd9d48722e6319f05b8d4aad9f9487c8 100644 (file)
@@ -97,7 +97,7 @@ void PartSet_PreviewSketchPlane::createSketchPlane(const CompositeFeaturePtr& th
   }
 
   XGUI_Displayer* aDisp = XGUI_Tools::workshop(theWorkshop)->displayer();
-  aDisp->displayAIS(myPlane, true, 1/*shaded*/, false);
+  aDisp->displayAIS(myPlane, false/*load object in selection*/, 1/*shaded*/, false);
   myPreviewIsDisplayed = true;
 }
 
@@ -124,6 +124,7 @@ AISObjectPtr PartSet_PreviewSketchPlane::createPreviewPlane()
     int aDispMode = 1; // shading
     Handle(AIS_InteractiveObject) anAISIO = aAIS->impl<Handle(AIS_InteractiveObject)>();
     if (!anAISIO.IsNull()) {
+      //anAISIO->SetInfiniteState(Standard_True);
       anAISIO->Attributes()->SetFaceBoundaryDraw( Standard_True );
       anAISIO->SetDisplayMode(aDispMode);
     }
index abaadd3119b5d3a25735baf406845eafc02354e0..e34587a07b4cbdf0bd3fab5f67b54bc35e25357a 100755 (executable)
@@ -19,6 +19,8 @@
 //
 
 #include "PartSet_SketcherMgr.h"
+
+#include "PartSet_Filters.h"
 #include "PartSet_SketcherReentrantMgr.h"
 #include "PartSet_Module.h"
 #include "PartSet_MouseProcessor.h"
@@ -34,6 +36,7 @@
 #include <XGUI_Workshop.h>
 #include <XGUI_ContextMenuMgr.h>
 #include <XGUI_Selection.h>
+#include <XGUI_SelectionActivate.h>
 #include <XGUI_SelectionMgr.h>
 #include <XGUI_ModuleConnector.h>
 #include <XGUI_PropertyPanel.h>
@@ -55,6 +58,7 @@
 #include <ModuleBase_ViewerPrs.h>
 #include <ModuleBase_Tools.h>
 #include <ModuleBase_ResultPrs.h>
+#include <ModuleBase_ViewerFilters.h>
 
 #include <GeomDataAPI_Point2D.h>
 
@@ -85,6 +89,9 @@
 #include <SketchPlugin_MultiTranslation.h>
 #include <SketchPlugin_IntersectionPoint.h>
 #include <SketchPlugin_Projection.h>
+#include <SketchPlugin_ConstraintDistanceAlongDir.h>
+#include <SketchPlugin_ConstraintDistanceHorizontal.h>
+#include <SketchPlugin_ConstraintDistanceVertical.h>
 
 #include <SketcherPrs_Tools.h>
 
@@ -183,12 +190,13 @@ PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule)
   myIsConstraintsShown[PartSet_Tools::Expressions] = false;
 
   mySketchPlane = new PartSet_PreviewSketchPlane();
+
+  registerSelectionFilter(SF_SketchCirclePointFilter, new PartSet_CirclePointFilter(anIWorkshop));
+  registerSelectionFilter(SF_SketchPlaneFilter, new ModuleBase_ShapeInPlaneFilter());
 }
 
 PartSet_SketcherMgr::~PartSet_SketcherMgr()
 {
-  if (!myPlaneFilter.IsNull())
-    myPlaneFilter.Nullify();
 }
 
 void PartSet_SketcherMgr::onEnterViewPort()
@@ -666,8 +674,8 @@ void PartSet_SketcherMgr::onApplicationStarted()
 
     connect(aPropertyPanel, SIGNAL(noMoreWidgets(const std::string&)),
             aReentranceMgr, SLOT(onNoMoreWidgets(const std::string&)));
-    connect(aPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)),
-            aReentranceMgr, SLOT(onWidgetActivated()));
+    //connect(aPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)),
+    //        aReentranceMgr, SLOT(onWidgetActivated()));
   }
 
   XGUI_ViewerProxy* aViewerProxy = aWorkshop->viewer();
@@ -799,13 +807,18 @@ const QStringList& PartSet_SketcherMgr::constraintsIdList()
     aConstraintIds << SketchPlugin_ConstraintMirror::ID().c_str();
     aConstraintIds << SketchPlugin_MultiTranslation::ID().c_str();
     aConstraintIds << SketchPlugin_MultiRotation::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintDistanceAlongDir::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintDistanceHorizontal::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintDistanceVertical::ID().c_str();
   }
   return aConstraintIds;
 }
 
-void PartSet_SketcherMgr::sketchSelectionModes(QIntList& theModes)
+void PartSet_SketcherMgr::sketchSelectionModes(const CompositeFeaturePtr& theSketch,
+                                               QIntList& theModes)
 {
-  theModes.clear();
+  if (!theSketch.get() || !PartSet_Tools::sketchPlane(theSketch).get())
+    return;
 
   theModes.append(SketcherPrs_Tools::Sel_Dimension_Text);
   theModes.append(SketcherPrs_Tools::Sel_Dimension_Line);
@@ -912,7 +925,10 @@ bool PartSet_SketcherMgr::isDistanceKind(std::string& theKind)
   return (theKind == SketchPlugin_ConstraintLength::ID()) ||
          (theKind == SketchPlugin_ConstraintDistance::ID()) ||
          (theKind == SketchPlugin_ConstraintRadius::ID()) ||
-         (theKind == SketchPlugin_ConstraintAngle::ID());
+         (theKind == SketchPlugin_ConstraintAngle::ID()) ||
+         (theKind == SketchPlugin_ConstraintDistanceHorizontal::ID()) ||
+         (theKind == SketchPlugin_ConstraintDistanceVertical::ID()) ||
+         (theKind == SketchPlugin_ConstraintDistanceAlongDir::ID());
 }
 
 void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
@@ -1005,26 +1021,17 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
   qDebug(QString("startSketch: %1, %2").arg(anInfo.size()).arg(anInfoStr).toStdString().c_str());
 #endif
 
-  if(myCirclePointFilter.IsNull()) {
-    myCirclePointFilter = new PartSet_CirclePointFilter(myModule->workshop());
-  }
-
-  myModule->workshop()->viewer()->addSelectionFilter(myCirclePointFilter);
-
-  if (myPlaneFilter.IsNull())
-    myPlaneFilter = new ModuleBase_ShapeInPlaneFilter();
-
-  myModule->workshop()->viewer()->addSelectionFilter(myPlaneFilter);
   bool aHasPlane = false;
   std::shared_ptr<GeomAPI_Pln> aPln;
   aPln = PartSet_Tools::sketchPlane(myCurrentSketch);
-  myPlaneFilter->setPlane(aPln);
+  Handle(SelectMgr_Filter) aFilter = myModule->selectionFilter(SF_SketchPlaneFilter);
+  if (!aFilter.IsNull())
+    Handle(ModuleBase_ShapeInPlaneFilter)::DownCast(aFilter)->setPlane(aPln);
+
+  workshop()->selectionActivate()->updateSelectionFilters();
+  workshop()->selectionActivate()->updateSelectionModes();
 
   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
-  // all displayed objects should be activated in current selection modes according to switched
-  // plane filter
-  if (aPln.get())
-    aConnector->activateModuleSelectionModes();
 
   myExternalPointsMgr = new PartSet_ExternalPointsMgr(myModule->workshop(), myCurrentSketch);
 }
@@ -1049,9 +1056,6 @@ void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
     // The sketch was aborted
     myCurrentSketch = CompositeFeaturePtr();
     mySketchPlane->eraseSketchPlane(myModule->workshop());
-    // TODO: move this outside of if-else
-    myModule->workshop()->viewer()->removeSelectionFilter(myCirclePointFilter);
-    myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter);
 
     // Erase all sketcher objects
     QObjectPtrList aObjects = aDisplayer->displayedObjects();
@@ -1094,13 +1098,10 @@ void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
     myCurrentSketch = CompositeFeaturePtr();
     mySketchPlane->eraseSketchPlane(myModule->workshop());
 
-    myModule->workshop()->viewer()->removeSelectionFilter(myCirclePointFilter);
-    myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter);
-
     Events_Loop::loop()->flush(aDispEvent);
   }
-  // restore the module selection modes, which were changed on startSketch
-  aConnector->activateModuleSelectionModes();
+  workshop()->selectionActivate()->updateSelectionFilters();
+  workshop()->selectionActivate()->updateSelectionModes();
 }
 
 void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation)
@@ -1160,12 +1161,16 @@ void PartSet_SketcherMgr::commitNestedSketch(ModuleBase_Operation* theOperation)
   }
 }
 
-void PartSet_SketcherMgr::activatePlaneFilter(const bool& toActivate)
+bool PartSet_SketcherMgr::sketchSelectionFilter(const XGUI_SelectionFilterType theFilterType)
 {
-  if (toActivate)
-    myModule->workshop()->viewer()->addSelectionFilter(myPlaneFilter);
-  else
-    myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter);
+  return mySelectionFilterTypes.find(theFilterType) != mySelectionFilterTypes.end();
+}
+
+void PartSet_SketcherMgr::registerSelectionFilter(const XGUI_SelectionFilterType theFilterType,
+                                                  const Handle(SelectMgr_Filter)& theFilter)
+{
+  mySelectionFilterTypes.insert(theFilterType);
+  myModule->registerSelectionFilter(theFilterType, theFilter);
 }
 
 bool PartSet_SketcherMgr::operationActivatedByPreselection()
@@ -1468,12 +1473,13 @@ bool PartSet_SketcherMgr::isObjectOfSketch(const ObjectPtr& theObject) const
   return isFoundObject;
 }
 
-void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>& thePln)
+void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>& thePlane)
 {
-  if (myPlaneFilter.IsNull())
-   myPlaneFilter = new ModuleBase_ShapeInPlaneFilter();
+  Handle(SelectMgr_Filter) aFilter = myModule->selectionFilter(SF_SketchPlaneFilter);
+  if (!aFilter.IsNull())
+    Handle(ModuleBase_ShapeInPlaneFilter)::DownCast(aFilter)->setPlane(thePlane);
 
-  myPlaneFilter->setPlane(thePln);
+  workshop()->selectionActivate()->updateSelectionModes();
 }
 
 bool PartSet_SketcherMgr::setDistanceValueByPreselection(ModuleBase_Operation* theOperation,
index 62e67fac2bd3a3beaa07f25473996e149f0f0f1a..634916b7814fb3019823ab6dea15a4305e24547a 100644 (file)
 
 #include "PartSet.h"
 
-#include "PartSet_Filters.h"
-#include "PartSet_Tools.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_ViewerFilters.h>
 #include <ModuleBase_Definitions.h>
 #include <ModuleBase_ModelWidget.h>
 
 #include <GeomAPI_Pln.h>
+
 #include <SelectMgr_IndexedMapOfOwner.hxx>
+#include <SelectMgr_ListOfFilter.hxx>
+
 #include <TopoDS_Shape.hxx>
 #include <TopTools_MapOfShape.hxx>
 
@@ -45,6 +47,8 @@
 #include <QList>
 #include <QMap>
 
+#include <set>
+
 class PartSet_Module;
 class ModuleBase_IViewWindow;
 class ModuleBase_ModelWidget;
@@ -194,9 +198,16 @@ public:
   /// \param theOperation a committed operation
   void commitNestedSketch(ModuleBase_Operation* theOperation);
 
-  /// Append the sketch plane filter into the current viewer
-  /// \param toActivate state whether the filter should be activated/deactivated
-  void activatePlaneFilter(const bool& toActivate);
+  /// 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);
+
+  /// 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);
 
   /// Commit the operation if it is possible. If the operation is dimention constraint,
   /// it gives widget editor to input dimention value
@@ -296,8 +307,9 @@ public:
   static const QStringList& constraintsIdList();
 
   /// Returns a list of modes, where the AIS objects should be activated
+  /// \param theSketch a sketch object, modes are empty if sketch plane is not defined yet
   /// \param theModes a list of modes
-  static void sketchSelectionModes(QIntList& theModes);
+  static void sketchSelectionModes(const CompositeFeaturePtr& theSketch, QIntList& theModes);
 
   /// Create specific for the module presentation
   /// \param theResult an object for presentation
@@ -433,8 +445,8 @@ private:
 
   CompositeFeaturePtr myCurrentSketch;
 
-  Handle(PartSet_CirclePointFilter) myCirclePointFilter;
-  Handle(ModuleBase_ShapeInPlaneFilter) myPlaneFilter;
+  std::set<XGUI_SelectionFilterType> mySelectionFilterTypes;
+
   FeatureToSelectionMap myCurrentSelection;
   bool myPreviousUpdateViewerEnabled;
 
index 5c4e1025735e16677eea0035593e502550291822..eb524325c96653b8ecf5f50333cea99d89807747 100644 (file)
@@ -32,6 +32,7 @@
 #include "GeomDataAPI_Point2D.h"
 
 #include <ModuleBase_IPropertyPanel.h>
+#include <ModuleBase_ISelectionActivate.h>
 #include <ModuleBase_OperationFeature.h>
 #include <ModuleBase_ModelWidget.h>
 #include <ModuleBase_ViewerPrs.h>
@@ -42,6 +43,7 @@
 #include <ModuleBase_OperationDescription.h>
 #include "ModuleBase_ToolBox.h"
 #include "ModuleBase_ISelection.h"
+#include "ModuleBase_ISelectionActivate.h"
 
 #include <SketchPlugin_Feature.h>
 #include <SketchPlugin_Line.h>
@@ -320,22 +322,24 @@ void PartSet_SketcherReentrantMgr::setReentrantPreSelection(
   aReentrantMessage->setClickedPoint(myClickedSketchPoint);
 }
 
-void PartSet_SketcherReentrantMgr::onWidgetActivated()
-{
-  if (!isActiveMgr())
-    return;
-  if (!myIsInternalEditOperation)
-    return;
-
-  PartSet_Module* aModule = module();
-  ModuleBase_ModelWidget* aFirstWidget = aModule->activeWidget();
-  ModuleBase_IPropertyPanel* aPanel = aModule->currentOperation()->propertyPanel();
-  if (aFirstWidget != aPanel->activeWidget()) {
-    ModuleBase_WidgetSelector* aWSelector = dynamic_cast<ModuleBase_WidgetSelector*>(aFirstWidget);
-    if (aWSelector)
-      aWSelector->activateSelectionAndFilters(true);
-  }
-}
+//void PartSet_SketcherReentrantMgr::onWidgetActivated()
+//{
+//  if (!isActiveMgr())
+//    return;
+//  if (!myIsInternalEditOperation)
+//    return;
+//
+//  PartSet_Module* aModule = module();
+//  ModuleBase_ModelWidget* aFirstWidget = aModule->activeWidget();
+//  ModuleBase_IPropertyPanel* aPanel = aModule->currentOperation()->propertyPanel();
+//  if (aFirstWidget != aPanel->activeWidget()) {
+//    ModuleBase_WidgetSelector* aWSelector = dynamic_cast<ModuleBase_WidgetSelector*>
+//      (aFirstWidget);
+//    if (aWSelector) {
+//      myWorkshop->selectionActivate()->updateSelectionModesAndFilters(aWSelector);
+//    }
+//  }
+//}
 
 void PartSet_SketcherReentrantMgr::onNoMoreWidgets(const std::string& thePreviousAttributeID)
 {
@@ -501,7 +505,7 @@ bool PartSet_SketcherReentrantMgr::startInternalEdit(const std::string& thePrevi
     connect(aFOperation, SIGNAL(beforeAborted()), this, SLOT(onBeforeStopped()));
 
     // activate selection filters of the first widget in the viewer
-    onWidgetActivated();
+    //onWidgetActivated();
 
     // activate the last active widget in the Property Panel
     if (!thePreviousAttributeID.empty()) {
@@ -656,13 +660,8 @@ void PartSet_SketcherReentrantMgr::deleteInternalFeature()
   std::cout << "PartSet_SketcherReentrantMgr::deleteInternalFeature: "
             << myInternalFeature->data()->name() << std::endl;
 #endif
-  if (myInternalActiveWidget) {
-    ModuleBase_WidgetSelector* aWSelector =
-      dynamic_cast<ModuleBase_WidgetSelector*>(myInternalActiveWidget);
-    if (aWSelector)
-      aWSelector->activateSelectionAndFilters(false);
+  if (myInternalActiveWidget)
     myInternalActiveWidget = 0;
-  }
   delete myInternalWidget;
   myInternalWidget = 0;
 
index 7a7b26c46a901190d92337775160258b89a3dfe9..073b534e8437138f85acb0033f3ee1a4ca9ed9da 100644 (file)
@@ -139,7 +139,7 @@ public:
 private slots:
   /// SLOT, that is called by a widget activating in the property panel
   /// If the 'internal' edit operation is started, it activates the first widget selection
-  void onWidgetActivated();
+  //void onWidgetActivated();
 
   /// SLOT, that is called by no more widget signal emitted by property panel
   /// Start an internal edit operation or, if the internal flag is forbided, commits
index dac76b8e98286ecada62e6c7adf612516a757e53..2d32f553e341349d33808337ca0eb7f4c8e763fc 100755 (executable)
@@ -686,13 +686,15 @@ ResultPtr PartSet_Tools::createFixedByExternalCenter(
     const std::shared_ptr<GeomAPI_Edge>& theEdge,
     ModelAPI_AttributeSelection::CenterType theType,
     const CompositeFeaturePtr& theSketch,
-    bool theTemporary)
+    bool theTemporary,
+    FeaturePtr& theCreatedFeature)
 {
   ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
   if (!aResult.get())
     return ResultPtr();
 
   FeaturePtr aProjectionFeature = theSketch->addFeature(SketchPlugin_Projection::ID());
+  theCreatedFeature = aProjectionFeature;
   AttributeSelectionPtr anExternalAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(
                  aProjectionFeature->attribute(SketchPlugin_Projection::EXTERNAL_FEATURE_ID()));
   anExternalAttr->setValueCenter(aResult, theEdge, theType, theTemporary);
index 486d361e01cdb6d30461f5fd587858973c176306..1f5bf51b12ae1b4c36a5e8d4a91a80660e42fea1 100755 (executable)
@@ -256,7 +256,7 @@ public:
     std::set<AttributePtr>::const_iterator anIt;
     for (anIt = aRefsList.cbegin(); anIt != aRefsList.cend(); ++anIt) {
       FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*anIt)->owner());
-      if (aRefFeature->getKind() == theFeatureId)
+      if (aRefFeature && aRefFeature->getKind() == theFeatureId)
         return aRefFeature;
     }
     return FeaturePtr();
@@ -283,7 +283,8 @@ public:
                                                const std::shared_ptr<GeomAPI_Edge>& theEdge,
                                                ModelAPI_AttributeSelection::CenterType theType,
                                                const CompositeFeaturePtr& theSketch,
-                                               bool theTemporary = false);
+                                               bool theTemporary,
+                                               FeaturePtr& theCreatedFeature);
 
 };
 
index 2ee93fbb4ffbde724f2a9ff624178ccf2b22f62f..1b4be74c099191fe1905422c064dd38050f389ac 100644 (file)
@@ -86,7 +86,7 @@ bool PartSet_WidgetFeaturePointSelector::isValidSelection(
 }
 
 //********************************************************************
-bool PartSet_WidgetFeaturePointSelector::activateSelectionAndFilters(bool toActivate)
+void PartSet_WidgetFeaturePointSelector::updateSelectionModesAndFilters(bool toActivate)
 {
 #ifdef HIGHLIGHT_STAYS_PROBLEM
   Handle(AIS_InteractiveContext) aContext =
@@ -113,7 +113,7 @@ bool PartSet_WidgetFeaturePointSelector::activateSelectionAndFilters(bool toActi
 
 #endif
 
-  return ModuleBase_WidgetShapeSelector::activateSelectionAndFilters(toActivate);
+  ModuleBase_WidgetShapeSelector::updateSelectionModesAndFilters(toActivate);
 }
 
 //********************************************************************
index 12d897c37e868a03bc7544313e026cbd4c484022..4825cf68647b3c07901957496b509434c993d09d 100644 (file)
@@ -74,7 +74,7 @@ Q_OBJECT
 
   /// Activate or deactivate selection and selection filters
   /// \return true if the selection filter of the widget is activated in viewer context
-  virtual bool activateSelectionAndFilters(bool toActivate);
+  virtual void updateSelectionModesAndFilters(bool toActivate);
 
   /// Set sketcher
   /// \param theSketch a sketcher object
index a858357346f58fb1e5697f9c00d35d23e677e00a..60d3d4a82baeadff22ad8ab7cfdbfdb9c301463e 100755 (executable)
@@ -34,6 +34,7 @@
 
 #include <Config_WidgetAPI.h>
 
+#include <PartSet_CenterPrs.h>
 #include <PartSet_Tools.h>
 #include <PartSet_ExternalObjectsMgr.h>
 #include <SketchPlugin_Feature.h>
@@ -61,7 +62,13 @@ PartSet_WidgetMultiSelector::~PartSet_WidgetMultiSelector()
 //********************************************************************
 bool PartSet_WidgetMultiSelector::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs)
 {
-  bool aValid = ModuleBase_WidgetMultiSelector::isValidSelectionCustom(thePrs);
+  bool aValid = false;
+  if (thePrs.get() && thePrs->interactive().get() &&
+      thePrs->interactive()->IsKind(STANDARD_TYPE(PartSet_CenterPrs)))
+    aValid = true; // we should not check acceptSubShape for such presentation
+  else
+    aValid = ModuleBase_WidgetMultiSelector::isValidSelectionCustom(thePrs);
+
   if (aValid) {
     ObjectPtr anObject = myWorkshop->selection()->getResult(thePrs);
     aValid = myExternalObjectMgr->isValidObject(anObject);
index 37d9fb01599b1bef5cfcb10f85d3e9520247a064..8782a90acd49dfcecd4be4b191d7e037bf019a00 100644 (file)
@@ -244,7 +244,7 @@ bool PartSet_WidgetPoint2D::setSelectionCustom(const ModuleBase_ViewerPrsPtr& th
   GeomShapePtr aShape = theValue->shape();
   if (aShape.get() && !aShape->isNull()) {
     Handle(V3d_View) aView = myWorkshop->viewer()->activeView();
-    double aX, aY;
+    double aX = 0, aY = 0;
     const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
     if (getPoint2d(aView, aTDShape, aX, aY)) {
       fillRefAttribute(aX, aY, theValue);
@@ -307,7 +307,7 @@ bool PartSet_WidgetPoint2D::setSelection(QList<ModuleBase_ViewerPrsPtr>& theValu
     GeomShapePtr aShape = aValue->shape();
     if (aShape.get() && !aShape->isNull()) {
       Handle(V3d_View) aView = myWorkshop->viewer()->activeView();
-      double aX, aY;
+      double aX = 0, aY = 0;
       const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
       if (getPoint2d(aView, aTDShape, aX, aY)) {
         isDone = setPoint(aX, aY);
@@ -442,14 +442,17 @@ QList<QWidget*> PartSet_WidgetPoint2D::getControls() const
   return aControls;
 }
 
+//********************************************************************
+void PartSet_WidgetPoint2D::selectionModes(int& theModuleSelectionModes, QIntList& theModes)
+{
+  theModuleSelectionModes = -1;
+  theModes << TopAbs_VERTEX;
+  theModes << TopAbs_EDGE;
+}
 
+//********************************************************************
 void PartSet_WidgetPoint2D::activateCustom()
 {
-  QIntList aModes;
-  aModes << TopAbs_VERTEX;
-  aModes << TopAbs_EDGE;
-  myWorkshop->activateSubShapesSelection(aModes);
-
   if (!isEditingMode()) {
     FeaturePtr aFeature = feature();
     if (aFeature.get() && aFeature->getKind() == SketchPlugin_Point::ID())
@@ -472,7 +475,6 @@ void PartSet_WidgetPoint2D::deactivate()
     storeValue();
 
   ModuleBase_ModelWidget::deactivate();
-  myWorkshop->deactivateSubShapesSelection();
 }
 
 bool PartSet_WidgetPoint2D::getPoint2d(const Handle(V3d_View)& theView,
@@ -626,7 +628,7 @@ void PartSet_WidgetPoint2D::mouseReleased(ModuleBase_IViewWindow* theWindow, QMo
       }
     }
     if (anExternal) {
-      double aX, aY;
+      double aX = 0, aY = 0;
       if (getPoint2d(aView, aShape, aX, aY) && isFeatureContainsPoint(myFeature, aX, aY)) {
         // do not create a constraint to the point, which already used by the feature
         // if the feature contains the point, focus is not switched
@@ -673,7 +675,7 @@ void PartSet_WidgetPoint2D::mouseReleased(ModuleBase_IViewWindow* theWindow, QMo
       }
     }
     if (!anExternal) {
-      double aX, aY;
+      double aX = 0, aY = 0;
       bool isProcessed = false;
       if (getPoint2d(aView, aShape, aX, aY) && isFeatureContainsPoint(myFeature, aX, aY)) {
         // when the point is selected, the coordinates of the point should be set into the attribute
@@ -726,15 +728,18 @@ void PartSet_WidgetPoint2D::mouseReleased(ModuleBase_IViewWindow* theWindow, QMo
       ResultPtr aFixedObject =
           PartSet_Tools::findFixedObjectByExternal(aShape, aAIS->object(), mySketch);
       if (!aFixedObject.get())
+      {
+        FeaturePtr aCreatedFeature;
         aFixedObject = PartSet_Tools::createFixedByExternalCenter(aAIS->object(), aAIS->edge(),
-                                                                  aAIS->centerType(), mySketch);
+          aAIS->centerType(), mySketch, false, aCreatedFeature);
+      }
       if (aFixedObject.get())
         setConstraintToObject(aFixedObject);
       // fignal updated should be flushed in order to visualize possible created
       // external objects e.g. selection of trihedron axis when input end arc point
       updateObject(feature());
 
-      double aX, aY;
+      double aX = 0, aY = 0;
       if (getPoint2d(aView, aShape, aX, aY)) {
         // do not create a constraint to the point, which already used by the feature
         // if the feature contains the point, focus is not switched
@@ -747,11 +752,11 @@ void PartSet_WidgetPoint2D::mouseReleased(ModuleBase_IViewWindow* theWindow, QMo
   else {
     // A case when point is taken from mouse event
     gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView());
-    double aX, anY;
-    PartSet_Tools::convertTo2D(aPoint, mySketch, aView, aX, anY);
+    double aX = 0, aY = 0;
+    PartSet_Tools::convertTo2D(aPoint, mySketch, aView, aX, aY);
 
     // if the feature contains the point, focus is not switched
-    if (!setPoint(aX, anY) || isFeatureContainsPoint(myFeature, aX, anY))
+    if (!setPoint(aX, aY) || isFeatureContainsPoint(myFeature, aX, aY))
       return;
 
     emit focusOutWidget(this);
@@ -784,13 +789,13 @@ void PartSet_WidgetPoint2D::mouseMoved(ModuleBase_IViewWindow* theWindow, QMouse
 
   gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView());
 
-  double aX, anY;
-  PartSet_Tools::convertTo2D(aPoint, mySketch, theWindow->v3dView(), aX, anY);
+  double aX = 0, aY = 0;
+  PartSet_Tools::convertTo2D(aPoint, mySketch, theWindow->v3dView(), aX, aY);
   if (myState != ModifiedInViewer)
     storeCurentValue();
   // we need to block the value state change
   bool isBlocked = blockValueState(true);
-  setPoint(aX, anY);
+  setPoint(aX, aY);
   blockValueState(isBlocked);
   setValueState(ModifiedInViewer);
 }
index 314308723a7354388c29984fcfbc1ba28a63931f..aa4fbc47752dcc0e7ac195bdbba69ff6d2f7cbc4 100755 (executable)
@@ -68,6 +68,11 @@ Q_OBJECT
   /// Destructor
   virtual ~PartSet_WidgetPoint2D();
 
+  /// Fills given container with selection modes if the widget has it
+  /// \param [out] theModuleSelectionModes module additional modes, -1 means all default modes
+  /// \param theModes [out] a container of modes
+  virtual void selectionModes(int& theModuleSelectionModes, QIntList& theModes);
+
   /// Checks if the selection presentation is valid in widget
   /// \param theValue a selected presentation in the view
   /// \return a boolean value
index ead2a719aab71e133fe8ea75ac919d9eeca000c6..fb8a9df78fc57d065b234694a568541f4fa2a364 100755 (executable)
@@ -19,6 +19,8 @@
 //
 
 #include "PartSet_WidgetShapeSelector.h"
+
+#include "PartSet_CenterPrs.h"
 #include "PartSet_Module.h"
 #include "PartSet_SketcherMgr.h"
 
@@ -58,23 +60,27 @@ PartSet_WidgetShapeSelector::~PartSet_WidgetShapeSelector()
 }
 
 //********************************************************************
-bool PartSet_WidgetShapeSelector::activateSelectionAndFilters(bool toActivate)
+void PartSet_WidgetShapeSelector::selectionFilters(QIntList& theModuleSelectionFilters,
+                                                   SelectMgr_ListOfFilter& theSelectionFilters)
 {
-  bool aHasSelectionFilter = ModuleBase_WidgetShapeSelector::activateSelectionAndFilters
-                                                                           (toActivate);
+  ModuleBase_WidgetShapeSelector::selectionFilters(theModuleSelectionFilters, theSelectionFilters);
+
   if (!myUseSketchPlane) {
-    XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
-    PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(aWorkshop->module());
-    bool isUsePlaneFilterOnly = !toActivate;
-    aModule->sketchMgr()->activatePlaneFilter(isUsePlaneFilterOnly);
+    if (theModuleSelectionFilters.contains(SF_SketchPlaneFilter))
+      theModuleSelectionFilters.removeAll(SF_SketchPlaneFilter);
   }
-  return aHasSelectionFilter;
 }
 
 //********************************************************************
 bool PartSet_WidgetShapeSelector::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs)
 {
-  bool aValid = ModuleBase_WidgetShapeSelector::isValidSelectionCustom(thePrs);
+  bool aValid = false;
+  if (thePrs.get() && thePrs->interactive().get() &&
+      thePrs->interactive()->IsKind(STANDARD_TYPE(PartSet_CenterPrs)))
+    aValid = true; // we should not check acceptSubShape for such presentation
+  else
+    aValid = ModuleBase_WidgetShapeSelector::isValidSelectionCustom(thePrs);
+
   if (aValid) {
     ObjectPtr anObject = myWorkshop->selection()->getResult(thePrs);
     aValid = myExternalObjectMgr->isValidObject(anObject);
index 5d531c4733fa415090be722d70d76ba7a79bdea5..8bf7505ff979b3fb712c70413811a47d8fac5864 100644 (file)
@@ -54,9 +54,11 @@ Q_OBJECT
   /// Retrurns installed sketcher
   CompositeFeaturePtr sketch() const { return mySketch; }
 
-  /// Activate or deactivate selection and selection filters
-  /// \param toActivate boolean state whether it should be activated/deactivated
-  virtual bool activateSelectionAndFilters(bool toActivate);
+  /// Appends into container of workshop selection filters
+  /// \param [out] theModuleSelectionFilters module additional modes, -1 means all default modes
+  /// \param [out] theSelectionFilters selection filters
+  virtual void selectionFilters(QIntList& theModuleSelectionFilters,
+                                SelectMgr_ListOfFilter& theSelectionFilters);
 
 protected:
   /// Checks the widget validity. By default, it returns true.
index f31198234f3d9be6d5d423019c3021f3522d811f..7f9fc5adae6c9a4a3725f0d91e36e1138b66b86a 100644 (file)
@@ -327,10 +327,12 @@ bool PartSet_WidgetSketchCreator::setSelection(QList<ModuleBase_ViewerPrsPtr>& t
 }
 
 //********************************************************************
-void PartSet_WidgetSketchCreator::onSelectionChanged()
+bool PartSet_WidgetSketchCreator::processSelection()
 {
   QList<ModuleBase_ViewerPrsPtr> aSelected = getFilteredSelected();
   bool isDone = setSelection(aSelected, true/*false*/);
+
+  return isDone;
 }
 
 //********************************************************************
index 58f8922dc391d4d3513af94f950b55c32929c76d..a37ec0d1dc63257a6f8dbaf275a1d0d3bcbc8e1b 100644 (file)
@@ -121,9 +121,9 @@ protected:
   /// \param theDone a state whether the selection is set
   void updateOnSelectionChanged(const bool theDone);
 
-protected slots:
-  /// Slot which is called on selection event
-  virtual void onSelectionChanged();
+protected:
+  /// Returns true if envent is processed.
+  virtual bool processSelection();
 
 private:
   /// Returns true if the selection mode is active. This is when composition feature has no
index 63cd3927ee2a66112b1837dd45677cc43786346a..96a84446d9d17eab9a8804e2d17643f13b3d1b32 100644 (file)
 
 #include "SketchPlugin_SketchEntity.h"
 
-#include <XGUI_Workshop.h>
+#include <XGUI_ActionsMgr.h>
 #include <XGUI_Displayer.h>
-#include <XGUI_SelectionMgr.h>
+#include <XGUI_ModuleConnector.h>
+#include <XGUI_SelectionActivate.h>
 #include <XGUI_Selection.h>
-#include <XGUI_ViewerProxy.h>
-#include <XGUI_ActionsMgr.h>
+#include <XGUI_SelectionMgr.h>
 #include <XGUI_Tools.h>
-#include <XGUI_ModuleConnector.h>
+#include <XGUI_ViewerProxy.h>
+#include <XGUI_Workshop.h>
+
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_Tools.h>
 
 #include <ModuleBase_Operation.h>
 #include <ModuleBase_ViewerPrs.h>
 #include <ModuleBase_Tools.h>
 #include <ModuleBase_IModule.h>
 
-#include <ModelAPI_ResultBody.h>
-#include <ModelAPI_Tools.h>
-
 #include <GeomAlgoAPI_FaceBuilder.h>
 #include <GeomAlgoAPI_ShapeTools.h>
 #include <GeomDataAPI_Point.h>
@@ -193,18 +194,24 @@ QList<QWidget*> PartSet_WidgetSketchLabel::getControls() const
   return aResult;
 }
 
-void PartSet_WidgetSketchLabel::onSelectionChanged()
+bool PartSet_WidgetSketchLabel::processSelection()
 {
+  std::shared_ptr<GeomAPI_Pln> aPlane = plane();
+  if (aPlane.get())
+    return false;
+
   QList<ModuleBase_ViewerPrsPtr> aSelected = getFilteredSelected();
 
   if (aSelected.empty())
-    return;
+    return false;
   ModuleBase_ViewerPrsPtr aPrs = aSelected.first();
   bool aDone = setSelectionInternal(aSelected, false);
   if (aDone) {
     updateByPlaneSelected(aPrs);
     updateObject(myFeature);
   }
+
+  return aDone;
 }
 
 void PartSet_WidgetSketchLabel::onShowConstraint(bool theOn)
@@ -347,6 +354,20 @@ void PartSet_WidgetSketchLabel::updateByPlaneSelected(const ModuleBase_ViewerPrs
     if (aRotate) {
       myWorkshop->viewer()->setViewProjection(aXYZ.X(), aXYZ.Y(), aXYZ.Z(), aTwist);
     }
+    QString aSizeOfViewStr = mySizeOfView->text();
+    if (!aSizeOfViewStr.isEmpty()) {
+      bool isOk;
+      double aSizeOfView = aSizeOfViewStr.toDouble(&isOk);
+      if (isOk && aSizeOfView > 0) {
+        Handle(V3d_View) aView3d = myWorkshop->viewer()->activeView();
+        if (!aView3d.IsNull()) {
+          Bnd_Box aBndBox;
+          double aHalfSize = aSizeOfView/2.0;
+          aBndBox.Update(-aHalfSize, -aHalfSize, -aHalfSize, aHalfSize, aHalfSize, aHalfSize);
+          aView3d->FitAll(aBndBox, 0.01, false);
+        }
+      }
+    }
     PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
     if (aModule)
       aModule->onViewTransformed();
@@ -356,17 +377,14 @@ void PartSet_WidgetSketchLabel::updateByPlaneSelected(const ModuleBase_ViewerPrs
   //myLabel->setText("");
   //myLabel->setToolTip("");
   XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
-  disconnect(aWorkshop->selector(), SIGNAL(selectionChanged()),
-              this, SLOT(onSelectionChanged()));
-  // 4. deactivate face selection filter
-  activateFilters(false);
 
   // 5. Clear selection mode and define sketching mode
   emit planeSelected(plane());
   // after the plane is selected in the sketch, the sketch selection should be activated
   // it can not be performed in the sketch label widget because, we don't need to switch off
   // the selection by any label deactivation, but need to switch it off by stop the sketch
-  activateSelection(true);
+  myWorkshop->selectionActivate()->updateSelectionFilters();
+  myWorkshop->selectionActivate()->updateSelectionModes();
 
   // 6. Update sketcher actions
   XGUI_ActionsMgr* anActMgr = aWorkshop->actionsMgr();
@@ -492,7 +510,6 @@ void PartSet_WidgetSketchLabel::activateCustom()
   std::shared_ptr<GeomAPI_Pln> aPlane = plane();
   if (aPlane.get()) {
     myStackWidget->setCurrentIndex(1);
-    activateSelection(true);
     return;
   }
 
@@ -502,7 +519,7 @@ void PartSet_WidgetSketchLabel::activateCustom()
   // Clear previous selection mode It is necessary for correct activation of preview planes
   XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
   XGUI_Displayer* aDisp = aWorkshop->displayer();
-  aDisp->activateObjects(QIntList(), aDisp->displayedObjects(), false);
+  aWorkshop->selectionActivate()->activateObjects(QIntList(), aDisp->displayedObjects(), false);
 
   if (!aBodyIsVisualized) {
     // We have to select a plane before any operation
@@ -511,43 +528,35 @@ void PartSet_WidgetSketchLabel::activateCustom()
   }
   else
     mySizeOfViewWidget->setVisible(false);
-
-  activateSelection(true);
-
-  connect(XGUI_Tools::workshop(myWorkshop)->selector(), SIGNAL(selectionChanged()),
-          this, SLOT(onSelectionChanged()));
-  activateFilters(true);
 }
 
 void PartSet_WidgetSketchLabel::deactivate()
 {
-  ModuleBase_ModelWidget::deactivate();
+  ModuleBase_WidgetValidated::deactivate();
   bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
   myPreviewPlanes->erasePreviewPlanes(myWorkshop);
-  activateSelection(false);
 
-  activateFilters(false);
   if (aHidePreview)
     myWorkshop->viewer()->update();
 }
 
-void PartSet_WidgetSketchLabel::activateSelection(bool toActivate)
+void PartSet_WidgetSketchLabel::selectionModes(int& theModuleSelectionModes, QIntList& theModes)
 {
-  if (toActivate) {
-    QIntList aModes;
-    std::shared_ptr<GeomAPI_Pln> aPlane = plane();
-    if (aPlane.get()) {
-      myWorkshop->module()->activeSelectionModes(aModes);
-    }
-    else {
-      aModes << TopAbs_FACE;
-    }
-    myWorkshop->activateSubShapesSelection(aModes);
-  } else {
-    myWorkshop->deactivateSubShapesSelection();
-  }
+  theModuleSelectionModes = -1;
+  std::shared_ptr<GeomAPI_Pln> aPlane = plane();
+  if (!aPlane.get())
+    theModes << TopAbs_FACE;
 }
 
+void PartSet_WidgetSketchLabel::selectionFilters(QIntList& theModuleSelectionFilters,
+                                                 SelectMgr_ListOfFilter& theSelectionFilters)
+{
+  std::shared_ptr<GeomAPI_Pln> aPlane = plane();
+  if (aPlane.get())
+    return;
+  return ModuleBase_WidgetValidated::selectionFilters(theModuleSelectionFilters,
+                                                      theSelectionFilters);
+}
 
 std::shared_ptr<GeomAPI_Dir>
   PartSet_WidgetSketchLabel::setSketchPlane(const TopoDS_Shape& theShape)
index 5cc4a10cf76049ac3b633341362dcc22228c420c..a87a70acf58c310a68aeaac9c853c8d3e8d39665 100644 (file)
@@ -73,6 +73,17 @@ public:
   virtual bool setSelection(QList<std::shared_ptr<ModuleBase_ViewerPrs>>& theValues,
                             const bool theToValidate);
 
+  /// Fills given container with selection modes if the widget has it
+  /// \param [out] theModuleSelectionModes module additional modes, -1 means all default modes
+  /// \param theModes [out] a container of modes
+  virtual void selectionModes(int& theModuleSelectionModes, QIntList& theModes);
+
+  /// Using widget selection filter only if plane is not defined.
+  /// \param [out] theModuleSelectionFilters module additional modes, -1 means all default modes
+  /// \param [out] selection filters
+  virtual void selectionFilters(QIntList& theModuleSelectionFilters,
+                                SelectMgr_ListOfFilter& theSelectionFilters);
+
   /// Returns list of widget controls
   /// \return a control list
   virtual QList<QWidget*> getControls() const;
@@ -80,6 +91,9 @@ public:
   /// The methiod called when widget is deactivated
   virtual void deactivate();
 
+  /// The method called if widget should be activated always
+  virtual bool needToBeActiated() { return true; }
+
   /// Returns sketcher plane
   std::shared_ptr<GeomAPI_Pln> plane() const;
 
@@ -150,6 +164,9 @@ protected:
                               bool& isAttributeSetInitializedBlocked,
                               bool& isAttributeSendUpdatedBlocked);
 
+  /// Returns true if envent is processed.
+  virtual bool processSelection();
+
   /// Set the given wrapped value to the current widget
   /// This value should be processed in the widget according to the needs
   /// The method is called by the current operation to process the operation preselection.
@@ -168,14 +185,7 @@ protected:
   /// \param thePrs a presentation
   bool fillSketchPlaneBySelection(const std::shared_ptr<ModuleBase_ViewerPrs>& thePrs);
 
- protected:
-  /// Activate or deactivate selection
-  void activateSelection(bool toActivate);
-
- private slots:
-   /// Slot on change selection
-  void onSelectionChanged();
-
+private slots:
   /// A slot called on set sketch plane view
   void onSetPlaneView();
 
@@ -183,7 +193,7 @@ protected:
   /// \param theOn a flag show constraints or not
   void onShowConstraint(bool theOn);
 
- private:
+private:
   /// Set sketch plane by shape
   /// \param theShape a planar face
   std::shared_ptr<GeomAPI_Dir> setSketchPlane(const TopoDS_Shape& theShape);
index 800ce0e05fbec009dcfc5543ffc70186ca71dc30..aad9beb92d98a9730d5f7fa0dc174bcd15cc5abb 100644 (file)
@@ -132,7 +132,7 @@ def bottom_body():
 
 def body_3():
     # Create XOZ sketch
-    sketch = model.addSketch(part, "Boolean_1_1/Modified_3")
+    sketch = model.addSketch(part, "Boolean_1_1/Modified_Face_3")
 
     # Create base polygon
     H, L, l, r = 28, 40, 8, 12
@@ -170,7 +170,7 @@ def body_3():
     sketch.setRadius(arc, r)
 
     # Binding
-    bottom_e = sketch.addLine("Boolean_1_1/Modified_8&Boolean_1_1/Modified_5")
+    bottom_e = sketch.addLine("Boolean_1_1/Modified_Face_8&Boolean_1_1/Modified_Face_5")
     sketch.setCoincident(bottom_e, bottom.startPoint())
     sketch.setCoincident(bottom_e.startPoint(), bottom.endPoint())
 
@@ -183,7 +183,7 @@ def body_3():
 
 def body_4():
     # Create XOZ 2nd sketch
-    sketch = model.addSketch(part, "Boolean_2_1/Modified_4")
+    sketch = model.addSketch(part, "Boolean_2_1/Modified_Face_4")
 
     # Create base polygon
     points = [(0, 0), (0, 1), (1, 0)]
@@ -192,11 +192,11 @@ def body_4():
     left, diagonal, bottom = model.addPolygon(sketch, *geom_points)
 
     # Binding
-    bottom_e = sketch.addLine("Boolean_2_1/Modified_3&Boolean_2_1/Modified_4")
+    bottom_e = sketch.addLine("Boolean_2_1/Modified_Face_3&Boolean_2_1/Modified_Face_4")
     sketch.setCoincident(bottom_e.endPoint(), bottom.startPoint())
     sketch.setCoincident(bottom_e.startPoint(), left.startPoint())
 
-    left_e = sketch.addLine("Boolean_2_1/Modified_6&Boolean_2_1/Modified_7")
+    left_e = sketch.addLine("Boolean_2_1/Modified_Face_6&Boolean_2_1/Modified_Face_7")
     sketch.setCoincident(left_e.startPoint(), left.endPoint())
 
     model.do()  #!!!
index 1556669bf59169b91825a4d74842d646bffad431..ad57a024e866706854273323bb9baa504efa5d52 100644 (file)
@@ -1,5 +1,6 @@
 """Package for Build plugin for the Parametric Geometry API of the Modeler.
 """
 
-from BuildAPI import addVertex, addEdge, addWire, addFace, addShell
+from BuildAPI import addVertex, addEdge, addWire, addFace, addShell, addSolid, addCompSolid, addCompound
 from BuildAPI import addSubShapes
+from BuildAPI import addFilling
index f56860b041d968cb95d73b4ab6735ba97c92081a..5cb8cd081073ef6cbde2bd33ef13cf4d6015f446 100644 (file)
@@ -61,8 +61,9 @@ class DumpAssistant(ModelHighAPI.ModelHighAPI_Dumper):
         aFeatureKind = theFeature.getKind()
         if aFeatureKind in self.myFeatures:
             # Dump only feature created by user (in history).
+            # Also dump Export features (hard-coded here in order not to change the data model).
             # For all other features, just keep their name.
-            if theForce or theFeature.isInHistory():
+            if theForce or theFeature.isInHistory() or aFeatureKind=="Export":
                 self.myFeatures[aFeatureKind](theFeature).dump(self)
             else:
                 self.name(theFeature)
@@ -72,6 +73,11 @@ class DumpAssistant(ModelHighAPI.ModelHighAPI_Dumper):
             # In case of theFeature is not a constraint, it will not be dumped.
             self.myFeatures[SketchAPI.SketchAPI_Constraint.ID()](theFeature).dump(self)
 
+    ## Create wrapper for a folder and dump it
+    def dumpFolder(self, theFolder):
+        if theFolder.ID() in self.myFeatures:
+            self.myFeatures[theFolder.ID()](theFolder).dump(self)
+
     ## Dump all parameters
     def dumpParameter(self, theFeature):
         aFeatureKind = theFeature.getKind()
index a69fea2d010d28f9cb992ecfdaef9b1f10b2e4c9..0347b26b273484f14c39702e969245bb5e132788 100644 (file)
@@ -9,3 +9,4 @@ from FeaturesAPI import addPipe
 from FeaturesAPI import addCut, addFuse, addCommon, addSmash, addFill
 from FeaturesAPI import addIntersection, addPartition, addUnion, addRemoveSubShapes
 from FeaturesAPI import addRecover
+from FeaturesAPI import addFillet
index 8c15e89ecaf19521c50982e8cf42c9c133bbacd0..db5279d84ec6c7995b930b2522c2602f434b5636 100644 (file)
@@ -8,5 +8,6 @@ from ModelHighAPI import apply as do
 from ModelHighAPI import updateFeatures
 from ModelHighAPI import undo, redo
 from ModelHighAPI import reset
+from ModelHighAPI import addFolder
 from ModelHighAPI import ModelHighAPI_Selection as selection
 from ModelHighAPI import checkPythonDump as checkPythonDump
index 0b49118b289a8eef36e4d72ecc3c90c74508489f..263ed65d8967b629c653fbe4e51febf03985c5ee 100644 (file)
@@ -198,31 +198,45 @@ def testHaveNamingEdges(theFeature, theModel, thePartDoc) :
     assert(shape.isEdge())
     assert(name != ""), "String empty"
 
-def testHaveNamingVertices(theFeature, theModel, thePartDoc) :
-  """ Tests if all vertices of result have a unique name
+def testHaveNamingByType(theFeature, theModel, thePartDoc, theSubshapeType) :
+  """ Tests if all sub-shapes of result have a unique name
   :param theFeature: feature to test.
+  :param theSubshapeType: type of sub-shape
   """
-  # Get feature result/sub-result
-  aResult = theFeature.results()[0].resultSubShapePair()[0]
-  # Get result/sub-result shape
-  shape = aResult.shape()
-  # Create shape explorer with desired shape type
-  shapeExplorer = GeomAPI_ShapeExplorer(shape, GeomAPI_Shape.VERTEX)
-  # Create list, and store selections in it
+  aFirstRes = theFeature.results()[0]
+  # Get number of sub-results
+  hasSubs = True
+  nbSubs = aFirstRes.numberOfSubs()
+  if nbSubs == 0:
+    # no sub-results => treat current result as a sub
+    hasSubs = False
+    nbSubs = 1
+
   selectionList = []
   shapesList = [] # to append only unique shapes (not isSame)
-  while shapeExplorer.more():
-    aDuplicate = False
-    for alreadyThere in shapesList:
-      if alreadyThere.isSame(shapeExplorer.current()):
-        aDuplicate = True
-    if aDuplicate:
+  for sub in range(0, nbSubs):
+    # Get feature result/sub-result
+    if hasSubs:
+      aResult = aFirstRes.subResult(sub).resultSubShapePair()[0]
+    else:
+      aResult = aFirstRes.resultSubShapePair()[0]
+    # Get result/sub-result shape
+    shape = aResult.shape()
+    # Create shape explorer with desired shape type
+    shapeExplorer = GeomAPI_ShapeExplorer(shape, theSubshapeType)
+    # Create list, and store selections in it
+    while shapeExplorer.more():
+      aDuplicate = False
+      for alreadyThere in shapesList:
+        if alreadyThere.isSame(shapeExplorer.current()):
+          aDuplicate = True
+      if aDuplicate:
+        shapeExplorer.next()
+        continue
+      shapesList.append(shapeExplorer.current())
+      selection = theModel.selection(aResult, shapeExplorer.current()) # First argument should be result/sub-result, second is sub-shape on this result/sub-result
+      selectionList.append(selection)
       shapeExplorer.next()
-      continue
-    shapesList.append(shapeExplorer.current())
-    selection = theModel.selection(aResult, shapeExplorer.current()) # First argument should be result/sub-result, second is sub-shape on this result/sub-result
-    selectionList.append(selection)
-    shapeExplorer.next()
   # Create group with this selection list
   Group_1 = theModel.addGroup(thePartDoc, selectionList)
   theModel.do()
@@ -236,11 +250,23 @@ def testHaveNamingVertices(theFeature, theModel, thePartDoc) :
     attrSelection = groupSelectionList.value(index)
     shape = attrSelection.value()
     name = attrSelection.namingName()
-    assert(shape.isVertex())
+    if theSubshapeType == GeomAPI_Shape.VERTEX:
+      assert(shape.isVertex())
+    elif theSubshapeType == GeomAPI_Shape.EDGE:
+      assert(shape.isEdge())
+    elif theSubshapeType == GeomAPI_Shape.FACE:
+      assert(shape.isFace())
     assert(name != ""), "String empty"
     presented_names.add(name)
   assert(len(presented_names) == groupSelectionList.size()), "Some names are not unique"
 
+def testHaveNamingSubshapes(theFeature, theModel, thePartDoc) :
+  """ Tests if all vertices/edges/faces of result have a unique name
+  :param theFeature: feature to test.
+  """
+  testHaveNamingByType(theFeature, theModel, thePartDoc, GeomAPI_Shape.VERTEX)
+  testHaveNamingByType(theFeature, theModel, thePartDoc, GeomAPI_Shape.EDGE)
+  testHaveNamingByType(theFeature, theModel, thePartDoc, GeomAPI_Shape.FACE)
 
 def testNbSubFeatures(theComposite, theKindOfSub, theExpectedCount):
   """ Tests number of sub-features of the given type
@@ -271,8 +297,8 @@ def checkBooleansResult(theFeature,theModel,NbRes,NbSubRes,NbSolid,NbFace,NbEdge
   """ Tests numbers of sub-shapes in results (used in Boolean operations tests)
   """
   theModel.testNbResults(theFeature, NbRes)
-  theModel.testNbSubResults(theFeature,NbSubRes)
-  theModel.testNbSubShapes(theFeature, GeomAPI_Shape.SOLID, NbSolid )
+  theModel.testNbSubResults(theFeature, NbSubRes)
+  theModel.testNbSubShapes(theFeature, GeomAPI_Shape.SOLID, NbSolid)
   theModel.testNbSubShapes(theFeature, GeomAPI_Shape.FACE, NbFace)
   theModel.testNbSubShapes(theFeature, GeomAPI_Shape.EDGE, NbEdge)
   theModel.testNbSubShapes(theFeature, GeomAPI_Shape.VERTEX, NbVertex)
index 42c1b509051cf3f21dd89169ac2eb9a8b1af11bc..20524c9030f8fa31d56b65aa199c8ec559f6b905 100644 (file)
@@ -30,6 +30,8 @@
 #include <XGUI_OperationMgr.h>
 #include <XGUI_Displayer.h>
 #include <XGUI_MenuMgr.h>
+#include <XGUI_FacesPanel.h>
+#include <XGUI_SelectionActivate.h>
 
 #include <ModuleBase_Operation.h>
 #include <ModuleBase_Preferences.h>
@@ -322,6 +324,7 @@ bool SHAPERGUI::deactivateModule(SUIT_Study* theStudy)
     mySelector = 0;
   }
 
+  myWorkshop->hidePanel(myWorkshop->facesPanel());
   //myWorkshop->contextMenuMgr()->disconnectViewer();
 
   SUIT_ResourceMgr* aResMgr = application()->resourceMgr();
@@ -351,7 +354,8 @@ void SHAPERGUI::onViewManagerAdded(SUIT_ViewManager* theMgr)
 {
   if (!mySelector) {
     mySelector = createSelector(theMgr);
-    myWorkshop->module()->activateSelectionFilters();
+    myWorkshop->selectionActivate()->updateSelectionFilters();
+    myWorkshop->selectionActivate()->updateSelectionModes();
     myWorkshop->synchronizeViewer();
   }
 }
index 2175e6a780c68cf81a80946eb96711d2cc4cec78..f9f5fb5bede2e9af4f36f7f87322dd57fdfe32a3 100755 (executable)
@@ -77,6 +77,7 @@ ADD_LIBRARY(SamplePanelPlugin MODULE
 TARGET_LINK_LIBRARIES(SamplePanelPlugin ${PROJECT_LIBRARIES})
 
 INCLUDE_DIRECTORIES(
+  ${CAS_INCLUDE_DIRS}
   ../Config
   ../Events
   ../ModelAPI
index c5a75fef3a135a6dacc4f8feaee90d7a74007f61..82b5dfab474f323c0f1634ec230e4b25c5f98cfa 100644 (file)
@@ -169,6 +169,18 @@ void SketchAPI_Constraint::dump(ModelHighAPI_Dumper& theDumper) const
       return;
   }
 
+  // Check all attributes are already dumped. If not, store the constraint as postponed.
+  bool areAttributesDumped = true;
+  for (int i = 0; i < CONSTRAINT_ATTR_SIZE && areAttributesDumped; ++i) {
+    AttributeRefAttrPtr aRefAttr = aBase->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
+    if (aRefAttr && aRefAttr->isInitialized())
+      areAttributesDumped = theDumper.isDumped(aRefAttr);
+  }
+  if (!areAttributesDumped) {
+    theDumper.postpone(aBase);
+    return;
+  }
+
   bool isAngle = aBase->getKind() == SketchPlugin_ConstraintAngle::ID();
   std::string aSetterSuffix;
   if (isAngle)
@@ -187,8 +199,14 @@ void SketchAPI_Constraint::dump(ModelHighAPI_Dumper& theDumper) const
     }
   }
 
-  AttributeDoublePtr aValueAttr = aBase->real(
-      isAngle ? SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID() :SketchPlugin_Constraint::VALUE());
+  AttributeDoublePtr aValueAttr;
+  if (isAngle)
+    aValueAttr = aBase->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID());
+  else if (aBase->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID() ||
+           aBase->getKind() == SketchPlugin_ConstraintDistanceVertical::ID())
+    aValueAttr = aBase->real(SketchPlugin_ConstraintDistanceAlongDir::DISTANCE_VALUE_ID());
+  else
+    aValueAttr = aBase->real(SketchPlugin_Constraint::VALUE());
   if (aValueAttr && aValueAttr->isInitialized())
     theDumper << ", " << aValueAttr;
 
index b13e94f03abc6cc5a233985f818d0e65fe86db20..73f13635d9f67e51c5193374021b197da88b3723 100644 (file)
@@ -70,8 +70,16 @@ void SketchAPI_Mirror::dump(ModelHighAPI_Dumper& theDumper) const
   FeaturePtr aBase = feature();
   const std::string& aSketchName = theDumper.parentName(aBase);
 
+
   AttributeRefAttrPtr aMirrorLine = mirrorLine();
   AttributeRefListPtr aMirrorObjects = mirrorList();
+
+  // Check all attributes are already dumped. If not, store the constraint as postponed.
+  if (!theDumper.isDumped(aMirrorLine) || !theDumper.isDumped(aMirrorObjects)) {
+    theDumper.postpone(aBase);
+    return;
+  }
+
   theDumper << aBase << " = " << aSketchName << ".addMirror(" << aMirrorLine << ", "
             << aMirrorObjects << ")" << std::endl;
 
index b217ad0b3ef4affa412db57e9b5ddecd4e4c1bab..a736df25b8f759e1d19d9de19d71d93a24de1698 100644 (file)
@@ -86,6 +86,12 @@ void SketchAPI_Rotation::dump(ModelHighAPI_Dumper& theDumper) const
   AttributeIntegerPtr aNbCopies = numberOfObjects();
   bool isFullValue = valueType()->value() != "SingleAngle";
 
+  // Check all attributes are already dumped. If not, store the constraint as postponed.
+  if (!theDumper.isDumped(aCenter) || !theDumper.isDumped(aRotObjects)) {
+    theDumper.postpone(aBase);
+    return;
+  }
+
   theDumper << aBase << " = " << aSketchName << ".addRotation("
             << aRotObjects << ", " << aCenter << ", " << anAngle << ", " << aNbCopies;
   if (isFullValue)
index 5f36a0872b89739ee9b13bbe9dfe7da691049ed7..63e7a10f451ac8b68b5728ecb1e82a98bb9cbab8 100644 (file)
@@ -671,7 +671,8 @@ std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setHorizontalDistance(
       compositeFeature()->addFeature(SketchPlugin_ConstraintDistanceHorizontal::ID());
   fillAttribute(thePoint1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
   fillAttribute(thePoint2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
-  fillAttribute(theValue, aFeature->real(SketchPlugin_Constraint::VALUE()));
+  fillAttribute(theValue,
+      aFeature->real(SketchPlugin_ConstraintDistanceAlongDir::DISTANCE_VALUE_ID()));
   aFeature->execute();
   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
 }
@@ -685,7 +686,8 @@ std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setVerticalDistance(
       compositeFeature()->addFeature(SketchPlugin_ConstraintDistanceVertical::ID());
   fillAttribute(thePoint1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
   fillAttribute(thePoint2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
-  fillAttribute(theValue, aFeature->real(SketchPlugin_Constraint::VALUE()));
+  fillAttribute(theValue,
+      aFeature->real(SketchPlugin_ConstraintDistanceAlongDir::DISTANCE_VALUE_ID()));
   aFeature->execute();
   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
 }
index 05dcb1c8f994fd05a3f1b34a9e166767e4235942..dddf3b4ad7b0455eca4f2573a182f21a7471d295 100644 (file)
@@ -86,6 +86,13 @@ void SketchAPI_Translation::dump(ModelHighAPI_Dumper& theDumper) const
   AttributeIntegerPtr aNbCopies = numberOfObjects();
   bool isFullValue = valueType()->value() != "SingleValue";
 
+  // Check all attributes are already dumped. If not, store the constraint as postponed.
+  if (!theDumper.isDumped(aStart) || !theDumper.isDumped(aEnd) ||
+      !theDumper.isDumped(aTransObjects)) {
+    theDumper.postpone(aBase);
+    return;
+  }
+
   theDumper << aBase << " = " << aSketchName << ".addTranslation("
             << aTransObjects << ", " << aStart << ", " << aEnd << ", " << aNbCopies;
   if (isFullValue)
index 30bf99ae12333c80636975b6bf4cd366752653e4..c49b4913023edcb1a934f9b8298b6319dbf8ae2e 100644 (file)
@@ -179,6 +179,7 @@ ADD_UNIT_TESTS(TestSketchPointLine.py
                TestConstraintTangent.py
                TestConstraintAngle.py
                TestConstraintMiddlePoint.py
+               TestEdgesOrder.py
                TestMirror.py
                TestMultiRotation.py
                TestMultiTranslation.py
@@ -216,6 +217,7 @@ ADD_UNIT_TESTS(TestSketchPointLine.py
                TestTrimLine02.py
                Test2229.py
                Test2239.py
+               TestDistanceDump.py
                TestDistanceSignedVsUnsigned01.py
                TestDistanceSignedVsUnsigned02.py
                TestDistanceSignedVsUnsigned03.py
@@ -226,6 +228,7 @@ ADD_UNIT_TESTS(TestSketchPointLine.py
                Test2273.py
                Test2280.py
                Test2287.py
+               Test2341.py
 )
 
 if(${SKETCHER_CHANGE_RADIUS_WHEN_MOVE})
index 1981738505a0213ab9350ba4701f6598f3f229ee..0f441f3905ff237d3088cf21717c8dd3046c2803 100644 (file)
@@ -75,14 +75,17 @@ void SketchPlugin_Projection::execute()
     return;
   FeaturePtr aProjection = ModelAPI_Feature::feature(aRefAttr->object());
 
-  if (!lastResult().get() && aProjection->lastResult().get()) {
+  if (!lastResult().get()) {
+    bool hasProjResult = aProjection->lastResult().get() != NULL;
     ResultConstructionPtr aConstr = document()->createConstruction(data());
-    aConstr->setShape(aProjection->lastResult()->shape());
+    if (hasProjResult)
+      aConstr->setShape(aProjection->lastResult()->shape());
     aConstr->setIsInHistory(false);
     aConstr->setDisplayed(false);
     setResult(aConstr);
 
-    aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), lastResult()->shape());
+    if (hasProjResult)
+      aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), lastResult()->shape());
   }
 
   // is sketch plane is changed (issue 1791), attribute of projection is not changed, but
@@ -201,6 +204,10 @@ void SketchPlugin_Projection::computeProjection(const std::string& theID)
     std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
     double aRadius = aCircle->radius();
 
+    double aNormalsDot = aCircle->normal()->dot(aSketchPlane->direction());
+    if (fabs(fabs(aNormalsDot) - 1.0) > tolerance)
+      return; // circle is not in the plane, parallel to the sketch plane
+
     std::shared_ptr<GeomAPI_Pnt> aCenter = aSketchPlane->project(aCircle->center());
     std::shared_ptr<GeomAPI_Pnt2d> aCenterInSketch = sketch()->to2D(aCenter);
 
@@ -224,7 +231,11 @@ void SketchPlugin_Projection::computeProjection(const std::string& theID)
     std::shared_ptr<GeomAPI_Pnt> aCenter = aSketchPlane->project(aCircle->center());
     std::shared_ptr<GeomAPI_Pnt2d> aCenterInSketch = sketch()->to2D(aCenter);
 
-    bool isInversed = aCircle->normal()->dot(aSketchPlane->direction()) < 0.;
+    double aNormalsDot = aCircle->normal()->dot(aSketchPlane->direction());
+    if (fabs(fabs(aNormalsDot) - 1.0) > tolerance)
+      return; // arc is not in the plane, parallel to the sketch plane
+
+    bool isInversed = aNormalsDot < 0.;
 
     if (!hasPrevProj)
       aProjection = sketch()->addFeature(SketchPlugin_Arc::ID());
index a7a8f69b224e7250d4ef0b9ad8ab173509c5f3f9..b254d63d4bc890b7e9ca5d45fcb1cef3c6c77f37 100644 (file)
@@ -317,7 +317,7 @@ void SketchPlugin_Split::execute()
 
   // coincidence to feature
   updateCoincidenceConstraintsToFeature(aCoincidenceToFeature, aFurtherCoincidences,
-                                        aFeatureResults, aSplitFeature);
+                                        aFeatureResults, aSplitFeature, aFeaturesToDelete);
 
   updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes);
 
@@ -875,7 +875,8 @@ void SketchPlugin_Split::updateCoincidenceConstraintsToFeature(
       const std::map<std::shared_ptr<ModelAPI_Feature>, IdToPointPair>& theCoincidenceToFeature,
       const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theFurtherCoincidences,
       const std::set<ResultPtr>& theFeatureResults,
-      const FeaturePtr& theSplitFeature)
+      const FeaturePtr& theSplitFeature,
+      std::set<FeaturePtr>& theFeaturesToDelete)
 {
   if (theCoincidenceToFeature.empty())
     return;
@@ -898,6 +899,9 @@ void SketchPlugin_Split::updateCoincidenceConstraintsToFeature(
   for (; aCIt != aCLast; aCIt++) {
     FeaturePtr aCoincFeature = aCIt->first;
     std::string anAttributeId = aCIt->second.first;
+    std::string aSecondAttribute = anAttributeId == SketchPlugin_Constraint::ENTITY_A() ?
+        SketchPlugin_Constraint::ENTITY_B() : SketchPlugin_Constraint::ENTITY_A();
+
     AttributePoint2DPtr aCoincPoint = aCIt->second.second;
     std::set<AttributePoint2DPtr>::const_iterator aFCIt = theFurtherCoincidences.begin(),
                                                   aFCLast = theFurtherCoincidences.end();
@@ -909,17 +913,16 @@ void SketchPlugin_Split::updateCoincidenceConstraintsToFeature(
         aFeaturePointAttribute = aFCAttribute;
     }
     if (aFeaturePointAttribute.get()) {
-      aCoincFeature->refattr(anAttributeId)->setObject(ResultPtr());
-      aCoincFeature->refattr(anAttributeId)->setAttr(aFeaturePointAttribute);
+      // create new constraint and remove the current
+      aCoincFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
+          aFeaturePointAttribute, aCoincFeature->refattr(aSecondAttribute)->attr());
+      theFeaturesToDelete.insert(aCIt->first);
       // create new coincidences to split feature points
       std::set<AttributePoint2DPtr>::const_iterator aSFIt = aNewCoincidencesToSplitFeature.begin(),
                                                     aSFLast = aNewCoincidencesToSplitFeature.end();
       for (; aSFIt != aSFLast; aSFIt++) {
         AttributePoint2DPtr aSFAttribute = *aSFIt;
         if (aCoincPnt->isEqual(aSFAttribute->pnt())) {
-          std::string aSecondAttribute = SketchPlugin_Constraint::ENTITY_A();
-          if (anAttributeId == SketchPlugin_Constraint::ENTITY_A())
-            aSecondAttribute = SketchPlugin_Constraint::ENTITY_B();
           createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
                            aSFAttribute, aCoincFeature->refattr(aSecondAttribute)->attr());
         }
index 1c9ae40e53441b66a14737ec0cdd42675579968b..37f1e1659c98c331bf483df8a1b8fbc4183a7e09 100644 (file)
@@ -181,12 +181,15 @@ private:
   /// \param theFurtherCoincidences a list of points where coincidences will be build
   /// \param theFeatureResults created results after split where constaint might be connected
   /// \param theSplitFeature feature created by split, new coincidences to points should be created
+  /// \param theFeaturesToDelete the list of removed features (will be updated here by
+  ///                            the coincidences to be removed)
   /// if theCoincidenceToFeature contains equal points
   void updateCoincidenceConstraintsToFeature(
       const std::map<std::shared_ptr<ModelAPI_Feature>, IdToPointPair>& theCoincidenceToFeature,
       const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theFurtherCoincidences,
       const std::set<ResultPtr>& theFeatureResults,
-      const FeaturePtr& theSplitFeature);
+      const FeaturePtr& theSplitFeature,
+      std::set<FeaturePtr>& theFeaturesToDelete);
 
   /// Move constraints from base feature to given feature
   /// \param theFeature a base feature
index aedc763322e4c4969e9a362fe366714debcf09d9..74be0dc1f4854be50af6d6ec28101fe528128e65 100644 (file)
@@ -379,7 +379,7 @@ void SketchPlugin_Trim::execute()
       anIt != aLast; anIt++) {
     AttributePtr anAttribute = *anIt;
 
-    if (setCoincidenceToAttribute(anAttribute, aFurtherCoincidences))
+    if (setCoincidenceToAttribute(anAttribute, aFurtherCoincidences, aFeaturesToDelete))
       continue;
 
     // move tangency constraint to the nearest feature if possible
@@ -533,7 +533,8 @@ std::string SketchPlugin_Trim::processEvent(const std::shared_ptr<Events_Message
 }
 
 bool SketchPlugin_Trim::setCoincidenceToAttribute(const AttributePtr& theAttribute,
-                                const std::set<AttributePoint2DPtr>& theFurtherCoincidences)
+                                const std::set<AttributePoint2DPtr>& theFurtherCoincidences,
+                                std::set<std::shared_ptr<ModelAPI_Feature>>& theFeaturesToDelete)
 {
   FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
   if (aFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID())
@@ -551,12 +552,9 @@ bool SketchPlugin_Trim::setCoincidenceToAttribute(const AttributePtr& theAttribu
     AttributePoint2DPtr aPointAttribute = (*anIt);
     std::shared_ptr<GeomAPI_Pnt2d> aPoint2d = aPointAttribute->pnt();
     if (aPoint2d->isEqual(aRefPnt2d)) {
-      AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-                                                                           theAttribute);
-      if (aRefAttr.get()) {
-        aRefAttr->setAttr(aPointAttribute);
-        aFoundPoint = true;
-      }
+      // create new coincidence and then remove the old one
+      createConstraint(SketchPlugin_ConstraintCoincidence::ID(), aRefPointAttr, aPointAttribute);
+      theFeaturesToDelete.insert(aFeature);
     }
   }
   return aFoundPoint;
index f03c5d59f5bca6622e92ae62ac4135d9af77d781..6ad6a58c4f9b9967966fd24798ecd8dcc92a6f6c 100644 (file)
@@ -117,7 +117,8 @@ class SketchPlugin_Trim : public SketchPlugin_Feature, public GeomAPI_IPresentab
 
 private:
   bool setCoincidenceToAttribute(const AttributePtr& theAttribute,
-            const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theFurtherCoincidences);
+            const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theFurtherCoincidences,
+            std::set<std::shared_ptr<ModelAPI_Feature>>& theFeaturesToDelete);
   /// Move tangency constraint to the feature if it is geometrically closely to it
   /// \param theAttribute an attribute of a tangent constraint feature
   /// \param theFeature a feature that can be set into the attribute
diff --git a/src/SketchPlugin/Test/Test2341.py b/src/SketchPlugin/Test/Test2341.py
new file mode 100644 (file)
index 0000000..a621443
--- /dev/null
@@ -0,0 +1,172 @@
+## Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+"""
+    Test2341.py
+    Test case for issue #2341 "SIGSEGV when trying to move a point of a projected axis"
+"""
+
+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(-5.830951894848558, -7.5, -11, -7.5)
+SketchLine_2 = Sketch_1.addLine(-11, -7.5, -11, -10)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(-11, -10, 11, -10)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(11, -10, 11, -7.5)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(11, -7.5, 5.8309518948453, -7.5)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_2.result(), 2.5)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_4.result(), 2.5)
+SketchConstraintLength_3 = Sketch_1.setLength(SketchLine_3.result(), 22)
+SketchConstraintLength_3.setName("SketchConstraintLength_5")
+SketchLine_6 = Sketch_1.addLine(-6, 12, 6, 12)
+SketchLine_7 = Sketch_1.addLine(6, 12, 6, 8.121320343559642)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchLine_8 = Sketch_1.addLine(-6, 12, -6, 7.365459931328117)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_6.startPoint(), SketchLine_8.startPoint())
+SketchConstraintHorizontal_4 = Sketch_1.setHorizontal(SketchLine_6.result())
+SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_7.result())
+SketchConstraintVertical_4 = Sketch_1.setVertical(SketchLine_8.result())
+SketchConstraintLength_4 = Sketch_1.setLength(SketchLine_6.result(), 12)
+SketchConstraintLength_4.setName("SketchConstraintLength_6")
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchProjection_2 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchProjection_3 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_3 = SketchProjection_3.createdFeature()
+SketchProjection_4 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_4 = SketchProjection_4.createdFeature()
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Point(SketchPoint_4).coordinates(), SketchLine_4.startPoint(), 10)
+SketchProjection_5 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_5 = SketchProjection_5.createdFeature()
+SketchArc_1 = Sketch_1.addArc(0, 0, -5.830951894848558, -7.5, -6, 7.365459931328117, True)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchPoint_5.result(), SketchArc_1.center())
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchArc_1.startPoint())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], 9.5)
+SketchProjection_6 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_6 = SketchProjection_6.createdFeature()
+SketchArc_2 = Sketch_1.addArc(0, 0, 5.8309518948453, -7.5, 7.693909752490621, 5.572589408930978, False)
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchPoint_6.result(), SketchArc_2.center())
+SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchArc_2.startPoint())
+SketchConstraintRadius_2 = Sketch_1.setRadius(SketchArc_2.results()[1], 9.5)
+SketchArc_3 = Sketch_1.addArc(0, 0, 1.561361948645558, 3.6826822922052, 3.682682292205201, 1.561361948645557, False)
+SketchConstraintCoincidence_11 = Sketch_1.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchArc_3.center())
+SketchConstraintRadius_3 = Sketch_1.setRadius(SketchArc_3.results()[1], 4)
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_6.endPoint(), SketchArc_1.center(), 6)
+SketchConstraintDistanceHorizontal_2 = Sketch_1.setHorizontalDistance(SketchLine_3.endPoint(), SketchArc_1.center(), 11)
+SketchConstraintCoincidence_12 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchArc_1.endPoint())
+SketchConstraintDistanceVertical_2 = Sketch_1.setVerticalDistance(SketchLine_8.startPoint(), SketchLine_2.endPoint(), 22)
+SketchLine_9 = Sketch_1.addLine(0, 0, 14.14213562373095, 14.14213562373095)
+SketchLine_9.setAuxiliary(True)
+SketchConstraintCoincidence_13 = Sketch_1.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_9.startPoint())
+SketchProjection_7 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_10 = SketchProjection_7.createdFeature()
+SketchConstraintAngle_1 = Sketch_1.setAngle(SketchLine_10.result(), SketchLine_9.result(), 45)
+SketchLine_11 = Sketch_1.addLine(7.693909752490621, 5.572589408930978, 3.682682292205201, 1.561361948645557)
+SketchConstraintCoincidence_14 = Sketch_1.setCoincident(SketchArc_2.endPoint(), SketchLine_11.startPoint())
+SketchConstraintCoincidence_15 = Sketch_1.setCoincident(SketchArc_3.endPoint(), SketchLine_11.endPoint())
+SketchConstraintParallel_1 = Sketch_1.setParallel(SketchLine_9.result(), SketchLine_11.result())
+SketchLine_12 = Sketch_1.addLine(6, 8.121320343559642, 1.561361948645558, 3.6826822922052)
+SketchConstraintCoincidence_16 = Sketch_1.setCoincident(SketchArc_3.startPoint(), SketchLine_12.endPoint())
+SketchConstraintParallel_2 = Sketch_1.setParallel(SketchLine_9.result(), SketchLine_12.result())
+SketchConstraintCoincidence_17 = Sketch_1.setCoincident(SketchLine_12.startPoint(), SketchLine_7.endPoint())
+SketchLine_13 = Sketch_1.addLine(3.682682292205201, 1.561361948645557, 1.561361948645558, 3.6826822922052)
+SketchLine_13.setAuxiliary(True)
+SketchConstraintCoincidence_18 = Sketch_1.setCoincident(SketchArc_3.endPoint(), SketchLine_13.startPoint())
+SketchConstraintCoincidence_19 = Sketch_1.setCoincident(SketchArc_3.startPoint(), SketchLine_13.endPoint())
+SketchConstraintLength_5 = Sketch_1.setLength(SketchLine_13.result(), 3)
+SketchConstraintLength_5.setName("SketchConstraintLength_7")
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchArc_3.endPoint(), SketchLine_9.result(), 1.5, True)
+SketchConstraintLength_6 = Sketch_1.setLength(SketchLine_9.result(), 20)
+SketchConstraintLength_6.setName("SketchConstraintLength_8")
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchLine_2f-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_6r-SketchLine_7r-SketchLine_8f-SketchArc_1_2f-SketchArc_2_2f-SketchArc_3_2r-SketchLine_11f-SketchLine_12r")], model.selection(), 3.5, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_3"))
+SketchLine_14 = Sketch_2.addLine(6, 0, -6, 0)
+SketchProjection_8 = Sketch_2.addProjection(model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_7s-SketchLine_6e"), False)
+SketchPoint_7 = SketchProjection_8.createdFeature()
+SketchConstraintCoincidence_20 = Sketch_2.setCoincident(SketchLine_14.startPoint(), SketchPoint_7.result())
+SketchProjection_9 = Sketch_2.addProjection(model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_6s-SketchLine_8s"), False)
+SketchPoint_8 = SketchProjection_9.createdFeature()
+SketchConstraintCoincidence_21 = Sketch_2.setCoincident(SketchLine_14.endPoint(), SketchPoint_8.result())
+SketchLine_15 = Sketch_2.addLine(-6, 0, -6, -3.5)
+SketchConstraintCoincidence_22 = Sketch_2.setCoincident(SketchLine_14.endPoint(), SketchLine_15.startPoint())
+SketchLine_16 = Sketch_2.addLine(-6, -3.5, -6, -10.5)
+SketchConstraintCoincidence_23 = Sketch_2.setCoincident(SketchLine_15.endPoint(), SketchLine_16.startPoint())
+SketchLine_17 = Sketch_2.addLine(5.978225648847096, 0.08643259872215214, 6, -3.5)
+SketchProjection_10 = Sketch_2.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_3&Extrusion_1_1/To_Face_1"), False)
+SketchPoint_9 = SketchProjection_10.createdFeature()
+SketchConstraintCoincidence_24 = Sketch_2.setCoincident(SketchLine_17.endPoint(), SketchPoint_9.result())
+SketchLine_18 = Sketch_2.addLine(6, -3.5, 6, -10.5)
+SketchConstraintCoincidence_25 = Sketch_2.setCoincident(SketchLine_17.endPoint(), SketchLine_18.startPoint())
+SketchConstraintLength_7 = Sketch_2.setLength(SketchLine_18.result(), 7)
+SketchConstraintLength_7.setName("SketchConstraintLength_9")
+SketchProjection_11 = Sketch_2.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_2&Extrusion_1_1/To_Face_1"), False)
+SketchPoint_10 = SketchProjection_11.createdFeature()
+SketchConstraintCoincidence_26 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_10).coordinates(), SketchLine_15.endPoint())
+SketchConstraintVertical_5 = Sketch_2.setVertical(SketchLine_18.result())
+SketchConstraintVertical_6 = Sketch_2.setVertical(SketchLine_16.result())
+SketchLine_19 = Sketch_2.addLine(6, -10.5, -6, -10.5)
+SketchLine_19.setAuxiliary(True)
+SketchConstraintCoincidence_27 = Sketch_2.setCoincident(SketchLine_19.startPoint(), SketchLine_18.endPoint())
+SketchConstraintCoincidence_28 = Sketch_2.setCoincident(SketchLine_19.endPoint(), SketchLine_16.endPoint())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_18.result(), SketchLine_16.result())
+SketchProjection_12 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_20 = SketchProjection_12.createdFeature()
+model.do()
+
+SketchLine_20 = SketchAPI_Line(SketchLine_20)
+lineStart = [SketchLine_20.startPoint().x(), SketchLine_20.startPoint().y()]
+lineEnd = [SketchLine_20.endPoint().x(), SketchLine_20.endPoint().y()]
+
+# Try to move a line provided by projection of OZ axis
+
+# move start point
+Sketch_2.move(SketchLine_20.startPoint(), lineStart[0] + 1., lineStart[1] + 1.)
+model.do()
+assert(SketchLine_20.startPoint().x() == lineStart[0] and SketchLine_20.startPoint().y() == lineStart[1])
+
+# move end point
+Sketch_2.move(SketchLine_20.endPoint(), lineEnd[0] + 1., lineEnd[1] + 1.)
+model.do()
+assert(SketchLine_20.endPoint().x() == lineEnd[0] and SketchLine_20.endPoint().y() == lineEnd[1])
+
+# move whole line
+Sketch_2.move(SketchLine_20.result(), 50., 50.)
+model.do()
+assert(SketchLine_20.startPoint().x() == lineStart[0] and SketchLine_20.startPoint().y() == lineStart[1])
+assert(SketchLine_20.endPoint().x() == lineEnd[0] and SketchLine_20.endPoint().y() == lineEnd[1])
+
+model.end()
index a38089083b344ab3de2abc200841e464764bc1ba..269d4acfa7264d601f63941a182b894a80265c3c 100644 (file)
@@ -40,7 +40,8 @@ model.do()
 # Test 1.
 # =============================================================================
 # horizontal distance constraint
-SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(firstPoint, secondPoint, "distance")
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(firstPoint, secondPoint, 10)
+SketchConstraintDistanceHorizontal_1.feature().real("ConstraintValue").setText(DistanceParam.name().value())
 model.do()
 
 # changing the parameter
@@ -63,7 +64,8 @@ model.do()
 # Test 2.
 # =============================================================================
 # Vertical distance constraint
-SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(firstPoint, secondPoint, "distance")
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(firstPoint, secondPoint, 10)
+SketchConstraintDistanceVertical_1.feature().real("ConstraintValue").setText(DistanceParam.name().value())
 model.do()
 
 # changing the parameter
diff --git a/src/SketchPlugin/Test/TestDistanceDump.py b/src/SketchPlugin/Test/TestDistanceDump.py
new file mode 100644 (file)
index 0000000..c8375f5
--- /dev/null
@@ -0,0 +1,55 @@
+## Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+"""
+    TestDistanceDump.py
+
+    Check that distances set by parameters are dumped correctly
+"""
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Parameter_1 = model.addParameter(Part_1_doc, "a", "10")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(22.18754371333437, 31.96766851898132, 36.16301361286303, 24.640865178987)
+SketchLine_2 = Sketch_1.addLine(36.16301361286303, 24.640865178987, 45.95667186595785, 26.6618199092043)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(45.95667186595785, 26.6618199092043, 55.95667186595785, 16.6618199092043)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchLine_1.startPoint(), SketchLine_2.result(), Parameter_1.name().value(), True)
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_2.result(), Parameter_1.name().value())
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_2.endPoint(), SketchLine_3.endPoint(), Parameter_1.name().value())
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_2.endPoint(), SketchLine_3.endPoint(), Parameter_1.name().value())
+model.do()
+model.end()
+
+def assertEqual(str1, str2):
+    assert(str1 == str2), "{} != {}".format(str1, str2)
+
+assertEqual(SketchConstraintDistance_1.feature().real("ConstraintValue").text(), Parameter_1.name().value())
+assertEqual(SketchConstraintLength_1.feature().real("ConstraintValue").text(), Parameter_1.name().value())
+assertEqual(SketchConstraintDistanceHorizontal_1.feature().real("DistanceValue").text(), Parameter_1.name().value())
+assertEqual(SketchConstraintDistanceVertical_1.feature().real("DistanceValue").text(), Parameter_1.name().value())
+
+assert(model.checkPythonDump())
diff --git a/src/SketchPlugin/Test/TestEdgesOrder.py b/src/SketchPlugin/Test/TestEdgesOrder.py
new file mode 100644 (file)
index 0000000..cc8ae38
--- /dev/null
@@ -0,0 +1,171 @@
+## Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+"""
+    Verify the order of sketch edges is the same after dump
+"""
+
+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(40, 5, 40, -25)
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 30)
+SketchLine_2 = Sketch_1.addLine(40, -25, -10, -25)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), 50)
+SketchLine_3 = Sketch_1.addLine(-10, -25, -10, 5)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(-10, 5, 40, 5)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_4.endPoint())
+model.do()
+
+# Change Length references
+SketchConstraintLength_1.feature().refattr("ConstraintEntityA").setObject(SketchLine_3.feature().lastResult())
+SketchConstraintLength_2.feature().refattr("ConstraintEntityA").setObject(SketchLine_4.feature().lastResult())
+model.do()
+# Remove the first line, then build it and constraints from scratch
+Part_1_doc.removeFeature(SketchConstraintCoincidence_1.feature())
+Part_1_doc.removeFeature(SketchConstraintCoincidence_4.feature())
+Part_1_doc.removeFeature(SketchLine_1.feature())
+SketchLine_1 = Sketch_1.addLine(40, 5, 40, -25)
+Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_4.endPoint())
+Sketch_1.setLength(SketchLine_1.result(), 20)
+Sketch_1.setLength(SketchLine_2.result(), 40)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r")], model.selection(), 10, 0)
+
+# Extrude all lateral faces to check their area
+Extrusion_2 = model.addExtrusion(Part_1_doc, [], model.selection(), 10, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_1"))
+SketchLine_5 = Sketch_2.addLine(0.7346748749771982, 2.736245541082907e-015, 0.7346748749771982, 10.00000000000001)
+SketchProjection_1 = Sketch_2.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/From_Face_1"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_5.startPoint(), SketchPoint_1.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_1"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchPoint_2.result())
+SketchLine_6 = Sketch_2.addLine(0.7346748749771982, 10.00000000000001, -19.2653251250228, 10.00000000000001)
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchProjection_3 = Sketch_2.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_1"), False)
+SketchPoint_3 = SketchProjection_3.createdFeature()
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchPoint_3.result())
+SketchLine_7 = Sketch_2.addLine(-19.2653251250228, 10.00000000000001, -19.2653251250228, 2.775557561562891e-015)
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchProjection_4 = Sketch_2.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/From_Face_1"), False)
+SketchPoint_4 = SketchProjection_4.createdFeature()
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchPoint_4.result())
+SketchLine_8 = Sketch_2.addLine(-19.2653251250228, 2.775557561562891e-015, 0.7346748749771974, 3.386180225106727e-015)
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchLine_5.startPoint(), SketchLine_8.endPoint())
+Extrusion_2.setNestedSketch(Sketch_2)
+
+Extrusion_3 = model.addExtrusion(Part_1_doc, [], model.selection(), 10, 0)
+Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_2"))
+SketchLine_9 = Sketch_3.addLine(36.86324678550901, 2.286454635368208e-015, 36.86324678550901, 10)
+SketchProjection_5 = Sketch_3.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/From_Face_1"), False)
+SketchPoint_5 = SketchProjection_5.createdFeature()
+SketchConstraintCoincidence_13 = Sketch_3.setCoincident(SketchLine_9.startPoint(), SketchPoint_5.result())
+SketchProjection_6 = Sketch_3.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_1"), False)
+SketchPoint_6 = SketchProjection_6.createdFeature()
+SketchConstraintCoincidence_14 = Sketch_3.setCoincident(SketchLine_9.endPoint(), SketchPoint_6.result())
+SketchLine_10 = Sketch_3.addLine(36.86324678550901, 10, -3.136753214490995, 10)
+SketchConstraintCoincidence_15 = Sketch_3.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint())
+SketchProjection_7 = Sketch_3.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_2&Extrusion_1_1/To_Face_1"), False)
+SketchPoint_7 = SketchProjection_7.createdFeature()
+SketchConstraintCoincidence_16 = Sketch_3.setCoincident(SketchLine_10.endPoint(), SketchPoint_7.result())
+SketchLine_11 = Sketch_3.addLine(-3.136753214490995, 10, -3.136753214490995, 2.275957200481571e-015)
+SketchConstraintCoincidence_17 = Sketch_3.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint())
+SketchProjection_8 = Sketch_3.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_2&Extrusion_1_1/From_Face_1"), False)
+SketchPoint_8 = SketchProjection_8.createdFeature()
+SketchConstraintCoincidence_18 = Sketch_3.setCoincident(SketchLine_11.endPoint(), SketchPoint_8.result())
+SketchLine_12 = Sketch_3.addLine(-3.136753214490995, 2.275957200481571e-015, 36.86324678550902, 1.387778780781446e-015)
+SketchConstraintCoincidence_19 = Sketch_3.setCoincident(SketchLine_11.endPoint(), SketchLine_12.startPoint())
+SketchConstraintCoincidence_20 = Sketch_3.setCoincident(SketchLine_9.startPoint(), SketchLine_12.endPoint())
+Extrusion_3.setNestedSketch(Sketch_3)
+
+Extrusion_4 = model.addExtrusion(Part_1_doc, [], model.selection(), 10, 0)
+Sketch_4 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_3"))
+SketchLine_13 = Sketch_4.addLine(22.60959895285982, 4.420942808558057e-016, 22.60959895285982, 10)
+SketchProjection_9 = Sketch_4.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_2&Extrusion_1_1/From_Face_1"), False)
+SketchPoint_9 = SketchProjection_9.createdFeature()
+SketchConstraintCoincidence_21 = Sketch_4.setCoincident(SketchLine_13.startPoint(), SketchPoint_9.result())
+SketchProjection_10 = Sketch_4.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_2&Extrusion_1_1/To_Face_1"), False)
+SketchPoint_10 = SketchProjection_10.createdFeature()
+SketchConstraintCoincidence_22 = Sketch_4.setCoincident(SketchLine_13.endPoint(), SketchPoint_10.result())
+SketchLine_14 = Sketch_4.addLine(22.60959895285982, 10, -7.390401047140179, 10)
+SketchConstraintCoincidence_23 = Sketch_4.setCoincident(SketchLine_13.endPoint(), SketchLine_14.startPoint())
+SketchProjection_11 = Sketch_4.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_3&Extrusion_1_1/To_Face_1"), False)
+SketchPoint_11 = SketchProjection_11.createdFeature()
+SketchConstraintCoincidence_24 = Sketch_4.setCoincident(SketchLine_14.endPoint(), SketchPoint_11.result())
+SketchLine_15 = Sketch_4.addLine(-7.390401047140179, 10, -7.390401047140179, 8.881784197001252e-016)
+SketchConstraintCoincidence_25 = Sketch_4.setCoincident(SketchLine_14.endPoint(), SketchLine_15.startPoint())
+SketchProjection_12 = Sketch_4.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_3&Extrusion_1_1/From_Face_1"), False)
+SketchPoint_12 = SketchProjection_12.createdFeature()
+SketchConstraintCoincidence_26 = Sketch_4.setCoincident(SketchLine_15.endPoint(), SketchPoint_12.result())
+SketchLine_16 = Sketch_4.addLine(-7.390401047140179, 8.881784197001252e-016, 22.60959895285983, 0)
+SketchConstraintCoincidence_27 = Sketch_4.setCoincident(SketchLine_15.endPoint(), SketchLine_16.startPoint())
+SketchConstraintCoincidence_28 = Sketch_4.setCoincident(SketchLine_13.startPoint(), SketchLine_16.endPoint())
+Extrusion_4.setNestedSketch(Sketch_4)
+
+Extrusion_5 = model.addExtrusion(Part_1_doc, [], model.selection(), 10, 0)
+Sketch_5 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_4"))
+SketchLine_17 = Sketch_5.addLine(-10.64977324988603, -1.185841873934692e-016, -10.64977324988603, -10)
+SketchProjection_13 = Sketch_5.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_3&Extrusion_1_1/From_Face_1"), False)
+SketchPoint_13 = SketchProjection_13.createdFeature()
+SketchConstraintCoincidence_29 = Sketch_5.setCoincident(SketchLine_17.startPoint(), SketchPoint_13.result())
+SketchProjection_14 = Sketch_5.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_3&Extrusion_1_1/To_Face_1"), False)
+SketchPoint_14 = SketchProjection_14.createdFeature()
+SketchConstraintCoincidence_30 = Sketch_5.setCoincident(SketchLine_17.endPoint(), SketchPoint_14.result())
+SketchLine_18 = Sketch_5.addLine(-10.64977324988603, -10, 39.35022675011398, -10)
+SketchConstraintCoincidence_31 = Sketch_5.setCoincident(SketchLine_17.endPoint(), SketchLine_18.startPoint())
+SketchProjection_15 = Sketch_5.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_1"), False)
+SketchPoint_15 = SketchProjection_15.createdFeature()
+SketchConstraintCoincidence_32 = Sketch_5.setCoincident(SketchLine_18.endPoint(), SketchPoint_15.result())
+SketchLine_19 = Sketch_5.addLine(39.35022675011398, -10, 39.35022675011398, 4.440892098500626e-016)
+SketchConstraintCoincidence_33 = Sketch_5.setCoincident(SketchLine_18.endPoint(), SketchLine_19.startPoint())
+SketchProjection_16 = Sketch_5.addProjection(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/From_Face_1"), False)
+SketchPoint_16 = SketchProjection_16.createdFeature()
+SketchConstraintCoincidence_34 = Sketch_5.setCoincident(SketchLine_19.endPoint(), SketchPoint_16.result())
+SketchLine_20 = Sketch_5.addLine(39.35022675011398, 4.440892098500626e-016, -10.64977324988603, 0)
+SketchConstraintCoincidence_35 = Sketch_5.setCoincident(SketchLine_19.endPoint(), SketchLine_20.startPoint())
+SketchConstraintCoincidence_36 = Sketch_5.setCoincident(SketchLine_17.startPoint(), SketchLine_20.endPoint())
+Extrusion_5.setNestedSketch(Sketch_5)
+model.do()
+model.end()
+
+# check volumes
+model.testResultsVolumes(Extrusion_2, [4000])
+model.testResultsVolumes(Extrusion_3, [3000])
+model.testResultsVolumes(Extrusion_4, [5000])
+model.testResultsVolumes(Extrusion_5, [2000])
+
+assert(model.checkPythonDump())
+
+# check volumes after dump and restore
+model.testResultsVolumes(Extrusion_2, [4000])
+model.testResultsVolumes(Extrusion_3, [3000])
+model.testResultsVolumes(Extrusion_4, [5000])
+model.testResultsVolumes(Extrusion_5, [2000])
index 6fe6afe903899dd5d1a69f4661d8fdda08515369..59133d7f3d0341d92f6f14f00ccec73900b05da2 100644 (file)
@@ -133,7 +133,7 @@ for i in range(1, 10):
 # =============================================================================
 # Test 3. Constrain center of circle and move it again
 # =============================================================================
-SketchConstraintDistanceHorizontal_3 = Sketch_1.setHorizontalDistance(SketchCircle_1.center(), SketchArc_1.startPoint(), -30)
+SketchConstraintDistanceHorizontal_3 = Sketch_1.setHorizontalDistance(SketchCircle_1.center(), SketchArc_1.startPoint(), 30)
 model.do()
 # move center
 delta = [1., 1.]
index 4372af6457090572f69c3a43ff15a0bcebfb897c..6b728d2730f78dc1e15a846efe39d6b628ee2ee8 100644 (file)
@@ -494,7 +494,7 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
       <!--  SketchConstraintMirror  -->
       <feature
         id="SketchConstraintMirror"
-        title="Mirror" icon="icons/Sketch/mirror.png"
+        title="Mirror copy" icon="icons/Sketch/mirror.png"
         tooltip="Create constraint, mirroring group of objects">
         <sketch_shape_selector id="ConstraintEntityA"
             label="Mirror line" tooltip="Select mirror line" shape_types="edge">
@@ -515,8 +515,8 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
       <!--  SketchMultiTranslation  -->
       <feature
         id="SketchMultiTranslation"
-        title="Translation" icon="icons/Sketch/translate.png"
-        tooltip="Multiple translation">
+        title="Linear copy" icon="icons/Sketch/translate.png"
+        tooltip="Copy objects and move">
         <sketch_multi_selector id="MultiTranslationList"
             label="Segments:"
             tooltip="Select list of objects to be translated"
@@ -583,8 +583,8 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
       <!--  SketchMultiRotation  -->
       <feature
         id="SketchMultiRotation"
-        title="Rotation" icon="icons/Sketch/rotate.png"
-        tooltip="Multiple rotation">
+        title="Angular copy" icon="icons/Sketch/rotate.png"
+        tooltip="Copy objects and rotate">
         <sketch_multi_selector id="MultiRotationList"
             label="Segments:"
             tooltip="Select list of objects to be rotated"
index 16122052155c527b9c72a2177db06753c79a556c..830a482fed2eda7b2c61f1bafa6c99d2d6809f12 100644 (file)
@@ -150,7 +150,7 @@ static bool hasReference(std::shared_ptr<SketchPlugin_Feature> theFeature,
   for (std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
        aRefIt != aRefs.end(); ++aRefIt) {
      FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
-     if (anOwner->getKind() == theFeatureKind)
+     if (anOwner && anOwner->getKind() == theFeatureKind)
        return true;
   }
   return false;
index f5d6df055692edda89410318425c4c0cc87cb211..bbaf6ac24a33074bf48e4a4917683609b8b2761e 100644 (file)
@@ -212,6 +212,9 @@ void SketchSolver_ConstraintMovement::startPoint(
 void SketchSolver_ConstraintMovement::moveTo(
     const std::shared_ptr<GeomAPI_Pnt2d>& theDestinationPoint)
 {
+  if (!myMovedFeature)
+    return; // nothing to move
+
   double aDelta[2] = { theDestinationPoint->x() - myStartPoint->x(),
                        theDestinationPoint->y() - myStartPoint->y() };
 
index 9e91f3ff4e2214738025091df3793a5ce1e19f6f..3f38196864a251e3d999456009772fc5a64bd714 100644 (file)
@@ -59,7 +59,7 @@
 #endif
 
 /// Step between icons
-static const double MyDist = 0.02;
+static const double MyDist = 0.015;
 
 
 //**************************************************************
index 7f0fe59ff7d9dd72c9f9f147f36063391d4f495a..72be73b8ff01f17cdef47dc197fe801e445cf8da 100644 (file)
@@ -29,6 +29,8 @@ ADD_DEFINITIONS(${QT_DEFINITIONS})
 SET(PROJECT_HEADERS
     XGUI.h
     XGUI_ActionsMgr.h
+    XGUI_ActiveControlMgr.h
+    XGUI_ActiveControlSelector.h
     XGUI_ColorDialog.h
     XGUI_ContextMenuMgr.h
     XGUI_CustomPrs.h
@@ -37,6 +39,8 @@ SET(PROJECT_HEADERS
     XGUI_Displayer.h
     XGUI_ErrorDialog.h
     XGUI_ErrorMgr.h
+    XGUI_FacesPanel.h
+    XGUI_FacesPanelSelector.h
     XGUI_HistoryMenu.h
     XGUI_MenuGroup.h
     XGUI_MenuMgr.h
@@ -46,9 +50,12 @@ SET(PROJECT_HEADERS
     XGUI_OperationMgr.h
     XGUI_PropertyDialog.h
     XGUI_PropertyPanel.h
+    XGUI_PropertyPanelSelector.h
     XGUI_QtEvents.h
     XGUI_SalomeConnector.h
     XGUI_Selection.h
+    XGUI_SelectionActivate.h
+    XGUI_SelectionFilterType.h
     XGUI_SelectionMgr.h
     XGUI_Tools.h
     XGUI_TransparencyWidget.h
@@ -59,6 +66,8 @@ SET(PROJECT_HEADERS
 
 SET(PROJECT_MOC_HEADERS
     XGUI_ActionsMgr.h
+    XGUI_ActiveControlMgr.h
+    XGUI_ActiveControlSelector.h
     XGUI_ColorDialog.h
     XGUI_ContextMenuMgr.h
     XGUI_DataModel.h
@@ -66,12 +75,15 @@ SET(PROJECT_MOC_HEADERS
     XGUI_Displayer.h
     XGUI_ErrorDialog.h
     XGUI_ErrorMgr.h
+    XGUI_FacesPanel.h
+    XGUI_FacesPanelSelector.h
     XGUI_HistoryMenu.h
     XGUI_ModuleConnector.h
     XGUI_ObjectsBrowser.h
     XGUI_OperationMgr.h
     XGUI_PropertyDialog.h
     XGUI_PropertyPanel.h
+    XGUI_PropertyPanelSelector.h
     XGUI_SelectionMgr.h
     XGUI_TransparencyWidget.h
     XGUI_ViewerProxy.h
@@ -84,6 +96,7 @@ QT_WRAP_MOC(PROJECT_AUTOMOC ${PROJECT_MOC_HEADERS})
 
 SET(PROJECT_SOURCES
     XGUI_ActionsMgr.cpp
+    XGUI_ActiveControlMgr.cpp
     XGUI_ColorDialog.cpp
     XGUI_ContextMenuMgr.cpp
     XGUI_CustomPrs.cpp
@@ -92,6 +105,8 @@ SET(PROJECT_SOURCES
     XGUI_Displayer.cpp
     XGUI_ErrorDialog.cpp
     XGUI_ErrorMgr.cpp
+    XGUI_FacesPanel.cpp
+    XGUI_FacesPanelSelector.cpp
     XGUI_HistoryMenu.cpp
     XGUI_MenuGroup.cpp
     XGUI_MenuMgr.cpp
@@ -101,9 +116,11 @@ SET(PROJECT_SOURCES
     XGUI_OperationMgr.cpp
     XGUI_PropertyDialog.cpp
     XGUI_PropertyPanel.cpp
+    XGUI_PropertyPanelSelector.cpp
     XGUI_QtEvents.cpp
     XGUI_SalomeConnector.cpp
     XGUI_Selection.cpp
+    XGUI_SelectionActivate.cpp
     XGUI_SelectionMgr.cpp
     XGUI_Tools.cpp
     XGUI_TransparencyWidget.cpp
index deeb75433e7ba79ae07ebf18ba042c50ad01a141..3773ae9bac0b423261ac87ee44d34cca0b47fa55 100644 (file)
 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
 //
 
-/*
- * XGUI_ActionsMgr.h
- */
-
-#ifndef XGUI_ACTIONSMGR_H_
-#define XGUI_ACTIONSMGR_H_
+#ifndef XGUI_ActionsMgr_H
+#define XGUI_ActionsMgr_H
 
 #include "XGUI.h"
 
@@ -43,10 +39,9 @@ class XGUI_OperationMgr;
 class ModuleBase_Operation;
 class QAction;
 
-/**
-* \ingroup GUI
-* A class for management of actions (features) activation/deactivation
-*/
+/// class XGUI_ActionsMgr
+/// \ingroup GUI
+/// A class for management of actions (features) activation/deactivation
 class XGUI_EXPORT XGUI_ActionsMgr : public QObject, public Events_Listener
 {
   Q_OBJECT
@@ -68,16 +63,16 @@ class XGUI_EXPORT XGUI_ActionsMgr : public QObject, public Events_Listener
     Preview = 6
   };
 
-  //! Add a command in the manager.
-  //! Please note that nested commands in the Salome mode (No AppElements_Command, pure QActions)
-  //! won't be extracted and should be added manually using the addNestedCommands method.
+  /// Add a command in the manager.
+  /// Please note that nested commands in the Salome mode (No AppElements_Command, pure QActions)
+  /// won't be extracted and should be added manually using the addNestedCommands method.
   void addCommand(QAction* theCmd);
 
-  //! Sets relation between the command (with given Id) and it's nested actions.
+  /// Sets relation between the command (with given Id) and it's nested actions.
   void addNestedCommands(const QString& theId, const QStringList& theCommands);
 
-  //! Returns list of nested commands by parent command Id
-  //! \param theId a parent command Id
+  /// Returns list of nested commands by parent command Id
+  /// \param theId a parent command Id
   QStringList nestedCommands(const QString& theId) const;
 
   /// Returns True if the given Id is an Id of nested command
@@ -93,11 +88,11 @@ class XGUI_EXPORT XGUI_ActionsMgr : public QObject, public Events_Listener
   /// \param theKeySequence - string that contain a key sequence to register
   QKeySequence registerShortcut(const QString& theKeySequence);
 
-  //! Redefinition of Events_Listener method
+  /// Redefinition of Events_Listener method
   virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
 
-  //! Return property panel's action like ok, cancel, help.
-  //! If there is no such action, it will be created.
+  /// Return property panel's action like ok, cancel, help.
+  /// If there is no such action, it will be created.
   QAction* operationStateAction(OperationStateActionId theId);
 
   /// Return an action by the given id, if it was registered in the manager
@@ -108,40 +103,42 @@ class XGUI_EXPORT XGUI_ActionsMgr : public QObject, public Events_Listener
   ActionInfo actionInfoById(const QString& theId);
 
  private:
-  //! Update workbench actions according to OperationMgr state:
-  //! No active operations: all actions but nested are available
-  //! There is active operation: current operation + it's nested
-  //! are enabled, all the rest is disabled. All active commands is checked.
+  /// Update workbench actions according to OperationMgr state:
+  /// No active operations: all actions but nested are available
+  /// There is active operation: current operation + it's nested
+  /// are enabled, all the rest is disabled. All active commands is checked.
   void updateCommandsStatus();
 
-  //! Sets all commands checked if it's operation is active.
+  /// Sets all commands checked if it's operation is active.
   void updateCheckState();
 
-  //! Updates actions according to current selection in the viewer
+  /// Updates actions according to current selection in the viewer
   void updateOnViewSelection();
 
-  //! Sets all actions to enabled state.
+  /// Sets all actions to enabled state.
   void setAllEnabled();
 
-  //! Sets all nested actions to isEnabled state for the command with given ID.
-  //! If ID is empty - all nested actions will be affected.
+  /// Sets all nested actions to isEnabled state for the command with given ID.
+  /// If ID is empty - all nested actions will be affected.
   void setNestedCommandsEnabled(bool isEnabled, const QString& theParent = QString());
 
-  //! Sets to enabled state all siblings of the given operation and it's parents recursively
+  /// Sets to enabled state all siblings of the given operation and it's parents recursively
   void setNestedStackEnabled(ModuleBase_Operation* theOperation);
 
-  //! Sets the action with theId to theChecked state.
+  /// Sets the action with theId to theChecked state.
   void setActionChecked(const QString& theId, const bool theChecked);
 
-  //! Sets the action with theId to theEnabled state.
+  /// Sets the action with theId to theEnabled state.
   void setActionEnabled(const QString& theId, const bool theEnabled);
 
-  //! Updates actions according to their "document" tag
+  /// Updates actions according to their "document" tag
   void updateByDocumentKind();
 
-  //! Asks plugins about their features state, using the Events system
+  /// Asks plugins about their features state, using the Events system
   void updateByPlugins(FeaturePtr theActiveFeature);
 
+  /// Returns names of nested action for the feature of given operation
+  /// \param theOperation an operation
   QStringList allNestedCommands(ModuleBase_Operation* theOperation);
 
  private:
@@ -157,5 +154,5 @@ class XGUI_EXPORT XGUI_ActionsMgr : public QObject, public Events_Listener
   friend class XGUI_Workshop;
 };
 
-#endif /* XGUI_ACTIONSMGR_H_ */
+#endif /* XGUI_ActionsMgr_H */
 
diff --git a/src/XGUI/XGUI_ActiveControlMgr.cpp b/src/XGUI/XGUI_ActiveControlMgr.cpp
new file mode 100644 (file)
index 0000000..7176e06
--- /dev/null
@@ -0,0 +1,144 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "XGUI_ActiveControlMgr.h"
+#include "XGUI_ActiveControlSelector.h"
+#include "XGUI_SelectionActivate.h"
+#include "XGUI_SelectionMgr.h"
+#include "XGUI_Tools.h"
+#include "XGUI_Workshop.h"
+
+#include <ModuleBase_IModule.h>
+#include <ModuleBase_IWorkshop.h>
+
+//#define DEBUG_ACTIVE_SELECTOR
+
+#ifdef DEBUG_ACTIVE_SELECTOR
+void debugInfo(const QString& theMessage, XGUI_ActiveControlSelector* theSelector)
+{
+  std::cout << theMessage.toStdString().c_str() << ", active: "
+    << (theSelector ? theSelector->getType().toStdString().c_str() : "NULL") << std::endl;
+}
+#endif
+
+//********************************************************************
+XGUI_ActiveControlMgr::XGUI_ActiveControlMgr(ModuleBase_IWorkshop* theWorkshop)
+: myWorkshop(theWorkshop), myActiveSelector(0), myIsBlocked(false)
+{
+  connect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
+}
+
+//********************************************************************
+void XGUI_ActiveControlMgr::addSelector(XGUI_ActiveControlSelector* theSelector)
+{
+  mySelectors.append(theSelector);
+  connect(theSelector, SIGNAL(activated()), this, SLOT(onSelectorActivated()));
+  connect(theSelector, SIGNAL(deactivated()), this, SLOT(onSelectorDeactivated()));
+}
+
+//********************************************************************
+XGUI_ActiveControlSelector* XGUI_ActiveControlMgr::getSelector(const QString& theType)
+{
+  XGUI_ActiveControlSelector* aSelector;
+  for (int i = 0, aCount = mySelectors.count(); i < aCount; i++)
+  {
+    if (mySelectors[i]->getType() != theType)
+      continue;
+    aSelector = mySelectors[i];
+    break;
+  }
+  return aSelector;
+}
+
+//********************************************************************
+void XGUI_ActiveControlMgr::onSelectorActivated()
+{
+  XGUI_ActiveControlSelector* aSelector = qobject_cast<XGUI_ActiveControlSelector*>(sender());
+  if (!aSelector || aSelector == myActiveSelector)
+    return;
+
+  if (myIsBlocked) // we've come here from the same method
+    return;
+  myIsBlocked = true;
+  if (myActiveSelector) {
+    myActiveSelector->setActive(false);
+  }
+  activateSelector(aSelector);
+  XGUI_Tools::workshop(myWorkshop)->selectionActivate()->updateSelectionModes();
+  XGUI_Tools::workshop(myWorkshop)->selectionActivate()->updateSelectionFilters();
+
+#ifdef DEBUG_ACTIVE_SELECTOR
+  debugInfo("onSelectorActivated", myActiveSelector);
+#endif
+  myIsBlocked = false;
+}
+
+//********************************************************************
+void XGUI_ActiveControlMgr::onSelectorDeactivated()
+{
+  XGUI_ActiveControlSelector* aSelector = qobject_cast<XGUI_ActiveControlSelector*>(sender());
+  if (!aSelector || aSelector != myActiveSelector || !myActiveSelector)
+    return;
+
+  if (myIsBlocked) // we've come here from the same method
+    return;
+  myIsBlocked = true;
+
+  myActiveSelector->setActive(false);
+  activateSelector(NULL);
+
+  XGUI_ActiveControlSelector* aSelectorToBeActivated = 0;
+  for (int i = 0, aCount = mySelectors.count(); i < aCount; i++)
+  {
+    if (!mySelectors[i]->needToBeActiated())
+      continue;
+    aSelectorToBeActivated = mySelectors[i];
+    break;
+  }
+  if (aSelectorToBeActivated)
+    activateSelector(aSelectorToBeActivated);
+
+  XGUI_Tools::workshop(myWorkshop)->selectionActivate()->updateSelectionModes();
+  XGUI_Tools::workshop(myWorkshop)->selectionActivate()->updateSelectionFilters();
+#ifdef DEBUG_ACTIVE_SELECTOR
+  debugInfo("onSelectorDeactivated", myActiveSelector);
+#endif
+  myIsBlocked = false;
+}
+
+//********************************************************************
+void XGUI_ActiveControlMgr::onSelectionChanged()
+{
+  if (!myActiveSelector)
+    return;
+
+  myActiveSelector->processSelection();
+#ifdef DEBUG_ACTIVE_SELECTOR
+  debugInfo("onSelectionChanged", myActiveSelector);
+#endif
+}
+
+//********************************************************************
+void XGUI_ActiveControlMgr::activateSelector(XGUI_ActiveControlSelector* theSelector)
+{
+  myActiveSelector = theSelector;
+  if (myActiveSelector)
+    myActiveSelector->setActive(true);
+}
diff --git a/src/XGUI/XGUI_ActiveControlMgr.h b/src/XGUI/XGUI_ActiveControlMgr.h
new file mode 100644 (file)
index 0000000..7b0703a
--- /dev/null
@@ -0,0 +1,80 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef XGUI_ActiveControlMgr_H
+#define XGUI_ActiveControlMgr_H
+
+#include "XGUI.h"
+
+#include <QList>
+#include <QObject>
+
+
+class XGUI_ActiveControlSelector;
+class ModuleBase_IWorkshop;
+
+/**
+* Interface of providing only one active control for workshop.
+* It has container of selectors, where only one might be active at the moment.
+* Selection in 3D view is processed by the active selector.
+*/
+class XGUI_ActiveControlMgr : public QObject
+{
+  Q_OBJECT
+public:
+  /// Constructor
+  /// \param theWorkshop the current workshop instance
+  XGUI_EXPORT XGUI_ActiveControlMgr(ModuleBase_IWorkshop* theWorkshop);
+
+  XGUI_EXPORT virtual ~XGUI_ActiveControlMgr() {};
+
+  /// Register selector to process activation of control
+  void addSelector(XGUI_ActiveControlSelector* theSelector);
+
+  /// Returns selector by type name
+  /// \param theType a selector type
+  /// \return selector instance
+  XGUI_EXPORT XGUI_ActiveControlSelector* getSelector(const QString& theType);
+
+  /// Returns the active selector
+  /// \return selector instance
+  XGUI_ActiveControlSelector* activeSelector() const { return myActiveSelector; }
+
+protected slots:
+  /// Deactivates active selector and set the sender selector as active
+  void onSelectorActivated();
+  /// Deactivate the active selector
+  void onSelectorDeactivated();
+  /// Listens workshop selection and pass it to the active selector
+  void onSelectionChanged();
+
+protected:
+  void activateSelector(XGUI_ActiveControlSelector* theSelector);
+
+protected:
+  ModuleBase_IWorkshop* myWorkshop; ///< the current workshop
+
+  QList<XGUI_ActiveControlSelector*> mySelectors; ///< workshop selectors
+  XGUI_ActiveControlSelector* myActiveSelector; ///< active selector
+
+  bool myIsBlocked; ///< blocking flag to avoid cycling signals processing
+};
+
+#endif
diff --git a/src/XGUI/XGUI_ActiveControlSelector.h b/src/XGUI/XGUI_ActiveControlSelector.h
new file mode 100644 (file)
index 0000000..c0a3e15
--- /dev/null
@@ -0,0 +1,78 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef XGUI_ActiveControlSelector_H
+#define XGUI_ActiveControlSelector_H
+
+#include "XGUI.h"
+
+#include <QObject>
+
+/**
+* Interface to have an active control and process selection by the control.
+* Activation of control may set selection modes and selection filters of the control.
+*/
+class XGUI_ActiveControlSelector : public QObject
+{
+  Q_OBJECT
+
+public:
+  /// Constructor
+  /// \param theWorkshop the current workshop instance
+  XGUI_EXPORT XGUI_ActiveControlSelector() {};
+  /// Destructor
+  XGUI_EXPORT virtual ~XGUI_ActiveControlSelector() {};
+
+  /// Returns name of the selector
+  XGUI_EXPORT virtual QString getType() = 0;
+
+  /// Clear need to be activated widget if it exists
+  XGUI_EXPORT virtual void reset() {}
+
+  /// Sets enable/disable state of the selector. If disable, it will not react to selection
+  /// \param theEnabled if true, selector is enabled
+  XGUI_EXPORT void setEnable(const bool& theEnabled) { myIsEnabled = theEnabled; }
+
+  /// Returns whether the selector is enabled or not
+  /// \return boolean result
+  XGUI_EXPORT bool isEnabled() const { return myIsEnabled; }
+
+  /// Sets control active. It should activates/deactivates selection and selection filters.
+  /// \param isActive if true, the control becomes active
+  XGUI_EXPORT virtual void setActive(const bool& isActive) = 0;
+
+  /// Returns whether the selector should be activated as soon as possible (by deactivatate other)
+  /// \return boolean result
+  XGUI_EXPORT virtual bool needToBeActiated() const { return false; }
+
+  /// Processes current selection of workshop. Reaction to selection change in workshop.
+  XGUI_EXPORT virtual void processSelection() = 0;
+
+signals:
+  /// control is activated
+  void activated();
+  /// control is deactivated
+  void deactivated();
+
+protected:
+  bool myIsEnabled; ///< enable state of the selector
+};
+
+#endif
index 1a986b377ff86155065408fccb672b9f0b999a34..47aeb1ba75474d746223196e6d41080b7dbace26 100644 (file)
@@ -24,8 +24,9 @@
 #include "XGUI_SelectionMgr.h"
 #include "XGUI_Displayer.h"
 #include "XGUI_ViewerProxy.h"
-#include "XGUI_Selection.h"
 #include "XGUI_SalomeConnector.h"
+#include "XGUI_Selection.h"
+#include "XGUI_SelectionActivate.h"
 #include "XGUI_DataModel.h"
 #include "XGUI_OperationMgr.h"
 #include "XGUI_Tools.h"
@@ -47,6 +48,8 @@
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_ResultField.h>
+#include <ModelAPI_Folder.h>
+#include <ModelAPI_AttributeReference.h>
 
 #include <Config_DataModelReader.h>
 
@@ -66,7 +69,7 @@
 XGUI_ContextMenuMgr::XGUI_ContextMenuMgr(XGUI_Workshop* theParent)
     : QObject(theParent),
       myWorkshop(theParent),
-      mySeparator(0)
+      mySeparator1(0), mySeparator2(0), mySeparator3(0)
 {
 }
 
@@ -135,8 +138,14 @@ void XGUI_ContextMenuMgr::createActions()
                                            aDesktop);
   addAction("WIREFRAME_CMD", aAction);
 
-  mySeparator = ModuleBase_Tools::createAction(QIcon(), "", aDesktop);
-  mySeparator->setSeparator(true);
+  mySeparator1 = ModuleBase_Tools::createAction(QIcon(), "", aDesktop);
+  mySeparator1->setSeparator(true);
+
+  mySeparator2 = ModuleBase_Tools::createAction(QIcon(), "", aDesktop);
+  mySeparator2->setSeparator(true);
+
+  mySeparator3 = ModuleBase_Tools::createAction(QIcon(), "", aDesktop);
+  mySeparator3->setSeparator(true);
 
   //mySelectActions = new QActionGroup(this);
   //mySelectActions->setExclusive(true);
@@ -180,6 +189,27 @@ void XGUI_ContextMenuMgr::createActions()
   addAction("TINSPECTOR_VIEW", aAction);
 #endif
 
+  // Features folders actions
+  aAction = ModuleBase_Tools::createAction(QIcon(":pictures/create_folder.png"),
+                                           tr("Insert a folder before"), aDesktop);
+  addAction("INSERT_FOLDER_CMD", aAction);
+
+  aAction = ModuleBase_Tools::createAction(QIcon(":pictures/insert_folder_before.png"),
+                                           tr("Move into the previous folder"), aDesktop);
+  addAction("ADD_TO_FOLDER_BEFORE_CMD", aAction);
+
+  aAction = ModuleBase_Tools::createAction(QIcon(":pictures/insert_folder_after.png"),
+                                           tr("Move into the next folder"), aDesktop);
+  addAction("ADD_TO_FOLDER_AFTER_CMD", aAction);
+
+  aAction = ModuleBase_Tools::createAction(QIcon(":pictures/move_out_before.png"),
+                                           tr("Move out before the folder"), aDesktop);
+  addAction("ADD_OUT_FOLDER_BEFORE_CMD", aAction);
+
+  aAction = ModuleBase_Tools::createAction(QIcon(":pictures/move_out_after.png"),
+                                           tr("Move out after the folder"), aDesktop);
+  addAction("ADD_OUT_FOLDER_AFTER_CMD", aAction);
+
   buildObjBrowserMenu();
   buildViewerMenu();
 }
@@ -263,10 +293,11 @@ void XGUI_ContextMenuMgr::updateObjectBrowserMenu()
     bool hasParameter = false;
     bool hasCompositeOwner = false;
     bool hasResultInHistory = false;
+    bool hasFolder = false;
     ModuleBase_Tools::checkObjects(aObjects, hasResult, hasFeature, hasParameter,
-                                   hasCompositeOwner, hasResultInHistory);
+                                   hasCompositeOwner, hasResultInHistory, hasFolder);
     //Process Feature
-    if (aSelected == 1) {
+    if (aSelected == 1) { // single selection
       ObjectPtr aObject = aObjects.first();
       if (aObject) {
         if (hasResult && myWorkshop->canBeShaded(aObject)) {
@@ -307,7 +338,8 @@ void XGUI_ContextMenuMgr::updateObjectBrowserMenu()
                                                   (hasFeature || hasParameter));
         }
       }
-    } else {
+      // end single selection
+    } else { // multiselection
       // parameter is commented because the actions are not in the list of result parameter actions
       if (hasResult /*&& (!hasParameter)*/) {
         action("SHOW_CMD")->setEnabled(true);
@@ -316,7 +348,98 @@ void XGUI_ContextMenuMgr::updateObjectBrowserMenu()
         action("SHADING_CMD")->setEnabled(true);
         action("WIREFRAME_CMD")->setEnabled(true);
       }
-    }
+    } // end multiselection
+
+    // Check folder management commands state if only features are selected
+    if ((!hasResult) && hasFeature && (!hasParameter) && (!hasCompositeOwner) &&
+      (!hasResultInHistory) && (!hasFolder)) {
+      std::list<FeaturePtr> aFeatures = aSelMgr->getSelectedFeatures();
+      if (aFeatures.size() > 0) { // Check that features do not include Parts
+        QModelIndexList aIndexes = aSelMgr->selection()->selectedIndexes();
+        QModelIndex aFirstIdx = aIndexes.first();
+        QModelIndex aLastIdx = aIndexes.last();
+        QModelIndex aParentIdx = aFirstIdx.parent();
+
+        // if all selected are from the same level
+        bool isSameParent = true;
+        foreach(QModelIndex aIdx, aIndexes) {
+          if (aIdx.parent() != aParentIdx) {
+            isSameParent = false;
+            break;
+          }
+        }
+        if (isSameParent) {
+          // Check is selection continuous
+          XGUI_DataModel* aModel = myWorkshop->objectBrowser()->dataModel();
+          DocumentPtr aDoc = aMgr->activeDocument();
+          std::list<FeaturePtr> aFeatures = aSelMgr->getSelectedFeatures();
+
+          bool isContinuos = true;
+          if (aSelected > 1) {
+            int aId = -1;
+            foreach(FeaturePtr aF, aFeatures) {
+              if (aId == -1)
+                aId = aDoc->index(aF);
+              else {
+                aId++;
+                if (aId != aDoc->index(aF)) {
+                  isContinuos = false;
+                  break;
+                }
+              }
+            }
+          }
+          if (isContinuos) {
+            ObjectPtr aDataObj = aModel->object(aParentIdx);
+
+            ObjectPtr aPrevObj;
+            if (aFirstIdx.row() > 0) {
+              QModelIndex aPrevIdx = aFirstIdx.sibling(aFirstIdx.row() - 1, 0);
+              aPrevObj = aModel->object(aPrevIdx);
+            }
+
+            ObjectPtr aNextObj;
+            if (aLastIdx.row() < (aModel->rowCount(aParentIdx) - 1)) {
+              QModelIndex aNextIdx = aFirstIdx.sibling(aLastIdx.row() + 1, 0);
+              aNextObj = aModel->object(aNextIdx);
+            }
+
+            bool isPrevFolder = (aPrevObj.get() &&
+              (aPrevObj->groupName() == ModelAPI_Folder::group()));
+            bool isNextFolder = (aNextObj.get() &&
+              (aNextObj->groupName() == ModelAPI_Folder::group()));
+            bool isInFolder = (aDataObj.get() &&
+              (aDataObj->groupName() == ModelAPI_Folder::group()));
+            bool isOutsideFolder = !isInFolder;
+
+            bool hasFirst = false;
+            bool hasLast = false;
+            if (isInFolder) {
+              FolderPtr aFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(aDataObj);
+              FeaturePtr aFirstFeatureInFolder;
+              AttributeReferencePtr aFirstFeatAttr =
+                  aFolder->data()->reference(ModelAPI_Folder::FIRST_FEATURE_ID());
+              if (aFirstFeatAttr)
+                aFirstFeatureInFolder = ModelAPI_Feature::feature(aFirstFeatAttr->value());
+              hasFirst = (aFirstFeatureInFolder == aFeatures.front());
+
+              FeaturePtr aLastFeatureInFolder;
+              AttributeReferencePtr aLastFeatAttr =
+                  aFolder->data()->reference(ModelAPI_Folder::LAST_FEATURE_ID());
+              if (aLastFeatAttr)
+                aLastFeatureInFolder = ModelAPI_Feature::feature(aLastFeatAttr->value());
+              hasLast = (aLastFeatureInFolder == aFeatures.back());
+            }
+            action("INSERT_FOLDER_CMD")->setEnabled(isOutsideFolder);
+            action("ADD_TO_FOLDER_BEFORE_CMD")->setEnabled(isOutsideFolder && isPrevFolder);
+            action("ADD_TO_FOLDER_AFTER_CMD")->setEnabled(isOutsideFolder && isNextFolder);
+            action("ADD_OUT_FOLDER_BEFORE_CMD")->setEnabled(isInFolder && hasFirst);
+            action("ADD_OUT_FOLDER_AFTER_CMD")->setEnabled(isInFolder && hasLast);
+          }
+        }
+      }
+    } // end folder management commands
+
     bool allActive = true;
     foreach( ObjectPtr aObject, aObjects )
       if( aMgr->activeDocument() != aObject->document() )  {
@@ -332,7 +455,7 @@ void XGUI_ContextMenuMgr::updateObjectBrowserMenu()
 
     action("SHOW_RESULTS_CMD")->setEnabled(hasFeature);
     action("SHOW_FEATURE_CMD")->setEnabled(hasResult && hasResultInHistory);
-  }
+  } // end selection processing
 
   // Show/Hide command has to be disabled for objects from non active document
   bool aDeactivate = false;
@@ -419,7 +542,7 @@ void XGUI_ContextMenuMgr::updateViewerMenu()
 #endif
 
   // Update selection menu
-  QIntList aModes = aDisplayer->activeSelectionModes();
+  QIntList aModes = myWorkshop->selectionActivate()->activeSelectionModes();
   action("SELECT_VERTEX_CMD")->setEnabled(true);
   action("SELECT_EDGE_CMD")->setEnabled(true);
   action("SELECT_FACE_CMD")->setEnabled(true);
@@ -492,7 +615,7 @@ void XGUI_ContextMenuMgr::buildObjBrowserMenu()
   aList.append(action("SHOW_CMD"));
   aList.append(action("HIDE_CMD"));
   aList.append(action("SHOW_ONLY_CMD"));
-  aList.append(mySeparator);
+  aList.append(mySeparator1);
   aList.append(action("RENAME_CMD"));
   aList.append(action("COLOR_CMD"));
   aList.append(action("DEFLECTION_CMD"));
@@ -507,12 +630,12 @@ void XGUI_ContextMenuMgr::buildObjBrowserMenu()
   aList.clear();
   aList.append(action("WIREFRAME_CMD"));
   aList.append(action("SHADING_CMD"));
-  aList.append(mySeparator); // this separator is not shown as this action is added after show only
+  aList.append(mySeparator1); // this separator is not shown as this action is added after show only
   // qt list container contains only one instance of the same action
   aList.append(action("SHOW_CMD"));
   aList.append(action("HIDE_CMD"));
   aList.append(action("SHOW_ONLY_CMD"));
-  aList.append(mySeparator);
+  aList.append(mySeparator2);
   aList.append(action("RENAME_CMD"));
   aList.append(action("COLOR_CMD"));
   aList.append(action("DEFLECTION_CMD"));
@@ -532,18 +655,30 @@ void XGUI_ContextMenuMgr::buildObjBrowserMenu()
   aList.append(action("RENAME_CMD"));
   aList.append(action("SHOW_RESULTS_CMD"));
   aList.append(action("MOVE_CMD"));
-  aList.append(mySeparator);
+  aList.append(mySeparator1);
+  aList.append(action("INSERT_FOLDER_CMD"));
+  aList.append(action("ADD_TO_FOLDER_BEFORE_CMD"));
+  aList.append(action("ADD_TO_FOLDER_AFTER_CMD"));
+  aList.append(mySeparator2);
+  aList.append(action("ADD_OUT_FOLDER_BEFORE_CMD"));
+  aList.append(action("ADD_OUT_FOLDER_AFTER_CMD"));
+  aList.append(mySeparator3);
   aList.append(action("CLEAN_HISTORY_CMD"));
   aList.append(action("DELETE_CMD"));
   myObjBrowserMenus[ModelAPI_Feature::group()] = aList;
 
   aList.clear();
   aList.append(action("RENAME_CMD"));
-  aList.append(mySeparator);
+  aList.append(mySeparator1);
   aList.append(action("CLEAN_HISTORY_CMD"));
   aList.append(action("DELETE_CMD"));
   myObjBrowserMenus[ModelAPI_ResultParameter::group()] = aList;
   //-------------------------------------
+
+  aList.clear();
+  aList.append(action("DELETE_CMD"));
+  myObjBrowserMenus[ModelAPI_Folder::group()] = aList;
+
 }
 
 void XGUI_ContextMenuMgr::buildViewerMenu()
@@ -552,7 +687,7 @@ void XGUI_ContextMenuMgr::buildViewerMenu()
   // Result construction menu
   aList.append(action("HIDE_CMD"));
   aList.append(action("SHOW_ONLY_CMD"));
-  aList.append(mySeparator);
+  aList.append(mySeparator1);
   aList.append(action("COLOR_CMD"));
   aList.append(action("DEFLECTION_CMD"));
 #ifdef USE_TRANSPARENCY
@@ -566,10 +701,10 @@ void XGUI_ContextMenuMgr::buildViewerMenu()
   aList.clear();
   aList.append(action("WIREFRAME_CMD"));
   aList.append(action("SHADING_CMD"));
-  aList.append(mySeparator);
+  aList.append(mySeparator1);
   aList.append(action("HIDE_CMD"));
   aList.append(action("SHOW_ONLY_CMD"));
-  aList.append(mySeparator);
+  aList.append(mySeparator2);
   aList.append(action("COLOR_CMD"));
   aList.append(action("DEFLECTION_CMD"));
 #ifdef USE_TRANSPARENCY
@@ -603,11 +738,16 @@ void XGUI_ContextMenuMgr::addObjBrowserMenu(QMenu* theMenu) const
   } else if (aSelected > 1) {
       aActions.append(action("WIREFRAME_CMD"));
       aActions.append(action("SHADING_CMD"));
-      aActions.append(mySeparator);
+      aActions.append(mySeparator1);
       aActions.append(action("SHOW_CMD"));
       aActions.append(action("HIDE_CMD"));
       aActions.append(action("SHOW_ONLY_CMD"));
-      aActions.append(mySeparator);
+      aActions.append(mySeparator2);
+      aActions.append(action("ADD_TO_FOLDER_BEFORE_CMD"));
+      aActions.append(action("ADD_TO_FOLDER_AFTER_CMD"));
+      aActions.append(action("ADD_OUT_FOLDER_BEFORE_CMD"));
+      aActions.append(action("ADD_OUT_FOLDER_AFTER_CMD"));
+      aActions.append(mySeparator3);
       //aActions.append(action("MOVE_CMD"));
       aActions.append(action("COLOR_CMD"));
       aActions.append(action("DEFLECTION_CMD"));
@@ -642,9 +782,8 @@ void XGUI_ContextMenuMgr::addViewerMenu(QMenu* theMenu) const
 
   // Create selection menu
   XGUI_OperationMgr* aOpMgr = myWorkshop->operationMgr();
-  QIntList aModes;
-  myWorkshop->module()->activeSelectionModes(aModes);
-  if ((!aOpMgr->hasOperation()) && aModes.isEmpty()) {
+  if (!aOpMgr->hasOperation() &&
+      myWorkshop->selectionActivate()->activeSelectionPlace() == XGUI_SelectionActivate::Workshop) {
     QMenu* aSelMenu = new QMenu(tr("Selection mode"), theMenu);
     aSelMenu->addAction(action("SELECT_VERTEX_CMD"));
     aSelMenu->addAction(action("SELECT_EDGE_CMD"));
index 7513d5e25199d57206bb7c3e2eeafc29a003f6a4..cc5dcf614996f9f1522201ca9a7ea56a5497b839 100644 (file)
@@ -34,7 +34,7 @@ class QActionGroup;
 
 /**
  * \ingroup GUI
- * A claas wihich provides manement of context menu
+ * A class wihich provides managent of context menu
  */
 class XGUI_EXPORT XGUI_ContextMenuMgr : public QObject
 {
@@ -142,7 +142,9 @@ signals:
 
   //QActionGroup* mySelectActions;
 
-  QAction* mySeparator;
+  QAction* mySeparator1;
+  QAction* mySeparator2;
+  QAction* mySeparator3;
 };
 
 #endif
index 6efc56250afdb3fc9b1899c889cf3770d7c90bc8..b4ee3b011269487627067cdc6dbefabf2ac6ac97 100644 (file)
@@ -35,6 +35,8 @@
 #include <ModelAPI_ResultCompSolid.h>
 #include <ModelAPI_ResultField.h>
 #include <ModelAPI_Tools.h>
+#include <ModelAPI_Folder.h>
+#include <ModelAPI_AttributeReference.h>
 
 #include <Config_FeatureMessage.h>
 #include <Config_DataModelReader.h>
@@ -73,7 +75,10 @@ ResultPartPtr getPartResult(ModelAPI_Object* theObj)
 /// Returns pointer on document if the given object is document object
 ModelAPI_Document* getSubDocument(void* theObj)
 {
-  ModelAPI_Document* aDoc = dynamic_cast<ModelAPI_Document*>((ModelAPI_Entity*)theObj);
+  ModelAPI_Document* aDoc = 0;
+  try {
+    aDoc = dynamic_cast<ModelAPI_Document*>((ModelAPI_Entity*)theObj);
+  } catch(...) {}
   return aDoc;
 }
 
@@ -141,7 +146,7 @@ void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMess
         // Insert new object
         int aRow = aRootDoc->size(aObjType) - 1;
         if (aRow != -1) {
-          if (aObjType == aRootType) {
+          if ((aObjType == aRootType) || (aObjType == ModelAPI_Folder::group())) {
             insertRow(aRow + aNbFolders + 1);
           } else {
             int aFolderId = myXMLReader->rootFolderId(aObjType);
@@ -165,10 +170,10 @@ void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMess
               }
             }
          }
-          int aRow = aDoc->index(aObject);
+          int aRow = aDoc->index(aObject, true);
           if (aRow != -1) {
             int aNbSubFolders = foldersCount(aDoc.get());
-            if (aObjType == aSubType) {
+            if ((aObjType == aSubType) || (aObjType == ModelAPI_Folder::group())) {
               // List of objects under document root
               insertRow(aRow + aNbSubFolders, aDocRoot);
             } else {
@@ -215,8 +220,8 @@ void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMess
     for (aIt = aGroups.begin(); aIt != aGroups.end(); ++aIt) {
       std::string aGroup = (*aIt);
       if (aDoc == aRootDoc) {  // If root objects
-        int aRow = aRootDoc->size(aGroup);
-        if (aGroup == aRootType) {
+        int aRow = aRootDoc->size(aGroup, true);
+        if ((aGroup == aRootType) || (aGroup == ModelAPI_Folder::group())) {
           // Process root folder
           removeRow(aRow + aNbFolders);
           rebuildBranch(aNbFolders, aRow);
@@ -232,7 +237,7 @@ void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMess
         // Check that some folders could erased
         QStringList aNotEmptyFolders = listOfShowNotEmptyFolders();
         foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
-          if ((aNotEmptyFolder.toStdString() == aGroup) && (aRootDoc->size(aGroup) == 0)) {
+          if ((aNotEmptyFolder.toStdString() == aGroup) && (aRootDoc->size(aGroup, true) == 0)) {
             // Appears first object in folder which can not be shown empty
             removeRow(myXMLReader->rootFolderId(aGroup));
             removeShownFolder(aRootDoc, aNotEmptyFolder);
@@ -244,9 +249,9 @@ void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMess
         // Remove row for sub-document
         QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get(), 0);
         if (aDocRoot.isValid()) {
-          int aRow = aDoc->size(aGroup);
+          int aRow = aDoc->size(aGroup, true);
           int aNbSubFolders = foldersCount(aDoc.get());
-          if (aGroup == aSubType) {
+          if ((aGroup == aSubType) || (aGroup == ModelAPI_Folder::group())) {
             // List of objects under document root
             removeRow(aRow + aNbSubFolders, aDocRoot);
             rebuildBranch(aNbSubFolders, aRow, aDocRoot);
@@ -261,7 +266,7 @@ void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMess
           }
           // Check that some folders could disappear
           QStringList aNotEmptyFolders = listOfShowNotEmptyFolders(false);
-          int aSize = aDoc->size(aGroup);
+          int aSize = aDoc->size(aGroup, true);
           foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
             if ((aNotEmptyFolder.toStdString() == aGroup) && (aSize == 0)) {
               // Appears first object in folder which can not be shown empty
@@ -283,7 +288,6 @@ void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMess
     std::set<ObjectPtr> aObjects = aUpdMsg->objects();
 
     std::set<ObjectPtr>::const_iterator aIt;
-    std::string aObjType;
     for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
       ObjectPtr aObject = (*aIt);
       if (aObject->data()->isValid()) {
@@ -295,9 +299,13 @@ void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMess
             QModelIndex aIndex = objectIndex(aResult, 0);
             removeRows(0, aResult->stepsSize(), aIndex);
         } else {
-          QModelIndex aIndex = objectIndex(aObject, 0);
-          if (aIndex.isValid()) {
-            emit dataChanged(aIndex, aIndex);
+          if (aObject->groupName() == ModelAPI_Folder::group()) {
+            rebuildDataTree();
+          } else {
+            QModelIndex aIndex = objectIndex(aObject, 0);
+            if (aIndex.isValid()) {
+              emit dataChanged(aIndex, aIndex);
+            }
           }
         }
       } else {
@@ -368,8 +376,11 @@ ObjectPtr XGUI_DataModel::object(const QModelIndex& theIndex) const
 {
   if (theIndex.internalId() == 0) // this is a folder
     return ObjectPtr();
-  ModelAPI_Object* aObj =
-    dynamic_cast<ModelAPI_Object*>((ModelAPI_Entity*)theIndex.internalPointer());
+  ModelAPI_Object* aObj = 0;
+  try {
+    aObj = dynamic_cast<ModelAPI_Object*>((ModelAPI_Entity*)theIndex.internalPointer());
+  } catch(...) {}
+
   if (!aObj)
     return ObjectPtr();
   if (getSubDocument(aObj)) // the selected index is a folder of sub-document
@@ -383,7 +394,7 @@ QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject, int theColumn
 {
   std::string aType = theObject->groupName();
   DocumentPtr aDoc = theObject->document();
-  int aRow = aDoc->index(theObject);
+  int aRow = aDoc->index(theObject, true);
   if (aRow == -1) {
     // it could be a part of complex object
     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
@@ -397,6 +408,10 @@ QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject, int theColumn
           }
         }
       }
+      int aFRow = -1;
+      FolderPtr aFolder = aDoc->findContainingFolder(aFeature, aFRow);
+      if (aFolder.get())
+        aRow = aFRow;
     } else {
       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
       if (aResult.get()) {
@@ -413,10 +428,11 @@ QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject, int theColumn
   }
   SessionPtr aSession = ModelAPI_Session::get();
   DocumentPtr aRootDoc = aSession->moduleDocument();
-  if (aDoc == aRootDoc && myXMLReader->rootType() == aType) {
+  if (aDoc == aRootDoc &&
+    ((myXMLReader->rootType() == aType) || (aType == ModelAPI_Folder::group()))) {
     // The object from root document
     aRow += foldersCount();
-  } else if (myXMLReader->subType() == aType) {
+  } else if ((myXMLReader->subType() == aType) || (aType == ModelAPI_Folder::group())) {
     // The object from sub document
     aRow += foldersCount(aDoc.get());
   }
@@ -497,14 +513,13 @@ QVariant XGUI_DataModel::data(const QModelIndex& theIndex, int theRole) const
         }
       }
     } else {
-      ModelAPI_Object* aObj =
-        dynamic_cast<ModelAPI_Object*>((ModelAPI_Entity*)theIndex.internalPointer());
+      ObjectPtr aObj = object(theIndex);
       if (aObj) {
         switch (theRole) {
         case Qt::DisplayRole:
           {
             if (aObj->groupName() == ModelAPI_ResultParameter::group()) {
-              ModelAPI_ResultParameter* aParam = dynamic_cast<ModelAPI_ResultParameter*>(aObj);
+              ResultParameterPtr aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObj);
               AttributeDoublePtr aValueAttribute =
                 aParam->data()->real(ModelAPI_ResultParameter::VALUE());
               QString aVal = QString::number(aValueAttribute->value());
@@ -513,7 +528,7 @@ QVariant XGUI_DataModel::data(const QModelIndex& theIndex, int theRole) const
             }
             QString aSuffix;
             if (aObj->groupName() == myXMLReader->subType()) {
-              ResultPartPtr aPartRes = getPartResult(aObj);
+              ResultPartPtr aPartRes = getPartResult(aObj.get());
               if (aPartRes.get()) {
                 if (aPartRes->partDoc().get() == NULL)
                   aSuffix = " (Not loaded)";
@@ -522,7 +537,12 @@ QVariant XGUI_DataModel::data(const QModelIndex& theIndex, int theRole) const
             return aObj->data()->name().c_str() + aSuffix;
           }
         case Qt::DecorationRole:
-          return ModuleBase_IconFactory::get()->getIcon(object(theIndex));
+          {
+            if (aObj->groupName() == ModelAPI_Folder::group())
+              return QIcon(":pictures/features_folder.png");
+            else
+              return ModuleBase_IconFactory::get()->getIcon(aObj);
+          }
         }
       } else {
         switch (theRole) {
@@ -564,7 +584,7 @@ int XGUI_DataModel::rowCount(const QModelIndex& theParent) const
     int aNbItems = 0;
     std::string aType = myXMLReader->rootType();
     if (!aType.empty())
-      aNbItems = aRootDoc->size(aType);
+      aNbItems = aRootDoc->size(aType, true);
     return aNbFolders + aNbItems;
   }
 
@@ -601,7 +621,7 @@ int XGUI_DataModel::rowCount(const QModelIndex& theParent) const
         int aNbSubItems = 0;
         std::string aSubType = myXMLReader->subType();
         if (!aSubType.empty())
-          aNbSubItems = aSubDoc->size(aSubType);
+          aNbSubItems = aSubDoc->size(aSubType, true);
         return aNbSubItems + aNbSubFolders;
       } else {
         // Check for composite object
@@ -614,6 +634,9 @@ int XGUI_DataModel::rowCount(const QModelIndex& theParent) const
         ModelAPI_ResultField* aFieldRes = dynamic_cast<ModelAPI_ResultField*>(aObj);
         if (aFieldRes)
           return aFieldRes->stepsSize();
+        ModelAPI_Folder* aFolder = dynamic_cast<ModelAPI_Folder*>(aObj);
+        if (aFolder)
+          return getNumberOfFolderItems(aFolder);
       }
     }
   }
@@ -641,8 +664,8 @@ QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex &
     else { // return object under root index
       std::string aType = myXMLReader->rootType();
       int aObjId = theRow - aNbFolders;
-      if (aObjId < aRootDoc->size(aType)) {
-        ObjectPtr aObj = aRootDoc->object(aType, aObjId);
+      if (aObjId < aRootDoc->size(aType, true)) {
+        ObjectPtr aObj = aRootDoc->object(aType, aObjId, true);
         aIndex = objectIndex(aObj, theColumn);
       }
     }
@@ -652,7 +675,7 @@ QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex &
     if (aId == 0) { // return object index inside of first level of folders
       std::string aType = myXMLReader->rootFolderType(aParentPos);
       if (theRow < aRootDoc->size(aType)) {
-        ObjectPtr aObj = aRootDoc->object(aType, theRow);
+        ObjectPtr aObj = aRootDoc->object(aType, theRow, true);
         aIndex = objectIndex(aObj, theColumn);
       }
     } else {
@@ -685,7 +708,7 @@ QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex &
           } else {
             // this is an object under sub document root
             std::string aType = myXMLReader->subType();
-            ObjectPtr aObj = aSubDoc->object(aType, theRow - aNbSubFolders);
+            ObjectPtr aObj = aSubDoc->object(aType, theRow - aNbSubFolders, true);
             aIndex = objectIndex(aObj, theColumn);
           }
         } else {
@@ -704,6 +727,11 @@ QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex &
                 dynamic_cast<ModelAPI_ResultField*>(aParentObj);
               if (aFieldRes) {
                 aIndex = createIndex(theRow, theColumn, aFieldRes->step(theRow));
+              } else {
+                ModelAPI_Folder* aFolder = dynamic_cast<ModelAPI_Folder*>(aParentObj);
+                ObjectPtr aObj = getObjectInFolder(aFolder, theRow);
+                if (aObj.get())
+                  aIndex = objectIndex(aObj, theColumn);
               }
             }
           }
@@ -734,10 +762,13 @@ QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const
     }
     ObjectPtr aObj = object(theIndex);
     if (!aObj.get()) {
-      // It can b e a step of a field
-      ModelAPI_ResultField::ModelAPI_FieldStep* aStep =
-        dynamic_cast<ModelAPI_ResultField::ModelAPI_FieldStep*>
-        ((ModelAPI_Entity*)theIndex.internalPointer());
+      // It can be a step of a field
+      ModelAPI_ResultField::ModelAPI_FieldStep* aStep = 0;
+      try {
+        aStep = dynamic_cast<ModelAPI_ResultField::ModelAPI_FieldStep*>
+                ((ModelAPI_Entity*)theIndex.internalPointer());
+      } catch(...) {}
+
       if (aStep) {
         ModelAPI_ResultField* aField = aStep->field();
         DocumentPtr aDoc = aSession->activeDocument();
@@ -760,6 +791,11 @@ QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const
       if (aCompFea.get()) {
         return objectIndex(aCompFea);
       }
+      DocumentPtr aDoc = aFeature->document();
+      int aRow;
+      FolderPtr aFolder = aDoc->findContainingFolder(aFeature, aRow);
+      if (aFolder.get())
+        return objectIndex(aFolder);
     }
     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
     if (aResult.get()) {
@@ -773,7 +809,7 @@ QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const
     DocumentPtr aRootDoc = aSession->moduleDocument();
     DocumentPtr aSubDoc = aObj->document();
     if (aSubDoc == aRootDoc) {
-      if (aType == myXMLReader->rootType())
+      if ((aType == myXMLReader->rootType()) || (aType == ModelAPI_Folder::group()))
         return QModelIndex();
       else {
         // return first level of folder index
@@ -782,7 +818,7 @@ QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const
         return createIndex(aFolderId, 1, (void*)Q_NULLPTR);
       }
     } else {
-      if (aType == myXMLReader->subType())
+      if ((aType == myXMLReader->subType()) || (aType == ModelAPI_Folder::group()))
         return findDocumentRootIndex(aSubDoc.get());
       else {
         // return first level of folder index
@@ -912,11 +948,11 @@ QModelIndex
       }
     }
   } else { // If document is attached to feature
-    int aNb = aRootDoc->size(ModelAPI_Feature::group());
+    int aNb = aRootDoc->size(ModelAPI_Feature::group(), true);
     ObjectPtr aObj;
     ResultPartPtr aPartRes;
     for (int i = 0; i < aNb; i++) {
-      aObj = aRootDoc->object(ModelAPI_Feature::group(), i);
+      aObj = aRootDoc->object(ModelAPI_Feature::group(), i, true);
       aPartRes = getPartResult(aObj.get());
       if (aPartRes.get() && (aPartRes->partDoc().get() == theDoc)) {
         int aRow = i;
@@ -1029,6 +1065,12 @@ QModelIndex XGUI_DataModel::lastHistoryIndex() const
   }
 }
 
+//******************************************************
+bool XGUI_DataModel::hasHiddenState(const QModelIndex& theIndex)
+{
+  return getVisibilityState(theIndex) == Hidden;
+}
+
 //******************************************************
 int XGUI_DataModel::folderId(std::string theType, ModelAPI_Document* theDoc) const
 {
@@ -1119,3 +1161,45 @@ XGUI_DataModel::VisibilityState
   }
   return NoneState;
 }
+
+
+int XGUI_DataModel::getNumberOfFolderItems(const ModelAPI_Folder* theFolder) const
+{
+  DocumentPtr aDoc = theFolder->document();
+
+  FeaturePtr aFirstFeatureInFolder;
+  AttributeReferencePtr aFirstFeatAttr =
+      theFolder->data()->reference(ModelAPI_Folder::FIRST_FEATURE_ID());
+  if (aFirstFeatAttr)
+    aFirstFeatureInFolder = ModelAPI_Feature::feature(aFirstFeatAttr->value());
+  if (!aFirstFeatureInFolder.get())
+    return 0;
+
+  FeaturePtr aLastFeatureInFolder;
+  AttributeReferencePtr aLastFeatAttr =
+      theFolder->data()->reference(ModelAPI_Folder::LAST_FEATURE_ID());
+  if (aLastFeatAttr)
+    aLastFeatureInFolder = ModelAPI_Feature::feature(aLastFeatAttr->value());
+  if (!aLastFeatureInFolder.get())
+    return 0;
+
+  int aFirst = aDoc->index(aFirstFeatureInFolder);
+  int aLast = aDoc->index(aLastFeatureInFolder);
+  return aLast - aFirst + 1;
+}
+
+ObjectPtr XGUI_DataModel::getObjectInFolder(const ModelAPI_Folder* theFolder, int theId) const
+{
+  DocumentPtr aDoc = theFolder->document();
+
+  FeaturePtr aFirstFeatureInFolder;
+  AttributeReferencePtr aFirstFeatAttr =
+      theFolder->data()->reference(ModelAPI_Folder::FIRST_FEATURE_ID());
+  if (aFirstFeatAttr)
+    aFirstFeatureInFolder = ModelAPI_Feature::feature(aFirstFeatAttr->value());
+  if (!aFirstFeatureInFolder.get())
+    return ObjectPtr();
+
+  int aFirst = aDoc->index(aFirstFeatureInFolder);
+  return aDoc->object(ModelAPI_Feature::group(), aFirst + theId);
+}
index 53e9109801667ffbe392733c4636fb5dbbcd619d..e89546161dda5a6b3a564dcc0fe37741a607a222 100644 (file)
@@ -142,6 +142,11 @@ public:
   /// Do not processing anymore events of model loop
   //bool blockEventsProcessing(const bool theState);
 
+  /// Returns true if the data model item has Hidden visual state
+  /// \param theIndex a tree model item
+  /// \return boolean value
+  bool hasHiddenState(const QModelIndex& theIndex);
+
 signals:
   /// Signal about tree had been rebuilt
   void treeRebuilt();
@@ -182,6 +187,9 @@ private:
   /// \param fromRoot - root document flag
   QStringList listOfShowNotEmptyFolders(bool fromRoot = true) const;
 
+  int getNumberOfFolderItems(const ModelAPI_Folder* theFolder) const;
+  ObjectPtr getObjectInFolder(const ModelAPI_Folder* theFolder, int theId) const;
+
   VisibilityState getVisibilityState(const QModelIndex& theIndex) const;
 
   void addShownFolder(DocumentPtr theDoc, QString theFolder)
index 9612452007b84038bfce8bec51f01a0824c51f4f..b0dec532345a4f86c6e01b08a53a488e3d879609 100644 (file)
 //
 
 #include "XGUI_Displayer.h"
-#include "XGUI_Workshop.h"
-#include "XGUI_ViewerProxy.h"
-#include "XGUI_SelectionMgr.h"
-#include "XGUI_Selection.h"
+
 #include "XGUI_CustomPrs.h"
+#include "XGUI_FacesPanel.h"
+#include "XGUI_Selection.h"
+#include "XGUI_SelectionActivate.h"
+#include "XGUI_SelectionMgr.h"
+#include "XGUI_ViewerProxy.h"
+#include "XGUI_Workshop.h"
 
 #ifndef HAVE_SALOME
 #include <AppElements_Viewer.h>
 #include <ModelAPI_AttributeIntArray.h>
 #include <ModelAPI_ResultCompSolid.h>
 
+#include <ModuleBase_BRepOwner.h>
+#include <ModuleBase_IModule.h>
+#include <ModuleBase_Preferences.h>
 #include <ModuleBase_ResultPrs.h>
 #include <ModuleBase_Tools.h>
-#include <ModuleBase_IModule.h>
 #include <ModuleBase_ViewerPrs.h>
-#include <ModuleBase_Preferences.h>
 
 #include <GeomAPI_Shape.h>
 #include <GeomAPI_IPresentable.h>
 #include <AIS_Point.hxx>
 #endif
 #include <AIS_Selection.hxx>
-#include <TColStd_ListIteratorOfListOfInteger.hxx>
-#include <SelectMgr_ListOfFilter.hxx>
-#include <SelectMgr_ListIteratorOfListOfFilter.hxx>
 #include <Prs3d_Drawer.hxx>
 #include <Prs3d_IsoAspect.hxx>
+#include <SelectMgr_ListOfFilter.hxx>
+#include <SelectMgr_ListIteratorOfListOfFilter.hxx>
 #include <SelectMgr_SelectionManager.hxx>
+#include <TColStd_ListIteratorOfListOfInteger.hxx>
 
 #include <StdSelect_ViewerSelector3d.hxx>
 
 /// defines the local context mouse selection sensitivity
 const int MOUSE_SENSITIVITY_IN_PIXEL = 10;
 
-//#define DEBUG_ACTIVATE_OBJECTS
-//#define DEBUG_DEACTIVATE
-//#define DEBUG_ACTIVATE_AIS
-//#define DEBUG_DEACTIVATE_AIS
-
 //#define DEBUG_DISPLAY
 //#define DEBUG_FEATURE_REDISPLAY
 //#define DEBUG_SELECTION_FILTERS
@@ -100,6 +99,9 @@ const int MOUSE_SENSITIVITY_IN_PIXEL = 10;
 
 #define CLEAR_OUTDATED_SELECTION_BEFORE_REDISPLAY
 
+//#define DEBUG_VIEWER_BLOCKED_COUNT
+
+//**************************************************************
 void displayedObjects(const Handle(AIS_InteractiveContext)& theAIS, AIS_ListOfInteractive& theList)
 {
   // Get from null point
@@ -116,44 +118,26 @@ QString qIntListInfo(const QIntList& theValues, const QString& theSeparator = QS
   return anInfo.join(theSeparator);
 }
 
-void deselectPresentation(const Handle(AIS_InteractiveObject) theObject,
-                          const Handle(AIS_InteractiveContext)& theContext)
-{
-  NCollection_List<Handle(SelectBasics_EntityOwner)> aResultOwners;
-
-  for (theContext->InitSelected(); theContext->MoreSelected(); theContext->NextSelected()) {
-    Handle(SelectMgr_EntityOwner) anOwner = theContext->SelectedOwner();
-    if (anOwner.IsNull()) // TODO: check why it is possible
-      continue;
-    if (anOwner->Selectable() == theObject && anOwner->IsSelected())
-      aResultOwners.Append(anOwner);
-  }
-  NCollection_List<Handle(SelectBasics_EntityOwner)>::Iterator anOwnersIt (aResultOwners);
-  Handle(SelectMgr_EntityOwner) anOwner;
-  for (; anOwnersIt.More(); anOwnersIt.Next()) {
-    anOwner = Handle(SelectMgr_EntityOwner)::DownCast(anOwnersIt.Value());
-    if (!anOwner.IsNull())
-      theContext->AddOrRemoveSelected(anOwner, false);
-  }
-}
-
+//**************************************************************
 XGUI_Displayer::XGUI_Displayer(XGUI_Workshop* theWorkshop)
-  : myWorkshop(theWorkshop), myNeedUpdate(false),
-  myIsTrihedronActive(true), myViewerBlockedRecursiveCount(0),
-  myIsFirstAISContextUse(true)
+: myWorkshop(theWorkshop), myNeedUpdate(false),
+  myViewerBlockedRecursiveCount(0), myIsFirstAISContextUse(true)
 {
   myCustomPrs = std::shared_ptr<GeomAPI_ICustomPrs>(new XGUI_CustomPrs(theWorkshop));
 }
 
+//**************************************************************
 XGUI_Displayer::~XGUI_Displayer()
 {
 }
 
+//**************************************************************
 bool XGUI_Displayer::isVisible(ObjectPtr theObject) const
 {
   return myResult2AISObjectMap.contains(theObject);
 }
 
+//**************************************************************
 bool XGUI_Displayer::display(ObjectPtr theObject, bool theUpdateViewer)
 {
   bool aDisplayed = false;
@@ -235,6 +219,7 @@ bool XGUI_Displayer::display(ObjectPtr theObject, bool theUpdateViewer)
   return aDisplayed;
 }
 
+//**************************************************************
 bool canBeShaded(Handle(AIS_InteractiveObject) theAIS, ModuleBase_IModule* theModule)
 {
   Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(theAIS);
@@ -253,6 +238,7 @@ bool canBeShaded(Handle(AIS_InteractiveObject) theAIS, ModuleBase_IModule* theMo
   return false;
 }
 
+//**************************************************************
 bool XGUI_Displayer::display(ObjectPtr theObject, AISObjectPtr theAIS,
                              bool isShading, bool theUpdateViewer)
 {
@@ -279,7 +265,7 @@ bool XGUI_Displayer::display(ObjectPtr theObject, AISObjectPtr theAIS,
     aDisplayed = true;
 
     emit objectDisplayed(theObject, theAIS);
-    activate(anAISIO, myActiveSelectionModes, theUpdateViewer);
+    selectionActivate()->activate(anAISIO, theUpdateViewer);
   }
   if (theUpdateViewer)
     updateViewer();
@@ -287,6 +273,7 @@ bool XGUI_Displayer::display(ObjectPtr theObject, AISObjectPtr theAIS,
   return aDisplayed;
 }
 
+//**************************************************************
 bool XGUI_Displayer::erase(ObjectPtr theObject, const bool theUpdateViewer)
 {
   bool aErased = false;
@@ -324,6 +311,7 @@ bool XGUI_Displayer::erase(ObjectPtr theObject, const bool theUpdateViewer)
   return aErased;
 }
 
+//**************************************************************
 bool XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer)
 {
   bool aRedisplayed = false;
@@ -382,7 +370,7 @@ bool XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer)
         myWorkshop->module()->storeSelection();
 
 #ifdef CLEAR_OUTDATED_SELECTION_BEFORE_REDISPLAY
-      deselectPresentation(aAISIO, aContext);
+      myWorkshop->selector()->deselectPresentation(aAISIO);
 #endif
       aContext->Redisplay(aAISIO, false);
 
@@ -404,6 +392,7 @@ bool XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer)
   return aRedisplayed;
 }
 
+//**************************************************************
 void XGUI_Displayer::redisplayObjects()
 {
   // redisplay objects visualized in the viewer
@@ -417,30 +406,7 @@ void XGUI_Displayer::redisplayObjects()
   Events_Loop::loop()->flush(EVENT_DISP);
 }
 
-void XGUI_Displayer::deactivate(ObjectPtr theObject, const bool theUpdateViewer)
-{
-#ifdef DEBUG_DEACTIVATE
-  QString anInfoStr = ModuleBase_Tools::objectInfo(theObject);
-  qDebug(QString("deactivate: myActiveSelectionModes[%1]: %2, objects = ").
-    arg(myActiveSelectionModes.size()).arg(qIntListInfo(myActiveSelectionModes)).
-    arg(anInfoStr).
-    toStdString().c_str());
-#endif
-  Handle(AIS_InteractiveContext) aContext = AISContext();
-  if (!aContext.IsNull() && isVisible(theObject)) {
-    AISObjectPtr anObj = myResult2AISObjectMap[theObject];
-    Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
-
-    deactivateAIS(anAIS);
-    // the selection from the previous activation modes should be cleared manually (#26172)
-#ifndef CLEAR_OUTDATED_SELECTION_BEFORE_REDISPLAY
-    deselectPresentation(anAIS, aContext);
-#endif
-    if (theUpdateViewer)
-      updateViewer();
-  }
-}
-
+//**************************************************************
 void XGUI_Displayer::deactivateObjects(const QObjectPtrList& theObjList,
                                        const bool theUpdateViewer)
 {
@@ -450,38 +416,14 @@ void XGUI_Displayer::deactivateObjects(const QObjectPtrList& theObjList,
 
   QObjectPtrList::const_iterator anIt = theObjList.begin(), aLast = theObjList.end();
   for (; anIt != aLast; anIt++) {
-    deactivate(*anIt, false);
+    selectionActivate()->deactivate(*anIt, false);
   }
   //VSV It seems that there is no necessity to update viewer on deactivation
   //if (theUpdateViewer)
   //  updateViewer();
 }
 
-void XGUI_Displayer::getModesOfActivation(ObjectPtr theObject, QIntList& theModes)
-{
-  Handle(AIS_InteractiveContext) aContext = AISContext();
-  if (aContext.IsNull() || !isVisible(theObject))
-    return;
-
-  AISObjectPtr aAISObj = getAISObject(theObject);
-
-  if (aAISObj.get() != NULL) {
-    Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
-    TColStd_ListOfInteger aTColModes;
-    aContext->ActivatedModes(anAISIO, aTColModes);
-    TColStd_ListIteratorOfListOfInteger itr( aTColModes );
-    for (; itr.More(); itr.Next() ) {
-      theModes.append(itr.Value());
-    }
-  }
-}
-
-int XGUI_Displayer::getSelectionMode(int theShapeType)
-{
-  return (theShapeType > TopAbs_SHAPE) ? theShapeType :
-                                         AIS_Shape::SelectionMode((TopAbs_ShapeEnum)theShapeType);
-}
-
+//**************************************************************
 bool XGUI_Displayer::isVisible(XGUI_Displayer* theDisplayer, const ObjectPtr& theObject)
 {
   bool aVisible = false;
@@ -520,127 +462,7 @@ bool XGUI_Displayer::isVisible(XGUI_Displayer* theDisplayer, const ObjectPtr& th
   return aVisible;
 }
 
-#ifdef DEBUG_ACTIVATE_OBJECTS
-QString getModeInfo(const int theMode)
-{
-  QString anInfo = "Undefined";
-  switch(theMode) {
-    case 0: anInfo = "SHAPE(0)"; break;
-    case 1: anInfo = "VERTEX(1)"; break;
-    case 2: anInfo = "EDGE(2)"; break;
-    case 3: anInfo = "WIRE(3)"; break;
-    case 4: anInfo = "FACE(4)"; break;
-    case 5: anInfo = "SHELL(5)"; break;
-    case 6: anInfo = "SOLID(6)"; break;
-    case 7: anInfo = "COMPSOLID(7)"; break;
-    case 8: anInfo = "COMPOUND(8)"; break;
-    case 100: anInfo = "Sel_Mode_First(100)"; break; //SketcherPrs_Tools
-    case 101: anInfo = "Sel_Constraint(101)"; break;
-    case 102: anInfo = "Sel_Dimension_All(102)"; break;
-    case 103: anInfo = "Sel_Dimension_Line(103)"; break;
-    case 104: anInfo = "Sel_Dimension_Text(104)"; break;
-    default: break;
-  }
-  return anInfo;
-}
-
-QString getModesInfo(const QIntList& theModes)
-{
-  QStringList aModesInfo;
-  for (int i = 0, aSize = theModes.size(); i < aSize; i++)
-    aModesInfo.append(getModeInfo(theModes[i]));
-  return QString("[%1] = %2").arg(aModesInfo.size()).arg(aModesInfo.join(", "));
-}
-#endif
-
-void XGUI_Displayer::activateObjects(const QIntList& theModes, const QObjectPtrList& theObjList,
-                                     const bool theUpdateViewer)
-{
-  // Convert shape types to selection types
-  QIntList aModes;
-  foreach(int aType, theModes) {
-    aModes.append(getSelectionMode(aType));
-  }
-
-#ifdef DEBUG_ACTIVATE_OBJECTS
-  QStringList anInfo;
-  QObjectPtrList::const_iterator anIt = theObjList.begin(), aLast = theObjList.end();
-  for (; anIt != aLast; ++anIt) {
-    anInfo.append(ModuleBase_Tools::objectInfo((*anIt)));
-  }
-  QString anInfoStr = anInfo.join(", ");
-
-  qDebug(QString("activateObjects: new modes%1, active modes%2, objects[%3] = %4").
-    arg(getModesInfo(aModes)).
-    arg(getModesInfo(myActiveSelectionModes)).
-    arg(theObjList.size()).
-    arg(anInfoStr).
-    toStdString().c_str());
-#endif
-  // In order to avoid doblications of selection modes
-  QIntList aNewModes;
-  foreach (int aMode, aModes) {
-    if (!aNewModes.contains(aMode))
-      aNewModes.append(aMode);
-  }
-  myActiveSelectionModes = aNewModes;
-  Handle(AIS_InteractiveContext) aContext = AISContext();
-  // Open local context if there is no one
-  if (aContext.IsNull())
-    return;
-
-  //aContext->UseDisplayedObjects();
-  //myUseExternalObjects = true;
-
-  Handle(AIS_InteractiveObject) anAISIO;
-  AIS_ListOfInteractive aPrsList;
-  //if (aObjList.isEmpty())
-  //  return;
-  //else {
-  foreach(ObjectPtr aObj, theObjList) {
-    if (myResult2AISObjectMap.contains(aObj))
-      aPrsList.Append(myResult2AISObjectMap[aObj]->impl<Handle(AIS_InteractiveObject)>());
-  }
-  //}
-
-  // Add trihedron because it has to partisipate in selection
-  Handle(AIS_InteractiveObject) aTrihedron;
-  if (isTrihedronActive()) {
-    aTrihedron = getTrihedron();
-    if (!aTrihedron.IsNull() && aContext->IsDisplayed(aTrihedron))
-      aPrsList.Append(aTrihedron);
-  }
-  if (aPrsList.Extent() == 0)
-    return;
-
-  AIS_ListIteratorOfListOfInteractive aLIt(aPrsList);
-  bool isActivationChanged = false;
-  for(aLIt.Initialize(aPrsList); aLIt.More(); aLIt.Next()){
-    anAISIO = aLIt.Value();
-    if (activate(anAISIO, myActiveSelectionModes, false))
-      isActivationChanged = true;
-  }
-}
-
-bool XGUI_Displayer::isActive(ObjectPtr theObject) const
-{
-  Handle(AIS_InteractiveContext) aContext = AISContext();
-  if (aContext.IsNull() || !isVisible(theObject))
-    return false;
-
-  AISObjectPtr anObj = myResult2AISObjectMap[theObject];
-  Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
-
-  TColStd_ListOfInteger aModes;
-  aContext->ActivatedModes(anAIS, aModes);
-  #ifdef TINSPECTOR
-  if (getCallBack()) getCallBack()->ActivatedModes(anAIS, aModes);
-  #endif
-
-  return aModes.Extent() > 0;
-}
-
-
+//**************************************************************
 void XGUI_Displayer::setSelected(const  QList<ModuleBase_ViewerPrsPtr>& theValues,
                                  bool theUpdateViewer)
 {
@@ -703,6 +525,7 @@ void XGUI_Displayer::setSelected(const  QList<ModuleBase_ViewerPrsPtr>& theValue
     updateViewer();
 }
 
+//**************************************************************
 void XGUI_Displayer::clearSelected(const bool theUpdateViewer)
 {
   Handle(AIS_InteractiveContext) aContext = AISContext();
@@ -715,6 +538,7 @@ void XGUI_Displayer::clearSelected(const bool theUpdateViewer)
   }
 }
 
+//**************************************************************
 bool XGUI_Displayer::eraseAll(const bool theUpdateViewer)
 {
   bool aErased = false;
@@ -744,169 +568,8 @@ bool XGUI_Displayer::eraseAll(const bool theUpdateViewer)
   return aErased;
 }
 
-void deactivateObject(Handle(AIS_InteractiveContext) theContext,
-                      Handle(AIS_InteractiveObject) theObject
-#ifdef TINSPECTOR
-                      , Handle(VInspectorAPI_CallBack) theCallBack
-#endif
-                      )
-{
-  if (!theObject.IsNull()) {
-    theContext->Deactivate(theObject);
-    #ifdef TINSPECTOR
-    if (theCallBack) theCallBack->Deactivate(theObject);
-    #endif
-  }
-}
-
-void XGUI_Displayer::deactivateTrihedron(const bool theUpdateViewer) const
-{
-  Handle(AIS_InteractiveObject) aTrihedron = getTrihedron();
-  Handle(AIS_InteractiveContext) aContext = AISContext();
-  if (!aTrihedron.IsNull() && aContext->IsDisplayed(aTrihedron)) {
-    Handle(AIS_Trihedron) aTrie = Handle(AIS_Trihedron)::DownCast(aTrihedron);
-    deactivateObject(aContext, aTrie
-    #ifdef TINSPECTOR
-      , getCallBack()
-    #endif
-      );
-
-    /// #1136 hidden axis are selected in sketch
-#ifdef BEFORE_TRIHEDRON_PATCH
-    deactivateObject(aContext, aTrie->XAxis()
-    #ifdef TINSPECTOR
-      , getCallBack()
-    #endif
-    );
-    deactivateObject(aContext, aTrie->YAxis()
-    #ifdef TINSPECTOR
-      , getCallBack()
-    #endif
-    );
-    deactivateObject(aContext, aTrie->Axis()
-    #ifdef TINSPECTOR
-      , getCallBack()
-    #endif
-    );
-    deactivateObject(aContext, aTrie->Position()
-    #ifdef TINSPECTOR
-      , getCallBack()
-    #endif
-    );
-
-    deactivateObject(aContext, aTrie->XYPlane()
-    #ifdef TINSPECTOR
-      , getCallBack()
-    #endif
-    );
-    deactivateObject(aContext, aTrie->XZPlane()
-    #ifdef TINSPECTOR
-      , getCallBack()
-    #endif
-    );
-    deactivateObject(aContext, aTrie->YZPlane()
-    #ifdef TINSPECTOR
-      , getCallBack()
-    #endif
-    );
-#endif
-    if (theUpdateViewer)
-      updateViewer();
-  }
-}
-
-Handle(AIS_InteractiveObject) XGUI_Displayer::getTrihedron() const
-{
-  return myWorkshop->viewer()->trihedron();
-}
-
-/*void XGUI_Displayer::openLocalContext()
-{
-  Handle(AIS_InteractiveContext) aContext = AISContext();
-  // Open local context if there is no one
-  if (!aContext.IsNull() && !aContext->HasOpenedContext()) {
-    // Preserve selected objects
-    //AIS_ListOfInteractive aAisList;
-    //for (aContext->InitCurrent(); aContext->MoreCurrent(); aContext->NextCurrent())
-    //  aAisList.Append(aContext->Current());
-
-    // get the filters from the global context and append them to the local context
-    // a list of filters in the global context is not cleared and should be cleared here
-    SelectMgr_ListOfFilter aFilters;
-    aFilters.Assign(aContext->Filters());
-    // it is important to remove the filters in the global context, because there is a code
-    // in the closeLocalContex, which restore the global context filters
-    aContext->RemoveFilters();
-
-    //aContext->ClearCurrents();
-    aContext->OpenLocalContext();
-    //deactivateTrihedron();
-    //aContext->NotUseDisplayedObjects();
-
-    //myUseExternalObjects = false;
-
-    SelectMgr_ListIteratorOfListOfFilter aIt(aFilters);
-    for (;aIt.More(); aIt.Next()) {
-      aContext->AddFilter(aIt.Value());
-    }
-    // Restore selection
-    //AIS_ListIteratorOfListOfInteractive aIt2(aAisList);
-    //for(; aIt2.More(); aIt2.Next()) {
-    //  aContext->SetSelected(aIt2.Value(), false);
-    //}
-  }
-}*/
-
-/*void XGUI_Displayer::closeLocalContexts(const bool theUpdateViewer)
-{
-  Handle(AIS_InteractiveContext) aContext = AISContext();
-  if (!aContext.IsNull() && aContext->HasOpenedContext()) {
-    // Preserve selected objects
-    //AIS_ListOfInteractive aAisList;
-    //for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected())
-    //  aAisList.Append(aContext->SelectedInteractive());
-
-    // get the filters from the local context and append them to the global context
-    // a list of filters in the local context is cleared
-    SelectMgr_ListOfFilter aFilters;
-    aFilters.Assign(aContext->Filters());
-
-    //aContext->ClearSelected();
-    aContext->CloseAllContexts(false);
-
-    // From the moment when the AIS_DS_Displayed flag is used in the Display of AIS object,
-    // this code is obsolete. It is temporaty commented and should be removed after
-    // the test campaign.
-    // Redisplay all object if they were displayed in localContext
-    /*Handle(AIS_InteractiveObject) aAISIO;
-    foreach (AISObjectPtr aAIS, myResult2AISObjectMap) {
-      aAISIO = aAIS->impl<Handle(AIS_InteractiveObject)>();
-      if (aContext->DisplayStatus(aAISIO) != AIS_DS_Displayed) {
-        aContext->Display(aAISIO, false);
-        aContext->SetDisplayMode(aAISIO, Shading, false);
-      }
-    }*+/
-
-    // Append the filters from the local selection in the global selection context
-    SelectMgr_ListIteratorOfListOfFilter aIt(aFilters);
-    for (;aIt.More(); aIt.Next()) {
-      Handle(SelectMgr_Filter) aFilter = aIt.Value();
-      aContext->AddFilter(aFilter);
-    }
-
-    if (theUpdateViewer)
-      updateViewer();
-    //myUseExternalObjects = false;
-
-    // Restore selection
-    //AIS_ListIteratorOfListOfInteractive aIt2(aAisList);
-    //for(; aIt2.More(); aIt2.Next()) {
-    //  if (aContext->IsDisplayed(aIt2.Value()))
-    //    aContext->SetCurrentObject(aIt2.Value(), false);
-    //}
-  }
-}*/
 
+//**************************************************************
 AISObjectPtr XGUI_Displayer::getAISObject(ObjectPtr theObject) const
 {
   AISObjectPtr anIO;
@@ -915,12 +578,14 @@ AISObjectPtr XGUI_Displayer::getAISObject(ObjectPtr theObject) const
   return anIO;
 }
 
+//**************************************************************
 ObjectPtr XGUI_Displayer::getObject(const AISObjectPtr& theIO) const
 {
   Handle(AIS_InteractiveObject) aRefAIS = theIO->impl<Handle(AIS_InteractiveObject)>();
   return getObject(aRefAIS);
 }
 
+//**************************************************************
 ObjectPtr XGUI_Displayer::getObject(const Handle(AIS_InteractiveObject)& theIO) const
 {
   ObjectPtr anObject;
@@ -942,6 +607,7 @@ ObjectPtr XGUI_Displayer::getObject(const Handle(AIS_InteractiveObject)& theIO)
   return anObject;
 }
 
+//**************************************************************
 bool XGUI_Displayer::enableUpdateViewer(const bool isEnabled)
 {
   bool aWasEnabled = isUpdateEnabled();
@@ -950,6 +616,10 @@ bool XGUI_Displayer::enableUpdateViewer(const bool isEnabled)
   else
     myViewerBlockedRecursiveCount++;
 
+#ifdef DEBUG_VIEWER_BLOCKED_COUNT
+  std::cout << "myViewerBlockedRecursiveCount = " << myViewerBlockedRecursiveCount << std::endl;
+#endif
+
   if (myNeedUpdate && isUpdateEnabled()) {
     updateViewer();
     myNeedUpdate = false;
@@ -957,14 +627,22 @@ bool XGUI_Displayer::enableUpdateViewer(const bool isEnabled)
   return aWasEnabled;
 }
 
+//**************************************************************
 bool XGUI_Displayer::isUpdateEnabled() const
 {
   return myViewerBlockedRecursiveCount == 0;
 }
 
+//**************************************************************
 void XGUI_Displayer::updateViewer() const
 {
   Handle(AIS_InteractiveContext) aContext = AISContext();
+
+#ifdef DEBUG_VIEWER_BLOCKED_COUNT
+  std::cout << "updateViewer: " << (myViewerBlockedRecursiveCount == 0 ? " done" : " later")
+            << std::endl;
+#endif
+
   if (!aContext.IsNull() && isUpdateEnabled()) {
     //myWorkshop->viewer()->Zfitall();
     aContext->UpdateCurrentViewer();
@@ -973,93 +651,22 @@ void XGUI_Displayer::updateViewer() const
   }
 }
 
-void XGUI_Displayer::activateAIS(const Handle(AIS_InteractiveObject)& theIO,
-                                 const int theMode, const bool theUpdateViewer) const
-{
-  Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
-  if (!theIO.IsNull() && theIO == getTrihedron()) {
-    if (theMode != AIS_Shape::SelectionType(TopAbs_EDGE) &&
-        theMode != AIS_Shape::SelectionType(TopAbs_VERTEX))
-      return;
-  }
-  if (!aContext.IsNull()) {
-    if (myWorkshop->module()) {
-      int aMode = (theMode > 8)? theMode : AIS_Shape::SelectionType(theMode);
-      aContext->Activate(theIO, theMode, false);
-    } else
-      aContext->Activate(theIO, theMode, false);
-    #ifdef TINSPECTOR
-    if (getCallBack()) getCallBack()->Activate(theIO, theMode);
-    #endif
-
-    // the fix from VPA for more suitable selection of sketcher lines
-    if (theIO->Width() > 1) {
-      double aPrecision = theIO->Width() + 2;
-      if (theMode == getSelectionMode(TopAbs_VERTEX))
-        aPrecision = ModuleBase_Preferences::resourceMgr()->doubleValue("Viewer",
-                                                                    "point-selection-sensitivity",
-                                                                        12);
-      else if ((theMode == getSelectionMode(TopAbs_EDGE)) ||
-               (theMode == getSelectionMode(TopAbs_WIRE)))
-        aPrecision = theIO->Width() +
-           ModuleBase_Preferences::resourceMgr()->doubleValue("Viewer",
-                                                              "edge-selection-sensitivity", 2);
-      aContext->SetSelectionSensitivity(theIO, theMode, aPrecision);
-    }
-
-#ifdef DEBUG_ACTIVATE_AIS
-    ObjectPtr anObject = getObject(theIO);
-    anInfo.append(ModuleBase_Tools::objectInfo((*anIt)));
-    qDebug(QString("activateAIS: theMode = %1, object = %2").arg(theMode)
-      .arg(anInfo).toStdString().c_str());
-#endif
-    if (theUpdateViewer)
-      updateViewer();
-  }
-}
-
-void XGUI_Displayer::deactivateAIS(const Handle(AIS_InteractiveObject)& theIO,
-                                   const int theMode) const
-{
-  Handle(AIS_InteractiveContext) aContext = AISContext();
-  if (!aContext.IsNull()) {
-    if (theMode == -1) {
-      aContext->Deactivate(theIO);
-      #ifdef TINSPECTOR
-      if (getCallBack()) getCallBack()->Deactivate(theIO);
-      #endif
-    }
-    else {
-      aContext->Deactivate(theIO, theMode);
-      #ifdef TINSPECTOR
-      if (getCallBack()) getCallBack()->Deactivate(theIO, theMode);
-      #endif
-    }
-
-#ifdef DEBUG_DEACTIVATE_AIS
-    ObjectPtr anObject = getObject(theIO);
-    anInfo.append(ModuleBase_Tools::objectInfo((*anIt)));
-    qDebug(QString("deactivateAIS: theMode = %1, object = %2").arg(theMode)
-      .arg(anInfo).toStdString().c_str());
-#endif
-  }
-}
-
+//**************************************************************
 Handle(AIS_InteractiveContext) XGUI_Displayer::AISContext() const
 {
   Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
   if (!aContext.IsNull() && myIsFirstAISContextUse/*&& !aContext->HasOpenedContext()*/) {
     XGUI_Displayer* aDisplayer = (XGUI_Displayer*)this;
     aDisplayer->myIsFirstAISContextUse = false;
-    //aContext->OpenLocalContext();
-    if (!isTrihedronActive())
-      deactivateTrihedron(true);
+    if (!myWorkshop->selectionActivate()->isTrihedronActive())
+      selectionActivate()->deactivateTrihedron(true);
     aContext->DefaultDrawer()->VIsoAspect()->SetNumber(0);
     aContext->DefaultDrawer()->UIsoAspect()->SetNumber(0);
   }
   return aContext;
 }
 
+//**************************************************************
 Handle(SelectMgr_AndFilter) XGUI_Displayer::GetFilter()
 {
   Handle(AIS_InteractiveContext) aContext = AISContext();
@@ -1070,6 +677,7 @@ Handle(SelectMgr_AndFilter) XGUI_Displayer::GetFilter()
   return myAndFilter;
 }
 
+//**************************************************************
 bool XGUI_Displayer::displayAIS(AISObjectPtr theAIS, const bool toActivateInSelectionModes,
                                 const Standard_Integer theDisplayMode, bool theUpdateViewer)
 {
@@ -1090,21 +698,16 @@ bool XGUI_Displayer::displayAIS(AISObjectPtr theAIS, const bool toActivateInSele
     #ifdef TINSPECTOR
     if (getCallBack()) getCallBack()->Load(anAISIO);
     #endif
-    if (toActivateInSelectionModes) {
-      if (myActiveSelectionModes.size() == 0)
-        activateAIS(anAISIO, 0, theUpdateViewer);
-      else {
-        foreach(int aMode, myActiveSelectionModes) {
-          activateAIS(anAISIO, aMode, theUpdateViewer);
-        }
-      }
-    }
+    if (toActivateInSelectionModes)
+      myWorkshop->selectionActivate()->activateOnDisplay(anAISIO, theUpdateViewer);
+
     if (theUpdateViewer)
       updateViewer();
   }
   return aDisplayed;
 }
 
+//**************************************************************
 bool XGUI_Displayer::eraseAIS(AISObjectPtr theAIS, const bool theUpdateViewer)
 {
   bool aErased = false;
@@ -1124,7 +727,7 @@ bool XGUI_Displayer::eraseAIS(AISObjectPtr theAIS, const bool theUpdateViewer)
   return aErased;
 }
 
-
+//**************************************************************
 void XGUI_Displayer::setDisplayMode(ObjectPtr theObject, DisplayMode theMode, bool theUpdateViewer)
 {
   if (theMode == NoMode)
@@ -1145,6 +748,7 @@ void XGUI_Displayer::setDisplayMode(ObjectPtr theObject, DisplayMode theMode, bo
     updateViewer();
 }
 
+//**************************************************************
 XGUI_Displayer::DisplayMode XGUI_Displayer::displayMode(ObjectPtr theObject) const
 {
   Handle(AIS_InteractiveContext) aContext = AISContext();
@@ -1159,7 +763,8 @@ XGUI_Displayer::DisplayMode XGUI_Displayer::displayMode(ObjectPtr theObject) con
   return (XGUI_Displayer::DisplayMode) aAISIO->DisplayMode();
 }
 
-void XGUI_Displayer::deactivateSelectionFilters()
+//**************************************************************
+void XGUI_Displayer::deactivateSelectionFilters(const bool theAddFilterOnly)
 {
   Handle(AIS_InteractiveContext) aContext = AISContext();
   if (!myAndFilter.IsNull()) {
@@ -1178,6 +783,7 @@ void XGUI_Displayer::deactivateSelectionFilters()
   }
 }
 
+//**************************************************************
 void XGUI_Displayer::addSelectionFilter(const Handle(SelectMgr_Filter)& theFilter)
 {
   Handle(AIS_InteractiveContext) aContext = AISContext();
@@ -1194,6 +800,7 @@ void XGUI_Displayer::addSelectionFilter(const Handle(SelectMgr_Filter)& theFilte
   }
 }
 
+//**************************************************************
 void XGUI_Displayer::removeSelectionFilter(const Handle(SelectMgr_Filter)& theFilter)
 {
   Handle(AIS_InteractiveContext) aContext = AISContext();
@@ -1211,6 +818,7 @@ void XGUI_Displayer::removeSelectionFilter(const Handle(SelectMgr_Filter)& theFi
   }
 }
 
+//**************************************************************
 bool XGUI_Displayer::hasSelectionFilter(const Handle(SelectMgr_Filter)& theFilter)
 {
   bool aFilterFound = false;
@@ -1235,6 +843,7 @@ bool XGUI_Displayer::hasSelectionFilter(const Handle(SelectMgr_Filter)& theFilte
   return aFilterFound;
 }
 
+//**************************************************************
 void XGUI_Displayer::removeFilters()
 {
   Handle(AIS_InteractiveContext) aContext = AISContext();
@@ -1246,6 +855,7 @@ void XGUI_Displayer::removeFilters()
     aCompositeFilter->Clear();
 }
 
+//**************************************************************
 void XGUI_Displayer::showOnly(const QObjectPtrList& theList)
 {
   QObjectPtrList aDispList = myResult2AISObjectMap.keys();
@@ -1260,6 +870,7 @@ void XGUI_Displayer::showOnly(const QObjectPtrList& theList)
   updateViewer();
 }
 
+//**************************************************************
 bool XGUI_Displayer::canBeShaded(ObjectPtr theObject) const
 {
   if (!isVisible(theObject))
@@ -1273,98 +884,7 @@ bool XGUI_Displayer::canBeShaded(ObjectPtr theObject) const
   return ::canBeShaded(anAIS, myWorkshop->module());
 }
 
-bool XGUI_Displayer::activate(const Handle(AIS_InteractiveObject)& theIO,
-                              const QIntList& theModes,
-                              const bool theUpdateViewer) const
-{
-  Handle(AIS_InteractiveContext) aContext = AISContext();
-  if (aContext.IsNull() || theIO.IsNull())
-    return false;
-
-  bool isActivationChanged = false;
-  // deactivate object in all modes, which are not in the list of activation
-  // It seems that after the IO deactivation the selected state of the IO's owners
-  // is modified in OCC(version: 6.8.0) and the selection of the object later is lost.
-  // By this reason, the number of the IO deactivate is decreased and the object is deactivated
-  // only if there is a difference in the current modes and the parameters modes.
-  // If the selection problem happens again, it is possible to write a test scenario and create
-  // a bug. The bug steps are the following:
-  // Create two IO, activate them in 5 modes, select the first IO, deactivate 3 modes for both,
-  // with clicked SHIFT select the second object.
-  // The result is the selection of the first IO is lost.
-  TColStd_ListOfInteger aTColModes;
-  aContext->ActivatedModes(theIO, aTColModes);
-  #ifdef TINSPECTOR
-  if (getCallBack()) getCallBack()->ActivatedModes(theIO, aTColModes);
-  #endif
-  TColStd_ListIteratorOfListOfInteger itr( aTColModes );
-  QIntList aModesActivatedForIO;
-  bool isDeactivated = false;
-  bool aHasValidMode = false;
-  for (; itr.More(); itr.Next() ) {
-    Standard_Integer aMode = itr.Value();
-    aHasValidMode = aHasValidMode || aMode != -1;
-    int aShapeMode = (aMode > 8)? aMode : AIS_Shape::SelectionType(aMode);
-    if (!theModes.contains(aMode)) {
-      deactivateAIS(theIO, aMode);
-      isDeactivated = true;
-    }
-    else {
-      aModesActivatedForIO.append(aMode);
-    }
-  }
-  if (isDeactivated) {
-    // the selection from the previous activation modes should be cleared manually (#26172)
-    //theIO->ClearSelected();
-    //#ifdef TINSPECTOR
-    //if (getCallBack()) getCallBack()->ClearSelected(theIO);
-    //#endif
-#ifndef CLEAR_OUTDATED_SELECTION_BEFORE_REDISPLAY
-    deselectPresentation(theIO, aContext);
-#endif
-    // For performance issues
-    //if (theUpdateViewer)
-    //  updateViewer();
-    isActivationChanged = true;
-  }
-
-  // loading the interactive object allowing the decomposition
-  if (aTColModes.IsEmpty() || !aHasValidMode) {
-    aContext->Load(theIO, -1, true);
-    Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast(theIO);
-    if (!aTrihedron.IsNull()) {
-      // Workaround for Trihedron. It should be loaded using the next Load method to
-      // add this object to myGlobal map of selection manager
-      // it is important to activate trihedron in two selection modes: edges and vertices
-      aContext->SelectionManager()->Load(theIO);
-    }
-
-    #ifdef TINSPECTOR
-    if (getCallBack()) getCallBack()->Load(theIO);
-    #endif
-  }
-
-  // trihedron AIS check should be after the AIS loading.
-  // If it is not loaded, it is steel selectable in the viewer.
-  Handle(AIS_Trihedron) aTrihedron;
-  if (!isTrihedronActive())
-    aTrihedron = Handle(AIS_Trihedron)::DownCast(theIO);
-  if (aTrihedron.IsNull()) {
-      // In order to clear active modes list
-    if (theModes.size() == 0) {
-      activateAIS(theIO, 0, theUpdateViewer);
-    } else {
-      foreach(int aMode, theModes) {
-        if (!aModesActivatedForIO.contains(aMode)) {
-          activateAIS(theIO, aMode, theUpdateViewer);
-          isActivationChanged = true;
-        }
-      }
-    }
-  }
-  return isActivationChanged;
-}
-
+//**************************************************************
 bool XGUI_Displayer::customizeObject(ObjectPtr theObject)
 {
   AISObjectPtr anAISObj = getAISObject(theObject);
@@ -1389,10 +909,15 @@ bool XGUI_Displayer::customizeObject(ObjectPtr theObject)
                       aCustomPrs->customisePresentation(aResult, anAISObj, myCustomPrs);
   isCustomized = myWorkshop->module()->afterCustomisePresentation(aResult, anAISObj, myCustomPrs)
                  || isCustomized;
+
+  // update presentation state if faces panel is active
+  if (anAISObj.get() && myWorkshop->facesPanel())
+    isCustomized = myWorkshop->facesPanel()->customizeObject(theObject, anAISObj) || isCustomized;
+
   return isCustomized;
 }
 
-
+//**************************************************************
 QColor XGUI_Displayer::setObjectColor(ObjectPtr theObject,
                                       const QColor& theColor,
                                       bool theUpdateViewer)
@@ -1409,6 +934,7 @@ QColor XGUI_Displayer::setObjectColor(ObjectPtr theObject,
   return QColor(aR, aG, aB);
 }
 
+//**************************************************************
 void XGUI_Displayer::appendResultObject(ObjectPtr theObject, AISObjectPtr theAIS)
 {
   myResult2AISObjectMap[theObject] = theAIS;
@@ -1422,6 +948,7 @@ void XGUI_Displayer::appendResultObject(ObjectPtr theObject, AISObjectPtr theAIS
 }
 
 #ifdef _DEBUG
+//**************************************************************
 std::string XGUI_Displayer::getResult2AISObjectMapInfo() const
 {
   QStringList aContent;
@@ -1439,6 +966,7 @@ std::string XGUI_Displayer::getResult2AISObjectMapInfo() const
 }
 #endif
 
+//**************************************************************
 void XGUI_Displayer::getPresentations(const ObjectPtr& theObject,
                                   NCollection_Map<Handle(AIS_InteractiveObject)>& thePresentations)
 {
@@ -1483,14 +1011,7 @@ void XGUI_Displayer::getPresentations(const ObjectPtr& theObject,
   }
 }
 
-void XGUI_Displayer::activateTrihedron(bool theIsActive)
-{
-  myIsTrihedronActive = theIsActive;
-  if (!myIsTrihedronActive) {
-    deactivateTrihedron(true);
-  }
-}
-
+//**************************************************************
 void XGUI_Displayer::displayTrihedron(bool theToDisplay) const
 {
   Handle(AIS_InteractiveContext) aContext = AISContext();
@@ -1499,6 +1020,7 @@ void XGUI_Displayer::displayTrihedron(bool theToDisplay) const
 
   Handle(AIS_Trihedron) aTrihedron = myWorkshop->viewer()->trihedron();
 
+  XGUI_SelectionActivate* aSelectionActive = selectionActivate();
   if (theToDisplay) {
     if (!aContext->IsDisplayed(aTrihedron))
       aContext->Display(aTrihedron,
@@ -1511,12 +1033,12 @@ void XGUI_Displayer::displayTrihedron(bool theToDisplay) const
     if (getCallBack()) getCallBack()->Display(aTrihedron);
     #endif
 
-    if (!isTrihedronActive())
-      deactivateTrihedron(false);
+    if (!aSelectionActive->isTrihedronActive())
+      aSelectionActive->deactivateTrihedron(false);
     else
-      activate(aTrihedron, myActiveSelectionModes, false);
+      aSelectionActive->activate(aTrihedron, false);
   } else {
-    deactivateTrihedron(false);
+    aSelectionActive->deactivateTrihedron(false);
 
     aContext->Erase(aTrihedron, Standard_True);
     #ifdef TINSPECTOR
@@ -1527,16 +1049,7 @@ void XGUI_Displayer::displayTrihedron(bool theToDisplay) const
   updateViewer();
 }
 
-QIntList XGUI_Displayer::activeSelectionModes() const
-{
-  QIntList aModes;
-  foreach (int aMode, myActiveSelectionModes) {
-    // aMode < 9 is a Shape Enum values
-    aModes << ((aMode < 9)? AIS_Shape::SelectionType(aMode) : aMode);
-  }
-  return aModes;
-}
-
+//**************************************************************
 void XGUI_Displayer::AddOrRemoveSelectedShapes(Handle(AIS_InteractiveContext) theContext,
                            const NCollection_DataMap<TopoDS_Shape,
                            NCollection_Map<Handle(AIS_InteractiveObject)>>& theShapesToBeSelected)
@@ -1610,3 +1123,9 @@ void XGUI_Displayer::AddOrRemoveSelectedShapes(Handle(AIS_InteractiveContext) th
     theContext->AddOrRemoveSelected(anIt.Value(), Standard_False);
   }
 }
+
+//**************************************************************
+XGUI_SelectionActivate* XGUI_Displayer::selectionActivate() const
+{
+  return myWorkshop->selectionActivate();
+}
index 9b606dab3b55c0877694e1fe5033e150b8df9d77..50b4a79d5cd8f61606ffeed8e0fe42c9a7130c85 100644 (file)
 #include "XGUI.h"
 
 #include <GeomAPI_AISObject.h>
-#include <TopoDS_Shape.hxx>
-#include <AIS_InteractiveObject.hxx>
-#include <AIS_InteractiveContext.hxx>
-#include <NCollection_Map.hxx>
-#include <NCollection_DataMap.hxx>
+#include <GeomAPI_ICustomPrs.h>
 
 #include <ModelAPI_Result.h>
 
 #include <ModuleBase_Definitions.h>
 
-#include <GeomAPI_ICustomPrs.h>
-
+#include <AIS_InteractiveObject.hxx>
+#include <AIS_InteractiveContext.hxx>
+#include <NCollection_Map.hxx>
+#include <NCollection_DataMap.hxx>
 #include <SelectMgr_AndFilter.hxx>
+#include <TopoDS_Shape.hxx>
 
-#include <QString>
+#include <QColor>
 #include <QMap>
 #include <QObject>
-#include <QColor>
+#include <QString>
 
 class ModuleBase_ViewerPrs;
 class ModelAPI_Feature;
+class XGUI_SelectionActivate;
 class XGUI_Workshop;
 
 #ifdef TINSPECTOR
@@ -61,12 +61,9 @@ class XGUI_EXPORT XGUI_Displayer: public QObject
  public:
    /// \enum DisplayMode display mode
    enum DisplayMode {
-     /// Mode is not defined
-     NoMode = -1,
-     /// Wireframe display mode
-     Wireframe,
-     /// Shading display mode
-     Shading
+     NoMode = -1, ///< Mode is not defined
+     Wireframe, ///< Wireframe display mode
+     Shading ///< Shading display mode
    };
 
   /// Constructor
@@ -138,12 +135,9 @@ class XGUI_EXPORT XGUI_Displayer: public QObject
   /// \return true if the object visibility state is changed
   bool eraseAll(const bool theUpdateViewer = true);
 
-  /// Deactivates selection of sub-shapes
-  /// \param theUpdateViewer the parameter whether the viewer should be update immediatelly
-  //void closeLocalContexts(const bool theUpdateViewer = true);
-
   /// Remove default selection filters of the module from the current viewer
-  void deactivateSelectionFilters();
+  /// \param theAddFilterOnly if is not 'true' it will deactivate all fiters in viewer
+  void deactivateSelectionFilters(const bool theAddFilterOnly = true);
 
   /// \brief Add selection filter
   /// \param theFilter a filter instance
@@ -174,19 +168,6 @@ class XGUI_EXPORT XGUI_Displayer: public QObject
   /// Updates the viewer
   void updateViewer() const;
 
-  /// Activate interactive context
-  /// \param theIO an interactive object
-  /// \param theMode activation mode
-  /// \param theUpdateViewer update viewer flag
-  void activateAIS(const Handle(AIS_InteractiveObject)& theIO, const int theMode,
-                   const bool theUpdateViewer) const;
-
-  /// Activate interactive context. It is necessary to call ClearOutdatedSelection
-  /// after deactivation
-  /// \param theIO an interactive object
-  /// \param theMode a mode to deactivate. When theMode=-1 then all modes will be deactivated
-  void deactivateAIS(const Handle(AIS_InteractiveObject)& theIO, const int theMode = -1) const;
-
   /// Searches the interactive object by feature
   /// \param theObject the object or presentable feature
   /// \return theIO an interactive object
@@ -208,22 +189,6 @@ class XGUI_EXPORT XGUI_Displayer: public QObject
   void deactivateObjects(const QObjectPtrList& theObjList,
                          const bool theUpdateViewer = true);
 
-  /// Returns the modes of activation
-  /// \param theObject the feature or NULL if it not visualized
-  /// \param theModes - modes on which it is activated (can be empty)
-  void getModesOfActivation(ObjectPtr theObject, QIntList& theModes);
-
-  /// Returns true if the given object can be selected
-  /// \param theObject object to check
-  bool isActive(ObjectPtr theObject) const;
-
-  /// Activates in local context displayed outside of the context.
-  /// \param theModes - modes on which it has to be activated (can be empty)
-  /// \param theObjList - list of objects which has to be activated.
-  /// \param theUpdateViewer an update viewer flag
-  void activateObjects(const QIntList& theModes, const QObjectPtrList& theObjList,
-                       const bool theUpdateViewer = true);
-
   /// Sets display mode for the given object if this object is displayed
   void setDisplayMode(ObjectPtr theObject, DisplayMode theMode, bool theUpdateViewer = true);
 
@@ -256,31 +221,15 @@ class XGUI_EXPORT XGUI_Displayer: public QObject
   /// \return previously defined color on the object
   QColor setObjectColor(ObjectPtr theObject, const QColor& theColor, bool theUpdateViewer = true);
 
-  /// Returns Trihedron object if it is displayed
-  Handle(AIS_InteractiveObject) getTrihedron() const;
-
-  /// Set trihedron active (used in selection) or non active
-  void activateTrihedron(bool theIsActive);
-
   /// Displays/erases thrihedron in current modes. It will be activated or deactivated
   /// depending on the trihedron visible state and displayer active trihedron state
   void displayTrihedron(bool theToDisplay) const;
 
-  /// Returns true if the trihedron should be activated in current selection modes
-  bool isTrihedronActive() const { return myIsTrihedronActive; }
-
-  /// Returns list of currently active selection modes
-  /// Selection modes will be returned according to TopAbs_ShapeEnum
-  QIntList activeSelectionModes() const;
-
 #ifdef TINSPECTOR
   void setCallBack(const Handle(VInspectorAPI_CallBack)& theCallBack)
     { myVCallBack = theCallBack; }
   Handle(VInspectorAPI_CallBack) getCallBack() const { return myVCallBack; }
 #endif
-  /// Converts shape type (TopAbs_ShapeEnum) to selection mode
-  /// \param theShapeType a shape type from TopAbs_ShapeEnum
-  static int getSelectionMode(int theShapeType);
 
   /// Return true if the object is visible. If the object is feature, it returns true
   /// if all results of the feature are shown
@@ -318,21 +267,6 @@ signals:
                bool theUpdateViewer = true);
 
 private:
-  /// Activates the interactive object in the local context.
-  /// \param theIO an interactive object
-  /// \param theModes - modes on which it has to be activated (can be empty)
-  /// \return a flag is object activated or not
-  bool activate(const Handle(AIS_InteractiveObject)& theIO, const QIntList& theModes,
-                const bool theUpdateViewer) const;
-
-  /// Deactivates the given object (not allow selection)
-  /// \param theObject object to deactivate
-  void deactivate(ObjectPtr theObject, const bool theUpdateViewer);
-
-  /// Find a trihedron in a list of displayed presentations and deactivate it.
-  /// \param theUpdateViewer an update viewer flag
-  void deactivateTrihedron(const bool theUpdateViewer) const;
-
   /// Update the object presentable properties such as color, lines width and other
   /// If the object is result with the color attribute value set, it is used,
   /// otherwise the customize is applyed to the object's feature if it is a custom prs
@@ -366,17 +300,18 @@ private:
   /// owner is selected if it is found there.
   /// Only first owner is processed(according to OCCT logic)
   static void AddOrRemoveSelectedShapes(Handle(AIS_InteractiveContext) theContext,
-          const NCollection_DataMap<TopoDS_Shape,
-                          NCollection_Map<Handle(AIS_InteractiveObject)>>& theShapesToBeSelected);
+    const NCollection_DataMap<TopoDS_Shape,
+      NCollection_Map<Handle(AIS_InteractiveObject)>>& theShapesToBeSelected);
 
- protected:
-   /// Reference to workshop
-  XGUI_Workshop* myWorkshop;
+protected:
+  XGUI_SelectionActivate* selectionActivate() const;
+
+protected:
+  XGUI_Workshop* myWorkshop; ///< Reference to workshop
 #ifdef TINSPECTOR
   Handle(VInspectorAPI_CallBack) myVCallBack;
 #endif
-  /// A container for selection filters
-  Handle(SelectMgr_AndFilter) myAndFilter;
+  Handle(SelectMgr_AndFilter) myAndFilter; ///< A container for selection filters
 
   /// A default custom presentation, which is used if the displayed feature is not
   /// a custom presentation
@@ -384,24 +319,13 @@ private:
 
   /// Definition of a type of map which defines correspondance between objects and presentations
   typedef QMap<ObjectPtr, AISObjectPtr> ResultToAISMap;
+  ResultToAISMap myResult2AISObjectMap; ///< A map of displayed objects
 
-  /// A map of displayed objects
-  ResultToAISMap myResult2AISObjectMap;
-
-  /// Selection modes installed for external objects in local context
-  QIntList myActiveSelectionModes;
-
-  /// Number of blocking of the viewer update. The viewer is updated only if it equals zero
+  /// Number of blocking of the viewer update. The viewer is updated only if it is zero
   int myViewerBlockedRecursiveCount;
 
-  /// Flag: first asking of AIS context: trihedron activation
-  bool myIsFirstAISContextUse;
-
-  /// Flag: use trihedgon for selection or not
-  bool myIsTrihedronActive;
-
-  /// A flag that update was requested but not done
-  mutable bool myNeedUpdate;
+  bool myIsFirstAISContextUse; ///< Flag: first asking of AIS context: trihedron activation
+  mutable bool myNeedUpdate; ///< A flag that update was requested but not done
 };
 
 #endif
diff --git a/src/XGUI/XGUI_FacesPanel.cpp b/src/XGUI/XGUI_FacesPanel.cpp
new file mode 100644 (file)
index 0000000..01211ae
--- /dev/null
@@ -0,0 +1,527 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "XGUI_FacesPanel.h"
+
+#include <Config_PropManager.h>
+#include <Events_Loop.h>
+#include <GeomAlgoAPI_CompoundBuilder.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>
+#include <QGridLayout>
+#include <QListWidget>
+#include <QMainWindow>
+
+static const int LayoutMargin = 3;
+
+//********************************************************************
+XGUI_FacesPanel::XGUI_FacesPanel(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop)
+  : QDockWidget(theParent), myIsActive(false), myWorkshop(theWorkshop)
+{
+  setWindowTitle(tr("Hide Faces"));
+  QAction* aViewAct = toggleViewAction();
+  setStyleSheet("::title { position: relative; padding-left: 5px; text-align: left center }");
+
+  QWidget* aContent = new QWidget(this);
+  QGridLayout* aMainLayout = new QGridLayout(aContent);
+  aMainLayout->setContentsMargins(LayoutMargin, LayoutMargin, LayoutMargin, LayoutMargin);
+  setWidget(aContent);
+
+  myHiddenOrTransparent = new QCheckBox(tr("Transparent"), aContent);
+  connect(myHiddenOrTransparent, SIGNAL(toggled(bool)), SLOT(onTransparencyChanged()));
+
+  myListView = new ModuleBase_ListView(aContent, "", "Hidden/transparent faces in 3D view");
+  connect(myListView, SIGNAL(deleteActionClicked()), SLOT(onDeleteItem()));
+
+  aMainLayout->addWidget(myHiddenOrTransparent, 0, 0);
+  aMainLayout->addWidget(myListView->getControl(), 1, 0);
+
+  myListView->getControl()->setFocusPolicy(Qt::StrongFocus);
+  myListView->getControl()->viewport()->installEventFilter(this);
+}
+
+//********************************************************************
+void XGUI_FacesPanel::reset(const bool isToFlushRedisplay)
+{
+  if (myLastItemIndex == 0) // do nothing because there was no activity in the pane after reset
+    return;
+
+  // clear internal containers
+  myListView->getControl()->clear();
+  myItems.clear();
+
+  // restore previous view of presentations
+  bool isModified = redisplayObjects(myItemObjects);
+  std::set<std::shared_ptr<ModelAPI_Object> > aHiddenObjects = myHiddenObjects;
+  isModified = displayHiddenObjects(aHiddenObjects, myHiddenObjects) || isModified;
+  if (isModified)// && isToFlushRedisplay) // flush signal immediatelly until container is filled
+    flushRedisplay();
+
+  updateProcessedObjects(myItems, myItemObjects);
+  myHiddenObjects.clear();
+  myLastItemIndex = 0; // it should be after redisplay as flag used in customize
+}
+
+//********************************************************************
+bool XGUI_FacesPanel::isEmpty() const
+{
+  return myItems.size() == 0;
+}
+
+//********************************************************************
+void XGUI_FacesPanel::selectionModes(QIntList& theModes)
+{
+  theModes.append(TopAbs_FACE);
+}
+
+//********************************************************************
+void XGUI_FacesPanel::selectionFilters(SelectMgr_ListOfFilter& theSelectionFilters)
+{
+  ModuleBase_IModule* aModule = myWorkshop->module();
+  QIntList aModuleSelectionFilters = myWorkshop->module()->selectionFilters();
+
+  theSelectionFilters.Append(aModule->selectionFilter(SF_GlobalFilter));
+  theSelectionFilters.Append(aModule->selectionFilter(SF_FilterInfinite));
+  theSelectionFilters.Append(aModule->selectionFilter(SF_ResultGroupNameFilter));
+}
+
+//********************************************************************
+bool XGUI_FacesPanel::eventFilter(QObject* theObject, QEvent *theEvent)
+{
+  QWidget* aWidget = qobject_cast<QWidget*>(theObject);
+  if (theEvent->type() == QEvent::MouseButtonRelease)
+  {
+    if (myListView->getControl()->viewport() == aWidget)
+      setActivePanel(true);
+  }
+  // pass the event on to the parent class
+  return QObject::eventFilter(theObject, theEvent);
+}
+
+//********************************************************************
+void XGUI_FacesPanel::setActivePanel(const bool theIsActive)
+{
+  if (myIsActive == theIsActive)
+    return;
+
+  ModuleBase_Tools::setShadowEffect(myListView->getControl(), theIsActive);
+  myIsActive = theIsActive;
+
+  if (myIsActive) {
+    emit activated();
+    // selection should be cleared after emit of signal to do not process selection change
+    // event by the previous selector
+    // the selection is cleared by activating selection control
+    XGUI_Tools::workshop(myWorkshop)->selector()->clearSelection();
+  }
+  else
+    emit deactivated();
+}
+
+//********************************************************************
+bool XGUI_FacesPanel::useTransparency() const
+{
+  return myHiddenOrTransparent->isChecked();
+}
+
+//********************************************************************
+void XGUI_FacesPanel::restoreObjects(const std::set<ObjectPtr>& theHiddenObjects)
+{
+  std::set<int> anIndicesToBeRemoved;
+  for (QMap<int, ModuleBase_ViewerPrsPtr>::const_iterator anItemsIt = myItems.begin();
+    anItemsIt != myItems.end(); anItemsIt++)
+  {
+    ModuleBase_ViewerPrsPtr aPrs = anItemsIt.value();
+    ObjectPtr anObject = aPrs->object();
+    if (theHiddenObjects.find(anObject) == theHiddenObjects.end()) // not found
+      continue;
+    anIndicesToBeRemoved.insert(anItemsIt.key());
+  }
+
+  // remove from myItes container
+  for (std::set<int>::const_iterator aToBeRemovedIt = anIndicesToBeRemoved.begin();
+    aToBeRemovedIt != anIndicesToBeRemoved.end(); aToBeRemovedIt++)
+  {
+    myItems.remove(*aToBeRemovedIt);
+  }
+  if (!anIndicesToBeRemoved.empty()) // means that myItems has been changed
+    updateProcessedObjects(myItems, myItemObjects);
+  myListView->removeItems(anIndicesToBeRemoved);
+
+  // remove from container of hidden objects
+  for (std::set<ObjectPtr>::const_iterator aHiddenIt = theHiddenObjects.begin();
+    aHiddenIt != theHiddenObjects.end(); aHiddenIt++)
+  {
+    if (myHiddenObjects.find(*aHiddenIt) != myHiddenObjects.end()) /// found objects
+      myHiddenObjects.erase(*aHiddenIt);
+  }
+}
+
+//********************************************************************
+bool XGUI_FacesPanel::processAction(ModuleBase_ActionType theActionType)
+{
+  switch (theActionType) {
+    //case ActionEnter:
+    //  return processEnter();
+    case ActionEscape:
+      setActivePanel(false);
+      return true;
+    case ActionDelete:
+      return processDelete();
+    //case ActionUndo:
+    //case ActionRedo:
+    default:
+      return false;
+  }
+}
+
+//********************************************************************
+void XGUI_FacesPanel::processSelection()
+{
+  QList<ModuleBase_ViewerPrsPtr> aSelected = myWorkshop->selection()->getSelected(
+                                                       ModuleBase_ISelection::Viewer);
+  bool isModified = false;
+  static Events_ID aDispEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+
+  std::map<ObjectPtr, NCollection_List<TopoDS_Shape> > anObjectToShapes;
+  std::map<ObjectPtr, Handle(ModuleBase_ResultPrs) > anObjectToPrs;
+  for (int i = 0; i < aSelected.size(); i++) {
+    ModuleBase_ViewerPrsPtr aPrs = aSelected[i];
+    ObjectPtr anObject = aPrs->object();
+    if (!anObject.get())
+      continue;
+    if (ModuleBase_Tools::getSelectedShape(aPrs).ShapeType() != TopAbs_FACE)
+      continue;
+
+    Handle(ModuleBase_ResultPrs) aResultPrs = Handle(ModuleBase_ResultPrs)::DownCast(
+      aPrs->interactive());
+    if (aResultPrs.IsNull())
+      continue;
+
+    myItems.insert(myLastItemIndex, aPrs);
+    myListView->addItem(generateName(aPrs), myLastItemIndex);
+    myLastItemIndex++;
+    isModified = true;
+
+    if (anObjectToShapes.find(anObject) != anObjectToShapes.end())
+      anObjectToShapes.at(anObject).Append(ModuleBase_Tools::getSelectedShape(aPrs));
+    else {
+      NCollection_List<TopoDS_Shape> aListOfShapes;
+      aListOfShapes.Append(ModuleBase_Tools::getSelectedShape(aPrs));
+      anObjectToShapes[anObject] = aListOfShapes;
+      anObjectToPrs[anObject] = aResultPrs;
+    }
+  }
+  for (std::map<ObjectPtr, NCollection_List<TopoDS_Shape> >::const_iterator
+    anIt = anObjectToShapes.begin(); anIt != anObjectToShapes.end(); anIt++) {
+    ObjectPtr anObject = anIt->first;
+    if (!anObject.get() || anObjectToPrs.find(anObject) == anObjectToPrs.end())
+      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
+      anObject->setDisplayed(false);
+      myHiddenObjects.insert(anObject);
+      ModelAPI_EventCreator::get()->sendUpdated(anObject, aDispEvent);
+    }
+  }
+  if (isModified) {
+    updateProcessedObjects(myItems, myItemObjects);
+    flushRedisplay();
+  }
+}
+
+//********************************************************************
+bool XGUI_FacesPanel::processDelete()
+{
+  //appendFirstSelectionInHistory();
+  QModelIndexList anIndices = myListView->getControl()->selectionModel()->selectedIndexes();
+
+  std::set<int> aSelectedIds;
+  myListView->getSelectedIndices(aSelectedIds);
+  if (aSelectedIds.empty())
+    return false;
+
+  bool isModified = false;
+  std::set<ObjectPtr> aRestoredObjects;
+  for (std::set<int>::const_iterator anIt = aSelectedIds.begin(); anIt != aSelectedIds.end();
+       anIt++) {
+    ModuleBase_ViewerPrsPtr aPrs = myItems[*anIt];
+    if (aRestoredObjects.find(aPrs->object()) == aRestoredObjects.end())
+      aRestoredObjects.insert(aPrs->object());
+    myItems.remove(*anIt);
+    isModified = true;
+  }
+  if (isModified) {
+    bool isRedisplayed = redisplayObjects(aRestoredObjects);
+    isRedisplayed = displayHiddenObjects(aRestoredObjects, myHiddenObjects)
+                    || isRedisplayed;
+    if (isRedisplayed)
+      flushRedisplay();
+    // should be after flush of redisplay to have items object to be updated
+    updateProcessedObjects(myItems, myItemObjects);
+  }
+
+  myListView->removeSelectedItems();
+  // Restore selection
+  myListView->restoreSelection(anIndices);
+  //appendSelectionInHistory();
+  return true;
+}
+
+//********************************************************************
+bool XGUI_FacesPanel::redisplayObjects(
+  const std::set<std::shared_ptr<ModelAPI_Object> >& theObjects)
+{
+  if (theObjects.empty())
+    return false;
+
+  bool isModified = false;
+  static Events_ID aDispEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  for (std::set<ObjectPtr>::const_iterator anIt = theObjects.begin(); anIt != theObjects.end();
+       anIt++)
+  {
+    ObjectPtr anObject = *anIt;
+    if (!anObject->isDisplayed())
+      continue;
+    ModelAPI_EventCreator::get()->sendUpdated(anObject, aDispEvent);
+    isModified = true;
+  }
+  return isModified;
+}
+
+//********************************************************************
+bool XGUI_FacesPanel::displayHiddenObjects(
+  const std::set<std::shared_ptr<ModelAPI_Object> >& theObjects,
+  std::set<std::shared_ptr<ModelAPI_Object> >& theHiddenObjects)
+{
+  if (theObjects.empty())
+    return false;
+
+  bool isModified = false;
+  static Events_ID aDispEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+
+  for (std::set<ObjectPtr>::const_iterator anIt = theObjects.begin(); anIt != theObjects.end();
+       anIt++)
+  {
+    ObjectPtr anObject = *anIt;
+    // if the object was hidden by this panel
+    if (anObject->isDisplayed() || theHiddenObjects.find(anObject) == theHiddenObjects.end())
+      continue;
+    theHiddenObjects.erase(anObject);
+    anObject->setDisplayed(true); // it means that the object is hidden by hide all faces
+    ModelAPI_EventCreator::get()->sendUpdated(anObject, aDispEvent);
+    isModified = true;
+  }
+  return isModified;
+}
+
+//********************************************************************
+bool XGUI_FacesPanel::hideEmptyObjects()
+{
+  bool isModified = false;
+  static Events_ID aDispEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  std::map<ObjectPtr, NCollection_List<TopoDS_Shape> > anObjectToShapes;
+  std::map<ObjectPtr, Handle(ModuleBase_ResultPrs) > anObjectToPrs;
+
+  for (QMap<int, ModuleBase_ViewerPrsPtr>::const_iterator anIt = myItems.begin();
+       anIt != myItems.end(); anIt++) {
+    ModuleBase_ViewerPrsPtr aPrs = anIt.value();
+    ObjectPtr anObject = aPrs->object();
+    if (!anObject.get() || !anObject->isDisplayed())
+      continue;
+
+    Handle(ModuleBase_ResultPrs) aResultPrs = Handle(ModuleBase_ResultPrs)::DownCast(
+      aPrs->interactive());
+    if (aResultPrs.IsNull())
+      continue;
+
+    if (anObjectToShapes.find(anObject) != anObjectToShapes.end())
+      anObjectToShapes.at(anObject).Append(ModuleBase_Tools::getSelectedShape(aPrs));
+    else {
+      NCollection_List<TopoDS_Shape> aListOfShapes;
+      aListOfShapes.Append(ModuleBase_Tools::getSelectedShape(aPrs));
+      anObjectToShapes[anObject] = aListOfShapes;
+      anObjectToPrs[anObject] = aResultPrs;
+    }
+  }
+  for (std::map<ObjectPtr, NCollection_List<TopoDS_Shape> >::const_iterator
+    anIt = anObjectToShapes.begin(); anIt != anObjectToShapes.end(); anIt++) {
+    ObjectPtr anObject = anIt->first;
+    if (!anObject.get() || anObjectToPrs.find(anObject) == anObjectToPrs.end())
+      continue;
+    Handle(ModuleBase_ResultPrs) aResultPrs = anObjectToPrs.at(anObject);
+
+    if (!aResultPrs->hasSubShapeVisible(anIt->second)) {
+      // erase object because it is entirely hidden
+      anObject->setDisplayed(false);
+      myHiddenObjects.insert(anObject);
+      ModelAPI_EventCreator::get()->sendUpdated(anObject, aDispEvent);
+      isModified = true;
+    }
+  }
+  return isModified;
+}
+
+//********************************************************************
+void XGUI_FacesPanel::updateProcessedObjects(QMap<int, ModuleBase_ViewerPrsPtr> theItems,
+                                             std::set<ObjectPtr>& theObjects)
+{
+  theObjects.clear();
+  for (QMap<int, ModuleBase_ViewerPrsPtr>::const_iterator anIt = theItems.begin();
+       anIt != theItems.end(); anIt++) {
+    ModuleBase_ViewerPrsPtr aPrs = anIt.value();
+    ObjectPtr anObject = aPrs.get() ? aPrs->object() : ObjectPtr();
+    if (anObject.get() && theObjects.find(anObject) != theObjects.end())
+      continue;
+    theObjects.insert(anObject);
+  }
+}
+
+//********************************************************************
+void XGUI_FacesPanel::closeEvent(QCloseEvent* theEvent)
+{
+  QDockWidget::closeEvent(theEvent);
+  emit closed();
+}
+
+//********************************************************************
+QString XGUI_FacesPanel::generateName(const ModuleBase_ViewerPrsPtr& thePrs)
+{
+  if (!thePrs.get() || !thePrs->object().get())
+    return "Undefined";
+
+  GeomShapePtr aContext;
+  ObjectPtr anObject = thePrs->object();
+  ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
+  if (aResult.get())
+    aContext = aResult->shape();
+  else {
+    // TODO if there is this case
+  }
+
+  QString aName = anObject->data()->name().c_str();
+  if (aContext.get()) {
+    GeomShapePtr aSubShape(new GeomAPI_Shape());
+    aSubShape->setImpl(new TopoDS_Shape(ModuleBase_Tools::getSelectedShape(thePrs)));
+    if (!aSubShape->isEqual(aContext))
+      aName += QString("_%1").arg(GeomAlgoAPI_CompoundBuilder::id(aContext, aSubShape));
+  }
+  return aName;
+}
+
+//********************************************************************
+bool XGUI_FacesPanel::customizeObject(const ObjectPtr& theObject,
+                                      const AISObjectPtr& thePresentation)
+{
+  if (myLastItemIndex == 0) // do nothing because there was no activity in the pane after reset
+    return false;
+
+  if (thePresentation.get() == NULL)
+    return false;
+
+  if (myItemObjects.find(theObject) == myItemObjects.end()) // not found
+    return false;
+
+  // if the object is displayed, the hidden faces are collected and set to the presentation
+  bool isModified = false;
+  NCollection_List<TopoDS_Shape> aHiddenSubShapes;
+  for (QMap<int, ModuleBase_ViewerPrsPtr>::const_iterator anIt = myItems.begin();
+    anIt != myItems.end(); anIt++) {
+    ModuleBase_ViewerPrsPtr aPrs = anIt.value();
+    if (aPrs.get() && aPrs->object() != theObject)
+      continue;
+    TopoDS_Shape aShape = ModuleBase_Tools::getSelectedShape(aPrs);
+    if (!aHiddenSubShapes.Contains(aShape))
+      aHiddenSubShapes.Append(aShape);
+  }
+
+  Handle(ModuleBase_ResultPrs) aResultPrs = Handle(ModuleBase_ResultPrs)::DownCast(
+    thePresentation->impl<Handle(AIS_InteractiveObject)>());
+  if (aResultPrs.IsNull())
+    return false;
+
+  isModified = aResultPrs->setSubShapeHidden(aHiddenSubShapes);
+
+  double aTransparency = !useTransparency() ? 1
+    : Config_PropManager::real("Visualization", "hidden_face_transparency");
+  isModified = aResultPrs->setHiddenSubShapeTransparency(aTransparency) || isModified;
+
+  return isModified;
+}
+
+//********************************************************************
+void XGUI_FacesPanel::onDeleteItem()
+{
+  processDelete();
+}
+
+//********************************************************************
+void XGUI_FacesPanel::onTransparencyChanged()
+{
+  bool isModified = false;
+  if (useTransparency()) {
+    std::set<std::shared_ptr<ModelAPI_Object> > aHiddenObjects = myHiddenObjects;
+    isModified = displayHiddenObjects(aHiddenObjects, myHiddenObjects);
+  }
+  else
+    isModified = hideEmptyObjects();
+
+  isModified = redisplayObjects(myItemObjects) || isModified;
+  if (isModified)
+    flushRedisplay();
+}
+
+//********************************************************************
+void XGUI_FacesPanel::onClosed()
+{
+  setActivePanel(false);
+  reset(true);
+}
+
+//********************************************************************
+void XGUI_FacesPanel::flushRedisplay() const
+{
+  Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY));
+  // Necessary for update visibility icons in ObjectBrowser
+  XGUI_ObjectsBrowser* anObjectBrowser = XGUI_Tools::workshop(myWorkshop)->objectBrowser();
+  if (anObjectBrowser)
+    anObjectBrowser->updateAllIndexes();
+}
diff --git a/src/XGUI/XGUI_FacesPanel.h b/src/XGUI/XGUI_FacesPanel.h
new file mode 100644 (file)
index 0000000..567fa8e
--- /dev/null
@@ -0,0 +1,207 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef XGUI_FacesPanel_H_
+#define XGUI_FacesPanel_H_
+
+#include "XGUI.h"
+
+#include <ModelAPI_Object.h>
+
+#include <ModuleBase_ActionType.h>
+#include <ModuleBase_Definitions.h>
+#include <ModuleBase_ViewerPrs.h>
+
+#include <SelectMgr_ListOfFilter.hxx>
+
+#include <QDockWidget>
+#include <QObject>
+#include <QMap>
+
+#include <set>
+
+class AIS_InteractiveObject;
+
+class GeomAPI_AISObject;
+
+class ModuleBase_IWorkshop;
+class ModuleBase_ListView;
+
+class QAction;
+class QCheckBox;
+class QEvent;
+
+/**
+* \ingroup GUI
+* A Hide Faces panel for making it possible to hide faces in the 3D view.
+* The panel has multi-selector filled by faces elements. When the control is active
+* it is possible to select faces in the viewer. The selected faces are hidden/transparent
+* after selection and the corresponding item is appeared in the multi selector.
+*
+* In order to redisplay a face, it is enough to click delete on the name of this face
+* in the multiselector.
+* When the panel is opened, the multiselector is empty.
+* When the panel is closed, the multiselector is emptied and the faces are displayed again.
+* The default position by of this dockable window is to the right of the view (in SALOME mode).
+* If no feature is processed (in neutral point), this panel can be activated too.
+* On feature edition start or finish, movement of the history line, undo/redo and other
+* modification of the model, the multiselector is emptied.
+*/
+class XGUI_EXPORT XGUI_FacesPanel : public QDockWidget
+{
+  Q_OBJECT
+public:
+  /// Constructor
+  /// \param theParent is a parent of the property panel
+  XGUI_FacesPanel(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop);
+  ~XGUI_FacesPanel() {}
+
+  /// Clear content of list widget
+  /// \param isToFlushRedisplay flag if redisplay should be flushed immediatelly
+  virtual void reset(const bool isToFlushRedisplay);
+
+  /// Returns whether faces panel contains elements
+  /// \return boolean value
+  bool isEmpty() const;
+
+  /// Fills container with the panel selection mode: FACE
+  // \param theModes [out] a container of modes
+  void selectionModes(QIntList& theModes);
+
+  /// Appends into container of workshop selection filters
+  /// \param [out] selection filters
+  void selectionFilters(SelectMgr_ListOfFilter& theSelectionFilters);
+
+  /// Returns whether the panel is active or not
+  bool isActivePanel() const { return myIsActive; }
+
+  /// Stores the state if panel is active and highlight the panel in an active color
+  /// \param theIsActive state whether the panel should be activated or deactivated
+  void setActivePanel(const bool theIsActive);
+
+  /// Returns true if transparency choice is checked
+  /// \return boolean value
+  bool useTransparency() const;
+
+  /// Returns true if the object is in internal container of hidden objects by this panel
+  /// \param theObject a checked object
+  /// \return boolean value
+  bool isObjectHiddenByPanel(const std::shared_ptr<ModelAPI_Object>& theObject) const
+  { return myHiddenObjects.find(theObject) != myHiddenObjects.end(); }
+
+  /// Removed faces of the objects from the panel
+  /// \param container of objects
+  void restoreObjects(const std::set<std::shared_ptr<ModelAPI_Object> >& theHiddenObjects);
+
+  /// Returns true if the event is processed. The default implementation is empty, returns false.
+  virtual bool processAction(ModuleBase_ActionType theActionType);
+
+  /// Append selected item in the list and customize presentations to hide faces
+  void processSelection();
+
+  /// Deletes item in a list of elements
+  /// \return whether the delete action is processed
+  bool processDelete();
+
+  /// Processing focus in/out for the faces control
+  /// \param theObject source object of event
+  /// \param theEvent an event
+  virtual bool eventFilter(QObject* theObject, QEvent *theEvent);
+
+  /// Hide/show faces of the object if:
+  /// - face selector is active
+  /// - object is mentioned in the list of selected elements
+  /// If the object is displayed, all panel faces selected on it will be moved into presentation
+  /// or, if redisplayed, fuction return if the object should be redisplayed or not
+  /// \param theObject a customized object
+  /// \param thePresentation visualized presentation of the object
+  /// \return true if the presentation is customized
+  bool customizeObject(const std::shared_ptr<ModelAPI_Object>& theObject,
+    const std::shared_ptr<GeomAPI_AISObject>& thePresentation);
+
+protected:
+  /// Reimplementation to emit a signal about the panel close
+  virtual void closeEvent(QCloseEvent* theEvent);
+
+signals:
+  /// Signal about activating pane
+  void activated();
+  /// Signal about deactivating pane
+  void deactivated();
+  /// Signal is emitted by the top widget cross button click
+  void closed();
+
+private:
+  /// Redisplay objects.
+  /// \param theObjects container of objects
+  /// \return true if some of objects was redisplayed
+  static bool redisplayObjects(const std::set<std::shared_ptr<ModelAPI_Object> >& theObjects);
+
+  /// Display objects if the objects are in a container of hidden by this pane.
+  /// \param theObjects container of objects
+  /// \param theHiddenObjects hidden objects, if object is in the container, it should be removed
+  /// \return true if some of objects was redisplayed
+  static bool displayHiddenObjects(const std::set<std::shared_ptr<ModelAPI_Object> >& theObjects,
+                                   std::set<std::shared_ptr<ModelAPI_Object> >& theHiddenObjects);
+
+  /// Iterates by items and hide objects where all sub-shapes are hidden
+  /// \return true if some of objects was redisplayed
+  bool hideEmptyObjects();
+
+  /// Container of objects participating in the panel, it is filled by internal container
+  /// \param theItems container of selected values
+  /// \param theObjects [out] container of objects
+  static void updateProcessedObjects(QMap<int, std::shared_ptr<ModuleBase_ViewerPrs> > theItems,
+                                     std::set<std::shared_ptr<ModelAPI_Object> >& theObjects);
+
+  /// Generates a presentation name in form: <object_name>/<face>_<face_index>
+  /// \param thePrs a presentation
+  /// \return string value
+  static QString generateName(const std::shared_ptr<ModuleBase_ViewerPrs>& thePrs);
+
+protected slots:
+  /// Deletes element in list of items
+  void onDeleteItem();
+
+  /// Upates hidden faces to be hidden or transparent
+  void onTransparencyChanged();
+
+  /// Closes faces panel restore all hidden faces by calling reset()
+  void onClosed();
+
+private:
+  /// Flushes redisplay event and perform update of object browser icons
+  /// (objects might be hidden/shown)
+  void flushRedisplay() const;
+
+protected:
+  QCheckBox* myHiddenOrTransparent; ///< if checked - transparent, else hidden
+  ModuleBase_ListView* myListView; ///< list control of processed faces
+  ModuleBase_IWorkshop* myWorkshop; ///< workshop
+
+  bool myIsActive; ///< current state about the panel is active
+  int myLastItemIndex; ///< last index to be used in the map of items for the next added item
+
+  QMap<int, std::shared_ptr<ModuleBase_ViewerPrs> > myItems; ///< selected face items
+  std::set<std::shared_ptr<ModelAPI_Object> > myItemObjects; ///< cached objects of myItems
+  std::set<std::shared_ptr<ModelAPI_Object> > myHiddenObjects; ///< hidden objects
+};
+
+#endif
\ No newline at end of file
diff --git a/src/XGUI/XGUI_FacesPanelSelector.cpp b/src/XGUI/XGUI_FacesPanelSelector.cpp
new file mode 100644 (file)
index 0000000..7d49699
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include <XGUI_FacesPanelSelector.h>
+
+#include <XGUI_FacesPanel.h>
+
+//********************************************************************
+XGUI_FacesPanelSelector::XGUI_FacesPanelSelector(XGUI_FacesPanel* thePanel)
+: myPanel(thePanel)
+{
+  connect(myPanel, SIGNAL(activated()), this, SIGNAL(activated()));
+  connect(myPanel, SIGNAL(deactivated()), this, SIGNAL(deactivated()));
+}
+
+//********************************************************************
+void XGUI_FacesPanelSelector::reset()
+{
+  myPanel->reset(true);
+}
+
+//********************************************************************
+void XGUI_FacesPanelSelector::setActive(const bool& isActive)
+{
+  myPanel->setActivePanel(isActive);
+}
+
+//********************************************************************
+void XGUI_FacesPanelSelector::processSelection()
+{
+  myPanel->processSelection();
+}
diff --git a/src/XGUI/XGUI_FacesPanelSelector.h b/src/XGUI/XGUI_FacesPanelSelector.h
new file mode 100644 (file)
index 0000000..fc16b36
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef XGUI_FacesPanelSelector_H
+#define XGUI_FacesPanelSelector_H
+
+#include "XGUI.h"
+
+#include <XGUI_ActiveControlSelector.h>
+
+class XGUI_FacesPanel;
+
+/**
+* Processing selection by the faces panel.
+*/
+class XGUI_FacesPanelSelector : public XGUI_ActiveControlSelector
+{
+  Q_OBJECT
+
+public:
+  /// Constructor
+  /// \param thePanel the workshop faces panel
+  XGUI_EXPORT XGUI_FacesPanelSelector(XGUI_FacesPanel* thePanel);
+  /// Destructor
+  XGUI_EXPORT virtual ~XGUI_FacesPanelSelector() {};
+
+  /// Returns name of the selector
+  XGUI_EXPORT static QString Type() { return "XGUI_FacesPanelSelector"; }
+
+  /// Returns name of the selector
+  XGUI_EXPORT virtual QString getType() { return Type(); }
+
+  /// Set empty widget that need to be activated widget if it is not empty
+  XGUI_EXPORT virtual void reset();
+
+  /// Sets control active. It should activates/deactivates selection and selection filters.
+  /// \param isActive if true, the control becomes active
+  XGUI_EXPORT virtual void setActive(const bool& isActive);
+
+  /// Processes current selection of workshop. Reaction to selection change in workshop.
+  XGUI_EXPORT virtual void processSelection();
+
+protected:
+  XGUI_FacesPanel* myPanel; ///< processed panel
+};
+
+#endif
index b832fbb3071833f34b1eb610a7dcef366587b1c3..34b7d462c7c6c6a1a84d929c7873d2b386ae8cac 100644 (file)
@@ -21,8 +21,9 @@
 #include "XGUI_ModuleConnector.h"
 #include "XGUI_Workshop.h"
 #include "XGUI_ViewerProxy.h"
-#include "XGUI_SelectionMgr.h"
 #include "XGUI_Selection.h"
+#include "XGUI_SelectionActivate.h"
+#include "XGUI_SelectionMgr.h"
 #include "XGUI_OperationMgr.h"
 #include "XGUI_Displayer.h"
 #include "XGUI_PropertyPanel.h"
@@ -78,6 +79,11 @@ ModuleBase_IErrorMgr* XGUI_ModuleConnector::errorMgr() const
   return myWorkshop->errorMgr();
 }
 
+ModuleBase_ISelectionActivate* XGUI_ModuleConnector::selectionActivate() const
+{
+  return myWorkshop->selectionActivate();
+}
+
 ModuleBase_Operation* XGUI_ModuleConnector::currentOperation() const
 {
   return myWorkshop->operationMgr()->currentOperation();
@@ -96,27 +102,6 @@ QObjectPtrList XGUI_ModuleConnector::activeObjects(const QObjectPtrList& theObjL
   return aActiveOPbjects;
 }
 
-void XGUI_ModuleConnector::activateSubShapesSelection(const QIntList& theTypes)
-{
-  QIntList aTypes = theTypes;
-
-  XGUI_Displayer* aDisp = myWorkshop->displayer();
-  myWorkshop->module()->customSubShapesSelectionModes(aTypes);
-  aDisp->activateObjects(aTypes, activeObjects(aDisp->displayedObjects()));
-}
-
-void XGUI_ModuleConnector::deactivateSubShapesSelection()
-{
-  // Clear selection modes
-  activateModuleSelectionModes();
-}
-
-void XGUI_ModuleConnector::activateModuleSelectionModes()
-{
-  XGUI_Displayer* aDisp = myWorkshop->displayer();
-  myWorkshop->activateObjectsSelection(activeObjects(aDisp->displayedObjects()));
-}
-
 AISObjectPtr XGUI_ModuleConnector::findPresentation(const ObjectPtr& theObject) const
 {
   XGUI_Displayer* aDisp = myWorkshop->displayer();
index 06536228efd826ec8b0abb1e7cee7310c6260328..6bf3914c29d3656eee583281953927fe99e97c4f 100644 (file)
@@ -45,16 +45,6 @@ Q_OBJECT
   //! Returns list of currently selected data objects
   virtual ModuleBase_ISelection* selection() const;
 
-  /// Activate sub-shapes selection (opens local context if it was not opened)
-  /// Types has to be dined according to TopAbs_ShapeEnum
-  virtual void activateSubShapesSelection(const QIntList& theTypes);
-
-  /// Activate objects in the module selection modes(opens local context)
-  virtual void activateModuleSelectionModes();
-
-  /// Deactivate sub-shapes selection (closes local context)
-  virtual void deactivateSubShapesSelection();
-
   //! Returns instance of loaded module
   virtual ModuleBase_IModule* module() const;
 
@@ -67,6 +57,9 @@ Q_OBJECT
   //! Returns error manager
   virtual ModuleBase_IErrorMgr* errorMgr() const;
 
+  /// A selection activate in 3D View handler
+  virtual ModuleBase_ISelectionActivate* selectionActivate() const;
+
   //! Returns currently active operation
   virtual ModuleBase_Operation* currentOperation() const;
 
index eda25f837032b3830713a6fb4b4ef37f9c6a4657..f3f53962692511480fff8747ed96435ad7370815 100644 (file)
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Document.h>
+#include <ModelAPI_ResultCompSolid.h>
 #include <ModelAPI_Tools.h>
 
 #include <ModuleBase_Tools.h>
 
+#include <XGUI_Workshop.h>
+
 #include <QLayout>
 #include <QLineEdit>
 #include <QPixmap>
@@ -233,14 +236,23 @@ void XGUI_DataTree::processEyeClick(const QModelIndex& theIndex)
   ObjectPtr aObj = aModel->object(theIndex);
   if (aObj.get()) {
     ResultPtr aResObj = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
+    XGUI_ObjectsBrowser* aObjBrowser = qobject_cast<XGUI_ObjectsBrowser*>(parent());
     if (aResObj.get()) {
-      aResObj->setDisplayed(!aResObj->isDisplayed());
+      std::set<ObjectPtr> anObjects;
+      anObjects.insert(aResObj);
+
+      bool hasHiddenState = aModel->hasHiddenState(theIndex);
+      if (aObjBrowser && hasHiddenState && !aObjBrowser->workshop()->prepareForDisplay(anObjects))
+        return;
+      if (hasHiddenState) // #issue 2335(hide all faces then show solid problem)
+        aResObj->setDisplayed(true);
+      else
+        aResObj->setDisplayed(!aResObj->isDisplayed());
       Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
       update(theIndex);
     }
     // Update list of selected objects because this event happens after
     // selection event in object browser
-    XGUI_ObjectsBrowser* aObjBrowser = qobject_cast<XGUI_ObjectsBrowser*>(parent());
     if (aObjBrowser) {
       aObjBrowser->onSelectionChanged();
     }
@@ -614,3 +626,15 @@ void XGUI_ObjectsBrowser::setStateForDoc(DocumentPtr theDoc, const std::list<boo
     myTreeView->setExpanded(aIdx, (*aIt));
   }
 }
+
+void XGUI_ObjectsBrowser::updateAllIndexes(int theColumn, const QModelIndex& theParent)
+{
+  int aNb = myDocModel->rowCount(theParent);
+  for (int i = 0; i < aNb; i++) {
+    QModelIndex aIdx = myDocModel->index(i, theColumn, theParent);
+    if (aIdx.isValid()) {
+      myTreeView->update(aIdx);
+      updateAllIndexes(theColumn, aIdx);
+    }
+  }
+}
index fd522c61a8dd253aaafc940fec2aadac2b942018..372d4bb76402395ec1a7a286abace45cf66a999a 100644 (file)
@@ -206,6 +206,10 @@ Q_OBJECT
 
   void onSelectionChanged();
 
+  /// Updates all items of object browser
+  /// \param theColumn - column of items
+  /// \param theParent - a parent item (by default from root)
+  void updateAllIndexes(int theColumn = 0, const QModelIndex& theParent = QModelIndex());
 
 public slots:
   //! Called on Edit command request
index 50f690425b92de3e73a40b4e3ce721691c1bb6cb..6d77ef8a3a3b0e78904dc0744538d25e7b66471d 100644 (file)
 //
 
 #include "XGUI_OperationMgr.h"
+
+#include "XGUI_ActiveControlMgr.h"
+#include "XGUI_ActiveControlSelector.h"
+#include "XGUI_FacesPanelSelector.h"
 #include "XGUI_ModuleConnector.h"
 #include "XGUI_Workshop.h"
 #include "XGUI_ErrorMgr.h"
+#include "XGUI_FacesPanel.h"
 #include "XGUI_Tools.h"
 #include "XGUI_ObjectsBrowser.h"
 #include "XGUI_ContextMenuMgr.h"
@@ -711,6 +716,13 @@ bool XGUI_OperationMgr::onKeyPressed(QObject *theObject, QKeyEvent* theEvent)
         if (anActiveWgt)
           isAccepted = anActiveWgt && anActiveWgt->processAction(ActionEscape);
       }
+      if (!isAccepted)
+      {
+        XGUI_ActiveControlSelector* anActiveSelector =
+          XGUI_Tools::workshop(myWorkshop)->activeControlMgr()->activeSelector();
+        if (anActiveSelector && anActiveSelector->getType() == XGUI_FacesPanelSelector::Type())
+          isAccepted = XGUI_Tools::workshop(myWorkshop)->facesPanel()->processAction(ActionEscape);
+      }
       // default Escape button functionality
       if (!isAccepted && aOperation) {
         onAbortOperation();
@@ -730,6 +742,8 @@ bool XGUI_OperationMgr::onProcessEnter(QObject* theObject)
   if (!aOperation)
     return isAccepted;
   ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
+  if (!aPanel)
+    return isAccepted;
   // the next code is obsolete as we want to process Enter in property panel always
   // only property panel enter is processed in order to do not process enter in application dialogs
   //bool isPPChild = isChildObject(theObject, aPanel);
@@ -801,6 +815,13 @@ bool XGUI_OperationMgr::onProcessDelete(QObject* theObject)
       }
     }
   }
+  if (!isAccepted)
+  {
+    XGUI_ActiveControlSelector* anActiveSelector =
+      XGUI_Tools::workshop(myWorkshop)->activeControlMgr()->activeSelector();
+    if (anActiveSelector && anActiveSelector->getType() == XGUI_FacesPanelSelector::Type())
+      isAccepted = XGUI_Tools::workshop(myWorkshop)->facesPanel()->processAction(ActionDelete);
+  }
   if (!isAccepted) {
     // after widget, object browser and viewer should process delete
     /// other widgets such as line edit controls should not lead to
index a2e2f0ed0d3176d4a8632d3acfa4c54e9e901e16..07ed810a3c7aff83f03aac3237b07c2f9ec10f34 100755 (executable)
@@ -53,8 +53,8 @@ public:
   /// Enumeration of kind of message that is used when trying to stop the active operation
   enum XGUI_MessageKind
   {
-    XGUI_AbortOperationMessage, //< warns and give possibility to abort current operation
-    XGUI_InformationMessage //< ask to apply the current operation before performing something
+    XGUI_AbortOperationMessage, ///< warns and give possibility to abort current operation
+    XGUI_InformationMessage ///< ask to apply the current operation before performing something
   };
 
 public:
index e8735b7307c8fb3498673eb4cc2a4fbc714cc3e0..5d287669ffb6cf4794a1ff28c6ad5fcd7a3e0197 100755 (executable)
 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
 //
 
-#include <XGUI_PropertyPanel.h>
 #include <XGUI_ActionsMgr.h>
+#include <XGUI_ActiveControlMgr.h>
+#include <XGUI_SelectionActivate.h>
+#include <XGUI_ActiveControlSelector.h>
+#include <XGUI_PropertyPanel.h>
+#include <XGUI_PropertyPanelSelector.h>
 #include <XGUI_OperationMgr.h>
+#include <XGUI_Tools.h>
+#include <XGUI_Workshop.h>
+
 //#include <AppElements_Constants.h>
 #include <ModuleBase_WidgetMultiSelector.h>
 #include <ModuleBase_Tools.h>
@@ -124,6 +131,10 @@ void XGUI_PropertyPanel::cleanContent()
   if (myActiveWidget)
     myActiveWidget->deactivate();
 
+  XGUI_ActiveControlSelector* aPPSelector = XGUI_Tools::workshop(myOperationMgr->workshop())->
+    activeControlMgr()->getSelector(XGUI_PropertyPanelSelector::Type());
+  aPPSelector->reset(); // it removes need to be updated widget link
+
   /// as the widgets are deleted later, it is important that the signals
   /// of these widgets are not processed. An example of the error is issue 986.
   /// In the given case, the property panel is firstly filled by new widgets
@@ -142,6 +153,9 @@ void XGUI_PropertyPanel::cleanContent()
   myWidgets.clear();
   myPanelPage->clearPage();
   myActiveWidget = NULL;
+  emit propertyPanelDeactivated();
+  myOperationMgr->workshop()->selectionActivate()->updateSelectionModes();
+  myOperationMgr->workshop()->selectionActivate()->updateSelectionFilters();
 #ifdef DEBUG_ACTIVE_WIDGET
   std::cout << "myActiveWidget = NULL" << std::endl;
 #endif
@@ -425,7 +439,7 @@ bool XGUI_PropertyPanel::focusNextPrevChild(bool theIsNext)
       bool isFirstControl = !theIsNext;
       QWidget* aLastFocusControl = myActiveWidget->getControlAcceptingFocus(isFirstControl);
       if (aFocusWidget == aLastFocusControl) {
-        setActiveWidget(NULL);
+        setActiveWidget(NULL, false);
       }
     }
 
@@ -453,39 +467,61 @@ void XGUI_PropertyPanel::activateWidget(ModuleBase_ModelWidget* theWidget, const
     aPreviosAttributeID = myActiveWidget->attributeID();
 
   // Avoid activation of already actve widget. It could happen on focusIn event many times
-  if (setActiveWidget(theWidget) && theEmitSignal) {
-    emit widgetActivated(myActiveWidget);
-    if (!myActiveWidget && !isEditingMode()) {
-      emit noMoreWidgets(aPreviosAttributeID);
-    }
-  }
+  setActiveWidget(theWidget, theEmitSignal);
 }
 
-bool XGUI_PropertyPanel::setActiveWidget(ModuleBase_ModelWidget* theWidget)
+bool XGUI_PropertyPanel::setActiveWidget(ModuleBase_ModelWidget* theWidget, const bool isEmitSignal)
 {
   // Avoid activation of already actve widget. It could happen on focusIn event many times
   if (theWidget == myActiveWidget) {
     return false;
   }
   std::string aPreviosAttributeID;
+  ModuleBase_ModelWidget* aDeactivatedWidget = NULL, *anActivatedWidget = NULL;
   if(myActiveWidget) {
     aPreviosAttributeID = myActiveWidget->attributeID();
     myActiveWidget->processValueState();
     myActiveWidget->deactivate();
     myActiveWidget->setHighlighted(false);
+    aDeactivatedWidget = myActiveWidget;
   }
   if(theWidget) {
     emit beforeWidgetActivated(theWidget);
     theWidget->setHighlighted(true);
     theWidget->activate();
+    anActivatedWidget = theWidget;
   }
   myActiveWidget = theWidget;
+
 #ifdef DEBUG_ACTIVE_WIDGET
   std::cout << "myActiveWidget = " << (theWidget ? theWidget->context().c_str() : "") << std::endl;
 #endif
-  static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION);
-  Events_Loop::loop()->flush(anEvent);
-
+  bool aHasMoreWidgets = true;
+  if (isEmitSignal) {
+    //emit widgetActivated(myActiveWidget);
+    if (!myActiveWidget && !isEditingMode()) {
+      aHasMoreWidgets = false;
+      emit noMoreWidgets(aPreviosAttributeID);
+    }
+  }
+  if (myActiveWidget)
+    emit propertyPanelActivated();
+  else
+    emit propertyPanelDeactivated();
+  myOperationMgr->workshop()->selectionActivate()->updateSelectionModes();
+  myOperationMgr->workshop()->selectionActivate()->updateSelectionFilters();
+
+  if (aHasMoreWidgets && aDeactivatedWidget)
+    aDeactivatedWidget->updateAfterDeactivation();
+  if (aHasMoreWidgets && anActivatedWidget)
+    anActivatedWidget->updateAfterActivation();
+
+  if (aHasMoreWidgets && myActiveWidget)
+  {
+    // restore widget selection should be done after selection modes of widget activating
+    static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION);
+    Events_Loop::loop()->flush(anEvent);
+  }
   return true;
 }
 
index 7f1f0b325a467e0f75199e1862fc14394b6babf8..5b1a68b88c16daf6e677081aa03da9cd2c557acc 100644 (file)
@@ -146,7 +146,6 @@ public slots:
   /**
   * Makes the given widget active, highlights it and removes
   * highlighting from the previous active widget
-  * emits widgetActivated(theWidget) signal
   * \param theWidget which has to be activated
   * \param theEmitSignal a flag to prohibit signal emit
   */
@@ -166,10 +165,16 @@ signals:
   /// \param theObject a sender of the event
   void enterClicked(QObject* theObject);
 
+  /// Emits on deactivating property panel (e.g. by clearContent)
+  void propertyPanelDeactivated();
+  /// Emits on widget activating
+  void propertyPanelActivated();
+
 protected:
   /// Makes the widget active, deactivate the previous, activate and hightlight the given one
   /// \param theWidget a widget
-  bool setActiveWidget(ModuleBase_ModelWidget* theWidget);
+  /// \param isEmitSignal flag whether panel signals should be emitted
+  bool setActiveWidget(ModuleBase_ModelWidget* theWidget, const bool isEmitSignal);
   /// The parent method that processes the "Tab"/"SHIF + Tab" keyboard events
   /// Emits a signal about focus change
   /// If theIsNext is true, this function searches forward, if next is false, it searches backward.
diff --git a/src/XGUI/XGUI_PropertyPanelSelector.cpp b/src/XGUI/XGUI_PropertyPanelSelector.cpp
new file mode 100644 (file)
index 0000000..30fc0f9
--- /dev/null
@@ -0,0 +1,72 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include <XGUI_PropertyPanelSelector.h>
+#include <XGUI_PropertyPanel.h>
+
+//********************************************************************
+XGUI_PropertyPanelSelector::XGUI_PropertyPanelSelector(XGUI_PropertyPanel* thePanel)
+: myPanel(thePanel), myWidgetToBeActivated (NULL)
+{
+  connect(myPanel, SIGNAL(propertyPanelActivated()), this, SIGNAL(activated()));
+  connect(myPanel, SIGNAL(propertyPanelDeactivated()), this, SIGNAL(deactivated()));
+}
+
+//********************************************************************
+void XGUI_PropertyPanelSelector::reset()
+{
+  myWidgetToBeActivated = NULL;
+}
+
+//********************************************************************
+void XGUI_PropertyPanelSelector::setActive(const bool& isActive)
+{
+  if (isActive && myWidgetToBeActivated) {
+    // e.g. widget sketch label
+    myPanel->activateWidget(myWidgetToBeActivated, true);
+    myWidgetToBeActivated = NULL;
+    return;
+  }
+
+  if (!isActive) { // on deactivating, store previous active widget
+    ModuleBase_ModelWidget* aWidget = myPanel->activeWidget();
+    if (aWidget && aWidget->needToBeActiated())
+    {
+      myWidgetToBeActivated = aWidget;
+    }
+    myPanel->activateWidget(NULL, false);
+  }
+}
+
+//********************************************************************
+bool XGUI_PropertyPanelSelector::needToBeActiated() const
+{
+  return myWidgetToBeActivated != NULL;
+}
+
+//********************************************************************
+void XGUI_PropertyPanelSelector::processSelection()
+{
+  ModuleBase_ModelWidget* aWidget = myPanel->activeWidget();
+  if (!aWidget)
+    return;
+
+  aWidget->processAction(ActionSelection);
+}
diff --git a/src/XGUI/XGUI_PropertyPanelSelector.h b/src/XGUI/XGUI_PropertyPanelSelector.h
new file mode 100644 (file)
index 0000000..37b5e27
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef XGUI_PropertyPanelSelector_H
+#define XGUI_PropertyPanelSelector_H
+
+#include "XGUI.h"
+
+#include <XGUI_ActiveControlSelector.h>
+
+class ModuleBase_ModelWidget;
+class XGUI_PropertyPanel;
+
+/**
+* Processing selection by the property panel.
+*/
+class XGUI_PropertyPanelSelector : public XGUI_ActiveControlSelector
+{
+  Q_OBJECT
+
+public:
+  /// Constructor
+  /// \param thePanel the workshop property panel
+  XGUI_EXPORT XGUI_PropertyPanelSelector(XGUI_PropertyPanel* thePanel);
+  /// Destructor
+  XGUI_EXPORT virtual ~XGUI_PropertyPanelSelector() {};
+
+  /// Returns name of the selector
+  XGUI_EXPORT static QString Type() { return "XGUI_PropertyPanelSelector"; }
+
+  /// Returns name of the selector
+  XGUI_EXPORT virtual QString getType() { return Type(); }
+
+  /// Clear need to be activated widget if it exists
+  XGUI_EXPORT virtual void reset();
+
+  /// Sets control active. It should activates/deactivates selection and selection filters.
+  /// \param isActive if true, the control becomes active
+  XGUI_EXPORT virtual void setActive(const bool& isActive);
+
+  /// Returns whether the selector should be activated as soon as possible (by deactivatate other)
+  /// \return boolean result
+  XGUI_EXPORT virtual bool needToBeActiated() const;
+
+  /// Processes current selection of workshop. Reaction to selection change in workshop.
+  XGUI_EXPORT virtual void processSelection();
+
+protected:
+  XGUI_PropertyPanel* myPanel; ///< processed panel
+  ModuleBase_ModelWidget* myWidgetToBeActivated; ///< used as need to be activated back
+
+};
+
+#endif
index 42df80d1259551f8ab64000032e23e7260ba86f5..2c19972df35c8f35748590a260dcbd041cad4db7 100644 (file)
@@ -34,7 +34,7 @@ class ModuleBase_IViewer;
 
 /**
  * \ingroup GUI
- * An interface which provides a connection of XGUI functionality 
+ * An interface which provides a connection of XGUI functionality
  * with functionality of SALOME module interface.
  */
 class XGUI_EXPORT XGUI_SalomeConnector
index a6edd15f9aed56966fc4f9362564e066477b817c..ed54a60a27ab034ff8100903077474cb28b4320a 100644 (file)
@@ -24,8 +24,9 @@
 #include "XGUI_ViewerProxy.h"
 #include "XGUI_ObjectsBrowser.h"
 
+#include "ModuleBase_BRepOwner.h"
 #include "ModuleBase_ResultPrs.h"
-#include <ModuleBase_ViewerPrs.h>
+#include "ModuleBase_ViewerPrs.h"
 
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Tools.h>
@@ -308,11 +309,6 @@ QObjectPtrList XGUI_Selection::selectedObjects() const
   return QObjectPtrList();
 }
 
-void XGUI_Selection::setSelectedObjects( const QObjectPtrList& theObjects ) const
-{
-  return myWorkshop->objectBrowser()->setObjectsSelected( theObjects );
-}
-
 QObjectPtrList XGUI_Selection::selectedPresentations() const
 {
   QObjectPtrList aSelectedList;
@@ -335,18 +331,6 @@ QModelIndexList XGUI_Selection::selectedIndexes() const
   return myWorkshop->objectBrowser()->selectedIndexes();
 }
 
-//**************************************************************
-void XGUI_Selection::selectedAISObjects(AIS_ListOfInteractive& theList) const
-{
-  theList.Clear();
-
-  Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
-  if (!aContext.IsNull()) {
-    for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected())
-      theList.Append(aContext->SelectedInteractive());
-  }
-}
-
 //**************************************************************
 ObjectPtr XGUI_Selection::getSelectableObject(const Handle(SelectMgr_EntityOwner)& theOwner) const
 {
index 9ff42e6d8cebf6755445d9a43f7e0a031f71e28b..5717d3580712ca023d7327073521a17268865c45 100644 (file)
@@ -37,10 +37,8 @@ class XGUI_Workshop;
 class SelectMgr_EntityOwner;
 class ModuleBase_ViewerPrs;
 
-/**
-* \ingroup GUI
-* Implementation of \ref ModuleBase_ISelection interface.
-*/
+/// \ingroup GUI
+/// Implementation of \ref ModuleBase_ISelection interface.
 class XGUI_EXPORT XGUI_Selection : public ModuleBase_ISelection
 {
  public:
@@ -63,53 +61,42 @@ class XGUI_EXPORT XGUI_Selection : public ModuleBase_ISelection
   /// \return list of presentations
   virtual QList<std::shared_ptr<ModuleBase_ViewerPrs>> getHighlighted() const;
 
-  /**
-   * Returns list of currently selected objects in object browser
-   */
+  /// Returns list of currently selected objects in object browser
   virtual QObjectPtrList selectedObjects() const;
 
-  virtual void setSelectedObjects( const QObjectPtrList& ) const;
-
-  /**
-   * Returns list of currently selected results
-   */
+  /// Returns list of currently selected results
   virtual QObjectPtrList selectedPresentations() const;
 
-  //! Returns list of currently selected QModelIndexes
+  /// Returns list of currently selected QModelIndexes
   virtual QModelIndexList selectedIndexes() const;
 
-  //! Returns list of currently selected QModelIndexes
-  ObjectPtr getSelectableObject(const Handle(SelectMgr_EntityOwner)& theOwner);
-
-  //! Returns list of currently selected AIS objects
-  virtual void selectedAISObjects(AIS_ListOfInteractive& theList) const;
-
-  //! Return a selectable object by the entity owner. It founds AIS object in the viewer
-  //! and returns the corresponded object
-  /// \param theOwner an entity owner
-  /// \return a found object or NULL
-  ObjectPtr getSelectableObject(const Handle(SelectMgr_EntityOwner)& theOwner) const;
-
-  //! Returns list of currently selected owners
+  /// Returns list of currently selected owners
   /// \return list of owners
   void selectedOwners(SelectMgr_IndexedMapOfOwner& theSelectedOwners) const;
 
-  //! Returns a list of selection entity owners of the interactive object
+  /// Returns a list of selection entity owners of the interactive object
   /// It depends on the modes, in which the object is activated in the context
   /// \param theObject an object
   /// \param theOwners a map of entity owners
   void entityOwners(const Handle_AIS_InteractiveObject& theObject,
                     SelectMgr_IndexedMapOfOwner& theOwners) const;
 
-  //! Return the IO from the viewer presentation.
-  //! \param thePrs a selected object
-  //! \return an interactive object
+  /// Return the IO from the viewer presentation.
+  /// \param thePrs a selected object
+  /// \return an interactive object
   virtual Handle(AIS_InteractiveObject) getIO(const std::shared_ptr<ModuleBase_ViewerPrs>& thePrs);
 
 protected:
+  /// Return a selectable object by the entity owner. It founds AIS object in the viewer
+  /// and returns the corresponded object
+  /// \param theOwner an entity owner
+  /// \return a found object or NULL
+  ObjectPtr getSelectableObject(const Handle(SelectMgr_EntityOwner)& theOwner) const;
+
   /// Fills the list of presentations by objects selected in the viewer.
   /// \param thePresentations an output list of presentation
   void getSelectedInViewer(QList<std::shared_ptr<ModuleBase_ViewerPrs>>& thePresentations) const;
+
   /// Fills the list of presentations by objects selected in the object browser.
   /// ViewerPrs contains only object parameter not empty.
   /// If the given list of presentations already has a viewer presentation with the same object
@@ -125,7 +112,7 @@ protected:
 #endif
 
 private:
-  XGUI_Workshop* myWorkshop;
+  XGUI_Workshop* myWorkshop; ///< current workshop
 };
 
 #endif
diff --git a/src/XGUI/XGUI_SelectionActivate.cpp b/src/XGUI/XGUI_SelectionActivate.cpp
new file mode 100644 (file)
index 0000000..f8a1aaa
--- /dev/null
@@ -0,0 +1,581 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "XGUI_SelectionActivate.h"
+
+#include "ModelAPI_Object.h"
+
+#include "ModuleBase_IModule.h"
+#include "ModuleBase_IViewer.h"
+#include "ModuleBase_ModelWidget.h"
+#include "ModuleBase_Preferences.h"
+
+#include "XGUI_ActiveControlMgr.h"
+#include "XGUI_ActiveControlSelector.h"
+#include "XGUI_Displayer.h"
+#include "XGUI_FacesPanel.h"
+#include "XGUI_FacesPanelSelector.h"
+#include "XGUI_SelectionMgr.h"
+#include "XGUI_Tools.h"
+#include "XGUI_Workshop.h"
+
+#include <SUIT_ResourceMgr.h>
+
+#include <AIS_InteractiveContext.hxx>
+#include <AIS_Shape.hxx>
+#include <AIS_Trihedron.hxx>
+
+#include <SelectMgr_SelectionManager.hxx>
+
+//#define DEBUG_ACTIVATE_OBJECTS
+//#define DEBUG_DEACTIVATE
+//#define DEBUG_ACTIVATE_AIS
+//#define DEBUG_DEACTIVATE_AIS
+
+#define CLEAR_OUTDATED_SELECTION_BEFORE_REDISPLAY
+
+//**************************************************************
+XGUI_SelectionActivate::XGUI_SelectionActivate(ModuleBase_IWorkshop* theWorkshop)
+ : ModuleBase_ISelectionActivate(theWorkshop), myIsTrihedronActive(true)
+{
+}
+
+//**************************************************************
+XGUI_SelectionActivate::SelectionPlace XGUI_SelectionActivate::activeSelectionPlace() const
+{
+  XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
+  XGUI_ActiveControlSelector* anActiveSelector = aWorkshop->activeControlMgr()->activeSelector();
+  if (!anActiveSelector)
+    return Workshop;
+
+  if (anActiveSelector->getType() == XGUI_FacesPanelSelector::Type())
+    return FacesPanel;
+  else
+    return PropertyPanel;
+}
+
+//**************************************************************
+void XGUI_SelectionActivate::updateSelectionModes()
+{
+  QIntList aModes;
+  switch (activeSelectionPlace()) {
+  case Workshop:
+    myWorkshop->module()->activeSelectionModes(aModes);
+    break;
+    case PropertyPanel: {
+      ModuleBase_ModelWidget* anActiveWidget = myWorkshop->module()->activeWidget();
+      if (anActiveWidget)
+        getSelectionModes(anActiveWidget, aModes);
+      else
+        myWorkshop->module()->activeSelectionModes(aModes); //using module modes
+    }
+    break;
+    case FacesPanel: {
+      XGUI_Tools::workshop(myWorkshop)->facesPanel()->selectionModes(aModes);
+      myWorkshop->module()->moduleSelectionModes(-1/*all modes*/, aModes);
+    }
+    break;
+    default: break;
+  }
+  activateObjects(aModes, getDisplayer()->displayedObjects(), true);
+}
+
+//**************************************************************
+void XGUI_SelectionActivate::updateSelectionFilters()
+{
+  SelectMgr_ListOfFilter aSelectionFilters;
+  switch (activeSelectionPlace()) {
+    case Workshop: {
+      QIntList aModuleSelectionFilters = myWorkshop->module()->selectionFilters();
+      myWorkshop->module()->moduleSelectionFilters(aModuleSelectionFilters, aSelectionFilters);
+    }
+    break;
+    case PropertyPanel: {
+      QIntList aModuleSelectionFilters = myWorkshop->module()->selectionFilters();
+
+      ModuleBase_ModelWidget* anActiveWidget = myWorkshop->module()->activeWidget();
+      if (anActiveWidget)
+        anActiveWidget->selectionFilters(aModuleSelectionFilters, aSelectionFilters);
+      myWorkshop->module()->moduleSelectionFilters(aModuleSelectionFilters, aSelectionFilters);
+    }
+    break;
+    case FacesPanel: {
+      XGUI_Tools::workshop(myWorkshop)->facesPanel()->selectionFilters(aSelectionFilters);
+      //QIntList aModuleSelectionFilters = myWorkshop->module()->selectionFilters();
+      //myWorkshop->module()->moduleSelectionFilters(aModuleSelectionFilters, aSelectionFilters);
+    }
+    break;
+    default: break;
+  }
+  activateSelectionFilters(aSelectionFilters);
+}
+
+//**************************************************************
+void XGUI_SelectionActivate::activateSelectionFilters
+  (const SelectMgr_ListOfFilter& theSelectionFilters)
+{
+  XGUI_Displayer* aDisplayer = getDisplayer();
+  aDisplayer->deactivateSelectionFilters(false);
+
+  SelectMgr_ListIteratorOfListOfFilter aIt(theSelectionFilters);
+  for (; aIt.More(); aIt.Next()) {
+    Handle(SelectMgr_Filter) aFilter = aIt.Value();
+    if (aFilter.IsNull())
+      continue;
+    aDisplayer->addSelectionFilter(aFilter);
+  }
+}
+
+//**************************************************************
+void XGUI_SelectionActivate::getSelectionModes(ModuleBase_ModelWidget* theWidget,
+                                               QIntList& theModes)
+{
+  if (!theWidget)
+    return;
+
+  int aModuleSelectionModes = -1;
+  theWidget->selectionModes(aModuleSelectionModes, theModes);
+  myWorkshop->module()->moduleSelectionModes(aModuleSelectionModes, theModes);
+}
+
+//**************************************************************
+QIntList XGUI_SelectionActivate::activeSelectionModes() const
+{
+  QIntList aModes;
+  foreach (int aMode, myActiveSelectionModes) {
+    // aMode < 9 is a Shape Enum values
+    aModes << ((aMode < 9)? AIS_Shape::SelectionType(aMode) : aMode);
+  }
+  return aModes;
+}
+
+//**************************************************************
+bool XGUI_SelectionActivate::isActive(ObjectPtr theObject) const
+{
+  Handle(AIS_InteractiveContext) aContext = AISContext();
+  if (aContext.IsNull() || !getDisplayer()->isVisible(theObject))
+    return false;
+
+  AISObjectPtr anObj = getDisplayedAISObject(theObject);
+  Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
+
+  TColStd_ListOfInteger aModes;
+  aContext->ActivatedModes(anAIS, aModes);
+
+  return aModes.Extent() > 0;
+}
+
+//**************************************************************
+void XGUI_SelectionActivate::activateObjects(const QIntList& theModes,
+  const QObjectPtrList& theObjList, const bool theUpdateViewer)
+{
+  setSelectionModes(theModes);
+
+  Handle(AIS_InteractiveContext) aContext = AISContext();
+  // Open local context if there is no one
+  if (aContext.IsNull())
+    return;
+
+  //aContext->UseDisplayedObjects();
+  //myUseExternalObjects = true;
+
+  Handle(AIS_InteractiveObject) anAISIO;
+  AIS_ListOfInteractive aPrsList;
+  AIS_ListOfInteractive aPrsListToBeDeactivated;
+  //if (aObjList.isEmpty())
+  //  return;
+  //else {
+  foreach(ObjectPtr anObject, theObjList) {
+    AISObjectPtr anAISObject = getDisplayedAISObject(anObject);
+    if (!anAISObject.get())
+      continue;
+
+    Handle(AIS_InteractiveObject) aPrs = anAISObject->impl<Handle(AIS_InteractiveObject)>();
+    if (myWorkshop->module()->canActivateSelection(anObject))
+      aPrsList.Append(aPrs);
+    else
+      aPrsListToBeDeactivated.Append(aPrs);
+  }
+  //}
+
+  // Add trihedron because it has to partisipate in selection
+  Handle(AIS_InteractiveObject) aTrihedron;
+  if (isTrihedronActive()) {
+    aTrihedron = getTrihedron();
+    if (!aTrihedron.IsNull() && aContext->IsDisplayed(aTrihedron))
+      aPrsList.Append(aTrihedron);
+  }
+  if (aPrsList.Extent() == 0 && aPrsListToBeDeactivated.Extent() == 0)
+    return;
+
+  AIS_ListIteratorOfListOfInteractive aLIt;
+  bool isActivationChanged = false;
+  for(aLIt.Initialize(aPrsList); aLIt.More(); aLIt.Next()) {
+    anAISIO = aLIt.Value();
+    if (activate(anAISIO, false))
+      isActivationChanged = true;
+  }
+
+  for(aLIt.Initialize(aPrsListToBeDeactivated); aLIt.More(); aLIt.Next()) {
+    anAISIO = aLIt.Value();
+    deactivateAIS(anAISIO);
+    isActivationChanged = true;
+  }
+}
+
+#ifdef DEBUG_ACTIVATE_OBJECTS
+//**************************************************************
+QString getModeInfo(const int theMode)
+{
+  QString anInfo = "Undefined";
+  switch(theMode) {
+    case 0: anInfo = "SHAPE(0)"; break;
+    case 1: anInfo = "VERTEX(1)"; break;
+    case 2: anInfo = "EDGE(2)"; break;
+    case 3: anInfo = "WIRE(3)"; break;
+    case 4: anInfo = "FACE(4)"; break;
+    case 5: anInfo = "SHELL(5)"; break;
+    case 6: anInfo = "SOLID(6)"; break;
+    case 7: anInfo = "COMPSOLID(7)"; break;
+    case 8: anInfo = "COMPOUND(8)"; break;
+    case 100: anInfo = "Sel_Mode_First(100)"; break; //SketcherPrs_Tools
+    case 101: anInfo = "Sel_Constraint(101)"; break;
+    case 102: anInfo = "Sel_Dimension_All(102)"; break;
+    case 103: anInfo = "Sel_Dimension_Line(103)"; break;
+    case 104: anInfo = "Sel_Dimension_Text(104)"; break;
+    default: break;
+  }
+  return anInfo;
+}
+
+//**************************************************************
+QString getModesInfo(const QIntList& theModes)
+{
+  QStringList aModesInfo;
+  for (int i = 0, aSize = theModes.size(); i < aSize; i++)
+    aModesInfo.append(getModeInfo(theModes[i]));
+  return QString("[%1] = %2").arg(aModesInfo.size()).arg(aModesInfo.join(", "));
+}
+#endif
+
+//**************************************************************
+void XGUI_SelectionActivate::setSelectionModes(const QIntList& theModes)
+{
+  // Convert shape types to selection types
+  QIntList aModes;
+  foreach(int aType, theModes) {
+    aModes.append(getSelectionMode(aType));
+  }
+
+#ifdef DEBUG_ACTIVATE_OBJECTS
+  QStringList anInfo;
+  QObjectPtrList::const_iterator anIt = theObjList.begin(), aLast = theObjList.end();
+  for (; anIt != aLast; ++anIt) {
+    anInfo.append(ModuleBase_Tools::objectInfo((*anIt)));
+  }
+  QString anInfoStr = anInfo.join(", ");
+
+  qDebug(QString("activateObjects: new modes%1, active modes%2, objects[%3] = %4").
+    arg(getModesInfo(aModes)).
+    arg(getModesInfo(myActiveSelectionModes)).
+    arg(theObjList.size()).
+    arg(anInfoStr).
+    toStdString().c_str());
+#endif
+  // In order to avoid doblications of selection modes
+  QIntList aNewModes;
+  foreach (int aMode, aModes) {
+    if (!aNewModes.contains(aMode))
+      aNewModes.append(aMode);
+  }
+  myActiveSelectionModes = aNewModes;
+}
+
+//**************************************************************
+void XGUI_SelectionActivate::activateOnDisplay(const Handle(AIS_InteractiveObject)& theIO,
+                                               const bool theUpdateViewer)
+{
+  if (myActiveSelectionModes.size() == 0)
+    activateAIS(theIO, 0, theUpdateViewer);
+  else {
+    foreach(int aMode, myActiveSelectionModes) {
+      activateAIS(theIO, aMode, theUpdateViewer);
+    }
+  }
+}
+
+//**************************************************************
+void XGUI_SelectionActivate::activateAIS(const Handle(AIS_InteractiveObject)& theIO,
+                                         const int theMode, const bool theUpdateViewer) const
+{
+  Handle(AIS_InteractiveContext) aContext = AISContext();
+  if (!theIO.IsNull() && theIO == getTrihedron()) {
+    if (theMode != AIS_Shape::SelectionType(TopAbs_EDGE) &&
+        theMode != AIS_Shape::SelectionType(TopAbs_VERTEX))
+      return;
+  }
+  if (!aContext.IsNull()) {
+    if (myWorkshop->module()) {
+      int aMode = (theMode > 8)? theMode : AIS_Shape::SelectionType(theMode);
+      aContext->Activate(theIO, theMode, false);
+    } else
+      aContext->Activate(theIO, theMode, false);
+
+    // the fix from VPA for more suitable selection of sketcher lines
+    if (theIO->Width() > 1) {
+      double aPrecision = theIO->Width() + 2;
+      if (theMode == getSelectionMode(TopAbs_VERTEX))
+        aPrecision = ModuleBase_Preferences::resourceMgr()->doubleValue("Viewer",
+        "point-selection-sensitivity", 12);
+      else if ((theMode == getSelectionMode(TopAbs_EDGE)) ||
+               (theMode == getSelectionMode(TopAbs_WIRE)))
+        aPrecision = theIO->Width() + ModuleBase_Preferences::resourceMgr()->doubleValue("Viewer",
+           "edge-selection-sensitivity", 2);
+      aContext->SetSelectionSensitivity(theIO, theMode, aPrecision);
+    }
+
+#ifdef DEBUG_ACTIVATE_AIS
+    ObjectPtr anObject = getObject(theIO);
+    anInfo.append(ModuleBase_Tools::objectInfo((*anIt)));
+    qDebug(QString("activateAIS: theMode = %1, object = %2").arg(theMode)
+      .arg(anInfo).toStdString().c_str());
+#endif
+    if (theUpdateViewer)
+      getDisplayer()->updateViewer();
+  }
+}
+
+//**************************************************************
+void XGUI_SelectionActivate::deactivateAIS(const Handle(AIS_InteractiveObject)& theIO,
+                                           const int theMode) const
+{
+  Handle(AIS_InteractiveContext) aContext = AISContext();
+  if (!aContext.IsNull()) {
+    if (theMode == -1)
+      aContext->Deactivate(theIO);
+    else
+      aContext->Deactivate(theIO, theMode);
+
+#ifdef DEBUG_DEACTIVATE_AIS
+    ObjectPtr anObject = getObject(theIO);
+    anInfo.append(ModuleBase_Tools::objectInfo((*anIt)));
+    qDebug(QString("deactivateAIS: theMode = %1, object = %2").arg(theMode)
+      .arg(anInfo).toStdString().c_str());
+#endif
+  }
+}
+
+//**************************************************************
+bool XGUI_SelectionActivate::activate(const Handle(AIS_InteractiveObject)& theIO,
+                                      const bool theUpdateViewer) const
+{
+  Handle(AIS_InteractiveContext) aContext = AISContext();
+  if (aContext.IsNull() || theIO.IsNull())
+    return false;
+
+  bool isActivationChanged = false;
+  // deactivate object in all modes, which are not in the list of activation
+  // It seems that after the IO deactivation the selected state of the IO's owners
+  // is modified in OCC(version: 6.8.0) and the selection of the object later is lost.
+  // By this reason, the number of the IO deactivate is decreased and the object is deactivated
+  // only if there is a difference in the current modes and the parameters modes.
+  // If the selection problem happens again, it is possible to write a test scenario and create
+  // a bug. The bug steps are the following:
+  // Create two IO, activate them in 5 modes, select the first IO, deactivate 3 modes for both,
+  // with clicked SHIFT select the second object.
+  // The result is the selection of the first IO is lost.
+  TColStd_ListOfInteger aTColModes;
+  aContext->ActivatedModes(theIO, aTColModes);
+  TColStd_ListIteratorOfListOfInteger itr( aTColModes );
+  QIntList aModesActivatedForIO;
+  bool isDeactivated = false;
+  bool aHasValidMode = false;
+  for (; itr.More(); itr.Next() ) {
+    Standard_Integer aMode = itr.Value();
+    aHasValidMode = aHasValidMode || aMode != -1;
+    int aShapeMode = (aMode > 8)? aMode : AIS_Shape::SelectionType(aMode);
+    if (!myActiveSelectionModes.contains(aMode)) {
+      deactivateAIS(theIO, aMode);
+      isDeactivated = true;
+    }
+    else {
+      aModesActivatedForIO.append(aMode);
+    }
+  }
+  if (isDeactivated) {
+    // the selection from the previous activation modes should be cleared manually (#26172)
+    //theIO->ClearSelected();
+#ifndef CLEAR_OUTDATED_SELECTION_BEFORE_REDISPLAY
+    XGUI_Tools::workshop(myWorkshop)->selector()->deselectPresentation(theIO);
+#endif
+    // For performance issues
+    //if (theUpdateViewer)
+    //  getDisplayer()->updateViewer();
+    isActivationChanged = true;
+  }
+
+  // loading the interactive object allowing the decomposition
+  if (aTColModes.IsEmpty() || !aHasValidMode) {
+    aContext->Load(theIO, -1, true);
+    Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast(theIO);
+    if (!aTrihedron.IsNull()) {
+      // Workaround for Trihedron. It should be loaded using the next Load method to
+      // add this object to myGlobal map of selection manager
+      // it is important to activate trihedron in two selection modes: edges and vertices
+      aContext->SelectionManager()->Load(theIO);
+    }
+  }
+
+  // trihedron AIS check should be after the AIS loading.
+  // If it is not loaded, it is steel selectable in the viewer.
+  Handle(AIS_Trihedron) aTrihedron;
+  if (!isTrihedronActive())
+    aTrihedron = Handle(AIS_Trihedron)::DownCast(theIO);
+  if (aTrihedron.IsNull()) {
+      // In order to clear active modes list
+    if (myActiveSelectionModes.size() == 0) {
+      activateAIS(theIO, 0, theUpdateViewer);
+    } else {
+      foreach(int aMode, myActiveSelectionModes) {
+        if (!aModesActivatedForIO.contains(aMode)) {
+          activateAIS(theIO, aMode, theUpdateViewer);
+          isActivationChanged = true;
+        }
+      }
+    }
+  }
+  return isActivationChanged;
+}
+
+//**************************************************************
+void XGUI_SelectionActivate::deactivate(const ObjectPtr& theObject, const bool theUpdateViewer)
+{
+#ifdef DEBUG_DEACTIVATE
+  QString anInfoStr = ModuleBase_Tools::objectInfo(theObject);
+  qDebug(QString("deactivate: myActiveSelectionModes[%1]: %2, objects = ").
+    arg(myActiveSelectionModes.size()).arg(qIntListInfo(myActiveSelectionModes)).
+    arg(anInfoStr).
+    toStdString().c_str());
+#endif
+  Handle(AIS_InteractiveContext) aContext = AISContext();
+  if (!aContext.IsNull() && getDisplayer()->isVisible(theObject)) {
+    AISObjectPtr anObj = getDisplayedAISObject(theObject);
+    Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
+
+    deactivateAIS(anAIS);
+    // the selection from the previous activation modes should be cleared manually (#26172)
+#ifndef CLEAR_OUTDATED_SELECTION_BEFORE_REDISPLAY
+    XGUI_Tools::workshop(myWorkshop)->selector()->deselectPresentation(anAIS);
+#endif
+    if (theUpdateViewer)
+      getDisplayer()->updateViewer();
+  }
+}
+
+/// #1136 hidden axis are selected in sketch
+#ifdef BEFORE_TRIHEDRON_PATCH
+//**************************************************************
+void deactivateObject(Handle(AIS_InteractiveContext) theContext,
+                      Handle(AIS_InteractiveObject) theObject)
+{
+  if (!theObject.IsNull())
+    theContext->Deactivate(theObject);
+}
+#endif
+
+//**************************************************************
+void XGUI_SelectionActivate::activateTrihedron(bool theIsActive)
+{
+  myIsTrihedronActive = theIsActive;
+  if (!myIsTrihedronActive)
+    deactivateTrihedron(true);
+}
+
+//**************************************************************
+void XGUI_SelectionActivate::deactivateTrihedron(const bool theUpdateViewer) const
+{
+  Handle(AIS_InteractiveObject) aTrihedron = getTrihedron();
+  Handle(AIS_InteractiveContext) aContext = AISContext();
+  if (!aTrihedron.IsNull() && aContext->IsDisplayed(aTrihedron)) {
+    Handle(AIS_Trihedron) aTrie = Handle(AIS_Trihedron)::DownCast(aTrihedron);
+    if (!aTrie.IsNull())
+      aContext->Deactivate(aTrie);
+
+    /// #1136 hidden axis are selected in sketch
+#ifdef BEFORE_TRIHEDRON_PATCH
+    deactivateObject(aContext, aTrie->XAxis());
+    deactivateObject(aContext, aTrie->YAxis());
+    deactivateObject(aContext, aTrie->Axis());
+    deactivateObject(aContext, aTrie->Position());
+
+    deactivateObject(aContext, aTrie->XYPlane());
+    deactivateObject(aContext, aTrie->XZPlane());
+    deactivateObject(aContext, aTrie->YZPlane());
+#endif
+    if (theUpdateViewer)
+      getDisplayer()->updateViewer();
+  }
+}
+
+//**************************************************************
+void XGUI_SelectionActivate::deactivateTrihedronInSelectionModes()
+{
+  Handle(AIS_InteractiveContext) aContext = AISContext();
+  Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast(getTrihedron());
+  /// deactivate trihedron in selection modes
+  TColStd_ListOfInteger aTColModes;
+  aContext->ActivatedModes(aTrihedron, aTColModes);
+  TColStd_ListIteratorOfListOfInteger itr( aTColModes );
+  for (; itr.More(); itr.Next() ) {
+    Standard_Integer aMode = itr.Value();
+    aContext->Deactivate(aTrihedron, aMode);
+  }
+}
+
+//**************************************************************
+Handle(AIS_InteractiveContext) XGUI_SelectionActivate::AISContext() const
+{
+  return myWorkshop->viewer()->AISContext();
+}
+
+//**************************************************************
+XGUI_Displayer* XGUI_SelectionActivate::getDisplayer() const
+{
+  return XGUI_Tools::workshop(myWorkshop)->displayer();
+}
+
+//**************************************************************
+Handle(AIS_InteractiveObject) XGUI_SelectionActivate::getTrihedron() const
+{
+  return myWorkshop->viewer()->trihedron();
+}
+
+//**************************************************************
+AISObjectPtr XGUI_SelectionActivate::getDisplayedAISObject(ObjectPtr theObject) const
+{
+  return getDisplayer()->getAISObject(theObject);
+}
+
+//**************************************************************
+int XGUI_SelectionActivate::getSelectionMode(int theShapeType)
+{
+  return (theShapeType > TopAbs_SHAPE) ? theShapeType :
+                                         AIS_Shape::SelectionMode((TopAbs_ShapeEnum)theShapeType);
+}
diff --git a/src/XGUI/XGUI_SelectionActivate.h b/src/XGUI/XGUI_SelectionActivate.h
new file mode 100644 (file)
index 0000000..93f65e4
--- /dev/null
@@ -0,0 +1,166 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef XGUI_ISelectionActivate_H
+#define XGUI_ISelectionActivate_H
+
+#include "XGUI.h"
+
+#include "ModuleBase_Definitions.h"
+#include "ModuleBase_ISelectionActivate.h"
+
+#include "SelectMgr_ListOfFilter.hxx"
+
+#include <memory>
+
+class AIS_InteractiveContext;
+class AIS_InteractiveObject;
+class ModelAPI_Object;
+
+class XGUI_Displayer;
+
+/// \ingroup GUI
+/// A class which implements activation/deactivate selection modes and using selection filters.
+class XGUI_SelectionActivate : public ModuleBase_ISelectionActivate
+{
+public:
+  /// Types of the activation place
+  enum SelectionPlace { Workshop, PropertyPanel, FacesPanel };
+
+public:
+  /// Constructor
+  XGUI_EXPORT XGUI_SelectionActivate(ModuleBase_IWorkshop* theWorkshop);
+
+  /// Destructor
+  ~XGUI_SelectionActivate() {}
+
+  /// Returns place of activation modes that now is active
+  /// \return place
+  SelectionPlace activeSelectionPlace() const;
+
+  /// Updates active selection modes in the viewer depending on the application state
+  XGUI_EXPORT virtual void updateSelectionModes();
+
+  /// Updates active selection filters in the viewer depending on the application state
+  XGUI_EXPORT virtual void updateSelectionFilters();
+
+  /// Activates parameter filters in the workshop, deactivate active out of the container
+  /// Please find a possibility to use updateSelectionFilters instead of direct call this method.
+  /// \param theSelectionFilters a filtes
+  XGUI_EXPORT virtual void activateSelectionFilters
+    (const SelectMgr_ListOfFilter& theSelectionFilters);
+
+  /// Returns list of currently active selection modes
+  /// Selection modes will be returned according to TopAbs_ShapeEnum
+  XGUI_EXPORT QIntList activeSelectionModes() const;
+
+  /// Returns true if the given object can be selected
+  /// \param theObject object to check
+  XGUI_EXPORT bool isActive(ObjectPtr theObject) const;
+
+  /// Activates in local context displayed outside of the context.
+  /// \param theModes - modes on which it has to be activated (can be empty)
+  /// \param theObjList - list of objects which has to be activated.
+  /// \param theUpdateViewer an update viewer flag
+  XGUI_EXPORT void activateObjects(const QIntList& theModes, const QObjectPtrList& theObjList,
+                                   const bool theUpdateViewer = true);
+
+  /// Fill container of current selection modes
+  /// \param theModes selection modes
+  XGUI_EXPORT void setSelectionModes(const QIntList& theModes);
+
+  /// Activate object in the selection modes
+  /// \param theIO an object
+  /// \param theUpdateViewer an update viewer flag
+  XGUI_EXPORT void activateOnDisplay(const Handle(AIS_InteractiveObject)& theIO,
+                                     const bool theUpdateViewer);
+
+  /// Activate interactive object
+  /// \param theIO an interactive object
+  /// \param theMode activation mode
+  /// \param theUpdateViewer update viewer flag
+  XGUI_EXPORT void activateAIS(const Handle(AIS_InteractiveObject)& theIO, const int theMode,
+                               const bool theUpdateViewer) const;
+
+  /// Activate interactive object. It is necessary to call ClearOutdatedSelection
+  /// after deactivation
+  /// \param theIO an interactive object
+  /// \param theMode a mode to deactivate. When theMode=-1 then all modes will be deactivated
+  XGUI_EXPORT void deactivateAIS(const Handle(AIS_InteractiveObject)& theIO,
+                                 const int theMode = -1) const;
+
+  /// Activates the interactive object in the local context.
+  /// \param theIO an interactive object
+  /// \param theUpdateViewer the parameter whether the viewer should be update immediatelly
+  /// \return a flag is object activated or not
+  XGUI_EXPORT bool activate(const Handle(AIS_InteractiveObject)& theIO,
+                            const bool theUpdateViewer) const;
+
+  /// Deactivates the given object (not allow selection)
+  /// \param theObject object to deactivate
+  /// \param theUpdateViewer the parameter whether the viewer should be update immediatelly
+  XGUI_EXPORT void deactivate(const std::shared_ptr<ModelAPI_Object>& theObject,
+                              const bool theUpdateViewer);
+
+  /// Returns true if the trihedron should be activated in current selection modes
+  bool isTrihedronActive() const { return myIsTrihedronActive; }
+
+  /// Set trihedron active (used in selection) or non active
+  XGUI_EXPORT void activateTrihedron(bool theIsActive);
+
+  /// Find a trihedron in a list of displayed presentations and deactivate it.
+  /// \param theUpdateViewer the parameter whether the viewer should be update immediatelly
+  XGUI_EXPORT void deactivateTrihedron(const bool theUpdateViewer) const;
+
+  /// Get selection modes of trihedron and deactivate it in it.
+  XGUI_EXPORT void deactivateTrihedronInSelectionModes();
+
+protected:
+  /// Returns selection modes of the widget
+  /// \param theWidget model widget
+  /// \param theModes selection modes
+  void getSelectionModes(ModuleBase_ModelWidget* theWidget, QIntList& theModes);
+
+  /// Returns Trihedron object if it is displayed
+  Handle(AIS_InteractiveObject) getTrihedron() const;
+
+  /// Returns context of the 3D viewer
+  /// \return context instance
+  Handle(AIS_InteractiveContext) AISContext() const;
+
+  /// Returns displayer
+  /// \return displayer
+  XGUI_Displayer* getDisplayer() const;
+
+  /// Returns AIS object displayed in 3D viewer for the given model object
+  /// \param theObject source object
+  /// \returns interactive object
+  AISObjectPtr getDisplayedAISObject(std::shared_ptr<ModelAPI_Object> theObject) const;
+
+  /// Converts shape type (TopAbs_ShapeEnum) to selection mode
+  /// \param theShapeType a shape type from TopAbs_ShapeEnum
+  static int getSelectionMode(int theShapeType);
+
+protected:
+  QIntList myActiveSelectionModes; ///< Current activated selection modes
+  bool myIsTrihedronActive; ///< Flag: use trihedgon for selection or not
+};
+
+#endif
diff --git a/src/XGUI/XGUI_SelectionFilterType.h b/src/XGUI/XGUI_SelectionFilterType.h
new file mode 100644 (file)
index 0000000..17a7ad6
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef 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 eebb23d221e1983816e69be758bfcede126ac176..bece087dc5f4266476d175da5814030859875d1f 100755 (executable)
@@ -150,6 +150,28 @@ void XGUI_SelectionMgr::onViewerSelection()
   emit selectionChanged();
 }
 
+//**************************************************************
+void XGUI_SelectionMgr::deselectPresentation(const Handle(AIS_InteractiveObject) theObject)
+{
+  NCollection_List<Handle(SelectBasics_EntityOwner)> aResultOwners;
+
+  Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
+  for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected()) {
+    Handle(SelectMgr_EntityOwner) anOwner = aContext->SelectedOwner();
+    if (anOwner.IsNull()) // TODO: check why it is possible
+      continue;
+    if (anOwner->Selectable() == theObject && anOwner->IsSelected())
+      aResultOwners.Append(anOwner);
+  }
+  NCollection_List<Handle(SelectBasics_EntityOwner)>::Iterator anOwnersIt (aResultOwners);
+  Handle(SelectMgr_EntityOwner) anOwner;
+  for (; anOwnersIt.More(); anOwnersIt.Next()) {
+    anOwner = Handle(SelectMgr_EntityOwner)::DownCast(anOwnersIt.Value());
+    if (!anOwner.IsNull())
+      aContext->AddOrRemoveSelected(anOwner, false);
+  }
+}
+
 //**************************************************************
 void XGUI_SelectionMgr::updateSelectionBy(const ModuleBase_ISelection::SelectionPlace& thePlace)
 {
@@ -220,3 +242,23 @@ void XGUI_SelectionMgr::convertToObjectBrowserSelection(
     }
   }
 }
+
+std::list<FeaturePtr> XGUI_SelectionMgr::getSelectedFeatures()
+{
+  std::list<FeaturePtr> aFeatures;
+  QObjectPtrList aObjects = selection()->selectedObjects();
+  if (aObjects.isEmpty())
+    return aFeatures;
+
+  bool isPart = false;
+  foreach(ObjectPtr aObj, aObjects) {
+    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
+    if (aFeature.get()) {
+      ResultPtr aRes = aFeature->firstResult();
+      isPart = (aRes.get() && (aRes->groupName() == ModelAPI_ResultPart::group()));
+      if (!isPart)
+        aFeatures.push_back(aFeature);
+    }
+  }
+  return aFeatures;
+}
\ No newline at end of file
index 25bb95d85b774d0452595435a47041cdc1f8bf53..da5d1cb9b602b9477c032d6d2175659f85da5e50 100644 (file)
 #include "XGUI.h"
 #include <ModuleBase_Definitions.h>
 #include <ModuleBase_ISelection.h>
+#include <ModelAPI_Feature.h>
 #include <QObject>
 #include <QModelIndexList>
 
+#include <AIS_InteractiveObject.hxx>
 #include <AIS_ListOfInteractive.hxx>
 #include <NCollection_List.hxx>
 #include <TopoDS_Shape.hxx>
@@ -73,10 +75,17 @@ Q_OBJECT
   //! \param theValues a container of values to be selected.
   void setSelected(const QList<std::shared_ptr<ModuleBase_ViewerPrs> >& theValues);
 
+  //! Find all selected owners of the object and remove the owners from selection
+  //! \param theObject an interactive object
+  void deselectPresentation(const Handle(AIS_InteractiveObject) theObject);
+
   /// Updates selection, which are depend on the selection in the given place
   /// \param thePlace a widget where selection has happened.
   void updateSelectionBy(const ModuleBase_ISelection::SelectionPlace& thePlace);
 
+  /// Returns list of selected features (ignores other selected objects and parts)
+  std::list<FeaturePtr> getSelectedFeatures();
+
 signals:
   //! Emited when selection in a one of viewers was changed
   void selectionChanged();
index 5ab4e495c20c12fa3289256498e04363b969236f..e55494d77bb45f26be0bba2d24ba54841c36a34f 100755 (executable)
@@ -21,6 +21,8 @@
 #include "XGUI_Workshop.h"
 
 #include "XGUI_ActionsMgr.h"
+#include "XGUI_ActiveControlMgr.h"
+#include "XGUI_ActiveControlSelector.h"
 #include "XGUI_MenuMgr.h"
 #include "XGUI_ColorDialog.h"
 #include "XGUI_DeflectionDialog.h"
 #include "XGUI_Displayer.h"
 #include "XGUI_ErrorDialog.h"
 #include "XGUI_ErrorMgr.h"
+#include "XGUI_FacesPanel.h"
+#include "XGUI_FacesPanelSelector.h"
 #include "XGUI_ModuleConnector.h"
 #include "XGUI_ObjectsBrowser.h"
 #include "XGUI_OperationMgr.h"
 #include "XGUI_PropertyPanel.h"
+#include "XGUI_PropertyPanelSelector.h"
 #include "XGUI_PropertyDialog.h"
 #include "XGUI_SalomeConnector.h"
 #include "XGUI_Selection.h"
+#include "XGUI_SelectionActivate.h"
 #include "XGUI_SelectionMgr.h"
 #include "XGUI_Tools.h"
 #include "XGUI_ViewerProxy.h"
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Object.h>
 #include <ModelAPI_ResultBody.h>
+#include <ModelAPI_ResultCompSolid.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_ResultGroup.h>
 #include <ModelAPI_ResultParameter.h>
 #include <ModelAPI_ResultField.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Validator.h>
-#include <ModelAPI_ResultCompSolid.h>
 #include <ModelAPI_Tools.h>
 
 //#include <PartSetPlugin_Part.h>
 #include <ModuleBase_WidgetValidated.h>
 #include <ModuleBase_ModelWidget.h>
 #include <ModuleBase_ResultPrs.h>
+#include <ModuleBase_ActionIntParameter.h>
 
 #include <Config_Common.h>
 #include <Config_FeatureMessage.h>
@@ -152,18 +159,22 @@ static Handle(VInspector_CallBack) MyVCallBack;
 #include <dlfcn.h>
 #endif
 
+//#define DEBUG_WITH_MESSAGE_REPORT
+
 QString XGUI_Workshop::MOVE_TO_END_COMMAND = QObject::tr("Move to the end");
 
 //#define DEBUG_DELETE
 //#define DEBUG_FEATURE_NAME
 //#define DEBUG_CLEAN_HISTORY
 
+//******************************************************
 XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
     : QObject(),
       myCurrentDir(QString()),
       myModule(NULL),
       mySalomeConnector(theConnector),
       myPropertyPanel(0),
+      myFacesPanel(0),
       myObjectBrowser(0),
       myDisplayer(0)
       //myViewerSelMode(TopAbs_FACE)
@@ -174,6 +185,7 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
   ModuleBase_IWorkshop* aWorkshop = moduleConnector();
   // Has to be defined first in order to get errors and messages from other components
   myEventsListener = new XGUI_WorkshopListener(aWorkshop);
+  mySelectionActivate = new XGUI_SelectionActivate(aWorkshop);
 
   SUIT_ResourceMgr* aResMgr = ModuleBase_Preferences::resourceMgr();
 #ifndef HAVE_SALOME
@@ -213,6 +225,7 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
   connect(mySelector, SIGNAL(selectionChanged()), this, SLOT(updateCommandStatus()));
 
   myActionsMgr = new XGUI_ActionsMgr(this);
+  myActiveControlMgr = new XGUI_ActiveControlMgr(myModuleConnector);
   myMenuMgr = new XGUI_MenuMgr(this);
   myErrorDlg = new XGUI_ErrorDialog(QApplication::desktop());
   myContextMenuMgr = new XGUI_ContextMenuMgr(this);
@@ -304,6 +317,9 @@ void XGUI_Workshop::startApplication()
 #ifdef _DEBUG
   Config_PropManager::registerProp("Plugins", "create_part_by_start", "Create Part by Start",
     Config_Prop::Boolean, "false");
+
+  Config_PropManager::registerProp("Plugins", "show_hide_faces", "Show Hide Faces (on the right)",
+    Config_Prop::Boolean, "false");
 #endif
   registerValidators();
 
@@ -333,9 +349,10 @@ void XGUI_Workshop::startApplication()
 #endif
 }
 
+//******************************************************
 void XGUI_Workshop::activateModule()
 {
-  myModule->activateSelectionFilters();
+  selectionActivate()->updateSelectionFilters();
 
   connect(myDisplayer, SIGNAL(objectDisplayed(ObjectPtr, AISObjectPtr)),
     myModule, SLOT(onObjectDisplayed(ObjectPtr, AISObjectPtr)));
@@ -351,12 +368,11 @@ void XGUI_Workshop::activateModule()
   myOperationMgr->activate();
 }
 
+//******************************************************
 void XGUI_Workshop::deactivateModule()
 {
-  myModule->deactivateSelectionFilters();
-
   // remove internal displayer filter
-  displayer()->deactivateSelectionFilters();
+  displayer()->deactivateSelectionFilters(false);
 
   disconnect(myDisplayer, SIGNAL(objectDisplayed(ObjectPtr, AISObjectPtr)),
     myModule, SLOT(onObjectDisplayed(ObjectPtr, AISObjectPtr)));
@@ -366,17 +382,10 @@ void XGUI_Workshop::deactivateModule()
   XGUI_Displayer* aDisplayer = displayer();
   QObjectPtrList aDisplayed = aDisplayer->displayedObjects();
   aDisplayer->deactivateObjects(aDisplayed, true);
-  Handle(AIS_InteractiveContext) aContext = viewer()->AISContext();
-  Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast(aDisplayer->getTrihedron());
-  /// deactivate trihedron in selection modes
-  TColStd_ListOfInteger aTColModes;
-  aContext->ActivatedModes(aTrihedron, aTColModes);
-  TColStd_ListIteratorOfListOfInteger itr( aTColModes );
-  for (; itr.More(); itr.Next() ) {
-    Standard_Integer aMode = itr.Value();
-    aContext->Deactivate(aTrihedron, aMode);
-  }
+  selectionActivate()->deactivateTrihedronInSelectionModes();
+
 #ifdef BEFORE_TRIHEDRON_PATCH
+  //Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast(aDisplayer->getTrihedron());
   /// Trihedron problem: objects stayed in the viewer, should be removed manually
   /// otherwise in SALOME happens crash by HideAll in the viewer
   aContext->Remove(aTrihedron->Position(), true);
@@ -415,14 +424,6 @@ void XGUI_Workshop::initMenu()
   addHistoryMenu(aAction, SIGNAL(updateRedoHistory(const QList<ActionInfo>&)), SLOT(onRedo(int)));
 
   salomeConnector()->addDesktopMenuSeparator("MEN_DESK_EDIT");
-  //aAction = salomeConnector()->addDesktopCommand("REBUILD_CMD", tr("Rebuild"),
-  //                                            tr("Rebuild data objects"),
-  //                                            QIcon(":pictures/rebuild.png"), QKeySequence(),
-  //                                            false, "MEN_DESK_EDIT");
-  //salomeConnector()->addActionInToolbar( aAction, aToolBarTitle );
-
-  //connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onRebuild()));
-  //salomeConnector()->addDesktopMenuSeparator("MEN_DESK_EDIT");
 
   aAction = salomeConnector()->addDesktopCommand("SAVEAS_CMD", tr("Export native..."),
                                              tr("Export the current document into a native file"),
@@ -470,12 +471,6 @@ void XGUI_Workshop::initMenu()
                  SIGNAL(updateRedoHistory(const QList<ActionInfo>&)),
                  SLOT(onRedo(int)));
 
-  //aCommand = aGroup->addFeature("REBUILD_CMD", tr("Rebuild"), tr("Rebuild data objects"),
-  //  QIcon(":pictures/rebuild.png"), QKeySequence());
-  //aCommand->connectTo(this, SLOT(onRebuild()));
-
-  //aCommand->disable();
-
   aCommand = aGroup->addFeature("OPEN_CMD", tr("Open..."), tr("Open a new document"),
                                 QIcon(":pictures/open.png"), QKeySequence::Open);
   aCommand->connectTo(this, SLOT(onOpen()));
@@ -491,6 +486,7 @@ void XGUI_Workshop::initMenu()
 }
 
 #ifndef HAVE_SALOME
+//******************************************************
 AppElements_Workbench* XGUI_Workshop::addWorkbench(const QString& theName)
 {
   AppElements_MainMenu* aMenuBar = myMainWindow->menuObject();
@@ -565,7 +561,7 @@ void XGUI_Workshop::onPreviewActionClicked()
 void XGUI_Workshop::deactivateActiveObject(const ObjectPtr& theObject, const bool theUpdateViewer)
 {
   if (!myModule->canActivateSelection(theObject)) {
-    if (myDisplayer->isActive(theObject)) {
+    if (selectionActivate()->isActive(theObject)) {
       QObjectPtrList anObjects;
       anObjects.append(theObject);
       myDisplayer->deactivateObjects(anObjects, theUpdateViewer);
@@ -591,6 +587,7 @@ bool XGUI_Workshop::isFeatureOfNested(const FeaturePtr& theFeature)
   return aHasNested;
 }
 
+//******************************************************
 void XGUI_Workshop::fillPropertyPanel(ModuleBase_Operation* theOperation)
 {
   ModuleBase_OperationFeature* aFOperation =
@@ -598,7 +595,7 @@ void XGUI_Workshop::fillPropertyPanel(ModuleBase_Operation* theOperation)
   if (!aFOperation)
     return;
 
-  showPropertyPanel();
+  showPanel(myPropertyPanel);
   myPropertyPanel->cleanContent();
 
   QList<ModuleBase_ModelWidget*> aWidgets;
@@ -684,6 +681,7 @@ void XGUI_Workshop::fillPropertyPanel(ModuleBase_Operation* theOperation)
   myErrorMgr->setPropertyPanel(myPropertyPanel);
 }
 
+//******************************************************
 void XGUI_Workshop::connectToPropertyPanel(const bool isToConnect)
 {
   XGUI_PropertyPanel* aPropertyPanel = propertyPanel();
@@ -719,7 +717,6 @@ void XGUI_Workshop::onOperationResumed(ModuleBase_Operation* theOperation)
   myModule->operationResumed(theOperation);
 }
 
-
 //******************************************************
 void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation)
 {
@@ -733,7 +730,7 @@ void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation)
   ModuleBase_ISelection* aSel = mySelector->selection();
   QObjectPtrList aObj = aSel->selectedPresentations();
   //!< No need for property panel
-  hidePropertyPanel();
+  hidePanel(myPropertyPanel);
   myPropertyPanel->cleanContent();
 
   connectToPropertyPanel(false);
@@ -744,14 +741,14 @@ void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation)
   QObjectPtrList anObjects;
   FeaturePtr aFeature = aFOperation->feature();
   if (aFeature.get()) { // feature may be not created (plugin load fail)
-    if (myDisplayer->isVisible(aFeature) && !myDisplayer->isActive(aFeature))
+    if (myDisplayer->isVisible(aFeature) && !selectionActivate()->isActive(aFeature))
       anObjects.append(aFeature);
     std::list<ResultPtr> aResults;
     ModelAPI_Tools::allResults(aFeature, aResults);
     std::list<ResultPtr>::const_iterator aIt;
     for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
       ResultPtr anObject = *aIt;
-      if (myDisplayer->isVisible(anObject) && !myDisplayer->isActive(anObject)) {
+      if (myDisplayer->isVisible(anObject) && !selectionActivate()->isActive(anObject)) {
         anObjects.append(anObject);
       }
     }
@@ -759,17 +756,19 @@ void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation)
   activateObjectsSelection(anObjects);
 }
 
-
+//******************************************************
 void XGUI_Workshop::onOperationCommitted(ModuleBase_Operation* theOperation)
 {
   myModule->operationCommitted(theOperation);
 }
 
+//******************************************************
 void XGUI_Workshop::onOperationAborted(ModuleBase_Operation* theOperation)
 {
   myModule->operationAborted(theOperation);
 }
 
+//******************************************************
 void XGUI_Workshop::setGrantedFeatures(ModuleBase_Operation* theOperation)
 {
   ModuleBase_OperationFeature* aFOperation =
@@ -1035,59 +1034,59 @@ bool XGUI_Workshop::onSaveAs()
 //******************************************************
 void XGUI_Workshop::onUndo(int theTimes)
 {
-  ModuleBase_ModelWidget* anActiveWidget = myOperationMgr->activeWidget();
-  if (anActiveWidget && anActiveWidget->processAction(ActionUndo))
-    return;
-
-  objectBrowser()->treeView()->setCurrentIndex(QModelIndex());
-  SessionPtr aMgr = ModelAPI_Session::get();
-  std::list<std::string> aUndoList = aMgr->undoList();
-  if (aMgr->isOperation()) {
-    /// this is important for nested operations
-    /// when sketch operation is active, this condition is false and
-    /// the sketch operation is not aborted
-    operationMgr()->onAbortOperation();
-  }
-  std::list<std::string>::const_iterator aIt = aUndoList.cbegin();
-  for (int i = 0; (i < theTimes) && (aIt != aUndoList.cend()); ++i, ++aIt) {
-    aMgr->undo();
-    if (QString((*aIt).c_str()) == MOVE_TO_END_COMMAND)
-      myObjectBrowser->rebuildDataTree();
-  }
-
-  operationMgr()->updateApplyOfOperations();
-  updateCommandStatus();
+  processUndoRedo(ActionUndo, theTimes);
 }
 
 //******************************************************
 void XGUI_Workshop::onRedo(int theTimes)
 {
-  ModuleBase_ModelWidget* anActiveWidget = myOperationMgr->activeWidget();
-  if (anActiveWidget && anActiveWidget->processAction(ActionRedo))
-    return;
+  processUndoRedo(ActionRedo, theTimes);
+}
 
+//******************************************************
+void XGUI_Workshop::processUndoRedo(const ModuleBase_ActionType theActionType, int theTimes)
+{
+  ModuleBase_ModelWidget* anActiveWidget = myOperationMgr->activeWidget();
+  if (anActiveWidget) {
+    ActionIntParamPtr aParam(new ModuleBase_ActionIntParameter(theTimes));
+    if (anActiveWidget->processAction(theActionType, aParam))
+      return;
+  }
   // the viewer update should be blocked in order to avoid the features blinking. For the created
   // feature a results are created, the flush of the created signal caused the viewer redisplay for
   // each created result. After a redisplay signal is flushed. So, the viewer update is blocked
   // until redo of all possible objects happens
   bool isUpdateEnabled = myDisplayer->enableUpdateViewer(false);
 
-  objectBrowser()->treeView()->setCurrentIndex(QModelIndex());
   SessionPtr aMgr = ModelAPI_Session::get();
-  std::list<std::string> aRedoList = aMgr->redoList();
   if (aMgr->isOperation()) {
+    XGUI_OperationMgr* aOpMgr = operationMgr();
     /// this is important for nested operations
     /// when sketch operation is active, this condition is false and
     /// the sketch operation is not aborted
-    operationMgr()->onAbortOperation();
+    if (aOpMgr->canStopOperation(aOpMgr->currentOperation()))
+      aOpMgr->abortOperation(aOpMgr->currentOperation());
+    else
+    {
+      myDisplayer->enableUpdateViewer(isUpdateEnabled);
+      return;
+    }
   }
-  std::list<std::string>::const_iterator aIt = aRedoList.cbegin();
-  for (int i = 0; (i < theTimes) && (aIt != aRedoList.cend()); ++i, ++aIt) {
-    aMgr->redo();
+  objectBrowser()->treeView()->setCurrentIndex(QModelIndex());
+  std::list<std::string> anActionList = theActionType == ActionUndo ? aMgr->undoList()
+    : aMgr->redoList();
+  std::list<std::string>::const_iterator aIt = anActionList.cbegin();
+  for (int i = 0; (i < theTimes) && (aIt != anActionList.cend()); ++i, ++aIt) {
+    if (theActionType == ActionUndo)
+      aMgr->undo();
+    else
+      aMgr->redo();
+
     if (QString((*aIt).c_str()) == MOVE_TO_END_COMMAND)
       myObjectBrowser->rebuildDataTree();
   }
   operationMgr()->updateApplyOfOperations();
+  facesPanel()->reset(true);
   updateCommandStatus();
 
   // unblock the viewer update functionality and make update on purpose
@@ -1095,23 +1094,6 @@ void XGUI_Workshop::onRedo(int theTimes)
   myDisplayer->updateViewer();
 }
 
-//******************************************************
-//void XGUI_Workshop::onRebuild()
-//{
-//  SessionPtr aMgr = ModelAPI_Session::get();
-//  bool aWasOperation = aMgr->isOperation(); // keep this value
-//  if (!aWasOperation) {
-//    aMgr->startOperation("Rebuild");
-//  }
-//  static const Events_ID aRebuildEvent = Events_Loop::loop()->eventByName("Rebuild");
-//  Events_Loop::loop()->send(std::shared_ptr<Events_Message>(
-//    new Events_Message(aRebuildEvent, this)));
-//  if (!aWasOperation) {
-//    aMgr->finishOperation();
-//  }
-//  updateCommandStatus();
-//}
-
 //******************************************************
 void XGUI_Workshop::onWidgetStateChanged(int thePreviousState)
 {
@@ -1150,11 +1132,13 @@ void XGUI_Workshop::onValuesChanged()
   }
 }
 
+//******************************************************
 void XGUI_Workshop::onWidgetObjectUpdated()
 {
   operationMgr()->onValidateOperation();
 }
 
+//******************************************************
 ModuleBase_IModule* XGUI_Workshop::loadModule(const QString& theModule)
 {
   QString libName = QString::fromStdString(library(theModule.toStdString()));
@@ -1288,14 +1272,24 @@ void XGUI_Workshop::updateCommandStatus()
   emit commandStatusUpdated();
 }
 
+//******************************************************
 void XGUI_Workshop::updateHistory()
 {
-  std::list<std::string> aUndoList = ModelAPI_Session::get()->undoList();
-  QList<ActionInfo> aUndoRes = processHistoryList(aUndoList);
-  emit updateUndoHistory(aUndoRes);
+  bool isActionEnabled = false;
+  ModuleBase_ModelWidget* anActiveWidget = myOperationMgr->activeWidget();
+  QList<ActionInfo> aUndoRes;
+  QList<ActionInfo> aRedoRes;
+  if (anActiveWidget && anActiveWidget->canProcessAction(ActionUndo, isActionEnabled)) {
+    aUndoRes = anActiveWidget->actionsList(ActionUndo);
+    aRedoRes = anActiveWidget->actionsList(ActionRedo);
+  } else {
+    std::list<std::string> aUndoList = ModelAPI_Session::get()->undoList();
+    aUndoRes = processHistoryList(aUndoList);
 
-  std::list<std::string> aRedoList = ModelAPI_Session::get()->redoList();
-  QList<ActionInfo> aRedoRes = processHistoryList(aRedoList);
+    std::list<std::string> aRedoList = ModelAPI_Session::get()->redoList();
+    aRedoRes = processHistoryList(aRedoList);
+  }
+  emit updateUndoHistory(aUndoRes);
   emit updateRedoHistory(aRedoRes);
 }
 
@@ -1329,13 +1323,52 @@ void XGUI_Workshop::createDockWidgets()
   QDockWidget* aObjDock = createObjectBrowser(aDesktop);
   aDesktop->addDockWidget(Qt::LeftDockWidgetArea, aObjDock);
   myPropertyPanel = new XGUI_PropertyPanel(aDesktop, myOperationMgr);
+  myActiveControlMgr->addSelector(new XGUI_PropertyPanelSelector(myPropertyPanel));
+
   myPropertyPanel->setupActions(myActionsMgr);
   myPropertyPanel->setAllowedAreas(Qt::LeftDockWidgetArea |
                                    Qt::RightDockWidgetArea |
                                    Qt::BottomDockWidgetArea);
   aDesktop->addDockWidget(Qt::LeftDockWidgetArea, myPropertyPanel);
-  hidePropertyPanel();  ///<! Invisible by default
+  hidePanel(myPropertyPanel);  ///<! Invisible by default
+
+  myFacesPanel = new XGUI_FacesPanel(aDesktop, myModuleConnector);
+  myActiveControlMgr->addSelector(new XGUI_FacesPanelSelector(myFacesPanel));
+  myFacesPanel->setAllowedAreas(Qt::LeftDockWidgetArea |
+                                Qt::RightDockWidgetArea |
+                                Qt::BottomDockWidgetArea);
+  connect(myFacesPanel, SIGNAL(closed()), myFacesPanel, SLOT(onClosed()));
+
+  aDesktop->addDockWidget(
+#ifdef HAVE_SALOME
+    Qt::RightDockWidgetArea,
+#else
+    Qt::LeftDockWidgetArea,
+#endif
+    myFacesPanel);
+  hidePanel(myFacesPanel);  ///<! Invisible by default
+
+#ifdef _DEBUG
+  bool aShowOnTheRight = Config_PropManager::boolean("Plugins", "show_hide_faces");
+  if (aShowOnTheRight) {
+    aDesktop->addDockWidget(Qt::RightDockWidgetArea, myFacesPanel);
+    showPanel(myFacesPanel);
+  }
+#endif
   hideObjectBrowser();
+
+#ifndef HAVE_SALOME
+#ifdef _DEBUG
+  if (!aShowOnTheRight)
+  {
+#endif // _DEBUG
+  aDesktop->tabifyDockWidget(myFacesPanel, aObjDock);
+#ifdef _DEBUG
+  }
+#endif // _DEBUG
+
+#endif // HAVE_SALOME
+
   aDesktop->tabifyDockWidget(aObjDock, myPropertyPanel);
   myPropertyPanel->installEventFilter(myOperationMgr);
 
@@ -1358,28 +1391,32 @@ void XGUI_Workshop::createDockWidgets()
 }
 
 //******************************************************
-void XGUI_Workshop::showPropertyPanel()
+void XGUI_Workshop::showPanel(QDockWidget* theDockWidget)
 {
-  QAction* aViewAct = myPropertyPanel->toggleViewAction();
-  ///<! Restore ability to close panel from the window's menu
-  aViewAct->setEnabled(true);
-  myPropertyPanel->show();
-  myPropertyPanel->raise();
+  if (theDockWidget == myPropertyPanel) {
+    QAction* aViewAct = myPropertyPanel->toggleViewAction();
+    ///<! Restore ability to close panel from the window's menu
+    aViewAct->setEnabled(true);
+  }
+  theDockWidget->show();
+  theDockWidget->raise();
 
   // The next code is necessary to made the property panel the active window
   // in order to operation manager could process key events of the panel.
   // otherwise they are ignored. It happens only if the same(activateWindow) is
   // not happened by property panel activation(e.g. resume operation of Sketch)
-  ModuleBase_Tools::setFocus(myPropertyPanel, "XGUI_Workshop::showPropertyPanel()");
+  ModuleBase_Tools::setFocus(theDockWidget, "XGUI_Workshop::showPanel()");
 }
 
 //******************************************************
-void XGUI_Workshop::hidePropertyPanel()
+void XGUI_Workshop::hidePanel(QDockWidget* theDockWidget)
 {
-  QAction* aViewAct = myPropertyPanel->toggleViewAction();
-  ///<! Do not allow to show empty property panel
-  aViewAct->setEnabled(false);
-  myPropertyPanel->hide();
+  if (theDockWidget && theDockWidget == myPropertyPanel) {
+    QAction* aViewAct = theDockWidget->toggleViewAction();
+    ///<! Do not allow to show empty property panel
+    aViewAct->setEnabled(false);
+  }
+  theDockWidget->hide();
 
   // the property panel is active window of the desktop, when it is
   // hidden, it is undefined which window becomes active. By this reason
@@ -1389,7 +1426,7 @@ void XGUI_Workshop::hidePropertyPanel()
   // are processed by this console. For example Undo actions.
   // It is possible that this code is to be moved to SHAPER package
   QMainWindow* aDesktop = desktop();
-  ModuleBase_Tools::setFocus(aDesktop, "XGUI_Workshop::showPropertyPanel()");
+  ModuleBase_Tools::setFocus(aDesktop, "XGUI_Workshop::hidePanel()");
 }
 
 //******************************************************
@@ -1466,12 +1503,24 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked)
     viewer()->eraseAll();
 #endif
     updateCommandStatus();
+    // Necessary for update icons in ObjectBrowser on Linux
+    myObjectBrowser->updateAllIndexes();
   } else if (theId == "SELECT_VERTEX_CMD") {
     setViewerSelectionMode(TopAbs_VERTEX);
   } else if (theId == "SELECT_EDGE_CMD") {
     setViewerSelectionMode(TopAbs_EDGE);
   } else if (theId == "SELECT_FACE_CMD") {
     setViewerSelectionMode(TopAbs_FACE);
+  } else if (theId == "INSERT_FOLDER_CMD") {
+    insertFeatureFolder();
+  } else if (theId == "ADD_TO_FOLDER_BEFORE_CMD") {
+    insertToFolder(true);
+  } else if (theId == "ADD_TO_FOLDER_AFTER_CMD") {
+    insertToFolder(false);
+  } else if (theId == "ADD_OUT_FOLDER_BEFORE_CMD") {
+    moveOutFolder(true);
+  } else if (theId == "ADD_OUT_FOLDER_AFTER_CMD") {
+    moveOutFolder(false);
   } else if (theId == "SELECT_RESULT_CMD") {
     //setViewerSelectionMode(-1);
     //IMP: an attempt to use result selection with other selection modes
@@ -1497,6 +1546,13 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked)
         if (!aContext.IsNull())
           aParameters.Append(aContext);
 
+#ifdef DEBUG_WITH_MESSAGE_REPORT
+        Handle(Message_Report) aContextReport = aContext->GetReport();
+        aContext->SetReportActive (Standard_True);
+        aContextReport->SetLimit (1000);
+        if (!aContextReport.IsNull())
+          aParameters.Append(aContextReport);
+#endif
         MyVCallBack = new VInspector_CallBack();
         myDisplayer->setCallBack(MyVCallBack);
         #ifndef HAVE_SALOME
@@ -1509,13 +1565,23 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked)
         MyTCommunicator->RegisterPlugin("TKDFBrowser");
         MyTCommunicator->RegisterPlugin("TKShapeView");
         MyTCommunicator->RegisterPlugin("TKVInspector");
+#ifdef DEBUG_WITH_MESSAGE_REPORT
+        MyTCommunicator->RegisterPlugin("TKMessageView");
+#endif
         MyTCommunicator->RegisterPlugin("SMBrowser"); // custom plugin to view ModelAPI
         //MyTCommunicator->RegisterPlugin("TKSMBrowser"); // custom plugin to view ModelAPI
 
         MyTCommunicator->Init(aParameters);
         MyTCommunicator->Activate("TKSMBrowser"); // to have button in TInspector
+#ifndef DEBUG_WITH_MESSAGE_REPORT
         MyTCommunicator->Activate("TKVInspector"); // to have filled callback by model
+#endif
         MyTCommunicator->Activate("TKDFBrowser");
+
+#ifdef DEBUG_WITH_MESSAGE_REPORT
+        MyTCommunicator->Activate("TKMessageView"); // temporary
+        MyTCommunicator->Activate("TKVInspector"); // to have filled callback by model
+#endif
       }
       MyTCommunicator->SetVisible(true);
     }
@@ -1534,7 +1600,7 @@ void XGUI_Workshop::setViewerSelectionMode(int theMode)
     else
       myViewerSelMode.append(theMode);
   }
-  activateObjectsSelection(myDisplayer->displayedObjects());
+  selectionActivate()->updateSelectionModes();
 }
 
 //**************************************************************
@@ -1544,7 +1610,59 @@ void XGUI_Workshop::activateObjectsSelection(const QObjectPtrList& theList)
   module()->activeSelectionModes(aModes);
   if (aModes.isEmpty() && (myViewerSelMode.length() > 0))
     aModes.append(myViewerSelMode);
-  myDisplayer->activateObjects(aModes, theList);
+  selectionActivate()->activateObjects(aModes, theList);
+}
+
+//**************************************************************
+bool XGUI_Workshop::prepareForDisplay(const std::set<ObjectPtr>& theObjects) const
+{
+  if (facesPanel()->isEmpty())
+    return true;
+
+  // generate container of objects taking into account sub elments of compsolid
+  std::set<ObjectPtr> anAllProcessedObjects;
+  for (std::set<ObjectPtr>::const_iterator anObjectsIt = theObjects.begin();
+    anObjectsIt != theObjects.end(); anObjectsIt++) {
+    ObjectPtr anObject = *anObjectsIt;
+    ResultCompSolidPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(anObject);
+    if (aCompRes.get()) {
+      if (aCompRes->numberOfSubs(true) == 0)
+        anAllProcessedObjects.insert(anObject);
+      else {
+        for (int i = 0; i < aCompRes->numberOfSubs(true); i++) {
+          ResultPtr aSubRes = aCompRes->subResult(i, true);
+          anAllProcessedObjects.insert(aCompRes->subResult(i, true));
+        }
+      }
+    }
+    else
+      anAllProcessedObjects.insert(anObject);
+  }
+
+  // find hidden objects in faces panel
+  std::set<ObjectPtr> aHiddenObjects;
+  QStringList aHiddenObjectNames;
+  for (std::set<ObjectPtr>::const_iterator anObjectsIt = anAllProcessedObjects.begin();
+       anObjectsIt != anAllProcessedObjects.end(); anObjectsIt++) {
+    if (!facesPanel()->isObjectHiddenByPanel(*anObjectsIt))
+      continue;
+    aHiddenObjects.insert(*anObjectsIt);
+    aHiddenObjectNames.append((*anObjectsIt)->data()->name().c_str());
+  }
+  if (aHiddenObjects.empty()) // in parameter objects there are no hidden objects in hide face
+    return true;
+
+  int anAnswer = QMessageBox::question(
+        desktop(), tr("Show object"),
+        tr("'%1'\n are hidden by %2:\nRemove objects from the panel to be displayed?")
+        .arg(aHiddenObjectNames.join(' ,')).arg(facesPanel()->windowTitle()),
+        QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
+
+  bool aToBeDisplayed = anAnswer == QMessageBox::Yes;
+  if (aToBeDisplayed)
+    facesPanel()->restoreObjects(aHiddenObjects);
+
+  return aToBeDisplayed;
 }
 
 //**************************************************************
@@ -1566,9 +1684,10 @@ void XGUI_Workshop::deleteObjects()
   bool hasParameter = false;
   bool hasCompositeOwner = false;
   bool hasResultInHistory = false;
+  bool hasFolder = false;
   ModuleBase_Tools::checkObjects(anObjects, hasResult, hasFeature, hasParameter, hasCompositeOwner,
-                                 hasResultInHistory);
-  if (!(hasFeature || hasParameter))
+                                 hasResultInHistory, hasFolder);
+  if (!(hasFeature || hasParameter || hasFolder))
     return;
 
   // delete objects
@@ -1577,6 +1696,9 @@ void XGUI_Workshop::deleteObjects()
   ModuleBase_Tools::convertToFeatures(anObjects, aFeatures);
   ModelAPI_Tools::findAllReferences(aFeatures, aReferences);
 
+  std::set<FolderPtr> aFolders;
+  ModuleBase_Tools::convertToFolders(anObjects, aFolders);
+
   bool aDone = false;
   QString aDescription = contextMenuMgr()->action("DELETE_CMD")->text() + " %1";
   aDescription = aDescription.arg(XGUI_Tools::unionOfObjectNames(anObjects, ", "));
@@ -1595,6 +1717,18 @@ void XGUI_Workshop::deleteObjects()
       aFeatures.insert(aFeatureRefsToDelete.begin(), aFeatureRefsToDelete.end());
     aDone = ModelAPI_Tools::removeFeatures(aFeatures, false);
   }
+  if (aFolders.size() > 0) {
+    std::set<FolderPtr>::const_iterator anIt = aFolders.begin(),
+                                         aLast = aFolders.end();
+    for (; anIt != aLast; anIt++) {
+      FolderPtr aFolder = *anIt;
+      if (aFolder.get()) {
+        DocumentPtr aDoc = aFolder->document();
+        aDoc->removeFolder(aFolder);
+      }
+    }
+  }
+
   if (aDone)
     operationMgr()->commitOperation();
   else
@@ -1794,6 +1928,7 @@ bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theObjects)
   return ModelAPI_Tools::removeFeaturesAndReferences(aFeatures);
 }
 
+//******************************************************
 bool hasResults(QObjectPtrList theObjects, const std::set<std::string>& theTypes)
 {
   bool isFoundResultType = false;
@@ -1867,6 +2002,7 @@ std::list<FeaturePtr> toCurrentFeatures(const ObjectPtr& theObject)
   return std::list<FeaturePtr>(aObjectIt, aCurrentIt);
 }
 
+//******************************************************
 bool XGUI_Workshop::canMoveFeature()
 {
   QString anActionId = "MOVE_CMD";
@@ -1954,6 +2090,7 @@ bool XGUI_Workshop::canChangeProperty(const QString& theActionName) const
   return false;
 }
 
+//******************************************************
 void setColor(ResultPtr theResult, const std::vector<int>& theColor)
 {
   if (!theResult.get())
@@ -2228,21 +2365,24 @@ void XGUI_Workshop::onPreviewStateChanged()
 for (int i = 0; i < aDoc->size(aGroupName); i++) { \
   aDoc->object(aGroupName, i)->setDisplayed(aDisplay); \
 }
+
+//******************************************************
 void XGUI_Workshop::showObjects(const QObjectPtrList& theList, bool isVisible)
 {
+  if (isVisible) {
+    std::set<ObjectPtr> anObjects;
+    foreach (ObjectPtr aObj, theList) {
+      anObjects.insert(aObj);
+    }
+    if (!prepareForDisplay(anObjects))
+      return;
+  }
+
   foreach (ObjectPtr aObj, theList) {
     aObj->setDisplayed(isVisible);
   }
   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
-#ifndef WIN32
-  // Necessary for update icons in ObjectBrowser on Linux
-  QModelIndexList aIndexes = mySelector->selection()->selectedIndexes();
-  foreach (QModelIndex aIdx, aIndexes) {
-    if (aIdx.column() == 0) {
-      myObjectBrowser->treeView()->update(aIdx);
-    }
-  }
-#endif
+  myObjectBrowser->updateAllIndexes();
 }
 
 //**************************************************************
@@ -2263,23 +2403,24 @@ void XGUI_Workshop::showOnlyObjects(const QObjectPtrList& theList)
     viewer()->eraseAll();
 #endif
 
+  std::set<ObjectPtr> anObjects;
+  foreach (ObjectPtr aObj, theList) {
+    anObjects.insert(aObj);
+  }
+
+  if (!prepareForDisplay(anObjects))
+    return;
+
   // Show only objects from the list
   foreach (ObjectPtr aObj, theList) {
     aObj->setDisplayed(true);
   }
   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
-#ifndef WIN32
+
   // Necessary for update icons in ObjectBrowser on Linux
-  QModelIndexList aIndexes = mySelector->selection()->selectedIndexes();
-  foreach (QModelIndex aIdx, aIndexes) {
-    if (aIdx.column() == 0) {
-      myObjectBrowser->treeView()->update(aIdx);
-    }
-  }
-#endif
+  myObjectBrowser->updateAllIndexes();
 }
 
-
 //**************************************************************
 void XGUI_Workshop::registerValidators() const
 {
@@ -2350,6 +2491,7 @@ void XGUI_Workshop::closeDocument()
   //objectBrowser()->dataModel()->blockEventsProcessing(isBlocked);
 }
 
+//******************************************************
 void XGUI_Workshop::addHistoryMenu(QObject* theObject, const char* theSignal, const char* theSlot)
 {
   XGUI_HistoryMenu* aMenu = NULL;
@@ -2366,6 +2508,7 @@ void XGUI_Workshop::addHistoryMenu(QObject* theObject, const char* theSignal, co
   connect(aMenu, SIGNAL(actionSelected(int)), this, theSlot);
 }
 
+//******************************************************
 QList<ActionInfo> XGUI_Workshop::processHistoryList(const std::list<std::string>& theList) const
 {
   QList<ActionInfo> aResult;
@@ -2391,6 +2534,7 @@ QList<ActionInfo> XGUI_Workshop::processHistoryList(const std::list<std::string>
   return aResult;
 }
 
+//******************************************************
 void XGUI_Workshop::setStatusBarMessage(const QString& theMessage)
 {
 #ifdef HAVE_SALOME
@@ -2400,6 +2544,8 @@ void XGUI_Workshop::setStatusBarMessage(const QString& theMessage)
 #endif
 }
 
+#ifdef HAVE_SALOME
+//******************************************************
 void XGUI_Workshop::synchronizeViewer()
 {
   SessionPtr aMgr = ModelAPI_Session::get();
@@ -2415,6 +2561,7 @@ void XGUI_Workshop::synchronizeViewer()
   }
 }
 
+//******************************************************
 void XGUI_Workshop::synchronizeGroupInViewer(const DocumentPtr& theDoc,
                                              const std::string& theGroup,
                                              bool theUpdateViewer)
@@ -2435,7 +2582,9 @@ void XGUI_Workshop::synchronizeGroupInViewer(const DocumentPtr& theDoc,
   if (theUpdateViewer)
     myDisplayer->updateViewer();
 }
+#endif
 
+//******************************************************
 void XGUI_Workshop::highlightResults(const QObjectPtrList& theObjects)
 {
   FeaturePtr aFeature;
@@ -2464,6 +2613,7 @@ void XGUI_Workshop::highlightResults(const QObjectPtrList& theObjects)
                              tr("Results not found"), QMessageBox::Ok);
 }
 
+//******************************************************
 void XGUI_Workshop::highlightFeature(const QObjectPtrList& theObjects)
 {
   ResultPtr aResult;
@@ -2485,3 +2635,69 @@ void XGUI_Workshop::highlightFeature(const QObjectPtrList& theObjects)
     objectBrowser()->blockSignals(aBlocked);
   }
 }
+
+void XGUI_Workshop::insertFeatureFolder()
+{
+  QObjectPtrList aObjects = mySelector->selection()->selectedObjects();
+  if (aObjects.isEmpty())
+    return;
+  ObjectPtr aObj = aObjects.first();
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
+  if (aFeature.get() == NULL)
+    return;
+  SessionPtr aMgr = ModelAPI_Session::get();
+  DocumentPtr aDoc = aMgr->activeDocument();
+
+  QString aDescription = contextMenuMgr()->action("INSERT_FOLDER_CMD")->text();
+
+  aMgr->startOperation(aDescription.toStdString());
+  aDoc->addFolder(aFeature);
+  aMgr->finishOperation();
+
+  updateCommandStatus();
+}
+
+
+void XGUI_Workshop::insertToFolder(bool isBefore)
+{
+  std::list<FeaturePtr> aFeatures = mySelector->getSelectedFeatures();
+  if (aFeatures.empty())
+    return;
+
+  SessionPtr aMgr = ModelAPI_Session::get();
+  DocumentPtr aDoc = aMgr->activeDocument();
+
+  FolderPtr aFolder = isBefore? aDoc->findFolderAbove(aFeatures):
+                                aDoc->findFolderBelow(aFeatures);
+  if (!aFolder.get())
+    return;
+
+  QString aDescription = contextMenuMgr()->action(
+    isBefore ? "ADD_TO_FOLDER_BEFORE_CMD" : "ADD_TO_FOLDER_AFTER_CMD")->text();
+
+  aMgr->startOperation(aDescription.toStdString());
+  aDoc->moveToFolder(aFeatures, aFolder);
+  aMgr->finishOperation();
+
+  updateCommandStatus();
+}
+
+void XGUI_Workshop::moveOutFolder(bool isBefore)
+{
+  std::list<FeaturePtr> aFeatures = mySelector->getSelectedFeatures();
+  if (aFeatures.empty())
+    return;
+
+  SessionPtr aMgr = ModelAPI_Session::get();
+  DocumentPtr aDoc = aMgr->activeDocument();
+
+
+  QString aDescription = contextMenuMgr()->action(
+    isBefore ? "ADD_OUT_FOLDER_BEFORE_CMD" : "ADD_OUT_FOLDER_AFTER_CMD")->text();
+
+  aMgr->startOperation(aDescription.toStdString());
+  aDoc->removeFromFolder(aFeatures, isBefore);
+  aMgr->finishOperation();
+
+  updateCommandStatus();
+}
index de4266d845c933eb14b73e3758a6ada5c54d0fd9..7495365b43824d14eb09af3ea719752d016a1df4 100755 (executable)
 #define XGUI_WORKSHOP_H
 
 #include "XGUI.h"
-//#include "XGUI_Constants.h"
-#include <ModuleBase_Definitions.h>
+
 #include <ModelAPI_Document.h>
 #include <ModelAPI_Feature.h>
 
 #include <ModuleBase_ActionInfo.h>
+#include <ModuleBase_ActionType.h>
+#include <ModuleBase_Definitions.h>
 
+#include <SelectMgr_ListOfFilter.hxx>
+
+#include <QIcon>
 #include <QObject>
-#include <QMap>
 #include <QKeySequence>
-#include <QIcon>
+#include <QMap>
 
 #ifndef HAVE_SALOME
-class AppElements_MainWindow;
 class AppElements_Command;
+class AppElements_MainWindow;
 class AppElements_Workbench;
 #endif
 
+class Config_DataModelReader;
+
 class XGUI_ActionsMgr;
+class XGUI_ActiveControlMgr;
 class XGUI_ContextMenuMgr;
 class XGUI_Displayer;
 class XGUI_ErrorDialog;
 class XGUI_ErrorMgr;
+class XGUI_FacesPanel;
 class XGUI_MenuMgr;
 class XGUI_ModuleConnector;
 class XGUI_ObjectsBrowser;
@@ -52,6 +59,7 @@ class XGUI_OperationMgr;
 class XGUI_PropertyPanel;
 class XGUI_SalomeConnector;
 class XGUI_SalomeViewer;
+class XGUI_SelectionActivate;
 class XGUI_SelectionMgr;
 class XGUI_ViewerProxy;
 class XGUI_WorkshopListener;
@@ -60,17 +68,14 @@ class ModuleBase_IModule;
 class ModuleBase_IViewer;
 class ModuleBase_Operation;
 
-class QWidget;
+class QAction;
 class QDockWidget;
 class QMainWindow;
+class QWidget;
 
-class QAction;
-class Config_DataModelReader;
-
-/**\class XGUI_Workshop
- * \ingroup GUI
- * \brief Class which defines a configuration of the application (Workshop) and launches it.
- */
+/// \class XGUI_Workshop
+/// \ingroup GUI
+/// \brief Class which defines a configuration of the application (Workshop) and launches it.
 class XGUI_EXPORT XGUI_Workshop : public QObject
 {
 Q_OBJECT
@@ -81,7 +86,7 @@ Q_OBJECT
   XGUI_Workshop(XGUI_SalomeConnector* theConnector = 0);
   virtual ~XGUI_Workshop();
 
-  //! Starting of the application
+  /// Starting of the application
   void startApplication();
 
   /// Activates the module controls. Should be called after module creation
@@ -91,149 +96,122 @@ Q_OBJECT
   void deactivateModule();
 
 #ifndef HAVE_SALOME
-  //! Returns main window (Desktop) of the application
-  AppElements_MainWindow* mainWindow() const
-  {
-    return myMainWindow;
-  }
+  /// Returns main window (Desktop) of the application
+  AppElements_MainWindow* mainWindow() const { return myMainWindow; }
 
-  //! Creates and adds a new workbench (menu group) with the given name and returns it
+  /// Creates and adds a new workbench (menu group) with the given name and returns it
   AppElements_Workbench* addWorkbench(const QString& theName);
 #endif
 
-  //! Returns selection manager object
-  XGUI_SelectionMgr* selector() const
-  {
-    return mySelector;
-  }
-
-  //! Returns displayer
-  XGUI_Displayer* displayer() const
-  {
-    return myDisplayer;
-  }
-
-  //! ! Returns operation manager.
-  XGUI_OperationMgr* operationMgr() const
-  {
-    return myOperationMgr;
-  }
-
-  //! ! Returns error manager.
-  XGUI_ErrorMgr* errorMgr() const
-  {
-    return myErrorMgr;
-  }
-
-  //! ! Returns an actions manager
-  XGUI_ActionsMgr* actionsMgr() const
-  {
-    return myActionsMgr;
-  }
-
-  //! ! Returns an actions manager
-  XGUI_MenuMgr* menuMgr() const
-  {
-    return myMenuMgr;
-  }
-
-  //! Returns property panel widget
-  XGUI_PropertyPanel* propertyPanel() const
-  {
-    return myPropertyPanel;
-  }
-
-  //! Returns context menu manager object
-  XGUI_ContextMenuMgr* contextMenuMgr() const
-  {
-    return myContextMenuMgr;
-  }
-
-  //! Returns an object which provides interface to Salome Module (LightApp_Module)
-  XGUI_SalomeConnector* salomeConnector() const
-  {
-    return mySalomeConnector;
-  }
-
-  //! Provides an object which provides interface to Salome Viewer
+  /// Returns selection manager object
+  XGUI_SelectionMgr* selector() const { return mySelector; }
+
+  /// Returns selection activating object
+  XGUI_SelectionActivate* selectionActivate() const { return mySelectionActivate; }
+
+  /// Returns displayer
+  XGUI_Displayer* displayer() const { return myDisplayer; }
+
+  /// Returns operation manager.
+  XGUI_OperationMgr* operationMgr() const { return myOperationMgr; }
+
+  /// Returns error manager.
+  XGUI_ErrorMgr* errorMgr() const { return myErrorMgr; }
+
+  /// Returns an actions manager
+  XGUI_ActionsMgr* actionsMgr() const { return myActionsMgr; }
+
+  /// Returns an active control manager
+  XGUI_ActiveControlMgr* activeControlMgr() const { return myActiveControlMgr; }
+
+  /// Returns an actions manager
+  XGUI_MenuMgr* menuMgr() const { return myMenuMgr; }
+
+  /// Returns property panel widget
+  XGUI_PropertyPanel* propertyPanel() const { return myPropertyPanel; }
+
+  /// Returns panel for hide object faces
+  XGUI_FacesPanel* facesPanel() const { return myFacesPanel; }
+
+  /// Returns context menu manager object
+  XGUI_ContextMenuMgr* contextMenuMgr() const { return myContextMenuMgr; }
+
+  /// Returns an object which provides interface to Salome Module (LightApp_Module)
+  XGUI_SalomeConnector* salomeConnector() const { return mySalomeConnector; }
+
+  /// Provides an object which provides interface to Salome Viewer
   ModuleBase_IViewer* salomeViewer() const;
 
-  //! Returns true if the application works as SALOME module
-  bool isSalomeMode() const
-  {
-    return mySalomeConnector != 0;
-  }
+  /// Returns true if the application works as SALOME module
+  bool isSalomeMode() const { return mySalomeConnector != 0; }
 
-  //! Returns Object browser
-  XGUI_ObjectsBrowser* objectBrowser() const
-  {
-    return myObjectBrowser;
-  }
+  /// Returns Object browser
+  XGUI_ObjectsBrowser* objectBrowser() const { return myObjectBrowser; }
 
   /// This method is called by Salome module when selection is changed
   void salomeViewerSelectionChanged();
 
   /// Returns viewer which unifies access as to Salome viewer as to standalone viewer
-  XGUI_ViewerProxy* viewer() const
-  {
-    return myViewerProxy;
-  }
+  XGUI_ViewerProxy* viewer() const { return myViewerProxy; }
 
   /// Returns the module connector
   /// \returns the instance of connector
-  XGUI_ModuleConnector* moduleConnector() const
-  {
-    return myModuleConnector;
-  }
+  XGUI_ModuleConnector* moduleConnector() const { return myModuleConnector; }
 
   /// Returns a desktop
   /// \return a desktop instance
   QMainWindow* desktop() const;
 
-  //! Delete features
+  /// If faces panel made the object hidden, show message box whether the object should be
+  /// restored (removed from the panel) and displayed, if answer is No, returns false
+  /// \param theObject a model object
+  /// \return boolean state if the object should not be displayed
+  virtual bool prepareForDisplay(const std::set<ObjectPtr>& theObjects) const;
+
+  /// Delete features
   void deleteObjects();
 
-  //! Searches for selected features unused in other (not selected) features. If one or several
-  //! selected features are found, a warning message proposes to delete them. It contains
-  //! the list of features to be deleted.
+  /// Searches for selected features unused in other (not selected) features. If one or several
+  /// selected features are found, a warning message proposes to delete them. It contains
+  /// the list of features to be deleted.
   void cleanHistory();
 
-  //! Returns true if the selected feature can be moved to the position after the current feature
-  //! \return boolean value
+  /// Returns true if the selected feature can be moved to the position after the current feature
+  /// \return boolean value
   bool canMoveFeature();
 
-  //! Move selected features to be after the current feature
+  /// Move selected features to be after the current feature
   void moveObjects();
 
-  //! Returns true if the object can be shaded. If the object is a compsolid result, the method
-  //! checks subobjects of the result
-  //! \return boolean value
+  /// Returns true if the object can be shaded. If the object is a compsolid result, the method
+  /// checks subobjects of the result
+  /// \return boolean value
   bool canBeShaded(const ObjectPtr& theObject) const;
 
-  //! Returns true if there is at least one selected body/construction/group result
-  //! \param theActionName text of the checked action
-  //! \return boolean value
+  /// Returns true if there is at least one selected body/construction/group result
+  /// \param theActionName text of the checked action
+  /// \return boolean value
   bool canChangeProperty(const QString& theActionName) const;
 
-  //! Change color of the results if it is possible
-  //! The operation is available for construction, body and group results
-  //! theObjects a list of selected objects
+  /// Change color of the results if it is possible
+  /// The operation is available for construction, body and group results
+  /// theObjects a list of selected objects
   void changeColor(const QObjectPtrList& theObjects);
 
-  //! Change deflection of the results if it is possible
-  //! The operation is available for construction, body and group results
-  //! theObjects a list of selected objects
+  /// Change deflection of the results if it is possible
+  /// The operation is available for construction, body and group results
+  /// theObjects a list of selected objects
   void changeDeflection(const QObjectPtrList& theObjects);
 
-  //! Change transparency of the results if it is possible
-  //! The operation is available for construction, body and group results
-  //! theObjects a list of selected objects
+  /// Change transparency of the results if it is possible
+  /// The operation is available for construction, body and group results
+  /// theObjects a list of selected objects
   void changeTransparency(const QObjectPtrList& theObjects);
 
-  //! Show the given features in 3d Viewer
+  /// Show the given features in 3d Viewer
   void showObjects(const QObjectPtrList& theList, bool isVisible);
 
-  //! Show the given features in 3d Viewer
+  /// Show the given features in 3d Viewer
   void showOnlyObjects(const QObjectPtrList& theList);
 
   /// Set display mode for the given objects
@@ -249,10 +227,7 @@ Q_OBJECT
   void activateObjectsSelection(const QObjectPtrList& theList);
 
   /// Returns current module
-  ModuleBase_IModule* module() const
-  {
-    return myModule;
-  }
+  ModuleBase_IModule* module() const { return myModule; }
 
   /// Returns current directory which contains data files
   QString currentDataDir() const { return myCurrentDir; }
@@ -260,19 +235,15 @@ Q_OBJECT
   /// Returns current directory which contains data files
   void setCurrentDataDir(const QString& theDir) { myCurrentDir = theDir; }
 
-  /**
-  * Save the current document into a directory
-  * \param theName - path to the directory
-  * \param theFileNames - returned file names created in this directory
-  */
+  /// Save the current document into a directory
+  /// \param theName - path to the directory
+  /// \param theFileNames - returned file names created in this directory
   void saveDocument(const QString& theName, std::list<std::string>& theFileNames);
 
-  /**
-   * If there is an active (uncommitted) operation shows a prompt to abort it
-   * and performs abortion if user agreed. Returns true if
-   * - operation aborted successfully
-   * - there is no active operation
-   */
+  /// If there is an active (uncommitted) operation shows a prompt to abort it
+  /// and performs abortion if user agreed. Returns true if
+  /// - operation aborted successfully
+  /// - there is no active operation
   bool abortAllOperations();
 
   /// Updates workshop state according to the started operation, e.g. visualizes the property panel
@@ -280,10 +251,9 @@ Q_OBJECT
   /// \param theOpertion a started operation
   void operationStarted(ModuleBase_Operation* theOperation);
 
-
-  //! Delete features. Delete the referenced features. There can be a question with a list of
-  //! referenced objects.
-  //! \param theFeatures a list of objects to be deleted
+  /// Delete features. Delete the referenced features. There can be a question with a list of
+  /// referenced objects.
+  /// \param theFeatures a list of objects to be deleted
   bool deleteFeatures(const QObjectPtrList& theFeatures);
 
   /// Deactivates the object, if it is active and the module returns that the activation
@@ -296,10 +266,11 @@ Q_OBJECT
   /// \param theFeature a feature
   bool isFeatureOfNested(const FeaturePtr& theFeature);
 
-  //! Shows the message in the status bar
-  //! \param theMessage a message
+  /// Shows the message in the status bar
+  /// \param theMessage a message
   void setStatusBarMessage(const QString& theMessage);
 
+#ifdef HAVE_SALOME
   /// Has to be called in order to display objects with visibility status = true
   void synchronizeViewer();
 
@@ -312,6 +283,7 @@ Q_OBJECT
                                 const std::string& theGroup,
                                 bool theUpdateViewer);
 
+#endif
   /// Update the property panel content by the XML description of the operation and set the panel
   /// into the operation
   /// \param theOperation an operation
@@ -340,24 +312,24 @@ Q_OBJECT
   /// It is used for specific processing of Undo/Redo for this command.
   static QString MOVE_TO_END_COMMAND;
 
-  //! Closes all in the current session and load the directory
-  //! \param theDirectory a path to directory
+  /// Closes all in the current session and load the directory
+  /// \param theDirectory a path to directory
   void openDirectory(const QString& theDirectory);
 
 signals:
   /// Emitted when selection happens in Salome viewer
   void salomeViewerSelection();
 
-  //! the signal about the workshop actions states are updated.
+  /// the signal about the workshop actions states are updated.
   void commandStatusUpdated();
 
-  //! the application is started
+  /// the application is started
   void applicationStarted();
 
-  //! Signal to update Undo history list
+  /// Signal to update Undo history list
   void updateUndoHistory(const QList<ActionInfo>&);
 
-  //! Signal to update Redo history list
+  /// Signal to update Redo history list
   void updateRedoHistory(const QList<ActionInfo>&);
 
  public slots:
@@ -379,9 +351,6 @@ signals:
   /// Redo previous command
   void onRedo(int times = 1);
 
-  // Rebuild data tree
-  //void onRebuild();
-
   /// Validates the operation to change the "Apply" button state.
   /// \param thePreviousState the previous state of the widget
   void onWidgetStateChanged(int thePreviousState);
@@ -393,11 +362,11 @@ signals:
   /// Listens the corresponded signal of model widget and updates Apply button state by feature
   void onWidgetObjectUpdated();
 
-  /// Show property panel
-  void showPropertyPanel();
+  /// Show dock widget panel
+  void showPanel(QDockWidget* theDockWidget);
 
-  /// Hide property panel
-  void hidePropertyPanel();
+  /// Hide dock widget panel
+  void hidePanel(QDockWidget* theDockWidget);
 
   /// Show object Browser
   void showObjectBrowser();
@@ -438,9 +407,6 @@ signals:
    void setGrantedFeatures(ModuleBase_Operation* theOperation);
 
 private:
-  /// Display all results
-  //void displayAllResults();
-
   /// Display results from document
   /// \param theDoc a document
   void displayDocumentResults(DocumentPtr theDoc);
@@ -448,12 +414,16 @@ private:
   /// Display results from a group
   void displayGroupResults(DocumentPtr theDoc, std::string theGroup);
 
- private slots:
-  /// SLOT, that is called after the operation is started. Update workshop state according to
-  /// the started operation, e.g. visualizes the property panel and connect to it.
-  /// \param theOpertion a started operation
-  // void onOperationStarted(ModuleBase_Operation* theOperation);
+  /// Insert folder object before currently selected feature
+  void insertFeatureFolder();
+
+  /// Insert an object to a folder above or below
+  void insertToFolder(bool isBefore);
+
+  /// Insert an object to a folder above or below
+  void moveOutFolder(bool isBefore);
 
+ private slots:
   /// SLOT, that is called after the operation is resumed. Update workshop state according to
   /// the started operation, e.g. visualizes the property panel and connect to it.
   /// \param theOpertion a resumed operation
@@ -493,7 +463,7 @@ private:
   void onPreviewActionClicked();
 
  private:
-   /// Init menu
+  /// Init menu
   void initMenu();
 
   /// Register validators
@@ -517,42 +487,47 @@ private:
   // Creates Dock widgets: Object browser and Property panel
   void createDockWidgets();
 
-  //! Extends undo/redo toolbutton's with history menu
-  //! \param theObject - in the OpenParts it is a QToolButton by itself,
-  //! in salome mode - QAction that creates a button.
-  //! \param theSignal - void "updateUndoHistory" or "updateRedoHistory" SIGNAL;
-  //! \param theSlot - onUndo(int) or onRedo(int) SLOT
+  /// Extends undo/redo toolbutton's with history menu
+  /// \param theObject - in the OpenParts it is a QToolButton by itself,
+  /// in salome mode - QAction that creates a button.
+  /// \param theSignal - void "updateUndoHistory" or "updateRedoHistory" SIGNAL;
+  /// \param theSlot - onUndo(int) or onRedo(int) SLOT
   void addHistoryMenu(QObject* theObject, const char* theSignal, const char* theSlot);
 
-  //! Creates list of actions (commands) by given history list from session
+  /// Creates list of actions (commands) by given history list from session
   QList<ActionInfo> processHistoryList(const std::list<std::string>&) const;
 
+  /// Pefrom Undo/Redo and necessary workshop updates(viewer, browser, actions state)
+  /// \param theActionType a type of the action (Undo or Redo)
+  /// \param theTimes number of applies the given action
+  void processUndoRedo(const ModuleBase_ActionType theActionType, int theTimes);
+
 private:
 #ifndef HAVE_SALOME
-  AppElements_MainWindow* myMainWindow;
+  AppElements_MainWindow* myMainWindow; ///< desktop window
 #endif
 
-  ModuleBase_IModule* myModule;
-  XGUI_ErrorMgr* myErrorMgr;
-  XGUI_ObjectsBrowser* myObjectBrowser;
-  XGUI_PropertyPanel* myPropertyPanel;
-  XGUI_SelectionMgr* mySelector;
-  XGUI_Displayer* myDisplayer;
+  ModuleBase_IModule* myModule; ///< current module
+  XGUI_ErrorMgr* myErrorMgr; ///< updator of error message
+  XGUI_ObjectsBrowser* myObjectBrowser; ///< data tree widget
+  XGUI_PropertyPanel* myPropertyPanel; ///< container of feature attributes widgets
+  XGUI_FacesPanel* myFacesPanel; ///< panel for hide object faces
+  XGUI_SelectionMgr* mySelector; ///< handler of selection processing
+  XGUI_SelectionActivate* mySelectionActivate; /// manager of selection activating
+  XGUI_Displayer* myDisplayer; ///< handler of objects display
   XGUI_OperationMgr* myOperationMgr;  ///< manager to manipulate through the operations
-  XGUI_ActionsMgr* myActionsMgr;
+  XGUI_ActionsMgr* myActionsMgr; ///< manager of workshop actions
+  XGUI_ActiveControlMgr* myActiveControlMgr; ///< manager to have none or one active control
   XGUI_MenuMgr* myMenuMgr; ///< manager to build menu/tool bar using order defined in XML
-  XGUI_SalomeConnector* mySalomeConnector;
-  XGUI_ErrorDialog* myErrorDlg;
-  XGUI_ViewerProxy* myViewerProxy;
-  XGUI_ContextMenuMgr* myContextMenuMgr;
-  XGUI_ModuleConnector* myModuleConnector;
-  XGUI_WorkshopListener* myEventsListener;
-
-  QString myCurrentDir;
-
-  QIntList myViewerSelMode;
-
-  Config_DataModelReader* myDataModelXMLReader;
+  XGUI_SalomeConnector* mySalomeConnector; ///< connector to SALOME module interface
+  XGUI_ErrorDialog* myErrorDlg; ///< dialog to show information of occured error events
+  XGUI_ViewerProxy* myViewerProxy; ///< connector to SALOME viewer interface
+  XGUI_ContextMenuMgr* myContextMenuMgr; ///< manager of context menu build
+  XGUI_ModuleConnector* myModuleConnector; ///< implementation of ModuleBase_IWorkshop
+  XGUI_WorkshopListener* myEventsListener; ///< processing of events
+  QString myCurrentDir; ///< cached the last open directory
+  QIntList myViewerSelMode; ///< selection modes set in the viewer
+  Config_DataModelReader* myDataModelXMLReader; ///< XML reader of data model
 };
 
 #endif
index d1b34d181e594d4a0f0742629db393e22c41b380..fd5c11630267e7a01f080d7075db5377249bec53 100755 (executable)
 //
 
 #include "XGUI_WorkshopListener.h"
-#include "XGUI_Workshop.h"
-#include "XGUI_Displayer.h"
-#include "XGUI_ErrorMgr.h"
-#include "XGUI_OperationMgr.h"
-#include "XGUI_SalomeConnector.h"
-#include "XGUI_ActionsMgr.h"
-#include "XGUI_PropertyPanel.h"
-#include "XGUI_ModuleConnector.h"
-#include "XGUI_QtEvents.h"
-#include "XGUI_SelectionMgr.h"
 
 #ifndef HAVE_SALOME
 #include <AppElements_MainWindow.h>
 #endif
 
-#include <ModuleBase_IModule.h>
-#include <ModuleBase_Events.h>
+#include <Config_FeatureMessage.h>
+#include <Config_PointerMessage.h>
+#include <Config_Keywords.h>
+
+#include <Events_InfoMessage.h>
+#include <Events_Loop.h>
+#include <Events_LongOp.h>
 
 #include <ModelAPI_Object.h>
 #include <ModelAPI_Events.h>
 #include <ModelAPI_ResultCompSolid.h>
 #include <ModelAPI_Tools.h>
 
-#include <Events_Loop.h>
-#include <Events_LongOp.h>
-
+#include <ModuleBase_Events.h>
+#include <ModuleBase_IModule.h>
+#include <ModuleBase_IViewer.h>
 #include <ModuleBase_IWorkshop.h>
-
 #include <ModuleBase_Operation.h>
 #include <ModuleBase_OperationDescription.h>
 #include <ModuleBase_OperationFeature.h>
 #include <ModuleBase_Tools.h>
-#include <ModuleBase_IViewer.h>
 #include <ModuleBase_WidgetSelector.h>
 
-#include <Config_FeatureMessage.h>
-#include <Config_PointerMessage.h>
-#include <Config_Keywords.h>
-#include <Events_InfoMessage.h>
+#include "XGUI_ActionsMgr.h"
+#include "XGUI_Displayer.h"
+#include "XGUI_ErrorMgr.h"
+#include "XGUI_FacesPanel.h"
+#include "XGUI_OperationMgr.h"
+#include "XGUI_ModuleConnector.h"
+#include "XGUI_PropertyPanel.h"
 
+#include "XGUI_QtEvents.h"
+#include "XGUI_SalomeConnector.h"
+#include "XGUI_SelectionMgr.h"
+#include "XGUI_Workshop.h"
+
+#include <QAction>
 #include <QApplication>
 #include <QMainWindow>
 #include <QThread>
-#include <QAction>
 
 #ifdef _DEBUG
 #include <QDebug>
@@ -110,6 +111,9 @@ void XGUI_WorkshopListener::initializeEventListening()
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED));
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_EMPTY_AIS_PRESENTATION));
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION));
+
+  aLoop->registerListener(this, Events_Loop::eventByName("FinishOperation"));
+  aLoop->registerListener(this, Events_Loop::eventByName("AbortOperation"));
 }
 
 //******************************************************
@@ -157,7 +161,9 @@ void XGUI_WorkshopListener::processEvent(const std::shared_ptr<Events_Message>&
       if (aWidgetSelector)
         workshop()->selector()->setSelected(aWidgetSelector->getAttributeSelection());
     }
-  }
+  } else if (theMessage->eventID() == Events_Loop::eventByName("FinishOperation")/* ||
+             theMessage->eventID() == Events_Loop::eventByName("AbortOperation")*/)
+    workshop()->facesPanel()->reset(false); // do not flush redisplay, it is flushed after event
 
   //Update property panel on corresponding message. If there is no current operation (no
   //property panel), or received message has different feature to the current - do nothing.
index 879fa44168e43ce829408a17217999722591e62c..913ca9b006711b083ec2e68edc21483ebeac384f 100644 (file)
      <file>pictures/face32.png</file>
      <file>pictures/edge32.png</file>
      <file>pictures/vertex32.png</file>
+     <file>pictures/features_folder.png</file>
+     <file>pictures/create_folder.png</file>
+     <file>pictures/insert_folder_after.png</file>
+     <file>pictures/insert_folder_before.png</file>
+     <file>pictures/move_out_after.png</file>
+     <file>pictures/move_out_before.png</file>
+     <file>pictures/selection.png</file>
  </qresource>
  </RCC>
diff --git a/src/XGUI/pictures/create_folder.png b/src/XGUI/pictures/create_folder.png
new file mode 100644 (file)
index 0000000..371d86d
Binary files /dev/null and b/src/XGUI/pictures/create_folder.png differ
index df57123b2cd55f6eec3b6d395294c8e31fb27482..a41797ea97d70df384c9638d70d8694ab42ea8dd 100644 (file)
Binary files a/src/XGUI/pictures/eyeclosed.png and b/src/XGUI/pictures/eyeclosed.png differ
index e05e411fbb2ef9989a8b5a25ab4066900efbc35e..95843a5e5c608f3afa62365e17aca92228117d9e 100644 (file)
Binary files a/src/XGUI/pictures/eyemiclosed.png and b/src/XGUI/pictures/eyemiclosed.png differ
index e578fe6d2ee9f6443b03fb575341e3b0dc6cec2d..acb26c47e25345782efa6dedf890e6f57099d8d9 100644 (file)
Binary files a/src/XGUI/pictures/eyeopen.png and b/src/XGUI/pictures/eyeopen.png differ
diff --git a/src/XGUI/pictures/features_folder.png b/src/XGUI/pictures/features_folder.png
new file mode 100644 (file)
index 0000000..055992b
Binary files /dev/null and b/src/XGUI/pictures/features_folder.png differ
diff --git a/src/XGUI/pictures/insert_folder_after.png b/src/XGUI/pictures/insert_folder_after.png
new file mode 100644 (file)
index 0000000..f10a6c9
Binary files /dev/null and b/src/XGUI/pictures/insert_folder_after.png differ
diff --git a/src/XGUI/pictures/insert_folder_before.png b/src/XGUI/pictures/insert_folder_before.png
new file mode 100644 (file)
index 0000000..2563478
Binary files /dev/null and b/src/XGUI/pictures/insert_folder_before.png differ
diff --git a/src/XGUI/pictures/move_out_after.png b/src/XGUI/pictures/move_out_after.png
new file mode 100644 (file)
index 0000000..6adcf64
Binary files /dev/null and b/src/XGUI/pictures/move_out_after.png differ
diff --git a/src/XGUI/pictures/move_out_before.png b/src/XGUI/pictures/move_out_before.png
new file mode 100644 (file)
index 0000000..cf248a6
Binary files /dev/null and b/src/XGUI/pictures/move_out_before.png differ
diff --git a/src/XGUI/pictures/selection.png b/src/XGUI/pictures/selection.png
new file mode 100644 (file)
index 0000000..4cc4088
Binary files /dev/null and b/src/XGUI/pictures/selection.png differ
index 56fcd4ed2f865b5a945e6f2ca9cfffbdff13ea94..fcd1406ab78bcd4e861c805a1b7bf62230a992c1 100644 (file)
@@ -181,16 +181,16 @@ Translation_6 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_
 Translation_7 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_7_1")], model.selection("EDGE", "Edge_1_1"), 15)
 Translation_8 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_8_1")], model.selection("EDGE", "Box_8_1/Right&Box_8_1/Top"), 15)
 Translation_9 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_9_1")], model.selection("EDGE", "PartSet/Axis_4"), 15)
-Translation_10 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Box_10_1")], model.selection("EDGE", "PartSet/OZ"), 15)
-Translation_11 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Box_11_1")], model.selection("EDGE", "PartSet/OZ"), 0)
-Translation_12 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Box_12_1")], model.selection("EDGE", "PartSet/OZ"), -15)
-Translation_13 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Box_13_1")], model.selection("EDGE", "InvalidName"), 15)
-Translation_14 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Box_14_1")], model.selection("EDGE", "PartSet/OZ"), "d")
-Translation_15 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Box_15_1")], model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), 50)
-Translation_16 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Box_16_1")], model.selection("EDGE", "Edge_1_1"), 50)
-#Translation_17 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "MultiTranslation_8_1")], model.selection("EDGE", "MultiTranslation_8_1/Translated_Edge_8_8"), 50)
-Translation_17 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Box_17_1")], model.selection("EDGE", "Box_17_1/Translated_Face_3_4&Box_17_1/Translated_Face_3_1"), 50)
-Translation_18 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Box_18_1")], model.selection("EDGE", "PartSet/Axis_4"), 50)
+Translation_10 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_1_1")], model.selection("EDGE", "PartSet/OZ"), 15)
+Translation_11 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_2_1")], model.selection("EDGE", "PartSet/OZ"), 0)
+Translation_12 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_3_1")], model.selection("EDGE", "PartSet/OZ"), -15)
+Translation_13 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_4_1")], model.selection("EDGE", "InvalidName"), 15)
+Translation_14 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_5_1")], model.selection("EDGE", "PartSet/OZ"), "d")
+Translation_15 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_6_1")], model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), 50)
+Translation_16 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_7_1")], model.selection("EDGE", "Edge_1_1"), 50)
+#Translation_17 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_8_1")], model.selection("EDGE", "LinearCopy_8_1/Translated_Edge_8_8"), 50)
+Translation_17 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_8_1")], model.selection("EDGE", "LinearCopy_8_1/Translated_Face_3_4&LinearCopy_8_1/Translated_Face_3_1"), 50)
+Translation_18 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_9_1")], model.selection("EDGE", "PartSet/Axis_4"), 50)
 Translation_19 = model.addTranslation(partSet, [model.selection("COMPOUND", "Part_2/")], model.selection("EDGE", "OX"), 15)
 Translation_20 = model.addTranslation(partSet, [model.selection("COMPOUND", "Part_3/")], model.selection("EDGE", "OX"), 0)
 Translation_21 = model.addTranslation(partSet, [model.selection("COMPOUND", "Part_4/")], model.selection("EDGE", "OX"), -15)
index bc030e28bc7a06258c5bb462251a92f0be086632..0f3e3e9e2158dccd1bf4e610aabb06661d4f6d90 100644 (file)
@@ -91,93 +91,93 @@ model.addParameter(Part_1_doc, "d", "15")
 
 # Translation 27
 Translation_27_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 5)
-Intersection_1 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Box_2_1")], [model.selection("SOLID", "Box_1_1")])
-Translation_27 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Box_2_1")], model.selection("EDGE", "PartSet/OX"), 15)
+Intersection_1 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Box_2_1")], [model.selection("SOLID", "Translation_1_1")])
+Translation_27 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Intersection_1_1")], model.selection("EDGE", "PartSet/OX"), 15)
 
 # Translation 28
 Translation_28_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_3_1")], model.selection("EDGE", "PartSet/OX"), 5)
-Intersection_2 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Box_4_1")], [model.selection("SOLID", "Box_3_1")])
-Translation_28 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Box_4_1")], model.selection("EDGE", "PartSet/OX"), 0)
+Intersection_2 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Box_4_1")], [model.selection("SOLID", "Translation_3_1")])
+Translation_28 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Intersection_2_1")], model.selection("EDGE", "PartSet/OX"), 0)
 
 # Translation 29
 Translation_29_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_5_1")], model.selection("EDGE", "PartSet/OX"), 5)
-Intersection_3 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Box_6_1")], [model.selection("SOLID", "Box_5_1")])
-Translation_29 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Box_6_1")], model.selection("EDGE", "PartSet/OX"), -15)
+Intersection_3 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Box_6_1")], [model.selection("SOLID", "Translation_5_1")])
+Translation_29 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Intersection_3_1")], model.selection("EDGE", "PartSet/OX"), -15)
 
 # Translation 30
 Translation_30_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_7_1")], model.selection("EDGE", "PartSet/OX"), 5)
-Intersection_4 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Box_8_1")], [model.selection("SOLID", "Box_7_1")])
-Translation_30 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Box_8_1")], model.selection("EDGE", "InvalidName"), -15)
+Intersection_4 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Box_8_1")], [model.selection("SOLID", "Translation_7_1")])
+Translation_30 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Intersection_4_1")], model.selection("EDGE", "InvalidName"), -15)
 
 # Translation 31
 Translation_31_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_9_1")], model.selection("EDGE", "PartSet/OX"), 5)
-Intersection_5 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Box_10_1")], [model.selection("SOLID", "Box_9_1")])
-Translation_31 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Box_10_1")], model.selection("EDGE", "PartSet/OY"), "d")
+Intersection_5 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Box_10_1")], [model.selection("SOLID", "Translation_9_1")])
+Translation_31 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Intersection_5_1")], model.selection("EDGE", "PartSet/OY"), "d")
 
 # Translation 32
 Translation_32_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_11_1")], model.selection("EDGE", "PartSet/OX"), 5)
-Intersection_6 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Box_12_1")], [model.selection("SOLID", "Box_11_1")])
-Translation_32 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Box_12_1")], model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), 15)
+Intersection_6 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Box_12_1")], [model.selection("SOLID", "Translation_11_1")])
+Translation_32 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Intersection_6_1")], model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), 15)
 
 # Translation 33
 Translation_33_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_13_1")], model.selection("EDGE", "PartSet/OX"), 5)
-Intersection_7 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Box_14_1")], [model.selection("SOLID", "Box_13_1")])
-Translation_33 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Box_14_1")], model.selection("EDGE", "Edge_1_1"), 15)
+Intersection_7 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Box_14_1")], [model.selection("SOLID", "Translation_13_1")])
+Translation_33 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Intersection_7_1")], model.selection("EDGE", "Edge_1_1"), 15)
 
 # Translation 34
 Translation_34_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_15_1")], model.selection("EDGE", "PartSet/OX"), 5)
-Intersection_8 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Box_16_1")], [model.selection("SOLID", "Box_15_1")])
-Translation_34 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Box_16_1")], model.selection("EDGE", "Intersection_8_1_6"), 15)
+Intersection_8 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Box_16_1")], [model.selection("SOLID", "Translation_15_1")])
+Translation_34 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Intersection_8_1")], model.selection("EDGE", "Intersection_8_1_6"), 15)
 
 # Translation 35
 Translation_35_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_17_1")], model.selection("EDGE", "PartSet/OX"), 5)
-Intersection_9 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Box_18_1")], [model.selection("SOLID", "Box_17_1")])
-Translation_35 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Box_18_1")], model.selection("EDGE", "Axis_1"), 15)
+Intersection_9 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Box_18_1")], [model.selection("SOLID", "Translation_17_1")])
+Translation_35 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "Intersection_9_1")], model.selection("EDGE", "Axis_1"), 15)
 
 #Translation 36
 Translation_36_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_19_1")], model.selection("EDGE", "PartSet/OX"), 5)
-Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_20_1"), model.selection("SOLID", "Box_19_1")])
-Translation_36 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Box_20_1")], model.selection("EDGE", "PartSet/OX"), 15)
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_20_1"), model.selection("SOLID", "Translation_19_1")])
+Translation_36 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Partition_1_1")], model.selection("EDGE", "PartSet/OX"), 15)
 
 ## Translation 37
 Translation_37_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_21_1")], model.selection("EDGE", "PartSet/OX"), 5)
-Partition_2 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_22_1"), model.selection("SOLID", "Box_21_1")])
-Translation_37 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Box_22_1")], model.selection("EDGE", "PartSet/OX"), 0)
+Partition_2 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_22_1"), model.selection("SOLID", "Translation_21_1")])
+Translation_37 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Partition_2_1")], model.selection("EDGE", "PartSet/OX"), 0)
 
 ## Translation 38
 Translation_38_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_23_1")], model.selection("EDGE", "PartSet/OX"), 5)
-Partition_3 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_24_1"), model.selection("SOLID", "Box_23_1")])
-Translation_38 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Box_24_1")], model.selection("EDGE", "PartSet/OX"), 0)
+Partition_3 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_24_1"), model.selection("SOLID", "Translation_23_1")])
+Translation_38 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Partition_3_1")], model.selection("EDGE", "PartSet/OX"), 0)
 
 ## Translation 39
 Translation_39_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_25_1")], model.selection("EDGE", "PartSet/OX"), 5)
-Partition_4 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_26_1"), model.selection("SOLID", "Box_25_1")])
-Translation_39 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Box_26_1")], model.selection("EDGE", "InvalidName"), 0)
+Partition_4 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_26_1"), model.selection("SOLID", "Translation_25_1")])
+Translation_39 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Partition_4_1")], model.selection("EDGE", "InvalidName"), 0)
 
 ## Translation 40
 Translation_40_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_27_1")], model.selection("EDGE", "PartSet/OX"), 5)
-Partition_5 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_28_1"), model.selection("SOLID", "Box_27_1")])
-Translation_40 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Box_28_1")], model.selection("EDGE", "PartSet/OX"), "d")
+Partition_5 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_28_1"), model.selection("SOLID", "Translation_27_1")])
+Translation_40 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Partition_5_1")], model.selection("EDGE", "PartSet/OX"), "d")
 
 # Translation 41
 Translation_41_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_29_1")], model.selection("EDGE", "PartSet/OX"), 5)
-Partition_6 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_30_1"), model.selection("SOLID", "Box_29_1")])
-Translation_41 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Box_30_1")], model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), 15)
+Partition_6 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_30_1"), model.selection("SOLID", "Translation_29_1")])
+Translation_41 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Partition_6_1")], model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), 15)
 
 # Translation 42
 Translation_42_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_31_1")], model.selection("EDGE", "PartSet/OX"), 5)
-Partition_7 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_32_1"), model.selection("SOLID", "Box_31_1")])
-Translation_42 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Box_32_1")], model.selection("EDGE", "Edge_1_1"), 15)
+Partition_7 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_32_1"), model.selection("SOLID", "Translation_31_1")])
+Translation_42 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Partition_7_1")], model.selection("EDGE", "Edge_1_1"), 15)
 
 # Translation 43
 Translation_43_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_33_1")], model.selection("EDGE", "PartSet/OX"), 5)
-Partition_8 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_34_1"), model.selection("SOLID", "Box_33_1")])
-Translation_43 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Box_34_1")], model.selection("EDGE", "Partition_8_1_1/Modified_Face_2_5&Partition_8_1_1/Modified_Face_2_2"), 15)
+Partition_8 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_34_1"), model.selection("SOLID", "Translation_33_1")])
+Translation_43 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Partition_8_1")], model.selection("EDGE", "Partition_8_1_1/Modified_Face_2_5&Partition_8_1_1/Modified_Face_2_2"), 15)
 
 # Translation 44
 Translation_44_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_35_1")], model.selection("EDGE", "PartSet/OX"), 5)
-Partition_9 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_36_1"), model.selection("SOLID", "Box_35_1")])
-Translation_44 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Box_36_1")], model.selection("EDGE", "Axis_1"), 15)
+Partition_9 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Box_36_1"), model.selection("SOLID", "Translation_35_1")])
+Translation_44 = model.addTranslation(Part_1_doc, [model.selection("COMPSOLID", "Partition_9_1")], model.selection("EDGE", "Axis_1"), 15)
 model.do()
 model.end()
 
index 7029f13964babaeabd6584891ea42243dfeaba2a..ff88affcd2875f2382cf0a59e0167ed47d689595 100644 (file)
@@ -102,7 +102,6 @@ SketchConstraintCoincidence_15.setName("SketchConstraintCoincidence_16")
 SketchConstraintRadius_3 = Sketch_2.setRadius(SketchCircle_1.results()[1], "50/2")
 model.do()
 ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchCircle_1_2f")], model.selection(), 0, 13, [model.selection("SOLID", "Extrusion_1_1")])
-ExtrusionCut_1.result().setName("ExtrusionCut_1_1")
 Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_1_1/Modfied_4"))
 SketchPoint_3 = Sketch_3.addPoint(model.selection("VERTEX", "ExtrusionCut_1_1/Modfied_2&ExtrusionCut_1_1/Modfied_3&ExtrusionCut_1_1/Modfied_4"))
 SketchLine_11 = Sketch_3.addLine(model.selection("EDGE", "ExtrusionCut_1_1/Modfied_3&ExtrusionCut_1_1/Modfied_4"))
@@ -128,7 +127,6 @@ SketchConstraintCoincidence_23 = Sketch_3.setCoincident(SketchArc_3.results()[1]
 SketchConstraintCoincidence_23.setName("SketchConstraintCoincidence_24")
 model.do()
 ExtrusionFuse_1 = model.addExtrusionFuse(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchArc_3_2f-SketchLine_12f-SketchArc_5_2r")], model.selection(), 5, 0, [model.selection("SOLID", "ExtrusionCut_1_1")])
-ExtrusionFuse_1.result().setName("ExtrusionFuse_1_1")
 Sketch_4 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionFuse_1_1/To_Face_1"))
 SketchPoint_4 = Sketch_4.addPoint(model.selection("VERTEX", "ExtrusionFuse_1_1/Modfied_4&ExtrusionFuse_1_1/Modfied_5&ExtrusionFuse_1_1/To_Face_1"))
 SketchCircle_2 = Sketch_4.addCircle(-15, 35.00000000000001, 5)
@@ -137,7 +135,6 @@ SketchConstraintCoincidence_24.setName("SketchConstraintCoincidence_25")
 SketchConstraintRadius_4 = Sketch_4.setRadius(SketchCircle_2.results()[1], "10/2")
 model.do()
 ExtrusionFuse_2 = model.addExtrusionFuse(Part_1_doc, [model.selection("FACE", "Sketch_4/Face-SketchCircle_2_2f")], model.selection(), 8, 0, [model.selection("SOLID", "ExtrusionFuse_1_1")])
-ExtrusionFuse_2.result().setName("ExtrusionFuse_2_1")
 Sketch_5 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_1_1/Modfied_1"))
 SketchArc_6 = Sketch_5.addArc(model.selection("EDGE", "ExtrusionCut_1_1/Modfied_1&ExtrusionFuse_1_1/Modfied_3"))
 SketchArc_7 = Sketch_5.addArc(-45, 35, -45, 5, -25.41666666666737, 12.27351642784166, False)
@@ -167,7 +164,6 @@ SketchConstraintCoincidence_33 = Sketch_5.setCoincident(SketchArc_9.startPoint()
 SketchConstraintCoincidence_33.setName("SketchConstraintCoincidence_34")
 model.do()
 ExtrusionFuse_3 = model.addExtrusionFuse(Part_1_doc, [model.selection("FACE", "Sketch_5/Face-SketchArc_7_2f-SketchArc_8_2r-SketchLine_13r-SketchArc_9_2r")], model.selection(), 0, 8, [model.selection("SOLID", "ExtrusionFuse_2_1")])
-ExtrusionFuse_3.result().setName("ExtrusionFuse_3_1")
 Sketch_6 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionFuse_3_1/Modfied_3"))
 SketchLine_14 = Sketch_6.addLine(model.selection("EDGE", "ExtrusionFuse_3_1/Modfied_3&Extrusion_1_1/Generated_Face_7"))
 SketchArc_10 = Sketch_6.addArc(55, 35, 55, 15, 35, 35, True)
@@ -198,7 +194,6 @@ SketchConstraintCoincidence_41 = Sketch_6.setCoincident(SketchLine_14.endPoint()
 SketchConstraintCoincidence_41.setName("SketchConstraintCoincidence_42")
 model.do()
 ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_6/Wire-SketchArc_10_2f-SketchLine_16r-SketchLine_18f-SketchLine_19r")], model.selection(), 0, 9, [model.selection("SOLID", "ExtrusionFuse_3_1")])
-ExtrusionCut_2.result().setName("ExtrusionCut_2_1")
 Sketch_7 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_2_1/Modfied_4"))
 SketchCircle_4 = Sketch_7.addCircle(45, 35, 5)
 SketchLine_20 = Sketch_7.addLine(model.selection("EDGE", "ExtrusionCut_2_1/Modfied_2&ExtrusionCut_2_1/Modfied_4"))
@@ -214,7 +209,6 @@ SketchConstraintCoincidence_43.setName("SketchConstraintCoincidence_44")
 SketchConstraintHorizontal_4 = Sketch_7.setHorizontal(SketchLine_21.result())
 model.do()
 ExtrusionCut_3 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_7/Face-SketchCircle_4_2f")], model.selection(), model.selection(), 0, model.selection("FACE", "Extrusion_1_1/From_Face_1"), 0, [model.selection("SOLID", "ExtrusionCut_2_1")])
-ExtrusionCut_3.result().setName("ExtrusionCut_3_1")
 Sketch_8 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_4"))
 SketchLine_22 = Sketch_8.addLine(55, 25, 5.000000000000002, 25)
 SketchLine_23 = Sketch_8.addLine(5.000000000000002, 25, 5.000000000000002, 13)
@@ -243,7 +237,6 @@ SketchConstraintCoincidence_49 = Sketch_8.setCoincident(SketchLine_22.startPoint
 SketchConstraintCoincidence_49.setName("SketchConstraintCoincidence_50")
 model.do()
 ExtrusionCut_4 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_8/Face-SketchLine_22f-SketchLine_23f-SketchLine_24f-SketchLine_25f")], model.selection(), model.selection(), 0, model.selection("FACE", "Extrusion_1_1/Generated_Face_8"), 0, [model.selection("SOLID", "ExtrusionCut_3_1")])
-ExtrusionCut_4.result().setName("ExtrusionCut_4_1")
 Sketch_9 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionFuse_1_1/Modfied_2"))
 SketchLine_28 = Sketch_9.addLine(25, -45, 18.44853578320836, -63)
 SketchLine_29 = Sketch_9.addLine(model.selection("EDGE", "ExtrusionFuse_1_1/Modfied_2&ExtrusionCut_4_1/Modfied_6"))
@@ -266,7 +259,6 @@ SketchConstraintCoincidence_55 = Sketch_9.setCoincident(SketchLine_28.startPoint
 SketchConstraintCoincidence_55.setName("SketchConstraintCoincidence_56")
 model.do()
 ExtrusionCut_5 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_9/Face-SketchLine_28f-SketchLine_31f-SketchLine_32f")], model.selection(), model.selection(), 0, model.selection("FACE", "ExtrusionCut_4_1/Modfied_3"), 0, [model.selection("SOLID", "ExtrusionCut_4_1")])
-ExtrusionCut_5.result().setName("ExtrusionCut_5_1")
 Sketch_10 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_5_1/Modfied_1"))
 SketchCircle_5 = Sketch_10.addCircle(-6.000000000000002, 4.999999999999997, 5)
 SketchLine_33 = Sketch_10.addLine(model.selection("EDGE", "ExtrusionCut_2_1/Modfied_3&ExtrusionCut_5_1/Modfied_1"))
@@ -276,7 +268,6 @@ SketchConstraintDistance_12 = Sketch_10.setDistance(SketchCircle_5.result(), Ske
 SketchConstraintRadius_7 = Sketch_10.setRadius(SketchCircle_5.results()[1], "10/2")
 model.do()
 ExtrusionCut_6 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_10/Face-SketchCircle_5_2f")], model.selection(), model.selection(), 0, model.selection("FACE", "Extrusion_1_1/Generated_Face_12"), 0, [model.selection("SOLID", "ExtrusionCut_5_1")])
-ExtrusionCut_6.result().setName("ExtrusionCut_6_1")
 model.do()
 
 # Test reexecution after parameter change
index 8bed73f7c2ca3fc2b5251eecc66efd1c4f38ef93..c2252d669c97fb0bc88488a24d9630b09f7ad8ac 100644 (file)
@@ -141,7 +141,6 @@ model.do()
 Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchCircle_1_2f")], model.selection(), 75, 45)
 Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_3")], model.selection(), 22, 22)
 Boolean_1 = model.addCommon(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], [model.selection("SOLID", "Extrusion_2_1")])
-Boolean_1.result().setName("Boolean_1_1")
 Sketch_4 = model.addSketch(Part_1_doc, model.selection("FACE", "PartSet/XOY"))
 SketchLine_20 = Sketch_4.addLine(-4, 38.00000000000001, -4, 21.26617031813674)
 SketchLine_20.setName("SketchLine_36")
@@ -354,11 +353,9 @@ model.do()
 Extrusion_3 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_4")], model.selection(), 50, 30)
 Extrusion_4 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_3")], model.selection(), 22, 22)
 Boolean_2 = model.addCommon(Part_1_doc, [model.selection("SOLID", "Extrusion_3_1")], [model.selection("SOLID", "Extrusion_4_1")])
-Boolean_2.result().setName("Boolean_2_1")
 Extrusion_5 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_3")], model.selection(), 22, 22)
 Extrusion_6 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchCircle_2_2f")], model.selection(), 75, 40)
 Boolean_3 = model.addCommon(Part_1_doc, [model.selection("SOLID", "Extrusion_6_1")], [model.selection("SOLID", "Extrusion_5_1")])
-Boolean_3.result().setName("Boolean_3_1")
 Sketch_5 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
 SketchLine_38 = Sketch_5.addLine(44, 3.464101615137769, 17.52573586555855, 49.31887218898888)
 SketchLine_38.setName("SketchLine_41")
@@ -492,11 +489,8 @@ SketchConstraintCoincidence_90.setName("SketchConstraintCoincidence_94")
 model.do()
 Extrusion_7 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_6/Face-SketchLine_55r-SketchLine_44r-SketchLine_52r-SketchLine_53r-SketchLine_54r-SketchLine_47r-SketchLine_48r-SketchLine_49r-SketchArc_12_2r-SketchArc_13_2r")], model.selection(), 0, 40)
 Boolean_4 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Boolean_1_1")], [model.selection("SOLID", "Boolean_2_1")])
-Boolean_4.result().setName("Boolean_4_1")
 Boolean_5 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Boolean_4_1")], [model.selection("SOLID", "Extrusion_7_1")])
-Boolean_5.result().setName("Boolean_5_1")
 Boolean_6 = model.addCut(Part_1_doc, [model.selection("SOLID", "Boolean_5_1")], [model.selection("SOLID", "Boolean_3_1")])
-Boolean_6.result().setName("Boolean_6_1")
 Extrusion_8 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_10r-SketchLine_11r-SketchLine_8r-SketchLine_3r-SketchLine_9r-SketchLine_6r-SketchArc_1_2r-SketchArc_2_2f")], model.selection(), 55, 55)
 Sketch_7 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_8_1/Generated_Face_1"))
 SketchLine_54 = Sketch_7.addLine(55, -9.237604307034024, 55, -60)
@@ -619,12 +613,11 @@ SketchConstraintDistance_33 = Sketch_7.setDistance(SketchCircle_7.center(), Sket
 SketchConstraintDistance_34 = Sketch_7.setDistance(SketchCircle_7.center(), SketchLine_66.result(), 11)
 model.do()
 ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_7/Wire-SketchLine_66f-SketchLine_67f-SketchLine_68f-SketchLine_60f-SketchLine_61f-SketchLine_62f-SketchLine_63f-SketchLine_64f-SketchArc_14_2r-SketchArc_15_2r"), model.selection("FACE", "Sketch_7/Face-SketchCircle_4_2f"), model.selection("FACE", "Sketch_7/Face-SketchCircle_5_2f"), model.selection("FACE", "Sketch_7/Face-SketchCircle_7_2f"), model.selection("FACE", "Sketch_7/Face-SketchCircle_6_2f")], model.selection(), 0, 10, [model.selection("SOLID", "Extrusion_8_1")])
-ExtrusionCut_1.result().setName("ExtrusionCut_1_1")
 Sketch_8 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_8_1/Generated_Face_3"))
 SketchLine_67 = Sketch_8.addLine(55, -34.06366588218793, 55, 66.69872981077805)
 SketchLine_67.setName("SketchLine_79")
 SketchLine_67.result().setName("SketchLine_79")
-SketchPoint_10 = Sketch_8.addPoint(model.selection("VERTEX", "ExtrusionCut_1_1/Modfied_6&ExtrusionCut_1_1/Modfied_1&Extrusion_8_1/Generated_Face_3"))
+SketchPoint_10 = Sketch_8.addPoint(model.selection("VERTEX", "ExtrusionCut_1_1/Modfied_4&ExtrusionCut_1_1/Modfied_1&Extrusion_8_1/Generated_Face_3"))
 SketchLine_68 = Sketch_8.addLine(55, -34.06366588218793, 55, 76.69872981077803)
 SketchLine_68.setName("SketchLine_70")
 SketchLine_68.result().setName("SketchLine_70")
@@ -643,7 +636,7 @@ SketchLine_70.result().setName("SketchLine_71")
 SketchLine_70.setAuxiliary(True)
 SketchConstraintCoincidence_118 = Sketch_8.setCoincident(SketchLine_68.endPoint(), SketchLine_70.startPoint())
 SketchConstraintCoincidence_118.setName("SketchConstraintCoincidence_122")
-SketchPoint_12 = Sketch_8.addPoint(model.selection("VERTEX", "ExtrusionCut_1_1/Modfied_3&Extrusion_8_1/Generated_Face_3&Extrusion_8_1/Generated_Face_4"))
+SketchPoint_12 = Sketch_8.addPoint(model.selection("VERTEX", "ExtrusionCut_1_1/Modfied_2&Extrusion_8_1/Generated_Face_3&Extrusion_8_1/Generated_Face_4"))
 SketchConstraintCoincidence_119 = Sketch_8.setCoincident(SketchLine_70.endPoint(), SketchPoint_12.result())
 SketchConstraintCoincidence_119.setName("SketchConstraintCoincidence_123")
 SketchLine_71 = Sketch_8.addLine(-55, 66.69872976783566, -55, -34.06366588218793)
@@ -653,7 +646,7 @@ SketchLine_72 = Sketch_8.addLine(-55, 76.69872981077803, -55, -34.06366588218793
 SketchLine_72.setAuxiliary(True)
 SketchConstraintCoincidence_120 = Sketch_8.setCoincident(SketchLine_70.endPoint(), SketchLine_72.startPoint())
 SketchConstraintCoincidence_120.setName("SketchConstraintCoincidence_124")
-SketchPoint_13 = Sketch_8.addPoint(model.selection("VERTEX", "ExtrusionCut_1_1/Modfied_6&ExtrusionCut_1_1/Modfied_3&Extrusion_8_1/Generated_Face_3"))
+SketchPoint_13 = Sketch_8.addPoint(model.selection("VERTEX", "ExtrusionCut_1_1/Modfied_4&ExtrusionCut_1_1/Modfied_2&Extrusion_8_1/Generated_Face_3"))
 SketchConstraintCoincidence_121 = Sketch_8.setCoincident(SketchLine_72.endPoint(), SketchPoint_13.result())
 SketchConstraintCoincidence_121.setName("SketchConstraintCoincidence_125")
 SketchLine_73 = Sketch_8.addLine(-55, -34.06366588218793, -83.25521566485324, -34.06366588218793)
@@ -768,9 +761,7 @@ SketchConstraintDistance_44 = Sketch_8.setDistance(SketchArc_18.startPoint(), Sk
 SketchConstraintDistance_44.setName("SketchConstraintDistance_45")
 model.do()
 ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_8/Face-SketchLine_79r-SketchLine_80r-SketchLine_81r-SketchLine_73r-SketchLine_74r-SketchLine_75r-SketchLine_76r-SketchLine_77r-SketchArc_16_2r-SketchArc_17_2r"), model.selection("WIRE", "Sketch_8/Wire-SketchCircle_8_2f"), model.selection("WIRE", "Sketch_8/Wire-SketchCircle_9_2f"), model.selection("WIRE", "Sketch_8/Wire-SketchArc_19_2f-SketchArc_18_2f-SketchLine_82f-SketchLine_83r")], model.selection(), 0, 10, [model.selection("SOLID", "ExtrusionCut_1_1")])
-ExtrusionCut_2.result().setName("ExtrusionCut_2_1")
 Boolean_7 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Boolean_6_1")], [model.selection("SOLID", "ExtrusionCut_2_1")])
-Boolean_7.result().setName("Boolean_7_1")
 model.do()
 
 # Test reexecution after parameter change
index fc234273f2010e96e3b1491f6c0df56bc22c9f8c..393843543a7127c23fcbae3abeb37b5fd2f3a98d 100644 (file)
@@ -29,7 +29,6 @@ model.addParameter(partSet, "Rod", "12")
 model.addParameter(partSet, "Thickness", "25")
 Part_1 = model.addPart(partSet)
 Part_1.setName("Body")
-Part_1.result().setName("Part_1")
 Part_1_doc = Part_1.document()
 model.addParameter(Part_1_doc, "Radius", "50", "Radius of the body")
 model.addParameter(Part_1_doc, "Width", "25", "Width of body arms")
@@ -230,10 +229,8 @@ SketchConstraintDistance_9.setName("SketchConstraintDistance_8")
 model.do()
 Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchLine_10r-SketchLine_11r-SketchArc_3_2f-SketchArc_4_2f"), model.selection("WIRE", "Sketch_2/Wire-SketchLine_14r-SketchArc_7_2f-SketchLine_15r-SketchArc_8_2f"), model.selection("FACE", "Sketch_2/Face-SketchLine_12r-SketchArc_5_2f-SketchLine_13r-SketchArc_6_2f"), model.selection("FACE", "Sketch_2/Face-SketchLine_19f-SketchLine_20f-SketchLine_21f-SketchArc_10_2f"), model.selection("FACE", "Sketch_2/Face-SketchLine_16f-SketchLine_17f-SketchLine_18f-SketchArc_9_2f"), model.selection("WIRE", "Sketch_2/Wire-SketchLine_22f-SketchLine_23f-SketchLine_24f-SketchArc_11_2f")], model.selection(), model.selection(), 10, model.selection("FACE", "Revolution_1_1/Generated_Face_5"), 10)
 Boolean_1 = model.addCut(Part_1_doc, [model.selection("SOLID", "Revolution_1_1")], [model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_1_4"), model.selection("SOLID", "Extrusion_1_5")])
-Boolean_1.result().setName("Boolean_1_1")
 Boolean_2 = model.addCut(Part_1_doc, [model.selection("SOLID", "Boolean_1_1")], [model.selection("SOLID", "Extrusion_1_2"), model.selection("SOLID", "Extrusion_1_3"), model.selection("SOLID", "Extrusion_1_6")])
-Boolean_2.result().setName("Boolean_2_1")
-Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Boolean_2_1/Modified_7"), model.selection("FACE", "Boolean_2_1/Modified_9"))
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Boolean_2_1/Modified_Face_7"), model.selection("FACE", "Boolean_2_1/Modified_Face_9"))
 Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
 SketchCircle_3 = Sketch_3.addCircle(25, -10, 4)
 SketchCircle_4 = Sketch_3.addCircle(40, -10, 4)
@@ -246,7 +243,7 @@ SketchConstraintDistance_10 = Sketch_3.setDistance(SketchCircle_3.center(), Sket
 SketchConstraintDistance_10.setName("SketchConstraintDistance_9")
 SketchConstraintDistance_11 = Sketch_3.setDistance(SketchCircle_4.center(), SketchLine_28.result(), 40)
 SketchConstraintDistance_11.setName("SketchConstraintDistance_10")
-SketchProjection_1 = Sketch_3.addProjection(model.selection("EDGE", "Boolean_2_1/Modified_23&Boolean_2_1/Modified_7"))
+SketchProjection_1 = Sketch_3.addProjection(model.selection("EDGE", "Boolean_2_1/Modified_Face_17&Boolean_2_1/Modified_Face_7"))
 SketchLine_29 = SketchProjection_1.createdFeature()
 SketchLine_29.setName("SketchLine_26")
 SketchLine_29.result().setName("SketchLine_26")
@@ -255,25 +252,17 @@ SketchConstraintDistance_12.setName("SketchConstraintDistance_11")
 SketchConstraintDistance_13 = Sketch_3.setDistance(SketchCircle_3.center(), SketchLine_29.result(), 10)
 SketchConstraintDistance_13.setName("SketchConstraintDistance_12")
 model.do()
-Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchCircle_3_2f"), model.selection("WIRE", "Sketch_3/Wire-SketchCircle_4_2f")], model.selection(), model.selection("FACE", "Boolean_1_1/Modified_6"), 5, model.selection("FACE", "Boolean_1_1/Modified_8"), 5)
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchCircle_3_2f"), model.selection("WIRE", "Sketch_3/Wire-SketchCircle_4_2f")], model.selection(), model.selection("FACE", "Boolean_1_1/Modified_Face_6"), 5, model.selection("FACE", "Boolean_1_1/Modified_Face_8"), 5)
 Boolean_3 = model.addCut(Part_1_doc, [model.selection("SOLID", "Boolean_2_1")], [model.selection("SOLID", "Extrusion_2_1"), model.selection("SOLID", "Extrusion_2_2")])
-Boolean_3.result().setName("Boolean_3_1")
 Recover_1 = model.addRecover(Part_1_doc, Boolean_3, [Extrusion_2.results()[1], Extrusion_2.result()])
 Rotation_1 = model.addRotation(Part_1_doc, [model.selection("SOLID", "Recover_1_1"), model.selection("SOLID", "Recover_1_2")], model.selection("EDGE", "PartSet/OZ"), 120)
-Rotation_1.result().setName("Rotation_1_1")
-Rotation_1.results()[1].setName("Rotation_1_2")
 Boolean_4 = model.addCut(Part_1_doc, [model.selection("SOLID", "Boolean_3_1")], [model.selection("SOLID", "Rotation_1_1"), model.selection("SOLID", "Rotation_1_2")])
-Boolean_4.result().setName("Boolean_4_1")
 Recover_2 = model.addRecover(Part_1_doc, Boolean_4, [Rotation_1.results()[1], Rotation_1.result()])
 Rotation_2 = model.addRotation(Part_1_doc, [model.selection("SOLID", "Recover_2_1"), model.selection("SOLID", "Recover_2_2")], model.selection("EDGE", "PartSet/OZ"), 120)
-Rotation_2.result().setName("Rotation_2_1")
-Rotation_2.results()[1].setName("Rotation_2_2")
 Boolean_5 = model.addCut(Part_1_doc, [model.selection("SOLID", "Boolean_4_1")], [model.selection("SOLID", "Rotation_2_2"), model.selection("SOLID", "Rotation_2_1")])
-Boolean_5.result().setName("Boolean_5_1")
 model.do()
 Part_2 = model.addPart(partSet)
 Part_2.setName("Arm 1")
-Part_2.result().setName("Part_2")
 Part_2_doc = Part_2.document()
 model.addParameter(Part_2_doc, "a", "7.5")
 model.addParameter(Part_2_doc, "b", "12.5")
@@ -508,32 +497,24 @@ model.do()
 Face_1 = model.addFace(Part_2_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchArc_1_2f-SketchArc_4_2f-SketchArc_5_2f-SketchArc_6_2f-SketchArc_7_2f-SketchArc_8_2f-SketchArc_9_2f-SketchArc_10_2f")])
 Axis_4 = model.addAxis(Part_2_doc, model.selection("FACE", "PartSet/XOZ"), model.selection("VERTEX", "Sketch_2/Vertex-SketchArc_3-SketchLine_20s"))
 Rotation_3 = model.addRotation(Part_2_doc, [model.selection("FACE", "Face_1_1")], model.selection("EDGE", "Axis_1"), -43.8752)
-Rotation_3.result().setName("Rotation_1_1")
 Pipe_1 = model.addPipe(Part_2_doc, [model.selection("FACE", "Rotation_1_1")], model.selection("EDGE", "Sketch_2/Edge-SketchArc_3_2"))
-Pipe_1.result().setName("Pipe_1_1")
 Extrusion_3 = model.addExtrusion(Part_2_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchCircle_2_2f"), model.selection("WIRE", "Sketch_2/Wire-SketchLine_14r-SketchLine_15r-SketchLine_16r-SketchLine_17r")], model.selection(), "Gap/2", "Gap/2")
 Boolean_6 = model.addFuse(Part_2_doc, [model.selection("SOLID", "Pipe_1_1")], [model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_1_2")])
-Boolean_6.result().setName("Boolean_1_1")
 Extrusion_4 = model.addExtrusion(Part_2_doc, [model.selection("FACE", "Sketch_2/Face-SketchCircle_3_2f")], model.selection(), "Gap", "Gap")
 Boolean_7 = model.addCut(Part_2_doc, [model.selection("SOLID", "Boolean_1_1")], [model.selection("SOLID", "Extrusion_2_1")])
-Boolean_7.result().setName("Boolean_2_1")
 Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Boolean_2_1")], model.selection("VERTEX", "Sketch_2/Vertex-SketchArc_3_2s"), model.selection("VERTEX", "Sketch_2/Vertex-SketchLine_21e"))
-Translation_1.result().setName("Translation_1_1")
 model.do()
 Part_3 = model.duplicatePart(Part_2)
 Part_3.setName("Arm 2")
-Part_3.result().setName("Part_3")
 model.do()
 Part_4 = model.duplicatePart(Part_3)
 Part_4.setName("Arm 3")
-Part_4.result().setName("Part_4")
 model.do()
 Translation_4 = model.addTranslation(partSet, [model.selection("COMPOUND", "Part_2/"), model.selection("COMPOUND", "Part_3/"), model.selection("COMPOUND", "Part_4/")], model.selection("EDGE", "OX"), -40)
 Rotation_6 = model.addRotation(partSet, [model.selection("COMPOUND", "Translation_1_2/")], model.selection("EDGE", "OZ"), 120)
 Rotation_7 = model.addRotation(partSet, [model.selection("COMPOUND", "Translation_1_3/")], model.selection("EDGE", "OZ"), 240)
 Part_5 = model.addPart(partSet)
 Part_5.setName("Rod part")
-Part_5.result().setName("Part_5")
 Part_5_doc = Part_5.document()
 Parameter_H = model.addParameter(partSet, "H", "110")
 Sketch_10 = model.addSketch(Part_5_doc, model.defaultPlane("YOZ"))
@@ -617,9 +598,7 @@ SketchConstraintDistance_37 = Sketch_12.setDistance(SketchLine_108.startPoint(),
 model.do()
 Revolution_3 = model.addRevolution(Part_5_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_14f-SketchLine_15f-SketchLine_16f")], model.selection("EDGE", "PartSet/OZ"), 360, 0)
 Boolean_12 = model.addCut(Part_5_doc, [model.selection("SOLID", "Extrusion_1_1")], [model.selection("SOLID", "Revolution_2_1")])
-Boolean_12.result().setName("Boolean_1_1")
 Boolean_13 = model.addFuse(Part_5_doc, [model.selection("SOLID", "Boolean_1_1"), model.selection("SOLID", "Revolution_1_1")], [])
-Boolean_13.result().setName("Boolean_2_1")
 
 # Test reexecution after parameter change
 Parameter_H.setValue(120)
index 5db7d85c26a5532bf9d71b1e451447822ade6e2e..2bbe3fa8e6075e09c5bb15e1d61b25f2415903e2 100644 (file)
@@ -79,7 +79,6 @@ SketchConstraintCoincidence_8 = Sketch_5.setCoincident(SketchAPI_Line(SketchLine
 SketchConstraintCoincidence_8.setName("SketchConstraintCoincidence_16")
 Extrusion_5.setNestedSketch(Sketch_5)
 Boolean_1 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Extrusion_4_1"), model.selection("SOLID", "Extrusion_5_1"), model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_2_1"), model.selection("SOLID", "Extrusion_3_1")], [])
-Boolean_1.result().setName("Boolean_1_1")
 ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), model.selection("FACE", "Extrusion_5_1/To_Face_1"), 0, model.selection(), 0, [model.selection("SOLID", "Boolean_1_1")])
 Sketch_6 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/From_Face_1"))
 SketchCircle_6 = Sketch_6.addCircle(0, 0, 4.2)
@@ -88,7 +87,6 @@ SketchPoint_2 = Sketch_6.addPoint(model.selection("VERTEX", "PartSet/Origin"))
 SketchConstraintCoincidence_9 = Sketch_6.setCoincident(SketchPoint_2.coordinates(), SketchCircle_6.center())
 SketchConstraintCoincidence_9.setName("SketchConstraintCoincidence_17")
 ExtrusionCut_1.setNestedSketch(Sketch_6)
-ExtrusionCut_1.result().setName("ExtrusionCut_1_1")
 Sketch_7 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_1_1/Modfied_1"))
 SketchCircle_7 = Sketch_7.addCircle(0, -85, 66)
 SketchLine_6 = Sketch_7.addLine(model.selection("EDGE", "PartSet/OY"))
@@ -99,8 +97,7 @@ SketchMultiRotation_1 = Sketch_7.addRotation([SketchCircle_7.results()[1]], Sket
 [SketchCircle_8, SketchCircle_9] = SketchMultiRotation_1.rotated()
 model.do()
 ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_7")], model.selection(), model.selection("FACE", "ExtrusionCut_1_1/Modfied_2"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_1_1")])
-ExtrusionCut_2.result().setName("ExtrusionCut_2_1")
-Sketch_8 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_2_1/Modfied_22"))
+Sketch_8 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_2_1/Modfied_8"))
 SketchLine_7 = Sketch_8.addLine(-2.320957096353877e-016, 11.00000001704673, -7, 11.00000001704673)
 SketchConstraintHorizontal_1 = Sketch_8.setHorizontal(SketchLine_7.result())
 SketchLine_8 = Sketch_8.addLine(-7, 11.00000001704673, -6.329882773485103e-016, 30.00000001704673)
@@ -129,7 +126,7 @@ SketchLine_14.result().setName("SketchLine_13")
 SketchLine_13.setName("SketchLine_16")
 SketchLine_13.result().setName("SketchLine_16")
 model.do()
-ExtrusionCut_3 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_8/Face-SketchLine_7r-SketchLine_8r-SketchLine_10f-SketchLine_11f"), model.selection("FACE", "Sketch_8/Face-SketchLine_16f-SketchLine_17f-SketchLine_18r-SketchLine_19r"), model.selection("FACE", "Sketch_8/Face-SketchLine_12f-SketchLine_13f-SketchLine_14r-SketchLine_15r")], model.selection(), model.selection("FACE", "ExtrusionCut_2_1/Modfied_23"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_2_1")])
+ExtrusionCut_3 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_8/Face-SketchLine_7r-SketchLine_8r-SketchLine_10f-SketchLine_11f"), model.selection("FACE", "Sketch_8/Face-SketchLine_16f-SketchLine_17f-SketchLine_18r-SketchLine_19r"), model.selection("FACE", "Sketch_8/Face-SketchLine_12f-SketchLine_13f-SketchLine_14r-SketchLine_15r")], model.selection(), model.selection("FACE", "ExtrusionCut_2_1/Modfied_9"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_2_1")])
 
 # Test reexecution after parameter change
 Parameter_R.setValue(50)
index 3690c9d3b03974561cbb10fc7d30863bc1d36bcb..42dcf26c4399e669bd1a0cdc903516dec8041e11 100644 (file)
@@ -411,11 +411,8 @@ SketchConstraintRadius_10.setName("SketchConstraintRadius_4")
 model.do()
 Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), "TL/2-3", "TL/2-3")
 ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_2")], model.selection(), 100, 100, [model.selection("SOLID", "Extrusion_1_1")])
-ExtrusionCut_1.result().setName("ExtrusionCut_1_1")
 ExtrusionFuse_1 = model.addExtrusionFuse(Part_1_doc, [model.selection("COMPOUND", "Sketch_3")], model.selection(), "TL/2", "TL/2", [model.selection("SOLID", "ExtrusionCut_1_1")])
-ExtrusionFuse_1.result().setName("ExtrusionFuse_1_1")
 ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_4")], model.selection(), 60, 60, [model.selection("SOLID", "ExtrusionFuse_1_1")])
-ExtrusionCut_2.result().setName("ExtrusionCut_2_1")
 Sketch_5 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
 SketchCircle_5 = Sketch_5.addCircle(30, -41, 7.5)
 SketchLine_37 = Sketch_5.addLine(model.selection("EDGE", "PartSet/OX"))
@@ -542,7 +539,6 @@ SketchConstraintRadius_13 = Sketch_7.setRadius(SketchArc_7.results()[1], "BHPFR"
 SketchConstraintRadius_13.setName("SketchConstraintRadius_8")
 model.do()
 RevolutionFuse_1 = model.addRevolutionFuse(Part_1_doc, [model.selection("COMPOUND", "Sketch_7")], model.selection("EDGE", "Sketch_7/Edge-SketchLine_41"), 360, 0, [model.selection("SOLID", "ExtrusionCut_2_1")])
-RevolutionFuse_1.result().setName("RevolutionFuse_1_1")
 Sketch_8 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
 SketchLine_49 = Sketch_8.addLine(32, 6, 32.50001476412091, 6.000000000000001)
 SketchLine_49.setName("SketchLine_55")
@@ -639,7 +635,6 @@ SketchConstraintRadius_14 = Sketch_8.setRadius(SketchArc_8.results()[1], 1.5)
 SketchConstraintRadius_14.setName("SketchConstraintRadius_9")
 model.do()
 RevolutionFuse_2 = model.addRevolutionFuse(Part_1_doc, [model.selection("FACE", "Sketch_8/Face-SketchLine_55r-SketchLine_49f-SketchLine_50f-SketchLine_56r-SketchLine_52f-SketchLine_53f-SketchArc_7_2r")], model.selection("EDGE", "Sketch_8/Edge-SketchLine_50"), 360, 0, [model.selection("SOLID", "RevolutionFuse_1_1")])
-RevolutionFuse_2.result().setName("RevolutionFuse_2_1")
 Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/YOZ"), 30, True)
 Sketch_9 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_2"))
 SketchLine_57 = Sketch_9.addLine(-32.50001494742042, 5.999999999999998, -32, 6)
@@ -832,9 +827,7 @@ SketchConstraintRadius_16 = Sketch_10.setRadius(SketchArc_10.results()[1], 1.5)
 SketchConstraintRadius_16.setName("SketchConstraintRadius_11")
 model.do()
 RevolutionFuse_3 = model.addRevolutionFuse(Part_1_doc, [model.selection("COMPOUND", "Sketch_9")], model.selection("EDGE", "Sketch_9/Edge-SketchLine_58"), 360, 0, [model.selection("SOLID", "RevolutionFuse_2_1")])
-RevolutionFuse_3.result().setName("RevolutionFuse_3_1")
 RevolutionFuse_4 = model.addRevolutionFuse(Part_1_doc, [model.selection("COMPOUND", "Sketch_10")], model.selection("EDGE", "Sketch_10/Edge-SketchLine_66"), 360, 0, [model.selection("SOLID", "RevolutionFuse_3_1")])
-RevolutionFuse_4.result().setName("RevolutionFuse_4_1")
 ExtrusionCut_3 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_6/Face-SketchCircle_11_2f"), model.selection("FACE", "Sketch_6/Face-SketchCircle_9_2f"), model.selection("WIRE", "Sketch_6/Wire-SketchCircle_10_2f"), model.selection("FACE", "Sketch_6/Face-SketchCircle_12_2f")], model.selection("EDGE", "PartSet/OZ"), "BPS+5", 5, [model.selection("SOLID", "RevolutionFuse_4_1")])
 
 # Test reexecution after parameter change
index f095cbb63e47ed54c2132aa19d46cd8d08a99de7..c3f15e14d3cbfec2b8143491fa3061e678a68028 100644 (file)
@@ -584,9 +584,7 @@ SketchConstraintDistance_13 = Sketch_3.setDistance(SketchCircle_4.center(), Sket
 model.do()
 Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchLine_2f-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_6f-SketchLine_8f-SketchLine_9f-SketchLine_11f-SketchLine_12f-SketchLine_13f-SketchLine_14f")], model.selection("EDGE", "PartSet/OX"), 360, 0)
 ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchArc_1_2r-SketchLine_382f-SketchLine_383f-SketchLine_20f-SketchLine_22f-SketchLine_23f-SketchLine_24f-SketchLine_25f-SketchLine_26f-SketchLine_27f-SketchLine_28f-SketchLine_29f-SketchLine_30f-SketchLine_31f-SketchLine_32f-SketchLine_33f-SketchLine_34f-SketchLine_35f-SketchLine_36f-SketchLine_37f-SketchLine_38f-SketchLine_39f-SketchLine_40f-SketchLine_41f-SketchLine_42f-SketchLine_43f-SketchLine_44f-SketchLine_45f-SketchLine_46f-SketchLine_47f-SketchLine_48f-SketchLine_49f-SketchLine_50f-SketchLine_51f-SketchLine_52f-SketchLine_53f-SketchLine_54f-SketchLine_55f-SketchLine_56f-SketchLine_57f-SketchLine_58f-SketchLine_59f-SketchLine_60f-SketchLine_61f-SketchLine_62f-SketchLine_63f-SketchLine_64f-SketchLine_65f-SketchLine_66f-SketchLine_67f-SketchLine_68f-SketchLine_69f-SketchLine_70f-SketchLine_71f-SketchLine_72f-SketchLine_73f-SketchLine_74f-SketchLine_75f-SketchLine_76f-SketchLine_77f-SketchLine_78f-SketchLine_79f-SketchLine_80f-SketchLine_81f-SketchLine_82f-SketchLine_83f-SketchLine_84f-SketchLine_85f-SketchLine_86f-SketchLine_87f-SketchLine_88f-SketchLine_89f-SketchLine_90f-SketchLine_91f-SketchLine_92f-SketchLine_93f-SketchLine_94f-SketchLine_95f-SketchLine_96f-SketchLine_97f-SketchLine_98f-SketchLine_99f-SketchLine_100f-SketchLine_101f-SketchLine_102f-SketchLine_103f-SketchLine_104f-SketchLine_105f-SketchLine_106f-SketchLine_107f-SketchLine_108f-SketchLine_109f-SketchLine_110f-SketchLine_111f-SketchLine_112f-SketchLine_113f-SketchLine_114f-SketchLine_115f-SketchLine_116f-SketchLine_117f-SketchLine_118f-SketchLine_119f-SketchLine_120f-SketchLine_121f-SketchLine_122f-SketchLine_123f-SketchLine_124f-SketchLine_125f-SketchLine_126f-SketchLine_127f-SketchLine_128f-SketchLine_129f-SketchLine_130f-SketchLine_131f-SketchLine_132f-SketchLine_133f-SketchLine_134f-SketchLine_135f-SketchLine_136f-SketchLine_137f-SketchLine_138f-SketchLine_139f-SketchLine_140f-SketchLine_141f-SketchLine_142f-SketchLine_143f-SketchLine_144f-SketchLine_145f-SketchLine_146f-SketchLine_147f-SketchLine_148f-SketchLine_149f-SketchLine_150f-SketchLine_151f-SketchLine_152f-SketchLine_153f-SketchLine_154f-SketchLine_155f-SketchLine_156f-SketchLine_157f-SketchLine_158f-SketchLine_159f-SketchLine_160f-SketchLine_161f-SketchLine_162f-SketchLine_163f-SketchLine_164f-SketchLine_165f-SketchLine_166f-SketchLine_167f-SketchLine_168f-SketchLine_169f-SketchLine_170f-SketchLine_171f-SketchLine_172f-SketchLine_173f-SketchLine_174f-SketchLine_175f-SketchLine_176f-SketchLine_177f-SketchLine_178f-SketchLine_179f-SketchLine_180f-SketchLine_181f-SketchLine_182f-SketchLine_183f-SketchLine_184f-SketchLine_185f-SketchLine_186f-SketchLine_187f-SketchLine_188f-SketchLine_189f-SketchLine_190f-SketchLine_191f-SketchLine_192f-SketchLine_193f-SketchLine_194f-SketchLine_195f-SketchLine_196f-SketchLine_197f-SketchLine_198f-SketchLine_199f-SketchArc_2_2r-SketchArc_3_2r-SketchArc_4_2r-SketchArc_5_2r-SketchArc_6_2r-SketchArc_7_2r-SketchArc_8_2r-SketchArc_9_2r-SketchArc_10_2r-SketchArc_11_2r-SketchArc_12_2r-SketchArc_13_2r-SketchArc_14_2r-SketchArc_15_2r-SketchArc_16_2r-SketchArc_17_2r-SketchArc_18_2r-SketchArc_19_2r-SketchArc_20_2r-SketchArc_21_2r-SketchArc_22_2r-SketchArc_23_2r-SketchArc_24_2r-SketchArc_25_2r-SketchArc_26_2r-SketchArc_27_2r-SketchArc_28_2r-SketchArc_29_2r-SketchArc_30_2r-SketchArc_31_2r-SketchArc_32_2r-SketchArc_33_2r-SketchArc_34_2r-SketchArc_35_2r-SketchArc_36_2r-SketchArc_37_2r-SketchArc_38_2r-SketchArc_39_2r-SketchArc_40_2r-SketchArc_41_2r-SketchArc_42_2r-SketchArc_43_2r-SketchArc_44_2r-SketchArc_45_2r-SketchArc_46_2r-SketchArc_47_2r-SketchArc_48_2r-SketchArc_49_2r-SketchArc_50_2r-SketchArc_51_2r-SketchArc_52_2r-SketchArc_53_2r-SketchArc_54_2r-SketchArc_55_2r-SketchArc_56_2r-SketchArc_57_2r-SketchArc_58_2r-SketchArc_59_2r-SketchArc_60_2r-SketchArc_61_2r-SketchArc_62_2r-SketchArc_63_2r-SketchArc_64_2r-SketchArc_65_2r-SketchArc_66_2r-SketchArc_67_2r-SketchArc_68_2r-SketchArc_69_2r-SketchArc_70_2r-SketchArc_71_2r-SketchArc_72_2r-SketchArc_73_2r-SketchArc_74_2r-SketchArc_75_2r-SketchArc_76_2r-SketchArc_77_2r-SketchArc_78_2r-SketchArc_79_2r-SketchArc_80_2r-SketchArc_81_2r-SketchArc_82_2r-SketchArc_83_2r-SketchArc_84_2r-SketchArc_85_2r-SketchArc_86_2r-SketchArc_87_2r-SketchArc_88_2r-SketchArc_89_2r-SketchArc_90_2r-SketchArc_91_2r-SketchArc_92_2r-SketchArc_93_2r-SketchArc_94_2r-SketchArc_95_2r-SketchArc_96_2r-SketchArc_97_2r-SketchArc_98_2r-SketchArc_99_2r-SketchArc_100_2r-SketchArc_101_2r-SketchArc_102_2r-SketchArc_103_2r-SketchArc_104_2r-SketchArc_105_2r-SketchArc_106_2r-SketchArc_107_2r-SketchArc_108_2r-SketchArc_109_2r-SketchArc_110_2r-SketchArc_111_2r-SketchArc_112_2r-SketchArc_113_2r-SketchArc_114_2r-SketchArc_115_2r-SketchArc_116_2r-SketchArc_117_2r-SketchArc_118_2r-SketchArc_119_2r-SketchArc_120_2r-SketchArc_121_2r-SketchArc_122_2r-SketchArc_123_2r-SketchArc_124_2r-SketchArc_125_2r-SketchArc_126_2r-SketchArc_127_2r-SketchArc_128_2r-SketchArc_129_2r-SketchArc_130_2r-SketchArc_131_2r-SketchArc_132_2r-SketchArc_133_2r-SketchArc_134_2r-SketchArc_135_2r-SketchArc_136_2r-SketchArc_137_2r-SketchArc_138_2r-SketchArc_139_2r-SketchArc_140_2r-SketchArc_141_2r-SketchArc_142_2r-SketchArc_143_2r-SketchArc_144_2r-SketchArc_145_2r-SketchArc_146_2r-SketchArc_147_2r-SketchArc_148_2r-SketchArc_149_2r-SketchArc_150_2r-SketchArc_151_2r-SketchArc_152_2r-SketchArc_153_2r-SketchArc_154_2r-SketchArc_155_2r-SketchArc_156_2r-SketchArc_157_2r-SketchArc_158_2r-SketchArc_159_2r-SketchArc_160_2r-SketchArc_161_2r-SketchArc_162_2r-SketchArc_163_2r-SketchArc_164_2r-SketchArc_165_2r-SketchArc_166_2r-SketchArc_167_2r-SketchArc_168_2r-SketchArc_169_2r-SketchArc_170_2r-SketchArc_171_2r-SketchArc_172_2r-SketchArc_173_2r-SketchArc_174_2r-SketchArc_175_2r-SketchArc_176_2r-SketchArc_177_2r-SketchArc_178_2r-SketchArc_179_2r-SketchArc_180_2r-SketchLine_21f-SketchLine_200f-SketchLine_201f-SketchLine_202f-SketchLine_203f-SketchLine_204f-SketchLine_205f-SketchLine_206f-SketchLine_207f-SketchLine_208f-SketchLine_209f-SketchLine_210f-SketchLine_211f-SketchLine_212f-SketchLine_213f-SketchLine_214f-SketchLine_215f-SketchLine_216f-SketchLine_217f-SketchLine_218f-SketchLine_219f-SketchLine_220f-SketchLine_221f-SketchLine_222f-SketchLine_223f-SketchLine_224f-SketchLine_225f-SketchLine_226f-SketchLine_227f-SketchLine_228f-SketchLine_229f-SketchLine_230f-SketchLine_231f-SketchLine_232f-SketchLine_233f-SketchLine_234f-SketchLine_235f-SketchLine_236f-SketchLine_237f-SketchLine_238f-SketchLine_239f-SketchLine_240f-SketchLine_241f-SketchLine_242f-SketchLine_243f-SketchLine_244f-SketchLine_245f-SketchLine_246f-SketchLine_247f-SketchLine_248f-SketchLine_249f-SketchLine_250f-SketchLine_251f-SketchLine_252f-SketchLine_253f-SketchLine_254f-SketchLine_255f-SketchLine_256f-SketchLine_257f-SketchLine_258f-SketchLine_259f-SketchLine_260f-SketchLine_261f-SketchLine_262f-SketchLine_263f-SketchLine_264f-SketchLine_265f-SketchLine_266f-SketchLine_267f-SketchLine_268f-SketchLine_269f-SketchLine_270f-SketchLine_271f-SketchLine_272f-SketchLine_273f-SketchLine_274f-SketchLine_275f-SketchLine_276f-SketchLine_277f-SketchLine_278f-SketchLine_279f-SketchLine_280f-SketchLine_281f-SketchLine_282f-SketchLine_283f-SketchLine_284f-SketchLine_285f-SketchLine_286f-SketchLine_287f-SketchLine_288f-SketchLine_289f-SketchLine_290f-SketchLine_291f-SketchLine_292f-SketchLine_293f-SketchLine_294f-SketchLine_295f-SketchLine_296f-SketchLine_297f-SketchLine_298f-SketchLine_299f-SketchLine_300f-SketchLine_301f-SketchLine_302f-SketchLine_303f-SketchLine_304f-SketchLine_305f-SketchLine_306f-SketchLine_307f-SketchLine_308f-SketchLine_309f-SketchLine_310f-SketchLine_311f-SketchLine_312f-SketchLine_313f-SketchLine_314f-SketchLine_315f-SketchLine_316f-SketchLine_317f-SketchLine_318f-SketchLine_319f-SketchLine_320f-SketchLine_321f-SketchLine_322f-SketchLine_323f-SketchLine_324f-SketchLine_325f-SketchLine_326f-SketchLine_327f-SketchLine_328f-SketchLine_329f-SketchLine_330f-SketchLine_331f-SketchLine_332f-SketchLine_333f-SketchLine_334f-SketchLine_335f-SketchLine_336f-SketchLine_337f-SketchLine_338f-SketchLine_339f-SketchLine_340f-SketchLine_341f-SketchLine_342f-SketchLine_343f-SketchLine_344f-SketchLine_345f-SketchLine_346f-SketchLine_347f-SketchLine_348f-SketchLine_349f-SketchLine_350f-SketchLine_351f-SketchLine_352f-SketchLine_353f-SketchLine_354f-SketchLine_355f-SketchLine_356f-SketchLine_357f-SketchLine_358f-SketchLine_359f-SketchLine_360f-SketchLine_361f-SketchLine_362f-SketchLine_363f-SketchLine_364f-SketchLine_365f-SketchLine_366f-SketchLine_367f-SketchLine_368f-SketchLine_369f-SketchLine_370f-SketchLine_371f-SketchLine_372f-SketchLine_373f-SketchLine_374f-SketchLine_375f-SketchLine_376f-SketchLine_377f-SketchCircle_3_2f")], model.selection(), model.selection("FACE", "Revolution_1_1/Generated_Face_5"), 0, model.selection(), 0, [model.selection("SOLID", "Revolution_1_1")])
-ExtrusionCut_1.result().setName("ExtrusionCut_1_1")
 ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchCircle_4_2f")], model.selection(), 30, 0, [model.selection("SOLID", "ExtrusionCut_1_1")])
-ExtrusionCut_2.result().setName("ExtrusionCut_2_1")
 
 # Test reexecution after parameter change
 Parameter_H.setValue(14)
index 569774775979a22d82aededb3bbcea0d71b763f1..247658ae5e1d21dc97f7c3c2d086e49a828e6d4f 100644 (file)
@@ -82,7 +82,6 @@ SketchConstraintDistance_2 = Sketch_1.setDistance(SketchLine_3.endPoint(), Sketc
 model.do()
 Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_7r-SketchLine_1r-SketchLine_2r-SketchLine_8r-SketchArc_1_2f")], model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), 0, 180)
 ExtrusionFuse_1 = model.addExtrusionFuse(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_7r-SketchLine_1r-SketchLine_2r-SketchLine_8r-SketchArc_1_2f")], model.selection(), 0, 25, [model.selection("SOLID", "Revolution_1_1")])
-ExtrusionFuse_1.result().setName("ExtrusionFuse_1_1")
 Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
 SketchLine_9 = Sketch_2.addLine(0, 20, -17.00000285538278, 20)
 SketchLine_9.setName("SketchLine_13")
@@ -128,7 +127,6 @@ SketchConstraintDistance_3 = Sketch_2.setDistance(SketchLine_10.startPoint(), Sk
 SketchConstraintDistance_4 = Sketch_2.setDistance(SketchLine_11.endPoint(), SketchLine_10.result(), 20)
 model.do()
 ExtrusionFuse_2 = model.addExtrusionFuse(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_13f-SketchLine_9f-SketchLine_10f-SketchLine_14f-SketchArc_2_2f")], model.selection(), 0, 25, [model.selection("SOLID", "ExtrusionFuse_1_1")])
-ExtrusionFuse_2.result().setName("ExtrusionFuse_2_1")
 Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionFuse_2_1/Modfied_8"))
 SketchLine_15 = Sketch_3.addLine(0, -20, -17.00000002635728, -20)
 SketchLine_15.setName("SketchLine_19")
@@ -177,7 +175,6 @@ SketchConstraintParallel_1 = Sketch_3.setParallel(SketchLine_17.result(), Sketch
 SketchConstraintDistance_7 = Sketch_3.setDistance(SketchLine_21.startPoint(), SketchLine_18.result(), 3)
 model.do()
 RevolutionFuse_1 = model.addRevolutionFuse(Part_1_doc, [model.selection("COMPOUND", "Sketch_3")], model.selection("EDGE", "Sketch_3/Edge-SketchLine_21"), 71, 0, [model.selection("SOLID", "ExtrusionFuse_2_1")])
-RevolutionFuse_1.result().setName("RevolutionFuse_1_1")
 Sketch_4 = model.addSketch(Part_1_doc, model.selection("FACE", "RevolutionFuse_1_1/Modfied_7"))
 SketchLine_22 = Sketch_4.addLine(-3, -20, 17.00000452949485, -20)
 SketchLine_22.setName("SketchLine_26")
@@ -227,7 +224,6 @@ SketchConstraintParallel_2 = Sketch_4.setParallel(SketchLine_25.result(), Sketch
 SketchConstraintDistance_11 = Sketch_4.setDistance(SketchLine_23.startPoint(), SketchLine_29.result(), 3)
 model.do()
 RevolutionFuse_2 = model.addRevolutionFuse(Part_1_doc, [model.selection("FACE", "Sketch_4/Face-SketchLine_26f-SketchLine_22f-SketchLine_23f-SketchLine_27f-SketchArc_4_2f")], model.selection("EDGE", "Sketch_4/Edge-SketchLine_29"), 0, 71, [model.selection("SOLID", "RevolutionFuse_1_1")])
-RevolutionFuse_2.result().setName("RevolutionFuse_2_1")
 Sketch_5 = model.addSketch(Part_1_doc, model.selection("FACE", "PartSet/XOZ"))
 SketchLine_30 = Sketch_5.addLine(0, 0, 0, 82)
 SketchLine_31 = Sketch_5.addLine(model.selection("EDGE", "PartSet/OZ"))
@@ -309,7 +305,6 @@ SketchConstraintDistance_15 = Sketch_5.setDistance(SketchLine_37.startPoint(), S
 SketchConstraintDistance_15.setName("SketchConstraintDistance_16")
 model.do()
 RevolutionFuse_3 = model.addRevolutionFuse(Part_1_doc, [model.selection("WIRE", "Sketch_5/Wire-SketchLine_30r-SketchLine_39r-SketchLine_32r-SketchLine_40r-SketchLine_38r-SketchArc_6_2f-SketchArc_7_2r")], model.selection("EDGE", "PartSet/OZ"), 45, 315, [model.selection("SOLID", "RevolutionFuse_2_1")])
-RevolutionFuse_3.result().setName("RevolutionFuse_3_1")
 Sketch_6 = model.addSketch(Part_1_doc, model.selection("FACE", "PartSet/YOZ"))
 SketchLine_38 = Sketch_6.addLine(19.99999999999999, 60, -20, 60)
 SketchLine_38.setName("SketchLine_48")
@@ -416,7 +411,6 @@ SketchConstraintCoincidence_84 = Sketch_6.setCoincident(SketchLine_41.startPoint
 SketchConstraintCoincidence_84.setName("SketchConstraintCoincidence_156")
 model.do()
 ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_6")], model.selection(), 100, 0, [model.selection("SOLID", "RevolutionFuse_3_1")])
-ExtrusionCut_1.result().setName("ExtrusionCut_1_1")
 Sketch_7 = model.addSketch(Part_1_doc, model.selection("FACE", "PartSet/XOZ"))
 SketchLine_50 = Sketch_7.addLine(65, 23.09999999999939, 65, 23.00000523211526)
 SketchLine_50.setName("SketchLine_61")
@@ -439,7 +433,7 @@ SketchLine_54.result().setName("SketchLine_55")
 SketchLine_54.setAuxiliary(True)
 SketchConstraintCoincidence_86 = Sketch_7.setCoincident(SketchLine_52.endPoint(), SketchLine_54.startPoint())
 SketchConstraintCoincidence_86.setName("SketchConstraintCoincidence_96")
-SketchLine_55 = Sketch_7.addLine(model.selection("EDGE", "RevolutionFuse_3_1/Modfied_13&RevolutionFuse_3_1/Modfied_10"))
+SketchLine_55 = Sketch_7.addLine(model.selection("EDGE", "RevolutionFuse_3_1/Modfied_11&RevolutionFuse_3_1/Modfied_8"))
 SketchLine_55.setName("SketchLine_56")
 SketchLine_55.result().setName("SketchLine_56")
 SketchConstraintCoincidence_87 = Sketch_7.setCoincident(SketchLine_54.endPoint(), SketchLine_55.result())
@@ -500,7 +494,6 @@ SketchConstraintDistance_21 = Sketch_7.setDistance(SketchLine_50.startPoint(), S
 SketchConstraintDistance_21.setName("SketchConstraintDistance_23")
 model.do()
 RevolutionFuse_4 = model.addRevolutionFuse(Part_1_doc, [model.selection("COMPOUND", "Sketch_7")], model.selection("EDGE", "PartSet/OZ"), 14.4, 14.4, [model.selection("SOLID", "ExtrusionCut_1_1")])
-RevolutionFuse_4.result().setName("RevolutionFuse_4_1")
 Sketch_8 = model.addSketch(Part_1_doc, model.selection("FACE", "PartSet/XOZ"))
 SketchCircle_1 = Sketch_8.addCircle(0, 45, 12.5)
 SketchLine_60 = Sketch_8.addLine(model.selection("EDGE", "Sketch_5/Edge-SketchLine_30"))
@@ -517,7 +510,6 @@ SketchConstraintRadius_8 = Sketch_8.setRadius(SketchCircle_1.results()[1], 12.5)
 SketchConstraintRadius_8.setName("SketchConstraintRadius_13")
 model.do()
 ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_8/Face-SketchCircle_1_2f")], model.selection(), 100, 100, [model.selection("SOLID", "RevolutionFuse_4_1")])
-ExtrusionCut_2.result().setName("ExtrusionCut_2_1")
 Sketch_9 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
 SketchLine_62 = Sketch_9.addLine(0, 84, 0, -2)
 SketchLine_62.setName("SketchLine_65")
@@ -656,7 +648,7 @@ Sketch_10 = model.addSketch(Part_1_doc, model.selection("FACE", "PartSet/XOY"))
 SketchLine_77 = Sketch_10.addLine(64, 20, 89, 20)
 SketchLine_77.setName("SketchLine_76")
 SketchLine_77.result().setName("SketchLine_76")
-SketchPoint_4 = Sketch_10.addPoint(model.selection("VERTEX", "RevolutionFuse_2_1/Modfied_11&RevolutionFuse_2_1/Modfied_15&RevolutionFuse_3_1/Modfied_15&RevolutionFuse_3_1/Modfied_4"))
+SketchPoint_4 = Sketch_10.addPoint(model.selection("VERTEX", "RevolutionFuse_2_1/Modfied_9&RevolutionFuse_2_1/Modfied_12&RevolutionFuse_3_1/Modfied_12&RevolutionFuse_3_1/Modfied_1divided_f_1"))
 SketchConstraintCoincidence_122 = Sketch_10.setCoincident(SketchLine_77.startPoint(), SketchPoint_4.result())
 SketchConstraintCoincidence_122.setName("SketchConstraintCoincidence_120")
 SketchPoint_5 = Sketch_10.addPoint(model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_1s-SketchLine_8e-SketchLine_4e"))
@@ -665,10 +657,10 @@ SketchConstraintCoincidence_123.setName("SketchConstraintCoincidence_121")
 SketchLine_78 = Sketch_10.addLine(64, -20, 89, -20)
 SketchLine_78.setName("SketchLine_77")
 SketchLine_78.result().setName("SketchLine_77")
-SketchPoint_6 = Sketch_10.addPoint(model.selection("VERTEX", "RevolutionFuse_1_1/Modfied_4&RevolutionFuse_1_1/Modfied_10&RevolutionFuse_3_1/Modfied_17&RevolutionFuse_3_1/Modfied_8"))
+SketchPoint_6 = Sketch_10.addPoint(model.selection("VERTEX", "RevolutionFuse_1_1/Modfied_4&RevolutionFuse_1_1/Modfied_10&RevolutionFuse_3_1/Modfied_13&RevolutionFuse_3_1/Modfied_1divided_f_2"))
 SketchConstraintCoincidence_124 = Sketch_10.setCoincident(SketchLine_78.startPoint(), SketchPoint_6.result())
 SketchConstraintCoincidence_124.setName("SketchConstraintCoincidence_122")
-SketchPoint_7 = Sketch_10.addPoint(model.selection("VERTEX", "ExtrusionFuse_2_1/Modfied_3&RevolutionFuse_1_1/Modfied_4&ExtrusionFuse_2_1/Modfied_4&RevolutionFuse_3_1/Modfied_17"))
+SketchPoint_7 = Sketch_10.addPoint(model.selection("VERTEX", "ExtrusionFuse_2_1/Modfied_3&RevolutionFuse_1_1/Modfied_4&ExtrusionFuse_2_1/Modfied_4&RevolutionFuse_3_1/Modfied_13"))
 SketchConstraintCoincidence_125 = Sketch_10.setCoincident(SketchLine_78.endPoint(), SketchPoint_7.result())
 SketchConstraintCoincidence_125.setName("SketchConstraintCoincidence_123")
 SketchArc_10 = Sketch_10.addArc(89.00000104846708, 1.669244441022778e-015, 89, -20, 89, 20, False)
@@ -691,7 +683,7 @@ SketchConstraintCoincidence_129 = Sketch_10.setCoincident(SketchArc_11.startPoin
 SketchConstraintCoincidence_129.setName("SketchConstraintCoincidence_127")
 SketchConstraintTangent_19 = Sketch_10.setTangent(SketchArc_11.results()[1], SketchLine_78.result())
 SketchConstraintTangent_19.setName("SketchConstraintTangent_24")
-SketchPoint_8 = Sketch_10.addPoint(model.selection("VERTEX", "RevolutionFuse_3_1/Modfied_9&RevolutionFuse_3_1/Modfied_8&ExtrusionCut_2_1/Modfied_5&RevolutionFuse_3_1/Modfied_7&RevolutionFuse_3_1/Modfied_24"))
+SketchPoint_8 = Sketch_10.addPoint(model.selection("VERTEX", "RevolutionFuse_1_1/Modfied_10&RevolutionFuse_3_1/Modfied_7&RevolutionFuse_3_1/Modfied_1divided_f_2"))
 SketchConstraintCoincidence_130 = Sketch_10.setCoincident(SketchArc_11.endPoint(), SketchPoint_8.result())
 SketchConstraintCoincidence_130.setName("SketchConstraintCoincidence_128")
 SketchArc_12 = Sketch_10.addArc(64.00001789135865, 23.01137360115889, 64, 20, 61.15622559702543, 22.02080994708722, True)
@@ -702,7 +694,7 @@ SketchConstraintCoincidence_131 = Sketch_10.setCoincident(SketchArc_12.startPoin
 SketchConstraintCoincidence_131.setName("SketchConstraintCoincidence_129")
 SketchConstraintTangent_20 = Sketch_10.setTangent(SketchArc_12.results()[1], SketchLine_77.result())
 SketchConstraintTangent_20.setName("SketchConstraintTangent_25")
-SketchPoint_9 = Sketch_10.addPoint(model.selection("VERTEX", "RevolutionFuse_3_1/Modfied_5&RevolutionFuse_3_1/Modfied_4&ExtrusionCut_2_1/Modfied_5&RevolutionFuse_3_1/Modfied_3&RevolutionFuse_3_1/Modfied_24"))
+SketchPoint_9 = Sketch_10.addPoint(model.selection("VERTEX", "RevolutionFuse_2_1/Modfied_12&RevolutionFuse_3_1/Modfied_4&RevolutionFuse_3_1/Modfied_1divided_f_1"))
 SketchConstraintCoincidence_132 = Sketch_10.setCoincident(SketchArc_12.endPoint(), SketchPoint_9.result())
 SketchConstraintCoincidence_132.setName("SketchConstraintCoincidence_130")
 SketchLine_79 = Sketch_10.addLine(61.15622559702543, 22.02080994708722, 59.81204392543111, 22.0208099470871)
@@ -771,7 +763,6 @@ SketchArc_13.result().setName("SketchArc_16")
 SketchArc_13.results()[1].setName("SketchArc_16_2")
 model.do()
 ExtrusionFuse_3 = model.addExtrusionFuse(Part_1_doc, [model.selection("FACE", "Sketch_10/Face-SketchArc_16_2f-SketchLine_81r-SketchLine_82f-SketchArc_17_2r-SketchLine_83f-SketchLine_84f-SketchLine_85r-SketchArc_18_2r"), model.selection("FACE", "Sketch_10/Face-SketchArc_19_2f-SketchLine_86r-SketchLine_87f-SketchArc_20_2r-SketchLine_88f-SketchLine_89f-SketchLine_90r-SketchArc_21_2r")], model.selection(), 20, 0, [model.selection("SOLID", "ExtrusionCut_2_1")])
-ExtrusionFuse_3.result().setName("ExtrusionFuse_3_1")
 Sketch_11 = model.addSketch(Part_1_doc, model.selection("FACE", "PartSet/XOY"))
 SketchCircle_2 = Sketch_11.addCircle(89, 0, 6)
 SketchPoint_11 = Sketch_11.addPoint(model.selection("VERTEX", "Sketch_2/Vertex-SketchPoint_1-SketchLine_10s-SketchLine_9e"))
@@ -791,16 +782,13 @@ SketchMultiRotation_2 = Sketch_11.addRotation([SketchCircle_3.results()[1], Sket
 [SketchCircle_4, SketchCircle_5, SketchCircle_6, SketchCircle_7] = SketchMultiRotation_2.rotated()
 model.do()
 RevolutionCut_1 = model.addRevolutionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_9")], model.selection("EDGE", "PartSet/OZ"), 0, 360, [model.selection("SOLID", "ExtrusionFuse_3_1")])
-RevolutionCut_1.result().setName("RevolutionCut_1_1")
 ExtrusionCut_3 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_11/Wire-SketchCircle_4_2f"), model.selection("WIRE", "Sketch_11/Wire-SketchCircle_3_2f"), model.selection("WIRE", "Sketch_11/Wire-SketchCircle_5_2f")], model.selection(), 30, -15, [model.selection("SOLID", "RevolutionCut_1_1")])
-ExtrusionCut_3.result().setName("ExtrusionCut_3_1")
 ExtrusionCut_4 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_11/Wire-SketchCircle_2_2f"), model.selection("FACE", "Sketch_11/Face-SketchCircle_6_2f"), model.selection("WIRE", "Sketch_11/Wire-SketchCircle_7_2f")], model.selection(), 30, 2, [model.selection("SOLID", "ExtrusionCut_3_1")])
-ExtrusionCut_4.result().setName("ExtrusionCut_4_1")
 
 # Test reexecution after parameter change
 Parameter_R.setValue(5)
 model.do()
-model.testResultsVolumes(ExtrusionCut_4, [502615.944655187719035893678665161])
+model.testResultsVolumes(ExtrusionCut_4, [502616.749082866765093058347702026])
 Parameter_R.setValue(3)
 model.end()
 
@@ -810,8 +798,8 @@ model.testNbResults(ExtrusionCut_4, 1)
 model.testNbSubResults(ExtrusionCut_4, [0])
 model.testNbSubShapes(ExtrusionCut_4, GeomAPI_Shape.SOLID, [1])
 model.testNbSubShapes(ExtrusionCut_4, GeomAPI_Shape.FACE, [81])
-model.testNbSubShapes(ExtrusionCut_4, GeomAPI_Shape.EDGE, [406])
-model.testNbSubShapes(ExtrusionCut_4, GeomAPI_Shape.VERTEX, [812])
-model.testResultsVolumes(ExtrusionCut_4, [502902.431481667619664222002029419])
+model.testNbSubShapes(ExtrusionCut_4, GeomAPI_Shape.EDGE, [410])
+model.testNbSubShapes(ExtrusionCut_4, GeomAPI_Shape.VERTEX, [820])
+model.testResultsVolumes(ExtrusionCut_4, [502903.236060981987975537776947021])
 
 assert(model.checkPythonDump())
index 368df3b77d10c96c80931b4ab85891efcdb35e72..a7f26c547d0912dc171165aa476ee6af6406ca20 100644 (file)
@@ -181,7 +181,6 @@ SketchConstraintCoincidence_26 = Sketch_2.setCoincident(SketchArc_3.endPoint(),
 SketchConstraintCoincidence_26.setName("SketchConstraintCoincidence_30")
 model.do()
 ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchArc_3_2r-SketchLine_18r-SketchLine_19r-SketchLine_20r-SketchLine_21r-SketchLine_22r")], model.selection(), 7, 15, [model.selection("SOLID", "Extrusion_1_1")])
-ExtrusionCut_1.result().setName("ExtrusionCut_1_1")
 Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_9"))
 SketchLine_21 = Sketch_3.addLine(28, -6, -4.270492394552598, -6.000000000000001)
 SketchLine_21.setName("SketchLine_23")
@@ -320,7 +319,6 @@ SketchConstraintCoincidence_54.setName("SketchConstraintCoincidence_58")
 SketchConstraintEqual_2 = Sketch_3.setEqual(SketchLine_30.result(), SketchLine_25.result())
 model.do()
 ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_32f-SketchLine_33f-SketchLine_34f-SketchLine_35f"), model.selection("FACE", "Sketch_3/Face-SketchLine_26f-SketchLine_27f-SketchLine_28f-SketchLine_29f")], model.selection(), model.selection("FACE", "ExtrusionCut_1_1/Modfied_4"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_1_1")])
-ExtrusionCut_2.result().setName("ExtrusionCut_2_1")
 Sketch_4 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_1_1/Modfied_1"))
 SketchLine_37 = Sketch_4.addLine(0.4324637622511017, 3.581086955422081, 1.55585595716119, 2.812450190483599)
 SketchLine_37.setName("SketchLine_39")
@@ -372,8 +370,7 @@ SketchLine_41.setName("SketchLine_43")
 SketchLine_41.result().setName("SketchLine_43")
 model.do()
 ExtrusionCut_3 = model.addExtrusionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_4")], model.selection(), model.selection("FACE", "ExtrusionCut_1_1/Modfied_2"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_2_1")])
-ExtrusionCut_3.result().setName("ExtrusionCut_3_1")
-Plane_4 = model.addPlane(Part_1_doc, model.selection("VERTEX", "ExtrusionCut_1_1/Modfied_5&ExtrusionCut_3_1/Modfied_3&Extrusion_1_1/Generated_Face_1"), model.selection("VERTEX", "ExtrusionCut_3_1/Modfied_3&Extrusion_1_1/Generated_Face_7&Extrusion_1_1/Generated_Face_6"), model.selection("VERTEX", "ExtrusionCut_1_1/Modfied_5&ExtrusionCut_2_1/Modfied_9&ExtrusionCut_3_1/Modfied_3"))
+Plane_4 = model.addPlane(Part_1_doc, model.selection("VERTEX", "ExtrusionCut_1_1/Modfied_5&ExtrusionCut_3_1/Modfied_3&Extrusion_1_1/Generated_Face_1"), model.selection("VERTEX", "ExtrusionCut_3_1/Modfied_3&Extrusion_1_1/Generated_Face_7&Extrusion_1_1/Generated_Face_6"), model.selection("VERTEX", "ExtrusionCut_1_1/Modfied_5&ExtrusionCut_2_1/Modfied_6&ExtrusionCut_3_1/Modfied_3"))
 Sketch_5 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
 SketchArc_4 = Sketch_5.addArc(25.00007393928819, -7.521062532210847, 22.00014787857639, -7.5, 28, -7.5, True)
 SketchPoint_5 = Sketch_5.addPoint(22.00014787857639, -7.5)
@@ -416,9 +413,7 @@ model.do()
 Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "ExtrusionCut_3_1/Modfied_3"), 6, True)
 Plane_6 = model.addPlane(Part_1_doc, model.selection("FACE", "Plane_2"), 3, True)
 ExtrusionCut_4 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_5/Face-SketchArc_4_2f-SketchLine_52f-SketchLine_53f-SketchLine_54f")], model.selection(), 3, 0, [model.selection("SOLID", "ExtrusionCut_3_1")])
-ExtrusionCut_4.result().setName("ExtrusionCut_4_1")
 ExtrusionCut_5 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_5/Face-SketchArc_4_2f-SketchLine_52f-SketchLine_53f-SketchLine_54f")], model.selection(), model.selection("FACE", "Plane_3"), 0, model.selection("FACE", "Plane_2"), 0, [model.selection("SOLID", "ExtrusionCut_4_1")])
-ExtrusionCut_5.result().setName("ExtrusionCut_5_1")
 Sketch_6 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_4_1/Modfied_6"))
 SketchArc_5 = Sketch_6.addArc(45.99999999999999, 0, 45.49999999999999, 8.91700958118717e-020, 46.49999999999999, 8.280962276646116e-019, False)
 SketchLine_53 = Sketch_6.addLine(0, 0, 54, 0)
@@ -470,8 +465,7 @@ SketchLine_56.setName("SketchLine_58")
 SketchLine_56.result().setName("SketchLine_58")
 model.do()
 ExtrusionFuse_1 = model.addExtrusionFuse(Part_1_doc, [model.selection("COMPOUND", "Sketch_6")], model.selection(), model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_7f-SketchArc_1_2f-SketchLine_8f-SketchLine_9f-SketchLine_10r-SketchLine_11r-SketchLine_12r-SketchLine_14r-SketchArc_2_2r"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_5_1")])
-ExtrusionFuse_1.result().setName("ExtrusionFuse_1_1")
-Sketch_7 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_2_1/Modfied_12"))
+Sketch_7 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_2_1/Modfied_9"))
 SketchLine_64 = Sketch_7.addLine(50.25000000000001, -4.5, 31.24999999998802, -4.499999999999997)
 SketchLine_64.setName("SketchLine_76")
 SketchLine_64.result().setName("SketchLine_76")
@@ -642,8 +636,7 @@ SketchConstraintRadius_7 = Sketch_7.setRadius(SketchArc_15.results()[1], 0.25)
 SketchConstraintRadius_8 = Sketch_7.setRadius(SketchArc_17.results()[1], 0.25)
 model.do()
 ExtrusionCut_6 = model.addExtrusionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_7")], model.selection(), 0, 20, [model.selection("SOLID", "ExtrusionFuse_1_1")])
-ExtrusionCut_6.result().setName("ExtrusionCut_6_1")
-Sketch_8 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_6_1/Modfied_17"))
+Sketch_8 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_6_1/Modfied_10"))
 SketchPoint_12 = Sketch_8.addPoint(53.99994409538203, -1.615587133892632e-027)
 SketchPoint_13 = Sketch_8.addPoint(53.99994409538203, -1.615587133892632e-027)
 SketchConstraintRigid_7 = Sketch_8.setFixed(SketchPoint_13.result())
@@ -791,8 +784,7 @@ SketchConstraintCoincidence_141 = Sketch_8.setCoincident(SketchPoint_21.coordina
 SketchConstraintCoincidence_141.setName("SketchConstraintCoincidence_145")
 model.do()
 ExtrusionCut_7 = model.addExtrusionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_8")], model.selection(), 10, 0, [model.selection("SOLID", "ExtrusionCut_6_1")])
-ExtrusionCut_7.result().setName("ExtrusionCut_7_1")
-Sketch_9 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_7_1/Modfied_56"))
+Sketch_9 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_7_1/Modfied_32"))
 SketchLine_94 = Sketch_9.addLine(21.00014787857639, 4.163450069699051, 21.00014787857639, 0)
 SketchLine_94.setName("SketchLine_107")
 SketchLine_94.result().setName("SketchLine_107")
@@ -935,7 +927,6 @@ model.do()
 Plane_7 = model.addPlane(Part_1_doc, model.selection("FACE", "Plane_2"), 4, False)
 Plane_8 = model.addPlane(Part_1_doc, model.selection("FACE", "Plane_2"), 4, True)
 ExtrusionCut_8 = model.addExtrusionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_9")], model.selection(), model.selection("FACE", "Plane_5"), 0, model.selection("FACE", "Plane_4"), 0, [model.selection("SOLID", "ExtrusionCut_7_1")])
-ExtrusionCut_8.result().setName("ExtrusionCut_8_1")
 Sketch_10 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_8_1/Modfied_5"))
 SketchCircle_1 = Sketch_10.addCircle(12, 6, 1)
 SketchConstraintRadius_11 = Sketch_10.setRadius(SketchCircle_1.results()[1], 1)
@@ -962,7 +953,6 @@ SketchConstraintCoincidence_173.setName("SketchConstraintCoincidence_178")
 SketchConstraintDistance_17 = Sketch_10.setDistance(SketchLine_105.result(), SketchCircle_1.center(), 12)
 model.do()
 ExtrusionCut_9 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_10/Wire-SketchCircle_1_2f")], model.selection(), 0, 0.75, [model.selection("SOLID", "ExtrusionCut_8_1")])
-ExtrusionCut_9.result().setName("ExtrusionCut_9_1")
 model.do()
 Part_2 = model.addPart(partSet)
 Part_2_doc = Part_2.document()
@@ -1122,7 +1112,6 @@ SketchConstraintCoincidence_199 = Sketch_12.setCoincident(SketchArc_26.endPoint(
 SketchConstraintCoincidence_199.setName("SketchConstraintCoincidence_30")
 model.do()
 ExtrusionCut_10 = model.addExtrusionCut(Part_2_doc, [model.selection("FACE", "Sketch_2/Face-SketchArc_3_2r-SketchLine_18r-SketchLine_19r-SketchLine_20r-SketchLine_21r-SketchLine_22r")], model.selection(), 7, 15, [model.selection("SOLID", "Extrusion_1_1")])
-ExtrusionCut_10.result().setName("ExtrusionCut_1_1")
 Sketch_13 = model.addSketch(Part_2_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_9"))
 SketchLine_127 = Sketch_13.addLine(28, -6, -4.270492394552598, -6.000000000000001)
 SketchLine_127.setName("SketchLine_23")
@@ -1261,7 +1250,6 @@ SketchConstraintCoincidence_227.setName("SketchConstraintCoincidence_58")
 SketchConstraintEqual_5 = Sketch_13.setEqual(SketchLine_136.result(), SketchLine_131.result())
 model.do()
 ExtrusionCut_11 = model.addExtrusionCut(Part_2_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_32f-SketchLine_33f-SketchLine_34f-SketchLine_35f"), model.selection("FACE", "Sketch_3/Face-SketchLine_26f-SketchLine_27f-SketchLine_28f-SketchLine_29f")], model.selection(), model.selection("FACE", "ExtrusionCut_1_1/Modfied_4"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_1_1")])
-ExtrusionCut_11.result().setName("ExtrusionCut_2_1")
 Sketch_14 = model.addSketch(Part_2_doc, model.selection("FACE", "ExtrusionCut_1_1/Modfied_1"))
 SketchLine_143 = Sketch_14.addLine(0.4324637622511017, 3.581086955422081, 1.55585595716119, 2.812450190483599)
 SketchLine_143.setName("SketchLine_39")
@@ -1313,8 +1301,7 @@ SketchLine_147.setName("SketchLine_43")
 SketchLine_147.result().setName("SketchLine_43")
 model.do()
 ExtrusionCut_12 = model.addExtrusionCut(Part_2_doc, [model.selection("COMPOUND", "Sketch_4")], model.selection(), model.selection("FACE", "ExtrusionCut_1_1/Modfied_2"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_2_1")])
-ExtrusionCut_12.result().setName("ExtrusionCut_3_1")
-Plane_9 = model.addPlane(Part_2_doc, model.selection("VERTEX", "ExtrusionCut_1_1/Modfied_5&ExtrusionCut_3_1/Modfied_3&Extrusion_1_1/Generated_Face_1"), model.selection("VERTEX", "ExtrusionCut_3_1/Modfied_3&Extrusion_1_1/Generated_Face_7&Extrusion_1_1/Generated_Face_6"), model.selection("VERTEX", "ExtrusionCut_1_1/Modfied_5&ExtrusionCut_2_1/Modfied_9&ExtrusionCut_3_1/Modfied_3"))
+Plane_9 = model.addPlane(Part_2_doc, model.selection("VERTEX", "ExtrusionCut_1_1/Modfied_5&ExtrusionCut_3_1/Modfied_3&Extrusion_1_1/Generated_Face_1"), model.selection("VERTEX", "ExtrusionCut_3_1/Modfied_3&Extrusion_1_1/Generated_Face_7&Extrusion_1_1/Generated_Face_6"), model.selection("VERTEX", "ExtrusionCut_1_1/Modfied_5&ExtrusionCut_2_1/Modfied_6&ExtrusionCut_3_1/Modfied_3"))
 Sketch_15 = model.addSketch(Part_2_doc, model.selection("FACE", "Plane_1"))
 SketchArc_27 = Sketch_15.addArc(25.00007393928819, -7.521062532210847, 22.00014787857639, -7.5, 28, -7.5, True)
 SketchPoint_29 = Sketch_15.addPoint(22.00014787857639, -7.5)
@@ -1357,9 +1344,7 @@ model.do()
 Plane_10 = model.addPlane(Part_2_doc, model.selection("FACE", "ExtrusionCut_3_1/Modfied_3"), 6, True)
 Plane_11 = model.addPlane(Part_2_doc, model.selection("FACE", "Plane_2"), 3, True)
 ExtrusionCut_13 = model.addExtrusionCut(Part_2_doc, [model.selection("FACE", "Sketch_5/Face-SketchArc_4_2f-SketchLine_52f-SketchLine_53f-SketchLine_54f")], model.selection(), 3, 0, [model.selection("SOLID", "ExtrusionCut_3_1")])
-ExtrusionCut_13.result().setName("ExtrusionCut_4_1")
 ExtrusionCut_14 = model.addExtrusionCut(Part_2_doc, [model.selection("FACE", "Sketch_5/Face-SketchArc_4_2f-SketchLine_52f-SketchLine_53f-SketchLine_54f")], model.selection(), model.selection("FACE", "Plane_3"), 0, model.selection("FACE", "Plane_2"), 0, [model.selection("SOLID", "ExtrusionCut_4_1")])
-ExtrusionCut_14.result().setName("ExtrusionCut_5_1")
 Sketch_16 = model.addSketch(Part_2_doc, model.selection("FACE", "ExtrusionCut_4_1/Modfied_6"))
 SketchArc_28 = Sketch_16.addArc(45.99999999999999, 0, 45.49999999999999, 8.91700958118717e-020, 46.49999999999999, 8.280962276646116e-019, False)
 SketchLine_159 = Sketch_16.addLine(0, 0, 54, 0)
@@ -1411,8 +1396,7 @@ SketchLine_162.setName("SketchLine_58")
 SketchLine_162.result().setName("SketchLine_58")
 model.do()
 ExtrusionFuse_2 = model.addExtrusionFuse(Part_2_doc, [model.selection("COMPOUND", "Sketch_6")], model.selection(), model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_7f-SketchArc_1_2f-SketchLine_8f-SketchLine_9f-SketchLine_10r-SketchLine_11r-SketchLine_12r-SketchLine_14r-SketchArc_2_2r"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_5_1")])
-ExtrusionFuse_2.result().setName("ExtrusionFuse_1_1")
-Sketch_17 = model.addSketch(Part_2_doc, model.selection("FACE", "ExtrusionCut_2_1/Modfied_12"))
+Sketch_17 = model.addSketch(Part_2_doc, model.selection("FACE", "ExtrusionCut_2_1/Modfied_9"))
 SketchLine_170 = Sketch_17.addLine(50.25000000000001, -4.5, 31.24999999998802, -4.499999999999997)
 SketchLine_170.setName("SketchLine_76")
 SketchLine_170.result().setName("SketchLine_76")
@@ -1583,8 +1567,7 @@ SketchConstraintRadius_18 = Sketch_17.setRadius(SketchArc_38.results()[1], 0.25)
 SketchConstraintRadius_19 = Sketch_17.setRadius(SketchArc_40.results()[1], 0.25)
 model.do()
 ExtrusionCut_15 = model.addExtrusionCut(Part_2_doc, [model.selection("COMPOUND", "Sketch_7")], model.selection(), 0, 20, [model.selection("SOLID", "ExtrusionFuse_1_1")])
-ExtrusionCut_15.result().setName("ExtrusionCut_6_1")
-Sketch_18 = model.addSketch(Part_2_doc, model.selection("FACE", "ExtrusionCut_6_1/Modfied_17"))
+Sketch_18 = model.addSketch(Part_2_doc, model.selection("FACE", "ExtrusionCut_6_1/Modfied_10"))
 SketchPoint_36 = Sketch_18.addPoint(53.99994409538203, -1.615587133892632e-027)
 SketchPoint_37 = Sketch_18.addPoint(53.99994409538203, -1.615587133892632e-027)
 SketchConstraintRigid_20 = Sketch_18.setFixed(SketchPoint_37.result())
@@ -1732,8 +1715,7 @@ SketchConstraintCoincidence_314 = Sketch_18.setCoincident(SketchPoint_45.coordin
 SketchConstraintCoincidence_314.setName("SketchConstraintCoincidence_145")
 model.do()
 ExtrusionCut_16 = model.addExtrusionCut(Part_2_doc, [model.selection("COMPOUND", "Sketch_8")], model.selection(), 10, 0, [model.selection("SOLID", "ExtrusionCut_6_1")])
-ExtrusionCut_16.result().setName("ExtrusionCut_7_1")
-Sketch_19 = model.addSketch(Part_2_doc, model.selection("FACE", "ExtrusionCut_7_1/Modfied_56"))
+Sketch_19 = model.addSketch(Part_2_doc, model.selection("FACE", "ExtrusionCut_7_1/Modfied_32"))
 SketchLine_200 = Sketch_19.addLine(21.00014787857639, 4.163450069699051, 21.00014787857639, 0)
 SketchLine_200.setName("SketchLine_107")
 SketchLine_200.result().setName("SketchLine_107")
@@ -1876,7 +1858,6 @@ model.do()
 Plane_12 = model.addPlane(Part_2_doc, model.selection("FACE", "Plane_2"), 4, False)
 Plane_13 = model.addPlane(Part_2_doc, model.selection("FACE", "Plane_2"), 4, True)
 ExtrusionCut_17 = model.addExtrusionCut(Part_2_doc, [model.selection("COMPOUND", "Sketch_9")], model.selection(), model.selection("FACE", "Plane_5"), 0, model.selection("FACE", "Plane_4"), 0, [model.selection("SOLID", "ExtrusionCut_7_1")])
-ExtrusionCut_17.result().setName("ExtrusionCut_8_1")
 Sketch_20 = model.addSketch(Part_2_doc, model.selection("FACE", "ExtrusionCut_8_1/Modfied_5"))
 SketchCircle_2 = Sketch_20.addCircle(12, 6, 1)
 SketchConstraintRadius_22 = Sketch_20.setRadius(SketchCircle_2.results()[1], 1)
@@ -1903,11 +1884,10 @@ SketchConstraintCoincidence_346.setName("SketchConstraintCoincidence_178")
 SketchConstraintDistance_34 = Sketch_20.setDistance(SketchLine_211.result(), SketchCircle_2.center(), 12)
 model.do()
 ExtrusionCut_18 = model.addExtrusionCut(Part_2_doc, [model.selection("WIRE", "Sketch_10/Wire-SketchCircle_1_2f")], model.selection(), 0, 0.75, [model.selection("SOLID", "ExtrusionCut_8_1")])
-ExtrusionCut_18.result().setName("ExtrusionCut_9_1")
 model.do()
-Rotation_1 = model.addRotation(partSet, [model.selection("COMPOUND", "Part_2/")], model.selection("EDGE", "Part_1/ExtrusionCut_9_1/Modfied_1&ExtrusionCut_7_1/Modfied_57"), 180)
+Rotation_1 = model.addRotation(partSet, [model.selection("COMPOUND", "Part_2/")], model.selection("EDGE", "Part_1/ExtrusionCut_9_1/Modfied_1&ExtrusionCut_7_1/Modfied_33"), 180)
 Placement_1 = model.addPlacement(partSet, [model.selection("COMPOUND", "Rotation_1/")], model.selection("FACE", "Rotation_1/ExtrusionCut_5_1/Modfied_1"), model.selection("FACE", "Part_1/ExtrusionCut_5_1/Modfied_1"), False, True)
-Rotation_2 = model.addRotation(partSet, [model.selection("COMPOUND", "Placement_1/")], model.selection("EDGE", "Part_1/ExtrusionCut_5_1/Modfied_8&ExtrusionCut_8_1/Modfied_3"), 7)
+Rotation_2 = model.addRotation(partSet, [model.selection("COMPOUND", "Placement_1/")], model.selection("EDGE", "Part_1/ExtrusionCut_5_1/Modfied_5&ExtrusionCut_8_1/Modfied_3"), 7)
 Rotation_2.result().setColor(255, 85, 0)
 model.end()
 
index 8f5c6417c76764f524391ca60044cb8b6cf8655b..a5a6b2019f5fa1bf0470a4134bdbd838cc0c7ae0 100644 (file)
@@ -117,7 +117,6 @@ SketchConstraintCoincidence_23 = Sketch_1.setCoincident(SketchLine_5.result(), S
 model.do()
 Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchLine_1f-SketchLine_10f-SketchLine_11f-SketchLine_12f-SketchLine_13f-SketchLine_4f-SketchLine_8f-SketchLine_9f-SketchArc_1_2r-SketchArc_2_2f")], model.selection(), "307/2.", "307/2.")
 Extrusion_1.setName("Profil")
-Extrusion_1.result().setName("Extrusion_1_1")
 Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_3"))
 SketchLine_14 = Sketch_2.addLine(149.5, -2.3, 153.5, -2.3)
 SketchPoint_1 = Sketch_2.addPoint(model.selection("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_3&Extrusion_1_1/To_Face_1"))
@@ -158,7 +157,6 @@ SketchConstraintCoincidence_34.setName("SketchConstraintCoincidence_39")
 model.do()
 ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_2")], model.selection(), model.selection("FACE", "Extrusion_1_1/Generated_Face_6"), 0, model.selection(), 0, [model.selection("SOLID", "Extrusion_1_1")])
 ExtrusionCut_1.setName("Decoupe_Angle")
-ExtrusionCut_1.result().setName("ExtrusionCut_1_1")
 Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_2"))
 SketchLine_22 = Sketch_3.addLine(153.5, -10.3, 153.5, -8.3)
 SketchLine_22.setName("SketchLine_29")
@@ -206,7 +204,6 @@ Sketch_3.setName("Sketch_4")
 Sketch_3.result().setName("Sketch_4")
 ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_4")], model.selection(), 0, 10, [model.selection("SOLID", "ExtrusionCut_1_1")])
 ExtrusionCut_2.setName("Chamfrein_1")
-ExtrusionCut_2.result().setName("ExtrusionCut_2_1")
 Sketch_4 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_1_1/Modfied_5"))
 SketchLine_30 = Sketch_4.addLine(-149.5, 10.3, -149.5, 8.3)
 SketchLine_30.setName("SketchLine_35")
@@ -292,7 +289,6 @@ model.do()
 Sketch_4.setName("Sketch_5")
 Sketch_4.result().setName("Sketch_5")
 ExtrusionCut_3 = model.addExtrusionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_5")], model.selection(), model.selection("FACE", "ExtrusionCut_1_1/Modfied_7"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_2_1")])
-ExtrusionCut_3.result().setName("ExtrusionCut_3_1")
 Sketch_5 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_1_1/Modfied_3"))
 SketchLine_40 = Sketch_5.addLine(152.2999838762584, -21.04999053274691, 153.5, -21.04999053274714)
 SketchLine_40.setName("SketchLine_58")
@@ -511,7 +507,6 @@ model.do()
 Sketch_5.setName("Sketch_6")
 Sketch_5.result().setName("Sketch_6")
 ExtrusionCut_4 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_6/Wire-SketchArc_9_2f-SketchArc_10_2f-SketchLine_73r-SketchLine_74r-SketchLine_75r-SketchLine_76r"), model.selection("WIRE", "Sketch_6/Wire-SketchLine_58f-SketchLine_61f-SketchLine_60f-SketchLine_51f-SketchArc_4_2f-SketchArc_5_2f"), model.selection("WIRE", "Sketch_6/Wire-SketchLine_57f-SketchLine_47f-SketchLine_62f-SketchLine_63f-SketchArc_3_2f-SketchArc_6_2f")], model.selection(), 0, 10, [model.selection("SOLID", "ExtrusionCut_3_1")])
-ExtrusionCut_4.result().setName("ExtrusionCut_4_1")
 Sketch_6 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_4_1/Modfied_1"))
 SketchArc_11 = Sketch_6.addArc(44.89, -23.54999053274703, 43.89, -23.54999053274703, 44.89, -22.54999053274703, False)
 SketchArc_12 = Sketch_6.addArc(44.89, -13.54999053274703, 44.89, -14.54999053274703, 43.89, -13.54999053274703, False)
@@ -848,7 +843,6 @@ model.do()
 Sketch_6.setName("Sketch_7")
 Sketch_6.result().setName("Sketch_7")
 ExtrusionCut_5 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_7/Wire-SketchArc_20_2f-SketchArc_21_2f-SketchArc_22_2f-SketchArc_23_2f-SketchLine_91r-SketchLine_92f-SketchLine_93r-SketchLine_94f"), model.selection("WIRE", "Sketch_7/Wire-SketchArc_52_2f-SketchArc_53_2f-SketchArc_56_2f-SketchArc_57_2f-SketchLine_114r-SketchLine_115f-SketchLine_116r-SketchLine_121f"), model.selection("WIRE", "Sketch_7/Wire-SketchArc_44_2f-SketchArc_45_2f-SketchArc_48_2f-SketchArc_49_2f-SketchLine_107f-SketchLine_113f-SketchLine_117r-SketchLine_123r"), model.selection("WIRE", "Sketch_7/Wire-SketchArc_16_2f-SketchArc_17_2f-SketchArc_18_2f-SketchArc_19_2f-SketchLine_87f-SketchLine_88f-SketchLine_89r-SketchLine_90r"), model.selection("WIRE", "Sketch_7/Wire-SketchArc_11_2f-SketchArc_12_2f-SketchArc_14_2f-SketchLine_81f-SketchLine_82r-SketchLine_83f-SketchLine_84r-SketchArc_15_2f"), model.selection("WIRE", "Sketch_7/Wire-SketchArc_36_2f-SketchArc_38_2f-SketchArc_40_2f-SketchArc_41_2f-SketchLine_108r-SketchLine_119r-SketchLine_127f-SketchLine_129f"), model.selection("WIRE", "Sketch_7/Wire-SketchArc_37_2f-SketchArc_39_2f-SketchArc_42_2f-SketchArc_43_2f-SketchLine_118r-SketchLine_120f-SketchLine_122r-SketchLine_130f"), model.selection("WIRE", "Sketch_7/Wire-SketchArc_24_2f-SketchArc_25_2f-SketchArc_26_2f-SketchArc_27_2f-SketchLine_98f-SketchLine_100r-SketchLine_101f-SketchLine_103r"), model.selection("WIRE", "Sketch_7/Wire-SketchArc_30_2f-SketchArc_31_2f-SketchArc_34_2f-SketchArc_35_2f-SketchLine_95f-SketchLine_96r-SketchLine_97f-SketchLine_105r"), model.selection("WIRE", "Sketch_7/Wire-SketchArc_46_2f-SketchArc_47_2f-SketchArc_50_2f-SketchArc_51_2f-SketchLine_124f-SketchLine_125r-SketchLine_126f-SketchLine_128r"), model.selection("WIRE", "Sketch_7/Wire-SketchArc_54_2f-SketchArc_55_2f-SketchArc_58_2f-SketchArc_59_2f-SketchLine_109f-SketchLine_110r-SketchLine_111r-SketchLine_112f"), model.selection("WIRE", "Sketch_7/Wire-SketchArc_28_2f-SketchArc_29_2f-SketchArc_32_2f-SketchArc_33_2f-SketchLine_99r-SketchLine_102f-SketchLine_104f-SketchLine_106r")], model.selection(), 0, 10, [model.selection("SOLID", "ExtrusionCut_4_1")])
-ExtrusionCut_5.result().setName("ExtrusionCut_5_1")
 Sketch_7 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_5_1/Modfied_1"))
 SketchLine_126 = Sketch_7.addLine(-153.5, -37.049990532747, -152.3000099350335, -37.0499905327475)
 SketchLine_126.setName("SketchLine_135")
@@ -942,7 +936,6 @@ model.do()
 Sketch_7.setName("Sketch_8")
 Sketch_7.result().setName("Sketch_8")
 ExtrusionCut_6 = model.addExtrusionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_8")], model.selection(), 0, 10, [model.selection("SOLID", "ExtrusionCut_5_1")])
-ExtrusionCut_6.result().setName("ExtrusionCut_6_1")
 Sketch_8 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_6_1/Modfied_2"))
 SketchLine_134 = Sketch_8.addLine(0.85, 50.75, -0.85, 50.75)
 SketchLine_134.setName("SketchLine_139")
@@ -1067,7 +1060,6 @@ model.do()
 Sketch_8.setName("Sketch_9")
 Sketch_8.result().setName("Sketch_9")
 ExtrusionCut_7 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_9/Face-SketchLine_147f-SketchLine_148f-SketchArc_64_2f-SketchArc_65_2f"), model.selection("FACE", "Sketch_9/Face-SketchLine_139f-SketchLine_141f-SketchArc_63_2f-SketchArc_62_2f"), model.selection("FACE", "Sketch_9/Face-SketchArc_66_2f-SketchArc_67_2f-SketchLine_149r-SketchLine_150r")], model.selection(), 0, 10, [model.selection("SOLID", "ExtrusionCut_6_1")])
-ExtrusionCut_7.result().setName("ExtrusionCut_7_1")
 model.do()
 
 # Test reexecution after parameter change
index 2ab00bd2eba47eceffc3cf5f546b0c9056e9aaae..f6b707a5cebc6c4fbbbb35a5d7149e08a245206f 100644 (file)
@@ -24,9 +24,9 @@ model.begin()
 partSet = model.moduleDocument()
 Part_1 = model.addPart(partSet)
 Part_1_doc = Part_1.document()
-model.addParameter(Part_1_doc, "dint", "58")
-model.addParameter(Part_1_doc, "thick", "16")
-model.addParameter(Part_1_doc, "length", "172")
+Parameter_dint = model.addParameter(Part_1_doc, "dint", "58")
+Parameter_thick = model.addParameter(Part_1_doc, "thick", "16")
+Parameter_length = model.addParameter(Part_1_doc, "length", "172")
 Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
 SketchLine_1 = Sketch_1.addLine(model.selection("EDGE", "PartSet/OZ"))
 SketchArc_1 = Sketch_1.addArc(-1.656176621148808e-020, 61, -36.69142117459658, 34.94736842105263, -1.927105092898643e-024, 106, True)
@@ -83,7 +83,6 @@ SketchConstraintCoincidence_16 = Sketch_2.setCoincident(SketchArc_9.endPoint(),
 model.do()
 Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchArc_9_2f-SketchLine_11f")], model.selection("EDGE", "PartSet/OZ"), 360, 0)
 Boolean_1 = model.addCut(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], [model.selection("SOLID", "Revolution_1_1")])
-Boolean_1.result().setName("Boolean_1_1")
 Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "PartSet/YOZ"))
 SketchLine_12 = Sketch_3.addLine(2.220446049250313e-016, 106, -4, 106)
 SketchLine_13 = Sketch_3.addLine(-4, 106, -4, 67.34428877022477)
@@ -122,8 +121,7 @@ SketchConstraintCoincidence_21.setName("SketchConstraintCoincidence_22")
 model.do()
 Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_3/Wire-SketchLine_12f-SketchLine_13f-SketchLine_17r-SketchLine_18r-SketchArc_10_2f")], model.selection(), "172/2", "172/2")
 Boolean_2 = model.addCut(Part_1_doc, [model.selection("SOLID", "Boolean_1_1")], [model.selection("SOLID", "Extrusion_2_1")])
-Boolean_2.result().setName("Boolean_2_1")
-Sketch_4 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_4"))
+Sketch_4 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_10"))
 SketchLine_18 = Sketch_4.addLine(-65, 16, -65, -16)
 SketchLine_18.setName("SketchLine_19")
 SketchLine_18.result().setName("SketchLine_19")
@@ -169,10 +167,31 @@ SketchConstraintTangent_5 = Sketch_4.setTangent(SketchLine_20.result(), SketchAr
 SketchConstraintTangent_6 = Sketch_4.setTangent(SketchLine_21.result(), SketchArc_11.results()[1])
 SketchConstraintTangent_7 = Sketch_4.setTangent(SketchArc_12.results()[1], SketchLine_20.result())
 model.do()
-Extrusion_3 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_4/Wire-SketchArc_11_2f-SketchArc_12_2f-SketchLine_21f-SketchLine_22r")], model.selection(), model.selection(), 0, model.selection("FACE", "Extrusion_1_1/Generated_Face_2"), 0)
-MultiTranslation_1 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Extrusion_3_1")], model.selection("EDGE", "Extrusion_1_1/To_Face_1&Extrusion_1_1/Generated_Face_2"), -130, 2)
-MultiTranslation_1.result().setName("MultiTranslation_1_1")
-Boolean_3 = model.addCut(Part_1_doc, [model.selection("SOLID", "Boolean_2_1")], [model.selection("COMPOUND", "MultiTranslation_1_1")])
-Boolean_3.result().setName("Boolean_3_1")
+Extrusion_3 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_4/Wire-SketchArc_11_2f-SketchArc_12_2f-SketchLine_21f-SketchLine_22r")], model.selection(), model.selection(), 0, model.selection("FACE", "Extrusion_1_1/Generated_Face_12"), 0)
+MultiTranslation_1 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Extrusion_3_1")], model.selection("EDGE", "Extrusion_1_1/To_Face_1&Extrusion_1_1/Generated_Face_12"), -130, 2)
+Boolean_3 = model.addCut(Part_1_doc, [model.selection("SOLID", "Boolean_2_1")], [model.selection("COMPOUND", "LinearCopy_1_1")])
 model.do()
+
+# Test reexecution after parameter change
+Parameter_dint.setValue(62)
+Parameter_thick.setValue(20)
+Parameter_length.setValue(200)
+model.do()
+model.testResultsVolumes(Boolean_3, [407959.406418853614013642072677612])
+Parameter_dint.setValue(58)
+Parameter_thick.setValue(16)
+Parameter_length.setValue(172)
+
 model.end()
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Boolean_3, 1)
+model.testNbSubResults(Boolean_3, [0])
+model.testNbSubShapes(Boolean_3, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Boolean_3, GeomAPI_Shape.FACE, [32])
+model.testNbSubShapes(Boolean_3, GeomAPI_Shape.EDGE, [192])
+model.testNbSubShapes(Boolean_3, GeomAPI_Shape.VERTEX, [384])
+model.testResultsVolumes(Boolean_3, [305733.913411944580730050802230835])
+
+assert(model.checkPythonDump)
index 065a84dbf35bdfd5599268b9730e6e39eef7fda6..4c042e49a6bb4dc032d372cc78613b283f00ddac 100644 (file)
@@ -197,11 +197,8 @@ SketchConstraintCoincidence_62 = Sketch_4.setCoincident(SketchPoint_6.coordinate
 SketchConstraintDistance_6 = Sketch_4.setDistance(SketchPoint_6.coordinates(), SketchLine_86.result(), 24.5)
 model.do()
 ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), model.selection("FACE", "Revolution_1_1/Generated_Face_5"), 0, model.selection(), 0, [model.selection("SOLID", "Revolution_1_1")])
-ExtrusionCut_1.result().setName("ExtrusionCut_1_1")
 RevolutionCut_1 = model.addRevolutionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_2")], model.selection("EDGE", "PartSet/OX"), 0, 360, [model.selection("SOLID", "ExtrusionCut_1_1")])
-RevolutionCut_1.result().setName("RevolutionCut_1_1")
 ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_3")], model.selection(), 0, 5, [model.selection("SOLID", "RevolutionCut_1_1")])
-ExtrusionCut_2.result().setName("ExtrusionCut_2_1")
 model.do()
 
 # Test reexecution after parameter change
index d3880bd7973daa5a1d2a9f74d3804bee973b9f07..2b08107f3cc0593d37b3adaed69108161858dccb 100644 (file)
@@ -165,11 +165,7 @@ Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-Sketc
 Face_2 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchCircle_3_2"), model.selection("EDGE", "Sketch_1/Edge-SketchCircle_2_2")])
 Face_3 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchCircle_4_2"), model.selection("EDGE", "Sketch_1/Edge-SketchCircle_1_2")])
 Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("FACE", "Face_2_1"), model.selection("FACE", "Face_3_1")], model.selection(), 2, 0)
-Extrusion_2.result().setName("Extrusion_2_1")
-Extrusion_2.results()[1].setName("Extrusion_2_2")
-Extrusion_2.results()[2].setName("Extrusion_2_3")
 Boolean_1 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_2_1"), model.selection("SOLID", "Extrusion_2_2"), model.selection("SOLID", "Extrusion_2_3")], [])
-Boolean_1.result().setName("Boolean_1_1")
 model.do()
 
 # Test reexecution after parameter change
index e9a036f831b45550b4701d9a5437b72eb7b4712e..6c10f5b7ff8e9b06b68cd8cd82844e41bb7d696a 100644 (file)
@@ -129,9 +129,7 @@ SketchConstraintRadius_3 = Sketch_2.setRadius(SketchCircle_2.results()[1], 2.5)
 SketchConstraintDistance_3 = Sketch_2.setDistance(SketchLine_12.result(), SketchCircle_4.center(), 8)
 model.do()
 ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_2/Wire-SketchCircle_1_2f"), model.selection("WIRE", "Sketch_2/Wire-SketchCircle_2_2r"), model.selection("WIRE", "Sketch_2/Wire-SketchCircle_3_2f")], model.selection(), 0, 15, [model.selection("SOLID", "Extrusion_1_1")])
-ExtrusionCut_1.result().setName("ExtrusionCut_1_1")
 ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchCircle_4_2f")], model.selection(), model.selection("FACE", "Extrusion_1_1/From_Face_1"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_1_1")])
-ExtrusionCut_2.result().setName("ExtrusionCut_2_1")
 Sketch_3 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
 SketchCircle_5 = Sketch_3.addCircle(20.99999999999342, 22.99999999999327, 19)
 SketchConstraintRadius_4 = Sketch_3.setRadius(SketchCircle_5.results()[1], 19)
@@ -370,11 +368,7 @@ SketchConstraintMiddle_16 = Sketch_5.setMiddlePoint(SketchLine_37.endPoint(), Sk
 SketchConstraintDistance_12 = Sketch_5.setDistance(SketchCircle_8.center(), SketchLine_37.result(), 8)
 model.do()
 ExtrusionCut_4 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_5/Wire-SketchLine_29f-SketchLine_30r-SketchLine_31r-SketchLine_32r-SketchArc_9_2f-SketchArc_10_2f-SketchArc_11_2f-SketchArc_12_2f")], model.selection(), 0, 15, [model.selection("SOLID", "Extrusion_2_1"), model.selection("SOLID", "ExtrusionCut_3_1")])
-ExtrusionCut_4.result().setName("ExtrusionCut_4_1")
-ExtrusionCut_4.results()[1].setName("ExtrusionCut_4_2")
 ExtrusionCut_5 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_5/Face-SketchCircle_8_2f"), model.selection("FACE", "Sketch_5/Face-SketchCircle_9_2f")], model.selection(), 0, 20, [model.selection("SOLID", "ExtrusionCut_4_1"), model.selection("SOLID", "ExtrusionCut_4_2")])
-ExtrusionCut_5.result().setName("ExtrusionCut_5_1")
-ExtrusionCut_5.results()[1].setName("ExtrusionCut_5_2")
 Sketch_6 = model.addSketch(Part_1_doc, model.selection("FACE", "PartSet/YOZ"))
 SketchLine_38 = Sketch_6.addLine(-59, 44, -59, 2)
 SketchLine_38.setName("SketchLine_39")
@@ -434,7 +428,7 @@ SketchProjection_3 = Sketch_6.addProjection(model.selection("EDGE", "Extrusion_1
 SketchLine_46 = SketchProjection_3.createdFeature()
 SketchLine_46.setName("SketchLine_47")
 SketchLine_46.result().setName("SketchLine_47")
-SketchProjection_4 = Sketch_6.addProjection(model.selection("EDGE", "ExtrusionCut_1_1/Modfied_3&Extrusion_1_1/Generated_Face_5"))
+SketchProjection_4 = Sketch_6.addProjection(model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&ExtrusionCut_1_1/Modfied_1"))
 SketchLine_47 = SketchProjection_4.createdFeature()
 SketchLine_47.setName("SketchLine_48")
 SketchLine_47.result().setName("SketchLine_48")
@@ -446,13 +440,12 @@ SketchConstraintDistance_13 = Sketch_6.setDistance(SketchLine_38.endPoint(), Ske
 SketchConstraintDistance_14 = Sketch_6.setDistance(SketchLine_38.startPoint(), SketchLine_47.result(), 17)
 model.do()
 ExtrusionCut_6 = model.addExtrusionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_6")], model.selection(), model.selection("FACE", "Extrusion_1_1/Generated_Face_5"), -2, model.selection(), -2, [model.selection("SOLID", "ExtrusionCut_5_2")])
-ExtrusionCut_6.result().setName("ExtrusionCut_6_1")
 Sketch_7 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_1"))
 SketchLine_49 = Sketch_7.addLine(0, -22.99999999998656, -76, -22.99999999998655)
 SketchLine_49.setName("SketchLine_50")
 SketchLine_49.result().setName("SketchLine_50")
 SketchLine_49.setAuxiliary(True)
-SketchLine_50 = Sketch_7.addLine(model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&ExtrusionCut_3_1/Modfied_4"))
+SketchLine_50 = Sketch_7.addLine(model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&ExtrusionCut_3_1/Modfied_2"))
 SketchLine_50.setName("SketchLine_51")
 SketchLine_50.result().setName("SketchLine_51")
 SketchConstraintCoincidence_74 = Sketch_7.setCoincident(SketchLine_49.startPoint(), SketchLine_50.result())
@@ -465,7 +458,7 @@ SketchLine_51 = Sketch_7.addLine(-38, -40.99999999998656, -38, -4.99999999998656
 SketchLine_51.setName("SketchLine_52")
 SketchLine_51.result().setName("SketchLine_52")
 SketchLine_51.setAuxiliary(True)
-SketchLine_52 = Sketch_7.addLine(model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&ExtrusionCut_4_2/Modfied_4"))
+SketchLine_52 = Sketch_7.addLine(model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&ExtrusionCut_4_2/Modfied_3"))
 SketchLine_52.setName("SketchLine_53")
 SketchLine_52.result().setName("SketchLine_53")
 SketchConstraintCoincidence_76 = Sketch_7.setCoincident(SketchLine_51.startPoint(), SketchLine_52.result())
@@ -492,7 +485,7 @@ SketchProjection_6 = Sketch_8.addProjection(model.selection("EDGE", "Sketch_2/Ed
 SketchLine_54 = SketchProjection_6.createdFeature()
 SketchLine_54.setName("SketchLine_55")
 SketchLine_54.result().setName("SketchLine_55")
-SketchProjection_7 = Sketch_8.addProjection(model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&ExtrusionCut_3_1/Modfied_4"))
+SketchProjection_7 = Sketch_8.addProjection(model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&ExtrusionCut_3_1/Modfied_2"))
 SketchLine_55 = SketchProjection_7.createdFeature()
 SketchLine_55.setName("SketchLine_56")
 SketchLine_55.result().setName("SketchLine_56")
@@ -517,11 +510,11 @@ SketchConstraintMiddle_23 = Sketch_8.setMiddlePoint(SketchLine_56.result(), Sket
 SketchConstraintCoincidence_83 = Sketch_8.setCoincident(SketchLine_57.result(), SketchPoint_5.coordinates())
 SketchConstraintCoincidence_83.setName("SketchConstraintCoincidence_84")
 SketchConstraintPerpendicular_1 = Sketch_8.setPerpendicular(SketchLine_57.result(), SketchLine_56.result())
-SketchProjection_8 = Sketch_8.addProjection(model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&ExtrusionCut_4_2/Modfied_4"))
+SketchProjection_8 = Sketch_8.addProjection(model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&ExtrusionCut_4_2/Modfied_3"))
 SketchLine_58 = SketchProjection_8.createdFeature()
 SketchLine_58.setName("SketchLine_59")
 SketchLine_58.result().setName("SketchLine_59")
-SketchProjection_9 = Sketch_8.addProjection(model.selection("EDGE", "Extrusion_1_1/Generated_Face_8&Extrusion_1_1/Generated_Face_7"))
+SketchProjection_9 = Sketch_8.addProjection(model.selection("EDGE", "Extrusion_1_1/Generated_Face_8&Extrusion_1_1/Generated_Face_1"))
 SketchLine_59 = SketchProjection_9.createdFeature()
 SketchLine_59.setName("SketchLine_60")
 SketchLine_59.result().setName("SketchLine_60")
@@ -541,7 +534,7 @@ SketchConstraintDistance_15 = Sketch_8.setDistance(SketchCircle_11.center(), Ske
 SketchConstraintDistance_16 = Sketch_8.setDistance(SketchCircle_11.center(), SketchCircle_12.center(), 16)
 model.do()
 Extrusion_4 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_8/Face-SketchCircle_11_2f"), model.selection("FACE", "Sketch_8/Face-SketchCircle_12_2f")], model.selection(), 17, 0)
-Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "ExtrusionCut_3_1/Modfied_4"), 38, True)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "ExtrusionCut_3_1/Modfied_2"), 38, True)
 Sketch_9 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
 SketchLine_60 = Sketch_9.addLine(-14, -36.99999999998992, 0, -36.99999999998992)
 SketchLine_60.setName("SketchLine_61")
@@ -586,7 +579,6 @@ SketchConstraintCoincidence_94 = Sketch_9.setCoincident(SketchLine_60.endPoint()
 SketchConstraintCoincidence_94.setName("SketchConstraintCoincidence_95")
 model.do()
 RevolutionCut_1 = model.addRevolutionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_9")], model.selection("EDGE", "Sketch_9/Edge-SketchLine_65"), 360, 0, [model.selection("SOLID", "Extrusion_3_1")])
-RevolutionCut_1.result().setName("RevolutionCut_1_1")
 model.do()
 
 from GeomAPI import  GeomAPI_Shape
index 969bfacd3aa66644f548a112c670f865715b94d6..b10608231e774f5a442db59132134955aca87c66 100644 (file)
@@ -260,9 +260,7 @@ SketchConstraintDistance_17 = Sketch_3.setDistance(SketchLine_26.result(), Sketc
 SketchConstraintLength_4 = Sketch_3.setLength(SketchLine_26.result(), "d7*coeff")
 model.do()
 ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_24r-SketchLine_26r-SketchLine_27r-SketchLine_28r-SketchLine_29r")], model.selection(), model.selection("FACE", "Extrusion_2_1/Generated_Face_6"), 0, model.selection(), 0, [model.selection("SOLID", "Extrusion_2_1")])
-ExtrusionCut_1.result().setName("ExtrusionCut_1_1")
 ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_30r-SketchLine_31r-SketchLine_32r-SketchLine_33r")], model.selection(), model.selection("FACE", "Extrusion_1_1/To_Face_1"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_1_1")])
-ExtrusionCut_2.result().setName("ExtrusionCut_2_1")
 Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_1"), "d3*coeff", True)
 Sketch_4 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_2"))
 SketchProjection_5 = Sketch_4.addProjection(model.selection("EDGE", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/To_Face_1"))
@@ -317,7 +315,6 @@ SketchConstraintDistance_22 = Sketch_5.setDistance(SketchCircle_1.center(), Sket
 SketchConstraintRadius_7 = Sketch_5.setRadius(SketchCircle_1.results()[1], "r_trou")
 model.do()
 ExtrusionCut_3 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_5/Face-SketchCircle_1_2f")], model.selection(), model.selection("FACE", "ExtrusionCut_1_1/Modfied_6"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_2_1")])
-ExtrusionCut_3.result().setName("ExtrusionCut_3_1")
 Sketch_6 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_6"))
 SketchCircle_2 = Sketch_6.addCircle(70, -17.5, 5)
 SketchLine_48 = Sketch_6.addLine(model.selection("EDGE", "Extrusion_1_1/Generated_Face_6&Extrusion_1_1/To_Face_1"))
@@ -331,7 +328,6 @@ SketchConstraintDistance_24 = Sketch_6.setDistance(SketchCircle_2.center(), Sket
 SketchConstraintDistance_24.setName("SketchConstraintDistance_25")
 model.do()
 ExtrusionCut_4 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_6/Face-SketchCircle_2_2f")], model.selection(), model.selection("FACE", "Extrusion_1_1/Generated_Face_16"), 0, model.selection(), 0, [model.selection("SOLID", "Extrusion_1_1")])
-ExtrusionCut_4.result().setName("ExtrusionCut_4_1")
 Sketch_7 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_12"))
 SketchLine_51 = Sketch_7.addLine(110, 21.46600893000899, 110, 7.22841614740048)
 SketchLine_51.setAuxiliary(True)
@@ -376,9 +372,7 @@ SketchConstraintMirror_2 = Sketch_7.addMirror(SketchLine_59.result(), SketchCons
 [SketchArc_17, SketchLine_63, SketchLine_64, SketchArc_18, SketchLine_65, SketchLine_66] = SketchConstraintMirror_2.mirrored()
 model.do()
 ExtrusionCut_5 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_7/Wire-SketchArc_16_2r-SketchLine_61f-SketchLine_62r"), model.selection("FACE", "Sketch_7/Face-SketchArc_18_2r-SketchLine_65f-SketchLine_66r"), model.selection("FACE", "Sketch_7/Face-SketchArc_17_2r-SketchLine_64r-SketchLine_66r"), model.selection("WIRE", "Sketch_7/Wire-SketchArc_15_2r-SketchLine_54f-SketchLine_55r")], model.selection(), model.selection("FACE", "Extrusion_1_1/Generated_Face_10"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_4_1")])
-ExtrusionCut_5.result().setName("ExtrusionCut_5_1")
 Boolean_1 = model.addFuse(Part_1_doc, [model.selection("SOLID", "ExtrusionCut_5_1")], [model.selection("SOLID", "Extrusion_3_1"), model.selection("SOLID", "ExtrusionCut_3_1")])
-Boolean_1.result().setName("Boolean_1_1")
 model.do()
 
 from GeomAPI import  GeomAPI_Shape
index f4159d38f069bd1a5ea1572e64cc53f86ceeef3a..1868b2b2d68a1e1c09335b5efdd99339a53d7847 100644 (file)
@@ -343,14 +343,9 @@ SketchConstraintRadius_9.setName("SketchConstraintRadius_6")
 model.do()
 Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_2")], model.selection(), "10*coeff", 0)
 ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchCircle_3_2f")], model.selection(), "p_trou1*coeff", 0, [model.selection("SOLID", "Extrusion_1_1")])
-ExtrusionCut_1.result().setName("ExtrusionCut_1_1")
 ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchCircle_1_2r")], model.selection(), "p2_trou1*coeff", 0, [model.selection("SOLID", "ExtrusionCut_1_1")])
-ExtrusionCut_2.result().setName("ExtrusionCut_2_1")
 ExtrusionCut_3 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_4_2f")], model.selection(), "p_trou2*coeff", 0, [model.selection("SOLID", "Extrusion_2_1"), model.selection("SOLID", "ExtrusionCut_2_1")])
-ExtrusionCut_3.result().setName("ExtrusionCut_3_1")
-ExtrusionCut_3.results()[1].setName("ExtrusionCut_3_2")
 ExtrusionCut_4 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchCircle_2_2r")], model.selection(), "p2_trou*coeff", 0, [model.selection("SOLID", "ExtrusionCut_3_2")])
-ExtrusionCut_4.result().setName("ExtrusionCut_4_1")
 Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOY"), "22.5*coeff", False)
 Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Plane_1"), "45*coeff", True)
 Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_2"))
@@ -437,11 +432,8 @@ SketchConstraintDistance_14.setName("SketchConstraintDistance_12")
 model.do()
 Extrusion_3 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_3/Wire-SketchLine_9r-SketchLine_12r-SketchLine_14r-SketchLine_26r-SketchLine_27r-SketchLine_28r")], model.selection(), model.selection("FACE", "Extrusion_1_1/Generated_Face_3"), 0, model.selection(), 0)
 Boolean_1 = model.addSmash(Part_1_doc, [model.selection("SOLID", "Extrusion_3_1")], [model.selection("SOLID", "ExtrusionCut_4_1")])
-Boolean_1.result().setName("Boolean_1_1")
 ExtrusionCut_5 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_3/Wire-SketchCircle_8_2f")], model.selection(), 10, 0, [model.selection("SOLID", "Boolean_1_1_1")])
-ExtrusionCut_5.result().setName("ExtrusionCut_5_1")
 ExtrusionCut_6 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchCircle_8_2f")], model.selection(), 10, 0, [model.selection("SOLID", "ExtrusionCut_5_1_1")])
-ExtrusionCut_6.result().setName("ExtrusionCut_6_1")
 Axis_4 = model.addAxis(Part_1_doc, model.selection("FACE", "ExtrusionCut_6_1_2/Modfied_1"))
 Sketch_4 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
 SketchProjection_7 = Sketch_4.addProjection(model.selection("EDGE", "PartSet/OY"))
@@ -528,12 +520,9 @@ SketchConstraintLength_10.setName("SketchConstraintLength_7")
 model.do()
 Extrusion_4 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_4/Wire-SketchLine_19f-SketchLine_20f-SketchLine_24f-SketchLine_21f-SketchLine_22f-SketchLine_23f")], model.selection(), model.selection("FACE", "Extrusion_1_1/Generated_Face_1"), 0, model.selection(), 0)
 Boolean_2 = model.addSmash(Part_1_doc, [model.selection("SOLID", "ExtrusionCut_6_1_1"), model.selection("SOLID", "Extrusion_4_1")], [model.selection("SOLID", "ExtrusionCut_6_1_2")])
-Boolean_2.result().setName("Boolean_2_1")
 ExtrusionCut_7 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_4/Face-SketchCircle_9_2f")], model.selection(), 0, 10, [model.selection("SOLID", "Boolean_2_1_1")])
-ExtrusionCut_7.result().setName("ExtrusionCut_7_1")
 ExtrusionCut_8 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_4/Face-SketchCircle_9_2f")], model.selection(), 0, 10, [model.selection("SOLID", "ExtrusionCut_7_1_1")])
-ExtrusionCut_8.result().setName("ExtrusionCut_8_1")
-Sketch_5 = model.addSketch(Part_1_doc, model.selection("FACE", "Boolean_2_1_1/Modified_1"))
+Sketch_5 = model.addSketch(Part_1_doc, model.selection("FACE", "Boolean_2_1_1/Modified_Face_1"))
 SketchPoint_3 = Sketch_5.addPoint(model.selection("VERTEX", "PartSet/Origin"))
 SketchPoint_3.setName("SketchPoint_2")
 SketchPoint_3.result().setName("SketchPoint_2")
@@ -675,7 +664,6 @@ SketchConstraintRadius_14 = Sketch_7.setRadius(SketchCircle_11.results()[1], "r3
 SketchConstraintRadius_14.setName("SketchConstraintRadius_12")
 model.do()
 ExtrusionCut_9 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_7/Wire-SketchCircle_10_2f")], model.selection(), 0, "10*coeff", [model.selection("SOLID", "Extrusion_6_1")])
-ExtrusionCut_9.result().setName("ExtrusionCut_9_1")
 ExtrusionCut_10 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_1/Wire-SketchArc_7_2r-SketchArc_10_2f-SketchLine_44r-SketchArc_12_2r-SketchArc_13_2r-SketchLine_48r-SketchLine_43f-SketchArc_14_2f"), model.selection("FACE", "Sketch_1/Face-SketchCircle_11_2f"), model.selection("WIRE", "Sketch_1/Wire-SketchLine_50f-SketchArc_15_2f-SketchArc_16_2r-SketchLine_51r-SketchArc_17_2r-SketchLine_52f"), model.selection("FACE", "Sketch_1/Face-SketchLine_53f-SketchArc_18_2r-SketchLine_54f-SketchArc_19_2r-SketchArc_20_2f-SketchLine_55r-SketchArc_21_2f-SketchArc_22_2r"), model.selection("FACE", "Sketch_1/Face-SketchArc_8_2r-SketchArc_9_2f-SketchLine_42r-SketchLine_45f-SketchLine_46r-SketchArc_11_2r")], model.selection(), model.selection("FACE", "ExtrusionCut_3_2/Modfied_1"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_8_1_2")])
 Sketch_8 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_9_1/Modfied_1"))
 SketchLine_50 = Sketch_8.addLine(37, 14.80042035331162, 37, -14)
@@ -776,7 +764,6 @@ SketchConstraintRadius_16 = Sketch_9.setRadius(SketchArc_23.results()[1], "3*coe
 SketchConstraintRadius_16.setName("SketchConstraintRadius_17")
 model.do()
 ExtrusionCut_12 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_9/Face-SketchArc_25_2r-SketchLine_67f-SketchLine_68f")], model.selection(), 0, "100*coeff", [model.selection("SOLID", "Extrusion_5_1")])
-ExtrusionCut_12.result().setName("ExtrusionCut_12_1")
 model.do()
 
 from GeomAPI import  GeomAPI_Shape