Salome HOME
merge V7_7_BR
authorPaul RASCLE <paul.rascle@edf.fr>
Mon, 1 Feb 2016 14:23:06 +0000 (15:23 +0100)
committerPaul RASCLE <paul.rascle@edf.fr>
Mon, 1 Feb 2016 14:23:06 +0000 (15:23 +0100)
303 files changed:
CMakeLists.txt
doc/salome/examples/CMakeLists.txt
doc/salome/examples/split_biquad.py [new file with mode: 0644]
doc/salome/examples/transforming_meshes_ex01.py
doc/salome/examples/transforming_meshes_ex05.py
doc/salome/examples/transforming_meshes_ex09.py
doc/salome/examples/transforming_meshes_ex10.py
doc/salome/gui/SMESH/images/extru_rib_segs.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/extrusionalongaline2.png
doc/salome/gui/SMESH/images/extrusionalongaline3.png
doc/salome/gui/SMESH/images/free_borders1.png [changed mode: 0755->0644]
doc/salome/gui/SMESH/images/hexa_ijk_mesh.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/image152.png [changed mode: 0755->0644]
doc/salome/gui/SMESH/images/image88.jpg [changed mode: 0755->0644]
doc/salome/gui/SMESH/images/mergeelems.png [changed mode: 0755->0644]
doc/salome/gui/SMESH/images/mergeelems_auto.png
doc/salome/gui/SMESH/images/mergenodes.png [changed mode: 0755->0644]
doc/salome/gui/SMESH/images/mergenodes_auto.png
doc/salome/gui/SMESH/images/merging_nodes1.png [changed mode: 0755->0644]
doc/salome/gui/SMESH/images/merging_nodes2.png [changed mode: 0755->0644]
doc/salome/gui/SMESH/images/preview_tmp_data.png
doc/salome/gui/SMESH/images/revolutionsn1.png
doc/salome/gui/SMESH/images/revolutionsn2.png
doc/salome/gui/SMESH/images/sew_after_merge.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/sew_using_merge.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/sewing1.png [changed mode: 0755->0644]
doc/salome/gui/SMESH/images/sewing2.png [changed mode: 0755->0644]
doc/salome/gui/SMESH/images/sewing3.png [changed mode: 0755->0644]
doc/salome/gui/SMESH/images/sewing4.png [changed mode: 0755->0644]
doc/salome/gui/SMESH/images/sewing_auto.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/sewing_manual.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/split_biquad_to_linear_dlg.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/split_biquad_to_linear_icon.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/split_biquad_to_linear_mesh.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/swap.png [new file with mode: 0644]
doc/salome/gui/SMESH/input/1d_meshing_hypo.doc
doc/salome/gui/SMESH/input/2d_meshing_hypo.doc
doc/salome/gui/SMESH/input/about_filters.doc
doc/salome/gui/SMESH/input/about_hypo.doc
doc/salome/gui/SMESH/input/about_meshes.doc
doc/salome/gui/SMESH/input/about_quality_controls.doc
doc/salome/gui/SMESH/input/adding_nodes_and_elements.doc
doc/salome/gui/SMESH/input/adding_quadratic_elements.doc
doc/salome/gui/SMESH/input/additional_hypo.doc
doc/salome/gui/SMESH/input/basic_meshing_algos.doc
doc/salome/gui/SMESH/input/borders_at_multi_connection.doc
doc/salome/gui/SMESH/input/borders_at_multi_connection_2d.doc
doc/salome/gui/SMESH/input/building_compounds.doc
doc/salome/gui/SMESH/input/cartesian_algo.doc
doc/salome/gui/SMESH/input/changing_orientation_of_elements.doc
doc/salome/gui/SMESH/input/constructing_meshes.doc
doc/salome/gui/SMESH/input/constructing_submeshes.doc
doc/salome/gui/SMESH/input/convert_to_from_quadratic_mesh.doc
doc/salome/gui/SMESH/input/create_groups_from_geometry.doc
doc/salome/gui/SMESH/input/creating_groups.doc
doc/salome/gui/SMESH/input/diagonal_inversion_of_elements.doc
doc/salome/gui/SMESH/input/extrusion.doc
doc/salome/gui/SMESH/input/free_borders.doc
doc/salome/gui/SMESH/input/free_edges.doc
doc/salome/gui/SMESH/input/group_of_underlying_elements.doc
doc/salome/gui/SMESH/input/grouping_elements.doc
doc/salome/gui/SMESH/input/importing_exporting_meshes.doc
doc/salome/gui/SMESH/input/index.doc
doc/salome/gui/SMESH/input/merging_elements.doc
doc/salome/gui/SMESH/input/merging_nodes.doc
doc/salome/gui/SMESH/input/mesh_infos.doc
doc/salome/gui/SMESH/input/mesh_preferences.doc
doc/salome/gui/SMESH/input/modifying_meshes.doc
doc/salome/gui/SMESH/input/pattern_mapping.doc
doc/salome/gui/SMESH/input/quad_from_ma_algo.doc
doc/salome/gui/SMESH/input/quad_ijk_algo.doc
doc/salome/gui/SMESH/input/reorient_faces.doc
doc/salome/gui/SMESH/input/revolution.doc
doc/salome/gui/SMESH/input/segments_around_vertex_algo.doc
doc/salome/gui/SMESH/input/selection_filter_library.doc
doc/salome/gui/SMESH/input/sewing_meshes.doc
doc/salome/gui/SMESH/input/smoothing.doc
doc/salome/gui/SMESH/input/split_biquad_to_linear.doc [new file with mode: 0644]
doc/salome/gui/SMESH/input/split_to_tetra.doc
doc/salome/gui/SMESH/input/symmetry.doc
doc/salome/gui/SMESH/input/tui_modifying_meshes.doc
doc/salome/gui/SMESH/input/uniting_set_of_triangles.doc
doc/salome/gui/SMESH/input/uniting_two_triangles.doc
doc/salome/gui/SMESH/input/viewing_meshes_overview.doc
idl/SMESH_BasicHypothesis.idl
idl/SMESH_Gen.idl
idl/SMESH_Mesh.idl
idl/SMESH_MeshEditor.idl
resources/CMakeLists.txt
resources/StdMeshers.xml.in
resources/mesh_quad_polygon.png [new file with mode: 0644]
resources/mesh_tree_algo_polygon.png [new file with mode: 0644]
resources/split_biquad.png [new file with mode: 0644]
src/Controls/SMESH_Controls.cxx
src/Controls/SMESH_ControlsDef.hxx
src/DriverCGNS/DriverCGNS_Write.cxx
src/DriverDAT/DriverDAT_W_SMDS_Mesh.cxx
src/DriverMED/DriverMED_R_SMESHDS_Mesh.cxx
src/DriverMED/DriverMED_W_SMESHDS_Mesh.cxx
src/DriverSTL/DriverSTL_W_SMDS_Mesh.cxx
src/DriverSTL/DriverSTL_W_SMDS_Mesh.h
src/MEDWrapper/Base/MED_Common.hxx
src/MEDWrapper/Base/MED_Utilities.cxx
src/MEDWrapper/V2_2/MED_V2_2_Wrapper.cxx
src/OBJECT/CMakeLists.txt
src/OBJECT/SMESH_Actor.cxx
src/OBJECT/SMESH_ExtractGeometry.cxx
src/OBJECT/SMESH_Object.cxx
src/OBJECT/SMESH_SVTKActor.cxx
src/SMDS/SMDS_Mesh.cxx
src/SMDS/SMDS_Mesh.hxx
src/SMDS/SMDS_Mesh0DElement.cxx
src/SMDS/SMDS_Mesh0DElement.hxx
src/SMDS/SMDS_MeshCell.cxx
src/SMDS/SMDS_MeshCell.hxx
src/SMDS/SMDS_MeshInfo.hxx
src/SMDS/SMDS_MeshNode.cxx
src/SMDS/SMDS_PolygonalFaceOfNodes.cxx
src/SMDS/SMDS_PolygonalFaceOfNodes.hxx
src/SMDS/SMDS_VolumeTool.cxx
src/SMDS/SMDS_VolumeTool.hxx
src/SMDS/SMDS_VtkCellIterator.cxx
src/SMDS/SMDS_VtkFace.cxx
src/SMDS/SMDS_VtkFace.hxx
src/SMESH/SMESH_Algo.cxx
src/SMESH/SMESH_Algo.hxx
src/SMESH/SMESH_Gen.cxx
src/SMESH/SMESH_Gen.hxx
src/SMESH/SMESH_Mesh.cxx
src/SMESH/SMESH_Mesh.hxx
src/SMESH/SMESH_MeshEditor.cxx
src/SMESH/SMESH_MeshEditor.hxx
src/SMESH/SMESH_MesherHelper.cxx
src/SMESH/SMESH_MesherHelper.hxx
src/SMESH/SMESH_Pattern.cxx
src/SMESH/SMESH_subMesh.cxx
src/SMESH/SMESH_subMesh.hxx
src/SMESHClient/SMESH_Client.cxx
src/SMESHDS/SMESHDS_Command.cxx
src/SMESHDS/SMESHDS_Command.hxx
src/SMESHDS/SMESHDS_CommandType.hxx
src/SMESHDS/SMESHDS_Document.cxx
src/SMESHDS/SMESHDS_Mesh.cxx
src/SMESHDS/SMESHDS_Mesh.hxx
src/SMESHDS/SMESHDS_Script.cxx
src/SMESHDS/SMESHDS_Script.hxx
src/SMESHDS/SMESHDS_SubMesh.cxx
src/SMESHDS/SMESHDS_SubMesh.hxx
src/SMESHGUI/CMakeLists.txt
src/SMESHGUI/SMESHGUI.cxx
src/SMESHGUI/SMESHGUI.h
src/SMESHGUI/SMESHGUI_Add0DElemsOnAllNodesDlg.cxx
src/SMESHGUI/SMESHGUI_Add0DElemsOnAllNodesDlg.h
src/SMESHGUI/SMESHGUI_AddMeshElementDlg.cxx
src/SMESHGUI/SMESHGUI_AddMeshElementDlg.h
src/SMESHGUI/SMESHGUI_AddQuadraticElementDlg.cxx
src/SMESHGUI/SMESHGUI_AddQuadraticElementDlg.h
src/SMESHGUI/SMESHGUI_ComputeDlg.cxx
src/SMESHGUI/SMESHGUI_ConvToQuadOp.cxx
src/SMESHGUI/SMESHGUI_CopyMeshDlg.cxx
src/SMESHGUI/SMESHGUI_CopyMeshDlg.h
src/SMESHGUI/SMESHGUI_CreatePatternDlg.cxx
src/SMESHGUI/SMESHGUI_CreatePatternDlg.h
src/SMESHGUI/SMESHGUI_CreatePolyhedralVolumeDlg.cxx
src/SMESHGUI/SMESHGUI_CreatePolyhedralVolumeDlg.h
src/SMESHGUI/SMESHGUI_DisplayEntitiesDlg.h
src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.cxx
src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.h
src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx
src/SMESHGUI/SMESHGUI_ExtrusionDlg.h
src/SMESHGUI/SMESHGUI_FilterDlg.cxx
src/SMESHGUI/SMESHGUI_FilterDlg.h
src/SMESHGUI/SMESHGUI_FindElemByPointDlg.cxx
src/SMESHGUI/SMESHGUI_FindElemByPointDlg.h
src/SMESHGUI/SMESHGUI_GroupDlg.cxx
src/SMESHGUI/SMESHGUI_GroupDlg.h
src/SMESHGUI/SMESHGUI_GroupOpDlg.cxx
src/SMESHGUI/SMESHGUI_GroupOpDlg.h
src/SMESHGUI/SMESHGUI_Hypotheses.cxx
src/SMESHGUI/SMESHGUI_Hypotheses.h
src/SMESHGUI/SMESHGUI_IdPreview.cxx [new file with mode: 0644]
src/SMESHGUI/SMESHGUI_IdPreview.h [new file with mode: 0644]
src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.cxx
src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.h
src/SMESHGUI/SMESHGUI_MergeDlg.cxx
src/SMESHGUI/SMESHGUI_MergeDlg.h
src/SMESHGUI/SMESHGUI_MeshInfo.cxx
src/SMESHGUI/SMESHGUI_MeshInfo.h
src/SMESHGUI/SMESHGUI_MeshInfosBox.cxx
src/SMESHGUI/SMESHGUI_MeshInfosBox.h
src/SMESHGUI/SMESHGUI_MeshOp.cxx
src/SMESHGUI/SMESHGUI_MeshOp.h
src/SMESHGUI/SMESHGUI_MeshPatternDlg.cxx
src/SMESHGUI/SMESHGUI_MeshPatternDlg.h
src/SMESHGUI/SMESHGUI_MultiEditDlg.cxx
src/SMESHGUI/SMESHGUI_MultiEditDlg.h
src/SMESHGUI/SMESHGUI_NodesDlg.cxx
src/SMESHGUI/SMESHGUI_NodesDlg.h
src/SMESHGUI/SMESHGUI_Operations.h
src/SMESHGUI/SMESHGUI_PreVisualObj.cxx [new file with mode: 0644]
src/SMESHGUI/SMESHGUI_PreVisualObj.h [new file with mode: 0644]
src/SMESHGUI/SMESHGUI_PreviewDlg.cxx
src/SMESHGUI/SMESHGUI_PreviewDlg.h
src/SMESHGUI/SMESHGUI_RemoveElementsDlg.cxx
src/SMESHGUI/SMESHGUI_RemoveElementsDlg.h
src/SMESHGUI/SMESHGUI_RemoveNodesDlg.cxx
src/SMESHGUI/SMESHGUI_RemoveNodesDlg.h
src/SMESHGUI/SMESHGUI_RevolutionDlg.cxx
src/SMESHGUI/SMESHGUI_RevolutionDlg.h
src/SMESHGUI/SMESHGUI_RotationDlg.cxx
src/SMESHGUI/SMESHGUI_RotationDlg.h
src/SMESHGUI/SMESHGUI_ScaleDlg.cxx
src/SMESHGUI/SMESHGUI_ScaleDlg.h
src/SMESHGUI/SMESHGUI_Selection.cxx
src/SMESHGUI/SMESHGUI_Selection.h
src/SMESHGUI/SMESHGUI_SewingDlg.cxx
src/SMESHGUI/SMESHGUI_SewingDlg.h
src/SMESHGUI/SMESHGUI_SingleEditDlg.cxx
src/SMESHGUI/SMESHGUI_SingleEditDlg.h
src/SMESHGUI/SMESHGUI_SmoothingDlg.cxx
src/SMESHGUI/SMESHGUI_SmoothingDlg.h
src/SMESHGUI/SMESHGUI_SplitBiQuad.cxx [new file with mode: 0644]
src/SMESHGUI/SMESHGUI_SplitBiQuad.h [new file with mode: 0644]
src/SMESHGUI/SMESHGUI_SymmetryDlg.cxx
src/SMESHGUI/SMESHGUI_SymmetryDlg.h
src/SMESHGUI/SMESHGUI_TranslationDlg.cxx
src/SMESHGUI/SMESHGUI_TranslationDlg.h
src/SMESHGUI/SMESHGUI_Utils.cxx
src/SMESHGUI/SMESH_images.ts
src/SMESHGUI/SMESH_msg_en.ts
src/SMESHGUI/SMESH_msg_fr.ts
src/SMESHGUI/SMESH_msg_ja.ts
src/SMESHUtils/CMakeLists.txt
src/SMESHUtils/SMESH_Block.cxx
src/SMESHUtils/SMESH_FreeBorders.cxx [new file with mode: 0644]
src/SMESHUtils/SMESH_MAT2d.cxx
src/SMESHUtils/SMESH_MAT2d.hxx
src/SMESHUtils/SMESH_MeshAlgos.cxx
src/SMESHUtils/SMESH_MeshAlgos.hxx
src/SMESHUtils/SMESH_OctreeNode.cxx
src/SMESHUtils/SMESH_OctreeNode.hxx
src/SMESHUtils/SMESH_TypeDefs.hxx
src/SMESH_I/SMESH_2smeshpy.cxx
src/SMESH_I/SMESH_DumpPython.cxx
src/SMESH_I/SMESH_Filter_i.cxx
src/SMESH_I/SMESH_Filter_i.hxx
src/SMESH_I/SMESH_Gen_i.cxx
src/SMESH_I/SMESH_Gen_i.hxx
src/SMESH_I/SMESH_Gen_i_1.cxx
src/SMESH_I/SMESH_Group_i.cxx
src/SMESH_I/SMESH_MeshEditor_i.cxx
src/SMESH_I/SMESH_MeshEditor_i.hxx
src/SMESH_I/SMESH_Mesh_i.cxx
src/SMESH_I/SMESH_Mesh_i.hxx
src/SMESH_I/SMESH_Pattern_i.cxx
src/SMESH_I/SMESH_PythonDump.hxx
src/SMESH_I/SMESH_subMesh_i.cxx
src/SMESH_SWIG/CMakeLists.txt
src/SMESH_SWIG/StdMeshersBuilder.py
src/SMESH_SWIG/smeshBuilder.py
src/SMESH_SWIG/smesh_algorithm.py
src/SMESH_SWIG/smesh_selection.py [new file with mode: 0644]
src/SMESH_SWIG_WITHIHM/CMakeLists.txt
src/SMESH_SWIG_WITHIHM/libSMESH_Swig.cxx
src/SMESH_SWIG_WITHIHM/libSMESH_Swig.h
src/SMESH_SWIG_WITHIHM/libSMESH_Swig.i
src/StdMeshers/CMakeLists.txt
src/StdMeshers/StdMeshers_Adaptive1D.cxx
src/StdMeshers/StdMeshers_CompositeHexa_3D.cxx
src/StdMeshers/StdMeshers_CompositeHexa_3D.hxx
src/StdMeshers/StdMeshers_FaceSide.cxx
src/StdMeshers/StdMeshers_FaceSide.hxx
src/StdMeshers/StdMeshers_Import_1D.cxx
src/StdMeshers/StdMeshers_Import_1D2D.cxx
src/StdMeshers/StdMeshers_Penta_3D.cxx
src/StdMeshers/StdMeshers_PolygonPerFace_2D.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_PolygonPerFace_2D.hxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_Projection_2D.cxx
src/StdMeshers/StdMeshers_QuadFromMedialAxis_1D2D.cxx
src/StdMeshers/StdMeshers_QuadFromMedialAxis_1D2D.hxx
src/StdMeshers/StdMeshers_Quadrangle_2D.cxx
src/StdMeshers/StdMeshers_Quadrangle_2D.hxx
src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.cxx
src/StdMeshersGUI/CMakeLists.txt
src/StdMeshersGUI/StdMeshersGUI_DistrPreview.cxx
src/StdMeshersGUI/StdMeshersGUI_LayerDistributionParamWdg.cxx
src/StdMeshersGUI/StdMeshersGUI_NbSegmentsCreator.cxx
src/StdMeshersGUI/StdMeshersGUI_NbSegmentsCreator.h
src/StdMeshersGUI/StdMeshersGUI_ObjectReferenceParamWdg.h
src/StdMeshersGUI/StdMeshersGUI_StdHypothesisCreator.cxx
src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.cxx
src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.h
src/StdMeshersGUI/StdMeshers_images.ts
src/StdMeshersGUI/StdMeshers_msg_en.ts
src/StdMeshersGUI/StdMeshers_msg_ja.ts
src/StdMeshers_I/CMakeLists.txt
src/StdMeshers_I/StdMeshers_PolygonPerFace_2D_i.cxx [new file with mode: 0644]
src/StdMeshers_I/StdMeshers_PolygonPerFace_2D_i.hxx [new file with mode: 0644]
src/StdMeshers_I/StdMeshers_Quadrangle_2D_i.cxx
src/StdMeshers_I/StdMeshers_Quadrangle_2D_i.hxx
src/StdMeshers_I/StdMeshers_i.cxx
src/Tools/padder/meshjob/impl/MeshJobManager_i.cxx
src/Tools/padder/spadderpy/gui/plugindialog.py

index b308616a7f77896555e04c5dd74f1ffdfc3f3371..08f74713394c0b9db53c69d8a5eeadbc612731dc 100755 (executable)
@@ -28,8 +28,8 @@ CMAKE_POLICY(SET CMP0003 NEW)
 STRING(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UC)
 
 SET(${PROJECT_NAME_UC}_MAJOR_VERSION 7)
-SET(${PROJECT_NAME_UC}_MINOR_VERSION 6)
-SET(${PROJECT_NAME_UC}_PATCH_VERSION 0)
+SET(${PROJECT_NAME_UC}_MINOR_VERSION 7)
+SET(${PROJECT_NAME_UC}_PATCH_VERSION 1)
 SET(${PROJECT_NAME_UC}_VERSION
   ${${PROJECT_NAME_UC}_MAJOR_VERSION}.${${PROJECT_NAME_UC}_MINOR_VERSION}.${${PROJECT_NAME_UC}_PATCH_VERSION})
 SET(${PROJECT_NAME_UC}_VERSION_DEV 0)
@@ -121,7 +121,9 @@ IF(SALOME_BUILD_GUI)
   IF(EXISTS ${GUI_ROOT_DIR})
     LIST(APPEND CMAKE_MODULE_PATH "${GUI_ROOT_DIR}/adm_local/cmake_files")
     FIND_PACKAGE(SalomeGUI)
-    FULL_GUI(TRUE) #check whether GUI builded in full mode and with CORBA
+    SALOME_GUI_WITH_CORBA() #check whether GUI builded with CORBA
+    SALOME_GUI_MODE(SALOME_USE_VTKVIEWER SALOME_USE_SALOMEOBJECT 
+                    OPTIONAL SALOME_USE_PLOT2DVIEWER SALOME_USE_PYCONSOLE)
     ##
     ## Prerequisites From GUI:
     ##
index 7ee8ff5fda3ebf1c2602f6548392862606fdc6ee..65d8e52e2ec78b1db9e43316cbcfe7c7ca3aff33 100644 (file)
@@ -165,6 +165,7 @@ SET(GOOD_TESTS
   transforming_meshes_ex13.py
   use_existing_faces.py
   viewing_meshes_ex02.py
+  split_biquad.py
 )
 
 SET(EXAMPLES_TESTS ${BAD_TESTS} ${GOOD_TESTS} testme.py)
diff --git a/doc/salome/examples/split_biquad.py b/doc/salome/examples/split_biquad.py
new file mode 100644 (file)
index 0000000..e53e7b0
--- /dev/null
@@ -0,0 +1,37 @@
+# Split bi-quadratic to linear
+
+import salome
+salome.salome_init()
+
+from salome.geom import geomBuilder
+geompy = geomBuilder.New(salome.myStudy)
+
+from salome.smesh import smeshBuilder
+smesh = smeshBuilder.New(salome.myStudy)
+
+# make a shape consisting of two quadranges
+OY  = geompy.MakeVectorDXDYDZ(0, 1, 0)
+OY1 = geompy.MakeTranslation( OY, 1, 0, 0 )
+OY2 = geompy.MakeTranslation( OY, 2, 0, 0 )
+q1  = geompy.MakeQuad2Edges( OY, OY1 )
+q2  = geompy.MakeQuad2Edges( OY1, OY2 )
+
+shape = geompy.Partition( [q1,q2], theName='shape' )
+ff    = geompy.SubShapeAll( shape, geompy.ShapeType["FACE"], theName="quad" )
+
+# mesh one quadrange with quadrangless and the other with triangles
+mesh = smesh.Mesh( shape )
+mesh.Segment().NumberOfSegments(1)
+mesh.Quadrangle()
+mesh.Triangle( ff[1] )
+mesh.Compute()
+
+# make group of quadrangles and extrude them into a hexahedron
+quadGroup = mesh.Group( ff[0], "quads")
+mesh.ExtrusionSweepObject2D( quadGroup, [0,0,1], 1 )
+
+# make the mesh bi-quadratic
+mesh.ConvertToQuadratic( theToBiQuad=True )
+
+# split all elements into linear ones
+mesh.SplitBiQuadraticIntoLinear()
index dc61324eccecfb125f7e104030a14a51048ad257..93f5196c0b0e59530d82bc560be1cb3b95bffcaa 100644 (file)
@@ -1,16 +1,11 @@
 # Translation
 
 import SMESH_mechanic
-import SMESH
 
-smesh = SMESH_mechanic.smesh 
 mesh = SMESH_mechanic.mesh 
 
 # define translation vector
-point = SMESH.PointStruct(-150., -150., 0.)
-vector =SMESH.DirStruct(point)
+vector = [-150., -150., 0.]
 
-# translate a mesh
-doCopy = 1
-
-mesh.Translate([], vector, doCopy)
+# make a translated copy of all elements of the mesh
+mesh.TranslateObject(mesh, vector, Copy=True)
index f99d50b6a97cc551004bbdd475db9c7996c46eb2..deba1c407c5e6c6827c5ed38635f8076a66113ee 100644 (file)
@@ -1,10 +1,14 @@
 # Merging Nodes
 
-import SMESH_mechanic
+import SMESH_mechanic, SMESH
 mesh = SMESH_mechanic.mesh
 
 # merge nodes
-Tolerance = 25.0
+Tolerance = 4.0
+
+# prevent nodes located on geom edges from removal during merge:
+# create a group including all nodes on edges
+allSegs = mesh.MakeGroup( "all segments", SMESH.EDGE, SMESH.FT_ElemGeomType,'=', SMESH.Geom_EDGE )
 
 GroupsOfNodes =  mesh.FindCoincidentNodes(Tolerance)
-mesh.MergeNodes(GroupsOfNodes)  
+mesh.MergeNodes(GroupsOfNodes, NodesToKeep=allSegs)
index 62fea88d108e92317decf710324bbabe073968a9..9264a5c4c508aa81410e9db22f167098ddb7a7b4 100644 (file)
@@ -11,35 +11,40 @@ import SMESH, SALOMEDS
 from salome.smesh import smeshBuilder
 smesh =  smeshBuilder.New(salome.myStudy)
 
-# create two faces of the box
-box1 = geompy.MakeBox(0., 0., 0., 20., 20., 15.)
-facesList1 = geompy.SubShapeAll(box1, geompy.ShapeType["FACE"])
-face1 = facesList1[2]
-
-box2 = geompy.MakeBox(0., 5., 0., 20., 20., 15.)
-facesList2 = geompy.SubShapeAll(box2, geompy.ShapeType["FACE"])
-face2 = facesList2[1]
-
-edgesList = geompy.SubShapeAll(face2, geompy.ShapeType["EDGE"])
-edge1 = edgesList[2]
-
-aComp = geompy.MakeCompound([face1, face2])
-geompy.addToStudy(aComp, "Two faces")
+# make two not sewed quadranges
+OY0 = geompy.MakeVectorDXDYDZ(0, 1, 0)
+OY1 = geompy.MakeTranslation( OY0, 1, 0, 0, theName="OY1" )
+OY2 = geompy.MakeTranslation( OY0, 1.01, 0, 0, theName="OY2" )
+OY3 = geompy.MakeTranslation( OY0, 2, 0, 0 )
+q1  = geompy.MakeQuad2Edges( OY0, OY1 )
+q2  = geompy.MakeQuad2Edges( OY2, OY3 )
+
+shape = geompy.MakeCompound( [q1,q2], theName='shape' )
+
+# make a non-uniform quadrangle mesh on two faces
+mesh = smesh.Mesh(shape, "Two faces : quadrangle mesh")
+mesh.Segment().Arithmetic1D( 0.1, 0.4 )
+mesh.Segment(q1).NumberOfSegments( 5 )
+mesh.Quadrangle()
+mesh.Compute()
 
-# create a mesh on two faces
-mesh = smesh.Mesh(aComp, "Two faces : quadrangle mesh")
+# sew free borders
 
-algo1D = mesh.Segment()
-algo1D.NumberOfSegments(4)
-algo2D = mesh.Quadrangle()
+segs1 = mesh.GetSubMeshElementsId( OY1 ) # mesh segments generated on borders
+segs2 = mesh.GetSubMeshElementsId( OY2 )
 
-algo_local = mesh.Segment(edge1)
-algo_local.Arithmetic1D(1, 4)
-algo_local.Propagation()
+FirstNodeID1  = mesh.GetElemNode( segs1[0], 0 )
+SecondNodeID1 = mesh.GetElemNode( segs1[0], 1 )
+LastNodeID1   = mesh.GetElemNode( segs1[-1], 1 )
+FirstNodeID2  = mesh.GetElemNode( segs2[0], 0 )
+SecondNodeID2 = mesh.GetElemNode( segs2[0], 1 )
+LastNodeID2   = mesh.GetElemNode( segs2[-1], 1 )
+CreatePolygons = True
+CreatePolyedrs = False
 
-mesh.Compute()
+res = mesh.SewFreeBorders(FirstNodeID1, SecondNodeID1, LastNodeID1,
+                          FirstNodeID2, SecondNodeID2, LastNodeID2,
+                          CreatePolygons, CreatePolyedrs )
+print res
+print "nb polygons:", mesh.NbPolygons()
 
-# sew free borders
-# FirstNodeID1, SecondNodeID1, LastNodeID1,
-# FirstNodeID2, SecondNodeID2, LastNodeID2, CreatePolygons, CreatePolyedrs
-mesh.SewFreeBorders(6, 21, 5, 1, 12, 3, 0, 0)
index 426a011a6b94616b51b1a67eadbb2ed5bdb45ddc..e0120b4810f5dc87b5a03dfc88aac0dc32bf8cfa 100644 (file)
@@ -20,7 +20,7 @@ aComp = geompy.MakeCompound([box1, box2])
 geompy.addToStudy(aComp, "Two boxes")
 
 # create a mesh on two boxes
-mesh = smesh.Mesh(aComp, "Two faces : quadrangle mesh")
+mesh = smesh.Mesh(aComp, "Sew Side Elements")
 
 algo1D = mesh.Segment()
 algo1D.NumberOfSegments(2)
@@ -33,6 +33,31 @@ algo_local.Propagation()
 mesh.Compute()
 
 # sew side elements
-# IDsOfSide1Elements, IDsOfSide2Elements,
-# NodeID1OfSide1ToMerge, NodeID1OfSide2ToMerge, NodeID2OfSide1ToMerge, NodeID2OfSide2ToMerge
-mesh.SewSideElements([69, 70, 71, 72], [91, 92, 89, 90], 8, 38, 23, 58)
+
+# find elements to sew
+face1 = geompy.GetFaceNearPoint( aComp, geompy.MakeVertex( 5, 10, 5 ))
+IDsOfSide1Elements = mesh.GetSubMeshElementsId( face1 )
+print "side faces 1:",IDsOfSide1Elements
+
+face1Translated = geompy.MakeTranslation( face1, 0,5,0 )
+faceFilter = smesh.GetFilter( SMESH.FACE, SMESH.FT_BelongToGeom,'=', face1Translated )
+IDsOfSide2Elements = mesh.GetIdsFromFilter( faceFilter )
+print "side faces 2:",IDsOfSide2Elements
+
+# find corresponding nodes on sides
+edge1 = geompy.GetEdgeNearPoint( aComp, geompy.MakeVertex( 0, 10, 5 ))
+segs1 = mesh.GetSubMeshElementsId( edge1 ) # mesh segments generated on edge1
+NodeID1OfSide1ToMerge = mesh.GetElemNode( segs1[0], 0 )
+NodeID2OfSide1ToMerge = mesh.GetElemNode( segs1[0], 1 )
+print "nodes of side1:", [NodeID1OfSide1ToMerge,NodeID2OfSide1ToMerge]
+
+edge2 = geompy.GetEdgeNearPoint( aComp, geompy.MakeVertex( 0, 15, 5 ))
+segs2 = mesh.GetSubMeshElementsId( edge2 ) # mesh segments generated on edge2
+NodeID1OfSide2ToMerge = mesh.GetElemNode( segs2[0], 0 )
+NodeID2OfSide2ToMerge = mesh.GetElemNode( segs2[0], 1 )
+print "nodes of side2:", [NodeID1OfSide2ToMerge,NodeID2OfSide2ToMerge]
+
+res = mesh.SewSideElements(IDsOfSide1Elements, IDsOfSide2Elements,
+                           NodeID1OfSide1ToMerge, NodeID1OfSide2ToMerge,
+                           NodeID2OfSide1ToMerge, NodeID2OfSide2ToMerge)
+print res
diff --git a/doc/salome/gui/SMESH/images/extru_rib_segs.png b/doc/salome/gui/SMESH/images/extru_rib_segs.png
new file mode 100644 (file)
index 0000000..24f04cf
Binary files /dev/null and b/doc/salome/gui/SMESH/images/extru_rib_segs.png differ
index 32ea34f4a01773b1e162c2fe4b50e4baed3baede..f0e6d9e939cbad17fee99225115d22d1fe457d66 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/extrusionalongaline2.png and b/doc/salome/gui/SMESH/images/extrusionalongaline2.png differ
index a75601c01190526fbd04295b6d898c5925424826..75c359b07645dbc2730ad7ed6a9443549c1d0d98 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/extrusionalongaline3.png and b/doc/salome/gui/SMESH/images/extrusionalongaline3.png differ
old mode 100755 (executable)
new mode 100644 (file)
index 6e73c93..871beba
Binary files a/doc/salome/gui/SMESH/images/free_borders1.png and b/doc/salome/gui/SMESH/images/free_borders1.png differ
diff --git a/doc/salome/gui/SMESH/images/hexa_ijk_mesh.png b/doc/salome/gui/SMESH/images/hexa_ijk_mesh.png
new file mode 100644 (file)
index 0000000..577ee8e
Binary files /dev/null and b/doc/salome/gui/SMESH/images/hexa_ijk_mesh.png differ
old mode 100755 (executable)
new mode 100644 (file)
index 604a150..d30ae67
Binary files a/doc/salome/gui/SMESH/images/image152.png and b/doc/salome/gui/SMESH/images/image152.png differ
old mode 100755 (executable)
new mode 100644 (file)
index 3b2a973..9499ab2
Binary files a/doc/salome/gui/SMESH/images/image88.jpg and b/doc/salome/gui/SMESH/images/image88.jpg differ
old mode 100755 (executable)
new mode 100644 (file)
index 3f59269..40d614f
Binary files a/doc/salome/gui/SMESH/images/mergeelems.png and b/doc/salome/gui/SMESH/images/mergeelems.png differ
index 904d234637a0af9ad75aa018c4b1f5055e53f20b..6e2b306971de80f9708dec533dfe4063909490cc 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/mergeelems_auto.png and b/doc/salome/gui/SMESH/images/mergeelems_auto.png differ
old mode 100755 (executable)
new mode 100644 (file)
index 05286a5..5b34361
Binary files a/doc/salome/gui/SMESH/images/mergenodes.png and b/doc/salome/gui/SMESH/images/mergenodes.png differ
index 6a2a92830dcc0c4d8c7c20242e388087fb2cea98..4f177f605fbce3dcea99859915a1fc8e84681e8b 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/mergenodes_auto.png and b/doc/salome/gui/SMESH/images/mergenodes_auto.png differ
old mode 100755 (executable)
new mode 100644 (file)
index f64bdcb..05c8175
Binary files a/doc/salome/gui/SMESH/images/merging_nodes1.png and b/doc/salome/gui/SMESH/images/merging_nodes1.png differ
old mode 100755 (executable)
new mode 100644 (file)
index 8d7cfdd..862ed17
Binary files a/doc/salome/gui/SMESH/images/merging_nodes2.png and b/doc/salome/gui/SMESH/images/merging_nodes2.png differ
index be1a1251562de42593c67ae14cf5dadf0b956e35..6f9fb31b351633fc697d0277def3506cdcc02577 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/preview_tmp_data.png and b/doc/salome/gui/SMESH/images/preview_tmp_data.png differ
index 6564c7fc615da0cfda3999f4393d0d55278945d2..3e7a7a1aafe3dcade08a79f52a031ea29cbf8caf 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/revolutionsn1.png and b/doc/salome/gui/SMESH/images/revolutionsn1.png differ
index 67a673144f6f9e4471b54d0afc1dc10cac90c115..064dd6c2da4561b772a4327c58ebbcd032d669ed 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/revolutionsn2.png and b/doc/salome/gui/SMESH/images/revolutionsn2.png differ
diff --git a/doc/salome/gui/SMESH/images/sew_after_merge.png b/doc/salome/gui/SMESH/images/sew_after_merge.png
new file mode 100644 (file)
index 0000000..43d6869
Binary files /dev/null and b/doc/salome/gui/SMESH/images/sew_after_merge.png differ
diff --git a/doc/salome/gui/SMESH/images/sew_using_merge.png b/doc/salome/gui/SMESH/images/sew_using_merge.png
new file mode 100644 (file)
index 0000000..80cc44c
Binary files /dev/null and b/doc/salome/gui/SMESH/images/sew_using_merge.png differ
old mode 100755 (executable)
new mode 100644 (file)
index daef959..55e0d83
Binary files a/doc/salome/gui/SMESH/images/sewing1.png and b/doc/salome/gui/SMESH/images/sewing1.png differ
old mode 100755 (executable)
new mode 100644 (file)
index b7563f9..2ba3e43
Binary files a/doc/salome/gui/SMESH/images/sewing2.png and b/doc/salome/gui/SMESH/images/sewing2.png differ
old mode 100755 (executable)
new mode 100644 (file)
index da2972f..d2d97d5
Binary files a/doc/salome/gui/SMESH/images/sewing3.png and b/doc/salome/gui/SMESH/images/sewing3.png differ
old mode 100755 (executable)
new mode 100644 (file)
index 748237c..ad66682
Binary files a/doc/salome/gui/SMESH/images/sewing4.png and b/doc/salome/gui/SMESH/images/sewing4.png differ
diff --git a/doc/salome/gui/SMESH/images/sewing_auto.png b/doc/salome/gui/SMESH/images/sewing_auto.png
new file mode 100644 (file)
index 0000000..f81cfe2
Binary files /dev/null and b/doc/salome/gui/SMESH/images/sewing_auto.png differ
diff --git a/doc/salome/gui/SMESH/images/sewing_manual.png b/doc/salome/gui/SMESH/images/sewing_manual.png
new file mode 100644 (file)
index 0000000..ff125bc
Binary files /dev/null and b/doc/salome/gui/SMESH/images/sewing_manual.png differ
diff --git a/doc/salome/gui/SMESH/images/split_biquad_to_linear_dlg.png b/doc/salome/gui/SMESH/images/split_biquad_to_linear_dlg.png
new file mode 100644 (file)
index 0000000..c3df009
Binary files /dev/null and b/doc/salome/gui/SMESH/images/split_biquad_to_linear_dlg.png differ
diff --git a/doc/salome/gui/SMESH/images/split_biquad_to_linear_icon.png b/doc/salome/gui/SMESH/images/split_biquad_to_linear_icon.png
new file mode 100644 (file)
index 0000000..0b9b7a0
Binary files /dev/null and b/doc/salome/gui/SMESH/images/split_biquad_to_linear_icon.png differ
diff --git a/doc/salome/gui/SMESH/images/split_biquad_to_linear_mesh.png b/doc/salome/gui/SMESH/images/split_biquad_to_linear_mesh.png
new file mode 100644 (file)
index 0000000..4a25e8f
Binary files /dev/null and b/doc/salome/gui/SMESH/images/split_biquad_to_linear_mesh.png differ
diff --git a/doc/salome/gui/SMESH/images/swap.png b/doc/salome/gui/SMESH/images/swap.png
new file mode 100644 (file)
index 0000000..6470710
Binary files /dev/null and b/doc/salome/gui/SMESH/images/swap.png differ
index 87c20b74f27e00237ddb6f5135ebd063e2aac01a..a5b54c82c0422fd3d8cbd7e11db971d3edba118b 100644 (file)
@@ -5,31 +5,31 @@
 Basic 1D hypothesis specifies:
 <ul>
 <li>how \ref a1d_algos_anchor "Wire Discretization" should divide the edge;</li>
-<li>how \ref a1d_algos_anchor "Composite Side Discretization" should divide the group of C1-continues edges.</li>
+<li>how \ref a1d_algos_anchor "Composite Side Discretization" should divide the group of C1-continuous edges.</li>
 </ul>
 
-By type of nodes distribution the 1D hypotheses can be categorized as follows:
+1D hypotheses can be categorized by type of nodes distribution as follows:
 <ul>
-<li>Uniform distribution
+<li>Uniform distribution:
   <ul>
     <li>\ref average_length_anchor "Local Length"</li>
     <li>\ref max_length_anchor "Max Size"</li>
     <li>\ref number_of_segments_anchor "Number of segments" with Equidistant distribution</li>
     <li>\ref automatic_length_anchor "Automatic Length"</li>
 </ul></li>
-<li>Constantly increasing or decreasing length of segments
+<li>Constantly increasing or decreasing length of segments:
   <ul>
     <li>\ref arithmetic_1d_anchor "Arithmetic 1D"</li>
     <li>\ref geometric_1d_anchor "Geometric Progression"</li>
     <li>\ref start_and_end_length_anchor "Start and end length"</li>
     <li>\ref number_of_segments_anchor "Number of segments" with Scale distribution</li>
 </ul></li>
-<li>Distribution depending on curvature
+<li>Distribution depending on curvature:
   <ul>
     <li>\ref adaptive_1d_anchor "Adaptive"</li>
     <li>\ref deflection_1d_anchor "Deflection 1D"</li>
 </ul></li>
-<li>Arbitrary distribution
+<li>Arbitrary distribution:
   <ul>
     <li>\ref fixed_points_1d_anchor "Fixed points 1D"</li>
     <li>\ref number_of_segments_anchor "Number of segments" with
@@ -144,12 +144,17 @@ composing your geometrical object. Definition of this hypothesis
 consists of setting the \b length of segments, which will approximate these
 edges, and the \b precision of rounding.
 
-The \b precision parameter is used to round a number of segments,
-calculated by dividing the edge length by the specified \b length of
-segment, to the higher integer if the remainder exceeds the precision
-and to the lower integer otherwise. Use value 0.5 to provide rounding
-to the nearest integer, 1.0 for the lower integer, 0.0 for the higher
-integer. Default value is 1e-07.
+The \b precision parameter is used to round a <em>number of segments</em>,
+calculated by dividing the <em>edge length</em> by the specified \b length of
+segment, to the higher integer if the \a remainder exceeds the \b precision
+and to the lower integer otherwise. <br>
+Use value 0.5 to provide rounding to the nearest integer, 1.0 for the lower integer, 0.0 for the higher integer. Default value is 1e-07.
+
+For example: if <em>edge length</em> is 10.0 and the segment \b length
+is 3.0 then their division gives 10./3. = 3.33(3) and the \a remainder is 0.33(3).
+If \b precision is less than 0.33(3) then the edge is divided into 3 segments.
+If \b precision is more than 0.33(3) then the edge is divided into 4 segments.
+
 
 \image html image41.gif
 
@@ -245,6 +250,7 @@ negative</b>.
 \ref tui_deflection_1d "Defining Number of Segments" hypothesis
 operation.
 
+\note The plot functionality is available only if GUI module is builded with Plot 2D Viewer (set option SALOME_USE_PLOT2DVIEWER to ON when building GUI module).
 
 <br>
 \anchor start_and_end_length_anchor
@@ -316,7 +322,7 @@ possible to select the edges to be reversed either directly picking them in
 the 3D viewer or selecting the edges or groups of edges in the
 Object Browser.
 
-\ref reversed_edges_helper_anchor "Helper" group assists you in
+\ref reversed_edges_helper_anchor "Helper" group assists in
 defining <b>Reversed Edges</b> parameter.
 
 
@@ -330,23 +336,23 @@ defining <b>Reversed Edges</b> parameter.
 
 \image html rev_edges_helper_dlg.png
 
-\b Helper group assists you in defining <b>Reversed Edges</b>
+\b Helper group assists in defining <b>Reversed Edges</b>
 parameter of the hypotheses depending on edge direction.
 
-<b>Show whole geometry</b> check-box lets you see the whole
-geometrical model in the 3D Viewer. This can help you to understand
-location within the model of a set of edges shown in the Viewer.
+<b>Show whole geometry</b> check-box allows seeing the whole
+geometrical model in the 3D Viewer, which can help to understand the
+location of a set of edges within the model.
 
-<b>Propagation chains</b> group helps you to define 
-<b>Reversed Edges</b> so that opposite edges of quadrilateral faces
-will be split in the logically same direction. When this group is
+<b>Propagation chains</b> group allows defining <b>Reversed Edges</b>
+for splitting opposite edges of quadrilateral faces
+in a logically uniform direction. When this group is
 activated, the list is filled with propagation chains found within the
-model. When you select a chain in the list, edges of the chain are
-shown in the Viewer with arrows so that you can chose a common
-direction for all chain edges. \b Reverse button inverses the common
-direction of chain edges. If \b Add button is active, this means that some
-edges of a chain have different direction and you can click \b Add
-button to add such edges to <b>Reversed Edges</b> list.
+model. When a chain is selected in the list its edges are
+shown in the Viewer with arrows, which enables choosing a common
+direction for all chain edges. \b Reverse button inverts the common
+direction of chain edges. If \b Add button is active, some
+edges of a chain have a different direction, so you can click \b Add
+button to add them to <b>Reversed Edges</b> list.
 
 \image html propagation_chain.png "The whole geometry and a propagation chain"
 
index 234ffd11b51fa1958685f97e9b05c65e4df7a8fd..308a6899ad1abbb854117cf134461fd32f26987c 100644 (file)
@@ -26,9 +26,9 @@ which will compose the mesh of these faces.
 \anchor length_from_edges_anchor
 <h2>Length from Edges</h2>
 
-<b>Length from edges</b> hypothesis defines maximum linear size of
-mesh faces as an average length of mesh edges approximating a boundary
-of a face being meshed.
+<b>Length from edges</b> hypothesis defines the maximum linear size of
+mesh faces as an average length of mesh edges approximating
+the meshed face boundary.
 
 <b>See Also</b> a sample TUI Script of a 
 \ref tui_length_from_edges "Length from Edges" hypothesis operation.
@@ -38,7 +38,7 @@ of a face being meshed.
 
 \image html hypo_quad_params_dialog.png "Quadrangle parameters: Transition"
 
-<b>Quadrangle parameters</b> is a hypothesis for Quadrangle (Mapping) algorithm.
+<b>Quadrangle parameters</b> is a hypothesis for \ref quad_ijk_algo_page.
 
 <b>Transition</b> tab is used to define the algorithm of transition
 between opposite sides of the face with a different number of
@@ -113,7 +113,7 @@ of the enforced nodes.
     projected to the meshed face and located close enough to the
     meshed face will be used to create the enforced nodes.</li>
 </ul>
-\note <b>Enforced nodes</b> can't be created at \b Reduced transition type.
+\note <b>Enforced nodes</b> cannot be created at \b Reduced transition type.
 
 Let us see how the algorithm works:
 <ul>
index bbd5960235c607d75f20042b18b3542644d63b14..f331fa4be3bb4aa521de3c7884b501ae093e06eb 100644 (file)
@@ -26,7 +26,7 @@ about selection filters and their usage in GUI.
 - In Python scripts, filters can be used to choose only some mesh
   entities (nodes or elements) for the operations, which require the
   list of entities as input parameter (create/modify group, remove
-  nodes/elements, etc) and for the operations, which accept objects as
+  nodes/elements, etc) and for the operations, which accept objects
   as input parameter. The page \ref tui_filters_page provides
   examples of the filters usage in Python scripts.
 */
index b2dab5dbf1e511d1247fb25733cee87fddacb52d..12f5c02e14967d774b2a93e68988c1bf77263f6d 100644 (file)
@@ -14,17 +14,16 @@ The choice of a hypothesis depends on the selected algorithm.
 
 Hypotheses are created during creation and edition of 
 \ref constructing_meshes_page "meshes" and
-\ref constructing_submeshes_page "sub-mesh". 
-Once created a hypotheses can be reused during creation and
-edition of other meshes and sub-meshes. All created hypotheses and
-algorithms are present in the Object Browser in \a Hypotheses and
-\a Algorithms folders correspondingly. From the context menu of the
-hypothesis you can invoke a dialog for modification of its parameters,
-and \b Unassign command that will unassign the hypothesis from all
-the meshes and sub-meshes using it.
-Modification of any hypothesis parameter and unassignment of a
-hypothesis leads to automatic removal of elements generated with use
-of this hypothesis.
+\ref constructing_submeshes_page "sub-meshes". 
+Once created a hypotheses can be reused during creation and edition of
+other meshes and sub-meshes. All created hypotheses and algorithms are
+present in the Object Browser in \a Hypotheses and \a Algorithms
+folders correspondingly. It is possible to open a dialog to modify the
+parameters of a hypothesis from its context menu. This menu also
+provides \b Unassign command that will unassign the hypothesis from
+all meshes and sub-meshes using it. Modification of any parameter of a
+hypothesis and its unassignment leads to automatic removal of elements
+generated using it.
 
 In \b MESH there are the following Basic Hypotheses:
 <ul>
index 470cb854da57d380967edefe89f8c359763639fb..7550e893495c187f75e969a7f1c20f72e2f9d6eb 100644 (file)
@@ -19,31 +19,31 @@ Mesh module provides several ways to create the mesh:
 
     Construction of \subpage constructing_submeshes_page "sub-meshes"
     allows to discretize some sub-shapes of the main shape, for example a face,
-    using different meshing parameters than other sub-shapes.<br>
+    using the meshing parameters that differ from those for other sub-shapes.<br>
     Meshing parameters of meshes and sub-meshes can be 
     \subpage editing_meshes_page "edited". (Upon edition only mesh entities
     generated using changed meshing parameters are removed and will be
     re-computed).<br>
-    \note Algorithms and hypotheses used at mesh level are referred as
-    \a global ones and those used at sub-mesh level are referred as \a
+    \note Algorithms and hypotheses used at mesh level are referred to as
+    \a global ones and those used at sub-mesh level are referred to as \a
     local ones.
   </li>
   <li>Bottom-up way, using \ref modifying_meshes_page "mesh modification"
     operations, especially \ref extrusion_page "extrusion" and \ref
-    revolution_page "revolution". To create an empty mesh not based on
+    revolution_page "revolution". To create an empty mesh not based on a
     geometry, use the same dialog as to \ref constructing_meshes_page
-    "construct the mesh on geometry" but do not specify any geometry
-    nor meshing algorithm.
+    "construct the mesh on geometry" but do not specify a geometry
+    or a meshing algorithm.
   </li>
-  <li>The mesh can be \ref importing_exporting_meshes_page "imported" from
+  <li>The mesh can be \subpage importing_exporting_meshes_page "imported" from
     (and exported to) the file in MED, UNV, STL, CGNS, DAT, GMF and
     SAUVE formats.
   </li>
   <li>The 3D mesh can be generated from the 2D mesh, \ref
     importing_exporting_meshes_page "imported" or manually created. To
-    setup the meshing parameters of a mesh not based on geometry, just
+    setup the meshing parameters of a mesh not based on geometry, just
     invoke \ref editing_meshes_page "Edit mesh / sub-mesh" command on
-    your 3D mesh.
+    your 2D mesh.
   </li>
   <li>Several meshes can be \subpage building_compounds_page "combined"
     into a new mesh.
@@ -66,29 +66,29 @@ Attractive meshing capabilities include:
   sub-meshes.
 
 The \b structure of a SALOME mesh is described by nodes and elements based on
-these nodes. Geometry of the element is defined by the sequence of
+these nodes. The geometry of an element is defined by the sequence of
 nodes constituting it and
 the <a href="http://www.code-aster.org/outils/med/html/connectivites.html">
   connectivity convention </a> (adopted from MED library). Definition of
-the element basing on elements of lower dimension is NOT supported.
+the element basing on the elements of a lower dimension is NOT supported.
 
 \anchor mesh_entities
 The mesh can include the following entities:
 <ul>
-<li>\b Node &mdash; an entity of a mesh defining a position in 3D
+<li>\b Node &mdash; a mesh entity defining a position in 3D
   space with coordinates (x, y, z).</li>
-<li>\b Edge (or segment) &mdash; 1D element of a mesh linking two nodes.</li>
-<li>\b Face &mdash; 2D element of a mesh representing a part of
+<li>\b Edge (or segment) &mdash; 1D mesh element linking two nodes.</li>
+<li>\b Face &mdash; 2D mesh element representing a part of
   surface bound by links between face nodes. A face can be a
   triangle, quadrangle or polygon.</li>
-<li>\b Volume &mdash; 3D element of a mesh representing a part of 3D
+<li>\b Volume &mdash; 3D mesh element representing a part of 3D
   space bound by volume facets. Nodes of a volume describing each
   facet are defined by
   the <a href="http://www.code-aster.org/outils/med/html/connectivites.html">
   MED connectivity convention.</a> A volume can be a tetrahedron, hexahedron,
   pentahedron, pyramid, hexagonal prism or polyhedron.</li>
-<li>\b 0D element &mdash; element of a mesh defined by one node.</li>
-<li>\b Ball element &mdash; discrete element of a mesh defined by a
+<li>\b 0D element &mdash; mesh element defined by one node.</li>
+<li>\b Ball element &mdash; discrete mesh element defined by a
   node and a diameter.</li>
 </ul>
 
@@ -97,10 +97,14 @@ generated on (if any). The node generated on the geometrical edge or
 surface in addition stores its position in parametric space of the
 associated geometrical entity.
 
-SALOME supports elements of second order, without central node
-(quadratic triangle, quadrangle, tetrahedron, hexahedron, pentahedron
-and pyramid) and with central nodes (bi-quadratic triangle and
-quadrangle and tri-quadratic hexahedron).<br>
+Mesh entities are identified by integer IDs starting from 1.
+Nodes and elements are countered separately, i.e. there can be a node
+and element with the same ID.
+
+SALOME supports elements of second order, without a central node
+(quadratic triangle, quadrangle, polygon, tetrahedron, hexahedron,
+pentahedron and pyramid) and with central nodes (bi-quadratic triangle
+and quadrangle and tri-quadratic hexahedron).<br>
 Quadratic mesh can be obtained in two ways:
 - Using a global \ref quadratic_mesh_anchor "Quadratic Mesh"
 hypothesis. (Elements with the central node are not generated in this way).
index 1e170e440bd0e15ecf80d7bfdeae228b887845e9..9dbb5c9923cff006424fe84e3a5c4867d98aa570 100644 (file)
@@ -24,7 +24,6 @@ Node quality controls:
 
 Edge quality controls:
 <ul>
-<li>\subpage free_edges_page "Free edges"</li>
 <li>\subpage free_borders_page "Free borders"</li>
 <li>\subpage length_page "Length"</li>
 <li>\subpage borders_at_multi_connection_page "Borders at multi-connection"</li>
@@ -33,6 +32,7 @@ Edge quality controls:
 
 Face quality controls:
 <ul>
+<li>\subpage free_edges_page "Free edges"</li>
 <li>\subpage free_faces_page "Free faces"</li>
 <li>\subpage bare_border_faces_page "Bare border faces"</li>
 <li>\subpage over_constrained_faces_page "Over-constrained faces"</li>
index e46385b2d204371c8a43f853f0b9d2900dbe3f67..855b7e5ea364c0a35c3baafc46974fd91f4bd6eb 100644 (file)
@@ -32,7 +32,7 @@ nodal connectivity of elements in the documentation on MED library or
   <li>From the \b Modification menu choose the \b Add item, the
     following associated sub-menu will appear:</li>
 
-  \image html image146.png
+  \image html image152.png
 
 From this sub-menu select the type of element which you would like to add to your mesh.
 
@@ -47,10 +47,13 @@ existing groups of the corresponding type becomes available. By
 default, no group is selected. In this case, when the user presses
 <b>Apply</b> or <b>Apply & Close</b> button, the warning message box
 informs the user about the necessity to input new group name. The
-combo box lists both \ref standalone_group "standalone groups"
-and \ref group_on_geom "groups on geometry". If the user chooses a
-group on geometry, he is warned and proposed to
-\ref convert_to_standalone "convert this group to standalone".
+combo box lists groups of all the 
+\ref grouping_elements_page "three types": both 
+\ref standalone_group "standalone groups",
+\ref group_on_filter "groups on filter", and 
+\ref group_on_geom "groups on geometry". If the user chooses a
+group on geometry or on filter, he is warned and proposed to
+convert this group to standalone.
 If the user rejects conversion operation, it is cancelled and
 a new node/element is not created!
 
@@ -87,29 +90,35 @@ selecting them in the 3D viewer and click the \b Apply or
 \anchor adding_0delems_on_all_nodes_anchor
 <h2>Making 0D elements on Element Nodes</h2>
 
-There is another way to create 0D elements. It is possible to create 
+There is another way to create 0D elements. It is possible to create
 0D elements on all nodes of the selected mesh, sub-mesh, or a group of elements or nodes.
 
 \image html dlg_0D_on_all_nodes.png
 
-In this dialog 
+In this dialog
 <ul>
   <li> The radio-buttons allow choosing the type of object to create 0D elements on.
     <ul>
-      <li><b> Mesh, sub-mesh, group </b> -  this button allows selecting
-       a mesh, a sub-mesh or a group to create 0D elements on the nodes of its
+      <li><b> Mesh, sub-mesh, group </b> - this button allows selecting
+        a mesh, a sub-mesh or a group to create 0D elements on the nodes of its
         elements. The name of the selected object is shown in the dialog. </li>
       <li><b> Elements </b> - this button allows selecting elements in the
         VTK viewer or typing their IDs in the dialog.</li>
       <li><b> Nodes </b> - this button allows selecting nodes to create
         0D elements on in the VTK viewer or typing their IDs in the dialog.</li>
   </ul></li>
-  <li><b> Set Filter </b> button allows selecting elements or nodes 
-by filtering mesh elements or nodes with different criteria
-(see \ref filtering_elements "Filter usage").</li>
-<li> Switching on <b>Add to group</b> check-box allows specifying the
-  name of the group to which all created or found 0D elements  will be added. You can either select an existing group from
-  a drop-down list, or enter the name of the group to be created.</li>
+  <li><b> Set Filter </b> button allows selecting elements or nodes
+    by filtering mesh elements or nodes with different criteria
+    (see \ref filtering_elements "Filter usage").</li>
+  <li> Switching on <b>Add to group</b> check-box allows specifying the
+    name of the group to which all created or found (existing) 0D elements will
+    be added. You can either select an existing group from a drop-down
+    list, or enter the name of the group to be created. If a selected
+    existing \ref grouping_elements_page "group" is not Standalone
+    (Group On Geometry or Group On Filter) it will be converted to
+    Standalone.
+    \warning If <b>Add to group</b> is activated it has to be filled in.
+</li>
 </ul>
 
 
@@ -121,7 +130,7 @@ by filtering mesh elements or nodes with different criteria
 In this dialog box specify the nodes, which will form your ball elements,
 either by selecting them in the 3D viewer or by manually entering their IDs,
 specify the ball diameter and click the \b Apply or <b>Apply and
-Close</b> button.
+  Close</b> button.
 
 \image html add_ball.png
 
index 6a9527b5d04ac4326f901108010db5c04035004b..2fd906bafbde6abd91d248ca97f7e08ce7be0a9f 100644 (file)
@@ -36,7 +36,7 @@ one of the following:
 
 \image html image152.png
 
-\note All dialogs for quadratic element adding to the mesh
+\note All dialogs for adding quadratic element to the mesh
 provide the possibility to automatically add an element
 to the specified group or to create the group anew using
 <b>Add to group</b> box, that allows choosing an existing group for
@@ -47,23 +47,29 @@ existing groups of the corresponding type becomes available. By
 default, no group is selected. In this case, when the user presses
 <b>Apply</b> or <b>Apply & Close</b> button, the warning message box
 informs the user about the necessity to input a new group name. The
-combo box lists both \ref standalone_group "standalone groups"
-and \ref group_on_geom "groups on geometry". If the user chooses a
-group on geometry, he is warned and proposed to
-\ref convert_to_standalone "convert this group to standalone".
+combo box lists groups of all the 
+\ref grouping_elements_page "three types": both 
+\ref standalone_group "standalone groups",
+\ref group_on_filter "groups on filter", and 
+\ref group_on_geom "groups on geometry". If the user chooses a
+group on geometry or on filter, he is warned and proposed to
+convert this group to standalone.
 If the user rejects conversion operation, it is cancelled and
 a new quadratic element is not created.
 
 
-To create any <b>Quadratic Element</b> specify the nodes which will form your
-element by selecting them in the 3D viewer with pressed Shift
-button. Their numbers will appear in the dialog box as <b>Corner Nodes</b>
-(alternatively you can just input numbers in this field without
-selection). The edges formed by the corner nodes will appear in the
-table. To define the middle nodes for each edge, double-click on the
-respective field and input the number of the node (or pick the node in
-the viewer). For bi-quadratic and tri-quadratic elements, your also
-need to specify central nodes.
+To create any <b>Quadratic Element</b> specify the nodes which will
+form your element by selecting them in the 3D viewer with pressed
+Shift button and click \a Selection button to the right of 
+<b>Corner Nodes</b> label. Their numbers will appear in the dialog box
+as <b>Corner Nodes</b> (alternatively you can just input numbers in
+this field without selection; note that to use this way the mesh
+should be selected before invoking this operation). The edges formed
+by the corner nodes will appear in the table. To define the middle
+nodes for each edge, double-click on the respective field and input
+the number of the node (or pick the node in the viewer). For
+bi-quadratic and tri-quadratic elements, your also need to specify
+central nodes.
 As soon as all needed nodes are specified, a preview of a new
 quadratic element will be displayed in the 3D viewer. Then
 you will be able to click \b Apply or <b>Apply and Close</b> button to
index 9bade2149870018900d2c4df6e4ea45fd513e6a2..5904e87d49e6211649a58be1cfb1dae0b896ea64 100644 (file)
@@ -31,12 +31,13 @@ The following additional hypothesis are available:
 <h2>Propagation of 1D Hypothesis on opposite edges</h2>
 
 <b>Propagation of 1D Hypothesis on opposite edges</b> allows to mesh
-opposite sides of a quadrangle face, and of other adjacent quadrangles,
-using the same hypothesis assigned to one edge only.<br>
-Thus you define a sub-mesh on an edge where you define 1D meshing
-parameters and a \b Propagation hypothesis. These local meshing
+opposite sides of a quadrangle face and other adjacent quadrangles,
+using the same hypothesis assigned to only one edge.<br>
+Thus you define a sub-mesh on the edge where you define 1D meshing
+parameters and the \b Propagation hypothesis. These local meshing
 parameters will be propagated via opposite sides of quadrangles to the
-whole geometry, or till an edge with other local meshing parameters.
+whole geometry, and this propagation stops at an edge with other local
+meshing parameters.
 
 This hypothesis can be taken into account by 
 \ref a1d_algos_anchor "Wire Discretization" and 
@@ -84,17 +85,17 @@ computations.
 <li><b>Stretch factor</b> - defines the growth factor of element height
   from the mesh boundary inwards.</li>
 <li><b>Extrusion method</b> (available in 3D only) - defines how
-  position of nodes are found during prism construction and how
-  creation of distorted and intersecting prisms is prevented.
-<ul><li><b>Surface offset + smooth</b> method extrudes nodes along normal
-    to underlying geometrical surface. Smoothing of internal surface of
+  positions of nodes are found during prism construction and how
+  the creation of distorted and intersecting prisms is prevented.
+<ul><li><b>Surface offset + smooth</b> method extrudes nodes along the normal
+    to the underlying geometrical surface. Smoothing of the internal surface of
     element layers is possible to avoid creation of invalid prisms.</li>
-  <li><b>Face offset</b> method extrudes nodes along average normal of
-    surrounding mesh faces till intersection with a neighbor mesh face
-    translated along its own normal by the layers thickness. Thickness
+  <li><b>Face offset</b> method extrudes nodes along the average normal of
+    surrounding mesh faces to the intersection with a neighbor mesh face
+    translated along its own normal by the thickness of layers. The thickness
     of layers can be limited to avoid creation of invalid prisms.</li>
-  <li><b>Node offset</b> method extrudes nodes along average normal of
-    surrounding mesh faces by the layers thickness. Thickness of
+  <li><b>Node offset</b> method extrudes nodes along the average normal of
+    surrounding mesh faces by the thickness of layers. The thickness of
     layers can be limited to avoid creation of invalid prisms.</li> 
 \image html viscous_layers_extrusion_method.png "Prisms created by the tree extrusion methods at the same other parameters"
 </ul></li>
@@ -107,9 +108,9 @@ computations.
   Faces (or edges) can be selected either in the Object Browser or in
   the VTK Viewer.
   \note A mesh shown in the 3D Viewer can prevent selection of faces
-  and edges, just hide the mesh to avoid this. Sometimes a face to
-  select is hidden by other faces, in this case consider creating a
-  group of faces you want to select in the Geometry module.<br>
+  and edges, just hide the mesh to avoid this. If a face, which should be
+  selected, is hidden by other faces, consider creating a
+  group of faces to be selected in the Geometry module.<br>
   To avoid a long wait when a
   geometry with many faces (or edges) is displayed, the number of faces
   (edges) shown at a time is limited by the value of "Sub-shapes
@@ -150,12 +151,12 @@ computations.
 
 Quadratic Mesh hypothesis allows to build a quadratic mesh (in which
 links between element nodes are not straight but curved lines due to
-presence of an additional midside node).
+presence of an additional mid-side node).
 
 This 1D hypothesis can be taken into account by 
 \ref a1d_algos_anchor "Wire Discretization" and 
 \ref a1d_algos_anchor "Composite Side Discretization" algorithms. To
-make a quadratic mesh assign this hypothesis at 
+create a quadratic mesh assign this hypothesis at 
 \ref constructing_meshes_page "mesh construction".
 
 See \ref adding_quadratic_elements_page
@@ -168,9 +169,13 @@ for more information about quadratic meshes.
 This additional hypothesis can be used together with 2D triangulation algorithms.
 It allows 2D triangulation algorithms to build quadrangular meshes.
 
-When used with "Quadrangle (Mapping)" meshing algorithm, that is obsolete
- since introducing \ref hypo_quad_params_anchor "Quadrangle parameters" 
-hypothesis, this hypothesis has one restriction on its work: the total quantity of 
-segments on all four sides of the face must be even (divisible by 2).
-
+Usage of this hypothesis with "Quadrangle (Mapping)" meshing algorithm
+is obsolete since introducing
+\ref hypo_quad_params_anchor "Quadrangle parameters" hypothesis.
+Usage of this hypothesis with "Quadrangle (Mapping)" meshing algorithm
+corresponds to specifying "Quadrangle Preference" transition type of
+\ref hypo_quad_params_anchor "Quadrangle parameters" hypothesis.
+\note "Quadrangle Preference" transition type can be used only if the
+total quantity of segments on all sides of the face is even (divisible
+by 2), else "Standard" transition type is used.
 */
index b82b67f89d7728a025d68f9dfb743843c3e20153..080727462dc2113a6b5a95b6cab6f0b67a91641b 100644 (file)
@@ -7,26 +7,26 @@ used for meshing entities (1D, 2D, 3D sub-shapes) composing
 geometrical objects.
 
 An algorithm represents either an implementation of a certain meshing
-technique or a interface to a whole meshing program generating elements
+technique or an interface to the whole meshing program generating elements
 of several dimensions.
 
 <ul>
 <li>For meshing of 1D entities (<b>edges</b>):</li>
 \anchor a1d_algos_anchor
 <ul>
-<li><em>Wire Discretization</em> meshing algorithm - splits an edge into a
+<li><b>Wire Discretization</b> meshing algorithm - splits an edge into a
 number of mesh segments following an 1D hypothesis.
 </li>
-<li><em>Composite Side Discretization</em> algorithm - allows to apply an 1D
+<li><b>Composite Side Discretization</b> algorithm - allows to apply a 1D
   hypothesis to a whole side of a geometrical face even if it is
-  composed of several edges provided that they form C1 curve and form
-  one side in all faces of the main shape.</li>
+  composed of several edges provided that they form C1 curve in all
+  faces of the main shape.</li>
 </ul>
 
 <li>For meshing of 2D entities (<b>faces</b>):</li>
 
 <ul>
-<li><em>Triangle (Mefisto)</em> meshing algorithm - splits faces
+<li><b>Triangle (Mefisto)</b> meshing algorithm - splits faces
   into triangular elements.</li>
 <li>\subpage quad_ijk_algo_page "Quadrangle (Mapping)" meshing
   algorithm - splits faces into quadrangular elements.</li>
@@ -39,8 +39,15 @@ number of mesh segments following an 1D hypothesis.
 <li>For meshing of 3D entities (<b>solid objects</b>):</li>
 
 <ul>
-<li><em>Hexahedron (i,j,k)</em>meshing algorithm - 6-sided solids are
-  split into hexahedral (cuboid) elements.</li>
+<li><b>Hexahedron (i,j,k)</b> meshing algorithm - solids are
+  split into hexahedral elements thus forming a structured 3D
+  mesh. The algorithm requires that 2D mesh generated on a solid could
+  be considered as a mesh of a box, i.e. there should be eight nodes
+  shared by three quadrangles and the rest nodes should be shared by
+  four quadrangles.
+\image html hexa_ijk_mesh.png "Structured mesh generated by Hexahedron (i,j,k) on a solid bound by 16 faces"
+</li>
+
 <li>\subpage cartesian_algo_page "Body Fitting" meshing
   algorithm - solids are split into hexahedral elements forming
   a Cartesian grid; polyhedra and other types of elements are generated
@@ -52,22 +59,25 @@ number of mesh segments following an 1D hypothesis.
 \image html image126.gif "Example of a hexahedral 3D mesh"
 </ul>
 
-Some 3D meshing algorithms, such as Hexahedron(i,j,k) and some
-commercial ones, also can generate 3D meshes from 2D meshes, working
-without geometrical objects.
+Some 3D meshing algorithms, such as Hexahedron(i,j,k) also can
+generate 3D meshes from 2D meshes, working without geometrical
+objects.
 
 There is also a number of more specific algorithms:
 <ul>
-<li>\subpage prism_3d_algo_page "for meshing prismatic 3D shapes"</li>
-<li>\subpage quad_from_ma_algo_page "for meshing faces with sinuous borders"</li>
+<li>\subpage prism_3d_algo_page "for meshing prismatic 3D shapes with hexahedra and prisms"</li>
+<li>\subpage quad_from_ma_algo_page "for quadrangle meshing of faces with sinuous borders"</li>
+<li> <b>Polygon per Face</b> meshing algorithm - generates one mesh
+  face (either a triangle, a quadrangle or a polygon) per a geometrical
+  face using all nodes from the face boundary.</li>
 <li>\subpage projection_algos_page "for meshing by projection of another mesh"</li>
 <li>\subpage import_algos_page "for meshing by importing elements from another mesh"</li>
-<li>\subpage radial_prism_algo_page "for meshing geometrical objects with cavities"</li>
-<li>\subpage radial_quadrangle_1D2D_algo_page "for meshing special 2d faces (circles and part of circles)"</li>
+<li>\subpage radial_prism_algo_page "for meshing 3D geometrical objects with cavities with hexahedra and prisms"</li>
+<li>\subpage radial_quadrangle_1D2D_algo_page "for quadrangle meshing of disks and parts of disks"</li>
 <li>\subpage use_existing_page "Use Edges to be Created Manually" and 
-\ref use_existing_page "Use Faces to be Created Manually" algorithms can be
-used to create a 1D or a 2D mesh in a python script.</li>
-<li>\subpage segments_around_vertex_algo_page "for defining the local size of elements around a certain node"</li>
+  \ref use_existing_page "Use Faces to be Created Manually" algorithms can be
+  used to create a 1D or a 2D mesh in a python script.</li>
+<li>\subpage segments_around_vertex_algo_page "for defining the length of mesh segments around certain vertices"</li>
 </ul>
 
 \ref constructing_meshes_page "Constructing meshes" page describes in
index b4f14481ffbc2041c80560332c6cf7432a7b390d..46fbc6047dc7baf1fb4c32cec4e40fb77b9b9fc8 100644 (file)
@@ -2,8 +2,8 @@
 
 \page borders_at_multi_connection_page Borders at multi-connection
 
-\n This mesh quality control highlights segments according to number
-of elements, faces and volumes, the segment belongs to.
+\n This mesh quality control highlights segments according to the number
+of elements, faces and volumes, to which the segment belongs.
 
 \image html image151.gif
 
index e0e78959b4772e4aafe51a8144c226ebbc54333b..77a439130e71118f795a4553d988a2470f098b7a 100644 (file)
@@ -3,7 +3,7 @@
 \page borders_at_multi_connection_2d_page Borders at multi-connection 2D
 
 \n This mesh quality control highlights borders of faces (links
-between nodes) according to number of faces the link belongs to.
+between nodes) according to the number of faces, to which the link belongs.
 
 \image html image127.gif
 
index fb48fdb266551d6efbf32abd8e61a76fab800840..ce5f3ce505e578a40cc03b60814cc0cb98ced66f 100644 (file)
@@ -4,10 +4,10 @@
 
 \n Compound Mesh is a combination of several meshes. All elements and
 groups present in input meshes are present in the compound
-mesh. Neither geometry nor hypotheses of initial meshes are used by
-the compound mesh. No link between input meshes and a compound mesh is
-supported, so that modification of an input mesh does not lead to
-update of the compound mesh.
+mesh. However, it does not use geometry or hypotheses of the initial meshes. 
+The links between the input meshes and the compound mesh are not
+supported, consequently the modification of an input mesh does not lead to
+the update of the compound mesh.
 
 <em>To Build a compound mesh:</em>
 
@@ -27,15 +27,16 @@ The following dialog box will appear:
 <ul>
   <li>\b Name - allows selecting the name of the resulting \b Compound mesh.</li>
   <li><b>Meshes, sub-meshes, groups</b> - allows selecting the meshes,
-    sub-meshes and groups which will be concatenated. They can be
+    sub-meshes and groups to be concatenated. They can be
     chosen in the Object Browser while holding \b Ctrl button.</li>
   <li><b>Processing identical groups</b> - allows selecting the method
     of processing the namesake groups existing in the input meshes.
     They can be either <ul>
-      <li>\b United - all elements of Group1 of Mesh_1 and Group1 of Mesh_2
-        become the elements of Group1 of the Compound_Mesh, or</li>
-      <li>\b Renamed - Group1 of Mesh_1 becomes Group1_1 and Group1 of Mesh_2
-        becomes Group1_2.</li>
+      <li>\b United - all elements of \em Group1 of \em Mesh_1 and \em
+      Group1 of \em Mesh_2 become the elements of \em Group1 of the
+      \em Compound_Mesh, or</li>
+      <li>\b Renamed - \em Group1 of \em Mesh_1 becomes \em Group1_1
+      and \em Group1 of \em Mesh_2 becomes \em Group1_2.</li>
     </ul>
     See \ref grouping_elements_page "Creating Groups" for more information
     about groups.</li>
index 4d00c577f5fb45ee38fb290dd547b4b5167137c3..63b81ffc4b792ae8f5a9c8d6729a30a2ebe77f3b 100644 (file)
@@ -41,11 +41,9 @@ To apply this algorithm when you define your mesh, select <b>Body
 This dialog allows to define
 <ul>
   <li>\b Name of the algorithm. </li>
-  
   <li> Minimal size of a cell truncated by the geometry boundary. If the
     size of a truncated grid cell is \b Threshold times less than a
     initial cell size, then a mesh element is not created. </li>
-       
   <li> <b> Implement Edges </b> check-box activates incorporation of
   geometrical edges in the mesh.
   
@@ -64,9 +62,10 @@ This dialog allows to define
         System.</li>
       <li> You can define the \b Spacing of a grid as an algebraic formula
         <em>f(t)</em> where \a t is a position along a grid axis
-        normalized at [0.0,1.0]. The whole range of geometry can be
-        divided into sub-ranges with their own spacing formulas to apply;
-        \a t varies between 0.0 and 1.0 within each sub-range. \b Insert button
+        normalized at [0.0,1.0]. <em>f(t)</em> must be non-negative
+        at 0. <= \a t <= 1. The whole extent of geometry can be
+        divided into ranges with their own spacing formulas to apply;
+        \a t varies between 0.0 and 1.0 within each \b Range. \b Insert button
         divides a selected range into two. \b Delete button adds the
         selected sub-range to the previous one. Double click on a range in
         the list enables edition of its right boundary. Double click on a
index 673e43fdae16f08765aac2fdbeb84214f1208bf7..7253782c1384736f084b50c72c9e8aab2c9c52de 100644 (file)
         element will be added to the list. To remove a selected element or
         elements from the list click the \b Remove button. The \b Sort button
         allows to sort the list of elements IDs. The <b>Set filter</b> button
-        allows to apply a definite \ref filtering_elements "filter" to
+        allows to apply a definite \ref filtering_elements "filter" to the
         selection of elements.</li>
       <li><b>Apply to all</b> radio button allows to modify the orientation
         of all elements of the selected mesh.</li>
       <li><b>Select from</b> set of fields allows to choose a sub-mesh or an
-        existing group whose elements then can be added to the list.</li>
+        existing group whose elements can be added to the list.</li>
     </ul>
 
   </li>
index 66941609e4856cc5f510d093212de136a031b90b..2ec8a49878fa121577843d32121c0b28324a3421 100644 (file)
@@ -2,55 +2,54 @@
 
 \page constructing_meshes_page Constructing meshes
 
-To create a mesh on geometry, at first you create a mesh object by choosing
+To create a mesh on geometry, it is necessary to create a mesh object by choosing
 - a geometrical shape produced in the Geometry module (<em>main shape</em>);
 - <em>meshing parameters</em>, including 
   - \ref basic_meshing_algos_page "meshing algorithms" and
   - \ref about_hypo_page "hypotheses" specifying constraints to be
-    taken into account by chosen meshing algorithms.
+    taken into account by the chosen meshing algorithms.
 
-Then you already can launch mesh generation by invoking \ref
-compute_anchor "Compute" command.
+Then you can launch mesh generation by invoking \ref compute_anchor "Compute" command.
 
 \note Sometimes \a hypotheses term is used to refer to both algorithms
 and hypotheses.
 
-Generation of the mesh on the geometry is performed in the bottom-up
+Mesh generation on the geometry is performed in the bottom-up
 flow: nodes on vertices are created first, then edges are divided into
-segments using nodes on vertices; the segments of the edges is then
-used while meshing faces; then the mesh of the faces is used while meshing
+segments using nodes on vertices; the node of segments are then
+used to mesh faces; then the nodes of faces are used to mesh
 solids. This automatically assures the conformity of the mesh.
 
-You are to choose a meshing algorithm for every dimension of
-sub-shapes up to the highest dimension you desire to generate. Note
-that some algorithms generate elements of several dimensions while
-others, of only one. But it's not necessary to define meshing
+It is required to choose a meshing algorithm for every dimension of
+sub-shapes up to the highest dimension to be generated. Note
+that some algorithms generate elements of several dimensions, and
+others of only one. It is not necessary to define meshing
 parameters for all dimensions at once; you can start from 1D
 meshing parameters only, compute the 1D mesh, then define 2D meshing
-parameters and compute the 2D mesh (note that 1D mesh won't be
+parameters and compute the 2D mesh (note that 1D mesh will not be
 re-computed).
 
 An algorithm of a certain dimension chosen at mesh creation is applied
-to discretize every sub-shape of this dimension. But you can
+to discretize every sub-shape of this dimension. It is possible to
 specify a different algorithm or hypothesis to be applied to one or
 a group of sub-shapes by creating a \ref constructing_submeshes_page
 "sub-mesh". You can specify no algorithms at all at mesh object
 creation and specify the meshing parameters on sub-meshes only; then
-only sub-shapes for which you defined an algorithm and a needed
-hypothesis (if any) will be discretized.
+only the sub-shapes, for which an algorithm and a hypothesis (if any)
+have been defined will be discretized.
 
-\n Construction of a mesh on some geometry includes at least two (mesh
-creation and computing) of the following steps:
+\n Construction of a mesh on a geometry includes at least two 
+(\ref create_mesh_anchor "mesh creation" and
+\ref compute_anchor "computing") of the following steps:
 <ul>
-  <li> \ref create_mesh_anchor "Creation of a mesh object" where you
+  <li> \ref create_mesh_anchor "Creation of a mesh object", where you
   can specify meshing parameters to apply to all sub-shapes of the
   main shape.</li>
-  <li> \ref constructing_submeshes_page "Creation of sub-meshes"
-  (optional) where you can specify meshing parameters to apply to
+  <li> \ref constructing_submeshes_page "Creation of sub-meshes",
+  (optional) where you can specify meshing parameters to apply to the
   selected sub-shapes.</li>
   <li> \ref evaluate_anchor "Evaluating mesh size" (optional) can be
-  used to know approximate number of elements before actual generation
-  of them.</li>
+  used to know an approximate number of elements before their actual generation.</li>
   <li> \ref preview_anchor "Previewing the mesh" (optional) can be
   used to generate mesh of only lower dimension(s) in order to
   visually estimate it before full mesh generation, which can be much
@@ -61,8 +60,8 @@ creation and computing) of the following steps:
   <li> \ref compute_anchor "Computing the mesh" uses defined meshing
   parameters to generate mesh elements.</li>
   <li> \ref edit_anchor "Editing the mesh" (optional) can be used to
-  \ref modifying_meshes_page "modify" mesh of lower dimension before
-  \ref compute_anchor "computing" elements of upper dimension.</li>
+  \ref modifying_meshes_page "modify" the mesh of a lower dimension before
+  \ref compute_anchor "computing" elements of an upper dimension.</li>
 </ul>
 
 \anchor create_mesh_anchor
@@ -103,10 +102,10 @@ creation and computing) of the following steps:
     3D sub-shapes (solids) and generate 3D mesh elements
     (tetrahedra, hexahedra etc.)
 
-    As soon as you have selected an algorithm, you can create (or
-    select already created) a hypothesis. A set of accessible
-    hypotheses includes only hypotheses the selected algorithm can take
-    into account.
+    As soon as you have selected an algorithm, you can create a
+    hypothesis (or select an already created one). A set of accessible
+    hypotheses includes only the hypotheses that can be used by the
+    selected algorithm.
 
     \note
     - Some page(s) can be disabled if the geometrical
@@ -115,10 +114,10 @@ creation and computing) of the following steps:
     \b 3D page is disabled.
     - Some algorithms affect the geometry of several dimensions,
     i.e. 1D+2D or 1D+2D+3D. If such an algorithm is selected, the
-    dialog box pages related to the corresponding lower dimensions are
+    dialog pages related to the corresponding lower dimensions are
     disabled.
-    - \b 0D page does not refer to the 0D elements, but to 0D
-    geometry (vertices). Mesh module does not provide algorithms that
+    - \b 0D page refers to 0D geometry (vertices) rather than
+    to 0D elements. Mesh module does not provide algorithms that
     produce 0D elements. Currently \b 0D page provides only one
     algorithm "Segments around vertex" that allows specifying the required
     size of mesh edges about the selected vertex (or vertices).
@@ -126,9 +125,9 @@ creation and computing) of the following steps:
     For example, you need to mesh a 3D object.
 
     First, you can change a default name of your mesh in the \b Name
-    box. Then check that a selected geometrical object, whose name is
-    shown in \b Geometry field, is that you wish to mesh; if not, click
-    the right object in the Object Browser. Click "Select" button
+    box. Then check that the selected geometrical object indicated in
+    \b Geometry field, is what you wish to mesh; if not, select
+    the correct object in the Object Browser. Click "Select" button
     near \b Geometry field if the name of the object has not yet
     appeared in \b Geometry field.
     <center>
@@ -189,13 +188,9 @@ creation and computing) of the following steps:
     which is a 2D object, you do not need to define a 3D Algorithm and
     Hypotheses.
 
-    In the <b>Object Browser</b> the structure of the new mesh will be
+    In the <b>Object Browser</b> the structure of the new mesh is
     displayed as follows:
-
-    <center>
     \image html image88.jpg
-    </center>
-
     It contains: 
     <ul>
       <li>a mesh name (<em>Mesh_mechanic</em>);
@@ -205,6 +200,13 @@ creation and computing) of the following steps:
         to the hypotheses chosen at the construction of the mesh;</li>
       <li><b>Applied algorithms</b> folder containing the references
         to the algorithms chosen at the construction of the mesh.</li> 
+      <li><b>SubMeshes on Face</b> folder containing the sub-meshes
+        defined on geometrical faces. There also can be folders for
+        sub-meshes on vertices, edges, wires, shells, solids and
+        compounds.</li>
+      <li><b>Groups of Faces</b> folder containing the groups of mesh
+        faces. There also can be folders for groups of nodes, edges,
+        volumes 0D elements and balls.</li>
     </ul>
 
     There is an alternative way to assign Algorithms and Hypotheses by
@@ -214,21 +216,32 @@ creation and computing) of the following steps:
     CustomMeshers.xml file located in the home directory. CustomMeshers.xml
     file must describe sets of hypotheses in the
     same way as ${SMESH_ROOT_DIR}/share/salome/resources/smesh/StdMeshers.xml 
-    file does (sets of hypotheses are enclosed between <hypotheses-set-group>
-      tags).
-      
-      <center>
+    file does (sets of hypotheses are enclosed between \<hypotheses-set-group\>
+      tags). For example:
+~~~~~~{.xml}
+    <?xml version='1.0' encoding='us-ascii'?>
+    <!DOCTYPE meshers PUBLIC "" "desktop.dtd">
+    <meshers>
+    <hypotheses-set-group>
+        <hypotheses-set name="My favorite hypotheses"
+                        hypos="AutomaticLength"
+                        algos="CompositeSegment_1D, Quadrangle_2D, GHS3D_3D"/>
+    </hypotheses-set-group>
+    </meshers>
+~~~~~~
+    If the file contents are incorrect, there can be an error at
+    activation of Mesh module: <em>"fatal parsing error: error
+    triggered by consumer in line ..."</em>
+<br>
+<center>
       \image html hypo_sets.png
       List of sets of hypotheses. Tag <em>[custom]</em> is
       automatically added to the sets defined by the user.
-      </center>
-
+</center>
       \note 
-      - \a "Automatic" in the names of predefined sets of
-        hypotheses came from previous versions of SALOME where
-        \ref automatic_length_anchor "Automatic Length" hypothesis 
-        was included in these sets, and not that these sets are suitable for
-        meshing any geometry.
+      - \a "Automatic" in the names of predefined sets of hypotheses
+      does not actually mean that they are suitable for meshing any
+      geometry.
       - The list of sets of hypotheses can be shorter than in the
         above image depending on the geometry dimension.
   </li>
@@ -253,7 +266,9 @@ information box:
 <h2>Previewing the mesh</h2>
 
 Before \ref compute_anchor "the mesh computation", it is also possible
-to see the mesh preview.
+to see the mesh preview. This operation allows to incrementally
+compute the mesh, dimension by dimension, and to discard an
+unsatisfactory mesh.
 
 For this, select the mesh in the Object Browser. From the \b Mesh menu
 select \b Preview or click "Preview" button in the toolbar or activate
@@ -371,8 +386,8 @@ will see the following information.
 It is equally possible to skip  \ref evaluate_anchor "the Evaluation"
 and \ref preview_anchor "the Preview" and to \b Compute the mesh after
 the hypotheses are assigned. For this, select your mesh in
-the <b>Object Browser</b>. From the \b Mesh menu select \b Compute or
-click "Compute" button of the toolbar.
+the <b>Object Browser</b>. From the \b Mesh menu or the context menu
+select \b Compute or click \a "Compute" button of the toolbar.
 
 <center>
 \image html image28.png
@@ -381,24 +396,25 @@ click "Compute" button of the toolbar.
 
 After the mesh computation finishes, the Mesh Computation information
 box appears. If you close this box and click "Compute" button again,
-without previously changing meshing parameters, the mesh is
-NOT re-computed and the Mesh Computation information box with
-the same contents is shown. (To fully re-compute the mesh, invoke \ref
-clear_mesh_anchor "Clear Mesh Data" command before).
+without previously changing meshing parameters, the mesh will NOT be
+re-computed and the Mesh Computation information box will be shown
+with the same contents. (To fully re-compute the mesh, invoke 
+\ref clear_mesh_anchor "Clear Mesh Data" command before). 
 
-In case of a success, the box shows information on number of entities
-of different types in the mesh.
+If the mesh computation has been a success, the box shows information
+on the number of entities of different types in the mesh.
 
 \image html meshcomputationsucceed.png
 
 \anchor meshing_failed_anchor
-If the mesh computation failed, the information about the cause of the
+If the mesh computation has failed, the information about the cause of the
 failure is provided in \b Errors table.
 
 \image html meshcomputationfail.png
 
-After you select an error, <b>Show Sub-shape</b> button allows
-visualizing in magenta the geometrical entity that causes the error.
+After you select an error in \b Errors table, <b>Show Sub-shape</b> button allows
+visualizing in magenta the geometrical entity meshing of which failed
+(Name of this entity or its ID and type is shown in \a Sub-shape column).
 
 <center>
 \image html failed_computation.png 
@@ -439,12 +455,12 @@ By default, the information box is always shown after mesh computation operation
 \anchor edit_anchor
 <h2>Editing the mesh</h2>
 
-It is possible to \ref modifying_meshes_page "edit the mesh" of
-lower dimension before generation of mesh of higher dimension.
+It is possible to \ref modifying_meshes_page "edit the mesh" of a 
+lower dimension before generation of the mesh of a higher dimension.
 
-For example you can generate 2D mesh, modify it using e.g. 
-\ref pattern_mapping_page, and then generate 3D mesh basing on the
-modified 2D mesh. The workflow is following:
+For example you can generate 2D mesh, modify it using e.g. 
+\ref pattern_mapping_page, and then generate 3D mesh basing on the
+modified 2D mesh. The workflow is as follows:
 - Define 1D and 2D meshing algorithms.
 - Compute the mesh. 2D mesh is generated.
 - Apply \ref pattern_mapping_page.
@@ -453,9 +469,9 @@ and hypotheses.
 - Compute the mesh. 3D mesh is generated.
 
 \note Nodes and elements added \ref adding_nodes_and_elements_page
-"manually" can't be used in this workflow because the manually created
-entities are not attached to any geometry and thus (usually) can't be
-found by a mesher paving some geometry.
+"manually" cannot be used in this workflow because the manually created
+entities are not attached to any geometry and thus (usually) cannot be
+found by the mesher paving a geometry.
 
 <b>See Also</b> a sample TUI Script demonstrates the possibility of 
 \ref tui_editing_while_meshing "Intermediate edition while meshing"
index 9da2e4f7f841b74f84681122e5531b299287bff4..43f99e5c599e71976cd33d0a38dfb9377b32dd54 100644 (file)
@@ -11,8 +11,8 @@ and/or hypotheses than those used to generate the mesh on other
 sub-shapes.
 
 Creation of a sub-mesh allows to control individually meshing of a
-certain sub-shape, thus allowing to get mesh locally coarser or finer, to get
-elements of different types in the same mesh etc.
+certain sub-shape, thus to get a locally coarser or finer mesh, to get
+elements of different types in the same mesh, etc.
 
 A sub-shape to create a sub-mesh on should be retrieved from the main shape
 in one of the following ways: <ul>
@@ -33,7 +33,7 @@ compound of solids, starts from searching an algorithm, 1D as for the
 edge. The following sub-shapes are sequentially checked for presence
 of a sub-mesh where 1D algorithm is assigned:
 <ul>
-<li> the \b edge it-self</li>
+<li> the \b edge itself</li>
 <li> <b>groups of edges</b> containing the edge, if any</li>
 <li> \b wires sharing the edge</li>
 <li> \b faces sharing the edge</li>
@@ -43,29 +43,28 @@ of a sub-mesh where 1D algorithm is assigned:
 <li> <b>groups of solids</b> sharing the edge, if any</li>
 <li> the <b>main shape</b></li>
 </ul>
-(This sequence of sub-shapes defines priority of sub-meshes. Thus more
+(This sequence of sub-shapes defines the priority of sub-meshes. Thus more
 local, i.e. assigned to sub-shape of lower dimension, algorithms and
 hypotheses have higher priority during the search of hypotheses to
 apply.)
 
-As soon as an 1D algorithm is found the search stops and the same
-sequence of sub-shapes is checked to find a main and additional 1D
-hypotheses the found 1D algorithm can take into account
+As soon as a 1D algorithm is found, the search stops and the same
+sequence of sub-shapes is checked to find the main and additional 1D
+hypotheses, which can be taken into account by the found 1D algorithm
 
-The multi-dimensional algorithms have higher priority than
-uni-dimensional algorithms if they are assigned to sub-meshes of the
+The multi-dimensional algorithms have higher priority than
+uni-dimensional ones if they are assigned to sub-meshes of the
 same priority.
 
 If meshing parameters are defined on sub-meshes of the same priority,
-for example different 1D hypotheses are assigned to two faces sharing
+for example, different 1D hypotheses are assigned to two faces sharing
 an edge, the hypothesis assigned to a sub-shape with a lower ID will
 be used for meshing. You can \ref submesh_order_anchor "change" mutual
 priority of such concurrent sub-meshes. 
 
-
 \n Construction of a sub-mesh consists of:
 <ul>
-<li>Selecting a mesh which will encapsulate your sub-mesh</li>
+<li>Selecting a mesh which will encapsulate the sub-mesh</li>
 <li>Selecting a sub-shape for meshing</li>
 <li>Applying one or several
 \ref about_hypo_page "hypotheses" and 
@@ -94,7 +93,7 @@ Geometry (e.g. a face if the parent mesh has been built on box) of the
 sub-mesh. You can define meshing algorithms and hypotheses in the same way as
 in \ref constructing_meshes_page "Create mesh" dialog. 
 
-Later you can change applied hypotheses or their parameters in 
+Later you can change the applied hypotheses or their parameters in 
 \ref editing_meshes_page "Edit mesh/sub-mesh" dialog. Mesh entities
 generated using changed hypotheses are automatically removed.
 
index a8ad620b563aa770efb9340a624f9c291d7ae9db..a253c05230094f9c65032646faa07204da743119 100644 (file)
@@ -51,7 +51,7 @@ The following dialog box will appear:
 <center>Quadratic mesh</center>
 
 </li>
-<li>Click the \b Apply or \b OK button.</li>
+<li>Click the \b Apply or <b>Apply and Close</b> button.</li>
 </ol>
 
 <br><b>See Also</b> a sample TUI Script of a \ref tui_quadratic "Convert to/from quadratic" operation.
index 34a09a4494a29e373e55ceecb7d5fbd716cf897c..009866e478f7eab6de60cb4b282dbca9f6973905 100644 (file)
@@ -14,9 +14,9 @@ menu in the Object browser <b>Create Groups from Geometry</b> item.
 
 \image html create_groups_from_geometry.png
 
-In this dialog \b Elements group contains a list of shapes to create
-groups of elements on them; \b Nodes group contains a list of shapes
-to create groups of node on them.
+In this dialog \b Elements group contains a list of shapes, on which 
+groups of elements will be created; \b Nodes group contains a list of shapes, 
+on which groups of nodes will be created.
 
 
 */
index 7963535280d0739a4388782ca8314d3ebf900d5c..da12c8337b6b5472b33fde063a5ca0b338cbc534 100644 (file)
@@ -23,7 +23,9 @@ elements which will form your group:</li>
 </ul>
 <li><b>Name</b> field allows to enter the name of your new group.</li>
 <li><b>Color</b> - allows to assign to the group a certain color. The
-  chosen color is used to display the elements of the group.</li>
+  chosen color is used to display the elements of the group.<br>
+  Activation of <em>Auto Color</em> item in mesh context menu
+  switches on a random choice of a color for a new group.</li>
 </ul>
 Mesh module distinguishes between the three Group types:
 <b>Standalone Group</b>, <b>Group on Geometry</b> and <b>Group on Filter</b>.
@@ -98,11 +100,11 @@ of a certain type generated on the selected geometrical object. Group
 contents are dynamically updated if the mesh is modified. The group on
 geometry can be created only if the mesh is based on geometry.
 
-To define a group, click a \a Selection button and chose
+To define a group, click the \a Selection button and choose
 - <em>Direct geometry selection</em> to select a shape in the Object
   Browser or in the Viewer;
 - <em>Find geometry by mesh element selection</em> to activate a
-  dialog which retrieves a shape by a selected element generated on
+  dialog which retrieves a shape by the selected element generated on
   this shape.
 
 Note that this choice is available only if the mesh elements are
@@ -130,8 +132,8 @@ of a certain type satisfying the defined filter. Group contents are
 dynamically updated if the mesh is modified.
 
 To define a group, click the <b>Set filter</b> button and define
-criteria of the filter in the opened dialog. After confirmation of the
-operation a new group of mesh elements will be created. See more about
+criteria of the filter in the opened dialog. After the
+operation is confirmed, a new group of mesh elements will be created. See more about
 filters on the 
 \ref selection_filter_library_page "Selection filter library" page. 
 
index 1bc75ef208055a6a6a2d933071b409e395f0e677..c97663de2fd735485ad1442ef29e972a6c1c23d4 100644 (file)
@@ -18,7 +18,8 @@ The following dialog box shall appear:
 \image html diagonalinversion.png
  
 </li>
-<li>Enter IDs of nodes forming the required edge in the \b Edge field (the node IDs must be separated by a dash) or select
+<li>Enter IDs of nodes forming the required edge in the \b Edge field
+(the node IDs must be separated by dashes) or select
 this edge in the 3D viewer.</li>
 <li>Click the \b Apply or <b>Apply and Close</b> button.</li>
 </ol>
index 6337e5a0ea141cfaf4c5e3267cf643775ae13c78..56cb32f4c687ea4aa1bdfa8728f47dbc9c2cacf6 100644 (file)
@@ -8,7 +8,7 @@ mesh of plus one dimension are additionally created. All created
 elements can be automatically grouped. Extrusion can be used to create
 a \ref extrusion_struct "structured mesh from scratch".
 
-\image html extrusion_box.png "If you extrude several quadrangles, you get exactly same mesh as if you meshed a geometrical box (except that the initial quadrangles can be incorrectly oriented): quadrangles and segments on boundary of generated mesh are created"
+\image html extrusion_box.png "If you extrude several quadrangles, you get exactly the same mesh as if you meshed a geometrical box (except for that the initial quadrangles can be incorrectly oriented): quadrangles and segments are created on the boundary of the generated mesh"
 
 <p>Any node, segment or 2D element can be extruded. Each type of
 elements is extruded into a corresponding type of result elements:
@@ -22,6 +22,14 @@ elements is extruded into a corresponding type of result elements:
 <tr><td>Hexagonal polygon </td><td> Hexagonal prism </td></tr>
 </table>
 
+When 2D elements are extruded, in addition to 3D elements segments are
+created on ribs of the result 3D mesh. Free edges of input 2D elements
+generate logically horizontal rib segments. Logically vertical rib
+segments are generated from nodes belonging to a sole input 2D element
+(a figure below illustrates this rule).
+
+\image html extru_rib_segs.png "Two triangles extruded: no vertical rib segments generated from nodes #2 and #3 as they are shared by both triangles"
+
 <em>To use extrusion:</em>
 <ol>
 <li>From the \b Modification menu choose the \b Extrusion item or click
@@ -32,24 +40,24 @@ elements is extruded into a corresponding type of result elements:
 <em>"Extrusion" button</em>
 </center>
 
-The following dialog, looking different depending on selected options,
-will appear:
+The following dialog will appear:
 
 \image html extrusionalongaline1.png
 
-\image html extrusionalongaline2.png
-
-\image html extrusionalongaline3.png
-
 </li>
 
 <li>In this dialog:
 <ul>
+  <li>Use \a Selection button to specify what you are going to
+    select at a given moment, \b Nodes, \b Edges or \b Faces.
+    \image html image120.png
+    <center><em>"Selection" button</em></center>
+  </li>
   <li>Specify \b Nodes, \b Edges and \b Faces, which will be extruded, by one
     of following means:
     <ul>
-      <li><b>Select the whole mesh, sub-mesh or group</b> activating this
-        checkbox.</li>
+      <li><b>Select the whole mesh, sub-mesh or group</b> activating the
+        corresponding check-box.</li>
       <li>Choose mesh elements with the mouse in the 3D Viewer. It is
         possible to select a whole area with a mouse frame.</li> 
       <li>Input the element IDs directly in <b>Node IDs</b>, <b>Edge
@@ -63,7 +71,11 @@ will appear:
   <li>If the <b>Extrusion to Distance</b> radio button is selected
     - specify the translation vector by which the elements will be extruded.
   </li>
-  <li>If the <b>Extrusion Along Vector</b> radio button is selected
+  <p><br></p>
+
+\image html extrusionalongaline2.png  
+
+ <li>If the <b>Extrusion Along Vector</b> radio button is selected
     <ul>
       <li>specify the coordinates of the \b Vector along which the elements
         will be extruded, either directly or by selecting the mesh face (the
@@ -72,19 +84,23 @@ will appear:
         be negative).</li>
     </ul>
   </li>
+  <p><br></p>
+
+\image html extrusionalongaline3.png  
+  
   <li>If the <b>Extrusion By Normal</b> radio button is selected,
-    every node of selected faces is extruded along the \a average
+    every node of the selected faces is extruded along the \a average
     of the \a normal vectors to the faces sharing the node. (Nodes and
-    edges can't be extruded in this mode.)
+    edges cannot be extruded in this mode.)
     <ul>
       <li>Specify the \b Distance of extrusion (it can be negative),</li>
       <li>Use <b>Along average normal</b> check-box to specify along
-        what vector the distance is measured.
+        which vector the distance is measured.
         <ul>
           <li>If it is \a activated the distance is measured along the
             average normal mentioned above. </li>
           <li>If it is \a deactivated every node is extruded along the
-            average normal till its intersection with the virtual plane got
+            average normal till its intersection with a virtual plane obtained
             by translation of the face sharing the node along its own normal
             by the \b Distance.</li>
         </ul>
@@ -95,8 +111,8 @@ will appear:
         \image html extrusionbynormal_alongavgnorm.png "'Along average normal' activated (to the left) and deactivated (to the right)"
         <p></li>
 
-      <li>Using <b>Use only input elements</b> check-box specify what
-        elements to use to compute the average normal.<ul>
+      <li><b>Use only input elements</b> check-box specifies what
+        elements will be used to compute the average normal.<ul>
           <li> If it is \a activated only selected faces, among faces
             sharing the node, are used to compute the average normal at
             the node. </li>
index 86e5e2a372d170d2b3b8bca208c9211d9f958970..3a8497c3047274f167b85acfabbff0cd567c4044 100644 (file)
@@ -2,14 +2,16 @@
 
 \page free_borders_page Free borders
 
-\n This mesh quality control highlights borders of faces consisting of
-1D elements (segments) belonging to one face only.
+\n This mesh quality control highlights 1D elements (segments)
+belonging to one element (face or volume) only.
 
 \image html free_borders1.png
 
-In this picture the free borders are displayed in white.
+In this picture the free borders are displayed in red. (Faces are
+explicitly shown via <em>Display Entity</em> menu as all elements but
+segments are hidden upon this control activation).
 
 <br><b>See Also</b> a sample TUI Script of a 
 \ref tui_free_borders "Free Borders quality control" operation.  
 
-*/
\ No newline at end of file
+*/
index 1a5720ee2fd121ceef9ed79ff99cca91d7ab52e9..2e9d4a6ecfce814aff2c25ace9e0a5c2e76df89d 100644 (file)
@@ -3,7 +3,7 @@
 \page free_edges_page Free edges
 
 \n This mesh quality control highlights borders of faces
-consisting of node links belonging to one face only.
+(links between nodes, not mesh segments) belonging to one face only.
 
 \image html free_edges.png
 <center>In this picture some elements of mesh have been deleted and
index e24cebd3eb0a66b8b6f7e7dba9a88130ff3cc169..7d31f73504d7dedf4e880d7d14a69081b36bf163 100755 (executable)
@@ -19,12 +19,12 @@ In this dialog box specify <ul>
       <li>\b All - include if all nodes are common;</li>
       <li>\b Main - include if all corner nodes are common (meaningful for
         a quadratic mesh) </li>
-      <li><b>At least one</b> - include if one or more node is common</li>
-      <li>\b Majority - include if half of nodes or more is common</li></ul>
+      <li><b>At least one</b> - include if one or more nodes are common</li>
+      <li>\b Majority - include if half or more nodes are common</li></ul>
   </li>
   <li> select reference groups,</li>
-  <li> <b>Include underlying entities only</b> option if activated
-  allows inclusion of an entity provided that it is based on nodes of
+  <li> If <b>Include underlying entities only</b> option is activated
+  an entity can be included if it is based on nodes of
   one element of a reference group.</li>
 </ul>
 
index b0b4ab065d0bad119a2c3f5e555d96233b4163e5..9548913da3b29ca9e8f5cf1a044b0c0bf8b67c6a 100644 (file)
@@ -12,35 +12,36 @@ visualization only and is not exported.
 There are three types of groups different by their internal
 organization:<ol>
 <li><b>Standalone group</b> is a static set of mesh entities. Its
-  contents can be explicitely controlled by the user. Upon removal of
+  contents can be explicitly controlled by the user. Upon removal of
   the entities included into the group, the group becomes empty and
-  the user is to pay efforts to restore its contents. Hence it is
-  resonable to create standalone groups when the mesh generation is
+  its content can be restored only manually. Hence it is
+  reasonable to create standalone groups when the mesh generation is
   finished and mesh quality is verified.
   \warning Creation and edition of large standalone groups in
   \ref creating_groups_page "Create group" dialog using manual edition
   is problematic due to poor performance of the dialog.</li>
-<li><b>Group on geomerty</b> is associated to one or a group of
+  
+<li><b>Group on geometry</b> is associated to a sub-shape or a group of
   sub-shapes of the main shape and includes mesh entities generated on
-  this geometrical entities. The association to geometry is
-  established at group construction and can't be changed. The group
-  contents is always up-to-date without user's efforts, hence the
+  these geometrical entities. The association to a geometry is
+  established at group construction and cannot be changed. The group
+  contents are always updated automatically, hence the
   group can be created even before mesh elements generation.</li>
-<li><b>Group on filter</b> encapsulates a filter which is used to
+<li><b>Group on filter</b> encapsulates a filter, which is used to
   select mesh entities composing the group from the whole
   mesh. Criteria of the filter can be changed at any time. The
-  group contents is always up-to-date without user's efforts, hence
+  group contents are always updated automatically, hence
   the group can be created even before mesh elements generation.</li>
 </ol>
 The group on geometry and group on filter can be converted to
-the standalone group.
+a standalone group.
 
 \image html groups_in_OB.png "Groups of different types look differently in the Object Browser"
 
 The following ways of group creation are possible:
 
 - \subpage creating_groups_page "Create group" dialog allows creation of
-  a group of any of all the three types:
+  a group of any type:
   \ref standalone_group "Standalone group",
   \ref group_on_geom "Group on geometry" and
   \ref group_on_filter "Group on filter" using dedicated tabs.
@@ -49,7 +50,7 @@ The following ways of group creation are possible:
 - Standalone groups of all nodes and elements of the chosen sub-mesh
   (type of elements depends on dimension of sub-mesh geometry) can
   be created using <b>Mesh -> Construct Group</b> menu item (available
-  in context menu as well).
+  from the context menu as well).
 - Standalone groups of any element type can be created basing on nodes
   of other groups - using \subpage group_of_underlying_elements_page
   "Group based on nodes of other groups" dialog.
@@ -69,10 +70,9 @@ The created groups can be later:
 - \ref importing_exporting_meshes_page "Exported" into a file as a
   whole mesh.
 
-In the Object Browser, if groups container item includes more
-than one group, it is possible to sort the groups by name in
-ascending order. For this, select the groups container in the Object
-Browser and choose <b>Sort children</b> context menu item. 
+In the Object Browser, if an item contains more than one child group,
+it is possible to sort the groups by name in ascending order
+using <b>Sort children</b> context menu item. 
 
 \image html smesh_sort_groups.png "Sorting groups"
 
index 516981cd95a856e85de3458a0a3981a0571f9f28..b8951f00a71824ad48b399acd5af4a3c9a9a2051 100644 (file)
@@ -4,8 +4,8 @@
 
 \n In MESH there is a functionality allowing import/export
 of meshes from/to \b MED, \b UNV (I-DEAS 10), \b DAT (simple ascii format), \b STL,
-\b GMF (internal format of DISTENE products, namely BLSurf, GHS3D and
-Hexotic algorithms) and \b CGNS format files. You can also export a
+\b GMF (internal format of DISTENE products, namely MG-CADSurf, MG-Tetra and
+MG-Hexa algorithms) and \b CGNS format files. You can also export a
 group as a whole mesh.
 
 
index 48047a29607d833a1b8858ca5173570664be3378..9ecb7c5f0886ac597c3170cd42dda4be700b74e2 100644 (file)
   either \ref importing_exporting_meshes_page "imported" or manually
   created); 
  </li>
-<li>\ref importing_exporting_meshes_page "import and export of meshes in various formats";</li>
+<li>\ref importing_exporting_meshes_page "importing and exporting meshes" 
+  in various formats;</li>
 <li>\subpage modifying_meshes_page "modifying meshes" with a vast
   array of dedicated operations;</li> 
-<li>\subpage grouping_elements_page "creating groups of mesh elements";</li>
+<li>\subpage grouping_elements_page "creating groups" of mesh
+  elements;</li>
 <li>filtering mesh entities (nodes or elements) using
   \subpage filters_page "Filters" functionality for \ref
   grouping_elements_page "creating groups" and applying \ref
   modifying_meshes_page "mesh modifications";</li>
 <li>\subpage viewing_meshes_overview_page "viewing meshes" in
-  the VTK viewer;</li>
+  the VTK viewer and \ref mesh_infos_page "getting info" on mesh
+  and its sub-objects;</li>
 <li>applying to meshes \subpage quality_page "Quality Controls", 
-  allowing to highlight important elements;
-<li>various \subpage measurements_page "measurements" of the mesh objects.
+  allowing to highlight important elements;</li>
+<li>taking various \subpage measurements_page "measurements" of the
+  mesh objects.</li>
 </ul>
 
-When setting parameters of operations, it is possible to use the variables predefined in
-\subpage using_notebook_mesh_page "Salome notebook".
+It is possible to use the variables predefined in
+\subpage using_notebook_mesh_page "Salome notebook" to set parameters
+of operations.
 
-Mesh module preferences are described in the \subpage mesh_preferences_page section of SALOME Mesh Help.
+Mesh module preferences are described in the \subpage mesh_preferences_page 
+section of SALOME Mesh Help.
 
 Almost all mesh module functionalities are accessible via
 \subpage smeshpy_interface_page "Mesh module Python interface".
index 9cde2b0cef76fc850ade9f003e31d43df3016d89..6236ad02bb55d12e90363728726b0adc45494523 100644 (file)
@@ -2,68 +2,62 @@
 
 \page merging_elements_page Merging Elements
 
-\n This functionality allows to merge coincident elements of a mesh
-object selectable in the dialog box. Two elements are considered coincident if they are based on the same set of nodes.
+\n This functionality allows to merge coincident elements of a
+mesh. Two elements are considered coincident if they are based on the
+same set of nodes.
 
 \image html mergeelems_ico.png "Merge elements menu button"
 
-<ol>
-<li>Choose in the main menu \b Modification -> \b Transformation
-  -> <b>Merge elements</b> item. The following dialog box shall
-  appear:</li> 
+To merge elements choose in the main menu \b Modification -> \b Transformation
+-> <b>Merge elements</b> item. The following dialog box shall
+appear:
 
 \image html mergeelems_auto.png
-<br>
-<ul>
-<li>\b Name is the name of the mesh object whose elements will be
-  merged.</li> 
-<li>\b Automatic or \b Manual Mode allows choosing how the elements
-  are processed.
-</ul>
 
-<li><b>Automatic mode:</b>
+In this dialog:
 <ul>
-<li>In the \b Automatic Mode the elements created on the same nodes
-  will be merged.</li> 
-</ul>
-</li>
+  <li>\b Name is the name of the mesh object whose elements will be
+    merged.</li> 
+  <li>\b Automatic or \b Manual Mode allows choosing how the elements
+    are processed. In the \b Automatic Mode all elements created on
+    the same nodes will be merged. In \b Manual mode you can adjust
+    groups of coincident elements detected by the program.
 
-<li>If the \b Manual Mode is selected, additional controls are
-  available:
+    If the \b Manual Mode is selected, additional controls are
+    available:
 
 \image html mergeelems.png
 <br>
 <ul>
-<li>\b Detect button generates the list of coincident elements found
-  in the selected object.</li>
-<li><b>Coincident elements</b> is a list of groups of elements for
-  merging. As result of the operation all elements of each group will
-  be replaced by the firts element of the group.
-<ul>
-<li>\b Remove button deletes the selected group from the list.</li>
-<li>\b Add button adds to the list a group of elements selected in the
-  viewer with pressed "Shift" key.</li>
-<li><b>Select all</b> checkbox selects all groups.</li>
-<li><b>Show double elements IDs</b> checkbox shows/hides identifiers of
-  elements of selected groups in the 3D viewer.</li>
-</ul></li>
-<li><b>Edit selected group</b> list allows editing the selected group:
-<br><br>
-\image html add.png
-<center>adds to the group the elements selected in the viewer.</center>
-<br>
-\image html remove.png
-<center>removes from the group the selected elements.</center>
-<br>
-\image html sort.png
-<center>moves the selected element to the first position in the
-  group. This means that all other elements of the group will be
-  replaced by this one.</center>
-<br>
-</li>
-<li>To confirm your choice click \b Apply or <b>Apply and Close</b> button.</li>
+  <li>\b Detect button generates the list of coincident elements found
+    in the selected object.</li>
+  <li><b>Coincident elements</b> is a list of groups of elements for
+    merging. After the operation all elements of each group will
+    be united into one element. The first element of a group is kept and
+    the others are removed.
+  <li>\b Remove button deletes the selected group from the list.</li>
+  <li>\b Add button adds to the list a group of elements selected in the
+    viewer with pressed "Shift" key.</li>
+  <li><b>Select all</b> check-box selects all groups.</li>
+  <li><b>Show double elements IDs</b> check-box shows/hides identifiers of
+    elements of the selected groups in the 3D viewer.</li>
+  <li><b>Edit selected group of coincident elements</b> list allows
+    editing the selected group:
+    <br><br>
+    \image html add.png
+    <center>adds to the group the elements selected in the viewer.</center>
+    <br>
+    \image html remove.png
+    <center>removes the selected elements from the group.</center>
+    <br>
+    \image html sort.png
+    <center>moves the selected element to the first position in the
+      group in order to keep it in the mesh.</center>
+    <br>
+  </li>
+</ul>
+  <li>To confirm your choice click \b Apply or <b>Apply and Close</b> button.</li>
 </ul>
-</ol>
 
 In this picture you see a triangle which coincides with one of the
 elements of the mesh. After we apply <b>Merge Elements</b> functionality, the
index 76692add1dd24be086850d1963dd7d6b14cfdade..8aff9aa0944e5c6ba8ebdad16e85d2d47d4a22c9 100644 (file)
@@ -18,35 +18,59 @@ then converted to the single node.
 <ul>
 <li>\b Name is the name of the mesh whose nodes will be merged.</li>
 <li>\b Automatic or \b Manual mode allows choosing how the nodes are
-processed.
+  processed. In \b Manual mode you can adjust groups of coincident nodes
+  detected by the program and/or select any nodes to be merged.</li>
 <li>\b Tolerance is a maximum distance between nodes sufficient for
 merging.</li>
-<li><b>Exclude Groups</b> group box allows to ignore the nodes which
-belong to the specified mesh groups.
+<li>Activation of <b>No merge of corner and medium nodes of quadratic
+    cells</b> check-box prevents merging medium nodes of quadratic
+    elements with corner nodes. This check-box is enabled provided
+    that the selected mesh includes quadratic elements.</li>
+<li><b>Exclude groups from detection</b> group allows to ignore the
+  nodes which belong to the specified mesh groups. This control is
+  active provided that the mesh includes groups.</li>
+<li><b>Nodes to keep during the merge</b> group allows to specify
+  nodes to keep in the mesh. (By default a node being the first in a
+  group of coincident nodes is kept.) It is possible to either select
+  nodes in the Viewer or select groups of any element type whose nodes
+  will be kept.
+  <ul>
+    <li>\a Selection button activates selection of nodes to keep.</li>
+    <li><b>Nodes</b> button activates selection of nodes in the
+      Viewer.</li>
+    <li><b>Groups and sub-meshes</b> button activates selection of
+      groups and sub-meshes.</li>
+    <li>\b Add button adds selected nodes or groups to the list.</li>
+    <li> Nodes or groups selected in the list can be removed using \b
+      Remove button.</li>
+  </ul>
+</li>
 </ul>
 
 <li><b>Automatic mode:</b>
 <br>
 <ul>
-<li>In the \b Automatic Mode all Nodes within the indicated tolerance
-will be merged. The nodes which belong to the groups specified in the
-<b>Exclude Groups</b> will be not taken into account.</li>
+<li>In the \b Automatic Mode all nodes within the indicated tolerance
+will be merged. The nodes which belong to the groups specified in
+<b>Exclude groups from detection</b> will NOT be taken into account.</li>
 </ul>
 </li><br>
 <li> The \b Manual mode gives you full control of what the operation will do.
 In this mode additional controls are available:
 <ul>
-<li>\b Detect button generates the list of coincident nodes for the given
-\b Tolerance.</li>
-<li><b>Coincident nodes</b> is a list of groups of nodes for
-  merging. As result of the operation all nodes of each group will be
-  replaces by the firts node of the group.
+  <li>\b Detect button generates the list of coincident nodes for the given
+    \b Tolerance.</li>
+  <li><b>Coincident nodes</b> is a list of groups of nodes for
+    merging. Upon \b Apply all nodes of each group will
+    be united into one node. The first node of a group is kept and
+    the others are removed. By default the first node has a lowest ID
+    within the group.
 <ul>
 <li>\b Remove button deletes the selected group from the list.</li>
 <li>\b Add button adds to the list a group of nodes selected in the
-viewer with pressed "Shift" key.</li>
-<li><b>Select all</b> checkbox selects all groups.</li>
-<li><b>Show double nodes IDs</b> checkbox shows/hides identifiers of
+viewer.</li>
+<li><b>Select all</b> check-box selects all groups.</li>
+<li><b>Show double nodes IDs</b> check-box shows/hides identifiers of
 nodes of selected groups in the 3D viewer.</li>
 </ul>
 
@@ -54,28 +78,32 @@ nodes of selected groups in the 3D viewer.</li>
 \image html mergenodes.png
 <br>
 </li>
-<li><b>Edit selected group</b> list allows editing the selected
-  group:
-  <br><br>
-  \image html add.png
-  <center>adds to the group the nodes selected in the viewer.</center>
-  <br>
-  \image html remove.png
-  <center>removes from the group the selected nodes.</center>
-  <br>
-  \image html sort.png
-  <center>moves the selected node to the first position in the
-    group. This means that all other nodes of the group will be
-    replaced by this one.</center><br>
-</li>
+  <li><b>Edit selected group of coincident nodes</b> list allows
+  editing the selected group:
+    <br><br>
+    \image html add.png
+    <center>adds to the group the nodes selected in the viewer.</center>
+    <br>
+    \image html remove.png
+    <center>removes from the group the selected nodes.</center>
+    <br>
+    \image html sort.png
+    <center>moves the selected node to the first position in the
+      group in order to keep it in the mesh.</center><br>
+  </li>
 </ul>
 </li>
 <li>To confirm your choice click \b Apply or <b>Apply and Close</b> button.</li>
 </ol>
 
-\image html merging_nodes1.png "The initial obgect" 
-
-\image html merging_nodes2.png "The object has been merged with a very big tolerance"
+\image html merging_nodes1.png 
+<center> The initial object. Nodes 25, 26 and 5 are added to <b>Nodes
+    to keep during the merge</b> group.
+</center>
+<br>
+\image html merging_nodes2.png
+<center> The object has been merged
+</center>
 
 <br><b>See Also</b> a sample TUI Script of a 
 \ref tui_merging_nodes "Merge Nodes" operation.  
index 8ead995f07ffe38d497b3246efa6c686d6860696..2013cd426aca786b2bf7ce75ca87b481f26be2a7 100644 (file)
@@ -14,14 +14,16 @@ in the toolbar.
 <em>"Mesh Information" button</em></center>
 
 The <b>Mesh Information</b> dialog box provides three tab pages:
-- <b>\ref advanced_mesh_infos_anchor "Base Info"</b> - to show base
-information about the selected mesh object.
+- <b>\ref advanced_mesh_infos_anchor "Base Info"</b> - to show
+  base and quantitative information about the selected mesh object.
 - <b>\ref mesh_element_info_anchor "Element Info"</b> - to show
-detailed information about the selected mesh node or element.
-- <b>\ref mesh_addition_info_anchor "Additional Info"</b> - to show additional information available
-for the selected mesh, sub-mesh or group object.
+  detailed information about the selected mesh nodes or elements.
+- <b>\ref mesh_addition_info_anchor "Additional Info"</b> - to show
+  additional information available for the selected mesh, sub-mesh or
+  group object. 
 - <b>\ref mesh_quality_info_anchor "Quality Info"</b> - to show
-overall quality information about the selected mesh, sub-mesh or group object.
+  overall quality information about the selected mesh, sub-mesh or group
+  object. 
 
 \anchor advanced_mesh_infos_anchor
 <h2>Base Information</h2>
@@ -43,7 +45,8 @@ information about the selected mesh node(s) or element(s), namely:
 - For a node:
   - Node ID;
   - Coordinates (X, Y, Z);
-  - Connectivity information (connected elements);
+  - Connectivity information (connected elements); double click in
+    this line makes the dialog show information of these elements;
   - Position on a shape (for meshes built on a geometry);
   - Groups information (names of groups the node belongs to).
 
@@ -55,7 +58,8 @@ information about the selected mesh node(s) or element(s), namely:
   - Element ID;
   - Type (triangle, quadrangle, etc.);
   - Gravity center (X, Y, Z coordinates);
-  - Connectivity information (connected nodes);
+  - Connectivity information (connected nodes); double click in
+    a line of a node makes the dialog show information of this node;
   - Quality controls (area, aspect ration, volume, etc.);
   - Position on a shape (for meshes built on a geometry);
   - Groups information (names of groups the element belongs to).
@@ -63,7 +67,7 @@ information about the selected mesh node(s) or element(s), namely:
 <center>\image html eleminfo2.png 
 <em>"Element Info" page, element information</em></center>
 
-The use can either input the ID of a node or element he wants to
+The user can either input the ID of a node or element he wants to
 analyze directly in the dialog box or select the node(s) or element(s) in
 the 3D viewer.
 
@@ -152,6 +156,8 @@ button. Also, values are automatically computed if the number of
 nodes / elements does not exceed the "Automatic controls compute limit" set 
 via the "Mesh information" preferences (zero value means that there is no limit).
 
+\note The plot functionality is available only if GUI module is builded with Plot 2D Viewer (set option SALOME_USE_PLOT2DVIEWER to ON when building GUI module).
+
 The button \b "Dump" allows printing the information displayed in the
 dialog box to a .txt file.
 
index 7c47c1fa203c9685d4c8330926e3c0226af5d7d3..26efbe272d13a378a0161f22292bb56a58419bf6 100644 (file)
@@ -44,17 +44,17 @@ or in later sessions with this module according to the preferences.
   presentation mode as default.
 
 - <b>Representation of the 2D quadratic elements</b>
-  - <b>Default mode of the 2D quadratic elements</b> combobox - allows
+  - <b>Default mode of the 2D quadratic elements</b> combo-box - allows
     to select lines or arcs for representation of quadratic elements as default.
   - <b>Maximum Angle</b> - maximum deviation angle used by the
     application to build arcs.
 
 - <b>Mesh export</b>
-  - If you toggle <b>Automatically create groups for MED export</b> checkbox,
+  - If you toggle <b>Automatically create groups for MED export</b> check-box,
     this operation will be carried out automatically.
 
 - <b>Mesh computation</b>
-  - <b>Show a computation result notification</b> combobox allows to
+  - <b>Show a computation result notification</b> combo-box allows to
     select the notification mode about a mesh computation result.
     There are 3 possible modes:
     - <b>Never</b> - do not show the result dialog at all;
@@ -132,16 +132,16 @@ or in later sessions with this module according to the preferences.
 \image html pref22.png
 
 - <b>Nodes</b> allows to define default parameters for nodes, which will be applied 
-  for a new created mesh only. Customization of already created meshes can be done using 
-  \ref colors_size_page "Properties dialog box" that is called by click on popup menu of mesh.
+  for a newly created mesh only. Existing meshes can be customized using 
+  \ref colors_size_page "Properties dialog box" available from the context menu of a mesh.
   - <b>Color</b> -  allows to select the color of nodes. Click on the
     colored line to access to the <b>Select Color</b> dialog box.
   - <b>Type of marker</b> - allows to define the shape of nodes.
   - <b>Scale of marker</b> - allows to define the size of nodes.
 
 - <b>Elements</b> allows to define default parameters for different elements, which will be applied 
-  for a new created mesh only. Customization of already created meshes can be done using 
-  \ref colors_size_page "Properties dialog box" that is called by click on popup menu of mesh.
+  for a newly created mesh only. Existing meshes can be customized using 
+  \ref colors_size_page "Properties dialog box" available from the context menu of a mesh.
   - <b>Surface color</b>  - allows to select the surface color of 2D elements
     (seen in Shading mode). Click on the colored line to access to the
     <b>Select Color</b> dialog box.
@@ -175,21 +175,21 @@ or in later sessions with this module according to the preferences.
 - <b>Groups</b>
   - <b>Names color</b> - specifies color of group names to be used in
     3D viewer.
-  - <b>Default color</b> - specifies default group color, which is used 
-  when creating new mesh group (see \ref creating_groups_page "Create Group dialog box").
+  - <b>Default color</b> - specifies the default group color, which is used 
+  to create a new mesh group (see \ref creating_groups_page "Create Group dialog box").
 
 - <b>Numbering</b> allows to define properties of numbering functionality:
   - <b>Nodes</b> - specifies text properties of nodes numbering
     (font family, size, attributes, color).
   - <b>Elements</b> - same for elements.
 
-- <b>Orientation of Faces</b> - allows to define the behavior of
-  <b>Orientation of faces</b> functionality, which will be applied 
-  for a new created mesh only. Customization of already created meshes can be done using 
-  \ref colors_size_page "Properties dialog box" that is called by click on popup menu of mesh.
-  - \b Color - allows to define the color of orientation vertors;
+- <b>Orientation of Faces</b> - allows to define default properties of orientation vectors.
+  These preferences will be applied to the newly created meshes only; properties of existing meshes
+  can be customized using \ref colors_size_page "Properties dialog box"
+  available from the context menu of a mesh.
+  - \b Color - allows to define the color of orientation vectors;
   - \b Scale - allows to define the size of orientation vectors;
-  - <b>3D Vector</b> checkbox allows to choose between 2D planar
+  - <b>3D Vector</b> check-box allows to choose between 2D planar
     and 3D vectors.
 
 <br><h2>Selection Preferences</h2>
@@ -220,9 +220,9 @@ or in later sessions with this module according to the preferences.
 \image html pref24.png
 
 \note The following settings are default and will be applied for 
-a new created mesh only. Customization of already created meshes 
-can be done using local \ref scalar_bar_dlg "Scalar Bar Properties dialog box" 
-that is called by click on popup menu of mesh.
+a newly created mesh only. Existing meshes 
+can be customized using local \ref scalar_bar_dlg "Scalar Bar Properties dialog box" 
+available from the context menu of a mesh.
 
 - <b>Font</b> - in this menu you can set type, face and color for
   the font of <b>Title</b> and <b>Labels</b>.
index 8aa6503ba013f0459c4de201930d8b1f6d456fe0..3490916bcb4311949eaad9ee7a21da5ae12ed485 100644 (file)
@@ -43,6 +43,8 @@ transformation operations, giving the possibility to:
   triangles.</li>
 <li>\subpage split_to_tetra_page "Split" volumic elements into
   tetrahedra or prisms.</li>
+<li>\subpage split_biquad_to_linear_page "Split bi-quadratic" elements
+  into linear ones without creation of additional nodes.</li>
 <li>\subpage smoothing_page "Smooth" elements, reducung distortions in
   them by adjusting the locations of nodes.</li>
 <li>Create an \subpage extrusion_page "extrusion" along a vector or by
@@ -58,8 +60,8 @@ transformation operations, giving the possibility to:
 <li>\subpage cut_mesh_by_plane_page "Cut a tetrahedron mesh by a plane".</li>
 </ul>
 
-It is possible to \ref edit_anchor "modify the mesh" of lower
-dimension before generation of mesh of higher dimension.
+\note It is possible to \ref edit_anchor "modify the mesh" of a lower
+dimension before generation of the mesh of a higher dimension.
 
 <p><br></p>
 
index 0fee46ccc870ebd42ea98aebc82fb54ac10f40f4..b42795e5d3eb2c6709c72f41f657a38a900a26a7 100644 (file)
@@ -149,7 +149,7 @@ Alternatively, it is possible to select <b>Refine selected mesh elements</b>
 check-box and apply the pattern to
 <ul>
   <li> One or several <b>Mesh volumes</b> instead of a geometric 3D object</li>
-  <li> and select two /b Nodes instead of vertices.</li> 
+  <li> and select two \b Nodes instead of vertices.</li> 
 </ul>
 Additionally it is possible to:
 <ul>
index 976783d40d419e0ed54b91b78b9017dab38a0ea7..6a90f376e4e63b7de1e9bba8c631fbf7815c1c2a 100644 (file)
@@ -5,15 +5,20 @@
 Medial Axis Projection algorithm can be used for meshing faces with
 sinuous borders and having channel-like shape, for which is it
 difficult to define 1D hypotheses so that generated quadrangles to be
-of good shape.
+of good shape. The algorithm can be also applied to faces with ring
+topology, which can be viewed as a closed 'channel'. In the latter
+case radial discretization of a ring can be specified by
+using <em>Number of Layers</em> or <em>Distribution of Layers</em>
+hypothesis.
 
-\image html quad_from_ma_mesh.png "A mesh of a river model"
+\image html quad_from_ma_mesh.png "A mesh of a river model to the left and of a ring-face to the right"
 
 The algorithm assures good shape of quadrangles by constructing Medial
 Axis between sinuous borders of the face and using it to
-discretize the borders.
+discretize the borders. (Shape of quadrangles can be not perfect at
+locations where opposite sides of a 'channel' are far from being parallel.)
 
-\image html quad_from_ma_medial_axis.png "Media Axis between two blue sinuous borders"
+\image html quad_from_ma_medial_axis.png "Medial Axis between two blue sinuous borders"
 
 The Medial Axis is used in two ways:
 <ol>
@@ -22,9 +27,9 @@ The Medial Axis is used in two ways:
   Axis.</li>
 <li> If there is no sub-meshes on the sinuous borders, then a part of
   the Medial Axis that can be mapped to both borders is discretized
-  using a hypothesis assigned to the face or its ancestor shapes,
+  using a 1D hypothesis assigned to the face or its ancestor shapes,
   and the division points are mapped from the Medial Axis to the both
-  borders.</li>
+  borders to find positions of nodes.</li>
 </ol>
 
 */
index dfdb2d5cbf8be2743e3d2d3db3033160424fa253..1ba49dd831126b3ad473c17b1802d7fbfebba876 100644 (file)
@@ -3,20 +3,20 @@
 \page quad_ijk_algo_page Quadrangle (Mapping) meshing algorithm
 
 <b>Quadrangle (Mapping)</b> meshing algorithm is intended for creating
-all-quadrangle and quad-dominant meshes on faces with no holes and
+all-quadrangle and quad-dominant meshes on faces without holes and
 bound by at least three edges.
 
-The algorithm can create mesh on any face but mesh quality and
-validity depends on two factors:
-- face shape (number of edges and concavity of boundary);
+The algorithm can create mesh on any face but its quality and
+validity depend on two factors:
+- face shape (number of edges and boundary concavity);
 - discretization of edges.
 
 \image html quad_mesh_invalid.png "Invalid mesh on quadrilateral concave faces"
 
-The algorithm uses <em>Transfinite Interpolation</em> technic in
+The algorithm uses <em>Transfinite Interpolation</em> technique in the 
 parametric space of a face to locate nodes inside the face.
 
-The algorithm treats any face as quadrangle. If a face is bound by
+The algorithm treats any face as quadrangle. If a face is bound by
 more than four edges, four most sharp vertices are considered as
 corners of the quadrangle and all edges between these vertices are
 treated as quadrangle sides. In the case of three edges, the vertex
@@ -26,24 +26,24 @@ quadrangle.
 \image html quad_meshes.png "Algorithm generates a structured mesh on complex faces provided that edges are properly discretized"
 
 To get an all-quadrangle mesh you have to carefully define 1D
-hypotheses on edges of a face. To get a \b structured mesh you have to assure
+hypotheses on edges of a face. To get a \b structured mesh you have to provide
 equal number of segments on opposite sides of the quadrangle. If this
-condition is not respected, the algorithm by default (with no
-hypothesis) creates \b quad-dominant mesh with triangles located near a
-side with maximal number of segments. But you can get an
+condition is not respected, the algorithm by default (without a 
+hypothesis) creates a \b quad-dominant mesh with triangles located near the
+side with the maximal number of segments. However, you can get an
 \b all-quadrangle mesh in this case by using 
 \ref hypo_quad_params_anchor "Quadrangle Parameters"
 hypothesis to specify how to make transition mesh between opposite
 sides with different number of segments, provided that certain
-conditions are respected. In any case total number of segments must be
-even. To use \a Reduced transition method there must be equal number
+conditions are respected. In any case the total number of segments must be
+even. To use \a Reduced transition method, there must be an equal number
 of segments on one pair of opposite sides.
 
-The following hypotheses help in creation of quadrangle meshes. 
+The following hypotheses help to create quadrangle meshes. 
 - \ref propagation_anchor "Propagation" additional 1D hypotheses
-  help to get equal number of segments on opposite sides of the
+  help to get an equal number of segments on the opposite sides of a
   quadrilateral face.
 - \ref a1d_algos_anchor "Composite Side Discretization" algorithm is useful
-  to discretize several C1 continues edges as one quadrangle side.
+  to discretize several C1 continuous edges as one quadrangle side.
 
 */
index f2581bb891eea656a36eb60137578ea84a7bd5ad..96072cf4392471d858d77d177900d9ef75f6c979 100644 (file)
@@ -5,8 +5,8 @@
 \n This operation allows fixing the orientation of a set of faces in
 the following ways:
 <ul>
-<li>The desired orientation of a set of neighboring faces can be defined
-  by a vector giving a desired direction of a normal of a certain face. <br>
+<li>The required orientation of a set of neighboring faces can be defined
+  by a vector giving the direction of a normal to a certain face. <br>
   Since the direction of face normals in the set can be even opposite,
   it is necessary to specify a \a control face, the normal to which
   will be compared with the vector. This face can be either:
@@ -41,7 +41,7 @@ The orientation of a face is changed by reverting the order of its nodes.
 <li>To reorient by direction of the face normal:
     <ul>
     <li>Specify the coordinates of the \b Point by which the control face
-      will be found. You can specify the \b Point by either picking a
+      will be found. You can specify the \b Point by picking a
       node in the 3D Viewer or selecting a vertex in the Object
       Browser.</li>
     <li>Set up the \b Direction vector to be compared with the normal of the
@@ -61,7 +61,7 @@ The orientation of a face is changed by reverting the order of its nodes.
 
 </li>
 
-<li>In the second mode it is possible to either pick the \b Face by mouse in the 3D Viewer or directly input the \b Face ID in the corresponding field.
+<li>In the second mode it is possible to pick the \b Face by mouse in the 3D Viewer or directly input the \b Face ID in the corresponding field.
 
 <center>
 \image html reorient_2d_face.png "The orientation of adjacent faces is chosen according to a vector. The control face is explicitly given."
@@ -81,7 +81,7 @@ The orientation of a face is changed by reverting the order of its nodes.
 
 <br>
 <center>
-\image html reorient_2d_volume.png "The orientation of faces is chosen with relation to adjacent volumes."
+\image html reorient_2d_volume.png "The orientation of faces is chosen relatively to adjacent volumes."
 </center>
 
 </li>
index fdc4f95449f56618852f310a563d4347b8f3844b..f0d4194df922cd2740cc5de2a62fc8b49a377a70 100644 (file)
@@ -6,7 +6,9 @@
 dimension than the input ones.  Boundary elements around generated
 mesh of plus one dimension are additionally created. All created
 elements can be automatically grouped. Revolution can be used to create
-a \ref extrusion_struct "structured mesh from scratch".
+a \ref extrusion_struct "structured mesh from scratch". 
+See \ref extrusion_page page for general information on Revolution
+which can be viewed as extrusion along a circular path.
 
 <em>To apply revolution:</em>
 <ol>
@@ -33,7 +35,7 @@ The following dialog will appear:
       of following means:
       <ul>
         <li><b>Select the whole mesh, sub-mesh or group</b> activating this
-          checkbox.</li>
+          check-box.</li>
         <li>Choose mesh elements with the mouse in the 3D Viewer. It is
           possible to select a whole area with a mouse frame.</li>
         <li>Input the element IDs directly in <b>Node IDs</b>, <b>Edge
@@ -46,14 +48,14 @@ The following dialog will appear:
     </li>
     <li>Specify the \b Axis of revolution:
       <ul>
-        <li>Specify the cooordinates of the start \b Point of the
+        <li>Specify the coordinates of the start \b Point of the
           axis of revolution; either directly or by picking a node
           in the Viewer (selection of nodes is activated as you click
           the \a Selection button).</li>
         <li>Specify the \b Vector of the axis in either of three ways:
           <ul>
             <li>directly adjust vector components;</li>
-            <li>click \a Selection button, chose <em>From Origin to
+            <li>click \a Selection button, choose <em>From Origin to
                 selected Point</em> in the opened menu and pick a node
                 in the Viewer; </li>
             <li>click \a Selection button, chose <em>Normal to
@@ -66,16 +68,16 @@ The following dialog will appear:
       <ul> 
         <li> <b>Angle by Step</b> - the elements are revolved by the
           specified angle at each step (i.e. for Angle=30 and Number of
-          Steps=2, the elements will be extruded by 30 degrees twice for a
-          total of 30*2=60)
-\image html revolutionsn2.png "Example of Revolution with Angle by Step"
+          Steps=3, the elements will be extruded by 30 degrees twice for a
+          total of 30*3=90)
+\image html revolutionsn2.png "Example of Revolution with Angle by Step. Angle=30 and Number of Steps=3"
         </li>
         <li> <b>Total Angle</b> - the elements are revolved by the
           specified angle only once and the number of steps defines the
-          number of iterations (i.e. for Angle=30 and Number of Steps=2,
-          the elements will be revolved by 30/2=15 degrees twice for a
+          number of iterations (i.e. for Angle=30 and Number of Steps=3,
+          the elements will be revolved by 30/3=10 degrees twice for a
           total of 30).
-\image html revolutionsn1.png "Example of Revolution with Total Angle"
+\image html revolutionsn1.png "Example of Revolution with Total Angle. Angle=30 and Number of Steps=3"
         </li>
       </ul>
     </li>
index f6250d2e509b0ddb13a1044d0eff9f82d0d8d972..ecd2e8aa9f91a13de0121db7a528cf1c8989fc3c 100644 (file)
@@ -3,15 +3,20 @@
 \page segments_around_vertex_algo_page Segments around Vertex
 
 \n <b>Segments around Vertex</b> algorithm is considered to be a 0D meshing
-algorithm, but, of course, it doesn't mesh nodes. It allows to define
-the local size of the elements in the neighborhood of a certain
-node. If we choose an object of higher dimension, it applies to all
-its tops, i.e. corners of a box.  The 0D algorithm combines with the
-algorithms of higher dimensions, but it is not necessarily required
-for their successful implementation.
+algorithm, but, of course, it doesn't mesh vertices. It allows to define
+the local size of the segments in the neighborhood of a certain
+vertex. If we assign this algorithm to a geometrical object of higher
+dimension, it applies to all its vertices.
 
-This algorithm allows only one hypothesis.
+Length of segments near vertex is defined by <b> Length Near
+  Vertex </b> hypothesis.
+This hypothesis is used by \ref a1d_algos_anchor "Wire Discretization" or
+\ref a1d_algos_anchor "Composite Side Discretization" algorithms as
+follows: a geometrical edge is discretized according to a 1D
+  hypotheses and then nodes near vertices are modified to assure the
+  segment length required by <b> Length Near Vertex </b> hypothesis.
 
 \image html lengthnearvertex.png
 
-*/
\ No newline at end of file
+
+*/
index 94ba013197c717ae8cb22bdf43164282b3b730ae..30870607574f58c3dc6b1b4465c452de6fc6ad2c 100644 (file)
@@ -2,9 +2,11 @@
 
 \page selection_filter_library_page Selection filter library
 
-\n Selection filter library is a powerful tool enabling to create
-filters to be used on meshes. You can access to it from the Main Menu
-via <b>Tools / Selection filter library</b>.
+\n Selection filter library allows creating and storing in files
+filters that can be later loaded and used for operations on meshes. You can
+access to it from the Main Menu via <b>Tools / Selection filter library</b>.
+It is also possible to save any filter by invoking the filter library
+from \a Filter dialog launched from any mesh operation.
 
 \image html selectionfilterlibrary.png
 
@@ -20,21 +22,23 @@ filter. By default it is prefixed with the corresponding entity type.
 
 When we use filters during a group creation or another operation (by 
 clicking <b>Set Filter</b> button in the corresponding dialog), the
-menu for setting filters looks as shown below.
+dialog for setting filters looks as shown below.
+
+\image html a-filteronfaces.png
 
 The \b Add button creates a new criterion at the end of the list of
 criteria. The \b Insert button creates a new criterion before the
 selected criterion. The \b Remove button deletes the selected
 criterion. The \b Clear button deletes all criteria.
 \n Each <b>Entity type</b> has its specific list of criteria, however all
-filters have common syntax. For each criterion you should specify the
-<b>Threshold Value</b> and for numerical criteria whether we search
-for the elements that should be \b More, \b Less or \b Equal to this
+filters have common syntax. The <b>Threshold Value</b> should be specified 
+for most criteria. For numerical criteria it is necessary to indicate if 
+the found elements should be \b More, \b Less or \b Equal to this
 \b Value. You can also reverse the sense of a criterion using \b Unary
 operator \a Not and you should specify logical relations between
 criteria using \b Binary operators \a Or and \a And.
 \n Some criteria have the additional parameter of \b Tolerance.<br> 
-Switching on <b>Insert filter in viewer</b> checkbox limits
+Switching on <b>Insert filter in viewer</b> check-box limits
 selection of elements in the Viewer to the current filter.
 <br>
 In the \b Source field you choose if the filter will be applied to
@@ -56,8 +60,6 @@ in the Library.
 is no selected mesh in the Object Browser and the filter can not be
 created. You have to select the mesh and the button will be enabled.
 
-\image html a-filteronfaces.png
-
 Some criteria are applicable to all <b>Entity types</b>:
 <ul><li>
 <b>Belong to Geom</b> selects entities whose all nodes lie on the
@@ -72,7 +74,7 @@ algorithm works faster, if this is any other
 shape, the algorithm works slower.
 </li><li>
 <b>Belong to Mesh Group</b> selects entities included into the mesh group
-defined by <b>Threshold Value</b>.
+defined by the <b>Threshold Value</b>.
 </li><li>
 <b>Range of IDs</b> allows selection of entities with the specified
 IDs. 
@@ -102,7 +104,7 @@ defined by the <b>Threshold Value</b>. The list of available geometric
 types depends on the current entity type.
 </li><li>
 <b>Entity type</b> allows selection of elements by their type defined
-as combination of geometry type + number of nodes.
+as a combination of geometry type and the number of nodes.
 </li>
 </ul>
 
@@ -133,7 +135,7 @@ See also \ref tui_double_nodes_control "Double Nodes quality control".
 The following criteria allow selecting mesh <b>Edges</b>:
 <ul><li>
 <b>Free Borders</b> selects free 1D mesh elements, i.e. edges belonging to 
-one face only. See also a
+one element (face or volume) only. See also a
 \ref free_borders_page "Free Borders quality control".
 </li><li>
 <b>Double edges</b> selects 1D mesh elements basing on the same set of nodes.
@@ -177,8 +179,8 @@ The following criteria allow selecting mesh <b>Faces</b>:
 \ref area_page "Area quality control"), which is more, less or equal (within a given
 <b>Tolerance</b>) to the predefined <b>Threshold Value</b>.
 </li><li>
-<b>Free edges</b> selects 2D mesh elements consisting of edges belonging to 
-one element of mesh only. See also a
+<b>Free edges</b> selects 2D mesh elements having at least one of its
+edges not shared with other faces. See also a
 \ref free_edges_page "Free Edges quality control".
 </li><li>
 <b>Free faces</b> selects 2D mesh elements, which belong to less than two volumes.
index 88edc1e62e3d4c7d8d5f4c0fe43fb2c6cd0b4f70..8697b36f48b7437b7a04232c5f6acc9e28f4790d 100644 (file)
@@ -20,19 +20,82 @@ and from its sub-menu select the \b Sewing item.</li>
 <li>Check in the dialog box one of the radio buttons corresponding to
 the type of sewing operation you would like to perform.</li>
 <li>Fill the other fields available in the dialog box.</li>
-<li>Click the \b Apply or <b>Apply and Close</b> button to perform the operation of sewing.</li>
+<li>Click the \b Apply or <b>Apply and Close</b> button to perform the
+  operation of sewing.</li>
 </ol>
 
+
 <br>
 \anchor free_borders_anchor
 <h2>Sew free borders</h2>
 
-This functionality allows you to unite two free borders of a 2D mesh.
+This functionality allows you to unite free borders of a 2D mesh.
+
+There are two working modes: \a Automatic and \a Manual. In the \b
+Automatic mode, the program finds free borders coincident within a
+specified tolerance and sews them. Optionally it is possible to
+visually check and correct is necessary the found free borders before
+sewing. <br>
+In the \b Manual mode you are to define borders to sew by picking
+three nodes of each of two borders.
 
 \image html sewing1.png
+<center>Default mode is \a Automatic</center>
+
+To use \b Automatic sewing:
+<ul>
+<li>Specify a mesh you want to sew by selecting it or any its part
+  (group or sub-mesh) in the Object Browser or in the VTK Viewer.</li>
+<li>Specify the \b Tolerance within which free borders are considered
+  coincident. At the default zero \b Tolerance, the tolerance used by
+  the search algorithm is defined as one tenth of an average size of
+  elements adjacent to free borders being compared.</li>
+<li>To visually check the coincident free borders found by the
+  algorithm, switch off <b>Auto Sewing</b> check-box. Then controls
+  to adjust groups of coincident free borders will become available in
+  the dialog.</li>
+
+\image html sewing_auto.png
+<center>Controls to adjust groups of coincident free borders</center>
+
+<li>\b Detect button launches the algorithm of search of coincident
+  free borders.</li>
+<li>The found groups of <b>Coincident Free Borders</b> are shown in a
+  list, a group per a line. Each group has its own color which is used
+  to display the borders of the group in the VTK Viewer. A free border
+  within a group is designated by IDs of its first, second and last
+  nodes within parenthesis. All borders present in the list will be
+  sewn upon \b Apply.</li>
+<li>\b Remove button removes selected groups from the list.</li>
+<li><b>Select All</b> check-box selects all groups in the list.</li>
+<li>When a group is selected, its borders appear in <b>Edit Selected
+    Group</b> list that allows you to change this group.</li>
+<li>
+\image html sort.png
+<em>Set First</em> button moves the selected border to the
+  first position in the group, as a result other borders will be moved
+  to this border during sewing.
+</li><li>
+\image html remove.png
+<em>Remove Border</em> button removes selected borders from the
+  group. It is active if there are more than two borders in the group.
+</li>
+<li>Selection of a border in the list allows to change its first and
+  last nodes whose IDs appear in two fields below the list. \a Arrow
+  buttons near each field move the corresponding end node by
+  number of nodes defined by \b Step field.</li>
+<li>
+\image html swap.png
+<em>Swap</em> button swaps the first and last nodes of a
+  selected border.
+</li>
+</ul>
+
+For sewing free borders manually you should switch the \b Mode to \b
+Manual and define three points on each border: first, second and the
+last node:
 
-For sewing free borders you should define three points on each border:
-first, second and the last node:
+\image html sewing_manual.png
 <ul>
 <li>the first node specifies beginning of the border;</li>
 <li>the second node specifies the part of the border which should be
@@ -50,6 +113,16 @@ corresponding end nodes of two borders will be merged. Intermediate
 nodes of two borders will be either merged or inserted into faces of
 the opposite border.
 
+In practice the borders to sew often coincide and in this case it is
+difficult to specify the first and the last nodes of a border since
+they coincide with the first and the last nodes of the other
+border. To cope with this,
+\ref merging_nodes_page "merge" coincident nodes into one
+beforehand. Two figures below illustrate this approach.
+\image html sew_using_merge.png "Merge coincident nodes which are difficult to distinguish"
+<br>
+\image html sew_after_merge.png "After merging nodes it is easy to specify border nodes"
+
 The sewing algorithm is as follows:
 <ol>
 <li>The parameter (U) of each node within a border is computed. So
index eb74611cfcae525b7a58a85b480b1311e579b3f5..801b1c9d8a4b24de5cb98973d2be67928ad10c44 100644 (file)
@@ -3,8 +3,11 @@
 \page smoothing_page Smoothing
 
 \n Smoothing is used to improve quality of 2D mesh by adjusting the
-locations of element corners (nodes). \note Depending on smoothing
-method and mesh geometry smoothing can decrease quality of elements.
+locations of element corners (nodes). 
+
+\note Depending on the chosen method and mesh geometry
+the smoothing can actually decrease the quality of elements and even
+make some elements inverted.
 
 <em>To apply smoothing to the elements of your mesh:</em>
 <ol>
diff --git a/doc/salome/gui/SMESH/input/split_biquad_to_linear.doc b/doc/salome/gui/SMESH/input/split_biquad_to_linear.doc
new file mode 100644 (file)
index 0000000..ea4ac72
--- /dev/null
@@ -0,0 +1,37 @@
+/*!
+
+\page split_biquad_to_linear_page Split bi-quadratic into linear
+
+\n This functionality allows to split bi-quadratic elements into
+linear ones without creation of additional nodes.
+
+So that
+- bi-quadratic triangle will be split into 3 linear quadrangles;
+- bi-quadratic quadrangle will be split into 4 linear quadrangles;
+- tri-quadratic hexahedron will be split into 8 linear hexahedra;
+- quadratic segments adjacent to the split bi-quadratic element will
+  be split into 2 liner segments.
+
+\image html split_biquad_to_linear_mesh.png "Mesh before and after splitting"
+
+<em>To split bi-quadratic elements into linear:</em>
+<ol>
+<li>From the \b Modification menu choose the <b>Split bi-quadratic into linear</b> item or
+click <em>"Split bi-quadratic into linear"</em> button in the toolbar.
+
+\image html split_biquad_to_linear_icon.png
+<center><em>"Split bi-quadratic into linear" button</em></center>
+
+The following dialog box shall appear:
+
+\image html split_biquad_to_linear_dlg.png
+</li>
+<li>Select a mesh, groups or sub-meshes in the Object Browser or in the
+  Viewer.</li>
+<li>Click the \b Apply or <b>Apply and Close</b> button.</li>
+</ol>
+
+<br><b>See Also</b> a sample TUI Script of a \ref tui_split_biquad "Split bi-quadratic into linear" operation.
+
+*/
index fb5c4e1651bd0be0cb9f5bdba72a4f76b35e69db..b6ee36e935a981d21f70a30335ca87c53bc62f16 100644 (file)
@@ -7,7 +7,7 @@ tetrahedra or hexahedra into prisms. 2D mesh is modified accordingly.
 
 <em>To split volumes:</em>
 <ol>
-<li>Display a mesh, a sub-mesh or a group in the 3D viewer.</li>
+<li>Select a mesh, a sub-mesh or a group.</li>
 <li>In the \b Modification menu select the <b>Split Volumes</b> item or
 click <em>"Split Volumes"</em> button in the toolbar.
 
index 9c0b432635dc7339716d4338418af3e452c93cd5..4641ffe31d908fb20724b104043adb18eedca748 100644 (file)
@@ -64,21 +64,21 @@ possible to select a whole area with a mouse frame; or</li>
 
 <li>specify the conditions of symmetry operation:
 <ul>
-<li>activate <b>Move elements</b> radio button to change location of
+<li>activate <b>Move elements</b> radio button to change the location of
   the selected elements within the current mesh;</li>
 <li>activate <b>Copy elements</b> radio button to duplicate the
   selected elements at the new location within the current mesh;</li>
-<li>activate <b>Create as new mesh</b> radio button to create new
+<li>activate <b>Create as new mesh</b> radio button to create new
   element in a new mesh; the new mesh appears in the Object Browser
-  with the default name MeshName_mirrored (it is possible to change
+  with the default name \a MeshName_mirrored (it is possible to change
   this name in the adjacent box);</li>
-<li>activate <b> Copy groups </b> checkbox to put new mesh enities
-  into new groups if source entities belongs to some groups. New
+<li>activate <b> Copy groups </b> check-box to put new mesh entities
+  into new groups if source entities belong to some groups. New
   groups are named by pattern "<old group name>_mirrored".</li>
 </ul>
 </li>
 </ul>
-<li>activate <b>Preview</b> checkbox to show the result of
+<li>activate <b>Preview</b> check-box to show the result of
   transformation in the viewer;</li>
 <li>click \b Apply or <b> Apply and Close</b> button to confirm the
   operation.</li>
index 7ceb5ebf7d3df335804156e73c12817bd4f1c6a0..107306547185e0be615e26d69d03f438370a357c 100644 (file)
 <h2>Convert mesh to/from quadratic</h2>
 \tui_script{modifying_meshes_ex26.py}
 
+<br>
+\anchor tui_split_biquad
+<h2>Split bi-quadratic into linear</h2>
+\tui_script{split_biquad.py}
+
 */
index 6397bd4014fc292db859969f34a8d2196189c156..b9704a41ab49f80f3a7f717bdc69d3b0799ee6fa 100644 (file)
@@ -2,7 +2,7 @@
 
 \page uniting_set_of_triangles_page Uniting a set of triangles
 
-\n In MESH you can union many neighboring triangles (cells) into
+\n It is possible to unite many neighboring triangles into
 quadrangles by deletion of the common edge.
 
 <em>To union several triangles:</em>
@@ -10,7 +10,7 @@ quadrangles by deletion of the common edge.
 <li>Select a mesh (and display it in the 3D Viewer if you are going to
   pick elements by mouse).</li>
 <li>In the \b Modification menu select the <b>Union of triangles</b>
-  item or click <em>"Union of triangles"</em> button in the toolbar.
+  item or click <em>"Union of triangles"</em> button in the tool-bar.
 
 \image html image80.png
 <center><em>"Union of triangles" button</em></center>
index 39a61bbb2d2963743d8aaa6e28712fc21244c4fe..f965a015f091f159b38c13a91de104f5e2a8f399 100644 (file)
@@ -2,14 +2,14 @@
 
 \page uniting_two_triangles_page Uniting two triangles
 
-\n In MESH you can union two neighboring triangles (cells) by deletion
+\n In MESH you can union two neighboring triangles by deletion
 of the common edge.
 
 <em>To unite two triangles:</em>
 <ol>
 <li>From the \b Modification menu choose the <b>Union of two
 triangles</b> item or click <em>"Union of two triangles"</em> button
-in the toolbar.
+in the tool-bar.
 
 \image html image71.png
 <center><em>"Union of two triangles" button</em></center>
@@ -20,7 +20,7 @@ The following dialog box shall appear:
 
 </li>
 <li>Enter IDs of nodes forming the required edge in the \b Edge field
-  (the node IDs must be separated by a dash) or select this edge in
+  (a couple of node IDs separated by a dash) or select this edge in
   the 3D viewer.</li>
 <li>Click the \b Apply or <b>Apply and Close</b> button.</li>
 </ol>
index 248685579d9520764670d9577cd559f271de8e09..2472c24fa5f02da5f6cee7a15102c728aaf548fc 100644 (file)
@@ -26,8 +26,11 @@ information about the mesh.</li>
 <li>\subpage find_element_by_point_page "Find Element by Point" -
 allows to find all mesh elements, to which belongs a point with the
 given coordinates.</li>
-<li><b>Auto Color</b> - switch on / off auto-assigning colors for the groups.</li>
-<li>\subpage numbering_page "Numbering"  - allows to display the ID
+<li><b>Auto Color</b> - switch on / off auto-assigning colors for the
+  groups. If switched on, a default color of a new group in 
+  \ref creating_groups_page "Create Group" dialog is chosen
+  randomly. </li>
+<li>\subpage numbering_page "Numbering" - allows to display the ID
 numbers of all meshing elements or nodes composing your mesh in the
 viewer.</li>
 <li>\subpage display_mode_page "Display Mode" - allows to select between
index 60f603caa3c25054e0796d4c64bb8dfa755e29c6..62e4ed488cf31b0d340b24ee3a0cee14ccabeaa0 100644 (file)
@@ -1097,6 +1097,13 @@ module StdMeshers
   {
   };
 
+  /*!
+   * StdMeshers_PolygonPerFace_2D: interface of "Polygon Per Face" 2D algorithm
+   */
+  interface StdMeshers_PolygonPerFace_2D : SMESH::SMESH_2D_Algo
+  {
+  };
+
   /*!
    * StdMeshers_Hexa_3D: interface of "Hexahedron (i,j,k)" algorithm
    */
index ef962582eb49fd8e32496e6fd1491da40cf5d47b..ec43ae7146def2c40e68c18b07bde5386984ce71 100644 (file)
@@ -439,6 +439,79 @@ module SMESH
                           in string             theLibName,
                           in GEOM::GEOM_Object  theShapeObject,
                           in boolean            toCheckAll );
+
+
+    /*!
+     * Return indices of elements, which are located inside the sphere
+     *  \param theSource - mesh, sub-mesh or group
+     *  \param theElemType - mesh element type
+     *  \param theX - x cooridate of the center of the sphere
+     *  \param theY - y cooridate of the center of the sphere
+     *  \param theZ - y cooridate of the center of the sphere
+     *  \param theR - radius of the sphere
+     */
+    long_array GetInsideSphere( in SMESH_IDSource theSource,
+                               in ElementType    theElemType,
+                               in double theX, 
+                               in double theY, 
+                               in double theZ,
+                               in double theR );    
+
+    /*!
+     * Return indices of elements, which are located inside the box
+     *  \param theSource - mesh, sub-mesh or group
+     *  \param theElemType - mesh element type
+     *  \param theX1 - x cooridate of the first opposite point
+     *  \param theY1 - y cooridate of the first opposite point
+     *  \param theZ1 - y cooridate of the first opposite point
+     *  \param theX2 - x cooridate of the second opposite point
+     *  \param theY2 - y cooridate of the second opposite point
+     *  \param theZ2 - y cooridate of the second opposite point
+     */
+    long_array GetInsideBox( in SMESH_IDSource theSource,
+                            in ElementType    theElemType,
+                            in double theX1, 
+                            in double theY1, 
+                            in double theZ1,
+                            in double theX2,
+                            in double theY2,
+                            in double theZ2);    
+    /*!
+     * Return indices of elements, which are located inside the box
+     *  \param theSource - mesh, sub-mesh or group
+     *  \param theElemType - mesh element type
+     *  \param theX - x cooridate of the cented of the bottom face
+     *  \param theY - y cooridate of the cented of the bottom face
+     *  \param theZ - y cooridate of the cented of the bottom face
+     *  \param theDX - x cooridate of the cented of the base vector
+     *  \param theDY - y cooridate of the cented of the base vector
+     *  \param theDZ - z cooridate of the cented of the base vector
+     *  \param theH - height of the cylinder
+     *  \param theR - radius of the cylinder
+     */
+    long_array GetInsideCylinder( in SMESH_IDSource theSource,
+                                 in ElementType    theElemType,
+                                 in double theX, 
+                                 in double theY, 
+                                 in double theZ,
+                                 in double theDX,
+                                 in double theDY,
+                                 in double theDZ,
+                                 in double theH,
+                                 in double theR );    
+    /*!
+     * Return indices of elements, which are located inside the geometry
+     *  \param theSource - mesh, sub-mesh or group
+     *  \param theElemType - mesh element type
+     *  \param theGeom - geometrical object
+     *  \param theTolerance - tolerance for selection.
+     */
+    long_array GetInside( in SMESH_IDSource theSource,
+                         in ElementType    theElemType,
+                         in GEOM::GEOM_Object theGeom,
+                         in double theTolerance );    
+
+
   };
 
 };
index bb193bcc15e2a26f3eea69c7811851f8417953e3..9ede0252fd5aec967268aa8430741bc3d24c4ec7 100644 (file)
@@ -66,6 +66,7 @@ module SMESH
       ADD_QUADEDGE,
       ADD_QUADTRIANGLE,
       ADD_QUADQUADRANGLE,
+      ADD_QUADPOLYGON,
       ADD_QUADTETRAHEDRON,
       ADD_QUADPYRAMID,
       ADD_QUADPENTAHEDRON,
@@ -89,18 +90,18 @@ module SMESH
 
   struct PointStruct { double x;
                        double y;
-                       double z; } ;
+                       double z; };
 
   typedef sequence<PointStruct> nodes_array;
 
-  struct DirStruct   { PointStruct PS ; } ;          // analog to OCCT gp_Vec
+  struct DirStruct   { PointStruct PS; };          // analog to OCCT gp_Vec
 
   struct AxisStruct  { double x;
                        double y;
                        double z;
                        double vx;
                        double vy;
-                       double vz; } ;
+                       double vz; };
   /*!
    * Node location on a shape
    */
@@ -132,7 +133,7 @@ module SMESH
     BALL,
     NB_ELEMENT_TYPES
   };
-  typedef sequence<ElementType> array_of_ElementType ;
+  typedef sequence<ElementType> array_of_ElementType;
 
   /*!
    * Enumeration for element geometry type, like SMDSAbs_GeometryType in SMDSAbs_ElementType.hxx
@@ -778,6 +779,9 @@ module SMESH
     long NbPolygons()
       raises (SALOME::SALOME_Exception);
 
+    long NbPolygonsOfOrder(in ElementOrder order)
+      raises (SALOME::SALOME_Exception);
+
     long NbVolumes()
       raises (SALOME::SALOME_Exception);
 
@@ -1040,7 +1044,7 @@ module SMESH
       raises (SALOME::SALOME_Exception);
     
     /*!
-     * Return type of submesh element
+     * Returns type of mesh element (same as SMESH_Mesh::GetElementType() )
      */
     ElementType GetElementType( in long id, in boolean iselem )
       raises (SALOME::SALOME_Exception);
index cc6dc0874ad21c60651b543a717594d087340f4b..8c63fdbdab7dc8a9eb4e57da139fe1d08ef25781 100644 (file)
 
 module SMESH
 {
+  interface NumericalFunctor;
+
   enum Bnd_Dimension { BND_2DFROM3D, BND_1DFROM3D, BND_1DFROM2D };
 
+
+  struct FreeBorder
+  {
+    SMESH::long_array nodeIDs; // all nodes defining a free border
+    // 1st and last node is same in a closed border
+  };
+  struct FreeBorderPart
+  {
+    short border; // border index within a sequence<FreeBorder>
+    long  node1;  // node index within the border-th FreeBorder
+    long  node2;
+    long  nodeLast;
+  };
+  typedef sequence<FreeBorder>       ListOfFreeBorders;
+  typedef sequence<FreeBorderPart>   FreeBordersGroup;
+  typedef sequence<FreeBordersGroup> ListOfFreeBorderGroups;
+
+  struct CoincidentFreeBorders
+  {
+    ListOfFreeBorders      borders;          // nodes of all free borders
+    ListOfFreeBorderGroups coincidentGroups; // groups of coincident parts of borders
+  };
+
+
   /*!
    * This interface makes modifications on the Mesh - removing elements and nodes etc.
    */
-  interface NumericalFunctor;
-
   interface SMESH_MeshEditor
   {
    /*!
@@ -143,6 +167,13 @@ module SMESH
 
     long AddPolygonalFace(in long_array IdsOfNodes) raises (SALOME::SALOME_Exception);
 
+    /*!
+     * Create a quadratic polygonal face
+     *  \param IdsOfNodes - nodes of the polygon; corner nodes follow first
+     *  \return long - ID of a new polygon
+     */
+    long AddQuadPolygonalFace(in long_array IdsOfNodes) raises (SALOME::SALOME_Exception);
+
     /*!
      *  Create volume, either linear and quadratic (this is determed
      *  by number of given nodes).
@@ -353,13 +384,25 @@ module SMESH
      *         to \a facetToSplitNormal location are split, else \a facetToSplitNormal
      *         is used to find the facet to split in all domains present in \a elems.
      */
-    void SplitHexahedraIntoPrisms(in SMESH_IDSource     elems, 
+    void SplitHexahedraIntoPrisms(in SMESH_IDSource     elems,
                                   in SMESH::PointStruct startHexPoint,
                                   in SMESH::DirStruct   facetToSplitNormal,
                                   in short              methodFlags,
                                   in boolean            allDomains)
       raises (SALOME::SALOME_Exception);
 
+    /*!
+     * \brief Split bi-quadratic elements into linear ones without creation of additional nodes.
+     *   - bi-quadratic triangle will be split into 3 linear quadrangles;
+     *   - bi-quadratic quadrangle will be split into 4 linear quadrangles;
+     *   - tri-quadratic hexahedron will be split into 8 linear hexahedra;
+     *   Quadratic elements of lower dimension  adjacent to the split bi-quadratic element
+     *   will be split in order to keep the mesh conformal.
+     *  \param elems - elements to split
+     */
+    void SplitBiQuadraticIntoLinear(in ListOfIDSources elems)
+      raises (SALOME::SALOME_Exception);
+
 
     enum Smooth_Method { LAPLACIAN_SMOOTH, CENTROIDAL_SMOOTH };
 
@@ -602,41 +645,45 @@ module SMESH
                                in AxisStruct Axis,
                                in double     AngleInRadians,
                                in boolean    CopyGroups,
-                               in string     MeshName) 
+                               in string     MeshName)
       raises (SALOME::SALOME_Exception);
 
     void RotateObject (in SMESH_IDSource theObject,
                        in AxisStruct     Axis,
                        in double         AngleInRadians,
-                       in boolean        Copy) 
+                       in boolean        Copy)
       raises (SALOME::SALOME_Exception);
     ListOfGroups RotateObjectMakeGroups (in SMESH_IDSource theObject,
                                          in AxisStruct     Axis,
-                                         in double         AngleInRadians) 
+                                         in double         AngleInRadians)
       raises (SALOME::SALOME_Exception);
     SMESH_Mesh RotateObjectMakeMesh (in SMESH_IDSource theObject,
                                      in AxisStruct     Axis,
                                      in double         AngleInRadians,
                                      in boolean        CopyGroups,
-                                     in string         MeshName) 
+                                     in string         MeshName)
       raises (SALOME::SALOME_Exception);
 
     void FindCoincidentNodes (in  double              Tolerance,
-                              out array_of_long_array GroupsOfNodes) 
+                              out array_of_long_array GroupsOfNodes,
+                              in  boolean             SeparateCornersAndMedium)
       raises (SALOME::SALOME_Exception);
 
     void FindCoincidentNodesOnPart (in  SMESH_IDSource      SubMeshOrGroup,
                                     in  double              Tolerance,
-                                    out array_of_long_array GroupsOfNodes) 
+                                    out array_of_long_array GroupsOfNodes,
+                                    in  boolean             SeparateCornersAndMedium)
       raises (SALOME::SALOME_Exception);
 
     void FindCoincidentNodesOnPartBut (in  SMESH_IDSource      SubMeshOrGroup,
                                        in  double              Tolerance,
                                        out array_of_long_array GroupsOfNodes,
-                                       in  ListOfIDSources     ExceptSubMeshOrGroups) 
+                                       in  ListOfIDSources     ExceptSubMeshOrGroups,
+                                       in  boolean             SeparateCornersAndMedium)
       raises (SALOME::SALOME_Exception);
 
-    void MergeNodes (in array_of_long_array GroupsOfNodes) 
+    void MergeNodes (in array_of_long_array    GroupsOfNodes,
+                     in SMESH::ListOfIDSources NodesToKeep)
       raises (SALOME::SALOME_Exception);
 
     /*!
@@ -700,6 +747,21 @@ module SMESH
     short GetPointState(in double x, in double y, in double z) 
       raises (SALOME::SALOME_Exception);
 
+    /*!
+     * Returns groups of FreeBorder's coincident within the given tolerance.
+     * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
+     * to free borders being compared is used.
+     */
+    CoincidentFreeBorders FindCoincidentFreeBorders(in double tolerance);
+
+    /*!
+     * Sew FreeBorder's of each group
+     */
+    short SewCoincidentFreeBorders (in CoincidentFreeBorders freeBorders,
+                                    in boolean               createPolygons,
+                                    in boolean               createPolyedrs)
+      raises (SALOME::SALOME_Exception);
+
     enum Sew_Error {
       SEW_OK,
       SEW_BORDER1_NOT_FOUND,
index 24a83d09a7ca19a0ce5717cc605f44f804cfbb08..66f426f0090dfbb9bbba5dd6183af7992de57bfd 100755 (executable)
@@ -98,6 +98,7 @@ SET(SMESH_RESOURCES_FILES
   mesh_tetra.png
   mesh_tree_algo_hexa.png
   mesh_tree_algo_mefisto.png
+  mesh_tree_algo_polygon.png
   mesh_tree_algo.png
   mesh_tree_algo_0D.png
   mesh_tree_algo_quad.png
@@ -170,6 +171,7 @@ SET(SMESH_RESOURCES_FILES
   mesh_quad_edge.png
   mesh_quad_triangle.png
   mesh_quad_quadrangle.png
+  mesh_quad_polygon.png
   mesh_quad_tetrahedron.png
   mesh_quad_pyramid.png
   mesh_quad_pentahedron.png
@@ -201,6 +203,7 @@ SET(SMESH_RESOURCES_FILES
   scale.png
   scale_along_axes.png
   split_into_tetra.png
+  split_biquad.png
   mesh_duplicate_nodes.png
   mesh_duplicate_nodes_with_elem.png
   mesh_duplicate_elem_only.png
index 4150b42dcf239a35accaffdd041553ae16db2674..c537c5adc9b1115e3ef318d155244315c2a11783 100644 (file)
     <algorithm type     ="QuadFromMedialAxis_1D2D"
                label-id ="Quadrangle (Medial Axis Projection)"
                icon-id  ="mesh_algo_quad.png"
+               hypos    ="NumberOfLayers2D, LayerDistribution2D"
                opt-hypos="ViscousLayers2D"
                input    ="EDGE"
                output   ="QUAD"
       <python-wrap>
         <algo>QuadFromMedialAxis_1D2D=Quadrangle(algo=smeshBuilder.QUAD_MA_PROJ)</algo>
         <hypo>ViscousLayers2D=ViscousLayers2D(SetTotalThickness(),SetNumberLayers(),SetStretchFactor(),SetIgnoreEdges())</hypo>
+        <hypo>NumberOfLayers2D=NumberOfLayers(SetNumberOfLayers())</hypo>
+      </python-wrap>
+    </algorithm>
+
+    <algorithm type     ="PolygonPerFace_2D"
+               label-id ="Polygon per Face"
+               icon-id  ="mesh_algo_polygon.png"
+               opt-hypos="ViscousLayers2D"
+               input    ="EDGE"
+               output   ="POLYGON,QUAD,TRIA"
+               dim      ="2">
+      <python-wrap>
+        <algo>PolygonPerFace_2D=Polygon()</algo>
+        <hypo>ViscousLayers2D=ViscousLayers2D(SetTotalThickness(),SetNumberLayers(),SetStretchFactor(),SetIgnoreEdges())</hypo>
       </python-wrap>
     </algorithm>
 
diff --git a/resources/mesh_quad_polygon.png b/resources/mesh_quad_polygon.png
new file mode 100644 (file)
index 0000000..e9dfa35
Binary files /dev/null and b/resources/mesh_quad_polygon.png differ
diff --git a/resources/mesh_tree_algo_polygon.png b/resources/mesh_tree_algo_polygon.png
new file mode 100644 (file)
index 0000000..3770515
Binary files /dev/null and b/resources/mesh_tree_algo_polygon.png differ
diff --git a/resources/split_biquad.png b/resources/split_biquad.png
new file mode 100644 (file)
index 0000000..0b9b7a0
Binary files /dev/null and b/resources/split_biquad.png differ
index 0b53dd266e85c0ea00ca3ebac208948d822a6660..769096df4344b7e69a9d61ac59e8d7d6d903b5f9 100644 (file)
 #include "SMDS_QuadraticFaceOfNodes.hxx"
 #include "SMDS_VolumeTool.hxx"
 #include "SMESHDS_GroupBase.hxx"
+#include "SMESHDS_GroupOnFilter.hxx"
 #include "SMESHDS_Mesh.hxx"
-#include "SMESH_OctreeNode.hxx"
 #include "SMESH_MeshAlgos.hxx"
+#include "SMESH_OctreeNode.hxx"
 
 #include <Basics_Utils.hxx>
 
@@ -68,7 +69,6 @@
 
 #include <set>
 #include <limits>
-#include <TopTools_MapOfShape.hxx>
 
 /*
                             AUXILIARY METHODS
@@ -136,8 +136,8 @@ namespace {
     int aResult0 = 0, aResult1 = 0;
      // last node, it is a medium one in a quadratic edge
     const SMDS_MeshNode* aLastNode = anEdge->GetNode( anEdge->NbNodes() - 1 );
-    const SMDS_MeshNode* aNode0 = anEdge->GetNode( 0 );
-    const SMDS_MeshNode* aNode1 = anEdge->GetNode( 1 );
+    const SMDS_MeshNode*    aNode0 = anEdge->GetNode( 0 );
+    const SMDS_MeshNode*    aNode1 = anEdge->GetNode( 1 );
     if ( aNode1 == aLastNode ) aNode1 = 0;
 
     SMDS_ElemIteratorPtr anElemIter = aLastNode->GetInverseElementIterator();
@@ -159,29 +159,6 @@ namespace {
     }
     int aResult = std::max ( aResult0, aResult1 );
 
-//     TColStd_MapOfInteger aMap;
-
-//     SMDS_ElemIteratorPtr anIter = anEdge->nodesIterator();
-//     if ( anIter != 0 ) {
-//       while( anIter->more() ) {
-//      const SMDS_MeshNode* aNode = (SMDS_MeshNode*)anIter->next();
-//      if ( aNode == 0 )
-//        return 0;
-//      SMDS_ElemIteratorPtr anElemIter = aNode->GetInverseElementIterator();
-//      while( anElemIter->more() ) {
-//        const SMDS_MeshElement* anElem = anElemIter->next();
-//        if ( anElem != 0 && anElem->GetType() != SMDSAbs_Edge ) {
-//          int anId = anElem->GetID();
-
-//          if ( anIter->more() )              // i.e. first node
-//            aMap.Add( anId );
-//          else if ( aMap.Contains( anId ) )
-//            aResult++;
-//        }
-//      }
-//       }
-//     }
-
     return aResult;
   }
 
@@ -233,7 +210,7 @@ void NumericalFunctor::SetMesh( const SMDS_Mesh* theMesh )
   myMesh = theMesh;
 }
 
-bool NumericalFunctor::GetPoints(const int theId,
+bool NumericalFunctor::GetPoints(const int       theId,
                                  TSequenceOfXYZ& theRes ) const
 {
   theRes.clear();
@@ -257,6 +234,7 @@ bool NumericalFunctor::GetPoints(const SMDS_MeshElement* anElem,
     return false;
 
   theRes.reserve( anElem->NbNodes() );
+  theRes.setElement( anElem );
 
   // Get nodes of the element
   SMDS_ElemIteratorPtr anIter;
@@ -273,7 +251,6 @@ bool NumericalFunctor::GetPoints(const SMDS_MeshElement* anElem,
       break;
     default:
       anIter = anElem->nodesIterator();
-      //return false;
     }
   }
   else {
@@ -281,9 +258,13 @@ bool NumericalFunctor::GetPoints(const SMDS_MeshElement* anElem,
   }
 
   if ( anIter ) {
+    double xyz[3];
     while( anIter->more() ) {
       if ( const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>( anIter->next() ))
-        theRes.push_back( gp_XYZ( aNode->X(), aNode->Y(), aNode->Z() ) );
+      {
+        aNode->GetXYZ( xyz );
+        theRes.push_back( gp_XYZ( xyz[0], xyz[1], xyz[2] ));
+      }
     }
   }
 
@@ -348,7 +329,7 @@ void NumericalFunctor::GetHistogram(int                  nbIntervals,
   std::multiset< double > values;
   if ( elements.empty() )
   {
-    SMDS_ElemIteratorPtr elemIt = myMesh->elementsIterator(GetType());
+    SMDS_ElemIteratorPtr elemIt = myMesh->elementsIterator( GetType() );
     while ( elemIt->more() )
       values.insert( GetValue( elemIt->next()->GetID() ));
   }
@@ -481,6 +462,27 @@ double MaxElementLength2D::GetValue( const TSequenceOfXYZ& P )
     double D2 = getDistance(P( 3 ),P( 7 ));
     aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(D1,D2));
   }
+  // Diagonals are undefined for concave polygons
+  // else if ( P.getElementEntity() == SMDSEntity_Quad_Polygon && P.size() > 2 ) // quad polygon
+  // {
+  //   // sides
+  //   aVal = getDistance( P( 1 ), P( P.size() )) + getDistance( P( P.size() ), P( P.size()-1 ));
+  //   for ( size_t i = 1; i < P.size()-1; i += 2 )
+  //   {
+  //     double L = getDistance( P( i ), P( i+1 )) + getDistance( P( i+1 ), P( i+2 ));
+  //     aVal = Max( aVal, L );
+  //   }
+  //   // diagonals
+  //   for ( int i = P.size()-5; i > 0; i -= 2 )
+  //     for ( int j = i + 4; j < P.size() + i - 2; i += 2 )
+  //     {
+  //       double D = getDistance( P( i ), P( j ));
+  //       aVal = Max( aVal, D );
+  //     }
+  // }
+  // { // polygons
+    
+  // }
 
   if( myPrecision >= 0 )
   {
@@ -699,8 +701,9 @@ double MinimumAngle::GetValue( const TSequenceOfXYZ& P )
   aMin = getAngle(P( P.size() ), P( 1 ), P( 2 ));
   aMin = Min(aMin,getAngle(P( P.size()-1 ), P( P.size() ), P( 1 )));
 
-  for (int i=2; i<P.size();i++){
-      double A0 = getAngle( P( i-1 ), P( i ), P( i+1 ) );
+  for ( int i = 2; i < P.size(); i++ )
+  {
+    double A0 = getAngle( P( i-1 ), P( i ), P( i+1 ) );
     aMin = Min(aMin,A0);
   }
 
@@ -1467,11 +1470,14 @@ SMDSAbs_ElementType Skew::GetType() const
 double Area::GetValue( const TSequenceOfXYZ& P )
 {
   double val = 0.0;
-  if ( P.size() > 2 ) {
+  if ( P.size() > 2 )
+  {
     gp_Vec aVec1( P(2) - P(1) );
     gp_Vec aVec2( P(3) - P(1) );
     gp_Vec SumVec = aVec1 ^ aVec2;
-    for (int i=4; i<=P.size(); i++) {
+
+    for (int i=4; i<=P.size(); i++)
+    {
       gp_Vec aVec1( P(i-1) - P(1) );
       gp_Vec aVec2( P(i) - P(1) );
       gp_Vec tmp = aVec1 ^ aVec2;
@@ -1523,7 +1529,7 @@ SMDSAbs_ElementType Length::GetType() const
 //================================================================================
 /*
   Class       : Length2D
-  Description : Functor for calculating length of edge
+  Description : Functor for calculating minimal length of edge
 */
 //================================================================================
 
@@ -1531,63 +1537,59 @@ double Length2D::GetValue( long theElementId )
 {
   TSequenceOfXYZ P;
 
-  //cout<<"Length2D::GetValue"<<endl;
-  if (GetPoints(theElementId,P)){
-    //for(int jj=1; jj<=P.size(); jj++)
-    //  cout<<"jj="<<jj<<" P("<<P(jj).X()<<","<<P(jj).Y()<<","<<P(jj).Z()<<")"<<endl;
-
-    double  aVal;// = GetValue( P );
-    const SMDS_MeshElement* aElem = myMesh->FindElement( theElementId );
-    SMDSAbs_ElementType aType = aElem->GetType();
-
+  if ( GetPoints( theElementId, P ))
+  {
+    double aVal = 0;
     int len = P.size();
+    SMDSAbs_EntityType aType = P.getElementEntity();
 
-    switch (aType){
-    case SMDSAbs_All:
-    case SMDSAbs_Node:
-    case SMDSAbs_Edge:
-      if (len == 2){
+    switch (aType) {
+    case SMDSEntity_Edge:
+      if (len == 2)
         aVal = getDistance( P( 1 ), P( 2 ) );
-        break;
-      }
-      else if (len == 3){ // quadratic edge
+      break;
+    case SMDSEntity_Quad_Edge:
+      if (len == 3) // quadratic edge
         aVal = getDistance(P( 1 ),P( 3 )) + getDistance(P( 3 ),P( 2 ));
-        break;
-      }
-    case SMDSAbs_Face:
+      break;
+    case SMDSEntity_Triangle:
       if (len == 3){ // triangles
         double L1 = getDistance(P( 1 ),P( 2 ));
         double L2 = getDistance(P( 2 ),P( 3 ));
         double L3 = getDistance(P( 3 ),P( 1 ));
         aVal = Min(L1,Min(L2,L3));
-        break;
       }
-      else if (len == 4){ // quadrangles
+      break;
+    case SMDSEntity_Quadrangle:
+      if (len == 4){ // quadrangles
         double L1 = getDistance(P( 1 ),P( 2 ));
         double L2 = getDistance(P( 2 ),P( 3 ));
         double L3 = getDistance(P( 3 ),P( 4 ));
         double L4 = getDistance(P( 4 ),P( 1 ));
         aVal = Min(Min(L1,L2),Min(L3,L4));
-        break;
       }
-      if (len == 6){ // quadratic triangles
+      break;
+    case SMDSEntity_Quad_Triangle:
+    case SMDSEntity_BiQuad_Triangle:
+      if (len >= 6){ // quadratic triangles
         double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 ));
         double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 ));
         double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 1 ));
         aVal = Min(L1,Min(L2,L3));
-        //cout<<"L1="<<L1<<" L2="<<L2<<"L3="<<L3<<" aVal="<<aVal<<endl;
-        break;
       }
-      else if (len == 8){ // quadratic quadrangles
+      break;
+    case SMDSEntity_Quad_Quadrangle:
+    case SMDSEntity_BiQuad_Quadrangle:
+      if (len >= 8){ // quadratic quadrangles
         double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 ));
         double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 ));
         double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 7 ));
         double L4 = getDistance(P( 7 ),P( 8 )) + getDistance(P( 8 ),P( 1 ));
         aVal = Min(Min(L1,L2),Min(L3,L4));
-        break;
       }
-    case SMDSAbs_Volume:
-      if (len == 4){ // tetraidrs
+      break;
+    case SMDSEntity_Tetra:
+      if (len == 4){ // tetrahedra
         double L1 = getDistance(P( 1 ),P( 2 ));
         double L2 = getDistance(P( 2 ),P( 3 ));
         double L3 = getDistance(P( 3 ),P( 1 ));
@@ -1595,9 +1597,10 @@ double Length2D::GetValue( long theElementId )
         double L5 = getDistance(P( 2 ),P( 4 ));
         double L6 = getDistance(P( 3 ),P( 4 ));
         aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
-        break;
       }
-      else if (len == 5){ // piramids
+      break;
+    case SMDSEntity_Pyramid:
+      if (len == 5){ // piramids
         double L1 = getDistance(P( 1 ),P( 2 ));
         double L2 = getDistance(P( 2 ),P( 3 ));
         double L3 = getDistance(P( 3 ),P( 4 ));
@@ -1609,9 +1612,10 @@ double Length2D::GetValue( long theElementId )
 
         aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
         aVal = Min(aVal,Min(L7,L8));
-        break;
       }
-      else if (len == 6){ // pentaidres
+      break;
+    case SMDSEntity_Penta:
+      if (len == 6) { // pentaidres
         double L1 = getDistance(P( 1 ),P( 2 ));
         double L2 = getDistance(P( 2 ),P( 3 ));
         double L3 = getDistance(P( 3 ),P( 1 ));
@@ -1624,9 +1628,10 @@ double Length2D::GetValue( long theElementId )
 
         aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
         aVal = Min(aVal,Min(Min(L7,L8),L9));
-        break;
       }
-      else if (len == 8){ // hexaider
+      break;
+    case SMDSEntity_Hexa:
+      if (len == 8){ // hexahedron
         double L1 = getDistance(P( 1 ),P( 2 ));
         double L2 = getDistance(P( 2 ),P( 3 ));
         double L3 = getDistance(P( 3 ),P( 4 ));
@@ -1643,10 +1648,9 @@ double Length2D::GetValue( long theElementId )
         aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
         aVal = Min(aVal,Min(Min(L7,L8),Min(L9,L10)));
         aVal = Min(aVal,Min(L11,L12));
-        break;
-
       }
-
+      break;
+    case SMDSEntity_Quad_Tetra:
       if (len == 10){ // quadratic tetraidrs
         double L1 = getDistance(P( 1 ),P( 5 )) + getDistance(P( 5 ),P( 2 ));
         double L2 = getDistance(P( 2 ),P( 6 )) + getDistance(P( 6 ),P( 3 ));
@@ -1655,9 +1659,10 @@ double Length2D::GetValue( long theElementId )
         double L5 = getDistance(P( 2 ),P( 9 )) + getDistance(P( 9 ),P( 4 ));
         double L6 = getDistance(P( 3 ),P( 10 )) + getDistance(P( 10 ),P( 4 ));
         aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
-        break;
       }
-      else if (len == 13){ // quadratic piramids
+      break;
+    case SMDSEntity_Quad_Pyramid:
+      if (len == 13){ // quadratic piramids
         double L1 = getDistance(P( 1 ),P( 6 )) + getDistance(P( 6 ),P( 2 ));
         double L2 = getDistance(P( 2 ),P( 7 )) + getDistance(P( 7 ),P( 3 ));
         double L3 = getDistance(P( 3 ),P( 8 )) + getDistance(P( 8 ),P( 4 ));
@@ -1668,9 +1673,10 @@ double Length2D::GetValue( long theElementId )
         double L8 = getDistance(P( 4 ),P( 13 )) + getDistance(P( 13 ),P( 5 ));
         aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
         aVal = Min(aVal,Min(L7,L8));
-        break;
       }
-      else if (len == 15){ // quadratic pentaidres
+      break;
+    case SMDSEntity_Quad_Penta:
+      if (len == 15){ // quadratic pentaidres
         double L1 = getDistance(P( 1 ),P( 7 )) + getDistance(P( 7 ),P( 2 ));
         double L2 = getDistance(P( 2 ),P( 8 )) + getDistance(P( 8 ),P( 3 ));
         double L3 = getDistance(P( 3 ),P( 9 )) + getDistance(P( 9 ),P( 1 ));
@@ -1682,9 +1688,11 @@ double Length2D::GetValue( long theElementId )
         double L9 = getDistance(P( 3 ),P( 15 )) + getDistance(P( 15 ),P( 6 ));
         aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
         aVal = Min(aVal,Min(Min(L7,L8),L9));
-        break;
       }
-      else if (len == 20){ // quadratic hexaider
+      break;
+    case SMDSEntity_Quad_Hexa:
+    case SMDSEntity_TriQuad_Hexa:
+      if (len >= 20) { // quadratic hexaider
         double L1 = getDistance(P( 1 ),P( 9 )) + getDistance(P( 9 ),P( 2 ));
         double L2 = getDistance(P( 2 ),P( 10 )) + getDistance(P( 10 ),P( 3 ));
         double L3 = getDistance(P( 3 ),P( 11 )) + getDistance(P( 11 ),P( 4 ));
@@ -1700,11 +1708,55 @@ double Length2D::GetValue( long theElementId )
         aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
         aVal = Min(aVal,Min(Min(L7,L8),Min(L9,L10)));
         aVal = Min(aVal,Min(L11,L12));
-        break;
-
       }
-
-    default: aVal=-1;
+      break;
+    case SMDSEntity_Polygon:
+      if ( len > 1 ) {
+        aVal = getDistance( P(1), P( P.size() ));
+        for ( size_t i = 1; i < P.size(); ++i )
+          aVal = Min( aVal, getDistance( P( i ), P( i+1 )));
+      }
+      break;
+    case SMDSEntity_Quad_Polygon:
+      if ( len > 2 ) {
+        aVal = getDistance( P(1), P( P.size() )) + getDistance( P(P.size()), P( P.size()-1 ));
+        for ( size_t i = 1; i < P.size()-1; i += 2 )
+          aVal = Min( aVal, getDistance( P( i ), P( i+1 )) + getDistance( P( i+1 ), P( i+2 )));
+      }
+      break;
+    case SMDSEntity_Hexagonal_Prism:
+      if (len == 12) { // hexagonal prism
+        double L1 = getDistance(P( 1 ),P( 2 ));
+        double L2 = getDistance(P( 2 ),P( 3 ));
+        double L3 = getDistance(P( 3 ),P( 4 ));
+        double L4 = getDistance(P( 4 ),P( 5 ));
+        double L5 = getDistance(P( 5 ),P( 6 ));
+        double L6 = getDistance(P( 6 ),P( 1 ));
+
+        double L7 = getDistance(P( 7 ), P( 8 ));
+        double L8 = getDistance(P( 8 ), P( 9 ));
+        double L9 = getDistance(P( 9 ), P( 10 ));
+        double L10= getDistance(P( 10 ),P( 11 ));
+        double L11= getDistance(P( 11 ),P( 12 ));
+        double L12= getDistance(P( 12 ),P( 7 ));
+
+        double L13 = getDistance(P( 1 ),P( 7 ));
+        double L14 = getDistance(P( 2 ),P( 8 ));
+        double L15 = getDistance(P( 3 ),P( 9 ));
+        double L16 = getDistance(P( 4 ),P( 10 ));
+        double L17 = getDistance(P( 5 ),P( 11 ));
+        double L18 = getDistance(P( 6 ),P( 12 ));
+        aVal = Min(Min(Min(L1,L2),Min(L3,L4)),Min(L5,L6));
+        aVal = Min(aVal, Min(Min(Min(L7,L8),Min(L9,L10)),Min(L11,L12)));
+        aVal = Min(aVal, Min(Min(Min(L13,L14),Min(L15,L16)),Min(L17,L18)));
+      }
+      break;
+    case SMDSEntity_Polyhedra:
+    {
+    }
+    break;
+    default:
+      return 0;
     }
 
     if (aVal < 0 ) {
@@ -1743,14 +1795,16 @@ Length2D::Value::Value(double theLength,long thePntId1, long thePntId2):
   }
 }
 
-bool Length2D::Value::operator<(const Length2D::Value& x) const{
+bool Length2D::Value::operator<(const Length2D::Value& x) const
+{
   if(myPntId[0] < x.myPntId[0]) return true;
   if(myPntId[0] == x.myPntId[0])
     if(myPntId[1] < x.myPntId[1]) return true;
   return false;
 }
 
-void Length2D::GetValues(TValues& theValues){
+void Length2D::GetValues(TValues& theValues)
+{
   TValues aValues;
   SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
   for(; anIter->more(); ){
@@ -1947,14 +2001,16 @@ MultiConnection2D::Value::Value(long thePntId1, long thePntId2)
   }
 }
 
-bool MultiConnection2D::Value::operator<(const MultiConnection2D::Value& x) const{
+bool MultiConnection2D::Value::operator<(const MultiConnection2D::Value& x) const
+{
   if(myPntId[0] < x.myPntId[0]) return true;
   if(myPntId[0] == x.myPntId[0])
     if(myPntId[1] < x.myPntId[1]) return true;
   return false;
 }
 
-void MultiConnection2D::GetValues(MValues& theValues){
+void MultiConnection2D::GetValues(MValues& theValues)
+{
   if ( !myMesh ) return;
   SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
   for(; anIter->more(); ){
@@ -2374,26 +2430,15 @@ bool FreeEdges::IsSatisfy( long theId )
   if ( aFace == 0 || aFace->GetType() != SMDSAbs_Face || aFace->NbNodes() < 3 )
     return false;
 
-  SMDS_ElemIteratorPtr anIter;
-  if ( aFace->IsQuadratic() ) {
-    anIter = dynamic_cast<const SMDS_VtkFace*>
-      (aFace)->interlacedNodesElemIterator();
-  }
-  else {
-    anIter = aFace->nodesIterator();
-  }
+  SMDS_NodeIteratorPtr anIter = aFace->interlacedNodesIterator();
   if ( !anIter )
     return false;
 
   int i = 0, nbNodes = aFace->NbNodes();
   std::vector <const SMDS_MeshNode*> aNodes( nbNodes+1 );
   while( anIter->more() )
-  {
-    const SMDS_MeshNode* aNode = (SMDS_MeshNode*)anIter->next();
-    if ( aNode == 0 )
+    if ( ! ( aNodes[ i++ ] = anIter->next() ))
       return false;
-    aNodes[ i++ ] = aNode;
-  }
   aNodes[ nbNodes ] = aNodes[ 0 ];
 
   for ( i = 0; i < nbNodes; i++ )
@@ -2526,7 +2571,7 @@ bool FreeFaces::IsSatisfy( long theId )
 
   int nbNode = aFace->NbNodes();
 
-  // collect volumes check that number of volumss with count equal nbNode not less than 2
+  // collect volumes to check that number of volumes with count equal nbNode not less than 2
   typedef map< SMDS_MeshElement*, int > TMapOfVolume; // map of volume counters
   typedef map< SMDS_MeshElement*, int >::iterator TItrMapOfVolume; // iterator
   TMapOfVolume mapOfVol;
@@ -2606,7 +2651,7 @@ GroupColor::GroupColor()
 
 bool GroupColor::IsSatisfy( long theId )
 {
-  return (myIDs.find( theId ) != myIDs.end());
+  return myIDs.count( theId );
 }
 
 void GroupColor::SetType( SMDSAbs_ElementType theType )
@@ -2624,16 +2669,15 @@ static bool isEqual( const Quantity_Color& theColor1,
 {
   // tolerance to compare colors
   const double tol = 5*1e-3;
-  return ( fabs( theColor1.Red() - theColor2.Red() ) < tol &&
+  return ( fabs( theColor1.Red()   - theColor2.Red() )   < tol &&
            fabs( theColor1.Green() - theColor2.Green() ) < tol &&
-           fabs( theColor1.Blue() - theColor2.Blue() ) < tol );
+           fabs( theColor1.Blue()  - theColor2.Blue() )  < tol );
 }
 
-
 void GroupColor::SetMesh( const SMDS_Mesh* theMesh )
 {
   myIDs.clear();
-  
+
   const SMESHDS_Mesh* aMesh = dynamic_cast<const SMESHDS_Mesh*>(theMesh);
   if ( !aMesh )
     return;
@@ -2641,20 +2685,24 @@ void GroupColor::SetMesh( const SMDS_Mesh* theMesh )
   int nbGrp = aMesh->GetNbGroups();
   if ( !nbGrp )
     return;
-  
+
   // iterates on groups and find necessary elements ids
   const std::set<SMESHDS_GroupBase*>& aGroups = aMesh->GetGroups();
   set<SMESHDS_GroupBase*>::const_iterator GrIt = aGroups.begin();
-  for (; GrIt != aGroups.end(); GrIt++) {
+  for (; GrIt != aGroups.end(); GrIt++)
+  {
     SMESHDS_GroupBase* aGrp = (*GrIt);
     if ( !aGrp )
       continue;
     // check type and color of group
-    if ( !isEqual( myColor, aGrp->GetColor() ) )
-      continue;
-    if ( myType != SMDSAbs_All && myType != (SMDSAbs_ElementType)aGrp->GetType() )
+    if ( !isEqual( myColor, aGrp->GetColor() ))
       continue;
 
+    // IPAL52867 (prevent infinite recursion via GroupOnFilter)
+    if ( SMESHDS_GroupOnFilter * gof = dynamic_cast< SMESHDS_GroupOnFilter* >( aGrp ))
+      if ( gof->GetPredicate().get() == this )
+        continue;
+
     SMDSAbs_ElementType aGrpElType = (SMDSAbs_ElementType)aGrp->GetType();
     if ( myType == aGrpElType || (myType == SMDSAbs_All && aGrpElType != SMDSAbs_Node) ) {
       // add elements IDS into control
@@ -4634,20 +4682,20 @@ bool LyingOnGeom::Contains( const SMESHDS_Mesh*     theMeshDS,
   return false;
 }
 
-TSequenceOfXYZ::TSequenceOfXYZ()
+TSequenceOfXYZ::TSequenceOfXYZ(): myElem(0)
 {}
 
-TSequenceOfXYZ::TSequenceOfXYZ(size_type n) : myArray(n)
+TSequenceOfXYZ::TSequenceOfXYZ(size_type n) : myArray(n), myElem(0)
 {}
 
-TSequenceOfXYZ::TSequenceOfXYZ(size_type n, const gp_XYZ& t) : myArray(n,t)
+TSequenceOfXYZ::TSequenceOfXYZ(size_type n, const gp_XYZ& t) : myArray(n,t), myElem(0)
 {}
 
-TSequenceOfXYZ::TSequenceOfXYZ(const TSequenceOfXYZ& theSequenceOfXYZ) : myArray(theSequenceOfXYZ.myArray)
+TSequenceOfXYZ::TSequenceOfXYZ(const TSequenceOfXYZ& theSequenceOfXYZ) : myArray(theSequenceOfXYZ.myArray), myElem(theSequenceOfXYZ.myElem)
 {}
 
 template <class InputIterator>
-TSequenceOfXYZ::TSequenceOfXYZ(InputIterator theBegin, InputIterator theEnd): myArray(theBegin,theEnd)
+TSequenceOfXYZ::TSequenceOfXYZ(InputIterator theBegin, InputIterator theEnd): myArray(theBegin,theEnd), myElem(0)
 {}
 
 TSequenceOfXYZ::~TSequenceOfXYZ()
@@ -4656,6 +4704,7 @@ TSequenceOfXYZ::~TSequenceOfXYZ()
 TSequenceOfXYZ& TSequenceOfXYZ::operator=(const TSequenceOfXYZ& theSequenceOfXYZ)
 {
   myArray = theSequenceOfXYZ.myArray;
+  myElem  = theSequenceOfXYZ.myElem;
   return *this;
 }
 
@@ -4689,6 +4738,11 @@ TSequenceOfXYZ::size_type TSequenceOfXYZ::size() const
   return myArray.size();
 }
 
+SMDSAbs_EntityType TSequenceOfXYZ::getElementEntity() const
+{
+  return myElem ? myElem->GetEntityType() : SMDSEntity_Last;
+}
+
 TMeshModifTracer::TMeshModifTracer():
   myMeshModifTime(0), myMesh(0)
 {
index 41448b1f68710b2e6ed36aaf6bd35633cf88b706..8a2ff7e245becdcf4147fa98c3ce0dc4c98cb65f 100644 (file)
@@ -67,7 +67,7 @@ namespace SMESH{
     public:
       TSequenceOfXYZ();
 
-      TSequenceOfXYZ(size_type n);
+      explicit TSequenceOfXYZ(size_type n);
 
       TSequenceOfXYZ(size_type n, const gp_XYZ& t);
 
@@ -92,8 +92,16 @@ namespace SMESH{
 
       size_type size() const;
 
+
+      void setElement(const SMDS_MeshElement* e) { myElem = e; }
+
+      const SMDS_MeshElement* getElement() const { return myElem; }
+
+      SMDSAbs_EntityType getElementEntity() const;
+
     private:
-      std::vector<gp_XYZ> myArray;
+      std::vector<gp_XYZ>     myArray;
+      const SMDS_MeshElement* myElem;
     };
 
     /*!
index a0834759c97ae129d2fd738a2e230ca46446b710..f83fe915e283cb75693c039c6f63f3717a4f8488 100644 (file)
@@ -147,6 +147,7 @@ namespace
       }
       {
         cgTypes[SMDSEntity_Polygon]         = CGNS_ENUMV( NGON_n );
+        cgTypes[SMDSEntity_Quad_Polygon]    = CGNS_ENUMV( NGON_n );
         cgTypes[SMDSEntity_Polyhedra]       = CGNS_ENUMV( NFACE_n );
         cgTypes[SMDSEntity_Hexagonal_Prism] = CGNS_ENUMV( NFACE_n );
       }
@@ -370,6 +371,21 @@ Driver_Mesh::Status DriverCGNS_Write::Perform()
       }
       while ( elem && elem->GetEntityType() == elemType );
 
+    else if ( elemType == SMDSEntity_Quad_Polygon ) // QUADRATIC POLYGONS
+      do // write as linear NGON_n
+      {
+        elemData.push_back( elem->NbNodes() );
+        interlace = & SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Quad_Polygon,
+                                                          elem->NbNodes() )[0];
+        for ( int i = 0, nb = elem->NbNodes(); i < nb; ++i )
+          elemData.push_back( cgnsID( elem->GetNode( interlace[i] ), n2cgID ));
+        if ( elem->GetID() != cgID )
+          elem2cgID.insert( elem2cgID.end(), make_pair( elem, cgID ));
+        ++cgID;
+        elem = elemIt->more() ? elemIt->next() : 0;
+      }
+      while ( elem && elem->GetEntityType() == elemType );
+
     else if ( elemType == SMDSEntity_Polyhedra ||
               elemType == SMDSEntity_Hexagonal_Prism) // POLYHEDRA
     {
index 5205292604e60d996bc3809a989d509896c5c582..63de896b38e3d67a147e1ab3d47ab46679d0a4e1 100644 (file)
@@ -38,7 +38,6 @@ Driver_Mesh::Status DriverDAT_W_SMDS_Mesh::Perform()
   Status aResult = DRS_OK;
 
   int nbNodes, nbCells;
-  //int i;
 
   char *file2Read = (char *)myFile.c_str();
   FILE* aFileId = fopen(file2Read, "w+");
@@ -55,7 +54,7 @@ Driver_Mesh::Status DriverDAT_W_SMDS_Mesh::Perform()
   nbNodes = myMesh->NbNodes();
 
   /* Combien de mailles, faces ou aretes ? */
-  int /*nb_of_nodes,*/ nb_of_edges, nb_of_faces, nb_of_volumes;
+  int nb_of_edges, nb_of_faces, nb_of_volumes;
   nb_of_edges = myMesh->NbEdges();
   nb_of_faces = myMesh->NbFaces();
   nb_of_volumes = myMesh->NbVolumes();
@@ -64,7 +63,7 @@ Driver_Mesh::Status DriverDAT_W_SMDS_Mesh::Perform()
   SCRUTE(nb_of_faces);
   SCRUTE(nb_of_volumes);
 
-  fprintf(stdout, "%d %d\n", nbNodes, nbCells);
+  //fprintf(stdout, "%d %d\n", nbNodes, nbCells);
   fprintf(aFileId, "%d %d\n", nbNodes, nbCells);
 
   /****************************************************************************
@@ -74,7 +73,7 @@ Driver_Mesh::Status DriverDAT_W_SMDS_Mesh::Perform()
   SMDS_NodeIteratorPtr itNodes=myMesh->nodesIterator();
   while(itNodes->more()){               
     const SMDS_MeshNode * node = itNodes->next();
-    fprintf(aFileId, "%d %e %e %e\n", node->GetID(), node->X(), node->Y(), node->Z());
+    fprintf(aFileId, "%d %.14e %.14e %.14e\n", node->GetID(), node->X(), node->Y(), node->Z());
   }
         
   /****************************************************************************
index 61b6fec1c7e5c9b56ca7f1fa25960acc14fdda25..ba851616c2851908b1dc7c075d991668fad55a39 100644 (file)
 //  Module : SMESH
 
 #include "DriverMED_R_SMESHDS_Mesh.h"
-#include "SMESHDS_Mesh.hxx"
-#include "utilities.h"
 
 #include "DriverMED_Family.h"
-
 #include "SMESHDS_Group.hxx"
+#include "SMESHDS_Mesh.hxx"
+#include "SMESH_Comment.hxx"
 
-#include "MED_Factory.hxx"
 #include "MED_CoordUtils.hxx"
+#include "MED_Factory.hxx"
 #include "MED_Utilities.hxx"
 
 #include <NCollection_Map.hxx>
 
-#include <stdlib.h>
+#include "utilities.h"
+
+//#include <stdlib.h>
 
 #ifdef _DEBUG_
 static int MYDEBUG = 1;
@@ -62,579 +63,836 @@ namespace DriverMED
                        const TID2FamilyMap&  myFamilies);
   /*!
    * \brief Ensure aFamily has a required ID
-    * \param aFamily - a family to check
-    * \param anID - an ID aFamily should have
-    * \param myFamilies - a map of the family ID to the Family
-    * \retval bool  - true if successful
+   * \param aFamily - a family to check
+   * \param anID - an ID aFamily should have
+   * \param myFamilies - a map of the family ID to the Family
+   * \retval bool  - true if successful
    */
   bool checkFamilyID(DriverMED_FamilyPtr & aFamily,
                      int                   anID,
                      const TID2FamilyMap&  myFamilies);
-}
 
-void
-DriverMED_R_SMESHDS_Mesh
-::SetMeshName(string theMeshName)
-{
-  myMeshName = theMeshName;
+
+  const SMDS_MeshNode* FindNode(const SMDS_Mesh* theMesh, TInt theId)
+  {
+    const SMDS_MeshNode* aNode = theMesh->FindNode(theId);
+    if(aNode) return aNode;
+    EXCEPTION(runtime_error,"SMDS_Mesh::FindNode - cannot find a SMDS_MeshNode for ID = "<<theId);
+  }
+
 }
 
-static const SMDS_MeshNode* 
-FindNode(const SMDS_Mesh* theMesh, TInt theId)
+//================================================================================
+/*!
+ * \brief Stores a mesh name
+ */
+//================================================================================
+
+void DriverMED_R_SMESHDS_Mesh::SetMeshName(string theMeshName)
 {
-  const SMDS_MeshNode* aNode = theMesh->FindNode(theId);
-  if(aNode) return aNode;
-  EXCEPTION(runtime_error,"SMDS_Mesh::FindNode - cannot find a SMDS_MeshNode for ID = "<<theId);
+  myMeshName = theMeshName;
 }
 
+//================================================================================
+/*!
+ * \brief Reads a med file
+ */
+//================================================================================
 
-Driver_Mesh::Status 
-DriverMED_R_SMESHDS_Mesh
-::Perform()
+Driver_Mesh::Status DriverMED_R_SMESHDS_Mesh::Perform()
 {
+  using namespace DriverMED;
+
   Status aResult = DRS_FAIL;
   bool isDescConn = false; // Mantis issue 0020483
 #ifndef _DEXCEPT_
-  try{
+  try {
 #endif
     myFamilies.clear();
     if(MYDEBUG) MESSAGE("Perform - myFile : "<<myFile);
     PWrapper aMed = CrWrapper(myFile,true);
 
     aResult = DRS_EMPTY;
-    if(TInt aNbMeshes = aMed->GetNbMeshes()){
-      for(int iMesh = 0; iMesh < aNbMeshes; iMesh++){
-        // Reading the MED mesh
-        //---------------------
-        PMeshInfo aMeshInfo = aMed->GetPMeshInfo(iMesh+1);
+    TInt aNbMeshes = aMed->GetNbMeshes();
+    for (int iMesh = 0; iMesh < aNbMeshes; iMesh++)
+    {
+      // Reading the MED mesh
+      //---------------------
+      PMeshInfo aMeshInfo = aMed->GetPMeshInfo(iMesh+1);
 
-        string aMeshName;
-        if (myMeshId != -1) {
-          ostringstream aMeshNameStr;
-          aMeshNameStr<<myMeshId;
-          aMeshName = aMeshNameStr.str();
-        } else {
-          aMeshName = myMeshName;
-        }
-        if(MYDEBUG) MESSAGE("Perform - aMeshName : "<<aMeshName<<"; "<<aMeshInfo->GetName());
-        if(aMeshName != aMeshInfo->GetName()) continue;
-        aResult = DRS_OK;
-
-        // Reading MED families to the temporary structure
-        //------------------------------------------------
-        TErr anErr;
-        TInt aNbFams = aMed->GetNbFamilies(aMeshInfo);
-        if(MYDEBUG) MESSAGE("Read " << aNbFams << " families");
-        for (TInt iFam = 0; iFam < aNbFams; iFam++) {
-          PFamilyInfo aFamilyInfo = aMed->GetPFamilyInfo(aMeshInfo,iFam+1,&anErr);
-          if(anErr >= 0){
-            TInt aFamId = aFamilyInfo->GetId();
-            if(MYDEBUG) MESSAGE("Family " << aFamId << " :");
-            
-            DriverMED_FamilyPtr aFamily (new DriverMED_Family);
-            
-            TInt aNbGrp = aFamilyInfo->GetNbGroup();
-            if(MYDEBUG) MESSAGE("belong to " << aNbGrp << " groups");
-            bool isAttrOk = false;
-            if(aFamilyInfo->GetNbAttr() == aNbGrp)
-              isAttrOk = true;
-            for (TInt iGr = 0; iGr < aNbGrp; iGr++) {
-              string aGroupName = aFamilyInfo->GetGroupName(iGr);
-              if(isAttrOk){
-                TInt anAttrVal = aFamilyInfo->GetAttrVal(iGr);
-                aFamily->SetGroupAttributVal(anAttrVal);
-              }
-              
-              if(MYDEBUG) MESSAGE(aGroupName);
-              aFamily->AddGroupName(aGroupName);
-              
+      string aMeshName;
+      if (myMeshId != -1) aMeshName = SMESH_Comment( myMeshId );
+      else                aMeshName = myMeshName;
+
+      if(MYDEBUG) MESSAGE("Perform - aMeshName : "<<aMeshName<<"; "<<aMeshInfo->GetName());
+      if ( aMeshName != aMeshInfo->GetName() ) continue;
+      aResult = DRS_OK;
+
+      // Reading MED families to the temporary structure
+      //------------------------------------------------
+      TErr anErr;
+      TInt aNbFams = aMed->GetNbFamilies(aMeshInfo);
+      if(MYDEBUG) MESSAGE("Read " << aNbFams << " families");
+      for (TInt iFam = 0; iFam < aNbFams; iFam++)
+      {
+        PFamilyInfo aFamilyInfo = aMed->GetPFamilyInfo(aMeshInfo,iFam+1,&anErr);
+        if(anErr >= 0){
+          TInt aFamId = aFamilyInfo->GetId();
+          if(MYDEBUG) MESSAGE("Family " << aFamId << " :");
+
+          DriverMED_FamilyPtr aFamily (new DriverMED_Family);
+
+          TInt aNbGrp = aFamilyInfo->GetNbGroup();
+          if(MYDEBUG) MESSAGE("belong to " << aNbGrp << " groups");
+          bool isAttrOk = false;
+          if(aFamilyInfo->GetNbAttr() == aNbGrp)
+            isAttrOk = true;
+          for (TInt iGr = 0; iGr < aNbGrp; iGr++)
+          {
+            string aGroupName = aFamilyInfo->GetGroupName(iGr);
+            if ( isAttrOk ) {
+              TInt anAttrVal = aFamilyInfo->GetAttrVal(iGr);
+              aFamily->SetGroupAttributVal(anAttrVal);
             }
-            aFamily->SetId( aFamId );
-            myFamilies[aFamId] = aFamily;
+            if(MYDEBUG) MESSAGE(aGroupName);
+            aFamily->AddGroupName(aGroupName);
           }
+          aFamily->SetId( aFamId );
+          myFamilies[aFamId] = aFamily;
         }
+      }
 
-        if (aMeshInfo->GetType() == MED::eSTRUCTURE){
-          /*bool aRes = */DriverMED::buildMeshGrille(aMed,aMeshInfo,myMesh,myFamilies);
-          continue;
-        }
+      if (aMeshInfo->GetType() == MED::eSTRUCTURE)
+      {
+        /*bool aRes = */DriverMED::buildMeshGrille(aMed,aMeshInfo,myMesh,myFamilies);
+        continue;
+      }
 
-        // Reading MED nodes to the corresponding SMDS structure
-        //------------------------------------------------------
-        PNodeInfo aNodeInfo = aMed->GetPNodeInfo(aMeshInfo);
-        if (!aNodeInfo) {
-          aResult = DRS_FAIL;
-          continue;
+      // Reading MED nodes to the corresponding SMDS structure
+      //------------------------------------------------------
+      PNodeInfo aNodeInfo = aMed->GetPNodeInfo(aMeshInfo);
+      if (!aNodeInfo) {
+        aResult = DRS_FAIL;
+        continue;
+      }
+      aMeshInfo->myDim=aMeshInfo->mySpaceDim;// ignore meshdim in MEDFile because it can be false
+      PCoordHelper aCoordHelper = GetCoordHelper(aNodeInfo);
+
+      EBooleen anIsNodeNum = aNodeInfo->IsElemNum();
+      TInt aNbElems = aNodeInfo->GetNbElem();
+      if(MYDEBUG) MESSAGE("Perform - aNodeInfo->GetNbElem() = "<<aNbElems<<"; anIsNodeNum = "<<anIsNodeNum);
+      DriverMED_FamilyPtr aFamily;
+      for ( TInt iElem = 0; iElem < aNbElems; iElem++ )
+      {
+        TCCoordSlice aCoordSlice = aNodeInfo->GetCoordSlice(iElem);
+        double aCoords[3] = {0.0, 0.0, 0.0};
+        for(TInt iDim = 0; iDim < 3; iDim++)
+          aCoords[iDim] = aCoordHelper->GetCoord(aCoordSlice,iDim);
+        const SMDS_MeshNode* aNode;
+        if ( anIsNodeNum ) {
+          aNode = myMesh->AddNodeWithID
+            (aCoords[0],aCoords[1],aCoords[2],aNodeInfo->GetElemNum(iElem));
+        }
+        else {
+          aNode = myMesh->AddNodeWithID
+            (aCoords[0],aCoords[1],aCoords[2], iElem+1);
         }
-        aMeshInfo->myDim=aMeshInfo->mySpaceDim;// ignore meshdim in MEDFile because it can be false
-        PCoordHelper aCoordHelper = GetCoordHelper(aNodeInfo);
-
-        EBooleen anIsNodeNum = aNodeInfo->IsElemNum();
-        TInt aNbElems = aNodeInfo->GetNbElem();
-        if(MYDEBUG) MESSAGE("Perform - aNodeInfo->GetNbElem() = "<<aNbElems<<"; anIsNodeNum = "<<anIsNodeNum);
-        DriverMED_FamilyPtr aFamily;
-        for(TInt iElem = 0; iElem < aNbElems; iElem++){
-          TCCoordSlice aCoordSlice = aNodeInfo->GetCoordSlice(iElem);
-          double aCoords[3] = {0.0, 0.0, 0.0};
-          for(TInt iDim = 0; iDim < 3; iDim++)
-            aCoords[iDim] = aCoordHelper->GetCoord(aCoordSlice,iDim);
-          const SMDS_MeshNode* aNode;
-          if(anIsNodeNum) {
-            aNode = myMesh->AddNodeWithID
-              (aCoords[0],aCoords[1],aCoords[2],aNodeInfo->GetElemNum(iElem));
-          } else {
-            aNode = myMesh->AddNodeWithID
-              (aCoords[0],aCoords[1],aCoords[2], iElem+1);
-          }
 
-          // Save reference to this node from its family
-          TInt aFamNum = aNodeInfo->GetFamNum(iElem);
-          if ( DriverMED::checkFamilyID ( aFamily, aFamNum, myFamilies ))
-          {
-            aFamily->AddElement(aNode);
-            aFamily->SetType(SMDSAbs_Node);
-          }
+        // Save reference to this node from its family
+        TInt aFamNum = aNodeInfo->GetFamNum(iElem);
+        if ( DriverMED::checkFamilyID ( aFamily, aFamNum, myFamilies ))
+        {
+          aFamily->AddElement(aNode);
+          aFamily->SetType(SMDSAbs_Node);
         }
+      }
 
-        // Are there any MED cells in descending connectivity
-        // Mantis issue 0020483
-        //---------------------------------------------------
-        NCollection_Map<EEntiteMaillage> aDescendingEntitiesMap;
-        if (!isDescConn) {
-          MED::TEntityInfo aEntityInfoDesc = aMed->GetEntityInfo(aMeshInfo, eDESC);
-          MED::TEntityInfo::iterator anEntityIterDesc = aEntityInfoDesc.begin();
-          //for (; anEntityIterDesc != aEntityInfoDesc.end() && !isDescConn; anEntityIterDesc++) {
-          for (; anEntityIterDesc != aEntityInfoDesc.end(); anEntityIterDesc++) {
-            const EEntiteMaillage& anEntity = anEntityIterDesc->first;
-            aDescendingEntitiesMap.Add(anEntity);
-            //if (anEntity != eNOEUD) isDescConn = true;
-          }
+      // Are there any MED cells in descending connectivity
+      // Mantis issue 0020483
+      //---------------------------------------------------
+      NCollection_Map<EEntiteMaillage> aDescendingEntitiesMap;
+      if (!isDescConn) {
+        MED::TEntityInfo aEntityInfoDesc = aMed->GetEntityInfo(aMeshInfo, eDESC);
+        MED::TEntityInfo::iterator anEntityIterDesc = aEntityInfoDesc.begin();
+        //for (; anEntityIterDesc != aEntityInfoDesc.end() && !isDescConn; anEntityIterDesc++) {
+        for (; anEntityIterDesc != aEntityInfoDesc.end(); anEntityIterDesc++) {
+          const EEntiteMaillage& anEntity = anEntityIterDesc->first;
+          aDescendingEntitiesMap.Add(anEntity);
+          //if (anEntity != eNOEUD) isDescConn = true;
         }
+      }
 
-        // Reading pre information about all MED cells
-        //--------------------------------------------
-        typedef MED::TVector<int> TNodeIds;
-        bool takeNumbers = true;  // initially we trust the numbers from file
-        MED::TEntityInfo aEntityInfo = aMed->GetEntityInfo(aMeshInfo, eNOD);
-        MED::TEntityInfo::iterator anEntityIter = aEntityInfo.begin();
-        for (; anEntityIter != aEntityInfo.end(); anEntityIter++) {
-          const EEntiteMaillage& anEntity = anEntityIter->first;
-          aDescendingEntitiesMap.Remove(anEntity); // Mantis issue 0020483
-          if (anEntity == eNOEUD) continue;
-          // Reading MED cells to the corresponding SMDS structure
-          //------------------------------------------------------
-          const MED::TGeom2Size& aGeom2Size = anEntityIter->second;
-          MED::TGeom2Size::const_iterator aGeom2SizeIter = aGeom2Size.begin();
-          for(; aGeom2SizeIter != aGeom2Size.end(); aGeom2SizeIter++){
-            const EGeometrieElement& aGeom = aGeom2SizeIter->first;
-
-            if ( anEntity == eSTRUCT_ELEMENT ) // MED_BALL (issue 0021459)
-            {
-              PBallInfo aBallInfo = aMed->GetPBallInfo(aMeshInfo);
-              TInt      aNbBalls  = aBallInfo->GetNbElem();
+      // Reading pre information about all MED cells
+      //--------------------------------------------
+      typedef MED::TVector<int> TNodeIds;
+      bool takeNumbers = true;  // initially we trust the numbers from file
+      MED::TEntityInfo aEntityInfo = aMed->GetEntityInfo(aMeshInfo, eNOD);
+      MED::TEntityInfo::iterator anEntityIter = aEntityInfo.begin();
+
+      for (; anEntityIter != aEntityInfo.end(); anEntityIter++)
+      {
+        const EEntiteMaillage& anEntity = anEntityIter->first;
+        aDescendingEntitiesMap.Remove(anEntity); // Mantis issue 0020483
+        if (anEntity == eNOEUD) continue;
+
+        // Reading MED cells to the corresponding SMDS structure
+        //------------------------------------------------------
+        const MED::TGeom2Size& aGeom2Size = anEntityIter->second;
+        MED::TGeom2Size::const_iterator aGeom2SizeIter = aGeom2Size.begin();
+        for ( ; aGeom2SizeIter != aGeom2Size.end(); aGeom2SizeIter++)
+        {
+          const EGeometrieElement& aGeom = aGeom2SizeIter->first;
+
+          if ( anEntity == eSTRUCT_ELEMENT ) // MED_BALL (issue 0021459)
+          {
+            PBallInfo aBallInfo = aMed->GetPBallInfo(aMeshInfo);
+            TInt      aNbBalls  = aBallInfo->GetNbElem();
 
-              EBooleen anIsElemNum = takeNumbers ? aBallInfo->IsElemNum() : eFAUX;
-              if ( anIsElemNum && aBallInfo->myElemNum->empty() )
-                anIsElemNum = eFAUX;
+            EBooleen anIsElemNum = takeNumbers ? aBallInfo->IsElemNum() : eFAUX;
+            if ( anIsElemNum && aBallInfo->myElemNum->empty() )
+              anIsElemNum = eFAUX;
 
-              // get supporting nodes
-              TNodeIds aNodeIds;
+            // get supporting nodes
+            TNodeIds aNodeIds;
 #ifdef _EDF_NODE_IDS_
-              if(anIsNodeNum) {
-                aNodeIds.resize( aNbBalls );
-                for(TInt iBall = 0; iBall < aNbBalls && anIsNodeNum; iBall++)
-                {
-                  aNodeIds[iBall] = aNodeInfo->GetElemNum( (*aBallInfo->myConn)[ iBall ]-1 );
-                  anIsNodeNum = myMesh->FindNode( aNodeIds[iBall] ) ? eVRAI : eFAUX;
-                }
+            if(anIsNodeNum) {
+              aNodeIds.resize( aNbBalls );
+              for(TInt iBall = 0; iBall < aNbBalls && anIsNodeNum; iBall++)
+              {
+                aNodeIds[iBall] = aNodeInfo->GetElemNum( (*aBallInfo->myConn)[ iBall ]-1 );
+                anIsNodeNum = myMesh->FindNode( aNodeIds[iBall] ) ? eVRAI : eFAUX;
               }
+            }
 #endif
-              if ( !anIsNodeNum )
-                aNodeIds.swap( *(aBallInfo->myConn ));
-
-              // allocate array of diameters
-              vtkIdType maxID = myMesh->MaxElementID() + aNbBalls;
-              if ( anIsElemNum && !aBallInfo->myElemNum->empty() )
-                maxID = *std::max_element( aBallInfo->myElemNum->begin(),
-                                           aBallInfo->myElemNum->end() );
-              myMesh->getGrid()->AllocateDiameters( maxID ); // performance optimization
-
-              // create balls
-              SMDS_MeshElement* anElement;
-              DriverMED_FamilyPtr aFamily;
-              for ( TInt iBall = 0; iBall < aNbBalls; iBall++)
+            if ( !anIsNodeNum )
+              aNodeIds.swap( *(aBallInfo->myConn ));
+
+            // allocate array of diameters
+            vtkIdType maxID = myMesh->MaxElementID() + aNbBalls;
+            if ( anIsElemNum && !aBallInfo->myElemNum->empty() )
+              maxID = *std::max_element( aBallInfo->myElemNum->begin(),
+                                         aBallInfo->myElemNum->end() );
+            myMesh->getGrid()->AllocateDiameters( maxID ); // performance optimization
+
+            // create balls
+            SMDS_MeshElement* anElement;
+            DriverMED_FamilyPtr aFamily;
+            for ( TInt iBall = 0; iBall < aNbBalls; iBall++)
+            {
+              anElement = 0;
+              if ( anIsElemNum ) {
+                if (!(anElement = myMesh->AddBallWithID( aNodeIds[iBall],
+                                                         aBallInfo->myDiameters[iBall],
+                                                         aBallInfo->GetElemNum(iBall))))
+                  anIsElemNum = eFAUX;
+              }
+              if ( !anElement )
+                myMesh->AddBall( myMesh->FindNode( aNodeIds[iBall]),
+                                 aBallInfo->myDiameters[iBall] );
+
+              // Save reference to this element from its family
+              TInt aFamNum = aBallInfo->GetFamNum(iBall);
+              if ( DriverMED::checkFamilyID ( aFamily, aFamNum, myFamilies ))
               {
-                anElement = 0;
+                aFamily->AddElement(anElement);
+                aFamily->SetType( SMDSAbs_Ball );
+              }
+            }
+
+            if ( !anIsElemNum &&
+                 ( takeNumbers && aBallInfo->IsElemNum() && !aBallInfo->myElemNum->empty() ))
+              if ( aResult < DRS_WARN_RENUMBER )
+                aResult = DRS_WARN_RENUMBER;
+
+            continue;
+          } // MED_BALL
+
+          switch(aGeom) {
+          // case ePOINT1: ## PAL16410
+          //     break;
+          case ePOLYGONE:
+          case ePOLYGON2:
+          {
+            PPolygoneInfo aPolygoneInfo = aMed->GetPPolygoneInfo(aMeshInfo,anEntity,aGeom);
+            EBooleen anIsElemNum = takeNumbers ? aPolygoneInfo->IsElemNum() : eFAUX;
+
+            typedef SMDS_MeshFace* (SMESHDS_Mesh::* FAddPolyWithID)
+              (const std::vector<int> & nodes_ids, const int ID);
+            typedef SMDS_MeshFace* (SMESHDS_Mesh::* FAddPolygon)
+              (const std::vector<const SMDS_MeshNode*> & nodes);
+
+            FAddPolyWithID addPolyWithID = & SMESHDS_Mesh::AddPolygonalFaceWithID;
+            FAddPolygon       addPolygon = & SMESHDS_Mesh::AddPolygonalFace;
+            if ( aGeom == ePOLYGON2 ) {
+              addPolyWithID = & SMESHDS_Mesh::AddQuadPolygonalFaceWithID;
+              addPolygon    = & SMESHDS_Mesh::AddQuadPolygonalFace;
+            }
+            TNodeIds aNodeIds;
+            vector<const SMDS_MeshNode*> aNodes;
+            const TInt aNbElem = aPolygoneInfo->GetNbElem();
+            for ( TInt iElem = 0; iElem < aNbElem; iElem++ )
+            {
+              MED::TCConnSlice aConnSlice = aPolygoneInfo->GetConnSlice(iElem);
+              TInt aNbConn = aPolygoneInfo->GetNbConn(iElem);
+              aNodeIds.resize( aNbConn );
+#ifdef _EDF_NODE_IDS_
+              if(anIsNodeNum)
+                for(TInt iConn = 0; iConn < aNbConn; iConn++)
+                  aNodeIds[iConn] = aNodeInfo->GetElemNum(aConnSlice[iConn] - 1);
+              else
+                for(TInt iConn = 0; iConn < aNbConn; iConn++)
+                  aNodeIds[iConn] = aConnSlice[iConn];
+#else
+              for(TInt iConn = 0; iConn < aNbConn; iConn++)
+                aNodeIds[iConn] = aConnSlice[iConn];
+#endif
+              bool isRenum = false;
+              SMDS_MeshElement* anElement = NULL;
+              TInt aFamNum = aPolygoneInfo->GetFamNum(iElem);
+#ifndef _DEXCEPT_
+              try {
+#endif
                 if ( anIsElemNum ) {
-                  if (!(anElement = myMesh->AddBallWithID( aNodeIds[iBall],
-                                                           aBallInfo->myDiameters[iBall],
-                                                           aBallInfo->GetElemNum(iBall))))
-                    anIsElemNum = eFAUX;
+                  TInt anElemId = aPolygoneInfo->GetElemNum( iElem );
+                  anElement = (myMesh->*addPolyWithID)( aNodeIds, anElemId );
+                }
+                if ( !anElement ) {
+                  aNodes.resize( aNbConn );
+                  for ( TInt iConn = 0; iConn < aNbConn; iConn++ )
+                    aNodes[iConn] = FindNode( myMesh, aNodeIds[iConn] );
+                  anElement = (myMesh->*addPolygon)( aNodes );
+                  isRenum = anIsElemNum;
+                }
+#ifndef _DEXCEPT_
+              } catch(const std::exception& exc) {
+                aResult = DRS_FAIL;
+              } catch (...) {
+                aResult = DRS_FAIL;
+              }
+#endif
+              if ( !anElement ) {
+                aResult = DRS_WARN_SKIP_ELEM;
+              }
+              else {
+                if ( isRenum ) {
+                  anIsElemNum = eFAUX;
+                  takeNumbers = false;
+                  if(aResult < DRS_WARN_RENUMBER)
+                    aResult = DRS_WARN_RENUMBER;
                 }
-                if ( !anElement )
-                  myMesh->AddBall( myMesh->FindNode( aNodeIds[iBall]),
-                                   aBallInfo->myDiameters[iBall] );
-
-                // Save reference to this element from its family
-                TInt aFamNum = aBallInfo->GetFamNum(iBall);
                 if ( DriverMED::checkFamilyID ( aFamily, aFamNum, myFamilies ))
                 {
+                  // Save reference to this element from its family
                   aFamily->AddElement(anElement);
-                  aFamily->SetType( SMDSAbs_Ball );
+                  aFamily->SetType(anElement->GetType());
                 }
               }
+            }
+            break;
+          }
+          case ePOLYEDRE: {
+            PPolyedreInfo aPolyedreInfo = aMed->GetPPolyedreInfo(aMeshInfo,anEntity,aGeom);
+            EBooleen anIsElemNum = takeNumbers ? aPolyedreInfo->IsElemNum() : eFAUX;
 
-              if ( !anIsElemNum &&
-                   ( takeNumbers && aBallInfo->IsElemNum() && !aBallInfo->myElemNum->empty() ))
-                if ( aResult < DRS_WARN_RENUMBER )
-                  aResult = DRS_WARN_RENUMBER;
-
-              continue;
-            } // MED_BALL
-
-            switch(aGeom) {
-//          case ePOINT1: ## PAL16410
-//            break;
-            case ePOLYGONE: {
-              PPolygoneInfo aPolygoneInfo = aMed->GetPPolygoneInfo(aMeshInfo,anEntity,aGeom);
-              EBooleen anIsElemNum = takeNumbers ? aPolygoneInfo->IsElemNum() : eFAUX;
-              
-              TInt aNbElem = aPolygoneInfo->GetNbElem();
-              for(TInt iElem = 0; iElem < aNbElem; iElem++){
-                MED::TCConnSlice aConnSlice = aPolygoneInfo->GetConnSlice(iElem);
-                TInt aNbConn = aPolygoneInfo->GetNbConn(iElem);
-                TNodeIds aNodeIds(aNbConn);
+            TInt aNbElem = aPolyedreInfo->GetNbElem();
+            for(TInt iElem = 0; iElem < aNbElem; iElem++){
+              MED::TCConnSliceArr aConnSliceArr = aPolyedreInfo->GetConnSliceArr(iElem);
+              TInt aNbFaces = aConnSliceArr.size();
+              typedef MED::TVector<int> TQuantities;
+              TQuantities aQuantities(aNbFaces);
+              TInt aNbNodes = aPolyedreInfo->GetNbNodes(iElem);
+              TNodeIds aNodeIds(aNbNodes);
+              for(TInt iFace = 0, iNode = 0; iFace < aNbFaces; iFace++){
+                MED::TCConnSlice aConnSlice = aConnSliceArr[iFace];
+                TInt aNbConn = aConnSlice.size();
+                aQuantities[iFace] = aNbConn;
 #ifdef _EDF_NODE_IDS_
                 if(anIsNodeNum)
                   for(TInt iConn = 0; iConn < aNbConn; iConn++)
-                    aNodeIds[iConn] = aNodeInfo->GetElemNum(aConnSlice[iConn] - 1);
+                  {
+                    aNodeIds[iNode] = aNodeInfo->GetElemNum(aConnSlice[iConn] - 1);
+                    iNode++;
+                  }
                 else
                   for(TInt iConn = 0; iConn < aNbConn; iConn++)
-                    aNodeIds[iConn] = aConnSlice[iConn];
+                  {
+                    aNodeIds[iNode++] = aConnSlice[iConn];
+                  }
 #else
                 for(TInt iConn = 0; iConn < aNbConn; iConn++)
-                  aNodeIds[iConn] = aConnSlice[iConn];
-#endif
-                bool isRenum = false;
-                SMDS_MeshElement* anElement = NULL;
-                TInt aFamNum = aPolygoneInfo->GetFamNum(iElem);
+                {
+                  aNodeIds[iNode++] = aConnSlice[iConn];
+                }
+#endif          
+              }
 
+              bool isRenum = false;
+              SMDS_MeshElement* anElement = NULL;
+              TInt aFamNum = aPolyedreInfo->GetFamNum(iElem);
+                
 #ifndef _DEXCEPT_
-                try{
+              try{
 #endif
-                  if(anIsElemNum){
-                    TInt anElemId = aPolygoneInfo->GetElemNum(iElem);
-                    anElement = myMesh->AddPolygonalFaceWithID(aNodeIds,anElemId);
-                  }
-                  if(!anElement){
-                    vector<const SMDS_MeshNode*> aNodes(aNbConn);
-                    for(TInt iConn = 0; iConn < aNbConn; iConn++)
-                      aNodes[iConn] = FindNode(myMesh,aNodeIds[iConn]);
-                    anElement = myMesh->AddPolygonalFace(aNodes);
-                    isRenum = anIsElemNum;
-                  }
-#ifndef _DEXCEPT_
-                }catch(const std::exception& exc){
-                  aResult = DRS_FAIL;
-                }catch (...){
-                  aResult = DRS_FAIL;
+                if(anIsElemNum){
+                  TInt anElemId = aPolyedreInfo->GetElemNum(iElem);
+                  anElement = myMesh->AddPolyhedralVolumeWithID(aNodeIds,aQuantities,anElemId);
                 }
-#endif
                 if(!anElement){
-                  aResult = DRS_WARN_SKIP_ELEM;
-                }else{
-                  if(isRenum){
-                    anIsElemNum = eFAUX;
-                    takeNumbers = false;
-                    if(aResult < DRS_WARN_RENUMBER)
-                      aResult = DRS_WARN_RENUMBER;
-                  }
-                  if ( DriverMED::checkFamilyID ( aFamily, aFamNum, myFamilies ))
-                  {
-                    // Save reference to this element from its family
-                    aFamily->AddElement(anElement);
-                    aFamily->SetType(anElement->GetType());
-                  }
+                  vector<const SMDS_MeshNode*> aNodes(aNbNodes);
+                  for(TInt iConn = 0; iConn < aNbNodes; iConn++)
+                    aNodes[iConn] = FindNode(myMesh,aNodeIds[iConn]);
+                  anElement = myMesh->AddPolyhedralVolume(aNodes,aQuantities);
+                  isRenum = anIsElemNum;
                 }
+#ifndef _DEXCEPT_
+              }catch(const std::exception& exc){
+                aResult = DRS_FAIL;
+              }catch(...){
+                aResult = DRS_FAIL;
               }
-              break;
-            }
-            case ePOLYEDRE: {
-              PPolyedreInfo aPolyedreInfo = aMed->GetPPolyedreInfo(aMeshInfo,anEntity,aGeom);
-              EBooleen anIsElemNum = takeNumbers ? aPolyedreInfo->IsElemNum() : eFAUX;
-
-              TInt aNbElem = aPolyedreInfo->GetNbElem();
-              for(TInt iElem = 0; iElem < aNbElem; iElem++){
-                MED::TCConnSliceArr aConnSliceArr = aPolyedreInfo->GetConnSliceArr(iElem);
-                TInt aNbFaces = aConnSliceArr.size();
-                typedef MED::TVector<int> TQuantities;
-                TQuantities aQuantities(aNbFaces);
-                TInt aNbNodes = aPolyedreInfo->GetNbNodes(iElem);
-                TNodeIds aNodeIds(aNbNodes);
-                for(TInt iFace = 0, iNode = 0; iFace < aNbFaces; iFace++){
-                  MED::TCConnSlice aConnSlice = aConnSliceArr[iFace];
-                  TInt aNbConn = aConnSlice.size();
-                  aQuantities[iFace] = aNbConn;
-#ifdef _EDF_NODE_IDS_
-                  if(anIsNodeNum)
-                    for(TInt iConn = 0; iConn < aNbConn; iConn++)
-                      {
-                      aNodeIds[iNode] = aNodeInfo->GetElemNum(aConnSlice[iConn] - 1);
-                      iNode++;
-                      }
-                  else
-                    for(TInt iConn = 0; iConn < aNbConn; iConn++)
-                      {
-                      aNodeIds[iNode++] = aConnSlice[iConn];
-                      }
-#else
-                  for(TInt iConn = 0; iConn < aNbConn; iConn++)
-                    {
-                    aNodeIds[iNode++] = aConnSlice[iConn];
-                    }
 #endif          
+              if(!anElement){
+                aResult = DRS_WARN_SKIP_ELEM;
+              }else{
+                if(isRenum){
+                  anIsElemNum = eFAUX;
+                  takeNumbers = false;
+                  if (aResult < DRS_WARN_RENUMBER)
+                    aResult = DRS_WARN_RENUMBER;
                 }
-
-                bool isRenum = false;
-                SMDS_MeshElement* anElement = NULL;
-                TInt aFamNum = aPolyedreInfo->GetFamNum(iElem);
-                
-#ifndef _DEXCEPT_
-                try{
-#endif
-                  if(anIsElemNum){
-                    TInt anElemId = aPolyedreInfo->GetElemNum(iElem);
-                    anElement = myMesh->AddPolyhedralVolumeWithID(aNodeIds,aQuantities,anElemId);
-                  }
-                  if(!anElement){
-                    vector<const SMDS_MeshNode*> aNodes(aNbNodes);
-                    for(TInt iConn = 0; iConn < aNbNodes; iConn++)
-                      aNodes[iConn] = FindNode(myMesh,aNodeIds[iConn]);
-                    anElement = myMesh->AddPolyhedralVolume(aNodes,aQuantities);
-                    isRenum = anIsElemNum;
-                  }
-#ifndef _DEXCEPT_
-                }catch(const std::exception& exc){
-                  aResult = DRS_FAIL;
-                }catch(...){
-                  aResult = DRS_FAIL;
-                }
-#endif          
-                if(!anElement){
-                  aResult = DRS_WARN_SKIP_ELEM;
-                }else{
-                  if(isRenum){
-                    anIsElemNum = eFAUX;
-                    takeNumbers = false;
-                    if (aResult < DRS_WARN_RENUMBER)
-                      aResult = DRS_WARN_RENUMBER;
-                  }
-                  if ( DriverMED::checkFamilyID ( aFamily, aFamNum, myFamilies )) {
-                    // Save reference to this element from its family
-                    aFamily->AddElement(anElement);
-                    aFamily->SetType(anElement->GetType());
-                  }
+                if ( DriverMED::checkFamilyID ( aFamily, aFamNum, myFamilies )) {
+                  // Save reference to this element from its family
+                  aFamily->AddElement(anElement);
+                  aFamily->SetType(anElement->GetType());
                 }
               }
-              break;
             }
-            default: {
-              PCellInfo aCellInfo = aMed->GetPCellInfo(aMeshInfo,anEntity,aGeom);
-              EBooleen anIsElemNum = takeNumbers ? aCellInfo->IsElemNum() : eFAUX;
-              TInt aNbElems = aCellInfo->GetNbElem();
-              if(MYDEBUG) MESSAGE("Perform - anEntity = "<<anEntity<<"; anIsElemNum = "<<anIsElemNum);
-              if(MYDEBUG) MESSAGE("Perform - aGeom = "<<aGeom<<"; aNbElems = "<<aNbElems);
-
-              TInt aNbNodes = -1;
-              switch(aGeom){
-              case eSEG2:    aNbNodes = 2;  break;
-              case eSEG3:    aNbNodes = 3;  break;
-              case eTRIA3:   aNbNodes = 3;  break;
-              case eTRIA6:   aNbNodes = 6;  break;
-              case eTRIA7:   aNbNodes = 7;  break;
-              case eQUAD4:   aNbNodes = 4;  break;
-              case eQUAD8:   aNbNodes = 8;  break;
-              case eQUAD9:   aNbNodes = 9;  break;
-              case eTETRA4:  aNbNodes = 4;  break;
-              case eTETRA10: aNbNodes = 10; break;
-              case ePYRA5:   aNbNodes = 5;  break;
-              case ePYRA13:  aNbNodes = 13; break;
-              case ePENTA6:  aNbNodes = 6;  break;
-              case ePENTA15: aNbNodes = 15; break;
-              case eHEXA8:   aNbNodes = 8;  break;
-              case eHEXA20:  aNbNodes = 20; break;
-              case eHEXA27:  aNbNodes = 27; break;
-              case eOCTA12:  aNbNodes = 12; break;
-              case ePOINT1:  aNbNodes = 1;  break;
-              default:;
-              }
-              vector<TInt> aNodeIds(aNbNodes);
-              for(int iElem = 0; iElem < aNbElems; iElem++){
-                bool anIsValidConnect = false;
-                TCConnSlice aConnSlice = aCellInfo->GetConnSlice(iElem);
+            break;
+          }
+          default: {
+            PCellInfo aCellInfo = aMed->GetPCellInfo(aMeshInfo,anEntity,aGeom);
+            EBooleen anIsElemNum = takeNumbers ? aCellInfo->IsElemNum() : eFAUX;
+            TInt aNbElems = aCellInfo->GetNbElem();
+            if(MYDEBUG) MESSAGE("Perform - anEntity = "<<anEntity<<"; anIsElemNum = "<<anIsElemNum);
+            if(MYDEBUG) MESSAGE("Perform - aGeom = "<<aGeom<<"; aNbElems = "<<aNbElems);
+
+            TInt aNbNodes = -1;
+            switch(aGeom){
+            case eSEG2:    aNbNodes = 2;  break;
+            case eSEG3:    aNbNodes = 3;  break;
+            case eTRIA3:   aNbNodes = 3;  break;
+            case eTRIA6:   aNbNodes = 6;  break;
+            case eTRIA7:   aNbNodes = 7;  break;
+            case eQUAD4:   aNbNodes = 4;  break;
+            case eQUAD8:   aNbNodes = 8;  break;
+            case eQUAD9:   aNbNodes = 9;  break;
+            case eTETRA4:  aNbNodes = 4;  break;
+            case eTETRA10: aNbNodes = 10; break;
+            case ePYRA5:   aNbNodes = 5;  break;
+            case ePYRA13:  aNbNodes = 13; break;
+            case ePENTA6:  aNbNodes = 6;  break;
+            case ePENTA15: aNbNodes = 15; break;
+            case eHEXA8:   aNbNodes = 8;  break;
+            case eHEXA20:  aNbNodes = 20; break;
+            case eHEXA27:  aNbNodes = 27; break;
+            case eOCTA12:  aNbNodes = 12; break;
+            case ePOINT1:  aNbNodes = 1;  break;
+            default:;
+            }
+            vector<TInt> aNodeIds(aNbNodes);
+            for(int iElem = 0; iElem < aNbElems; iElem++){
+              bool anIsValidConnect = false;
+              TCConnSlice aConnSlice = aCellInfo->GetConnSlice(iElem);
 #ifndef _DEXCEPT_
-                try{
+              try{
 #endif
 #ifdef _EDF_NODE_IDS_
-                  if(anIsNodeNum)
-                    for(int iNode = 0; iNode < aNbNodes; iNode++)
-                      aNodeIds[iNode] = aNodeInfo->GetElemNum(aConnSlice[iNode] - 1);
-                  else
-                    for(int iNode = 0; iNode < aNbNodes; iNode++)
-                      aNodeIds[iNode] = aConnSlice[iNode];
-#else
+                if(anIsNodeNum)
+                  for(int iNode = 0; iNode < aNbNodes; iNode++)
+                    aNodeIds[iNode] = aNodeInfo->GetElemNum(aConnSlice[iNode] - 1);
+                else
                   for(int iNode = 0; iNode < aNbNodes; iNode++)
                     aNodeIds[iNode] = aConnSlice[iNode];
+#else
+                for(int iNode = 0; iNode < aNbNodes; iNode++)
+                  aNodeIds[iNode] = aConnSlice[iNode];
 #endif
-                  anIsValidConnect = true;
+                anIsValidConnect = true;
 #ifndef _DEXCEPT_
-                }catch(const std::exception& exc){
-                  INFOS("Following exception was caught:\n\t"<<exc.what());
-                  aResult = DRS_FAIL;
-                }catch(...){
-                  INFOS("Unknown exception was caught !!!");
-                  aResult = DRS_FAIL;
-                }
+              }catch(const std::exception& exc){
+                INFOS("Following exception was caught:\n\t"<<exc.what());
+                aResult = DRS_FAIL;
+              }catch(...){
+                INFOS("Unknown exception was caught !!!");
+                aResult = DRS_FAIL;
+              }
 #endif          
-                if(!anIsValidConnect)
-                  continue;
+              if(!anIsValidConnect)
+                continue;
 
-                bool isRenum = false;
-                const SMDS_MeshElement* anElement = NULL;
-                TInt aFamNum = aCellInfo->GetFamNum(iElem);
+              bool isRenum = false;
+              const SMDS_MeshElement* anElement = NULL;
+              TInt aFamNum = aCellInfo->GetFamNum(iElem);
 #ifndef _DEXCEPT_
-                try{
+              try{
 #endif
-                  //MESSAGE("Try to create element # " << iElem << " with id = "
-                  //        << aCellInfo->GetElemNum(iElem));
-                  switch(aGeom) {
-                  case ePOINT1:
-                    //anElement = FindNode(myMesh,aNodeIds[0]);
-                    if(anIsElemNum)
-                      anElement = myMesh->Add0DElementWithID
-                        (aNodeIds[0], aCellInfo->GetElemNum(iElem));
-                    if (!anElement) {
-                      anElement = myMesh->Add0DElement(FindNode(myMesh,aNodeIds[0]));
-                      isRenum = anIsElemNum;
-                    }
-                    break;
-                  case eSEG2:
-                    if(anIsElemNum)
-                      anElement = myMesh->AddEdgeWithID(aNodeIds[0],
-                                                        aNodeIds[1],
+                //MESSAGE("Try to create element # " << iElem << " with id = "
+                //        << aCellInfo->GetElemNum(iElem));
+                switch(aGeom) {
+                case ePOINT1:
+                  //anElement = FindNode(myMesh,aNodeIds[0]);
+                  if(anIsElemNum)
+                    anElement = myMesh->Add0DElementWithID
+                      (aNodeIds[0], aCellInfo->GetElemNum(iElem));
+                  if (!anElement) {
+                    anElement = myMesh->Add0DElement(FindNode(myMesh,aNodeIds[0]));
+                    isRenum = anIsElemNum;
+                  }
+                  break;
+                case eSEG2:
+                  if(anIsElemNum)
+                    anElement = myMesh->AddEdgeWithID(aNodeIds[0],
+                                                      aNodeIds[1],
+                                                      aCellInfo->GetElemNum(iElem));
+                  if (!anElement) {
+                    anElement = myMesh->AddEdge(FindNode(myMesh,aNodeIds[0]),
+                                                FindNode(myMesh,aNodeIds[1]));
+                    isRenum = anIsElemNum;
+                  }
+                  break;
+                case eSEG3:
+                  if(anIsElemNum)
+                    anElement = myMesh->AddEdgeWithID(aNodeIds[0],
+                                                      aNodeIds[1],
+                                                      aNodeIds[2],
+                                                      aCellInfo->GetElemNum(iElem));
+                  if (!anElement) {
+                    anElement = myMesh->AddEdge(FindNode(myMesh,aNodeIds[0]),
+                                                FindNode(myMesh,aNodeIds[1]),
+                                                FindNode(myMesh,aNodeIds[2]));
+                    isRenum = anIsElemNum;
+                  }
+                  break;
+                case eTRIA3:
+                  aNbNodes = 3;
+                  if(anIsElemNum)
+                    anElement = myMesh->AddFaceWithID(aNodeIds[0],
+                                                      aNodeIds[1],
+                                                      aNodeIds[2],
+                                                      aCellInfo->GetElemNum(iElem));
+                  if (!anElement) {
+                    anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
+                                                FindNode(myMesh,aNodeIds[1]),
+                                                FindNode(myMesh,aNodeIds[2]));
+                    isRenum = anIsElemNum;
+                  }
+                  break;
+                case eTRIA6:
+                  aNbNodes = 6;
+                  if(anIsElemNum)
+                    anElement = myMesh->AddFaceWithID(aNodeIds[0], aNodeIds[1],
+                                                      aNodeIds[2], aNodeIds[3],
+                                                      aNodeIds[4], aNodeIds[5],
+                                                      aCellInfo->GetElemNum(iElem));
+                  if (!anElement) {
+                    anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
+                                                FindNode(myMesh,aNodeIds[1]),
+                                                FindNode(myMesh,aNodeIds[2]),
+                                                FindNode(myMesh,aNodeIds[3]),
+                                                FindNode(myMesh,aNodeIds[4]),
+                                                FindNode(myMesh,aNodeIds[5]));
+                    isRenum = anIsElemNum;
+                  }
+                  break;
+                case eTRIA7:
+                  aNbNodes = 7;
+                  if(anIsElemNum)
+                    anElement = myMesh->AddFaceWithID(aNodeIds[0], aNodeIds[1],
+                                                      aNodeIds[2], aNodeIds[3],
+                                                      aNodeIds[4], aNodeIds[5], aNodeIds[6],
+                                                      aCellInfo->GetElemNum(iElem));
+                  if (!anElement) {
+                    anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
+                                                FindNode(myMesh,aNodeIds[1]),
+                                                FindNode(myMesh,aNodeIds[2]),
+                                                FindNode(myMesh,aNodeIds[3]),
+                                                FindNode(myMesh,aNodeIds[4]),
+                                                FindNode(myMesh,aNodeIds[5]),
+                                                FindNode(myMesh,aNodeIds[6]));
+                    isRenum = anIsElemNum;
+                  }
+                  break;
+                case eQUAD4:
+                  aNbNodes = 4;
+                  if(anIsElemNum)
+                    anElement = myMesh->AddFaceWithID(aNodeIds[0], aNodeIds[1],
+                                                      aNodeIds[2], aNodeIds[3],
+                                                      aCellInfo->GetElemNum(iElem));
+                  if (!anElement) {
+                    anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
+                                                FindNode(myMesh,aNodeIds[1]),
+                                                FindNode(myMesh,aNodeIds[2]),
+                                                FindNode(myMesh,aNodeIds[3]));
+                    isRenum = anIsElemNum;
+                  }
+                  break;
+                case eQUAD8:
+                  aNbNodes = 8;
+                  if(anIsElemNum)
+                    anElement = myMesh->AddFaceWithID(aNodeIds[0], aNodeIds[1],
+                                                      aNodeIds[2], aNodeIds[3],
+                                                      aNodeIds[4], aNodeIds[5],
+                                                      aNodeIds[6], aNodeIds[7],
+                                                      aCellInfo->GetElemNum(iElem));
+                  if (!anElement) {
+                    anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
+                                                FindNode(myMesh,aNodeIds[1]),
+                                                FindNode(myMesh,aNodeIds[2]),
+                                                FindNode(myMesh,aNodeIds[3]),
+                                                FindNode(myMesh,aNodeIds[4]),
+                                                FindNode(myMesh,aNodeIds[5]),
+                                                FindNode(myMesh,aNodeIds[6]),
+                                                FindNode(myMesh,aNodeIds[7]));
+                    isRenum = anIsElemNum;
+                  }
+                  break;
+                case eQUAD9:
+                  aNbNodes = 9;
+                  if(anIsElemNum)
+                    anElement = myMesh->AddFaceWithID(aNodeIds[0], aNodeIds[1],
+                                                      aNodeIds[2], aNodeIds[3],
+                                                      aNodeIds[4], aNodeIds[5],
+                                                      aNodeIds[6], aNodeIds[7], aNodeIds[8],
+                                                      aCellInfo->GetElemNum(iElem));
+                  if (!anElement) {
+                    anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
+                                                FindNode(myMesh,aNodeIds[1]),
+                                                FindNode(myMesh,aNodeIds[2]),
+                                                FindNode(myMesh,aNodeIds[3]),
+                                                FindNode(myMesh,aNodeIds[4]),
+                                                FindNode(myMesh,aNodeIds[5]),
+                                                FindNode(myMesh,aNodeIds[6]),
+                                                FindNode(myMesh,aNodeIds[7]),
+                                                FindNode(myMesh,aNodeIds[8]));
+                    isRenum = anIsElemNum;
+                  }
+                  break;
+                case eTETRA4:
+                  aNbNodes = 4;
+                  if(anIsElemNum)
+                    anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
+                                                        aNodeIds[2], aNodeIds[3],
                                                         aCellInfo->GetElemNum(iElem));
-                    if (!anElement) {
-                      anElement = myMesh->AddEdge(FindNode(myMesh,aNodeIds[0]),
-                                                  FindNode(myMesh,aNodeIds[1]));
-                      isRenum = anIsElemNum;
-                    }
-                    break;
-                  case eSEG3:
-                    if(anIsElemNum)
-                      anElement = myMesh->AddEdgeWithID(aNodeIds[0],
-                                                        aNodeIds[1],
-                                                        aNodeIds[2],
+                  if (!anElement) {
+                    anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
+                                                  FindNode(myMesh,aNodeIds[1]),
+                                                  FindNode(myMesh,aNodeIds[2]),
+                                                  FindNode(myMesh,aNodeIds[3]));
+                    isRenum = anIsElemNum;
+                  }
+                  break;
+                case eTETRA10:
+                  aNbNodes = 10;
+                  if(anIsElemNum)
+                    anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
+                                                        aNodeIds[2], aNodeIds[3],
+                                                        aNodeIds[4], aNodeIds[5],
+                                                        aNodeIds[6], aNodeIds[7],
+                                                        aNodeIds[8], aNodeIds[9],
                                                         aCellInfo->GetElemNum(iElem));
-                    if (!anElement) {
-                      anElement = myMesh->AddEdge(FindNode(myMesh,aNodeIds[0]),
+                  if (!anElement) {
+                    anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
                                                   FindNode(myMesh,aNodeIds[1]),
-                                                  FindNode(myMesh,aNodeIds[2]));
-                      isRenum = anIsElemNum;
-                    }
-                    break;
-                  case eTRIA3:
-                    aNbNodes = 3;
-                    if(anIsElemNum)
-                      anElement = myMesh->AddFaceWithID(aNodeIds[0],
-                                                        aNodeIds[1],
-                                                        aNodeIds[2],
+                                                  FindNode(myMesh,aNodeIds[2]),
+                                                  FindNode(myMesh,aNodeIds[3]),
+                                                  FindNode(myMesh,aNodeIds[4]),
+                                                  FindNode(myMesh,aNodeIds[5]),
+                                                  FindNode(myMesh,aNodeIds[6]),
+                                                  FindNode(myMesh,aNodeIds[7]),
+                                                  FindNode(myMesh,aNodeIds[8]),
+                                                  FindNode(myMesh,aNodeIds[9]));
+                    isRenum = anIsElemNum;
+                  }
+                  break;
+                case ePYRA5:
+                  aNbNodes = 5;
+                  if(anIsElemNum)
+                    anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
+                                                        aNodeIds[2], aNodeIds[3],
+                                                        aNodeIds[4],
                                                         aCellInfo->GetElemNum(iElem));
-                    if (!anElement) {
-                      anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
+                  if (!anElement) {
+                    anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
                                                   FindNode(myMesh,aNodeIds[1]),
-                                                  FindNode(myMesh,aNodeIds[2]));
-                      isRenum = anIsElemNum;
-                    }
-                    break;
-                  case eTRIA6:
-                    aNbNodes = 6;
-                    if(anIsElemNum)
-                      anElement = myMesh->AddFaceWithID(aNodeIds[0], aNodeIds[1],
+                                                  FindNode(myMesh,aNodeIds[2]),
+                                                  FindNode(myMesh,aNodeIds[3]),
+                                                  FindNode(myMesh,aNodeIds[4]));
+                    isRenum = anIsElemNum;
+                  }
+                  break;
+                case ePYRA13:
+                  aNbNodes = 13;
+                  if(anIsElemNum)
+                    anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
                                                         aNodeIds[2], aNodeIds[3],
                                                         aNodeIds[4], aNodeIds[5],
+                                                        aNodeIds[6], aNodeIds[7],
+                                                        aNodeIds[8], aNodeIds[9],
+                                                        aNodeIds[10], aNodeIds[11],
+                                                        aNodeIds[12],
+                                                        aCellInfo->GetElemNum(iElem));
+                  if (!anElement) {
+                    anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
+                                                  FindNode(myMesh,aNodeIds[1]),
+                                                  FindNode(myMesh,aNodeIds[2]),
+                                                  FindNode(myMesh,aNodeIds[3]),
+                                                  FindNode(myMesh,aNodeIds[4]),
+                                                  FindNode(myMesh,aNodeIds[5]),
+                                                  FindNode(myMesh,aNodeIds[6]),
+                                                  FindNode(myMesh,aNodeIds[7]),
+                                                  FindNode(myMesh,aNodeIds[8]),
+                                                  FindNode(myMesh,aNodeIds[9]),
+                                                  FindNode(myMesh,aNodeIds[10]),
+                                                  FindNode(myMesh,aNodeIds[11]),
+                                                  FindNode(myMesh,aNodeIds[12]));
+                    isRenum = anIsElemNum;
+                  }
+                  break;
+                case ePENTA6:
+                  aNbNodes = 6;
+                  if(anIsElemNum)
+                    anElement = myMesh->AddVolumeWithID(aNodeIds[0],
+                                                        aNodeIds[1],
+                                                        aNodeIds[2],
+                                                        aNodeIds[3],
+                                                        aNodeIds[4],
+                                                        aNodeIds[5],
                                                         aCellInfo->GetElemNum(iElem));
-                    if (!anElement) {
-                      anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
+                  if (!anElement) {
+                    anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
                                                   FindNode(myMesh,aNodeIds[1]),
                                                   FindNode(myMesh,aNodeIds[2]),
                                                   FindNode(myMesh,aNodeIds[3]),
                                                   FindNode(myMesh,aNodeIds[4]),
                                                   FindNode(myMesh,aNodeIds[5]));
-                      isRenum = anIsElemNum;
-                    }
-                    break;
-                  case eTRIA7:
-                    aNbNodes = 7;
-                    if(anIsElemNum)
-                      anElement = myMesh->AddFaceWithID(aNodeIds[0], aNodeIds[1],
+                    isRenum = anIsElemNum;
+                  }
+                  break;
+                case ePENTA15:
+                  aNbNodes = 15;
+                  if(anIsElemNum)
+                    anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
                                                         aNodeIds[2], aNodeIds[3],
-                                                        aNodeIds[4], aNodeIds[5], aNodeIds[6],
+                                                        aNodeIds[4], aNodeIds[5],
+                                                        aNodeIds[6], aNodeIds[7],
+                                                        aNodeIds[8], aNodeIds[9],
+                                                        aNodeIds[10], aNodeIds[11],
+                                                        aNodeIds[12], aNodeIds[13],
+                                                        aNodeIds[14],
                                                         aCellInfo->GetElemNum(iElem));
-                    if (!anElement) {
-                      anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
+                  if (!anElement) {
+                    anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
                                                   FindNode(myMesh,aNodeIds[1]),
                                                   FindNode(myMesh,aNodeIds[2]),
                                                   FindNode(myMesh,aNodeIds[3]),
                                                   FindNode(myMesh,aNodeIds[4]),
                                                   FindNode(myMesh,aNodeIds[5]),
-                                                  FindNode(myMesh,aNodeIds[6]));
-                      isRenum = anIsElemNum;
-                    }
-                    break;
-                  case eQUAD4:
-                    aNbNodes = 4;
-                    if(anIsElemNum)
-                      anElement = myMesh->AddFaceWithID(aNodeIds[0], aNodeIds[1],
-                                                        aNodeIds[2], aNodeIds[3],
+                                                  FindNode(myMesh,aNodeIds[6]),
+                                                  FindNode(myMesh,aNodeIds[7]),
+                                                  FindNode(myMesh,aNodeIds[8]),
+                                                  FindNode(myMesh,aNodeIds[9]),
+                                                  FindNode(myMesh,aNodeIds[10]),
+                                                  FindNode(myMesh,aNodeIds[11]),
+                                                  FindNode(myMesh,aNodeIds[12]),
+                                                  FindNode(myMesh,aNodeIds[13]),
+                                                  FindNode(myMesh,aNodeIds[14]));
+                    isRenum = anIsElemNum;
+                  }
+                  break;
+                case eHEXA8:
+                  aNbNodes = 8;
+                  if(anIsElemNum)
+                    anElement = myMesh->AddVolumeWithID(aNodeIds[0],
+                                                        aNodeIds[1],
+                                                        aNodeIds[2],
+                                                        aNodeIds[3],
+                                                        aNodeIds[4],
+                                                        aNodeIds[5],
+                                                        aNodeIds[6],
+                                                        aNodeIds[7],
                                                         aCellInfo->GetElemNum(iElem));
-                    if (!anElement) {
-                      anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
+                  if (!anElement) {
+                    anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
                                                   FindNode(myMesh,aNodeIds[1]),
                                                   FindNode(myMesh,aNodeIds[2]),
-                                                  FindNode(myMesh,aNodeIds[3]));
-                      isRenum = anIsElemNum;
-                    }
-                    break;
-                  case eQUAD8:
-                    aNbNodes = 8;
-                    if(anIsElemNum)
-                      anElement = myMesh->AddFaceWithID(aNodeIds[0], aNodeIds[1],
+                                                  FindNode(myMesh,aNodeIds[3]),
+                                                  FindNode(myMesh,aNodeIds[4]),
+                                                  FindNode(myMesh,aNodeIds[5]),
+                                                  FindNode(myMesh,aNodeIds[6]),
+                                                  FindNode(myMesh,aNodeIds[7]));
+                    isRenum = anIsElemNum;
+                  }
+                  break;
+
+                case eHEXA20:
+                  aNbNodes = 20;
+                  if(anIsElemNum)
+                    anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
                                                         aNodeIds[2], aNodeIds[3],
                                                         aNodeIds[4], aNodeIds[5],
                                                         aNodeIds[6], aNodeIds[7],
+                                                        aNodeIds[8], aNodeIds[9],
+                                                        aNodeIds[10], aNodeIds[11],
+                                                        aNodeIds[12], aNodeIds[13],
+                                                        aNodeIds[14], aNodeIds[15],
+                                                        aNodeIds[16], aNodeIds[17],
+                                                        aNodeIds[18], aNodeIds[19],
                                                         aCellInfo->GetElemNum(iElem));
-                    if (!anElement) {
-                      anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
+                  if (!anElement) {
+                    anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
                                                   FindNode(myMesh,aNodeIds[1]),
                                                   FindNode(myMesh,aNodeIds[2]),
                                                   FindNode(myMesh,aNodeIds[3]),
                                                   FindNode(myMesh,aNodeIds[4]),
                                                   FindNode(myMesh,aNodeIds[5]),
                                                   FindNode(myMesh,aNodeIds[6]),
-                                                  FindNode(myMesh,aNodeIds[7]));
-                      isRenum = anIsElemNum;
-                    }
-                    break;
-                  case eQUAD9:
-                    aNbNodes = 9;
-                    if(anIsElemNum)
-                      anElement = myMesh->AddFaceWithID(aNodeIds[0], aNodeIds[1],
+                                                  FindNode(myMesh,aNodeIds[7]),
+                                                  FindNode(myMesh,aNodeIds[8]),
+                                                  FindNode(myMesh,aNodeIds[9]),
+                                                  FindNode(myMesh,aNodeIds[10]),
+                                                  FindNode(myMesh,aNodeIds[11]),
+                                                  FindNode(myMesh,aNodeIds[12]),
+                                                  FindNode(myMesh,aNodeIds[13]),
+                                                  FindNode(myMesh,aNodeIds[14]),
+                                                  FindNode(myMesh,aNodeIds[15]),
+                                                  FindNode(myMesh,aNodeIds[16]),
+                                                  FindNode(myMesh,aNodeIds[17]),
+                                                  FindNode(myMesh,aNodeIds[18]),
+                                                  FindNode(myMesh,aNodeIds[19]));
+                    isRenum = anIsElemNum;
+                  }
+                  break;
+
+                case eHEXA27:
+                  aNbNodes = 27;
+                  if(anIsElemNum)
+                    anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
                                                         aNodeIds[2], aNodeIds[3],
                                                         aNodeIds[4], aNodeIds[5],
-                                                        aNodeIds[6], aNodeIds[7], aNodeIds[8],
+                                                        aNodeIds[6], aNodeIds[7],
+                                                        aNodeIds[8], aNodeIds[9],
+                                                        aNodeIds[10], aNodeIds[11],
+                                                        aNodeIds[12], aNodeIds[13],
+                                                        aNodeIds[14], aNodeIds[15],
+                                                        aNodeIds[16], aNodeIds[17],
+                                                        aNodeIds[18], aNodeIds[19],
+                                                        aNodeIds[20], aNodeIds[21],
+                                                        aNodeIds[22], aNodeIds[23],
+                                                        aNodeIds[24], aNodeIds[25],
+                                                        aNodeIds[26],
                                                         aCellInfo->GetElemNum(iElem));
-                    if (!anElement) {
-                      anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
+                  if (!anElement) {
+                    anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
                                                   FindNode(myMesh,aNodeIds[1]),
                                                   FindNode(myMesh,aNodeIds[2]),
                                                   FindNode(myMesh,aNodeIds[3]),
@@ -642,322 +900,98 @@ DriverMED_R_SMESHDS_Mesh
                                                   FindNode(myMesh,aNodeIds[5]),
                                                   FindNode(myMesh,aNodeIds[6]),
                                                   FindNode(myMesh,aNodeIds[7]),
-                                                  FindNode(myMesh,aNodeIds[8]));
-                      isRenum = anIsElemNum;
-                    }
-                    break;
-                  case eTETRA4:
-                    aNbNodes = 4;
-                    if(anIsElemNum)
-                      anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
-                                                          aNodeIds[2], aNodeIds[3],
-                                                          aCellInfo->GetElemNum(iElem));
-                    if (!anElement) {
-                      anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
-                                                    FindNode(myMesh,aNodeIds[1]),
-                                                    FindNode(myMesh,aNodeIds[2]),
-                                                    FindNode(myMesh,aNodeIds[3]));
-                      isRenum = anIsElemNum;
-                    }
-                    break;
-                  case eTETRA10:
-                    aNbNodes = 10;
-                    if(anIsElemNum)
-                      anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
-                                                          aNodeIds[2], aNodeIds[3],
-                                                          aNodeIds[4], aNodeIds[5],
-                                                          aNodeIds[6], aNodeIds[7],
-                                                          aNodeIds[8], aNodeIds[9],
-                                                          aCellInfo->GetElemNum(iElem));
-                    if (!anElement) {
-                      anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
-                                                    FindNode(myMesh,aNodeIds[1]),
-                                                    FindNode(myMesh,aNodeIds[2]),
-                                                    FindNode(myMesh,aNodeIds[3]),
-                                                    FindNode(myMesh,aNodeIds[4]),
-                                                    FindNode(myMesh,aNodeIds[5]),
-                                                    FindNode(myMesh,aNodeIds[6]),
-                                                    FindNode(myMesh,aNodeIds[7]),
-                                                    FindNode(myMesh,aNodeIds[8]),
-                                                    FindNode(myMesh,aNodeIds[9]));
-                      isRenum = anIsElemNum;
-                    }
-                    break;
-                  case ePYRA5:
-                    aNbNodes = 5;
-                    if(anIsElemNum)
-                      anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
-                                                          aNodeIds[2], aNodeIds[3],
-                                                          aNodeIds[4],
-                                                          aCellInfo->GetElemNum(iElem));
-                    if (!anElement) {
-                      anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
-                                                    FindNode(myMesh,aNodeIds[1]),
-                                                    FindNode(myMesh,aNodeIds[2]),
-                                                    FindNode(myMesh,aNodeIds[3]),
-                                                    FindNode(myMesh,aNodeIds[4]));
-                      isRenum = anIsElemNum;
-                    }
-                    break;
-                  case ePYRA13:
-                    aNbNodes = 13;
-                    if(anIsElemNum)
-                      anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
-                                                          aNodeIds[2], aNodeIds[3],
-                                                          aNodeIds[4], aNodeIds[5],
-                                                          aNodeIds[6], aNodeIds[7],
-                                                          aNodeIds[8], aNodeIds[9],
-                                                          aNodeIds[10], aNodeIds[11],
-                                                          aNodeIds[12],
-                                                          aCellInfo->GetElemNum(iElem));
-                    if (!anElement) {
-                      anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
-                                                    FindNode(myMesh,aNodeIds[1]),
-                                                    FindNode(myMesh,aNodeIds[2]),
-                                                    FindNode(myMesh,aNodeIds[3]),
-                                                    FindNode(myMesh,aNodeIds[4]),
-                                                    FindNode(myMesh,aNodeIds[5]),
-                                                    FindNode(myMesh,aNodeIds[6]),
-                                                    FindNode(myMesh,aNodeIds[7]),
-                                                    FindNode(myMesh,aNodeIds[8]),
-                                                    FindNode(myMesh,aNodeIds[9]),
-                                                    FindNode(myMesh,aNodeIds[10]),
-                                                    FindNode(myMesh,aNodeIds[11]),
-                                                    FindNode(myMesh,aNodeIds[12]));
-                      isRenum = anIsElemNum;
-                    }
-                    break;
-                  case ePENTA6:
-                    aNbNodes = 6;
-                    if(anIsElemNum)
-                      anElement = myMesh->AddVolumeWithID(aNodeIds[0],
-                                                          aNodeIds[1],
-                                                          aNodeIds[2],
-                                                          aNodeIds[3],
-                                                          aNodeIds[4],
-                                                          aNodeIds[5],
-                                                          aCellInfo->GetElemNum(iElem));
-                    if (!anElement) {
-                      anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
-                                                    FindNode(myMesh,aNodeIds[1]),
-                                                    FindNode(myMesh,aNodeIds[2]),
-                                                    FindNode(myMesh,aNodeIds[3]),
-                                                    FindNode(myMesh,aNodeIds[4]),
-                                                    FindNode(myMesh,aNodeIds[5]));
-                      isRenum = anIsElemNum;
-                    }
-                    break;
-                  case ePENTA15:
-                    aNbNodes = 15;
-                    if(anIsElemNum)
-                      anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
-                                                          aNodeIds[2], aNodeIds[3],
-                                                          aNodeIds[4], aNodeIds[5],
-                                                          aNodeIds[6], aNodeIds[7],
-                                                          aNodeIds[8], aNodeIds[9],
-                                                          aNodeIds[10], aNodeIds[11],
-                                                          aNodeIds[12], aNodeIds[13],
-                                                          aNodeIds[14],
-                                                          aCellInfo->GetElemNum(iElem));
-                    if (!anElement) {
-                      anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
-                                                    FindNode(myMesh,aNodeIds[1]),
-                                                    FindNode(myMesh,aNodeIds[2]),
-                                                    FindNode(myMesh,aNodeIds[3]),
+                                                  FindNode(myMesh,aNodeIds[8]),
+                                                  FindNode(myMesh,aNodeIds[9]),
+                                                  FindNode(myMesh,aNodeIds[10]),
+                                                  FindNode(myMesh,aNodeIds[11]),
+                                                  FindNode(myMesh,aNodeIds[12]),
+                                                  FindNode(myMesh,aNodeIds[13]),
+                                                  FindNode(myMesh,aNodeIds[14]),
+                                                  FindNode(myMesh,aNodeIds[15]),
+                                                  FindNode(myMesh,aNodeIds[16]),
+                                                  FindNode(myMesh,aNodeIds[17]),
+                                                  FindNode(myMesh,aNodeIds[18]),
+                                                  FindNode(myMesh,aNodeIds[19]),
+                                                  FindNode(myMesh,aNodeIds[20]),
+                                                  FindNode(myMesh,aNodeIds[21]),
+                                                  FindNode(myMesh,aNodeIds[22]),
+                                                  FindNode(myMesh,aNodeIds[23]),
+                                                  FindNode(myMesh,aNodeIds[24]),
+                                                  FindNode(myMesh,aNodeIds[25]),
+                                                  FindNode(myMesh,aNodeIds[26]));
+                    isRenum = anIsElemNum;
+                  }
+                  break;
+
+                case eOCTA12:
+                  aNbNodes = 12;
+                  if(anIsElemNum)
+                    anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
+                                                        aNodeIds[2], aNodeIds[3],
+                                                        aNodeIds[4], aNodeIds[5],
+                                                        aNodeIds[6], aNodeIds[7],
+                                                        aNodeIds[8], aNodeIds[9],
+                                                        aNodeIds[10], aNodeIds[11],
+                                                        aCellInfo->GetElemNum(iElem));
+                  if (!anElement) {
+                    anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
+                                                  FindNode(myMesh,aNodeIds[1]),
+                                                  FindNode(myMesh,aNodeIds[2]),
+                                                  FindNode(myMesh,aNodeIds[3]),
                                                   FindNode(myMesh,aNodeIds[4]),
-                                                    FindNode(myMesh,aNodeIds[5]),
-                                                    FindNode(myMesh,aNodeIds[6]),
-                                                    FindNode(myMesh,aNodeIds[7]),
-                                                    FindNode(myMesh,aNodeIds[8]),
-                                                    FindNode(myMesh,aNodeIds[9]),
-                                                    FindNode(myMesh,aNodeIds[10]),
-                                                    FindNode(myMesh,aNodeIds[11]),
-                                                    FindNode(myMesh,aNodeIds[12]),
-                                                    FindNode(myMesh,aNodeIds[13]),
-                                                    FindNode(myMesh,aNodeIds[14]));
-                      isRenum = anIsElemNum;
-                    }
-                    break;
-                  case eHEXA8:
-                    aNbNodes = 8;
-                    if(anIsElemNum)
-                      anElement = myMesh->AddVolumeWithID(aNodeIds[0],
-                                                          aNodeIds[1],
-                                                          aNodeIds[2],
-                                                          aNodeIds[3],
-                                                          aNodeIds[4],
-                                                          aNodeIds[5],
-                                                          aNodeIds[6],
-                                                          aNodeIds[7],
-                                                          aCellInfo->GetElemNum(iElem));
-                    if (!anElement) {
-                      anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
-                                                    FindNode(myMesh,aNodeIds[1]),
-                                                    FindNode(myMesh,aNodeIds[2]),
-                                                    FindNode(myMesh,aNodeIds[3]),
-                                                    FindNode(myMesh,aNodeIds[4]),
-                                                    FindNode(myMesh,aNodeIds[5]),
-                                                    FindNode(myMesh,aNodeIds[6]),
-                                                    FindNode(myMesh,aNodeIds[7]));
-                      isRenum = anIsElemNum;
-                    }
-                    break;
-
-                  case eHEXA20:
-                    aNbNodes = 20;
-                    if(anIsElemNum)
-                      anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
-                                                          aNodeIds[2], aNodeIds[3],
-                                                          aNodeIds[4], aNodeIds[5],
-                                                          aNodeIds[6], aNodeIds[7],
-                                                          aNodeIds[8], aNodeIds[9],
-                                                          aNodeIds[10], aNodeIds[11],
-                                                          aNodeIds[12], aNodeIds[13],
-                                                          aNodeIds[14], aNodeIds[15],
-                                                          aNodeIds[16], aNodeIds[17],
-                                                          aNodeIds[18], aNodeIds[19],
-                                                          aCellInfo->GetElemNum(iElem));
-                    if (!anElement) {
-                      anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
-                                                    FindNode(myMesh,aNodeIds[1]),
-                                                    FindNode(myMesh,aNodeIds[2]),
-                                                    FindNode(myMesh,aNodeIds[3]),
-                                                    FindNode(myMesh,aNodeIds[4]),
-                                                    FindNode(myMesh,aNodeIds[5]),
-                                                    FindNode(myMesh,aNodeIds[6]),
-                                                    FindNode(myMesh,aNodeIds[7]),
-                                                    FindNode(myMesh,aNodeIds[8]),
-                                                    FindNode(myMesh,aNodeIds[9]),
-                                                    FindNode(myMesh,aNodeIds[10]),
-                                                    FindNode(myMesh,aNodeIds[11]),
-                                                    FindNode(myMesh,aNodeIds[12]),
-                                                    FindNode(myMesh,aNodeIds[13]),
-                                                    FindNode(myMesh,aNodeIds[14]),
-                                                    FindNode(myMesh,aNodeIds[15]),
-                                                    FindNode(myMesh,aNodeIds[16]),
-                                                    FindNode(myMesh,aNodeIds[17]),
-                                                    FindNode(myMesh,aNodeIds[18]),
-                                                    FindNode(myMesh,aNodeIds[19]));
-                      isRenum = anIsElemNum;
-                    }
-                    break;
-
-                  case eHEXA27:
-                    aNbNodes = 27;
-                    if(anIsElemNum)
-                      anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
-                                                          aNodeIds[2], aNodeIds[3],
-                                                          aNodeIds[4], aNodeIds[5],
-                                                          aNodeIds[6], aNodeIds[7],
-                                                          aNodeIds[8], aNodeIds[9],
-                                                          aNodeIds[10], aNodeIds[11],
-                                                          aNodeIds[12], aNodeIds[13],
-                                                          aNodeIds[14], aNodeIds[15],
-                                                          aNodeIds[16], aNodeIds[17],
-                                                          aNodeIds[18], aNodeIds[19],
-                                                          aNodeIds[20], aNodeIds[21],
-                                                          aNodeIds[22], aNodeIds[23],
-                                                          aNodeIds[24], aNodeIds[25],
-                                                          aNodeIds[26],
-                                                          aCellInfo->GetElemNum(iElem));
-                    if (!anElement) {
-                      anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
-                                                    FindNode(myMesh,aNodeIds[1]),
-                                                    FindNode(myMesh,aNodeIds[2]),
-                                                    FindNode(myMesh,aNodeIds[3]),
-                                                    FindNode(myMesh,aNodeIds[4]),
-                                                    FindNode(myMesh,aNodeIds[5]),
-                                                    FindNode(myMesh,aNodeIds[6]),
-                                                    FindNode(myMesh,aNodeIds[7]),
-                                                    FindNode(myMesh,aNodeIds[8]),
-                                                    FindNode(myMesh,aNodeIds[9]),
-                                                    FindNode(myMesh,aNodeIds[10]),
-                                                    FindNode(myMesh,aNodeIds[11]),
-                                                    FindNode(myMesh,aNodeIds[12]),
-                                                    FindNode(myMesh,aNodeIds[13]),
-                                                    FindNode(myMesh,aNodeIds[14]),
-                                                    FindNode(myMesh,aNodeIds[15]),
-                                                    FindNode(myMesh,aNodeIds[16]),
-                                                    FindNode(myMesh,aNodeIds[17]),
-                                                    FindNode(myMesh,aNodeIds[18]),
-                                                    FindNode(myMesh,aNodeIds[19]),
-                                                    FindNode(myMesh,aNodeIds[20]),
-                                                    FindNode(myMesh,aNodeIds[21]),
-                                                    FindNode(myMesh,aNodeIds[22]),
-                                                    FindNode(myMesh,aNodeIds[23]),
-                                                    FindNode(myMesh,aNodeIds[24]),
-                                                    FindNode(myMesh,aNodeIds[25]),
-                                                    FindNode(myMesh,aNodeIds[26]));
-                      isRenum = anIsElemNum;
-                    }
-                    break;
-
-                  case eOCTA12:
-                    aNbNodes = 12;
-                    if(anIsElemNum)
-                      anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
-                                                          aNodeIds[2], aNodeIds[3],
-                                                          aNodeIds[4], aNodeIds[5],
-                                                          aNodeIds[6], aNodeIds[7],
-                                                          aNodeIds[8], aNodeIds[9],
-                                                          aNodeIds[10], aNodeIds[11],
-                                                          aCellInfo->GetElemNum(iElem));
-                    if (!anElement) {
-                      anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
-                                                    FindNode(myMesh,aNodeIds[1]),
-                                                    FindNode(myMesh,aNodeIds[2]),
-                                                    FindNode(myMesh,aNodeIds[3]),
-                                                    FindNode(myMesh,aNodeIds[4]),
-                                                    FindNode(myMesh,aNodeIds[5]),
-                                                    FindNode(myMesh,aNodeIds[6]),
-                                                    FindNode(myMesh,aNodeIds[7]),
-                                                    FindNode(myMesh,aNodeIds[8]),
-                                                    FindNode(myMesh,aNodeIds[9]),
-                                                    FindNode(myMesh,aNodeIds[10]),
-                                                    FindNode(myMesh,aNodeIds[11]));
-                      isRenum = anIsElemNum;
-                    }
-                    break;
-
-                  } // switch(aGeom)
+                                                  FindNode(myMesh,aNodeIds[5]),
+                                                  FindNode(myMesh,aNodeIds[6]),
+                                                  FindNode(myMesh,aNodeIds[7]),
+                                                  FindNode(myMesh,aNodeIds[8]),
+                                                  FindNode(myMesh,aNodeIds[9]),
+                                                  FindNode(myMesh,aNodeIds[10]),
+                                                  FindNode(myMesh,aNodeIds[11]));
+                    isRenum = anIsElemNum;
+                  }
+                  break;
+
+                } // switch(aGeom)
 
 #ifndef _DEXCEPT_
-                }catch(const std::exception& exc){
-                  INFOS("The following exception was caught:\n\t"<<exc.what());
-                  aResult = DRS_FAIL;
-                }catch(...){
-                  INFOS("Unknown exception was caught !!!");
-                  aResult = DRS_FAIL;
-                }
+              }catch(const std::exception& exc){
+                INFOS("The following exception was caught:\n\t"<<exc.what());
+                aResult = DRS_FAIL;
+              }catch(...){
+                INFOS("Unknown exception was caught !!!");
+                aResult = DRS_FAIL;
+              }
 #endif          
-                if (!anElement) {
-                  aResult = DRS_WARN_SKIP_ELEM;
+              if (!anElement) {
+                aResult = DRS_WARN_SKIP_ELEM;
+              }
+              else {
+                if (isRenum) {
+                  anIsElemNum = eFAUX;
+                  takeNumbers = false;
+                  if (aResult < DRS_WARN_RENUMBER)
+                    aResult = DRS_WARN_RENUMBER;
                 }
-                else {
-                  if (isRenum) {
-                    anIsElemNum = eFAUX;
-                    takeNumbers = false;
-                    if (aResult < DRS_WARN_RENUMBER)
-                      aResult = DRS_WARN_RENUMBER;
-                  }
-                  if ( DriverMED::checkFamilyID ( aFamily, aFamNum, myFamilies )) {
-                    // Save reference to this element from its family
-                    myFamilies[aFamNum]->AddElement(anElement);
-                    myFamilies[aFamNum]->SetType(anElement->GetType());
-                  }
+                if ( DriverMED::checkFamilyID ( aFamily, aFamNum, myFamilies )) {
+                  // Save reference to this element from its family
+                  myFamilies[aFamNum]->AddElement(anElement);
+                  myFamilies[aFamNum]->SetType(anElement->GetType());
                 }
               }
-            }}
-          }
+            }
+          }}
         }
-        if (aDescendingEntitiesMap.Extent()) isDescConn = true; // Mantis issue 0020483
-      } // for(int iMesh = 0; iMesh < aNbMeshes; iMesh++)
-    } // if aNbMeshes
+      }
+      if (aDescendingEntitiesMap.Extent()) isDescConn = true; // Mantis issue 0020483
+    } // for(int iMesh = 0; iMesh < aNbMeshes; iMesh++)
 #ifndef _DEXCEPT_
-  }catch(const std::exception& exc){
+  }
+  catch(const std::exception& exc)
+  {
     INFOS("The following exception was caught:\n\t"<<exc.what());
     aResult = DRS_FAIL;
-  }catch(...){
+  }
+  catch(...)
+  {
     INFOS("Unknown exception was caught !!!");
     aResult = DRS_FAIL;
   }
index 86a41eb41adec9164b582bc37344f16e2aafb089..b4ab8dbe401b4a8caf9d5649d61359ea9f110ea3 100644 (file)
@@ -56,7 +56,8 @@ DriverMED_W_SMESHDS_Mesh::DriverMED_W_SMESHDS_Mesh():
   myDoGroupOfVolumes (false),
   myDoGroupOf0DElems(false),
   myDoGroupOfBalls(false),
-  myAutoDimension(true)
+  myAutoDimension(true),
+  myAddODOnVertices(false)
 {}
 
 void DriverMED_W_SMESHDS_Mesh::SetFile(const std::string& theFileName, 
@@ -605,12 +606,21 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform()
     if ( polyTypesSupported ) {
       aTElemTypeDatas.push_back( TElemTypeData(anEntity,
                                                ePOLYGONE,
-                                               nbElemInfo.NbPolygons(),
+                                               nbElemInfo.NbPolygons( ORDER_LINEAR ),
                                                SMDSAbs_Face));
       // we need one more loop on poly elements to count nb of their nodes
       aTElemTypeDatas.push_back( TElemTypeData(anEntity,
                                                ePOLYGONE,
-                                               nbElemInfo.NbPolygons(),
+                                               nbElemInfo.NbPolygons( ORDER_LINEAR ),
+                                               SMDSAbs_Face));
+      aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                               ePOLYGON2,
+                                               nbElemInfo.NbPolygons( ORDER_QUADRATIC ),
+                                               SMDSAbs_Face));
+      // we need one more loop on QUAD poly elements to count nb of their nodes
+      aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                               ePOLYGON2,
+                                               nbElemInfo.NbPolygons( ORDER_QUADRATIC ),
                                                SMDSAbs_Face));
     }
 #ifdef _ELEMENTS_BY_DIM_
@@ -706,9 +716,14 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform()
 
       // Treat POLYGONs
       // ---------------
-      if ( aElemTypeData->_geomType == ePOLYGONE )
+      if ( aElemTypeData->_geomType == ePOLYGONE ||
+           aElemTypeData->_geomType == ePOLYGON2 )
       {
-        elemIterator = myMesh->elementGeomIterator( SMDSGeom_POLYGON );
+        if ( aElemTypeData->_geomType == ePOLYGONE )
+          elemIterator = myMesh->elementEntityIterator( SMDSEntity_Polygon );
+        else
+          elemIterator = myMesh->elementEntityIterator( SMDSEntity_Quad_Polygon );
+
         if ( nbPolygonNodes == 0 ) {
           // Count nb of nodes
           while ( elemIterator->more() ) {
@@ -758,9 +773,10 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform()
               break;
           }
           myMed->SetPolygoneInfo(aPolygoneInfo);
-        }
 
-      } 
+          nbPolygonNodes = 0; // to treat next polygon type
+        }
+      }
 
       // Treat POLYEDREs
       // ----------------
index 78a068e578da1ef12631b8b4d319c05fe16a5131..6f9d02a3070e2d4970d99e8f4452b00ac22843b5 100644 (file)
 #include "SMDS_Mesh.hxx"
 #include "SMDS_MeshElement.hxx"
 #include "SMDS_MeshNode.hxx"
+#include "SMDS_PolygonalFaceOfNodes.hxx"
 #include "SMDS_SetIterator.hxx"
 #include "SMDS_VolumeTool.hxx"
 #include "SMESH_File.hxx"
 #include "SMESH_TypeDefs.hxx"
 
-//#include "utilities.h"
+#include <Standard_ErrorHandler.hxx>
+#include <Standard_Failure.hxx>
+#include <gp_Ax2.hxx>
 
 #include <limits>
 
@@ -74,6 +77,7 @@ Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::Perform()
 
   return aResult;
 }
+
 //================================================================================
 /*!
  * \brief Destructor deletes temporary faces
@@ -82,8 +86,8 @@ Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::Perform()
 
 DriverSTL_W_SMDS_Mesh::~DriverSTL_W_SMDS_Mesh()
 {
-  for ( unsigned i = 0; i < myVolumeTrias.size(); ++i )
-    delete myVolumeTrias[i];
+  for ( unsigned i = 0; i < myVolumeFacets.size(); ++i )
+    delete myVolumeFacets[i];
 }
 
 //================================================================================
@@ -94,6 +98,8 @@ DriverSTL_W_SMDS_Mesh::~DriverSTL_W_SMDS_Mesh()
 
 void DriverSTL_W_SMDS_Mesh::findVolumeTriangles()
 {
+  myNbVolumeTrias = 0;
+
   SMDS_VolumeTool theVolume;
   SMDS_VolumeIteratorPtr vIt = myMesh->volumesIterator();
   std::vector< const SMDS_MeshNode*> nodes;
@@ -106,19 +112,20 @@ void DriverSTL_W_SMDS_Mesh::findVolumeTriangles()
         const SMDS_MeshNode** n = theVolume.GetFaceNodes(iF);
         int                 nbN = theVolume.NbFaceNodes(iF);
         nodes.assign( n, n+nbN );
-        if ( !myMesh->FindElement( nodes, SMDSAbs_Face, /*Nomedium=*/false))
+        if ( !myMesh->FindElement( nodes, SMDSAbs_Face, /*noMedium=*/false))
         {
-          if ( nbN == 9 && !theVolume.IsPoly() ) // facet is SMDSEntity_BiQuad_Quadrangle
+          if (( nbN == 9 || nbN == 7 ) &&
+              ( !theVolume.IsPoly() )) // facet is bi-quaratic
           {
             int nbTria = nbN - 1;
             for ( int iT = 0; iT < nbTria; ++iT )
-              myVolumeTrias.push_back( new SMDS_FaceOfNodes( n[8], n[0+iT], n[1+iT] ));
+              myVolumeFacets.push_back( new SMDS_FaceOfNodes( n[8], n[0+iT], n[1+iT] ));
+            myNbVolumeTrias += nbTria;
           }
           else
           {
-            int nbTria = nbN - 2;
-            for ( int iT = 0; iT < nbTria; ++iT )
-              myVolumeTrias.push_back( new SMDS_FaceOfNodes( n[0], n[1+iT], n[2+iT] ));
+            myVolumeFacets.push_back( new SMDS_PolygonalFaceOfNodes( nodes ));
+            myNbVolumeTrias += nbN - 2;
           }
         }
       }
@@ -134,8 +141,8 @@ void DriverSTL_W_SMDS_Mesh::findVolumeTriangles()
 SMDS_ElemIteratorPtr DriverSTL_W_SMDS_Mesh::getFaces() const
 {
   SMDS_ElemIteratorPtr facesIter = myMesh->elementsIterator(SMDSAbs_Face);
-  SMDS_ElemIteratorPtr tmpTriaIter( new SMDS_ElementVectorIterator( myVolumeTrias.begin(),
-                                                                    myVolumeTrias.end()));
+  SMDS_ElemIteratorPtr tmpTriaIter( new SMDS_ElementVectorIterator( myVolumeFacets.begin(),
+                                                                    myVolumeFacets.end()));
   typedef std::vector< SMDS_ElemIteratorPtr > TElemIterVector;
   TElemIterVector iters(2);
   iters[0] = facesIter;
@@ -201,6 +208,177 @@ static gp_XYZ getNormale( const SMDS_MeshNode* n1,
   return n;
 }
 
+namespace
+{
+  /*!
+   * \brief Vertex of a polygon. Together with 2 neighbor Vertices represents a triangle
+   */
+  struct PolyVertex
+  {
+    SMESH_TNodeXYZ _nxyz;
+    gp_XY          _xy;
+    PolyVertex*    _prev;
+    PolyVertex*    _next;
+
+    void SetNodeAndNext( const SMDS_MeshNode* n, PolyVertex& v )
+    {
+      _nxyz.Set( n );
+      _next = &v;
+      v._prev = this;
+    }
+    PolyVertex* Delete()
+    {
+      _prev->_next = _next;
+      _next->_prev = _prev;
+      return _next;
+    }
+    void GetTriaNodes( const SMDS_MeshNode** nodes) const
+    {
+      nodes[0] = _prev->_nxyz._node;
+      nodes[1] =  this->_nxyz._node;
+      nodes[2] = _next->_nxyz._node;
+    }
+
+    inline static double Area( const PolyVertex* v0, const PolyVertex* v1, const PolyVertex* v2 )
+    {
+      gp_XY vPrev = v0->_xy - v1->_xy;
+      gp_XY vNext = v2->_xy - v1->_xy;
+      return vNext ^ vPrev;
+    }
+    double TriaArea() const { return Area( _prev, this, _next ); }
+
+    bool IsInsideTria( const PolyVertex* v )
+    {
+      gp_XY p = _prev->_xy - v->_xy;
+      gp_XY t =  this->_xy - v->_xy;
+      gp_XY n = _next->_xy - v->_xy;
+      const double tol = -1e-12;
+      return (( p ^ t ) >= tol &&
+              ( t ^ n ) >= tol &&
+              ( n ^ p ) >= tol );
+      // return ( Area( _prev, this, v ) > 0 &&
+      //          Area( this, _next, v ) > 0 &&
+      //          Area( _next, _prev, v ) > 0 );
+    }
+  };
+
+  //================================================================================
+  /*!
+   * \brief Triangulate a polygon. Assure correct orientation for concave polygons
+   */
+  //================================================================================
+
+  bool triangulate( std::vector< const SMDS_MeshNode*>& nodes, const size_t nbNodes )
+  {
+    // connect nodes into a ring
+    std::vector< PolyVertex > pv( nbNodes );
+    for ( size_t i = 1; i < nbNodes; ++i )
+      pv[i-1].SetNodeAndNext( nodes[i-1], pv[i] );
+    pv[ nbNodes-1 ].SetNodeAndNext( nodes[ nbNodes-1 ], pv[0] );
+
+    // get a polygon normal
+    gp_XYZ normal(0,0,0), p0,v01,v02;
+    p0  = pv[0]._nxyz;
+    v01 = pv[1]._nxyz - p0;
+    for ( size_t i = 2; i < nbNodes; ++i )
+    {
+      v02 = pv[i]._nxyz - p0;
+      normal += v01 ^ v02;
+      v01 = v02;
+    }
+    // project nodes to the found plane
+    gp_Ax2 axes;
+    try {
+      axes = gp_Ax2( p0, normal, v01 );
+    }
+    catch ( Standard_Failure ) {
+      return false;
+    }
+    for ( size_t i = 0; i < nbNodes; ++i )
+    {
+      gp_XYZ p = pv[i]._nxyz - p0;
+      pv[i]._xy.SetX( axes.XDirection().XYZ() * p );
+      pv[i]._xy.SetY( axes.YDirection().XYZ() * p );
+    }
+
+    // in a loop, find triangles with positive area and having no vertices inside
+    int iN = 0, nbTria = nbNodes - 2;
+    nodes.reserve( nbTria * 3 );
+    const double minArea = 1e-6;
+    PolyVertex* v = &pv[0], *vi;
+    int nbVertices = nbNodes, nbBadTria = 0, isGoodTria;
+    while ( nbBadTria < nbVertices )
+    {
+      if (( isGoodTria = v->TriaArea() > minArea ))
+      {
+        for ( vi = v->_next->_next;
+              vi != v->_prev;
+              vi = vi->_next )
+        {
+          if ( v->IsInsideTria( vi ))
+            break;
+        }
+        isGoodTria = ( vi == v->_prev );
+      }
+      if ( isGoodTria )
+      {
+        v->GetTriaNodes( &nodes[ iN ] );
+        iN += 3;
+        v = v->Delete();
+        if ( --nbVertices == 3 )
+        {
+          // last triangle remains
+          v->GetTriaNodes( &nodes[ iN ] );
+          return true;
+        }
+        nbBadTria = 0;
+      }
+      else
+      {
+        v = v->_next;
+        ++nbBadTria;
+      }
+    }
+
+    // the polygon is invalid; add triangles with positive area
+    nbBadTria = 0;
+    while ( nbBadTria < nbVertices )
+    {
+      isGoodTria = v->TriaArea() > minArea;
+      if ( isGoodTria )
+      {
+        v->GetTriaNodes( &nodes[ iN ] );
+        iN += 3;
+        v = v->Delete();
+        if ( --nbVertices == 3 )
+        {
+          // last triangle remains
+          v->GetTriaNodes( &nodes[ iN ] );
+          return true;
+        }
+        nbBadTria = 0;
+      }
+      else
+      {
+        v = v->_next;
+        ++nbBadTria;
+      }
+    }
+
+    // add all the rest triangles
+    while ( nbVertices >= 3 )
+    {
+      v->GetTriaNodes( &nodes[ iN ] );
+      iN += 3;
+      v = v->Delete();
+      --nbVertices;
+    }
+
+    return true;
+
+  } // triangulate()
+} // namespace
+
 //================================================================================
 /*!
  * \brief Return nb triangles in a decomposed mesh face
@@ -235,12 +413,13 @@ static int getNbTriangles( const SMDS_MeshElement* face)
  */
 //================================================================================
 
-static int getTriangles( const SMDS_MeshElement* face,
-                         const SMDS_MeshNode**   nodes)
+static int getTriangles( const SMDS_MeshElement*             face,
+                         std::vector< const SMDS_MeshNode*>& nodes)
 {
   // WARNING: decomposing into triangles must be coherent with getNbTriangles()
-  int nbTria, i = 0;
+  int nbTria, i = 0, nbNodes = face->NbNodes();
   SMDS_NodeIteratorPtr nIt = face->interlacedNodesIterator();
+  nodes.resize( nbNodes * 3 );
   nodes[ i++ ] = nIt->next();
   nodes[ i++ ] = nIt->next();
 
@@ -251,30 +430,42 @@ static int getTriangles( const SMDS_MeshElement* face,
   case SMDSEntity_BiQuad_Quadrangle:
     nbTria = ( type == SMDSEntity_BiQuad_Triangle ) ? 6 : 8;
     nodes[ i++ ] = face->GetNode( nbTria );
-    while ( i < 3*(nbTria-1) )
+    for ( i = 3; i < 3*(nbTria-1); i += 3 )
     {
-      nodes[ i++ ] = nodes[ i-2 ];
-      nodes[ i++ ] = nIt->next();
-      nodes[ i++ ] = nodes[ 2 ];
+      nodes[ i+0 ] = nodes[ i-2 ];
+      nodes[ i+1 ] = nIt->next();
+      nodes[ i+2 ] = nodes[ 2 ];
     }
-    nodes[ i++ ] = nodes[ i-2 ];
-    nodes[ i++ ] = nodes[ 0 ];
-    nodes[ i++ ] = nodes[ 2 ];
+    nodes[ i+0 ] = nodes[ i-2 ];
+    nodes[ i+1 ] = nodes[ 0 ];
+    nodes[ i+2 ] = nodes[ 2 ];
+    break;
+  case SMDSEntity_Triangle:
+    nbTria = 1;
+    nodes[ i++ ] = nIt->next();
     break;
   default:
-    // case SMDSEntity_Triangle:
     // case SMDSEntity_Quad_Triangle:
     // case SMDSEntity_Quadrangle:
     // case SMDSEntity_Quad_Quadrangle:
     // case SMDSEntity_Polygon:
     // case SMDSEntity_Quad_Polygon:
-    nbTria = face->NbNodes() - 2;
-    nodes[ i++ ] = nIt->next();
-    while ( i < 3*nbTria )
-    {
-      nodes[ i++ ] = nodes[ 0 ];
-      nodes[ i++ ] = nodes[ i-2 ];
+    nbTria = nbNodes - 2;
+    while ( nIt->more() )
       nodes[ i++ ] = nIt->next();
+
+    if ( !triangulate( nodes, nbNodes ))
+    {
+      nIt = face->interlacedNodesIterator();
+      nodes[ 0 ] = nIt->next();
+      nodes[ 1 ] = nIt->next();
+      nodes[ 2 ] = nIt->next();
+      for ( i = 3; i < 3*nbTria; i += 3 )
+      {
+        nodes[ i+0 ] = nodes[ 0 ];
+        nodes[ i+1 ] = nodes[ i-1 ];
+        nodes[ i+2 ] = nIt->next();
+      }
     }
     break;
   }
@@ -298,7 +489,7 @@ Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeAscii() const
   aFile.writeRaw( buf.c_str(), buf.size() );
 
   char sval[128];
-  const SMDS_MeshNode* triaNodes[2048];
+  std::vector< const SMDS_MeshNode* > triaNodes;
 
   SMDS_ElemIteratorPtr itFaces = getFaces();
   while ( itFaces->more() )
@@ -354,7 +545,7 @@ Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeBinary() const
   aFile.openForWriting();
 
   // we first count the number of triangles
-  int nbTri = myVolumeTrias.size();
+  int nbTri = myNbVolumeTrias;
   {
     SMDS_FaceIteratorPtr itFaces = myMesh->facesIterator();
     while ( itFaces->more() ) {
@@ -372,7 +563,7 @@ Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeBinary() const
 
   int dum=0;
 
-  const SMDS_MeshNode* triaNodes[2048];
+  std::vector< const SMDS_MeshNode* > triaNodes;
 
   SMDS_ElemIteratorPtr itFaces = getFaces();
   while ( itFaces->more() )
index d5fbabfa4fc262f42ec76e7f1f8dbcf71c2594bf..472610f0be47e3d3711edb23b5263d3efd8ff6c6 100644 (file)
@@ -57,7 +57,8 @@ class MESHDRIVERSTL_EXPORT DriverSTL_W_SMDS_Mesh: public Driver_SMDS_Mesh
  private:
   // PRIVATE FIELDS
   bool myIsAscii;
-  std::vector<const SMDS_MeshElement*> myVolumeTrias; // tmp triangles
+  int                                  myNbVolumeTrias;
+  std::vector<const SMDS_MeshElement*> myVolumeFacets; // tmp faces
 };
 
 #endif
index 2b393f44c84c10e8168b9348ac1fa4b80529a183..ff12d3821040724b39a49731e2ee292586cefc46 100644 (file)
@@ -71,7 +71,7 @@ namespace MED{
                 eQUAD4=204, eTRIA6=206, eTRIA7=207, eQUAD8=208, eQUAD9=209,eTETRA4=304,
                 ePYRA5=305, ePENTA6=306, eHEXA8=308, eOCTA12=312, eTETRA10=310, 
                 ePYRA13=313, ePENTA15=315, eHEXA20=320, eHEXA27=327,
-                ePOLYGONE=400, ePOLYEDRE=500, eNONE=0, 
+                ePOLYGONE=400, ePOLYGON2=420, ePOLYEDRE=500, eNONE=0, 
                 eBALL=1101 /*no such a type in med.h, it's just a trick*/,
                 eAllGeoType=-1 } EGeometrieElement;
 
index 1475ee8ab7d9d79cf68141f4616269cdfb1d8ec1..d04b0576241e1208954718f71dad4b8ea3a119c9 100644 (file)
@@ -79,6 +79,7 @@ bool InitEntity2GeomSet()
   aGeomFACESet.insert(eQUAD8);
   aGeomFACESet.insert(eQUAD9);
   aGeomFACESet.insert(ePOLYGONE);
+  aGeomFACESet.insert(ePOLYGON2);
 
   TGeomSet& aGeomMAILLESet = Entity2GeomSet[eMAILLE];
   aGeomMAILLESet.insert(ePOINT1);
index b12af78505f9ddac29a298e92982dbd30a058b24..549f1944aa5164e4474040d507b0466a7777222a 100644 (file)
@@ -960,22 +960,19 @@ namespace MED
 
       MED::TMeshInfo& aMeshInfo = *theInfo.myMeshInfo;
 
-      TValueHolder<TString, char> aMeshName(aMeshInfo.myName);
-      TValueHolder<TElemNum, med_int> anIndex(theInfo.myIndex);
-      TInt aNbElem = (TInt)theInfo.myElemNum->size();
-      TValueHolder<TElemNum, med_int> aConn(theInfo.myConn);
-      TValueHolder<EEntiteMaillage, med_entity_type> anEntity(theInfo.myEntity);
+      TValueHolder<TString, char                       > aMeshName(aMeshInfo.myName);
+      TValueHolder<TElemNum, med_int                   > anIndex  (theInfo.myIndex);
+      TValueHolder<TElemNum, med_int                   > aConn    (theInfo.myConn);
+      TValueHolder<EEntiteMaillage, med_entity_type    > anEntity (theInfo.myEntity);
+      TValueHolder<EGeometrieElement, med_geometry_type> aGeom    (theInfo.myGeom);
       TValueHolder<EConnectivite, med_connectivity_mode> aConnMode(theInfo.myConnMode);
+      TInt aNbElem = (TInt)theInfo.myElemNum->size();
 
       TErr aRet;
-      aRet = MEDmeshPolygonRd(myFile->Id(),
-                              &aMeshName,
-                              MED_NO_DT,
-                              MED_NO_IT,
-                              anEntity,
-                              aConnMode,
-                              &anIndex,
-                              &aConn);
+      aRet = MEDmeshPolygon2Rd(myFile->Id(), &aMeshName,
+                               MED_NO_DT, MED_NO_IT,
+                               anEntity, aGeom,
+                               aConnMode, &anIndex, &aConn);
 
       if(theErr) 
         *theErr = aRet;
@@ -983,18 +980,18 @@ namespace MED
         EXCEPTION(std::runtime_error,"GetPolygoneInfo - MEDmeshPolygonRd(...)");
 
       if(theInfo.myIsElemNames){
-        GetNames(theInfo,aNbElem,theInfo.myEntity,ePOLYGONE,&aRet);
+        GetNames(theInfo,aNbElem,theInfo.myEntity,theInfo.myGeom,&aRet);
         if(theErr) 
           *theErr = aRet;
       }
 
       if(theInfo.myIsElemNum){
-        GetNumeration(theInfo,aNbElem,theInfo.myEntity,ePOLYGONE,&aRet);
+        GetNumeration(theInfo,aNbElem,theInfo.myEntity,theInfo.myGeom,&aRet);
         if(theErr) 
           *theErr = aRet;
       }
 
-      GetFamilies(theInfo,aNbElem,theInfo.myEntity,ePOLYGONE,&aRet);
+      GetFamilies(theInfo,aNbElem,theInfo.myEntity,theInfo.myGeom,&aRet);
       if(theErr) 
         *theErr = aRet;
     }
@@ -1023,37 +1020,32 @@ namespace MED
       MED::TPolygoneInfo& anInfo = const_cast<MED::TPolygoneInfo&>(theInfo);
       MED::TMeshInfo& aMeshInfo = *anInfo.myMeshInfo;
 
-      TValueHolder<TString, char> aMeshName(aMeshInfo.myName);
-      TValueHolder<TElemNum, med_int> anIndex(anInfo.myIndex);
-      TValueHolder<TElemNum, med_int> aConn(anInfo.myConn);
-      TValueHolder<EEntiteMaillage, med_entity_type> anEntity(anInfo.myEntity);
+      TValueHolder<TString, char                       > aMeshName(aMeshInfo.myName);
+      TValueHolder<TElemNum, med_int                   > anIndex  (anInfo.myIndex);
+      TValueHolder<TElemNum, med_int                   > aConn    (anInfo.myConn);
+      TValueHolder<EEntiteMaillage, med_entity_type    > anEntity (anInfo.myEntity);
+      TValueHolder<EGeometrieElement, med_geometry_type> aGeom    (anInfo.myGeom);
       TValueHolder<EConnectivite, med_connectivity_mode> aConnMode(anInfo.myConnMode);
 
-      TErr aRet = MEDmeshPolygonWr(myFile->Id(),
-                                   &aMeshName,
-                                   MED_NO_DT,
-                                   MED_NO_IT,
-                                   MED_UNDEF_DT,
-                                   anEntity,
-                                   aConnMode,
-                                   anInfo.myNbElem + 1,
-                                   &anIndex,
-                                   &aConn);
-      
-      if(theErr) 
+      TErr aRet = MEDmeshPolygon2Wr(myFile->Id(), &aMeshName,
+                                    MED_NO_DT, MED_NO_IT, MED_UNDEF_DT,
+                                    anEntity, aGeom,
+                                    aConnMode, anInfo.myNbElem + 1,
+                                    &anIndex, &aConn);
+      if(theErr)
         *theErr = aRet;
       else if(aRet < 0)
         EXCEPTION(std::runtime_error,"SetPolygoneInfo - MEDmeshPolygonWr(...)");
       
-      SetNames(anInfo,theInfo.myEntity,ePOLYGONE,&aRet);
+      SetNames(anInfo,theInfo.myEntity,anInfo.myGeom,&aRet);
       if(theErr) 
         *theErr = aRet;
       
-      SetNumeration(anInfo,theInfo.myEntity,ePOLYGONE,&aRet);
+      SetNumeration(anInfo,theInfo.myEntity,anInfo.myGeom,&aRet);
       if(theErr) 
         *theErr = aRet;
       
-      SetFamilies(anInfo,theInfo.myEntity,ePOLYGONE,&aRet);
+      SetFamilies(anInfo,theInfo.myEntity,anInfo.myGeom,&aRet);
       if(theErr) 
         *theErr = aRet;
     }
@@ -1094,7 +1086,7 @@ namespace MED
                              MED_NO_DT,
                              MED_NO_IT,
                              med_entity_type(theEntity),
-                             MED_POLYGON,
+                             med_geometry_type(theGeom),
                              MED_CONNECTIVITY,
                              med_connectivity_mode(theConnMode),
                              &chgt,
@@ -1430,16 +1422,14 @@ namespace MED
       }
       return anInfo;
     }
-    
-    
+
+
     //-----------------------------------------------------------------
-    TInt
-    TVWrapper
-    ::GetNbCells(const MED::TMeshInfo& theMeshInfo, 
-                 EEntiteMaillage theEntity, 
-                 EGeometrieElement theGeom, 
-                 EConnectivite theConnMode,
-                 TErr* theErr)
+    TInt TVWrapper::GetNbCells(const MED::TMeshInfo& theMeshInfo,
+                               EEntiteMaillage theEntity,
+                               EGeometrieElement theGeom,
+                               EConnectivite theConnMode,
+                               TErr* theErr)
     {
       TFileWrapper aFileWrapper(myFile,eLECTURE,theErr);
 
@@ -1449,48 +1439,50 @@ namespace MED
       MED::TMeshInfo& aMeshInfo = const_cast<MED::TMeshInfo&>(theMeshInfo);
       TValueHolder<TString, char> aMeshName(aMeshInfo.myName);
       med_bool chgt,trsf;
-      if(theGeom!=MED::ePOLYGONE && theGeom!=MED::ePOLYEDRE && theGeom != MED::eBALL)
+      switch ( theGeom )
       {
-        return MEDmeshnEntity(myFile->Id(),
-                              &aMeshName,
-                              MED_NO_DT,
-                              MED_NO_IT,
-                              med_entity_type(theEntity),
-                              med_geometry_type(theGeom),
-                              MED_CONNECTIVITY,
-                              med_connectivity_mode(theConnMode),
-                              &chgt,
-                              &trsf);
-      }
-      else if(theGeom==MED::ePOLYGONE)
+      case MED::ePOLYGONE:
+      case MED::ePOLYGON2:
       {
-        return MEDmeshnEntity(myFile->Id(),&aMeshName,MED_NO_DT,MED_NO_IT,med_entity_type(theEntity),
-                              MED_POLYGON,MED_INDEX_NODE,med_connectivity_mode(theConnMode),&chgt,&trsf)-1;
+        return MEDmeshnEntity(myFile->Id(),&aMeshName,
+                              MED_NO_DT,MED_NO_IT,
+                              med_entity_type(theEntity),med_geometry_type(theGeom),
+                              MED_INDEX_NODE,med_connectivity_mode(theConnMode),
+                              &chgt,&trsf)-1;
       }
-      else if ( theGeom==MED::ePOLYEDRE )
+      case MED::ePOLYEDRE:
       {
-        return MEDmeshnEntity(myFile->Id(),&aMeshName,MED_NO_DT,MED_NO_IT,med_entity_type(theEntity),
-                              MED_POLYHEDRON,MED_INDEX_FACE,med_connectivity_mode(theConnMode),&chgt,&trsf)-1;
+        return MEDmeshnEntity(myFile->Id(),&aMeshName,
+                              MED_NO_DT,MED_NO_IT,
+                              med_entity_type(theEntity),MED_POLYHEDRON,
+                              MED_INDEX_FACE,med_connectivity_mode(theConnMode),
+                              &chgt,&trsf)-1;
       }
-      else if ( theGeom==MED::eBALL )
+      case MED::eBALL:
       {
         return GetNbBalls( theMeshInfo );
       }
+      default:
+      {
+        return MEDmeshnEntity(myFile->Id(),&aMeshName,
+                              MED_NO_DT,MED_NO_IT,
+                              med_entity_type(theEntity),med_geometry_type(theGeom),
+                              MED_CONNECTIVITY,med_connectivity_mode(theConnMode),
+                              &chgt,&trsf);
+      }
+      }
       return 0;
     }
 
 
     //----------------------------------------------------------------------------
-    void
-    TVWrapper
-    ::GetCellInfo(MED::TCellInfo& theInfo,
-                  TErr* theErr)
+    void TVWrapper::GetCellInfo(MED::TCellInfo& theInfo, TErr* theErr)
     {
       TFileWrapper aFileWrapper(myFile,eLECTURE,theErr);
 
       if(theErr && *theErr < 0)
         return;
-      
+
       MED::TMeshInfo& aMeshInfo = *theInfo.myMeshInfo;
 
       TValueHolder<TString, char>                        aMeshName    (aMeshInfo.myName);
index d9597de660f021c714dac63f579dc1cf7fb646e5..859e3da5a5d46b2be29d089d7766bfd2f8ecc042 100644 (file)
@@ -61,13 +61,18 @@ SET(_link_LIBRARIES
   ${GUI_qtx}
   ${GUI_suit}
   ${GUI_std}
-  ${GUI_Plot2d}
-  ${GUI_SPlot2d}
   SMESHClient
   SMDS
   SMESHControls
 )
 
+IF(SALOME_USE_PLOT2DVIEWER)
+  LIST(APPEND _link_LIBRARIES
+    ${GUI_Plot2d}
+    ${GUI_SPlot2d}
+    )
+ENDIF()
+
 # --- headers ---
 
 # header files / no moc processing
index 65f9e87877ed7722a2c0f4cfd1579cb8f4d0134e..1c9af415d5b13b7b52435b590c1e1d92b1f71808 100644 (file)
@@ -222,10 +222,11 @@ SMESH_ActorDef::SMESH_ActorDef()
   aFilter = my2DActor->GetExtractUnstructuredGrid();
   aFilter->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::eAdding);
   aFilter->RegisterCellsWithType(VTK_TRIANGLE);
-  aFilter->RegisterCellsWithType(VTK_POLYGON);
   aFilter->RegisterCellsWithType(VTK_QUAD);
+  aFilter->RegisterCellsWithType(VTK_POLYGON);
   aFilter->RegisterCellsWithType(VTK_QUADRATIC_TRIANGLE);
   aFilter->RegisterCellsWithType(VTK_QUADRATIC_QUAD);
+  aFilter->RegisterCellsWithType(VTK_QUADRATIC_POLYGON);
   aFilter->RegisterCellsWithType(VTK_BIQUADRATIC_QUAD);
   aFilter->RegisterCellsWithType(VTK_BIQUADRATIC_TRIANGLE);
 
@@ -245,10 +246,11 @@ SMESH_ActorDef::SMESH_ActorDef()
   my2DExtActor->SetRepresentation(SMESH_DeviceActor::eInsideframe);
   aFilter = my2DExtActor->GetExtractUnstructuredGrid();
   aFilter->RegisterCellsWithType(VTK_TRIANGLE);
-  aFilter->RegisterCellsWithType(VTK_POLYGON);
   aFilter->RegisterCellsWithType(VTK_QUAD);
+  aFilter->RegisterCellsWithType(VTK_POLYGON);
   aFilter->RegisterCellsWithType(VTK_QUADRATIC_TRIANGLE);
   aFilter->RegisterCellsWithType(VTK_QUADRATIC_QUAD);
+  aFilter->RegisterCellsWithType(VTK_QUADRATIC_POLYGON);
   aFilter->RegisterCellsWithType(VTK_BIQUADRATIC_QUAD);
   aFilter->RegisterCellsWithType(VTK_BIQUADRATIC_TRIANGLE);
 
@@ -275,10 +277,7 @@ SMESH_ActorDef::SMESH_ActorDef()
   aFilter->RegisterCellsWithType(VTK_QUADRATIC_WEDGE);
   aFilter->RegisterCellsWithType(VTK_QUADRATIC_PYRAMID);
   aFilter->RegisterCellsWithType(VTK_CONVEX_POINT_SET);
-//#ifdef VTK_HAVE_POLYHEDRON
-  MESSAGE("RegisterCellsWithType(VTK_POLYHEDRON)");
   aFilter->RegisterCellsWithType(VTK_POLYHEDRON);
-//#endif
 
   my3DExtProp = vtkProperty::New();
   my3DExtProp->DeepCopy(myNormalVProp);
@@ -1565,18 +1564,20 @@ void SMESH_ActorDef::SetEntityMode(unsigned int theMode)
   if (myEntityMode & eFaces) {
     if (MYDEBUG) MESSAGE("FACES");
     aFilter->RegisterCellsWithType(VTK_TRIANGLE);
-    aFilter->RegisterCellsWithType(VTK_POLYGON);
     aFilter->RegisterCellsWithType(VTK_QUAD);
+    aFilter->RegisterCellsWithType(VTK_POLYGON);
     aFilter->RegisterCellsWithType(VTK_QUADRATIC_TRIANGLE);
     aFilter->RegisterCellsWithType(VTK_QUADRATIC_QUAD);
+    aFilter->RegisterCellsWithType(VTK_QUADRATIC_POLYGON);
     aFilter->RegisterCellsWithType(VTK_BIQUADRATIC_QUAD);
     aFilter->RegisterCellsWithType(VTK_BIQUADRATIC_TRIANGLE);
 
     aHightFilter->RegisterCellsWithType(VTK_TRIANGLE);
-    aHightFilter->RegisterCellsWithType(VTK_POLYGON);
     aHightFilter->RegisterCellsWithType(VTK_QUAD);
+    aHightFilter->RegisterCellsWithType(VTK_POLYGON);
     aHightFilter->RegisterCellsWithType(VTK_QUADRATIC_TRIANGLE);
     aHightFilter->RegisterCellsWithType(VTK_QUADRATIC_QUAD);
+    aHightFilter->RegisterCellsWithType(VTK_QUADRATIC_POLYGON);
     aHightFilter->RegisterCellsWithType(VTK_BIQUADRATIC_QUAD);
     aHightFilter->RegisterCellsWithType(VTK_BIQUADRATIC_TRIANGLE);
   }
@@ -1595,9 +1596,7 @@ void SMESH_ActorDef::SetEntityMode(unsigned int theMode)
     aFilter->RegisterCellsWithType(VTK_QUADRATIC_PYRAMID);
     aFilter->RegisterCellsWithType(VTK_QUADRATIC_WEDGE);
     aFilter->RegisterCellsWithType(VTK_CONVEX_POINT_SET);
-//#ifdef VTK_HAVE_POLYHEDRON
     aFilter->RegisterCellsWithType(VTK_POLYHEDRON);
-//#endif
 
     aHightFilter->RegisterCellsWithType(VTK_TETRA);
     aHightFilter->RegisterCellsWithType(VTK_VOXEL);
@@ -1611,9 +1610,7 @@ void SMESH_ActorDef::SetEntityMode(unsigned int theMode)
     aHightFilter->RegisterCellsWithType(VTK_QUADRATIC_WEDGE);
     aHightFilter->RegisterCellsWithType(VTK_QUADRATIC_PYRAMID);
     aHightFilter->RegisterCellsWithType(VTK_CONVEX_POINT_SET);
-//#ifdef VTK_HAVE_POLYHEDRON
     aHightFilter->RegisterCellsWithType(VTK_POLYHEDRON);
-//#endif
   }
   aFilter->Update();
   if (MYDEBUG) MESSAGE(aFilter->GetOutput()->GetNumberOfCells());
index 3a9b380a3d117bae07491ded69269471ee17c6e5..b3ff7d74bd630b151851c9b49d1328db5e190d08 100644 (file)
@@ -55,35 +55,36 @@ SMESH_ExtractGeometry::SMESH_ExtractGeometry()
 {}
 
 
-SMESH_ExtractGeometry::~SMESH_ExtractGeometry(){}
-
+SMESH_ExtractGeometry::~SMESH_ExtractGeometry()
+{}
 
-vtkIdType SMESH_ExtractGeometry::GetElemObjId(int theVtkID){
+vtkIdType SMESH_ExtractGeometry::GetElemObjId(int theVtkID)
+{
   if( theVtkID < 0 || theVtkID >= myElemVTK2ObjIds.size()) return -1;
   return myElemVTK2ObjIds[theVtkID];
 }
 
 
-vtkIdType SMESH_ExtractGeometry::GetNodeObjId(int theVtkID){
+vtkIdType SMESH_ExtractGeometry::GetNodeObjId(int theVtkID)
+{
   if ( theVtkID < 0 || theVtkID >= myNodeVTK2ObjIds.size()) return -1;
   return myNodeVTK2ObjIds[theVtkID];
 }
 
 
-int SMESH_ExtractGeometry::RequestData(
-  vtkInformation *vtkNotUsed(request),
-  vtkInformationVector **inputVector,
-  vtkInformationVector *outputVector)
+int SMESH_ExtractGeometry::RequestData(vtkInformation *vtkNotUsed(request),
+                                       vtkInformationVector **inputVector,
+                                       vtkInformationVector *outputVector)
 {
   // get the info objects
   vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
   vtkInformation *outInfo = outputVector->GetInformationObject(0);
 
   // get the input and ouptut
-  vtkDataSet *input = vtkDataSet::SafeDownCast(
-    inInfo->Get(vtkDataObject::DATA_OBJECT()));
-  vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast(
-    outInfo->Get(vtkDataObject::DATA_OBJECT()));
+  vtkDataSet *input =
+    vtkDataSet::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
+  vtkUnstructuredGrid *output =
+    vtkUnstructuredGrid::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
 
   vtkIdType ptId, numPts, numCells, i, cellId, newCellId, newId, *pointMap;
   vtkIdList *cellPts;
@@ -100,35 +101,35 @@ int SMESH_ExtractGeometry::RequestData(
   int npts;
   numCells = input->GetNumberOfCells();
   numPts = input->GetNumberOfPoints();
-  
+
   vtkDebugMacro(<< "Extracting geometry");
 
   if ( ! this->ImplicitFunction )
-    {
+  {
     vtkErrorMacro(<<"No implicit function specified");
     return 0;
-    }
+  }
 
   newCellPts = vtkIdList::New();
   newCellPts->Allocate(VTK_CELL_SIZE);
 
   if ( this->ExtractInside )
-    {
+  {
     multiplier = 1.0;
-    }
-  else 
-    {
+  }
+  else
+  {
     multiplier = -1.0;
-    }
+  }
 
   // Loop over all points determining whether they are inside the
   // implicit function. Copy the points and point data if they are.
   //
   pointMap = new vtkIdType[numPts]; // maps old point ids into new
   for (i=0; i < numPts; i++)
-    {
+  {
     pointMap[i] = -1;
-    }
+  }
 
   output->Allocate(numCells/4); //allocate storage for geometry/topology
   newPts = vtkPoints::New();
@@ -136,7 +137,7 @@ int SMESH_ExtractGeometry::RequestData(
   outputPD->CopyAllocate(pd);
   outputCD->CopyAllocate(cd);
   vtkFloatArray *newScalars = NULL;
-  
+
   if(myStoreMapping){
     myElemVTK2ObjIds.clear();
     myElemVTK2ObjIds.reserve(numCells);
@@ -145,110 +146,110 @@ int SMESH_ExtractGeometry::RequestData(
   }
 
   if ( ! this->ExtractBoundaryCells )
-    {
+  {
     for ( ptId=0; ptId < numPts; ptId++ )
-      {
+    {
       x = input->GetPoint(ptId);
       if ( (this->ImplicitFunction->FunctionValue(x)*multiplier) < 0.0 )
-        {
+      {
         newId = newPts->InsertNextPoint(x);
         pointMap[ptId] = newId;
         myNodeVTK2ObjIds.push_back(ptId);
         outputPD->CopyData(pd,ptId,newId);
-        }
       }
     }
+  }
   else
-    {
+  {
     // To extract boundary cells, we have to create supplemental information
     if ( this->ExtractBoundaryCells )
-      {
+    {
       double val;
       newScalars = vtkFloatArray::New();
       newScalars->SetNumberOfValues(numPts);
 
       for (ptId=0; ptId < numPts; ptId++ )
-        {
+      {
         x = input->GetPoint(ptId);
         val = this->ImplicitFunction->FunctionValue(x) * multiplier;
         newScalars->SetValue(ptId, val);
         if ( val < 0.0 )
-          {
+        {
           newId = newPts->InsertNextPoint(x);
           pointMap[ptId] = newId;
           myNodeVTK2ObjIds.push_back(ptId);
           outputPD->CopyData(pd,ptId,newId);
-          }
         }
       }
     }
+  }
 
   // Now loop over all cells to see whether they are inside implicit
   // function (or on boundary if ExtractBoundaryCells is on).
   //
   for (cellId=0; cellId < numCells; cellId++)
-    {
+  {
     cell = input->GetCell(cellId);
     cellPts = cell->GetPointIds();
     numCellPts = cell->GetNumberOfPoints();
 
     newCellPts->Reset();
     if ( ! this->ExtractBoundaryCells ) //requires less work
-      {
+    {
       for ( npts=0, i=0; i < numCellPts; i++, npts++)
-        {
+      {
         ptId = cellPts->GetId(i);
         if ( pointMap[ptId] < 0 )
-          {
+        {
           break; //this cell won't be inserted
-          }
+        }
         else
-          {
+        {
           newCellPts->InsertId(i,pointMap[ptId]);
-          }
         }
-      } //if don't want to extract boundary cells
-    
+      }
+    } //if don't want to extract boundary cells
+
     else //want boundary cells
-      {
+    {
       for ( npts=0, i=0; i < numCellPts; i++ )
-        {
+      {
         ptId = cellPts->GetId(i);
         if ( newScalars->GetValue(ptId) <= 0.0 )
-          {
+        {
           npts++;
-          }
         }
+      }
       if ( npts > 0 )
-        {
+      {
         for ( i=0; i < numCellPts; i++ )
-          {
+        {
           ptId = cellPts->GetId(i);
           if ( pointMap[ptId] < 0 )
-            {
+          {
             x = input->GetPoint(ptId);
             newId = newPts->InsertNextPoint(x);
             pointMap[ptId] = newId;
             myNodeVTK2ObjIds.push_back(ptId);
             outputPD->CopyData(pd,ptId,newId);
-            }
-          newCellPts->InsertId(i,pointMap[ptId]);
           }
-        }//a boundary or interior cell
-      }//if mapping boundary cells
-      
-    if ( npts >= numCellPts || (this->ExtractBoundaryCells && npts > 0) )
-      {
-        if(cell->GetCellType() == VTK_POLYHEDRON) {
-          newCellPts->Reset();
-          vtkUnstructuredGrid::SafeDownCast(input)->GetFaceStream( cellId ,newCellPts );        
-          vtkUnstructuredGrid::ConvertFaceStreamPointIds(newCellPts, pointMap);
+          newCellPts->InsertId(i,pointMap[ptId]);
         }
-          newCellId = output->InsertNextCell(cell->GetCellType(),newCellPts);
-          myElemVTK2ObjIds.push_back(cellId);
-          outputCD->CopyData(cd,cellId,newCellId);
+      }//a boundary or interior cell
+    }//if mapping boundary cells
+
+    if ( npts >= numCellPts || (this->ExtractBoundaryCells && npts > 0) )
+    {
+      if(cell->GetCellType() == VTK_POLYHEDRON) {
+        newCellPts->Reset();
+        vtkUnstructuredGrid::SafeDownCast(input)->GetFaceStream( cellId ,newCellPts );
+        vtkUnstructuredGrid::ConvertFaceStreamPointIds(newCellPts, pointMap);
       }
-    }//for all cells
+      newCellId = output->InsertNextCell(cell->GetCellType(),newCellPts);
+      myElemVTK2ObjIds.push_back(cellId);
+      outputCD->CopyData(cd,cellId,newCellId);
+    }
+  }//for all cells
 
   // Update ourselves and release memory
   //
@@ -256,11 +257,11 @@ int SMESH_ExtractGeometry::RequestData(
   newCellPts->Delete();
   output->SetPoints(newPts);
   newPts->Delete();
-  
+
   if ( this->ExtractBoundaryCells )
-    {
+  {
     newScalars->Delete();
-    }
+  }
 
   output->Squeeze();
   return 1;
index ec37985d4371aab42422491b331deb95b55fd288..44d70da65188d8ad8cef4bc91a923efda8ed5eef 100644 (file)
 #include "SMESH_ObjectDef.h"
 #include "SMESH_ActorUtils.h"
 
+#include "SMDS_BallElement.hxx"
 #include "SMDS_Mesh.hxx"
+#include "SMDS_MeshCell.hxx"
 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
-#include "SMDS_BallElement.hxx"
 #include "SMESH_Actor.h"
 #include "SMESH_ControlsDef.hxx"
-#include "SalomeApp_Application.h"
-#include "VTKViewer_ExtractUnstructuredGrid.h"
-#include "VTKViewer_CellLocationsArray.h"
+
+#include <SalomeApp_Application.h>
+#include <VTKViewer_ExtractUnstructuredGrid.h>
+#include <VTKViewer_CellLocationsArray.h>
 
 #include CORBA_SERVER_HEADER(SMESH_Gen)
 #include CORBA_SERVER_HEADER(SALOME_Exception)
@@ -82,48 +84,48 @@ static int MYDEBUGWITHFILES = 0;
 // function : getCellType
 // purpose  : Get type of VTK cell
 //=================================================================================
-static inline vtkIdType getCellType( const SMDSAbs_ElementType theType,
-                                     const bool                thePoly,
-                                     const int                 theNbNodes )
-{
-  switch( theType )
-  {
-    case SMDSAbs_0DElement:         return VTK_VERTEX;
-
-    case SMDSAbs_Ball:              return VTK_POLY_VERTEX;
-
-    case SMDSAbs_Edge: 
-      if( theNbNodes == 2 )         return VTK_LINE;
-      else if ( theNbNodes == 3 )   return VTK_QUADRATIC_EDGE;
-      else return VTK_EMPTY_CELL;
-
-    case SMDSAbs_Face  :
-      if (thePoly && theNbNodes>2 ) return VTK_POLYGON;
-      else if ( theNbNodes == 3 )   return VTK_TRIANGLE;
-      else if ( theNbNodes == 4 )   return VTK_QUAD;
-      else if ( theNbNodes == 6 )   return VTK_QUADRATIC_TRIANGLE;
-      else if ( theNbNodes == 8 )   return VTK_QUADRATIC_QUAD;
-      else if ( theNbNodes == 9 )   return VTK_BIQUADRATIC_QUAD;
-      else if ( theNbNodes == 7 )   return VTK_BIQUADRATIC_TRIANGLE;
-      else return VTK_EMPTY_CELL;
+// static inline vtkIdType getCellType( const SMDSAbs_ElementType theType,
+//                                      const bool                thePoly,
+//                                      const int                 theNbNodes )
+// {
+//   switch( theType )
+//   {
+//     case SMDSAbs_0DElement:         return VTK_VERTEX;
+
+//     case SMDSAbs_Ball:              return VTK_POLY_VERTEX;
+
+//     case SMDSAbs_Edge: 
+//       if( theNbNodes == 2 )         return VTK_LINE;
+//       else if ( theNbNodes == 3 )   return VTK_QUADRATIC_EDGE;
+//       else return VTK_EMPTY_CELL;
+
+//     case SMDSAbs_Face  :
+//       if (thePoly && theNbNodes>2 ) return VTK_POLYGON;
+//       else if ( theNbNodes == 3 )   return VTK_TRIANGLE;
+//       else if ( theNbNodes == 4 )   return VTK_QUAD;
+//       else if ( theNbNodes == 6 )   return VTK_QUADRATIC_TRIANGLE;
+//       else if ( theNbNodes == 8 )   return VTK_QUADRATIC_QUAD;
+//       else if ( theNbNodes == 9 )   return VTK_BIQUADRATIC_QUAD;
+//       else if ( theNbNodes == 7 )   return VTK_BIQUADRATIC_TRIANGLE;
+//       else return VTK_EMPTY_CELL;
       
-    case SMDSAbs_Volume:
-      if (thePoly && theNbNodes>3 ) return VTK_POLYHEDRON; //VTK_CONVEX_POINT_SET;
-      else if ( theNbNodes == 4 )   return VTK_TETRA;
-      else if ( theNbNodes == 5 )   return VTK_PYRAMID;
-      else if ( theNbNodes == 6 )   return VTK_WEDGE;
-      else if ( theNbNodes == 8 )   return VTK_HEXAHEDRON;
-      else if ( theNbNodes == 12 )  return VTK_HEXAGONAL_PRISM;
-      else if ( theNbNodes == 10 )  return VTK_QUADRATIC_TETRA;
-      else if ( theNbNodes == 20 )  return VTK_QUADRATIC_HEXAHEDRON;
-      else if ( theNbNodes == 27 )  return VTK_TRIQUADRATIC_HEXAHEDRON;
-      else if ( theNbNodes == 15 )  return VTK_QUADRATIC_WEDGE;
-      else if ( theNbNodes == 13 )  return VTK_QUADRATIC_PYRAMID; //VTK_CONVEX_POINT_SET;
-      else return VTK_EMPTY_CELL;
-
-    default: return VTK_EMPTY_CELL;
-  }
-}
+//     case SMDSAbs_Volume:
+//       if (thePoly && theNbNodes>3 ) return VTK_POLYHEDRON; //VTK_CONVEX_POINT_SET;
+//       else if ( theNbNodes == 4 )   return VTK_TETRA;
+//       else if ( theNbNodes == 5 )   return VTK_PYRAMID;
+//       else if ( theNbNodes == 6 )   return VTK_WEDGE;
+//       else if ( theNbNodes == 8 )   return VTK_HEXAHEDRON;
+//       else if ( theNbNodes == 12 )  return VTK_HEXAGONAL_PRISM;
+//       else if ( theNbNodes == 10 )  return VTK_QUADRATIC_TETRA;
+//       else if ( theNbNodes == 20 )  return VTK_QUADRATIC_HEXAHEDRON;
+//       else if ( theNbNodes == 27 )  return VTK_TRIQUADRATIC_HEXAHEDRON;
+//       else if ( theNbNodes == 15 )  return VTK_QUADRATIC_WEDGE;
+//       else if ( theNbNodes == 13 )  return VTK_QUADRATIC_PYRAMID; //VTK_CONVEX_POINT_SET;
+//       else return VTK_EMPTY_CELL;
+
+//     default: return VTK_EMPTY_CELL;
+//   }
+// }
 
 //=================================================================================
 // functions : SMESH_VisualObjDef
@@ -438,23 +440,23 @@ void SMESH_VisualObjDef::buildElemPrs()
   for ( int i = 0; i < nbTypes; i++ ) // iterate through all types of elements
   {
     if ( nbEnts[ aTypes[ i ] ] > 0 ) {
-      
+
       const SMDSAbs_ElementType& aType = aTypes[ i ];
       const TEntityList& aList = anEnts[ aType ];
       TEntityList::const_iterator anIter;
       for ( anIter = aList.begin(); anIter != aList.end(); ++anIter )
       {
         const SMDS_MeshElement* anElem = *anIter;
-        
+
         vtkIdType aNbNodes = anElem->NbNodes();
         anIdList->SetNumberOfIds( aNbNodes );
-        const vtkIdType vtkElemType = getCellType( aType, anElem->IsPoly(), aNbNodes );
-        
+        const vtkIdType vtkElemType = SMDS_MeshCell::toVtkType( anElem->GetEntityType() );
+
         int anId = anElem->GetID();
-        
+
         mySMDS2VTKElems.insert( TMapOfIds::value_type( anId, iElem ) );
         myVTK2SMDSElems.insert( TMapOfIds::value_type( iElem, anId ) );
-        
+
         SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
         {
           // Convertions connectivities from SMDS to VTK
@@ -537,7 +539,7 @@ void SMESH_VisualObjDef::buildElemPrs()
 
 //=================================================================================
 // function : GetEdgeNodes
-// purpose  : Retrieve ids of nodes from edge of elements ( edge is numbered from 1 )
+// purpose  : Retrieve ids of nodes from edge of elements ( edge is numbered from 0 )
 //=================================================================================
 bool SMESH_VisualObjDef::GetEdgeNodes( const int theElemId,
                                        const int theEdgeNum,
@@ -554,25 +556,13 @@ bool SMESH_VisualObjDef::GetEdgeNodes( const int theElemId,
     
   int nbNodes = anElem->NbCornerNodes();
 
-  if ( theEdgeNum < 0 || theEdgeNum > 3 || (nbNodes != 3 && nbNodes != 4) || theEdgeNum > nbNodes )
+  if (( theEdgeNum < 0 || theEdgeNum > 3 ) ||
+      ( nbNodes != 3 && nbNodes != 4 ) ||
+      ( theEdgeNum >= nbNodes ))
     return false;
 
-  vector<int> anIds( nbNodes );
-  SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
-  int i = 0;
-  while( anIter->more() && i < nbNodes )
-    anIds[ i++ ] = anIter->next()->GetID();
-
-  if ( theEdgeNum < nbNodes - 1 )
-  {
-    theNodeId1 = anIds[ theEdgeNum ];
-    theNodeId2 = anIds[ theEdgeNum + 1 ];
-  }
-  else
-  {
-    theNodeId1 = anIds[ nbNodes - 1 ];
-    theNodeId2 = anIds[ 0 ];
-  }
+  theNodeId1 = anElem->GetNode(  theEdgeNum                 )->GetID();
+  theNodeId2 = anElem->GetNode(( theEdgeNum + 1 ) % nbNodes )->GetID();
 
   return true;
 }
@@ -582,7 +572,7 @@ vtkUnstructuredGrid* SMESH_VisualObjDef::GetUnstructuredGrid()
   if ( !myLocalGrid && !GetMesh()->isCompacted() )
   {
     GetMesh()->compactMesh();
-        updateEntitiesFlags();
+    updateEntitiesFlags();
     vtkUnstructuredGrid *theGrid = GetMesh()->getGrid();
     myGrid->ShallowCopy(theGrid);
   }
@@ -596,10 +586,9 @@ vtkUnstructuredGrid* SMESH_VisualObjDef::GetUnstructuredGrid()
 //=================================================================================
 bool SMESH_VisualObjDef::IsValid() const
 {
-        //MESSAGE("SMESH_VisualObjDef::IsValid");
-  return ( GetNbEntities(SMDSAbs_0DElement) > 0 || 
-           GetNbEntities(SMDSAbs_Ball     ) > 0 || 
-           GetNbEntities(SMDSAbs_Edge     ) > 0 || 
+  return ( GetNbEntities(SMDSAbs_0DElement) > 0 ||
+           GetNbEntities(SMDSAbs_Ball     ) > 0 ||
+           GetNbEntities(SMDSAbs_Edge     ) > 0 ||
            GetNbEntities(SMDSAbs_Face     ) > 0 ||
            GetNbEntities(SMDSAbs_Volume   ) > 0 ||
            GetNbEntities(SMDSAbs_Node     ) > 0 );
@@ -609,59 +598,67 @@ bool SMESH_VisualObjDef::IsValid() const
 // function : updateEntitiesFlags
 // purpose  : Update entities flags
 //=================================================================================
-void SMESH_VisualObjDef::updateEntitiesFlags() {
+void SMESH_VisualObjDef::updateEntitiesFlags()
+{
+  unsigned int tmp = myEntitiesState;
+  ClearEntitiesFlags();
 
-        unsigned int tmp = myEntitiesState;
-        ClearEntitiesFlags();
+  map<SMDSAbs_ElementType,int> entities = SMESH::GetEntitiesFromObject(this);
 
-        map<SMDSAbs_ElementType,int> entities = SMESH::GetEntitiesFromObject(this);
-        
 
-        if( myEntitiesCache[SMDSAbs_0DElement] != 0 ||  myEntitiesCache[SMDSAbs_0DElement] >= entities[SMDSAbs_0DElement] )
-                myEntitiesState &= ~SMESH_Actor::e0DElements;
+  if( myEntitiesCache[SMDSAbs_0DElement] != 0 ||
+      myEntitiesCache[SMDSAbs_0DElement] >= entities[SMDSAbs_0DElement] )
+    myEntitiesState &= ~SMESH_Actor::e0DElements;
 
-        if( myEntitiesCache[SMDSAbs_Ball] != 0 ||  myEntitiesCache[SMDSAbs_Ball] >= entities[SMDSAbs_Ball] )
-                myEntitiesState &= ~SMESH_Actor::eBallElem;
+  if( myEntitiesCache[SMDSAbs_Ball] != 0 ||
+      myEntitiesCache[SMDSAbs_Ball] >= entities[SMDSAbs_Ball] )
+    myEntitiesState &= ~SMESH_Actor::eBallElem;
 
-        if( myEntitiesCache[SMDSAbs_Edge] != 0 || myEntitiesCache[SMDSAbs_Edge] >= entities[SMDSAbs_Edge] )
-                myEntitiesState &= ~SMESH_Actor::eEdges; 
+  if( myEntitiesCache[SMDSAbs_Edge] != 0 ||
+      myEntitiesCache[SMDSAbs_Edge] >= entities[SMDSAbs_Edge] )
+    myEntitiesState &= ~SMESH_Actor::eEdges;
 
-        if( myEntitiesCache[SMDSAbs_Face] != 0 || myEntitiesCache[SMDSAbs_Face] >= entities[SMDSAbs_Face] )
-                myEntitiesState &= ~SMESH_Actor::eFaces; 
+  if( myEntitiesCache[SMDSAbs_Face] != 0 ||
+      myEntitiesCache[SMDSAbs_Face] >= entities[SMDSAbs_Face] )
+    myEntitiesState &= ~SMESH_Actor::eFaces;
 
-        if( myEntitiesCache[SMDSAbs_Volume] != 0 || myEntitiesCache[SMDSAbs_Volume] >= entities[SMDSAbs_Volume] )
-                myEntitiesState &= ~SMESH_Actor::eVolumes;
+  if( myEntitiesCache[SMDSAbs_Volume] != 0 ||
+      myEntitiesCache[SMDSAbs_Volume] >= entities[SMDSAbs_Volume] )
+    myEntitiesState &= ~SMESH_Actor::eVolumes;
 
-        if( tmp != myEntitiesState ) {
-                myEntitiesFlag = true;
-        }
-        
-        myEntitiesCache = entities;
+  if( tmp != myEntitiesState ) {
+    myEntitiesFlag = true;
+  }
+
+  myEntitiesCache = entities;
 }
 
 //=================================================================================
 // function : ClearEntitiesFlags
 // purpose  : Clear the entities flags
 //=================================================================================
-void SMESH_VisualObjDef::ClearEntitiesFlags() {
-        myEntitiesState = SMESH_Actor::eAllEntity;
-        myEntitiesFlag = false;
+void SMESH_VisualObjDef::ClearEntitiesFlags()
+{
+  myEntitiesState = SMESH_Actor::eAllEntity;
+  myEntitiesFlag = false;
 }
 
 //=================================================================================
 // function : GetEntitiesFlag
 // purpose  : Return the entities flag
 //=================================================================================
-bool SMESH_VisualObjDef::GetEntitiesFlag() {
-        return myEntitiesFlag;
+bool SMESH_VisualObjDef::GetEntitiesFlag()
+{
+  return myEntitiesFlag;
 }
 
 //=================================================================================
 // function : GetEntitiesState
 // purpose  : Return the entities state
 //=================================================================================
-unsigned int SMESH_VisualObjDef::GetEntitiesState() {
-        return myEntitiesState;
+unsigned int SMESH_VisualObjDef::GetEntitiesState()
+{
+  return myEntitiesState;
 }
 
 /*
@@ -711,20 +708,20 @@ bool SMESH_MeshObj::Update( int theIsClear )
 
 bool SMESH_MeshObj::NulData()
 {
-        MESSAGE ("SMESH_MeshObj::NulData() ==================================================================================");
-        if (!myEmptyGrid)
-        {
-          myEmptyGrid = SMDS_UnstructuredGrid::New();
-          myEmptyGrid->Initialize();
-          myEmptyGrid->Allocate();
-          vtkPoints* points = vtkPoints::New();
-          points->SetNumberOfPoints(0);
-          myEmptyGrid->SetPoints( points );
-          points->Delete();
-          myEmptyGrid->BuildLinks();
-        }
-        myGrid->ShallowCopy(myEmptyGrid);
-        return true;
+  MESSAGE ("SMESH_MeshObj::NulData() ==================================================================================");
+  if (!myEmptyGrid)
+  {
+    myEmptyGrid = SMDS_UnstructuredGrid::New();
+    myEmptyGrid->Initialize();
+    myEmptyGrid->Allocate();
+    vtkPoints* points = vtkPoints::New();
+    points->SetNumberOfPoints(0);
+    myEmptyGrid->SetPoints( points );
+    points->Delete();
+    myEmptyGrid->BuildLinks();
+  }
+  myGrid->ShallowCopy(myEmptyGrid);
+  return true;
 }
 //=================================================================================
 // function : GetElemDimension
index 4503dd1c427faf93fb9a22e7a1503fe11d065cb0..78ec260d66517867302678585c98df832596c352 100644 (file)
@@ -123,7 +123,7 @@ SMESH_SVTKActor
   SVTK::CopyPoints( GetSource(), aSourceDataSet );
   SVTK::CopyPoints( myBallGrid, aSourceDataSet );
   SVTK::CopyPoints( my0DGrid,    aSourceDataSet );
-  
+
 
   int aNbOfParts = theMapIndex.Extent();
 
@@ -143,12 +143,14 @@ SMESH_SVTKActor
       {
         if(aCell->GetCellType() == VTK_VERTEX ) {
           my0DGrid->InsertNextCell(aCell->GetCellType(),aCell->GetPointIds());
-        } else if(aCell->GetCellType() == VTK_POLY_VERTEX ) {
+        }
+        else if(aCell->GetCellType() == VTK_POLY_VERTEX ) {
           vtkIdType newCellId = myBallGrid->InsertNextCell(aCell->GetCellType(),aCell->GetPointIds());
           if(myVisualObj) {
             outputCD->CopyData(cd, myVisualObj->GetElemVTKId(aPartId), newCellId);
           }
-        } else {
+        }
+        else {
           myUnstructuredGrid->InsertNextCell(aCell->GetCellType(),aCell->GetPointIds());
         }
       }
index 056509ffe419d7defdf50172e4a306f7a07c9a09..87a2f15589acdfe42066b515bf39be6ad6ebca0c 100644 (file)
@@ -322,11 +322,11 @@ SMDS_BallElement* SMDS_Mesh::AddBallWithID(const SMDS_MeshNode * n, double diame
   SMDS_BallElement *ball = myBallPool->getNew();
   ball->init(n->getVtkId(), diameter, this);
   if (!this->registerElement(ID,ball))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(ball->getVtkId(), VTK_EMPTY_CELL);
-      myBallPool->destroy(ball);
-      return 0;
-    }
+  {
+    this->myGrid->GetCellTypesArray()->SetValue(ball->getVtkId(), VTK_EMPTY_CELL);
+    myBallPool->destroy(ball);
+    return 0;
+  }
   adjustmyCellsCapacity(ID);
   myCells[ID] = ball;
   myInfo.myNbBalls++;
@@ -1339,8 +1339,6 @@ SMDS_Mesh::AddPolygonalFaceWithID (const vector<const SMDS_MeshNode*> & nodes,
   }
   else
   {
-    //#ifdef VTK_HAVE_POLYHEDRON
-    //MESSAGE("AddPolygonalFaceWithID vtk " << ID);
     myNodeIds.resize( nodes.size() );
     for ( size_t i = 0; i < nodes.size(); ++i )
       myNodeIds[i] = nodes[i]->getVtkId();
@@ -1354,25 +1352,12 @@ SMDS_Mesh::AddPolygonalFaceWithID (const vector<const SMDS_MeshNode*> & nodes,
       return 0;
     }
     face = facevtk;
-    //#else
-    //    MESSAGE("AddPolygonalFaceWithID smds " << ID);
-    //     for ( int i = 0; i < nodes.size(); ++i )
-    //      if ( !nodes[ i ] ) return 0;
-    //      face = new SMDS_PolygonalFaceOfNodes(nodes);
-    //#endif
+
     adjustmyCellsCapacity(ID);
     myCells[ID] = face;
     myInfo.myNbPolygons++;
   }
 
-  //#ifndef VTK_HAVE_POLYHEDRON
-  //  if (!registerElement(ID, face))
-  //    {
-  //      registerElement(myElementIDFactory->GetFreeID(), face);
-  //      //RemoveElement(face, false);
-  //      //face = NULL;
-  //    }
-  //#endif
   return face;
 }
 
@@ -1386,6 +1371,69 @@ SMDS_MeshFace* SMDS_Mesh::AddPolygonalFace (const vector<const SMDS_MeshNode*> &
   return SMDS_Mesh::AddPolygonalFaceWithID(nodes, myElementIDFactory->GetFreeID());
 }
 
+///////////////////////////////////////////////////////////////////////////////
+/// Add a quadratic polygon defined by its nodes IDs
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFaceWithID (const vector<int> & nodes_ids,
+                                                      const int           ID)
+{
+  vector<const SMDS_MeshNode*> nodes( nodes_ids.size() );
+  for ( size_t i = 0; i < nodes.size(); i++) {
+    nodes[i] = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nodes_ids[i]);
+    if (!nodes[i]) return NULL;
+  }
+  return SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Add a quadratic polygon defined by its nodes
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace*
+SMDS_Mesh::AddQuadPolygonalFaceWithID (const vector<const SMDS_MeshNode*> & nodes,
+                                       const int                            ID)
+{
+  SMDS_MeshFace * face;
+
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if (hasConstructionEdges())
+  {
+    MESSAGE("Error : Not implemented");
+    return NULL;
+  }
+  else
+  {
+    myNodeIds.resize( nodes.size() );
+    for ( size_t i = 0; i < nodes.size(); ++i )
+      myNodeIds[i] = nodes[i]->getVtkId();
+
+    SMDS_VtkFace *facevtk = myFacePool->getNew();
+    facevtk->initQuadPoly(myNodeIds, this);
+    if (!this->registerElement(ID,facevtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+      myFacePool->destroy(facevtk);
+      return 0;
+    }
+    face = facevtk;
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = face;
+    myInfo.myNbQuadPolygons++;
+  }
+  return face;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Add a quadratic polygon defined by its nodes.
+/// An ID is automatically affected to the created face.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFace (const vector<const SMDS_MeshNode*> & nodes)
+{
+  return SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes, myElementIDFactory->GetFreeID());
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 /// Create a new polyhedral volume and add it to the mesh.
 /// @param ID The ID of the new volume
@@ -1779,8 +1827,8 @@ SMDS_MeshFace * SMDS_Mesh::createQuadrangle(const SMDS_MeshNode * node1,
 
 void SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node)
 {
-    MESSAGE("RemoveNode");
-        RemoveElement(node, true);
+  MESSAGE("RemoveNode");
+  RemoveElement(node, true);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1789,7 +1837,7 @@ void SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node)
 
 void SMDS_Mesh::Remove0DElement(const SMDS_Mesh0DElement * elem0d)
 {
-    MESSAGE("Remove0DElement");
+  MESSAGE("Remove0DElement");
   RemoveElement(elem0d,true);
 }
 
@@ -1799,8 +1847,8 @@ void SMDS_Mesh::Remove0DElement(const SMDS_Mesh0DElement * elem0d)
 
 void SMDS_Mesh::RemoveEdge(const SMDS_MeshEdge * edge)
 {
-    MESSAGE("RemoveEdge");
-        RemoveElement(edge,true);
+  MESSAGE("RemoveEdge");
+  RemoveElement(edge,true);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1809,8 +1857,8 @@ void SMDS_Mesh::RemoveEdge(const SMDS_MeshEdge * edge)
 
 void SMDS_Mesh::RemoveFace(const SMDS_MeshFace * face)
 {
-    MESSAGE("RemoveFace");
-        RemoveElement(face, true);
+  MESSAGE("RemoveFace");
+  RemoveElement(face, true);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1819,8 +1867,8 @@ void SMDS_Mesh::RemoveFace(const SMDS_MeshFace * face)
 
 void SMDS_Mesh::RemoveVolume(const SMDS_MeshVolume * volume)
 {
-    MESSAGE("RemoveVolume");
-        RemoveElement(volume, true);
+  MESSAGE("RemoveVolume");
+  RemoveElement(volume, true);
 }
 
 //=======================================================================
@@ -1830,8 +1878,8 @@ void SMDS_Mesh::RemoveVolume(const SMDS_MeshVolume * volume)
 
 bool SMDS_Mesh::RemoveFromParent()
 {
-        if (myParent==NULL) return false;
-        else return (myParent->RemoveSubMesh(this));
+  if (myParent==NULL) return false;
+  else return (myParent->RemoveSubMesh(this));
 }
 
 //=======================================================================
@@ -1841,20 +1889,20 @@ bool SMDS_Mesh::RemoveFromParent()
 
 bool SMDS_Mesh::RemoveSubMesh(const SMDS_Mesh * aMesh)
 {
-        bool found = false;
+  bool found = false;
 
-        list<SMDS_Mesh *>::iterator itmsh=myChildren.begin();
-        for (; itmsh!=myChildren.end() && !found; itmsh++)
-        {
-                SMDS_Mesh * submesh = *itmsh;
-                if (submesh == aMesh)
-                {
-                        found = true;
-                        myChildren.erase(itmsh);
-                }
-        }
+  list<SMDS_Mesh *>::iterator itmsh=myChildren.begin();
+  for (; itmsh!=myChildren.end() && !found; itmsh++)
+  {
+    SMDS_Mesh * submesh = *itmsh;
+    if (submesh == aMesh)
+    {
+      found = true;
+      myChildren.erase(itmsh);
+    }
+  }
 
-        return found;
+  return found;
 }
 
 //=======================================================================
@@ -1874,10 +1922,10 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
   bool Ok = false;
   SMDS_MeshCell* cell = dynamic_cast<SMDS_MeshCell*>((SMDS_MeshElement*) element);
   if (cell)
-    {
-      Ok = cell->vtkOrder(nodes, nbnodes);
-      Ok = cell->ChangeNodes(nodes, nbnodes);
-    }
+  {
+    Ok = cell->vtkOrder(nodes, nbnodes);
+    Ok = cell->ChangeNodes(nodes, nbnodes);
+  }
 
   if ( Ok ) { // update InverseElements
 
@@ -2436,7 +2484,7 @@ const SMDS_MeshElement* SMDS_Mesh::FindElement (const vector<const SMDS_MeshNode
       int nbNodesToCheck = noMedium ? e->NbCornerNodes() : e->NbNodes();
       if ( nbNodesToCheck == nodes.size() )
       {
-        for ( int i = 1; e && i < nodes.size(); ++ i )
+        for ( size_t i = 1; e && i < nodes.size(); ++i )
         {
           int nodeIndex = e->GetNodeIndex( nodes[ i ]);
           if ( nodeIndex < 0 || nodeIndex >= nbNodesToCheck )
index de397bf109d5867088d75dbe2ea3b63cea2cf2f6..7c728d6f96569de4fe510d87103148c0a9c631ab 100644 (file)
@@ -58,7 +58,7 @@
 
 #define MYASSERT(val) if (!(val)) throw SALOME_Exception(LOCALIZED("assertion not verified"));
 
-class SMDS_EXPORT SMDS_Mesh:public SMDS_MeshObject
+class SMDS_EXPORT SMDS_Mesh : public SMDS_MeshObject
 {
 public:
   friend class SMDS_MeshIDFactory;
@@ -576,14 +576,22 @@ public:
 
   virtual SMDS_MeshFace* AddPolygonalFace (const std::vector<const SMDS_MeshNode*> & nodes);
 
+  virtual SMDS_MeshFace* AddQuadPolygonalFaceWithID(const std::vector<int> & nodes_ids,
+                                                    const int                ID);
+
+  virtual SMDS_MeshFace* AddQuadPolygonalFaceWithID(const std::vector<const SMDS_MeshNode*> & nodes,
+                                                    const int                                 ID);
+
+  virtual SMDS_MeshFace* AddQuadPolygonalFace(const std::vector<const SMDS_MeshNode*> & nodes);
+
   virtual SMDS_MeshVolume* AddPolyhedralVolumeWithID
-                           (const std::vector<int> & nodes_ids,
-                            const std::vector<int> & quantities,
-                            const int                ID);
+    (const std::vector<int> & nodes_ids,
+     const std::vector<int> & quantities,
+     const int                ID);
 
   virtual SMDS_MeshVolume* AddPolyhedralVolumeWithID
-                           (const std::vector<const SMDS_MeshNode*> & nodes,
-                            const std::vector<int>                  & quantities,
+    (const std::vector<const SMDS_MeshNode*> & nodes,
+     const std::vector<int>                  & quantities,
                             const int                                 ID);
 
   virtual SMDS_MeshVolume* AddPolyhedralVolume
index be38ce1856a801ce30a4b1ce78033c85718265e9..95438eab06489782eb060766051d2ef23861e0d2 100644 (file)
@@ -28,6 +28,8 @@
 #include "SMDS_Mesh0DElement.hxx"
 #include "SMDS_IteratorOfElements.hxx"
 #include "SMDS_MeshNode.hxx"
+#include "SMDS_Mesh.hxx"
+
 #include "utilities.h"
 
 using namespace std;
@@ -139,8 +141,24 @@ const SMDS_MeshNode* SMDS_Mesh0DElement::GetNode(const int ind) const
 //function : ChangeNode
 //purpose  :
 //=======================================================================
-bool SMDS_Mesh0DElement::ChangeNode (const SMDS_MeshNode * node)
+bool SMDS_Mesh0DElement::ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes)
 {
-  myNode = node;
-  return true;
+  if ( nbNodes == 1 )
+  {
+    vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
+    vtkIdType npts = 0;
+    vtkIdType* pts = 0;
+    grid->GetCellPoints(myVtkID, npts, pts);
+    if (nbNodes != npts)
+    {
+      MESSAGE("ChangeNodes problem: not the same number of nodes " << npts << " -> " << nbNodes);
+      return false;
+    }
+    myNode = nodes[0];
+    pts[0] = myNode->getVtkId();
+
+    SMDS_Mesh::_meshList[myMeshId]->setMyModified();
+    return true;
+  }
+  return false;
 }
index b499871dafc6c7c460ee59301ade46aa200ca9a4..d0c07696067c9a5dd3237f0c34b90f2ddcc90e10 100644 (file)
@@ -34,8 +34,7 @@ class SMDS_EXPORT SMDS_Mesh0DElement: public SMDS_MeshCell
 {
  public:
   SMDS_Mesh0DElement (const SMDS_MeshNode * node);
-  bool ChangeNode (const SMDS_MeshNode * node);
-  virtual bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes) {return false;};
+  virtual bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes);
   virtual void Print (std::ostream & OS) const;
 
   virtual SMDSAbs_ElementType  GetType() const;
index 2232f68295911ee66c8f79ac065b5744bd4fb483..e629a2f5b7a02a7e18fb5f5ba9c5889044ed34c0 100644 (file)
@@ -56,7 +56,7 @@ VTKCellType SMDS_MeshCell::toVtkType (SMDSAbs_EntityType smdsType)
     vtkTypes[ SMDSEntity_Quad_Quadrangle ]   = VTK_QUADRATIC_QUAD;
     vtkTypes[ SMDSEntity_BiQuad_Quadrangle ] = VTK_BIQUADRATIC_QUAD;
     vtkTypes[ SMDSEntity_Polygon ]           = VTK_POLYGON;
-    //vtkTypes[ SMDSEntity_Quad_Polygon ]      = ;
+    vtkTypes[ SMDSEntity_Quad_Polygon ]      = VTK_QUADRATIC_POLYGON;
     vtkTypes[ SMDSEntity_Tetra ]             = VTK_TETRA;
     vtkTypes[ SMDSEntity_Quad_Tetra ]        = VTK_QUADRATIC_TETRA;
     vtkTypes[ SMDSEntity_Pyramid ]           = VTK_PYRAMID;
@@ -166,12 +166,14 @@ const std::vector< int >& SMDS_MeshCell::toVtkOrder(SMDSAbs_EntityType smdsType)
 
 //================================================================================
 /*!
- * \brief Return indices to reverse an SMDS cell of given type
+ * \brief Return indices to reverse an SMDS cell of given type.
+ *        nbNodes is useful for polygons
  * Usage: reverseIDs[i] = forwardIDs[ indices[ i ]]
  */
 //================================================================================
 
-const std::vector<int>& SMDS_MeshCell::reverseSmdsOrder(SMDSAbs_EntityType smdsType)
+const std::vector<int>& SMDS_MeshCell::reverseSmdsOrder(SMDSAbs_EntityType smdsType,
+                                                        const size_t       nbNodes)
 {
   static std::vector< std::vector< int > > reverseInterlaces;
   if ( reverseInterlaces.empty() )
@@ -256,6 +258,31 @@ const std::vector<int>& SMDS_MeshCell::reverseSmdsOrder(SMDSAbs_EntityType smdsT
       reverseInterlaces[SMDSEntity_Hexagonal_Prism].assign( &ids[0], &ids[0]+12 );
     }
   }
+
+  if ( smdsType == SMDSEntity_Polygon )
+  {
+    if ( reverseInterlaces[ smdsType ].size() != nbNodes )
+    {
+      reverseInterlaces[ smdsType ].resize( nbNodes );
+      for ( size_t i = 0; i < nbNodes; ++i )
+        reverseInterlaces[ smdsType ][i] = nbNodes - i - 1;
+    }
+  }
+  else if ( smdsType == SMDSEntity_Quad_Polygon )
+  {
+    if ( reverseInterlaces[ smdsType ].size() != nbNodes )
+    {
+      // e.g. for 8 nodes: [ 0, 3,2,1, 7,6,5,4 ]
+      reverseInterlaces[ smdsType ].resize( nbNodes );
+      size_t pos = 0;
+      reverseInterlaces[ smdsType ][pos++] = 0;
+      for ( int i = nbNodes / 2 - 1; i > 0 ; --i ) // 3,2,1
+        reverseInterlaces[ smdsType ][pos++] = i;
+      for ( int i = nbNodes - 1; i >= nbNodes / 2; --i ) // 7,6,5,4
+        reverseInterlaces[ smdsType ][pos++] = i;
+    }
+  }
+  
   return reverseInterlaces[smdsType];
 }
 
@@ -266,7 +293,8 @@ const std::vector<int>& SMDS_MeshCell::reverseSmdsOrder(SMDSAbs_EntityType smdsT
  */
 //================================================================================
 
-const std::vector<int>& SMDS_MeshCell::interlacedSmdsOrder(SMDSAbs_EntityType smdsType)
+const std::vector<int>& SMDS_MeshCell::interlacedSmdsOrder(SMDSAbs_EntityType smdsType,
+                                                           const size_t       nbNodes)
 {
   static std::vector< std::vector< int > > interlace;
   if ( interlace.empty() )
@@ -278,15 +306,28 @@ const std::vector<int>& SMDS_MeshCell::interlacedSmdsOrder(SMDSAbs_EntityType sm
     }
     {
       const int ids[] = {0,3,1,4,2,5,6};
-      interlace[SMDSEntity_Quad_Triangle].assign( &ids[0], &ids[0]+6 );
+      interlace[SMDSEntity_Quad_Triangle  ].assign( &ids[0], &ids[0]+6 );
       interlace[SMDSEntity_BiQuad_Triangle].assign( &ids[0], &ids[0]+7 );
     }
     {
       const int ids[] = {0,4,1,5,2,6,3,7,8};
-      interlace[SMDSEntity_Quad_Quadrangle].assign( &ids[0], &ids[0]+8 );
+      interlace[SMDSEntity_Quad_Quadrangle  ].assign( &ids[0], &ids[0]+8 );
       interlace[SMDSEntity_BiQuad_Quadrangle].assign( &ids[0], &ids[0]+9 );
     }
   }
+
+  if ( smdsType == SMDSEntity_Quad_Polygon )
+  {
+    if ( interlace[smdsType].size() != nbNodes )
+    {
+      interlace[smdsType].resize( nbNodes );
+      for ( size_t i = 0; i < nbNodes / 2; ++i )
+      {
+        interlace[smdsType][i*2+0] = i;
+        interlace[smdsType][i*2+1] = i + nbNodes / 2;
+      }
+    }
+  }
   return interlace[smdsType];
 }
 
index 85cc7475e1b90f8191bfd6db02e3f97a6982df32..d56f7b5dea636bbb2a22330c23522f399f37d3c8 100644 (file)
@@ -45,10 +45,12 @@ public:
   static const std::vector<int>& fromVtkOrder(VTKCellType vtkType);
   static const std::vector<int>& fromVtkOrder(SMDSAbs_EntityType smdsType);
 
-  static const std::vector<int>& reverseSmdsOrder(SMDSAbs_EntityType smdsType);
-  static const std::vector<int>& interlacedSmdsOrder(SMDSAbs_EntityType smdsType);
+  static const std::vector<int>& reverseSmdsOrder(SMDSAbs_EntityType smdsType,
+                                                  const size_t       nbNodes=0);
+  static const std::vector<int>& interlacedSmdsOrder(SMDSAbs_EntityType smdsType,
+                                                     const size_t       nbNodes=0);
 
-  template< class VECT >
+  template< class VECT > // interlacedIDs[i] = smdsIDs[ indices[ i ]]
     static void applyInterlace( const std::vector<int>& interlace, VECT & data)
   {
     if ( interlace.empty() ) return;
@@ -57,6 +59,15 @@ public:
       tmpData[i] = data[ interlace[i] ];
     data.swap( tmpData );
   }
+  template< class VECT > // interlacedIDs[ indices[ i ]] = smdsIDs[i]
+    static void applyInterlaceRev( const std::vector<int>& interlace, VECT & data)
+  {
+    if ( interlace.empty() ) return;
+    VECT tmpData( data.size() );
+    for ( size_t i = 0; i < data.size(); ++i )
+      tmpData[ interlace[i] ] = data[i];
+    data.swap( tmpData );
+  }
 
   static int nbCells;
 
index fa49ecd24b00f9874de49edd8c70a32318282cfe..5c22d7f9b0e62016ae87f8cf77cadfa625a6ed83 100644 (file)
@@ -56,7 +56,7 @@ public:
   inline int NbQuadrangles(SMDSAbs_ElementOrder order = ORDER_ANY) const;
   int NbBiQuadTriangles() const { return myNbBiQuadTriangles; }
   int NbBiQuadQuadrangles() const { return myNbBiQuadQuadrangles; }
-  int NbPolygons() const { return myNbPolygons; }
+  inline int NbPolygons(SMDSAbs_ElementOrder order = ORDER_ANY) const;
 
   inline int NbVolumes (SMDSAbs_ElementOrder order = ORDER_ANY) const;
   inline int NbTetras  (SMDSAbs_ElementOrder order = ORDER_ANY) const;
@@ -90,7 +90,7 @@ private:
   int myNbEdges      , myNbQuadEdges      ;
   int myNbTriangles  , myNbQuadTriangles,   myNbBiQuadTriangles  ;
   int myNbQuadrangles, myNbQuadQuadrangles, myNbBiQuadQuadrangles;
-  int myNbPolygons;
+  int myNbPolygons   , myNbQuadPolygons;
 
   int myNbTetras  , myNbQuadTetras  ;
   int myNbHexas   , myNbQuadHexas,    myNbTriQuadHexas;
@@ -110,7 +110,7 @@ inline SMDS_MeshInfo::SMDS_MeshInfo():
   myNbEdges      (0), myNbQuadEdges      (0),
   myNbTriangles  (0), myNbQuadTriangles  (0), myNbBiQuadTriangles(0),
   myNbQuadrangles(0), myNbQuadQuadrangles(0), myNbBiQuadQuadrangles(0),
-  myNbPolygons   (0),
+  myNbPolygons   (0), myNbQuadPolygons   (0),
   myNbTetras     (0), myNbQuadTetras  (0),
   myNbHexas      (0), myNbQuadHexas   (0), myNbTriQuadHexas(0),
   myNbPyramids   (0), myNbQuadPyramids(0),
@@ -193,15 +193,16 @@ inline SMDS_MeshInfo::SMDS_MeshInfo():
 inline SMDS_MeshInfo& // operator=
 SMDS_MeshInfo::operator=(const SMDS_MeshInfo& other)
 { for ( int i=0; i<myNb.size(); ++i ) if ( myNb[i] ) (*myNb[i])=(*other.myNb[i]);
-  myNbPolygons = other.myNbPolygons;
-  myNbPolyhedrons = other.myNbPolyhedrons;
+  myNbPolygons     = other.myNbPolygons;
+  myNbQuadPolygons = other.myNbQuadPolygons;
+  myNbPolyhedrons  = other.myNbPolyhedrons;
   return *this;
 }
 
 inline void // Clear
 SMDS_MeshInfo::Clear()
 { for ( int i=0; i<myNb.size(); ++i ) if ( myNb[i] ) (*myNb[i])=0;
-  myNbPolygons=myNbPolyhedrons=0;
+  myNbPolygons=myNbQuadPolygons=myNbPolyhedrons=0;
 }
 
 inline int // index
@@ -217,20 +218,26 @@ SMDS_MeshInfo::add(const SMDS_MeshElement* el)
 { ++(*myNb[ index(el->GetType(), el->NbNodes()) ]); }
 
 inline void // addWithPoly
-SMDS_MeshInfo::addWithPoly(const SMDS_MeshElement* el)
-{
-  if ( el->IsPoly() )
-    ++( el->GetType()==SMDSAbs_Face ? myNbPolygons : myNbPolyhedrons );
-  else
-    add(el);
+SMDS_MeshInfo::addWithPoly(const SMDS_MeshElement* el) {
+  switch ( el->GetEntityType() ) {
+  case SMDSEntity_Polygon:      ++myNbPolygons; break;
+  case SMDSEntity_Quad_Polygon: ++myNbQuadPolygons; break;
+  case SMDSEntity_Polyhedra:    ++myNbPolyhedrons; break;
+  default:                      add(el);
+  }
 }
 inline void // RemoveEdge
 SMDS_MeshInfo::RemoveEdge(const SMDS_MeshElement* el)
 { if ( el->IsQuadratic() ) --myNbQuadEdges; else --myNbEdges; }
 
 inline void // RemoveFace
-SMDS_MeshInfo::RemoveFace(const SMDS_MeshElement* el)
-{ if ( el->IsPoly() ) --myNbPolygons; else remove( el ); }
+SMDS_MeshInfo::RemoveFace(const SMDS_MeshElement* el) {
+  switch ( el->GetEntityType() ) {
+  case SMDSEntity_Polygon:      --myNbPolygons; break;
+  case SMDSEntity_Quad_Polygon: --myNbQuadPolygons; break;
+  default:                      remove(el);
+  }
+}
 
 inline void // RemoveVolume
 SMDS_MeshInfo::RemoveVolume(const SMDS_MeshElement* el)
@@ -242,7 +249,7 @@ SMDS_MeshInfo::NbEdges      (SMDSAbs_ElementOrder order) const
 
 inline int  // NbFaces
 SMDS_MeshInfo::NbFaces      (SMDSAbs_ElementOrder order) const
-{ return NbTriangles(order)+NbQuadrangles(order)+(order == ORDER_QUADRATIC ? 0 : myNbPolygons); }
+{ return NbTriangles(order)+NbQuadrangles(order)+(order == ORDER_ANY ? myNbPolygons+myNbQuadPolygons : order == ORDER_LINEAR ? myNbPolygons : myNbQuadPolygons ); }
 
 inline int  // NbTriangles
 SMDS_MeshInfo::NbTriangles  (SMDSAbs_ElementOrder order) const
@@ -252,6 +259,10 @@ inline int  // NbQuadrangles
 SMDS_MeshInfo::NbQuadrangles(SMDSAbs_ElementOrder order) const
 { return order == ORDER_ANY ? myNbQuadrangles+myNbQuadQuadrangles+myNbBiQuadQuadrangles : order == ORDER_LINEAR ? myNbQuadrangles : myNbQuadQuadrangles+myNbBiQuadQuadrangles; }
 
+inline int  // NbPolygons
+SMDS_MeshInfo::NbPolygons(SMDSAbs_ElementOrder order) const
+{ return order == ORDER_ANY ? myNbPolygons+myNbQuadPolygons : order == ORDER_LINEAR ? myNbPolygons : myNbQuadPolygons; }
+
 inline int  // NbVolumes
 SMDS_MeshInfo::NbVolumes (SMDSAbs_ElementOrder order) const
 { return NbTetras(order) + NbHexas(order) + NbPyramids(order) + NbPrisms(order) + NbHexPrisms(order) + (order == ORDER_QUADRATIC ? 0 : myNbPolyhedrons); }
@@ -283,7 +294,7 @@ SMDS_MeshInfo::NbElements(SMDSAbs_ElementType type) const
   switch (type) {
   case SMDSAbs_All:
     for ( int i=1+index( SMDSAbs_Node,1 ); i<myNb.size(); ++i ) if ( myNb[i] ) nb += *myNb[i];
-    nb += myNbPolygons + myNbPolyhedrons;
+    nb += myNbPolygons + myNbQuadPolygons + myNbPolyhedrons;
     break;
   case SMDSAbs_Volume:
     nb = ( myNbTetras+     myNbPyramids+     myNbPrisms+     myNbHexas+     myNbHexPrism+
@@ -293,7 +304,7 @@ SMDS_MeshInfo::NbElements(SMDSAbs_ElementType type) const
   case SMDSAbs_Face:
     nb = ( myNbTriangles+       myNbQuadrangles+
            myNbQuadTriangles+   myNbBiQuadTriangles+
-           myNbQuadQuadrangles+ myNbBiQuadQuadrangles+ myNbPolygons );
+           myNbQuadQuadrangles+ myNbBiQuadQuadrangles+ myNbPolygons+ myNbQuadPolygons );
     break;
   case SMDSAbs_Edge:
     nb = myNbEdges + myNbQuadEdges;
@@ -339,7 +350,7 @@ SMDS_MeshInfo::NbEntities(SMDSAbs_EntityType type) const
   case SMDSEntity_Polyhedra:        return myNbPolyhedrons;
   case SMDSEntity_0D:               return myNb0DElements;
   case SMDSEntity_Ball:             return myNbBalls;
-  case SMDSEntity_Quad_Polygon:
+  case SMDSEntity_Quad_Polygon:     return myNbQuadPolygons;
   case SMDSEntity_Quad_Polyhedra:
     break;
   }
@@ -362,7 +373,7 @@ SMDS_MeshInfo::NbElementsOfGeom(SMDSAbs_GeometryType geom) const
   case SMDSGeom_QUADRANGLE:      return (myNbQuadrangles +
                                          myNbQuadQuadrangles +
                                          myNbBiQuadQuadrangles );
-  case SMDSGeom_POLYGON:         return myNbPolygons;
+  case SMDSGeom_POLYGON:         return (myNbPolygons + myNbQuadPolygons );
     // 3D:
   case SMDSGeom_TETRA:           return (myNbTetras +
                                          myNbQuadTetras);
@@ -411,7 +422,7 @@ SMDS_MeshInfo::setNb(const SMDSAbs_EntityType geomType, const int nb)
   case SMDSEntity_Tetra:            myNbTetras            = nb; break;
   case SMDSEntity_TriQuad_Hexa:     myNbTriQuadHexas      = nb; break;
   case SMDSEntity_Triangle:         myNbTriangles         = nb; break;
-  case SMDSEntity_Quad_Polygon:
+  case SMDSEntity_Quad_Polygon:     myNbQuadPolygons      = nb; break;
   case SMDSEntity_Quad_Polyhedra:
     break;
   }
index 3bd528bb766e2a5087596d7a1a5808e8605da430..3524480cca6644fcc349cd9888dbc19cfa1eea96 100644 (file)
@@ -42,7 +42,7 @@ int SMDS_MeshNode::nbNodes =0;
 
 //=======================================================================
 //function : SMDS_MeshNode
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMDS_MeshNode::SMDS_MeshNode() :
   SMDS_MeshElement(-1, -1, 0),
@@ -83,31 +83,31 @@ SMDS_MeshNode::~SMDS_MeshNode()
 
 //=======================================================================
 //function : RemoveInverseElement
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 void SMDS_MeshNode::RemoveInverseElement(const SMDS_MeshElement * parent)
 {
-    //MESSAGE("RemoveInverseElement " << myID << " " << parent->GetID());
-    const SMDS_MeshCell* cell = dynamic_cast<const SMDS_MeshCell*>(parent);
-    MYASSERT(cell);
-    SMDS_Mesh::_meshList[myMeshId]->getGrid()->RemoveReferenceToCell(myVtkID, cell->getVtkId());
+  //MESSAGE("RemoveInverseElement " << myID << " " << parent->GetID());
+  const SMDS_MeshCell* cell = dynamic_cast<const SMDS_MeshCell*>(parent);
+  MYASSERT(cell);
+  SMDS_Mesh::_meshList[myMeshId]->getGrid()->RemoveReferenceToCell(myVtkID, cell->getVtkId());
 }
 
 //=======================================================================
 //function : Print
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 void SMDS_MeshNode::Print(ostream & OS) const
 {
-        OS << "Node <" << myID << "> : X = " << X() << " Y = "
-                << Y() << " Z = " << Z() << endl;
+  OS << "Node <" << myID << "> : X = " << X() << " Y = "
+     << Y() << " Z = " << Z() << endl;
 }
 
 //=======================================================================
 //function : SetPosition
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 void SMDS_MeshNode::SetPosition(const SMDS_PositionPtr& aPos)
@@ -121,7 +121,7 @@ void SMDS_MeshNode::SetPosition(const SMDS_PositionPtr& aPos)
 
 //=======================================================================
 //function : GetPosition
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 const SMDS_PositionPtr& SMDS_MeshNode::GetPosition() const
@@ -178,10 +178,10 @@ public:
     int smdsId = myMesh->fromVtkToSmds(vtkId);
     const SMDS_MeshElement* elem = myMesh->FindElement(smdsId);
     if (!elem)
-      {
-        MESSAGE("SMDS_MeshNode_MyInvIterator problem Null element");
-        throw SALOME_Exception("SMDS_MeshNode_MyInvIterator problem Null element");
-      }
+    {
+      MESSAGE("SMDS_MeshNode_MyInvIterator problem Null element");
+      throw SALOME_Exception("SMDS_MeshNode_MyInvIterator problem Null element");
+    }
     //MESSAGE("vtkId " << vtkId << " smdsId " << smdsId << " " << elem->GetType());
     iter++;
     return elem;
@@ -189,11 +189,11 @@ public:
 };
 
 SMDS_ElemIteratorPtr SMDS_MeshNode::
-        GetInverseElementIterator(SMDSAbs_ElementType type) const
+GetInverseElementIterator(SMDSAbs_ElementType type) const
 {
-    vtkCellLinks::Link l = SMDS_Mesh::_meshList[myMeshId]->getGrid()->GetCellLinks()->GetLink(myVtkID);
-    //MESSAGE("myID " << myID << " ncells " << l.ncells);
-    return SMDS_ElemIteratorPtr(new SMDS_MeshNode_MyInvIterator(SMDS_Mesh::_meshList[myMeshId], l.cells, l.ncells, type));
+  vtkCellLinks::Link l = SMDS_Mesh::_meshList[myMeshId]->getGrid()->GetCellLinks()->GetLink(myVtkID);
+  //MESSAGE("myID " << myID << " ncells " << l.ncells);
+  return SMDS_ElemIteratorPtr(new SMDS_MeshNode_MyInvIterator(SMDS_Mesh::_meshList[myMeshId], l.cells, l.ncells, type));
 }
 
 // Same as GetInverseElementIterator but the create iterator only return
@@ -208,47 +208,47 @@ private:
   int  iter;
   vector<SMDS_MeshElement*> myFiltCells;
 
- public:
+public:
   SMDS_MeshNode_MyIterator(SMDS_Mesh *mesh,
                            vtkIdType* cells,
                            int ncells,
                            SMDSAbs_ElementType type):
     myMesh(mesh), myCells(cells), myNcells(ncells), myType(type), iter(0)
   {
-        //MESSAGE("myNcells " << myNcells);
-       for (; iter<ncells; iter++)
-        {
-           int vtkId = myCells[iter];
-           int smdsId = myMesh->fromVtkToSmds(vtkId);
-           //MESSAGE("vtkId " << vtkId << " smdsId " << smdsId);
-           const SMDS_MeshElement* elem = myMesh->FindElement(smdsId);
-           if (elem->GetType() == type)
-               myFiltCells.push_back((SMDS_MeshElement*)elem);
-        }
-        myNcells = myFiltCells.size();
-        //MESSAGE("myNcells " << myNcells);
-       iter = 0;
-        //MESSAGE("SMDS_MeshNode_MyIterator (filter) " << ncells << " " << myNcells);
+    //MESSAGE("myNcells " << myNcells);
+    for (; iter<ncells; iter++)
+    {
+      int vtkId = myCells[iter];
+      int smdsId = myMesh->fromVtkToSmds(vtkId);
+      //MESSAGE("vtkId " << vtkId << " smdsId " << smdsId);
+      const SMDS_MeshElement* elem = myMesh->FindElement(smdsId);
+      if (elem->GetType() == type)
+        myFiltCells.push_back((SMDS_MeshElement*)elem);
+    }
+    myNcells = myFiltCells.size();
+    //MESSAGE("myNcells " << myNcells);
+    iter = 0;
+    //MESSAGE("SMDS_MeshNode_MyIterator (filter) " << ncells << " " << myNcells);
   }
 
   bool more()
   {
-      return (iter< myNcells);
+    return (iter< myNcells);
   }
 
   const SMDS_MeshElement* next()
   {
-      const SMDS_MeshElement* elem = myFiltCells[iter];
-      iter++;
-      return elem;
+    const SMDS_MeshElement* elem = myFiltCells[iter];
+    iter++;
+    return elem;
   }
 };
 
 SMDS_ElemIteratorPtr SMDS_MeshNode::
-        elementsIterator(SMDSAbs_ElementType type) const
+elementsIterator(SMDSAbs_ElementType type) const
 {
   if(type==SMDSAbs_Node)
-    return SMDS_MeshElement::elementsIterator(SMDSAbs_Node); 
+    return SMDS_MeshElement::elementsIterator(SMDSAbs_Node);
   else
   {
     vtkCellLinks::Link l = SMDS_Mesh::_meshList[myMeshId]->getGrid()->GetCellLinks()->GetLink(myVtkID);
@@ -258,7 +258,7 @@ SMDS_ElemIteratorPtr SMDS_MeshNode::
 
 int SMDS_MeshNode::NbNodes() const
 {
-        return 1;
+  return 1;
 }
 
 double* SMDS_MeshNode::getCoord() const
@@ -305,7 +305,7 @@ void SMDS_MeshNode::setXYZ(double x, double y, double z)
 
 SMDSAbs_ElementType SMDS_MeshNode::GetType() const
 {
-        return SMDSAbs_Node;
+  return SMDSAbs_Node;
 }
 
 vtkIdType SMDS_MeshNode::GetVtkType() const
@@ -358,11 +358,11 @@ int SMDS_MeshNode::NbInverseElements(SMDSAbs_ElementType type) const
   int nb = 0;
   SMDS_Mesh *mesh = SMDS_Mesh::_meshList[myMeshId];
   for (int i=0; i<l.ncells; i++)
-        {
-           const SMDS_MeshElement* elem = mesh->FindElement(mesh->fromVtkToSmds(l.cells[i]));
-           if (elem->GetType() == type)
-                nb++;
-        }
+  {
+    const SMDS_MeshElement* elem = mesh->FindElement(mesh->fromVtkToSmds(l.cells[i]));
+    if (elem->GetType() == type)
+      nb++;
+  }
   return nb;
 }
 
@@ -371,14 +371,14 @@ int SMDS_MeshNode::NbInverseElements(SMDSAbs_ElementType type) const
 ///////////////////////////////////////////////////////////////////////////////
 bool operator<(const SMDS_MeshNode& e1, const SMDS_MeshNode& e2)
 {
-        return e1.getVtkId()<e2.getVtkId();
-        /*if(e1.myX<e2.myX) return true;
-        else if(e1.myX==e2.myX)
-        {
-                if(e1.myY<e2.myY) return true;
-                else if(e1.myY==e2.myY) return (e1.myZ<e2.myZ);
-                else return false;
-        }
-        else return false;*/
+  return e1.getVtkId()<e2.getVtkId();
+  /*if(e1.myX<e2.myX) return true;
+    else if(e1.myX==e2.myX)
+    {
+    if(e1.myY<e2.myY) return true;
+    else if(e1.myY==e2.myY) return (e1.myZ<e2.myZ);
+    else return false;
+    }
+    else return false;*/
 }
 
index 5bc6aa1e9e36740a1632643d8683eb6cea5adbd9..f291b0bff1b150aa6f71d4cbc5b61da040fce562 100644 (file)
@@ -41,7 +41,7 @@ using namespace std;
 //purpose  : 
 //=======================================================================
 SMDS_PolygonalFaceOfNodes::SMDS_PolygonalFaceOfNodes
-                          (std::vector<const SMDS_MeshNode *> nodes)
+                          (const std::vector<const SMDS_MeshNode *>& nodes)
 {
   //MESSAGE("******************************************** SMDS_PolygonalFaceOfNodes");
   myNodes = nodes;
index ba15f67ac0a51005a64327cc87edaf4992c86fb8..bf6a1a5ff21abb092ae1bef5af94e88ee217731b 100644 (file)
@@ -38,7 +38,7 @@
 class SMDS_EXPORT SMDS_PolygonalFaceOfNodes:public SMDS_MeshFace
 {
  public:
-  SMDS_PolygonalFaceOfNodes (std::vector<const SMDS_MeshNode *> nodes);
+  SMDS_PolygonalFaceOfNodes (const std::vector<const SMDS_MeshNode *>& nodes);
 
   virtual SMDSAbs_ElementType GetType() const;
   virtual SMDSAbs_EntityType  GetEntityType() const { return SMDSEntity_Polygon; }
index 001387c5f4daa5b10efcb231c31277645c5cc80d..c0c506d9cc13ba79e607cbf392d6f612bd1cd4e2 100644 (file)
 #include <map>
 #include <limits>
 #include <cmath>
+#include <numeric>
+#include <algorithm>
 
 using namespace std;
 
+namespace
+{
 // ======================================================
 // Node indices in faces depending on volume orientation
 // making most faces normals external
@@ -349,8 +353,6 @@ static int TriQuadHexa_nbN [] = { 9, 9, 9, 9, 9, 9 };
 // ========================================================
 // to perform some calculations without linkage to CASCADE
 // ========================================================
-namespace
-{
 struct XYZ {
   double x;
   double y;
@@ -396,7 +398,7 @@ inline double XYZ::SquareMagnitude() {
   SMDS_VolumeTool::VolumeType quadToLinear(SMDS_VolumeTool::VolumeType quadType)
   {
     SMDS_VolumeTool::VolumeType linType = SMDS_VolumeTool::VolumeType( int(quadType)-4 );
-    const int nbCornersByQuad = SMDS_VolumeTool::NbCornerNodes( quadType );
+    const int           nbCornersByQuad = SMDS_VolumeTool::NbCornerNodes( quadType );
     if ( SMDS_VolumeTool::NbCornerNodes( linType ) == nbCornersByQuad )
       return linType;
 
@@ -410,14 +412,33 @@ inline double XYZ::SquareMagnitude() {
 
 } // namespace
 
+//================================================================================
+/*!
+ * \brief Saver/restorer of a SMDS_VolumeTool::myCurFace
+ */
+//================================================================================
+
+struct SMDS_VolumeTool::SaveFacet
+{
+  SMDS_VolumeTool::Facet  mySaved;
+  SMDS_VolumeTool::Facet& myToRestore;
+  SaveFacet( SMDS_VolumeTool::Facet& facet ): myToRestore( facet )
+  {
+    mySaved = facet;
+  }
+  ~SaveFacet()
+  {
+    if ( myToRestore.myIndex != mySaved.myIndex )
+      myToRestore = mySaved;
+  }
+};
+
 //=======================================================================
 //function : SMDS_VolumeTool
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 SMDS_VolumeTool::SMDS_VolumeTool ()
-  : myVolumeNodes( NULL ),
-    myFaceNodes( NULL )
 {
   Set( 0 );
 }
@@ -429,8 +450,6 @@ SMDS_VolumeTool::SMDS_VolumeTool ()
 
 SMDS_VolumeTool::SMDS_VolumeTool (const SMDS_MeshElement* theVolume,
                                   const bool              ignoreCentralNodes)
-  : myVolumeNodes( NULL ),
-    myFaceNodes( NULL )
 {
   Set( theVolume, ignoreCentralNodes );
 }
@@ -442,11 +461,7 @@ SMDS_VolumeTool::SMDS_VolumeTool (const SMDS_MeshElement* theVolume,
 
 SMDS_VolumeTool::~SMDS_VolumeTool()
 {
-  if ( myVolumeNodes != NULL ) delete [] myVolumeNodes;
-  if ( myFaceNodes != NULL   ) delete [] myFaceNodes;
-
-  myFaceNodeIndices = NULL;
-  myVolumeNodes = myFaceNodes = NULL;
+  myCurFace.myNodeIndices = NULL;
 }
 
 //=======================================================================
@@ -464,42 +479,37 @@ bool SMDS_VolumeTool::Set (const SMDS_MeshElement* theVolume,
 
   myVolForward = true;
   myNbFaces = 0;
-  myVolumeNbNodes = 0;
-  if (myVolumeNodes != NULL) {
-    delete [] myVolumeNodes;
-    myVolumeNodes = NULL;
-  }
+  myVolumeNodes.clear();
   myPolyIndices.clear();
+  myPolyQuantities.clear();
+  myPolyFacetOri.clear();
+  myFwdLinks.clear();
 
   myExternalFaces = false;
 
   myAllFacesNodeIndices_F  = 0;
-  //myAllFacesNodeIndices_FE = 0;
   myAllFacesNodeIndices_RE = 0;
   myAllFacesNbNodes        = 0;
 
-  myCurFace = -1;
-  myFaceNbNodes = 0;
-  myFaceNodeIndices = NULL;
-  if (myFaceNodes != NULL) {
-    delete [] myFaceNodes;
-    myFaceNodes = NULL;
-  }
+  myCurFace.myIndex = -1;
+  myCurFace.myNodeIndices = NULL;
+  myCurFace.myNodes.clear();
 
   // set volume data
   if ( !theVolume || theVolume->GetType() != SMDSAbs_Volume )
     return false;
 
   myVolume = theVolume;
-  if (myVolume->IsPoly())
-    myPolyedre = dynamic_cast<const SMDS_VtkVolume*>( myVolume );
-
   myNbFaces = theVolume->NbFaces();
-  myVolumeNbNodes = theVolume->NbNodes();
+  if ( myVolume->IsPoly() )
+  {
+    myPolyedre = dynamic_cast<const SMDS_VtkVolume*>( myVolume );
+    myPolyFacetOri.resize( myNbFaces, 0 );
+  }
 
   // set nodes
   int iNode = 0;
-  myVolumeNodes = new const SMDS_MeshNode* [myVolumeNbNodes];
+  myVolumeNodes.resize( myVolume->NbNodes() );
   SMDS_ElemIteratorPtr nodeIt = myVolume->nodesIterator();
   while ( nodeIt->more() )
     myVolumeNodes[ iNode++ ] = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
@@ -512,18 +522,19 @@ bool SMDS_VolumeTool::Set (const SMDS_MeshElement* theVolume,
   {
     // define volume orientation
     XYZ botNormal;
-    GetFaceNormal( 0, botNormal.x, botNormal.y, botNormal.z );
-    const SMDS_MeshNode* botNode = myVolumeNodes[ 0 ];
-    int topNodeIndex = myVolume->NbCornerNodes() - 1;
-    while ( !IsLinked( 0, topNodeIndex, /*ignoreMediumNodes=*/true )) --topNodeIndex;
-    const SMDS_MeshNode* topNode = myVolumeNodes[ topNodeIndex ];
-    XYZ upDir (topNode->X() - botNode->X(),
-               topNode->Y() - botNode->Y(),
-               topNode->Z() - botNode->Z() );
-    myVolForward = ( botNormal.Dot( upDir ) < 0 );
-
+    if ( GetFaceNormal( 0, botNormal.x, botNormal.y, botNormal.z ))
+    {
+      const SMDS_MeshNode* botNode = myVolumeNodes[ 0 ];
+      int topNodeIndex = myVolume->NbCornerNodes() - 1;
+      while ( !IsLinked( 0, topNodeIndex, /*ignoreMediumNodes=*/true )) --topNodeIndex;
+      const SMDS_MeshNode* topNode = myVolumeNodes[ topNodeIndex ];
+      XYZ upDir (topNode->X() - botNode->X(),
+                 topNode->Y() - botNode->Y(),
+                 topNode->Z() - botNode->Z() );
+      myVolForward = ( botNormal.Dot( upDir ) < 0 );
+    }
     if ( !myVolForward )
-      myCurFace = -1; // previous setFace(0) didn't take myVolForward into account
+      myCurFace.myIndex = -1; // previous setFace(0) didn't take myVolForward into account
   }
   return true;
 }
@@ -549,10 +560,10 @@ void SMDS_VolumeTool::Inverse ()
   }
 
   myVolForward = !myVolForward;
-  myCurFace = -1;
+  myCurFace.myIndex = -1;
 
   // inverse top and bottom faces
-  switch ( myVolumeNbNodes ) {
+  switch ( myVolumeNodes.size() ) {
   case 4:
     SWAP_NODES( myVolumeNodes, 1, 2 );
     break;
@@ -626,7 +637,7 @@ SMDS_VolumeTool::VolumeType SMDS_VolumeTool::GetVolumeType() const
   if ( myPolyedre )
     return POLYHEDA;
 
-  switch( myVolumeNbNodes ) {
+  switch( myVolumeNodes.size() ) {
   case 4: return TETRA;
   case 5: return PYRAM;
   case 6: return PENTA;
@@ -653,28 +664,18 @@ static double getTetraVolume(const SMDS_MeshNode* n1,
                              const SMDS_MeshNode* n3,
                              const SMDS_MeshNode* n4)
 {
-  double X1 = n1->X();
-  double Y1 = n1->Y();
-  double Z1 = n1->Z();
-
-  double X2 = n2->X();
-  double Y2 = n2->Y();
-  double Z2 = n2->Z();
-
-  double X3 = n3->X();
-  double Y3 = n3->Y();
-  double Z3 = n3->Z();
-
-  double X4 = n4->X();
-  double Y4 = n4->Y();
-  double Z4 = n4->Z();
-
-  double Q1 = -(X1-X2)*(Y3*Z4-Y4*Z3);
-  double Q2 =  (X1-X3)*(Y2*Z4-Y4*Z2);
-  double R1 = -(X1-X4)*(Y2*Z3-Y3*Z2);
-  double R2 = -(X2-X3)*(Y1*Z4-Y4*Z1);
-  double S1 =  (X2-X4)*(Y1*Z3-Y3*Z1);
-  double S2 = -(X3-X4)*(Y1*Z2-Y2*Z1);
+  double p1[3], p2[3], p3[3], p4[3];
+  n1->GetXYZ( p1 );
+  n2->GetXYZ( p2 );
+  n3->GetXYZ( p3 );
+  n4->GetXYZ( p4 );
+
+  double Q1 = -(p1[ 0 ]-p2[ 0 ])*(p3[ 1 ]*p4[ 2 ]-p4[ 1 ]*p3[ 2 ]);
+  double Q2 =  (p1[ 0 ]-p3[ 0 ])*(p2[ 1 ]*p4[ 2 ]-p4[ 1 ]*p2[ 2 ]);
+  double R1 = -(p1[ 0 ]-p4[ 0 ])*(p2[ 1 ]*p3[ 2 ]-p3[ 1 ]*p2[ 2 ]);
+  double R2 = -(p2[ 0 ]-p3[ 0 ])*(p1[ 1 ]*p4[ 2 ]-p4[ 1 ]*p1[ 2 ]);
+  double S1 =  (p2[ 0 ]-p4[ 0 ])*(p1[ 1 ]*p3[ 2 ]-p3[ 1 ]*p1[ 2 ]);
+  double S2 = -(p3[ 0 ]-p4[ 0 ])*(p1[ 1 ]*p2[ 2 ]-p2[ 1 ]*p1[ 2 ]);
 
   return (Q1+Q2+R1+R2+S1+S2)/6.0;
 }
@@ -697,23 +698,21 @@ double SMDS_VolumeTool::GetSize() const
 
     // split a polyhedron into tetrahedrons
 
-    int saveCurFace = myCurFace;
+    SaveFacet savedFacet( myCurFace );
     SMDS_VolumeTool* me = const_cast< SMDS_VolumeTool* > ( this );
     for ( int f = 0; f < NbFaces(); ++f )
     {
       me->setFace( f );
-      XYZ area (0,0,0), p1( myFaceNodes[0] );
-      for ( int n = 0; n < myFaceNbNodes; ++n )
+      XYZ area (0,0,0), p1( myCurFace.myNodes[0] );
+      for ( int n = 0; n < myCurFace.myNbNodes; ++n )
       {
-        XYZ p2( myFaceNodes[ n+1 ]);
+        XYZ p2( myCurFace.myNodes[ n+1 ]);
         area = area + p1.Crossed( p2 );
         p1 = p2;
       }
       V += p1.Dot( area );
     }
     V /= 6;
-    if ( saveCurFace > -1 && saveCurFace != myCurFace )
-      me->setFace( myCurFace );
   }
   else 
   {
@@ -844,14 +843,14 @@ bool SMDS_VolumeTool::GetBaryCenter(double & X, double & Y, double & Z) const
   if ( !myVolume )
     return false;
 
-  for ( int i = 0; i < myVolumeNbNodes; i++ ) {
+  for ( int i = 0; i < myVolumeNodes.size(); i++ ) {
     X += myVolumeNodes[ i ]->X();
     Y += myVolumeNodes[ i ]->Y();
     Z += myVolumeNodes[ i ]->Z();
   }
-  X /= myVolumeNbNodes;
-  Y /= myVolumeNbNodes;
-  Z /= myVolumeNbNodes;
+  X /= myVolumeNodes.size();
+  Y /= myVolumeNodes.size();
+  Z /= myVolumeNodes.size();
 
   return true;
 }
@@ -875,7 +874,7 @@ bool SMDS_VolumeTool::IsOut(double X, double Y, double Z, double tol) const
     if ( !IsFaceExternal( iF ))
       faceNormal = XYZ() - faceNormal; // reverse
 
-    XYZ face2p( p - XYZ( myFaceNodes[0] ));
+    XYZ face2p( p - XYZ( myCurFace.myNodes[0] ));
     if ( face2p.Dot( faceNormal ) > tol )
       return true;
   }
@@ -890,7 +889,7 @@ bool SMDS_VolumeTool::IsOut(double X, double Y, double Z, double tol) const
 void SMDS_VolumeTool::SetExternalNormal ()
 {
   myExternalFaces = true;
-  myCurFace = -1;
+  myCurFace.myIndex = -1;
 }
 
 //=======================================================================
@@ -900,9 +899,9 @@ void SMDS_VolumeTool::SetExternalNormal ()
 
 int SMDS_VolumeTool::NbFaceNodes( int faceIndex ) const
 {
-    if ( !setFace( faceIndex ))
-      return 0;
-    return myFaceNbNodes;
+  if ( !setFace( faceIndex ))
+    return 0;
+  return myCurFace.myNbNodes;
 }
 
 //=======================================================================
@@ -917,7 +916,7 @@ const SMDS_MeshNode** SMDS_VolumeTool::GetFaceNodes( int faceIndex ) const
 {
   if ( !setFace( faceIndex ))
     return 0;
-  return myFaceNodes;
+  return &myCurFace.myNodes[0];
 }
 
 //=======================================================================
@@ -933,15 +932,7 @@ const int* SMDS_VolumeTool::GetFaceNodesIndices( int faceIndex ) const
   if ( !setFace( faceIndex ))
     return 0;
 
-  if (myPolyedre)
-  {
-    SMDS_VolumeTool* me = const_cast< SMDS_VolumeTool* > ( this );
-    me->myPolyIndices.resize( myFaceNbNodes + 1 );
-    me->myFaceNodeIndices = & me->myPolyIndices[0];
-    for ( int i = 0; i <= myFaceNbNodes; ++i )
-      me->myFaceNodeIndices[i] = myVolume->GetNodeIndex( myFaceNodes[i] );
-  }
-  return myFaceNodeIndices;
+  return myCurFace.myNodeIndices;
 }
 
 //=======================================================================
@@ -956,11 +947,44 @@ bool SMDS_VolumeTool::GetFaceNodes (int                        faceIndex,
     return false;
 
   theFaceNodes.clear();
-  theFaceNodes.insert( myFaceNodes, myFaceNodes + myFaceNbNodes );
+  theFaceNodes.insert( myCurFace.myNodes.begin(), myCurFace.myNodes.end() );
 
   return true;
 }
 
+namespace
+{
+  struct NLink : public std::pair<int,int>
+  {
+    int myOri;
+    NLink(const SMDS_MeshNode* n1=0, const SMDS_MeshNode* n2=0, int ori=1 )
+    {
+      if ( n1 )
+      {
+        if (( myOri = ( n1->GetID() < n2->GetID() )))
+        {
+          first  = n1->GetID();
+          second = n2->GetID();
+        }
+        else
+        {
+          myOri  = -1;
+          first  = n2->GetID();
+          second = n1->GetID();
+        }
+        myOri *= ori;
+      }
+      else
+      {
+        myOri = first = second = 0;
+      }
+    }
+    //int Node1() const { return myOri == -1 ? second : first; }
+
+    //bool IsSameOri( const std::pair<int,int>& link ) const { return link.first == Node1(); }
+  };
+}
+
 //=======================================================================
 //function : IsFaceExternal
 //purpose  : Check normal orientation of a given face
@@ -971,39 +995,179 @@ bool SMDS_VolumeTool::IsFaceExternal( int faceIndex ) const
   if ( myExternalFaces || !myVolume )
     return true;
 
-  if (myVolume->IsPoly()) {
-    XYZ aNormal, baryCenter, p0 (myPolyedre->GetFaceNode(faceIndex + 1, 1));
-    GetFaceNormal(faceIndex, aNormal.x, aNormal.y, aNormal.z);
-    GetBaryCenter(baryCenter.x, baryCenter.y, baryCenter.z);
-    XYZ insideVec (baryCenter - p0);
-    if (insideVec.Dot(aNormal) > 0)
-      return false;
+  if ( !myPolyedre ) // all classical volumes have external facet normals
     return true;
+
+  SMDS_VolumeTool* me = const_cast< SMDS_VolumeTool* >( this );
+
+  if ( myPolyFacetOri[ faceIndex ])
+    return myPolyFacetOri[ faceIndex ] > 0;
+
+  int ori = 0; // -1-in, +1-out, 0-undef
+  double minProj, maxProj;
+  if ( projectNodesToNormal( faceIndex, minProj, maxProj ))
+  {
+    // all nodes are on the same side of the facet
+    ori = ( minProj < 0 ? +1 : -1 );
+    me->myPolyFacetOri[ faceIndex ] = ori;
+
+    if ( !myFwdLinks.empty() ) // concave polyhedron; collect oriented links
+      for ( int i = 0; i < myCurFace.myNbNodes; ++i )
+      {
+        NLink link( myCurFace.myNodes[i], myCurFace.myNodes[i+1], ori );
+        me->myFwdLinks.insert( make_pair( link, link.myOri ));
+      }
+    return ori > 0;
   }
 
-  // switch ( myVolumeNbNodes ) {
-  // case 4:
-  // case 5:
-  // case 10:
-  // case 13:
-  //   // only the bottom of a reversed tetrahedron can be internal
-  //   return ( myVolForward || faceIndex != 0 );
-  // case 6:
-  // case 15:
-  // case 12:
-  //   // in a forward prism, the top is internal, in a reversed one - bottom
-  //   return ( myVolForward ? faceIndex != 1 : faceIndex != 0 );
-  // case 8:
-  // case 20:
-  // case 27: {
-  //   // in a forward hexahedron, even face normal is external, odd - internal
-  //   bool odd = faceIndex % 2;
-  //   return ( myVolForward ? !odd : odd );
+  SaveFacet savedFacet( myCurFace );
+
+  // concave polyhedron
+
+  if ( myFwdLinks.empty() ) // get links of the least ambiguously oriented facet
+  {
+    for ( size_t i = 0; i < myPolyFacetOri.size() && !ori; ++i )
+      ori = myPolyFacetOri[ i ];
+
+    if ( !ori ) // none facet is oriented yet
+    {
+      // find the least ambiguously oriented facet
+      int faceMostConvex = -1;
+      std::map< double, int > convexity2face;
+      for ( size_t iF = 0; iF < myPolyFacetOri.size() && faceMostConvex < 0; ++iF )
+      {
+        if ( projectNodesToNormal( iF, minProj, maxProj ))
+        {
+          // all nodes are on the same side of the facet
+          me->myPolyFacetOri[ iF ] = ( minProj < 0 ? +1 : -1 );
+          faceMostConvex = iF;
+        }
+        else
+        {
+          ori = ( -minProj < maxProj ? -1 : +1 );
+          double convexity = std::min( -minProj, maxProj ) / std::max( -minProj, maxProj );
+          convexity2face.insert( make_pair( convexity, iF * ori ));
+        }
+      }
+      if ( faceMostConvex < 0 ) // none facet has nodes on the same side
+      {
+        // use the least ambiguous facet
+        faceMostConvex = convexity2face.begin()->second;
+        ori = ( faceMostConvex < 0 ? -1 : +1 );
+        faceMostConvex = std::abs( faceMostConvex );
+        me->myPolyFacetOri[ faceMostConvex ] = ori;
+      }
+    }
+    // collect links of the oriented facets in myFwdLinks
+    for ( size_t iF = 0; iF < myPolyFacetOri.size(); ++iF )
+    {
+      ori = myPolyFacetOri[ iF ];
+      if ( !ori ) continue;
+      setFace( iF );
+      for ( int i = 0; i < myCurFace.myNbNodes; ++i )
+      {
+        NLink link( myCurFace.myNodes[i], myCurFace.myNodes[i+1], ori );
+        me->myFwdLinks.insert( make_pair( link, link.myOri ));
+      }
+    }
+  }
+
+  // compare orientation of links of the facet with myFwdLinks
+  ori = 0;
+  setFace( faceIndex );
+  vector< NLink > links( myCurFace.myNbNodes ), links2;
+  for ( int i = 0; i < myCurFace.myNbNodes && !ori; ++i )
+  {
+    NLink link( myCurFace.myNodes[i], myCurFace.myNodes[i+1] );
+    std::map<Link, int>::const_iterator l2o = myFwdLinks.find( link );
+    if ( l2o != myFwdLinks.end() )
+      ori = link.myOri * l2o->second * -1;
+    links[ i ] = link;
+  }
+  while ( !ori ) // the facet has no common links with already oriented facets
+  {
+    // orient and collect links of other non-oriented facets
+    for ( size_t iF = 0; iF < myPolyFacetOri.size(); ++iF )
+    {
+      if ( myPolyFacetOri[ iF ] ) continue; // already oriented
+      setFace( iF );
+      links2.clear();
+      ori = 0;
+      for ( int i = 0; i < myCurFace.myNbNodes && !ori; ++i )
+      {
+        NLink link( myCurFace.myNodes[i], myCurFace.myNodes[i+1] );
+        std::map<Link, int>::const_iterator l2o = myFwdLinks.find( link );
+        if ( l2o != myFwdLinks.end() )
+          ori = link.myOri * l2o->second * -1;
+        links2.push_back( link );
+      }
+      if ( ori ) // one more facet oriented
+      {
+        me->myPolyFacetOri[ iF ] = ori;
+        for ( size_t i = 0; i < links2.size(); ++i )
+          me->myFwdLinks.insert( make_pair( links2[i], links2[i].myOri * ori ));
+        break;
+      }
+    }
+    if ( !ori )
+      return false; // error in algorithm: infinite loop
+
+    // try to orient the facet again
+    ori = 0;
+    for ( size_t i = 0; i < links.size() && !ori; ++i )
+    {
+      std::map<Link, int>::const_iterator l2o = myFwdLinks.find( links[i] );
+      if ( l2o != myFwdLinks.end() )
+        ori = links[i].myOri * l2o->second * -1;
+    }
+    me->myPolyFacetOri[ faceIndex ] = ori;
+  }
+
+  return ori > 0;
+}
+
+//=======================================================================
+//function : projectNodesToNormal
+//purpose  : compute min and max projections of all nodes to normal of a facet.
+//=======================================================================
+
+bool SMDS_VolumeTool::projectNodesToNormal( int     faceIndex,
+                                            double& minProj,
+                                            double& maxProj ) const
+{
+  minProj = std::numeric_limits<double>::max();
+  maxProj = std::numeric_limits<double>::min();
+
+  XYZ normal;
+  if ( !GetFaceNormal( faceIndex, normal.x, normal.y, normal.z ))
+    return false;
+  XYZ p0 ( myCurFace.myNodes[0] );
+  for ( size_t i = 0; i < myVolumeNodes.size(); ++i )
+  {
+    if ( std::find( myCurFace.myNodes.begin() + 1,
+                    myCurFace.myNodes.end(),
+                    myVolumeNodes[ i ] ) != myCurFace.myNodes.end() )
+      continue; // node of the faceIndex-th facet
+
+    double proj = normal.Dot( XYZ( myVolumeNodes[ i ]) - p0 );
+    if ( proj < minProj ) minProj = proj;
+    if ( proj > maxProj ) maxProj = proj;
+  }
+  const double tol = 1e-7;
+  minProj += tol;
+  maxProj -= tol;
+  bool diffSize = ( minProj * maxProj < 0 );
+  // if ( diffSize )
+  // {
+  //   minProj = -minProj;
   // }
-  // default:;
+  // else if ( minProj < 0 )
+  // {
+  //   minProj = -minProj;
+  //   maxProj = -maxProj;
   // }
-  // return false;
-  return true;
+
+  return !diffSize; // ? 0 : (minProj >= 0);
 }
 
 //=======================================================================
@@ -1016,16 +1180,16 @@ bool SMDS_VolumeTool::GetFaceNormal (int faceIndex, double & X, double & Y, doub
   if ( !setFace( faceIndex ))
     return false;
 
-  const int iQuad = ( myFaceNbNodes > 6 && !myPolyedre ) ? 2 : 1;
-  XYZ p1 ( myFaceNodes[0*iQuad] );
-  XYZ p2 ( myFaceNodes[1*iQuad] );
-  XYZ p3 ( myFaceNodes[2*iQuad] );
+  const int iQuad = ( !myPolyedre && myCurFace.myNbNodes > 6 ) ? 2 : 1;
+  XYZ p1 ( myCurFace.myNodes[0*iQuad] );
+  XYZ p2 ( myCurFace.myNodes[1*iQuad] );
+  XYZ p3 ( myCurFace.myNodes[2*iQuad] );
   XYZ aVec12( p2 - p1 );
   XYZ aVec13( p3 - p1 );
   XYZ cross = aVec12.Crossed( aVec13 );
 
-  if ( myFaceNbNodes >3*iQuad ) {
-    XYZ p4 ( myFaceNodes[3*iQuad] );
+  if ( myCurFace.myNbNodes >3*iQuad ) {
+    XYZ p4 ( myCurFace.myNodes[3*iQuad] );
     XYZ aVec14( p4 - p1 );
     XYZ cross2 = aVec13.Crossed( aVec14 );
     cross = cross + cross2;
@@ -1054,11 +1218,11 @@ bool SMDS_VolumeTool::GetFaceBaryCenter (int faceIndex, double & X, double & Y,
     return false;
 
   X = Y = Z = 0.0;
-  for ( int i = 0; i < myFaceNbNodes; ++i )
+  for ( int i = 0; i < myCurFace.myNbNodes; ++i )
   {
-    X += myFaceNodes[i]->X() / myFaceNbNodes;
-    Y += myFaceNodes[i]->Y() / myFaceNbNodes;
-    Z += myFaceNodes[i]->Z() / myFaceNbNodes;
+    X += myCurFace.myNodes[i]->X() / myCurFace.myNbNodes;
+    Y += myCurFace.myNodes[i]->Y() / myCurFace.myNbNodes;
+    Z += myCurFace.myNodes[i]->Z() / myCurFace.myNbNodes;
   }
   return true;
 }
@@ -1070,27 +1234,36 @@ bool SMDS_VolumeTool::GetFaceBaryCenter (int faceIndex, double & X, double & Y,
 
 double SMDS_VolumeTool::GetFaceArea( int faceIndex ) const
 {
-  if (myVolume->IsPoly()) {
-    MESSAGE("Warning: attempt to obtain area of a face of polyhedral volume");
-    return 0;
-  }
-
+  double area = 0;
   if ( !setFace( faceIndex ))
-    return 0;
+    return area;
 
-  XYZ p1 ( myFaceNodes[0] );
-  XYZ p2 ( myFaceNodes[1] );
-  XYZ p3 ( myFaceNodes[2] );
+  XYZ p1 ( myCurFace.myNodes[0] );
+  XYZ p2 ( myCurFace.myNodes[1] );
+  XYZ p3 ( myCurFace.myNodes[2] );
   XYZ aVec12( p2 - p1 );
   XYZ aVec13( p3 - p1 );
-  double area = aVec12.Crossed( aVec13 ).Magnitude() * 0.5;
+  area += aVec12.Crossed( aVec13 ).Magnitude();
 
-  if ( myFaceNbNodes == 4 ) {
-    XYZ p4 ( myFaceNodes[3] );
-    XYZ aVec14( p4 - p1 );
-    area += aVec14.Crossed( aVec13 ).Magnitude() * 0.5;
+  if (myVolume->IsPoly())
+  {
+    for ( int i = 3; i < myCurFace.myNbNodes; ++i )
+    {
+      XYZ pI ( myCurFace.myNodes[i] );
+      XYZ aVecI( pI - p1 );
+      area += aVec13.Crossed( aVecI ).Magnitude();
+      aVec13 = aVecI;
+    }
+  }
+  else
+  {
+    if ( myCurFace.myNbNodes == 4 ) {
+      XYZ p4 ( myCurFace.myNodes[3] );
+      XYZ aVec14( p4 - p1 );
+      area += aVec14.Crossed( aVec13 ).Magnitude();
+    }
   }
-  return area;
+  return area / 2;
 }
 
 //================================================================================
@@ -1101,7 +1274,7 @@ double SMDS_VolumeTool::GetFaceArea( int faceIndex ) const
 
 int SMDS_VolumeTool::GetCenterNodeIndex( int faceIndex ) const
 {
-  if ( myAllFacesNbNodes && myVolumeNbNodes == 27 ) // classic element with 27 nodes
+  if ( myAllFacesNbNodes && myVolumeNodes.size() == 27 ) // classic element with 27 nodes
   {
     switch ( faceIndex ) {
     case 0: return 20;
@@ -1129,7 +1302,7 @@ int SMDS_VolumeTool::GetOppFaceIndex( int faceIndex ) const
   const int nbHoriFaces = 2;
 
   if ( faceIndex >= 0 && faceIndex < NbFaces() ) {
-    switch ( myVolumeNbNodes ) {
+    switch ( myVolumeNodes.size() ) {
     case 6:
     case 15:
       if ( faceIndex == 0 || faceIndex == 1 )
@@ -1182,31 +1355,42 @@ bool SMDS_VolumeTool::IsLinked (const SMDS_MeshNode* theNode1,
       MESSAGE("Warning: bad volumic element");
       return false;
     }
-    bool isLinked = false;
-    int iface;
-    for (iface = 1; iface <= myNbFaces && !isLinked; iface++) {
-      int inode, nbFaceNodes = myPolyedre->NbFaceNodes(iface);
-
-      for (inode = 1; inode <= nbFaceNodes && !isLinked; inode++) {
-        const SMDS_MeshNode* curNode = myPolyedre->GetFaceNode(iface, inode);
-
-        if (curNode == theNode1 || curNode == theNode2) {
-          int inextnode = (inode == nbFaceNodes) ? 1 : inode + 1;
-          const SMDS_MeshNode* nextNode = myPolyedre->GetFaceNode(iface, inextnode);
-
-          if ((curNode == theNode1 && nextNode == theNode2) ||
-              (curNode == theNode2 && nextNode == theNode1)) {
-            isLinked = true;
-          }
-        }
+    if ( !myAllFacesNbNodes ) {
+      SMDS_VolumeTool*  me = const_cast< SMDS_VolumeTool* >( this );
+      me->myPolyQuantities = myPolyedre->GetQuantities();
+      myAllFacesNbNodes    = &myPolyQuantities[0];
+    }
+    int from, to = 0, d1 = 1, d2 = 2;
+    if ( myPolyedre->IsQuadratic() ) {
+      if ( theIgnoreMediumNodes ) {
+        d1 = 2; d2 = 0;
+      }
+    } else {
+      d2 = 0;
+    }
+    vector<const SMDS_MeshNode*>::const_iterator i;
+    for (int iface = 0; iface < myNbFaces; iface++)
+    {
+      from = to;
+      to  += myPolyQuantities[iface];
+      i    = std::find( myVolumeNodes.begin() + from, myVolumeNodes.begin() + to, theNode1 );
+      if ( i != myVolumeNodes.end() )
+      {
+        if ((  theNode2 == *( i-d1 ) ||
+               theNode2 == *( i+d1 )))
+          return true;
+        if (( d2 ) &&
+            (( theNode2 == *( i-d2 ) ||
+               theNode2 == *( i+d2 ))))
+          return true;
       }
     }
-    return isLinked;
+    return false;
   }
 
   // find nodes indices
   int i1 = -1, i2 = -1, nbFound = 0;
-  for ( int i = 0; i < myVolumeNbNodes && nbFound < 2; i++ )
+  for ( int i = 0; i < myVolumeNodes.size() && nbFound < 2; i++ )
   {
     if ( myVolumeNodes[ i ] == theNode1 )
       i1 = i, ++nbFound;
@@ -1234,7 +1418,7 @@ bool SMDS_VolumeTool::IsLinked (const int theNode1Index,
   int minInd = min( theNode1Index, theNode2Index );
   int maxInd = max( theNode1Index, theNode2Index );
 
-  if ( minInd < 0 || maxInd > myVolumeNbNodes - 1 || maxInd == minInd )
+  if ( minInd < 0 || maxInd > myVolumeNodes.size() - 1 || maxInd == minInd )
     return false;
 
   VolumeType type = GetVolumeType();
@@ -1351,7 +1535,7 @@ bool SMDS_VolumeTool::IsLinked (const int theNode1Index,
 int SMDS_VolumeTool::GetNodeIndex(const SMDS_MeshNode* theNode) const
 {
   if ( myVolume ) {
-    for ( int i = 0; i < myVolumeNbNodes; i++ ) {
+    for ( int i = 0; i < myVolumeNodes.size(); i++ ) {
       if ( myVolumeNodes[ i ] == theNode )
         return i;
     }
@@ -1370,24 +1554,32 @@ int SMDS_VolumeTool::GetNodeIndex(const SMDS_MeshNode* theNode) const
 int SMDS_VolumeTool::GetAllExistingFaces(vector<const SMDS_MeshElement*> & faces) const
 {
   faces.clear();
-  for ( int iF = 0; iF < NbFaces(); ++iF ) {
-    const SMDS_MeshFace* face = 0;
-    const SMDS_MeshNode** nodes = GetFaceNodes( iF );
-    switch ( NbFaceNodes( iF )) {
-    case 3:
-      face = SMDS_Mesh::FindFace( nodes[0], nodes[1], nodes[2] ); break;
-    case 4:
-      face = SMDS_Mesh::FindFace( nodes[0], nodes[1], nodes[2], nodes[3] ); break;
-    case 6:
-      face = SMDS_Mesh::FindFace( nodes[0], nodes[1], nodes[2],
-                                  nodes[3], nodes[4], nodes[5]); break;
-    case 8:
-      face = SMDS_Mesh::FindFace( nodes[0], nodes[1], nodes[2], nodes[3],
-                                  nodes[4], nodes[5], nodes[6], nodes[7]); break;
+  SaveFacet savedFacet( myCurFace );
+  if ( IsPoly() )
+    for ( int iF = 0; iF < NbFaces(); ++iF ) {
+      if ( setFace( iF ))
+        if ( const SMDS_MeshElement* face = SMDS_Mesh::FindFace( myCurFace.myNodes ))
+          faces.push_back( face );
+    }
+  else
+    for ( int iF = 0; iF < NbFaces(); ++iF ) {
+      const SMDS_MeshFace* face = 0;
+      const SMDS_MeshNode** nodes = GetFaceNodes( iF );
+      switch ( NbFaceNodes( iF )) {
+      case 3:
+        face = SMDS_Mesh::FindFace( nodes[0], nodes[1], nodes[2] ); break;
+      case 4:
+        face = SMDS_Mesh::FindFace( nodes[0], nodes[1], nodes[2], nodes[3] ); break;
+      case 6:
+        face = SMDS_Mesh::FindFace( nodes[0], nodes[1], nodes[2],
+                                    nodes[3], nodes[4], nodes[5]); break;
+      case 8:
+        face = SMDS_Mesh::FindFace( nodes[0], nodes[1], nodes[2], nodes[3],
+                                    nodes[4], nodes[5], nodes[6], nodes[7]); break;
+      }
+      if ( face )
+        faces.push_back( face );
     }
-    if ( face )
-      faces.push_back( face );
-  }
   return faces.size();
 }
 
@@ -1395,17 +1587,17 @@ int SMDS_VolumeTool::GetAllExistingFaces(vector<const SMDS_MeshElement*> & faces
 //================================================================================
 /*!
  * \brief Fill vector with boundary edges existing in the mesh
 * \param edges - vector of found edges
 * \retval int - nb of found faces
+ * \param edges - vector of found edges
+ * \retval int - nb of found faces
  */
 //================================================================================
 
 int SMDS_VolumeTool::GetAllExistingEdges(vector<const SMDS_MeshElement*> & edges) const
 {
   edges.clear();
-  edges.reserve( myVolumeNbNodes * 2 );
-  for ( int i = 0; i < myVolumeNbNodes-1; ++i ) {
-    for ( int j = i + 1; j < myVolumeNbNodes; ++j ) {
+  edges.reserve( myVolumeNodes.size() * 2 );
+  for ( int i = 0; i < myVolumeNodes.size()-1; ++i ) {
+    for ( int j = i + 1; j < myVolumeNodes.size(); ++j ) {
       if ( IsLinked( i, j )) {
         const SMDS_MeshElement* edge =
           SMDS_Mesh::FindEdge( myVolumeNodes[i], myVolumeNodes[j] );
@@ -1428,30 +1620,20 @@ double SMDS_VolumeTool::MinLinearSize2() const
   double minSize = 1e+100;
   int iQ = myVolume->IsQuadratic() ? 2 : 1;
 
-  // store current face data
-  int curFace = myCurFace, nbN = myFaceNbNodes;
-  int* ind = myFaceNodeIndices;
-  myFaceNodeIndices = NULL;
-  const SMDS_MeshNode** nodes = myFaceNodes;
-  myFaceNodes = NULL;
-  
+  SaveFacet savedFacet( myCurFace );
+
   // it seems that compute distance twice is faster than organization of a sole computing
-  myCurFace = -1;
+  myCurFace.myIndex = -1;
   for ( int iF = 0; iF < myNbFaces; ++iF )
   {
     setFace( iF );
-    for ( int iN = 0; iN < myFaceNbNodes; iN += iQ )
+    for ( int iN = 0; iN < myCurFace.myNbNodes; iN += iQ )
     {
-      XYZ n1( myFaceNodes[ iN ]);
-      XYZ n2( myFaceNodes[(iN + iQ) % myFaceNbNodes]);
+      XYZ n1( myCurFace.myNodes[ iN ]);
+      XYZ n2( myCurFace.myNodes[(iN + iQ) % myCurFace.myNbNodes]);
       minSize = std::min( minSize, (n1 - n2).SquareMagnitude());
     }
   }
-  // restore current face data
-  myCurFace = curFace;
-  myFaceNbNodes = nbN;
-  myFaceNodeIndices = ind;
-  delete [] myFaceNodes; myFaceNodes = nodes;
 
   return minSize;
 }
@@ -1467,30 +1649,20 @@ double SMDS_VolumeTool::MaxLinearSize2() const
   double maxSize = -1e+100;
   int iQ = myVolume->IsQuadratic() ? 2 : 1;
 
-  // store current face data
-  int curFace = myCurFace, nbN = myFaceNbNodes;
-  int* ind = myFaceNodeIndices;
-  myFaceNodeIndices = NULL;
-  const SMDS_MeshNode** nodes = myFaceNodes;
-  myFaceNodes = NULL;
+  SaveFacet savedFacet( myCurFace );
   
   // it seems that compute distance twice is faster than organization of a sole computing
-  myCurFace = -1;
+  myCurFace.myIndex = -1;
   for ( int iF = 0; iF < myNbFaces; ++iF )
   {
     setFace( iF );
-    for ( int iN = 0; iN < myFaceNbNodes; iN += iQ )
+    for ( int iN = 0; iN < myCurFace.myNbNodes; iN += iQ )
     {
-      XYZ n1( myFaceNodes[ iN ]);
-      XYZ n2( myFaceNodes[(iN + iQ) % myFaceNbNodes]);
+      XYZ n1( myCurFace.myNodes[ iN ]);
+      XYZ n2( myCurFace.myNodes[(iN + iQ) % myCurFace.myNbNodes]);
       maxSize = std::max( maxSize, (n1 - n2).SquareMagnitude());
     }
   }
-  // restore current face data
-  myCurFace         = curFace;
-  myFaceNbNodes     = nbN;
-  myFaceNodeIndices = ind;
-  delete [] myFaceNodes; myFaceNodes = nodes;
 
   return maxSize;
 }
@@ -1498,6 +1670,7 @@ double SMDS_VolumeTool::MaxLinearSize2() const
 //================================================================================
 /*!
  * \brief fast check that only one volume is build on the face nodes
+ *        This check is valid for conformal meshes only
  */
 //================================================================================
 
@@ -1505,24 +1678,35 @@ bool SMDS_VolumeTool::IsFreeFace( int faceIndex, const SMDS_MeshElement** otherV
 {
   const bool isFree = true;
 
-  if (!setFace( faceIndex ))
+  if ( !setFace( faceIndex ))
     return !isFree;
 
   const SMDS_MeshNode** nodes = GetFaceNodes( faceIndex );
 
-  const int di = myVolume->IsQuadratic() ? 2 : 1;
-  const SMDS_MeshNode* n1 = nodes[di*0];
-  const SMDS_MeshNode* n2 = nodes[di*1];
-  const SMDS_MeshNode* n3 = nodes[di*2];
+  const int  di = myVolume->IsQuadratic() ? 2 : 1;
+  const int nbN = ( myCurFace.myNbNodes/di <= 4 && !IsPoly()) ? 3 : myCurFace.myNbNodes/di; // nb nodes to check
 
-  SMDS_ElemIteratorPtr eIt = n1->GetInverseElementIterator( SMDSAbs_Volume );
-  SMDS_ElemIteratorPtr nIt;
-  while ( eIt->more() ) {
+  SMDS_ElemIteratorPtr eIt = nodes[0]->GetInverseElementIterator( SMDSAbs_Volume );
+  while ( eIt->more() )
+  {
     const SMDS_MeshElement* vol = eIt->next();
-    if ( vol != myVolume &&
-         vol->GetNodeIndex( n2 ) >= 0 &&
-         vol->GetNodeIndex( n3 ) >= 0 )
+    if ( vol == myVolume )
+      continue;
+    int iN;
+    for ( iN = 1; iN < nbN; ++iN )
+      if ( vol->GetNodeIndex( nodes[ iN*di ]) < 0 )
+        break;
+    if ( iN == nbN ) // nbN nodes are shared with vol
     {
+      // if ( vol->IsPoly() || vol->NbFaces() > 6 ) // vol is polyhed or hex prism 
+      // {
+      //   int nb = myCurFace.myNbNodes;
+      //   if ( myVolume->GetEntityType() != vol->GetEntityType() )
+      //     nb -= ( GetCenterNodeIndex(0) > 0 );
+      //   set<const SMDS_MeshNode*> faceNodes( nodes, nodes + nb );
+      //   if ( SMDS_VolumeTool( vol ).GetFaceIndex( faceNodes ) < 0 )
+      //     continue;
+      // }
       if ( otherVol ) *otherVol = vol;
       return !isFree;
     }
@@ -1545,7 +1729,7 @@ bool SMDS_VolumeTool::IsFreeFaceAdv( int faceIndex, const SMDS_MeshElement** oth
     return !isFree;
 
   const SMDS_MeshNode** nodes = GetFaceNodes( faceIndex );
-  const int nbFaceNodes = myFaceNbNodes;
+  const int nbFaceNodes = myCurFace.myNbNodes;
 
   // evaluate nb of face nodes shared by other volumes
   int maxNbShared = -1;
@@ -1724,19 +1908,14 @@ bool SMDS_VolumeTool::setFace( int faceIndex ) const
   if ( !myVolume )
     return false;
 
-  if ( myCurFace == faceIndex )
+  if ( myCurFace.myIndex == faceIndex )
     return true;
 
-  myCurFace = -1;
+  myCurFace.myIndex = -1;
 
   if ( faceIndex < 0 || faceIndex >= NbFaces() )
     return false;
 
-  if (myFaceNodes != NULL) {
-    delete [] myFaceNodes;
-    myFaceNodes = NULL;
-  }
-
   if (myVolume->IsPoly())
   {
     if (!myPolyedre) {
@@ -1745,21 +1924,31 @@ bool SMDS_VolumeTool::setFace( int faceIndex ) const
     }
 
     // set face nodes
-    int iNode;
-    myFaceNbNodes = myPolyedre->NbFaceNodes(faceIndex + 1);
-    myFaceNodes = new const SMDS_MeshNode* [myFaceNbNodes + 1];
-    for ( iNode = 0; iNode < myFaceNbNodes; iNode++ )
-      myFaceNodes[ iNode ] = myPolyedre->GetFaceNode(faceIndex + 1, iNode + 1);
-    myFaceNodes[ myFaceNbNodes ] = myFaceNodes[ 0 ]; // last = first
+    SMDS_VolumeTool* me = const_cast< SMDS_VolumeTool* >( this );
+    if ( !myAllFacesNbNodes ) {
+      me->myPolyQuantities = myPolyedre->GetQuantities();
+      myAllFacesNbNodes    = &myPolyQuantities[0];
+    }
+    myCurFace.myNbNodes = myAllFacesNbNodes[ faceIndex ];
+    myCurFace.myNodes.resize( myCurFace.myNbNodes + 1 );
+    me->myPolyIndices.resize( myCurFace.myNbNodes + 1 );
+    myCurFace.myNodeIndices = & me->myPolyIndices[0];
+    int shift = std::accumulate( myAllFacesNbNodes, myAllFacesNbNodes+faceIndex, 0 );
+    for ( int iNode = 0; iNode < myCurFace.myNbNodes; iNode++ )
+    {
+      myCurFace.myNodes      [ iNode ] = myVolumeNodes[ shift + iNode ];
+      myCurFace.myNodeIndices[ iNode ] = shift + iNode;
+    }
+    myCurFace.myNodes      [ myCurFace.myNbNodes ] = myCurFace.myNodes[ 0 ]; // last = first
+    myCurFace.myNodeIndices[ myCurFace.myNbNodes ] = myCurFace.myNodeIndices[ 0 ];
 
     // check orientation
     if (myExternalFaces)
     {
-      myCurFace = faceIndex; // avoid infinite recursion in IsFaceExternal()
+      myCurFace.myIndex = faceIndex; // avoid infinite recursion in IsFaceExternal()
       myExternalFaces = false; // force normal computation by IsFaceExternal()
       if ( !IsFaceExternal( faceIndex ))
-        for ( int i = 0, j = myFaceNbNodes; i < j; ++i, --j )
-          std::swap( myFaceNodes[i], myFaceNodes[j] );
+        std::reverse( myCurFace.myNodes.begin(), myCurFace.myNodes.end() );
       myExternalFaces = true;
     }
   }
@@ -1768,7 +1957,7 @@ bool SMDS_VolumeTool::setFace( int faceIndex ) const
     if ( !myAllFacesNodeIndices_F )
     {
       // choose data for an element type
-      switch ( myVolumeNbNodes ) {
+      switch ( myVolumeNodes.size() ) {
       case 4:
         myAllFacesNodeIndices_F  = &Tetra_F [0][0];
         //myAllFacesNodeIndices_FE = &Tetra_F [0][0];
@@ -1825,7 +2014,7 @@ bool SMDS_VolumeTool::setFace( int faceIndex ) const
         myAllFacesNodeIndices_RE = &QuadHexa_RE[0][0];
         myAllFacesNbNodes        = QuadHexa_nbN;
         myMaxFaceNbNodes         = sizeof(QuadHexa_F[0])/sizeof(QuadHexa_F[0][0]);
-        if ( !myIgnoreCentralNodes && myVolumeNbNodes == 27 )
+        if ( !myIgnoreCentralNodes && myVolumeNodes.size() == 27 )
         {
           myAllFacesNodeIndices_F  = &TriQuadHexa_F [0][0];
           //myAllFacesNodeIndices_FE = &TriQuadHexa_FE[0][0];
@@ -1845,21 +2034,21 @@ bool SMDS_VolumeTool::setFace( int faceIndex ) const
         return false;
       }
     }
-    myFaceNbNodes = myAllFacesNbNodes[ faceIndex ];
+    myCurFace.myNbNodes = myAllFacesNbNodes[ faceIndex ];
     // if ( myExternalFaces )
-    //   myFaceNodeIndices = (int*)( myVolForward ? myAllFacesNodeIndices_FE + faceIndex*myMaxFaceNbNodes : myAllFacesNodeIndices_RE + faceIndex*myMaxFaceNbNodes );
+    //   myCurFace.myNodeIndices = (int*)( myVolForward ? myAllFacesNodeIndices_FE + faceIndex*myMaxFaceNbNodes : myAllFacesNodeIndices_RE + faceIndex*myMaxFaceNbNodes );
     // else
-    //   myFaceNodeIndices = (int*)( myAllFacesNodeIndices_F + faceIndex*myMaxFaceNbNodes );
-    myFaceNodeIndices = (int*)( myVolForward ? myAllFacesNodeIndices_F + faceIndex*myMaxFaceNbNodes : myAllFacesNodeIndices_RE + faceIndex*myMaxFaceNbNodes );
+    //   myCurFace.myNodeIndices = (int*)( myAllFacesNodeIndices_F + faceIndex*myMaxFaceNbNodes );
+    myCurFace.myNodeIndices = (int*)( myVolForward ? myAllFacesNodeIndices_F + faceIndex*myMaxFaceNbNodes : myAllFacesNodeIndices_RE + faceIndex*myMaxFaceNbNodes );
 
     // set face nodes
-    myFaceNodes = new const SMDS_MeshNode* [myFaceNbNodes + 1];
-    for ( int iNode = 0; iNode < myFaceNbNodes; iNode++ )
-      myFaceNodes[ iNode ] = myVolumeNodes[ myFaceNodeIndices[ iNode ]];
-    myFaceNodes[ myFaceNbNodes ] = myFaceNodes[ 0 ];
+    myCurFace.myNodes.resize( myCurFace.myNbNodes + 1 );
+    for ( int iNode = 0; iNode < myCurFace.myNbNodes; iNode++ )
+      myCurFace.myNodes[ iNode ] = myVolumeNodes[ myCurFace.myNodeIndices[ iNode ]];
+    myCurFace.myNodes[ myCurFace.myNbNodes ] = myCurFace.myNodes[ 0 ];
   }
 
-  myCurFace = faceIndex;
+  myCurFace.myIndex = faceIndex;
 
   return true;
 }
index 4b0d63e2fb9de10d6009a8e5c499ede28bc1aab6..7e88f7c1a309c48061daf61a8ee4092da20c374e 100644 (file)
@@ -38,6 +38,7 @@ class SMDS_MeshVolume;
 
 #include <vector>
 #include <set>
+#include <map>
 
 // =========================================================================
 //
@@ -90,10 +91,10 @@ class SMDS_EXPORT SMDS_VolumeTool
   // top and bottom faces are reversed.
   // Result of IsForward() and methods returning nodes change
 
-  const SMDS_MeshNode** GetNodes() { return myVolumeNodes; }
+  const SMDS_MeshNode** GetNodes() { return &myVolumeNodes[0]; }
   // Return array of volume nodes
 
-  int NbNodes() { return myVolumeNbNodes; }
+  int NbNodes() { return myVolumeNodes.size(); }
   // Return array of volume nodes
 
   double GetSize() const;
@@ -242,31 +243,42 @@ class SMDS_EXPORT SMDS_VolumeTool
   static int GetOppFaceIndexOfHex( int faceIndex );
   // Return index of the opposite face of the hexahedron
 
-private:
+ private:
 
   bool setFace( int faceIndex ) const;
 
+  bool projectNodesToNormal( int faceIndex, double& minProj, double& maxProj ) const;
+
   const SMDS_MeshElement* myVolume;
   const SMDS_VtkVolume*   myPolyedre;
   bool                    myIgnoreCentralNodes;
 
   bool                    myVolForward;
   int                     myNbFaces;
-  int                     myVolumeNbNodes;
-  const SMDS_MeshNode**   myVolumeNodes;
-  std::vector< int >      myPolyIndices;
-
-  mutable bool                    myExternalFaces;
-
-  mutable const int*              myAllFacesNodeIndices_F;
-  mutable const int*              myAllFacesNodeIndices_RE;
-  mutable const int*              myAllFacesNbNodes;
-  mutable int                     myMaxFaceNbNodes;
-
-  mutable int                     myCurFace;
-  mutable int                     myFaceNbNodes;
-  mutable int*                    myFaceNodeIndices;
-  mutable const SMDS_MeshNode**   myFaceNodes;
+  std::vector<const SMDS_MeshNode*> myVolumeNodes;
+  std::vector< int >      myPolyIndices; // of a myCurFace
+  std::vector< int >      myPolyQuantities;
+  std::vector< int >      myPolyFacetOri; // -1-in, +1-out, 0-undef
+
+  typedef std::pair<int,int> Link;
+  std::map<Link, int>     myFwdLinks; // used in IsFaceExternal() to find out myPolyFacetOri
+
+  mutable bool            myExternalFaces;
+
+  mutable const int*      myAllFacesNodeIndices_F;
+  mutable const int*      myAllFacesNodeIndices_RE;
+  mutable const int*      myAllFacesNbNodes;
+  mutable int             myMaxFaceNbNodes;
+
+  struct SaveFacet;
+  struct Facet
+  {
+    int                   myIndex;
+    int                   myNbNodes;
+    int*                  myNodeIndices;
+    std::vector<const SMDS_MeshNode*> myNodes;
+  };
+  mutable Facet           myCurFace;
 
 };
 #endif
index 987ca65bf4d5f2b21ac306e8665c334582747dd6..d050097fba3139295005ad6ba30851fcbf18b0da 100644 (file)
@@ -71,75 +71,73 @@ SMDS_VtkCellIteratorToUNV::SMDS_VtkCellIteratorToUNV(SMDS_Mesh* mesh, int vtkCel
   vtkUnstructuredGrid* grid = _mesh->getGrid();
   grid->GetCellPoints((vtkIdType)_cellId, (vtkIdType&)_nbNodes, pts);
   _vtkIdList->SetNumberOfIds(_nbNodes);
-  int *ids = 0;
+  const int *ids = 0;
   switch (_type)
   {
-    case SMDSEntity_Quad_Edge:
-      {
-        static int id[] = { 0, 2, 1 };
-        ids = id;
-        break;
-      }
-    case SMDSEntity_Quad_Triangle:
-    case SMDSEntity_BiQuad_Triangle:
-      {
-        static int id[] = { 0, 3, 1, 4, 2, 5 };
-        ids = id;
-        _nbNodes = 6;
-        break;
-      }
-    case SMDSEntity_Quad_Quadrangle:
-    case SMDSEntity_BiQuad_Quadrangle:
-      {
-        static int id[] = { 0, 4, 1, 5, 2, 6, 3, 7 };
-        ids = id;
-        _nbNodes = 8;
-        break;
-      }
-    case SMDSEntity_Quad_Tetra:
-      {
-        static int id[] = { 0, 4, 1, 5, 2, 6, 7, 8, 9, 3 };
-        ids = id;
-        break;
-      }
-    case SMDSEntity_Quad_Pyramid:
-      {
-        static int id[] = { 0, 5, 1, 6, 2, 7, 3, 8, 9, 10, 11, 12, 4 };
-        ids = id;
-        break;
-      }
-    case SMDSEntity_Penta:
-      {
-        static int id[] = { 0, 2, 1, 3, 5, 4 };
-        ids = id;
-        break;
-      }
-    case SMDSEntity_Quad_Penta:
-      {
-        static int id[] = { 0, 8, 2, 7, 1, 6, 12, 14, 13, 3, 11, 5, 10, 4, 9 };
-        ids = id;
-        break;
-      }
-    case SMDSEntity_Quad_Hexa:
-    case SMDSEntity_TriQuad_Hexa:
-      {
-        static int id[] = { 0, 8, 1, 9, 2, 10, 3, 11, 16, 17, 18, 19, 4, 12, 5, 13, 6, 14, 7, 15 };
-        ids = id;
-        _nbNodes = 20;
-        break;
-      }
-    case SMDSEntity_Polygon:
-    case SMDSEntity_Quad_Polygon:
-    case SMDSEntity_Polyhedra:
-    case SMDSEntity_Quad_Polyhedra:
-    default:
-      {
-        // static int id[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
-        //                     25, 26, 27, 28, 29 };
-        // ids = id;
-        // break;
-      }
+  case SMDSEntity_Quad_Edge:
+  {
+    static int id[] = { 0, 2, 1 };
+    ids = id;
+    break;
+  }
+  case SMDSEntity_Quad_Triangle:
+  case SMDSEntity_BiQuad_Triangle:
+  {
+    static int id[] = { 0, 3, 1, 4, 2, 5 };
+    ids = id;
+    _nbNodes = 6;
+    break;
+  }
+  case SMDSEntity_Quad_Quadrangle:
+  case SMDSEntity_BiQuad_Quadrangle:
+  {
+    static int id[] = { 0, 4, 1, 5, 2, 6, 3, 7 };
+    ids = id;
+    _nbNodes = 8;
+    break;
   }
+  case SMDSEntity_Quad_Tetra:
+  {
+    static int id[] = { 0, 4, 1, 5, 2, 6, 7, 8, 9, 3 };
+    ids = id;
+    break;
+  }
+  case SMDSEntity_Quad_Pyramid:
+  {
+    static int id[] = { 0, 5, 1, 6, 2, 7, 3, 8, 9, 10, 11, 12, 4 };
+    ids = id;
+    break;
+  }
+  case SMDSEntity_Penta:
+  {
+    static int id[] = { 0, 2, 1, 3, 5, 4 };
+    ids = id;
+    break;
+  }
+  case SMDSEntity_Quad_Penta:
+  {
+    static int id[] = { 0, 8, 2, 7, 1, 6, 12, 14, 13, 3, 11, 5, 10, 4, 9 };
+    ids = id;
+    break;
+  }
+  case SMDSEntity_Quad_Hexa:
+  case SMDSEntity_TriQuad_Hexa:
+  {
+    static int id[] = { 0, 8, 1, 9, 2, 10, 3, 11, 16, 17, 18, 19, 4, 12, 5, 13, 6, 14, 7, 15 };
+    ids = id;
+    _nbNodes = 20;
+    break;
+  }
+  case SMDSEntity_Polygon:
+  case SMDSEntity_Quad_Polygon:
+  case SMDSEntity_Polyhedra:
+  case SMDSEntity_Quad_Polyhedra:
+  default:
+    const std::vector<int>& i = SMDS_MeshCell::interlacedSmdsOrder(aType, _nbNodes);
+    if ( !i.empty() )
+      ids = & i[0];
+  }
+
   if ( ids )
     for (int i = 0; i < _nbNodes; i++)
       _vtkIdList->SetId(i, pts[ids[i]]);
@@ -176,34 +174,34 @@ SMDS_VtkCellIteratorPolyH::SMDS_VtkCellIteratorPolyH(SMDS_Mesh* mesh, int vtkCel
   _nbNodes = _vtkIdList->GetNumberOfIds();
   switch (_type)
   {
-    case SMDSEntity_Polyhedra:
-      {
-        //MESSAGE("SMDS_VtkCellIterator Polyhedra");
-        vtkIdType nFaces = 0;
-        vtkIdType* ptIds = 0;
-        grid->GetFaceStream(_cellId, nFaces, ptIds);
-        int id = 0;
-        _nbNodesInFaces = 0;
-        for (int i = 0; i < nFaces; i++)
-          {
-            int nodesInFace = ptIds[id]; // nodeIds in ptIds[id+1 .. id+nodesInFace]
-            _nbNodesInFaces += nodesInFace;
-            id += (nodesInFace + 1);
-          }
-        _vtkIdList->SetNumberOfIds(_nbNodesInFaces);
-        id = 0;
-        int n = 0;
-        for (int i = 0; i < nFaces; i++)
-          {
-            int nodesInFace = ptIds[id]; // nodeIds in ptIds[id+1 .. id+nodesInFace]
-            for (int k = 1; k <= nodesInFace; k++)
-              _vtkIdList->SetId(n++, ptIds[id + k]);
-            id += (nodesInFace + 1);
-          }
-        break;
-      }
-    default:
-      assert(0);
+  case SMDSEntity_Polyhedra:
+  {
+    //MESSAGE("SMDS_VtkCellIterator Polyhedra");
+    vtkIdType nFaces = 0;
+    vtkIdType* ptIds = 0;
+    grid->GetFaceStream(_cellId, nFaces, ptIds);
+    int id = 0;
+    _nbNodesInFaces = 0;
+    for (int i = 0; i < nFaces; i++)
+    {
+      int nodesInFace = ptIds[id]; // nodeIds in ptIds[id+1 .. id+nodesInFace]
+      _nbNodesInFaces += nodesInFace;
+      id += (nodesInFace + 1);
+    }
+    _vtkIdList->SetNumberOfIds(_nbNodesInFaces);
+    id = 0;
+    int n = 0;
+    for (int i = 0; i < nFaces; i++)
+    {
+      int nodesInFace = ptIds[id]; // nodeIds in ptIds[id+1 .. id+nodesInFace]
+      for (int k = 1; k <= nodesInFace; k++)
+        _vtkIdList->SetId(n++, ptIds[id + k]);
+      id += (nodesInFace + 1);
+    }
+    break;
+  }
+  default:
+    assert(0);
   }
 }
 
index cd281e01a5dc56fbb0d04384e57beffe19285d01..0a772f53bc6be24307a17afbf475a3365fb03c1a 100644 (file)
@@ -85,6 +85,15 @@ void SMDS_VtkFace::initPoly(const std::vector<vtkIdType>& nodeIds, SMDS_Mesh* me
   mesh->setMyModified();
 }
 
+void SMDS_VtkFace::initQuadPoly(const std::vector<vtkIdType>& nodeIds, SMDS_Mesh* mesh)
+{
+  SMDS_MeshFace::init();
+  vtkUnstructuredGrid* grid = mesh->getGrid();
+  myMeshId = mesh->getMeshId();
+  myVtkID = grid->InsertNextLinkedCell(VTK_QUADRATIC_POLYGON, nodeIds.size(), (vtkIdType*) &nodeIds[0]);
+  mesh->setMyModified();
+}
+
 bool SMDS_VtkFace::ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes)
 {
   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
@@ -111,26 +120,28 @@ void SMDS_VtkFace::Print(std::ostream & OS) const
 
 int SMDS_VtkFace::NbEdges() const
 {
-  // TODO quadratic polygons ?
   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
   int nbEdges = 3;
   switch (aVtkType)
   {
-    case VTK_TRIANGLE:
-    case VTK_QUADRATIC_TRIANGLE:
-    case VTK_BIQUADRATIC_TRIANGLE:
-      nbEdges = 3;
-      break;
-    case VTK_QUAD:
-    case VTK_QUADRATIC_QUAD:
-    case VTK_BIQUADRATIC_QUAD:
-      nbEdges = 4;
-      break;
-    case VTK_POLYGON:
-    default:
-      nbEdges = grid->GetCell(myVtkID)->GetNumberOfPoints();
-      break;
+  case VTK_TRIANGLE:
+  case VTK_QUADRATIC_TRIANGLE:
+  case VTK_BIQUADRATIC_TRIANGLE:
+    nbEdges = 3;
+    break;
+  case VTK_QUAD:
+  case VTK_QUADRATIC_QUAD:
+  case VTK_BIQUADRATIC_QUAD:
+    nbEdges = 4;
+    break;
+  case VTK_QUADRATIC_POLYGON:
+    nbEdges = grid->GetCell(myVtkID)->GetNumberOfPoints() / 2;
+    break;
+  case VTK_POLYGON:
+  default:
+    nbEdges = grid->GetCell(myVtkID)->GetNumberOfPoints();
+    break;
   }
   return nbEdges;
 }
@@ -186,6 +197,7 @@ bool SMDS_VtkFace::IsQuadratic() const
   {
     case VTK_QUADRATIC_TRIANGLE:
     case VTK_QUADRATIC_QUAD:
+    case VTK_QUADRATIC_POLYGON:
     case VTK_BIQUADRATIC_QUAD:
     case VTK_BIQUADRATIC_TRIANGLE:
       return true;
@@ -199,7 +211,7 @@ bool SMDS_VtkFace::IsPoly() const
 {
   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
-  return (aVtkType == VTK_POLYGON);
+  return ( aVtkType == VTK_POLYGON || aVtkType == VTK_QUADRATIC_POLYGON );
 }
 
 bool SMDS_VtkFace::IsMediumNode(const SMDS_MeshNode* node) const
@@ -209,33 +221,36 @@ bool SMDS_VtkFace::IsMediumNode(const SMDS_MeshNode* node) const
   int rankFirstMedium = 0;
   switch (aVtkType)
   {
-    case VTK_QUADRATIC_TRIANGLE:
-    case VTK_BIQUADRATIC_TRIANGLE:
-      rankFirstMedium = 3; // medium nodes are of rank 3,4,5
-      break;
-    case VTK_QUADRATIC_QUAD:
-    case VTK_BIQUADRATIC_QUAD:
-      rankFirstMedium = 4; // medium nodes are of rank 4,5,6,7
-      break;
-    default:
-      //MESSAGE("wrong element type " << aVtkType);
-      return false;
+  case VTK_QUADRATIC_TRIANGLE:
+  case VTK_BIQUADRATIC_TRIANGLE:
+    rankFirstMedium = 3; // medium nodes are of rank 3,4,5
+    break;
+  case VTK_QUADRATIC_QUAD:
+  case VTK_BIQUADRATIC_QUAD:
+    rankFirstMedium = 4; // medium nodes are of rank 4,5,6,7
+    break;
+  case VTK_QUADRATIC_POLYGON:
+    rankFirstMedium = grid->GetCell(myVtkID)->GetNumberOfPoints() / 2;
+    break;
+  default:
+    //MESSAGE("wrong element type " << aVtkType);
+    return false;
   }
   vtkIdType npts = 0;
   vtkIdType* pts = 0;
   grid->GetCellPoints(myVtkID, npts, pts);
   vtkIdType nodeId = node->getVtkId();
   for (int rank = 0; rank < npts; rank++)
+  {
+    if (pts[rank] == nodeId)
     {
-      if (pts[rank] == nodeId)
-        {
-          //MESSAGE("rank " << rank << " is medium node " << (rank < rankFirstMedium));
-          if (rank < rankFirstMedium)
-            return false;
-          else
-            return true;
-        }
+      //MESSAGE("rank " << rank << " is medium node " << (rank < rankFirstMedium));
+      if (rank < rankFirstMedium)
+        return false;
+      else
+        return true;
     }
+  }
   //throw SALOME_Exception(LOCALIZED("node does not belong to this element"));
   MESSAGE("======================================================");
   MESSAGE("= IsMediumNode: node does not belong to this element =");
@@ -248,8 +263,17 @@ int SMDS_VtkFace::NbCornerNodes() const
   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
   int       nbPoints = grid->GetCell(myVtkID)->GetNumberOfPoints();
   vtkIdType aVtkType = grid->GetCellType(myVtkID);
-  if ( aVtkType != VTK_POLYGON )
-    return nbPoints <= 4 ? nbPoints : nbPoints / 2;
+  switch ( aVtkType )
+  {
+  case VTK_POLYGON:
+    break;
+  case VTK_QUADRATIC_POLYGON:
+    nbPoints /= 2;
+    break;
+  default:
+    if ( nbPoints > 4 )
+      nbPoints /= 2;
+  }
   return nbPoints;
 }
 
@@ -273,7 +297,8 @@ SMDSAbs_GeometryType SMDS_VtkFace::GetGeomType() const
   case VTK_QUADRATIC_QUAD:
   case VTK_BIQUADRATIC_QUAD: return SMDSGeom_QUADRANGLE;
 
-  case VTK_POLYGON: return SMDSGeom_POLYGON;
+  case VTK_POLYGON:
+  case VTK_QUADRATIC_POLYGON: return SMDSGeom_POLYGON;
   default:;
   }
   return SMDSGeom_NONE;
index 351c905f980d12130ce1cdb85ffb26e33f7c5249..235a9c2d8046535af8361fe1f80c35bd40fa3faa 100644 (file)
@@ -34,6 +34,7 @@ public:
   ~SMDS_VtkFace();
   void init(const std::vector<vtkIdType>& nodeIds, SMDS_Mesh* mesh);
   void initPoly(const std::vector<vtkIdType>& nodeIds, SMDS_Mesh* mesh);
+  void initQuadPoly(const std::vector<vtkIdType>& nodeIds, SMDS_Mesh* mesh);
 
   bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes);
   void ChangeApex(SMDS_MeshNode* node); // to use only for tmp triangles
index d764ffd4b05e453ca1c3bbb825afe826be370765..b7992de2f74473d3528e79b097a440dd69a918e6 100644 (file)
@@ -432,16 +432,14 @@ bool SMESH_Algo::GetSortedNodesOnEdge(const SMESHDS_Mesh*                   theM
       const SMDS_EdgePosition* epos =
         static_cast<const SMDS_EdgePosition*>(node->GetPosition());
       theNodes.insert( theNodes.end(), make_pair( epos->GetUParameter(), node ));
-      //MESSAGE("U " << epos->GetUParameter() << " ID " << node->GetID());
       ++nbNodes;
     }
   }
   // add vertex nodes
   TopoDS_Vertex v1, v2;
   TopExp::Vertices(theEdge, v1, v2);
-  const SMDS_MeshNode* n1 = VertexNode( v1, (SMESHDS_Mesh*) theMesh );
-  const SMDS_MeshNode* n2 = VertexNode( v2, (SMESHDS_Mesh*) theMesh );
-  //MESSAGE("Vertices ID " << n1->GetID() << " " << n2->GetID());
+  const SMDS_MeshNode* n1 = VertexNode( v1, eSubMesh, 0 );
+  const SMDS_MeshNode* n2 = VertexNode( v2, eSubMesh, 0 );
   Standard_Real f, l;
   BRep_Tool::Range(theEdge, f, l);
   if ( v1.Orientation() != TopAbs_FORWARD )
@@ -614,6 +612,118 @@ const SMDS_MeshNode* SMESH_Algo::VertexNode(const TopoDS_Vertex& V,
   return 0;
 }
 
+//=======================================================================
+/*!
+ * \brief Return the node built on a vertex.
+ *        A node moved to other geometry by MergeNodes() is also returned.
+ * \param V - the vertex
+ * \param mesh - mesh
+ * \retval const SMDS_MeshNode* - found node or NULL
+ */
+//=======================================================================
+
+const SMDS_MeshNode* SMESH_Algo::VertexNode(const TopoDS_Vertex& V,
+                                            const SMESH_Mesh*    mesh)
+{
+  const SMDS_MeshNode* node = VertexNode( V, mesh->GetMeshDS() );
+
+  if ( !node && mesh->HasModificationsToDiscard() )
+  {
+    PShapeIteratorPtr edgeIt = SMESH_MesherHelper::GetAncestors( V, *mesh, TopAbs_EDGE );
+    while ( const TopoDS_Shape* edge = edgeIt->next() )
+      if ( SMESHDS_SubMesh* edgeSM = mesh->GetMeshDS()->MeshElements( *edge ))
+        if ( edgeSM->NbElements() > 0 )
+          return VertexNode( V, edgeSM, mesh, /*checkV=*/false );
+  }
+  return node;
+}
+
+//=======================================================================
+/*!
+ * \brief Return the node built on a vertex.
+ *        A node moved to other geometry by MergeNodes() is also returned.
+ * \param V - the vertex
+ * \param edgeSM - sub-mesh of a meshed EDGE sharing the vertex
+ * \param checkV - if \c true, presence of a node on the vertex is checked
+ * \retval const SMDS_MeshNode* - found node or NULL
+ */
+//=======================================================================
+
+const SMDS_MeshNode* SMESH_Algo::VertexNode(const TopoDS_Vertex&   V,
+                                            const SMESHDS_SubMesh* edgeSM,
+                                            const SMESH_Mesh*      mesh,
+                                            const bool             checkV)
+{
+  const SMDS_MeshNode* node = checkV ? VertexNode( V, edgeSM->GetParent() ) : 0;
+
+  if ( !node && edgeSM )
+  {
+    // find nodes not shared by mesh segments
+    typedef set< const SMDS_MeshNode* >                       TNodeSet;
+    typedef map< const SMDS_MeshNode*, const SMDS_MeshNode* > TNodeMap;
+    TNodeMap notSharedNodes;
+    TNodeSet otherShapeNodes;
+    vector< const SMDS_MeshNode* > segNodes(3);
+    SMDS_ElemIteratorPtr segIt = edgeSM->GetElements();
+    while ( segIt->more() )
+    {
+      const SMDS_MeshElement* seg = segIt->next();
+      if ( seg->GetType() != SMDSAbs_Edge )
+        return node;
+      segNodes.assign( seg->begin_nodes(), seg->end_nodes() );
+      for ( int i = 0; i < 2; ++i )
+      {
+        const SMDS_MeshNode* n1 = segNodes[i];
+        const SMDS_MeshNode* n2 = segNodes[1-i];
+        pair<TNodeMap::iterator, bool> it2new = notSharedNodes.insert( make_pair( n1, n2 ));
+        if ( !it2new.second ) // n encounters twice
+          notSharedNodes.erase( it2new.first );
+        if ( n1->getshapeId() != edgeSM->GetID() )
+          otherShapeNodes.insert( n1 );
+      }
+    }
+    if ( otherShapeNodes.size() == 1 && notSharedNodes.empty() ) // a closed EDGE
+      return *otherShapeNodes.begin();
+
+    if ( notSharedNodes.size() == 2 ) // two end nodes found
+    {
+      SMESHDS_Mesh*  meshDS = edgeSM->GetParent();
+      const TopoDS_Shape& E = meshDS->IndexToShape( edgeSM->GetID() );
+      if ( E.IsNull() || E.ShapeType() != TopAbs_EDGE )
+        return node;
+      const SMDS_MeshNode* n1 = notSharedNodes.begin ()->first;
+      const SMDS_MeshNode* n2 = notSharedNodes.rbegin()->first;
+      TopoDS_Shape S1 = SMESH_MesherHelper::GetSubShapeByNode( n1, meshDS );
+      if ( S1.ShapeType() == TopAbs_VERTEX && SMESH_MesherHelper::IsSubShape( S1, E ))
+        return n2;
+      TopoDS_Shape S2 = SMESH_MesherHelper::GetSubShapeByNode( n2, meshDS );
+      if ( S2.ShapeType() == TopAbs_VERTEX && SMESH_MesherHelper::IsSubShape( S2, E ))
+        return n1;
+      if ( edgeSM->NbElements() <= 2 || !mesh ) // one-two segments
+      {
+        gp_Pnt pV = BRep_Tool::Pnt( V );
+        double dist1 = pV.SquareDistance( SMESH_TNodeXYZ( n1 ));
+        double dist2 = pV.SquareDistance( SMESH_TNodeXYZ( n2 ));
+        return dist1 < dist2 ? n1 : n2;
+      }
+      if ( mesh )
+      {
+        SMESH_MesherHelper helper( const_cast<SMESH_Mesh&>( *mesh ));
+        const SMDS_MeshNode* n1i = notSharedNodes.begin ()->second;
+        const SMDS_MeshNode* n2i = notSharedNodes.rbegin()->second;
+        const TopoDS_Edge&  edge = TopoDS::Edge( E );
+        bool  posOK = true;
+        double pos1 = helper.GetNodeU( edge, n1i, n2i, &posOK );
+        double pos2 = helper.GetNodeU( edge, n2i, n1i, &posOK );
+        double posV = BRep_Tool::Parameter( V, edge );
+        if ( Abs( pos1 - posV ) < Abs( pos2 - posV )) return n1;
+        else                                          return n2;
+      }
+    }
+  }
+  return node;
+}
+
 //=======================================================================
 //function : GetMeshError
 //purpose  : Finds topological errors of a sub-mesh
index 3462f0a0db212570b83314350624f59ed18981a0..6363dc469d4949411d6f380e7d869e937475893b 100644 (file)
@@ -179,10 +179,10 @@ class SMESH_EXPORT SMESH_Algo : public SMESH_Hypothesis
 
   /*!
    * \brief evaluates size of prospective mesh on a shape
-    * \param aMesh - the mesh
-    * \param aShape - the shape
-    * \param aNbElems - prospective number of elements by types
-    * \retval bool - is a success
+    \param aMesh - the mesh
+    \param aShape - the shape
+   *  \param aResMap - prospective number of elements by SMDSAbs_ElementType by a sub-mesh
+    \retval bool - is a success
    */
   virtual bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape,
                         MapShapeNbElems& aResMap) = 0;
@@ -313,6 +313,7 @@ public:
    * \param theEdge - The geometrical edge of interest
    * \param theParams - The resulting vector of sorted node parameters
    * \retval bool - false if not all parameters are OK
+   * \warning Nodes moved to other geometry by MergeNodes() are NOT returned.
    */
   static bool GetNodeParamOnEdge(const SMESHDS_Mesh*     theMesh,
                                  const TopoDS_Edge&      theEdge,
@@ -325,17 +326,14 @@ public:
    * \param ignoreMediumNodes - to store medium nodes of quadratic elements or not
    * \param typeToCheck - type of elements to check for medium nodes
    * \retval bool - false if not all parameters are OK
+   * \warning Nodes moved to other geometry by MergeNodes() are NOT returned.
    */
   static bool GetSortedNodesOnEdge(const SMESHDS_Mesh*                        theMesh,
                                    const TopoDS_Edge&                         theEdge,
                                    const bool                                 ignoreMediumNodes,
                                    std::map< double, const SMDS_MeshNode* > & theNodes,
                                    const SMDSAbs_ElementType                  typeToCheck = SMDSAbs_All);
-  /*!
-   * Moved to SMESH_MesherHelper
-   */
-  // static bool IsReversedSubMesh (const TopoDS_Face&  theFace,
-  //                                SMESHDS_Mesh*       theMeshDS);
+
   /*!
    * \brief Compute length of an edge
     * \param E - the edge
@@ -343,7 +341,6 @@ public:
    */
   static double EdgeLength(const TopoDS_Edge & E);
 
-  //static int NumberOfWires(const TopoDS_Shape& S);
   int NumberOfPoints(SMESH_Mesh& aMesh,const TopoDS_Wire& W);
 
   /*!
@@ -372,11 +369,34 @@ public:
   /*!
    * \brief Return the node built on a vertex
     * \param V - the vertex
-    * \param meshDS - mesh
+    * \param meshDS - mesh data structure
     * \retval const SMDS_MeshNode* - found node or NULL
    */
   static const SMDS_MeshNode* VertexNode(const TopoDS_Vertex& V, const SMESHDS_Mesh* meshDS);
 
+  /*!
+   * \brief Return the node built on a vertex.
+   *        A node moved to other geometry by MergeNodes() is also returned.
+    * \param V - the vertex
+    * \param mesh - mesh
+    * \retval const SMDS_MeshNode* - found node or NULL
+   */
+  static const SMDS_MeshNode* VertexNode(const TopoDS_Vertex& V, const SMESH_Mesh* mesh);
+
+  /*!
+   * \brief Return the node built on a vertex.
+   *        A node moved to other geometry by MergeNodes() is also returned.
+    * \param V - the vertex
+    * \param edgeSM - sub-mesh of a meshed EDGE sharing the vertex
+    * \param mesh - the mesh
+    * \param checkV - if \c true, presence of a node on the vertex is checked
+    * \retval const SMDS_MeshNode* - found node or NULL
+   */
+  static const SMDS_MeshNode* VertexNode(const TopoDS_Vertex&   V,
+                                         const SMESHDS_SubMesh* edgeSM,
+                                         const SMESH_Mesh*      mesh,
+                                         const bool             checkV=true);
+
   enum EMeshError { MEr_OK = 0, MEr_HOLES, MEr_BAD_ORI, MEr_EMPTY };
 
   /*!
index c613a597213fa3fd19c6108e587be1f75b95d4c6..4c264d50ae52a996e94983c8c87188d0ba7df108 100644 (file)
@@ -71,7 +71,6 @@ SMESH_Gen::SMESH_Gen()
   SMDS_Mesh::_meshList.clear();
   MESSAGE(SMDS_Mesh::_meshList.size());
   _compute_canceled = false;
-  _sm_current = NULL;
   //vtkDebugLeaks::SetExitError(0);
 }
 
@@ -181,9 +180,9 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
       {
         if (_compute_canceled)
           return false;
-        _sm_current = smToCompute;
+        setCurrentSubMesh( smToCompute );
         smToCompute->ComputeStateEngine( computeEvent );
-        _sm_current = NULL;
+        setCurrentSubMesh( NULL );
       }
 
       // we check all the sub-meshes here and detect if any of them failed to compute
@@ -268,9 +267,9 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
         {
           if (_compute_canceled)
             return false;
-          _sm_current = smToCompute;
+          setCurrentSubMesh( smToCompute );
           smToCompute->ComputeStateEngine( computeEvent );
-          _sm_current = NULL;
+          setCurrentSubMesh( NULL );
           if ( aShapesId )
             aShapesId->insert( smToCompute->GetId() );
         }
@@ -355,9 +354,9 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
 
           if (_compute_canceled)
             return false;
-          _sm_current = sm;
+          setCurrentSubMesh( sm );
           sm->ComputeStateEngine( computeEvent );
-          _sm_current = NULL;
+          setCurrentSubMesh( NULL );
           if ( aShapesId )
             aShapesId->insert( sm->GetId() );
         }
@@ -400,8 +399,9 @@ void SMESH_Gen::PrepareCompute(SMESH_Mesh &          aMesh,
                                const TopoDS_Shape &  aShape)
 {
   _compute_canceled = false;
-  _sm_current = NULL;
+  resetCurrentSubMesh();
 }
+
 //=============================================================================
 /*!
  * Cancel Compute a mesh
@@ -411,10 +411,44 @@ void SMESH_Gen::CancelCompute(SMESH_Mesh &          aMesh,
                               const TopoDS_Shape &  aShape)
 {
   _compute_canceled = true;
-  if(_sm_current)
-    {
-      _sm_current->ComputeStateEngine( SMESH_subMesh::COMPUTE_CANCELED );
-    }
+  if ( const SMESH_subMesh* sm = GetCurrentSubMesh() )
+  {
+    const_cast< SMESH_subMesh* >( sm )->ComputeStateEngine( SMESH_subMesh::COMPUTE_CANCELED );
+  }
+  resetCurrentSubMesh();
+}
+
+//================================================================================
+/*!
+ * \brief Returns a sub-mesh being currently computed
+ */
+//================================================================================
+
+const SMESH_subMesh* SMESH_Gen::GetCurrentSubMesh() const
+{
+  return _sm_current.empty() ? 0 : _sm_current.back();
+}
+
+//================================================================================
+/*!
+ * \brief Sets a sub-mesh being currently computed.
+ *
+ * An algorithm can call Compute() for a sub-shape, hence we keep a stack of sub-meshes
+ */
+//================================================================================
+
+void SMESH_Gen::setCurrentSubMesh(SMESH_subMesh* sm)
+{
+  if ( sm )
+    _sm_current.push_back( sm );
+
+  else if ( !_sm_current.empty() )
+    _sm_current.pop_back();
+}
+
+void SMESH_Gen::resetCurrentSubMesh()
+{
+  _sm_current.clear();
 }
 
 //=============================================================================
@@ -910,7 +944,7 @@ bool SMESH_Gen::GetAlgoState(SMESH_Mesh&               theMesh,
   if ( !hasAlgo ) {
     ret = false;
     theErrors.push_back( TAlgoStateError() );
-    theErrors.back().Set( SMESH_Hypothesis::HYP_MISSING, 1, true );
+    theErrors.back().Set( SMESH_Hypothesis::HYP_MISSING, theMesh.HasShapeToMesh() ? 1 : 3, true );
   }
 
   return ret;
index 52877fda9fd529957507b1e5347f84e2dfba2380..eb09db52b466e0a31ccce617cca4f21c0ae89f30 100644 (file)
@@ -87,7 +87,7 @@ public:
   void CancelCompute(::SMESH_Mesh &        aMesh,
                      const TopoDS_Shape &  aShape);
 
-  const SMESH_subMesh* GetCurrentSubMesh() const { return _sm_current; }
+  const SMESH_subMesh* GetCurrentSubMesh() const;
 
   /*!
    * \brief evaluates size of prospective mesh on a shape 
@@ -173,8 +173,11 @@ private:
   // default number of segments
   int _nbSegments;
 
-  volatile bool  _compute_canceled;
-  SMESH_subMesh* _sm_current;
+  void setCurrentSubMesh(SMESH_subMesh* sm);
+  void resetCurrentSubMesh();
+
+  volatile bool               _compute_canceled;
+  std::list< SMESH_subMesh* > _sm_current;
 };
 
 #endif
index 4b3444adf88aac5c6ce8302169e94421adc00d10..9e613c12156823e14482c27cd4571facc77768d1 100644 (file)
@@ -752,7 +752,7 @@ SMESH_Hypothesis::Hypothesis_Status
   // shape 
   
   bool isAlgo = ( !anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO );
-  int event = isAlgo ? SMESH_subMesh::REMOVE_ALGO : SMESH_subMesh::REMOVE_HYP;
+  int   event = isAlgo ? SMESH_subMesh::REMOVE_ALGO : SMESH_subMesh::REMOVE_HYP;
 
   SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
 
@@ -1117,7 +1117,7 @@ throw(SALOME_Exception)
 
 //================================================================================
 /*!
- * \brief Return submeshes of groups containing the given sub-shape
+ * \brief Return sub-meshes of groups containing the given sub-shape
  */
 //================================================================================
 
@@ -1131,8 +1131,8 @@ SMESH_Mesh::GetGroupSubMeshesContaining(const TopoDS_Shape & aSubShape) const
   if ( !subMesh )
     return found;
 
-  // submeshes of groups have max IDs, so search from the map end
-SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator( /*reverse=*/true ) );
+  // sub-meshes of groups have max IDs, so search from the map end
+  SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator( /*reverse=*/true ) );
   while ( smIt->more() ) {
     SMESH_subMesh*    sm = smIt->next();
     SMESHDS_SubMesh * ds = sm->GetSubMeshDS();
@@ -1158,6 +1158,12 @@ SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator( /*reverse=*/true ) )
           found.push_back( mainSM );
       }
   }
+  else // issue 0023068
+  {
+    if ( SMESH_subMesh * mainSM = GetSubMeshContaining(1) )
+      if ( mainSM->GetSubShape().ShapeType() == TopAbs_COMPOUND )
+        found.push_back( mainSM );
+  }
   return found;
 }
 //=======================================================================
@@ -1328,7 +1334,7 @@ bool SMESH_Mesh::HasModificationsToDiscard() const
   // return true if the next Compute() will be partial and
   // existing but changed elements may prevent successful re-compute
   bool hasComputed = false, hasNotComputed = false;
-SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() );
+  SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() );
   while ( smIt->more() )
   {
     const SMESH_subMesh* aSubMesh = smIt->next();
@@ -1783,10 +1789,10 @@ int SMESH_Mesh::NbBiQuadQuadrangles() const throw(SALOME_Exception)
  */
 //================================================================================
 
-int SMESH_Mesh::NbPolygons() const throw(SALOME_Exception)
+int SMESH_Mesh::NbPolygons(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
-  return _myMeshDS->GetMeshInfo().NbPolygons();
+  return _myMeshDS->GetMeshInfo().NbPolygons(order);
 }
 
 //================================================================================
index 4878dc4f96cd815f4d9c00bd403c8ef41a5f6529..5221ab7d2d1506486b714f020e07a7b49c986240 100644 (file)
@@ -283,7 +283,7 @@ class SMESH_EXPORT SMESH_Mesh
   int NbQuadrangles(SMDSAbs_ElementOrder order = ORDER_ANY) const throw(SALOME_Exception);
   int NbBiQuadQuadrangles() const throw(SALOME_Exception);
   int NbBiQuadTriangles() const throw(SALOME_Exception);
-  int NbPolygons() const throw(SALOME_Exception);
+  int NbPolygons(SMDSAbs_ElementOrder order = ORDER_ANY) const throw(SALOME_Exception);
   
   int NbVolumes(SMDSAbs_ElementOrder order = ORDER_ANY) const throw(SALOME_Exception);
   int NbTetras(SMDSAbs_ElementOrder order = ORDER_ANY) const throw(SALOME_Exception);
index b45e0117bb235707b4499f60e482f6619c487794..2c2fc35e0625002af51119b0a739747ff49b1fdb 100644 (file)
@@ -137,6 +137,40 @@ void SMESH_MeshEditor::ClearLastCreated()
   myLastCreatedElems.Clear();
 }
 
+//================================================================================
+/*!
+ * \brief Initializes members by an existing element
+ *  \param [in] elem - the source element
+ *  \param [in] basicOnly - if true, does not set additional data of Ball and Polyhedron
+ */
+//================================================================================
+
+SMESH_MeshEditor::ElemFeatures&
+SMESH_MeshEditor::ElemFeatures::Init( const SMDS_MeshElement* elem, bool basicOnly )
+{
+  if ( elem )
+  {
+    myType = elem->GetType();
+    if ( myType == SMDSAbs_Face || myType == SMDSAbs_Volume )
+    {
+      myIsPoly = elem->IsPoly();
+      if ( myIsPoly )
+      {
+        myIsQuad = elem->IsQuadratic();
+        if ( myType == SMDSAbs_Volume && !basicOnly )
+        {
+          vector<int > quant = static_cast<const SMDS_VtkVolume* >( elem )->GetQuantities();
+          myPolyhedQuantities.swap( quant );
+        }
+      }
+    }
+    else if ( myType == SMDSAbs_Ball && !basicOnly )
+    {
+      myBallDiameter = static_cast<const SMDS_BallElement*>(elem)->GetDiameter();
+    }
+  }
+  return *this;
+}
 
 //=======================================================================
 /*!
@@ -146,18 +180,16 @@ void SMESH_MeshEditor::ClearLastCreated()
 
 SMDS_MeshElement*
 SMESH_MeshEditor::AddElement(const vector<const SMDS_MeshNode*> & node,
-                             const SMDSAbs_ElementType            type,
-                             const bool                           isPoly,
-                             const int                            ID,
-                             const double                         ballDiameter)
+                             const ElemFeatures&                  features)
 {
-  //MESSAGE("AddElement " <<node.size() << " " << type << " " << isPoly << " " << ID);
   SMDS_MeshElement* e = 0;
   int nbnode = node.size();
   SMESHDS_Mesh* mesh = GetMeshDS();
-  switch ( type ) {
+  const int ID = features.myID;
+
+  switch ( features.myType ) {
   case SMDSAbs_Face:
-    if ( !isPoly ) {
+    if ( !features.myIsPoly ) {
       if      (nbnode == 3) {
         if ( ID >= 1 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], ID);
         else           e = mesh->AddFace      (node[0], node[1], node[2] );
@@ -190,14 +222,21 @@ SMESH_MeshEditor::AddElement(const vector<const SMDS_MeshNode*> & node,
         else           e = mesh->AddFace      (node[0], node[1], node[2], node[3],
                                                node[4], node[5], node[6], node[7], node[8] );
       }
-    } else {
+    }
+    else if ( !features.myIsQuad )
+    {
       if ( ID >= 1 ) e = mesh->AddPolygonalFaceWithID(node, ID);
       else           e = mesh->AddPolygonalFace      (node    );
     }
+    else if ( nbnode % 2 == 0 ) // just a protection
+    {
+      if ( ID >= 1 ) e = mesh->AddQuadPolygonalFaceWithID(node, ID);
+      else           e = mesh->AddQuadPolygonalFace      (node    );
+    }
     break;
 
   case SMDSAbs_Volume:
-    if ( !isPoly ) {
+    if ( !features.myIsPoly ) {
       if      (nbnode == 4) {
         if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], ID);
         else           e = mesh->AddVolume      (node[0], node[1], node[2], node[3] );
@@ -285,6 +324,16 @@ SMESH_MeshEditor::AddElement(const vector<const SMDS_MeshNode*> & node,
                                                  node[24],node[25],node[26] );
       }
     }
+    else if ( !features.myIsQuad )
+    {
+      if ( ID >= 1 ) e = mesh->AddPolyhedralVolumeWithID(node, features.myPolyhedQuantities, ID);
+      else           e = mesh->AddPolyhedralVolume      (node, features.myPolyhedQuantities    );
+    }
+    else
+    {
+      // if ( ID >= 1 ) e = mesh->AddQuadPolyhedralVolumeWithID(node, features.myPolyhedQuantities,ID);
+      // else           e = mesh->AddQuadPolyhedralVolume      (node, features.myPolyhedQuantities   );
+    }
     break;
 
   case SMDSAbs_Edge:
@@ -307,12 +356,12 @@ SMESH_MeshEditor::AddElement(const vector<const SMDS_MeshNode*> & node,
 
   case SMDSAbs_Node:
     if ( ID >= 1 ) e = mesh->AddNodeWithID(node[0]->X(), node[0]->Y(), node[0]->Z(), ID);
-    else           e = mesh->AddNode      (node[0]->X(), node[0]->Y(), node[0]->Z());
+    else           e = mesh->AddNode      (node[0]->X(), node[0]->Y(), node[0]->Z()    );
     break;
 
   case SMDSAbs_Ball:
-    if ( ID >= 1 ) e = mesh->AddBallWithID(node[0], ballDiameter, ID);
-    else           e = mesh->AddBall      (node[0], ballDiameter);
+    if ( ID >= 1 ) e = mesh->AddBallWithID(node[0], features.myBallDiameter, ID);
+    else           e = mesh->AddBall      (node[0], features.myBallDiameter    );
     break;
 
   default:;
@@ -327,10 +376,8 @@ SMESH_MeshEditor::AddElement(const vector<const SMDS_MeshNode*> & node,
  */
 //=======================================================================
 
-SMDS_MeshElement* SMESH_MeshEditor::AddElement(const vector<int> &       nodeIDs,
-                                               const SMDSAbs_ElementType type,
-                                               const bool                isPoly,
-                                               const int                 ID)
+SMDS_MeshElement* SMESH_MeshEditor::AddElement(const vector<int> & nodeIDs,
+                                               const ElemFeatures& features)
 {
   vector<const SMDS_MeshNode*> nodes;
   nodes.reserve( nodeIDs.size() );
@@ -341,7 +388,7 @@ SMDS_MeshElement* SMESH_MeshEditor::AddElement(const vector<int> &       nodeIDs
     else
       return 0;
   }
-  return AddElement( nodes, type, isPoly, ID );
+  return AddElement( nodes, features );
 }
 
 //=======================================================================
@@ -1100,12 +1147,12 @@ bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem)
   else // other elements
   {
     vector<const SMDS_MeshNode*> nodes( theElem->begin_nodes(), theElem->end_nodes() );
-    const std::vector<int>& interlace = SMDS_MeshCell::reverseSmdsOrder( geomType );
+    const std::vector<int>& interlace = SMDS_MeshCell::reverseSmdsOrder( geomType, nodes.size() );
     if ( interlace.empty() )
     {
-      std::reverse( nodes.begin(), nodes.end() ); // polygon
+      std::reverse( nodes.begin(), nodes.end() ); // obsolete, just in case
     }
-    else if ( interlace.size() > 1 )
+    else
     {
       SMDS_MeshCell::applyInterlace( interlace, nodes );
     }
@@ -2192,6 +2239,7 @@ void SMESH_MeshEditor::SplitVolumes (const TFacetOfElem & theElems,
   // map face of volume to it's baricenrtic node
   map< TVolumeFaceKey, const SMDS_MeshNode* > volFace2BaryNode;
   double bc[3];
+  vector<const SMDS_MeshElement* > splitVols;
 
   TFacetOfElem::const_iterator elem2facet = theElems.begin();
   for ( ; elem2facet != theElems.end(); ++elem2facet )
@@ -2267,7 +2315,7 @@ void SMESH_MeshEditor::SplitVolumes (const TFacetOfElem & theElems,
     }
 
     // make new volumes
-    vector<const SMDS_MeshElement* > splitVols( splitMethod._nbSplits ); // splits of a volume
+    splitVols.resize( splitMethod._nbSplits ); // splits of a volume
     const int* volConn = splitMethod._connectivity;
     if ( splitMethod._nbCorners == 4 ) // tetra
       for ( int i = 0; i < splitMethod._nbSplits; ++i, volConn += splitMethod._nbCorners )
@@ -2572,7 +2620,7 @@ void SMESH_MeshEditor::GetHexaFacetsToSplit( TIDSortedElemSet& theHexas,
 
       startHex = curHex;
 
-      // find a facet of startHex to split 
+      // find a facet of startHex to split
 
       set<const SMDS_MeshNode*> lateralNodes;
       vTool.GetFaceNodes( lateralFacet, lateralNodes );
@@ -2602,6 +2650,188 @@ void SMESH_MeshEditor::GetHexaFacetsToSplit( TIDSortedElemSet& theHexas,
         throw SALOME_Exception( THIS_METHOD "facet of a new startHex not found");
     }
   } //   while ( startHex )
+
+  return;
+}
+
+namespace
+{
+  //================================================================================
+  /*!
+   * \brief Selects nodes of several elements according to a given interlace
+   *  \param [in] srcNodes - nodes to select from
+   *  \param [out] tgtNodesVec - array of nodes of several elements to fill in
+   *  \param [in] interlace - indices of nodes for all elements
+   *  \param [in] nbElems - nb of elements
+   *  \param [in] nbNodes - nb of nodes in each element
+   *  \param [in] mesh - the mesh
+   *  \param [out] elemQueue - a list to push elements found by the selected nodes
+   *  \param [in] type - type of elements to look for
+   */
+  //================================================================================
+
+  void selectNodes( const vector< const SMDS_MeshNode* >& srcNodes,
+                    vector< const SMDS_MeshNode* >*       tgtNodesVec,
+                    const int*                            interlace,
+                    const int                             nbElems,
+                    const int                             nbNodes,
+                    SMESHDS_Mesh*                         mesh = 0,
+                    list< const SMDS_MeshElement* >*      elemQueue=0,
+                    SMDSAbs_ElementType                   type=SMDSAbs_All)
+  {
+    for ( int iE = 0; iE < nbElems; ++iE )
+    {
+      vector< const SMDS_MeshNode* >& elemNodes = tgtNodesVec[iE];
+      const int*                         select = & interlace[iE*nbNodes];
+      elemNodes.resize( nbNodes );
+      for ( int iN = 0; iN < nbNodes; ++iN )
+        elemNodes[iN] = srcNodes[ select[ iN ]];
+    }
+    const SMDS_MeshElement* e;
+    if ( elemQueue )
+      for ( int iE = 0; iE < nbElems; ++iE )
+        if (( e = mesh->FindElement( tgtNodesVec[iE], type, /*noMedium=*/false)))
+          elemQueue->push_back( e );
+  }
+}
+
+//=======================================================================
+/*
+ * Split bi-quadratic elements into linear ones without creation of additional nodes
+ *   - bi-quadratic triangle will be split into 3 linear quadrangles;
+ *   - bi-quadratic quadrangle will be split into 4 linear quadrangles;
+ *   - tri-quadratic hexahedron will be split into 8 linear hexahedra;
+ *   Quadratic elements of lower dimension  adjacent to the split bi-quadratic element
+ *   will be split in order to keep the mesh conformal.
+ *  \param elems - elements to split
+ */
+//=======================================================================
+
+void SMESH_MeshEditor::SplitBiQuadraticIntoLinear(TIDSortedElemSet& theElems)
+{
+  vector< const SMDS_MeshNode* > elemNodes(27), subNodes[12], splitNodes[8];
+  vector<const SMDS_MeshElement* > splitElems;
+  list< const SMDS_MeshElement* > elemQueue;
+  list< const SMDS_MeshElement* >::iterator elemIt;
+
+  SMESHDS_Mesh * mesh = GetMeshDS();
+  ElemFeatures *elemType, hexaType(SMDSAbs_Volume), quadType(SMDSAbs_Face), segType(SMDSAbs_Edge);
+  int nbElems, nbNodes;
+
+  TIDSortedElemSet::iterator elemSetIt = theElems.begin();
+  for ( ; elemSetIt != theElems.end(); ++elemSetIt )
+  {
+    elemQueue.clear();
+    elemQueue.push_back( *elemSetIt );
+    for ( elemIt = elemQueue.begin(); elemIt != elemQueue.end(); ++elemIt )
+    {
+      const SMDS_MeshElement* elem = *elemIt;
+      switch( elem->GetEntityType() )
+      {
+      case SMDSEntity_TriQuad_Hexa: // HEX27
+      {
+        elemNodes.assign( elem->begin_nodes(), elem->end_nodes() );
+        nbElems  = nbNodes = 8;
+        elemType = & hexaType;
+
+        // get nodes for new elements
+        static int vInd[8][8] = {{ 0,8,20,11,   16,21,26,24 },
+                                 { 1,9,20,8,    17,22,26,21 },
+                                 { 2,10,20,9,   18,23,26,22 },
+                                 { 3,11,20,10,  19,24,26,23 },
+                                 { 16,21,26,24, 4,12,25,15  },
+                                 { 17,22,26,21, 5,13,25,12  },
+                                 { 18,23,26,22, 6,14,25,13  },
+                                 { 19,24,26,23, 7,15,25,14  }};
+        selectNodes( elemNodes, & splitNodes[0], &vInd[0][0], nbElems, nbNodes );
+
+        // add boundary faces to elemQueue
+        static int fInd[6][9] = {{ 0,1,2,3, 8,9,10,11,   20 },
+                                 { 4,5,6,7, 12,13,14,15, 25 },
+                                 { 0,1,5,4, 8,17,12,16,  21 },
+                                 { 1,2,6,5, 9,18,13,17,  22 },
+                                 { 2,3,7,6, 10,19,14,18, 23 },
+                                 { 3,0,4,7, 11,16,15,19, 24 }};
+        selectNodes( elemNodes, & subNodes[0], &fInd[0][0], 6,9, mesh, &elemQueue, SMDSAbs_Face );
+
+        // add boundary segments to elemQueue
+        static int eInd[12][3] = {{ 0,1,8 }, { 1,2,9 }, { 2,3,10 }, { 3,0,11 },
+                                  { 4,5,12}, { 5,6,13}, { 6,7,14 }, { 7,4,15 },
+                                  { 0,4,16}, { 1,5,17}, { 2,6,18 }, { 3,7,19 }};
+        selectNodes( elemNodes, & subNodes[0], &eInd[0][0], 12,3, mesh, &elemQueue, SMDSAbs_Edge );
+        break;
+      }
+      case SMDSEntity_BiQuad_Triangle: // TRIA7
+      {
+        elemNodes.assign( elem->begin_nodes(), elem->end_nodes() );
+        nbElems = 3;
+        nbNodes = 4;
+        elemType = & quadType;
+
+        // get nodes for new elements
+        static int fInd[3][4] = {{ 0,3,6,5 }, { 1,4,6,3 }, { 2,5,6,4 }};
+        selectNodes( elemNodes, & splitNodes[0], &fInd[0][0], nbElems, nbNodes );
+
+        // add boundary segments to elemQueue
+        static int eInd[3][3] = {{ 0,1,3 }, { 1,2,4 }, { 2,0,5 }};
+        selectNodes( elemNodes, & subNodes[0], &eInd[0][0], 3,3, mesh, &elemQueue, SMDSAbs_Edge );
+        break;
+      }
+      case SMDSEntity_BiQuad_Quadrangle: // QUAD9
+      {
+        elemNodes.assign( elem->begin_nodes(), elem->end_nodes() );
+        nbElems = 4;
+        nbNodes = 4;
+        elemType = & quadType;
+
+        // get nodes for new elements
+        static int fInd[4][4] = {{ 0,4,8,7 }, { 1,5,8,4 }, { 2,6,8,5 }, { 3,7,8,6 }};
+        selectNodes( elemNodes, & splitNodes[0], &fInd[0][0], nbElems, nbNodes );
+
+        // add boundary segments to elemQueue
+        static int eInd[4][3] = {{ 0,1,4 }, { 1,2,5 }, { 2,3,6 }, { 3,0,7 }};
+        selectNodes( elemNodes, & subNodes[0], &eInd[0][0], 4,3, mesh, &elemQueue, SMDSAbs_Edge );
+        break;
+      }
+      case SMDSEntity_Quad_Edge:
+      {
+        if ( elemIt == elemQueue.begin() )
+          continue; // an elem is in theElems
+        elemNodes.assign( elem->begin_nodes(), elem->end_nodes() );
+        nbElems = 2;
+        nbNodes = 2;
+        elemType = & segType;
+
+        // get nodes for new elements
+        static int eInd[2][2] = {{ 0,2 }, { 2,1 }};
+        selectNodes( elemNodes, & splitNodes[0], &eInd[0][0], nbElems, nbNodes );
+        break;
+      }
+      default: continue;
+      } // switch( elem->GetEntityType() )
+
+      // Create new elements
+
+      SMESHDS_SubMesh* subMesh = mesh->MeshElements( elem->getshapeId() );
+
+      splitElems.clear();
+
+      //elemType->SetID( elem->GetID() ); // create an elem with the same ID as a removed one
+      mesh->RemoveFreeElement( elem, subMesh, /*fromGroups=*/false );
+      //splitElems.push_back( AddElement( splitNodes[ 0 ], *elemType ));
+      //elemType->SetID( -1 );
+
+      for ( int iE = 0; iE < nbElems; ++iE )
+        splitElems.push_back( AddElement( splitNodes[ iE ], *elemType ));
+
+
+      ReplaceElemInGroups( elem, splitElems, mesh );
+
+      if ( subMesh )
+        for ( size_t i = 0; i < splitElems.size(); ++i )
+          subMesh->AddElement( splitElems[i] );
+    }
+  }
 }
 
 //=======================================================================
@@ -2745,7 +2975,6 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
         }
       AddToSameGroups( newElem1, elem, aMesh );
       AddToSameGroups( newElem2, elem, aMesh );
-      //aMesh->RemoveFreeElement(elem, aMesh->MeshElements(aShapeId), true);
       aMesh->RemoveElement( elem );
     }
 
@@ -4326,7 +4555,7 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
     }
     else
     {
-      const vector<int>& ind = SMDS_MeshCell::reverseSmdsOrder( baseType );
+      const vector<int>& ind = SMDS_MeshCell::reverseSmdsOrder( baseType, nbNodes );
       SMDS_MeshCell::applyInterlace( ind, itNN );
       SMDS_MeshCell::applyInterlace( ind, prevNod );
       SMDS_MeshCell::applyInterlace( ind, nextNod );
@@ -4379,6 +4608,17 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
     iOpposSame   = ( iSameNode - 2 < 0  ? iSameNode + 2 : iSameNode - 2 );
   }
 
+  if ( baseType == SMDSEntity_Polygon )
+  {
+    if      ( nbNodes == 3 ) baseType = SMDSEntity_Triangle;
+    else if ( nbNodes == 4 ) baseType = SMDSEntity_Quadrangle;
+  }
+  else if ( baseType == SMDSEntity_Quad_Polygon )
+  {
+    if      ( nbNodes == 6 ) baseType = SMDSEntity_Quad_Triangle;
+    else if ( nbNodes == 8 ) baseType = SMDSEntity_Quad_Quadrangle;
+  }
+
   // make new elements
   for (int iStep = 0; iStep < nbSteps; iStep++ )
   {
@@ -4524,7 +4764,7 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
         break;
       }
       case SMDSEntity_Quad_Triangle:  // sweep (Bi)Quadratic TRIANGLE --->
-      case SMDSEntity_BiQuad_Triangle: /* ??? */ { 
+      case SMDSEntity_BiQuad_Triangle: /* ??? */ {
         if ( nbDouble+nbSame != 3 ) break;
         if(nbSame==0) {
           // --->  pentahedron with 15 nodes
@@ -4576,7 +4816,7 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
         else if(nbSame==1) {
           // ---> pyramid + pentahedron - can not be created since it is needed
           // additional middle node at the center of face
-          INFOS( " Sweep for face " << elem->GetID() << " can not be created" );
+          //INFOS( " Sweep for face " << elem->GetID() << " can not be created" );
           return;
         }
         else if( nbSame == 2 ) {
@@ -4652,7 +4892,7 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
     {
       if ( baseType != SMDSEntity_Polygon )
       {
-        const std::vector<int>& ind = SMDS_MeshCell::interlacedSmdsOrder(baseType);
+        const std::vector<int>& ind = SMDS_MeshCell::interlacedSmdsOrder(baseType,nbNodes);
         SMDS_MeshCell::applyInterlace( ind, prevNod );
         SMDS_MeshCell::applyInterlace( ind, nextNod );
         SMDS_MeshCell::applyInterlace( ind, midlNod );
@@ -4677,21 +4917,30 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
       quantities.push_back( nbNodes );
 
       // side faces
-      for (int iface = 0; iface < nbNodes; iface++)
+      // 3--6--2
+      // |     |
+      // 7     5
+      // |     |
+      // 0--4--1
+      const int iQuad = elem->IsQuadratic();
+      for (int iface = 0; iface < nbNodes; iface += 1+iQuad )
       {
-        const int prevNbNodes = polyedre_nodes.size();
-        int inextface = (iface+1) % nbNodes;
-        polyedre_nodes.push_back( prevNod[inextface] );
-        polyedre_nodes.push_back( prevNod[iface] );
-        if ( prevNod[iface] != nextNod[iface] )
+        const int prevNbNodes = polyedre_nodes.size(); // to detect degenerated face
+        int inextface = (iface+1+iQuad) % nbNodes;
+        int imid      = (iface+1) % nbNodes;
+        polyedre_nodes.push_back( prevNod[inextface] );         // 0
+        if ( iQuad ) polyedre_nodes.push_back( prevNod[imid] ); // 4
+        polyedre_nodes.push_back( prevNod[iface] );             // 1
+        if ( prevNod[iface] != nextNod[iface] ) // 1 != 2
         {
-          if ( midlNod[ iface ]) polyedre_nodes.push_back( midlNod[ iface ]);
-          polyedre_nodes.push_back( nextNod[iface] );
+          if ( midlNod[ iface ]) polyedre_nodes.push_back( midlNod[ iface ]); // 5
+          polyedre_nodes.push_back( nextNod[iface] );                         // 2
         }
-        if ( prevNod[inextface] != nextNod[inextface] )
+        if ( iQuad ) polyedre_nodes.push_back( nextNod[imid] );               // 6
+        if ( prevNod[inextface] != nextNod[inextface] ) // 0 != 3
         {
-          polyedre_nodes.push_back( nextNod[inextface] );
-          if ( midlNod[ inextface ]) polyedre_nodes.push_back( midlNod[ inextface ]);
+          polyedre_nodes.push_back( nextNod[inextface] );                            // 3
+          if ( midlNod[ inextface ]) polyedre_nodes.push_back( midlNod[ inextface ]);// 7
         }
         const int nbFaceNodes = polyedre_nodes.size() - prevNbNodes;
         if ( nbFaceNodes > 2 )
@@ -4701,7 +4950,7 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
       }
       aNewElem = aMesh->AddPolyhedralVolume (polyedre_nodes, quantities);
 
-    } //  // try to create a polyherdal prism
+    } // try to create a polyherdal prism
 
     if ( aNewElem ) {
       newElems.push_back( aNewElem );
@@ -4752,16 +5001,20 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
     const SMDS_MeshElement* el = 0;
     SMDSAbs_ElementType highType = SMDSAbs_Edge; // count most complex elements only
     while ( eIt->more() && nbInitElems < 2 ) {
-      el = eIt->next();
-      SMDSAbs_ElementType type = el->GetType();
-      if ( type == SMDSAbs_Volume || type < highType ) continue;
+      const SMDS_MeshElement* e = eIt->next();
+      SMDSAbs_ElementType  type = e->GetType();
+      if ( type == SMDSAbs_Volume ||
+           type < highType ||
+           !elemSet.count(e))
+        continue;
       if ( type > highType ) {
         nbInitElems = 0;
-        highType = type;
+        highType    = type;
       }
-      nbInitElems += elemSet.count(el);
+      el = e;
+      ++nbInitElems;
     }
-    if ( nbInitElems < 2 ) {
+    if ( nbInitElems == 1 ) {
       bool NotCreateEdge = el && el->IsMediumNode(node);
       if(!NotCreateEdge) {
         vector<TNodeOfNodeListMapItr> newNodesItVec( 1, nList );
@@ -4774,6 +5027,8 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
   // Make a ceiling for each element ie an equal element of last new nodes.
   // Find free links of faces - make edges and sweep them into faces.
 
+  ElemFeatures polyFace( SMDSAbs_Face, /*isPoly=*/true ), anyFace;
+
   TTElemOfElemListMap::iterator  itElem      = newElemsMap.begin();
   TElemOfVecOfNnlmiMap::iterator itElemNodes = elemNewNodesMap.begin();
   for ( ; itElem != newElemsMap.end(); itElem++, itElemNodes++ )
@@ -4877,7 +5132,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
 
     // sweep free links into faces
 
-    if ( hasFreeLinks )  {
+    if ( hasFreeLinks ) {
       list<const SMDS_MeshElement*> & newVolumes = itElem->second;
       int iVol, volNb, nbVolumesByStep = newVolumes.size() / nbSteps;
 
@@ -4911,11 +5166,12 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
             freeInd.push_back( iF );
             // find source edge of a free face iF
             vector<const SMDS_MeshNode*> commonNodes; // shared by the initial and free faces
-            commonNodes.resize( initNodeSet.size(), NULL ); // avoid spoiling memory
-            std::set_intersection( faceNodeSet.begin(), faceNodeSet.end(),
-                                   initNodeSet.begin(), initNodeSet.end(),
-                                   commonNodes.begin());
-            if ( (*v)->IsQuadratic() )
+            vector<const SMDS_MeshNode*>::iterator lastCommom;
+            commonNodes.resize( nbNodes, 0 );
+            lastCommom = std::set_intersection( faceNodeSet.begin(), faceNodeSet.end(),
+                                                initNodeSet.begin(), initNodeSet.end(),
+                                                commonNodes.begin());
+            if ( std::distance( commonNodes.begin(), lastCommom ) == 3 )
               srcEdges.push_back(aMesh->FindEdge (commonNodes[0],commonNodes[1],commonNodes[2]));
             else
               srcEdges.push_back(aMesh->FindEdge (commonNodes[0],commonNodes[1]));
@@ -4931,10 +5187,11 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
         if ( freeInd.empty() )
           continue;
 
-        // create faces for all steps;
+        // create wall faces for all steps;
         // if such a face has been already created by sweep of edge,
         // assure that its orientation is OK
-        for ( int iStep = 0; iStep < nbSteps; iStep++ ) {
+        for ( int iStep = 0; iStep < nbSteps; iStep++ )
+        {
           vTool.Set( *v, /*ignoreCentralNodes=*/false );
           vTool.SetExternalNormal();
           const int nextShift = vTool.IsForward() ? +1 : -1;
@@ -5061,7 +5318,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
                 if ( f )
                   aMesh->ChangeElementNodes( f, &polygon_nodes[0], nbn );
                 else
-                  AddElement(polygon_nodes, SMDSAbs_Face, polygon_nodes.size()>4);
+                  AddElement( polygon_nodes, polyFace.SetQuad( (*v)->IsQuadratic() ));
               }
             }
 
@@ -5088,36 +5345,20 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
       aFaceLastNodes.erase( vecNewNodes.back()->second.back() );
       iF = lastVol.GetFaceIndex( aFaceLastNodes );
     }
-    if ( iF >= 0 ) {
+    if ( iF >= 0 )
+    {
       lastVol.SetExternalNormal();
       const SMDS_MeshNode** nodes = lastVol.GetFaceNodes( iF );
-      int nbn = lastVol.NbFaceNodes( iF );
-      // we do not use this->AddElement() because nodes are interlaced
+      const               int nbn = lastVol.NbFaceNodes( iF );
       vector<const SMDS_MeshNode*> nodeVec( nodes, nodes+nbn );
       if ( !hasFreeLinks ||
            !aMesh->FindElement( nodeVec, SMDSAbs_Face, /*noMedium=*/false) )
       {
-        if ( nbn == 3 )
-          myLastCreatedElems.Append(aMesh->AddFace( nodes[0], nodes[1], nodes[2] ));
-
-        else if ( nbn == 4 )
-          myLastCreatedElems.Append(aMesh->AddFace( nodes[0], nodes[1], nodes[2], nodes[3]));
-
-        else if ( nbn == 6 && isQuadratic )
-          myLastCreatedElems.Append(aMesh->AddFace( nodes[0], nodes[2], nodes[4],
-                                                    nodes[1], nodes[3], nodes[5]));
-        else if ( nbn == 7 && isQuadratic )
-          myLastCreatedElems.Append(aMesh->AddFace( nodes[0], nodes[2], nodes[4],
-                                                    nodes[1], nodes[3], nodes[5], nodes[6]));
-        else if ( nbn == 8 && isQuadratic )
-          myLastCreatedElems.Append(aMesh->AddFace( nodes[0], nodes[2], nodes[4], nodes[6],
-                                                    nodes[1], nodes[3], nodes[5], nodes[7]));
-        else if ( nbn == 9 && isQuadratic )
-          myLastCreatedElems.Append(aMesh->AddFace( nodes[0], nodes[2], nodes[4], nodes[6],
-                                                    nodes[1], nodes[3], nodes[5], nodes[7],
-                                                    nodes[8]));
-        else
-          myLastCreatedElems.Append(aMesh->AddPolygonalFace( nodeVec ));
+        const vector<int>& interlace =
+          SMDS_MeshCell::interlacedSmdsOrder( elem->GetEntityType(), nbn );
+        SMDS_MeshCell::applyInterlaceRev( interlace, nodeVec );
+
+        AddElement( nodeVec, anyFace.Init( elem ));
 
         while ( srcElements.Length() < myLastCreatedElems.Length() )
           srcElements.Append( elem );
@@ -5181,7 +5422,6 @@ SMESH_MeshEditor::RotationSweep(TIDSortedElemSet   theElemSets[2],
       SMDS_ElemIteratorPtr itN = elem->nodesIterator();
       while ( itN->more() )
       {
-        // check if a node has been already sweeped
         const SMDS_MeshNode* node = cast2Node( itN->next() );
 
         gp_XYZ aXYZ( node->X(), node->Y(), node->Z() );
@@ -5189,6 +5429,7 @@ SMESH_MeshEditor::RotationSweep(TIDSortedElemSet   theElemSets[2],
         aXYZ.Coord( coord[0], coord[1], coord[2] );
         bool isOnAxis = ( aLine.SquareDistance( aXYZ ) <= aSqTol );
 
+        // check if a node has been already sweeped
         TNodeOfNodeListMapItr nIt =
           mapNewNodes.insert( make_pair( node, list<const SMDS_MeshNode*>() )).first;
         list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
@@ -5745,6 +5986,10 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
   ASSERT( theTrack );
 
   SMESHDS_SubMesh* pSubMeshDS = theTrack->GetSubMeshDS();
+  if ( !pSubMeshDS )
+    return ExtrusionAlongTrack( theElements, theTrack->GetFather(), theN1,
+                                theHasAngles, theAngles, theLinearVariation,
+                                theHasRefPoint, theRefPoint, theMakeGroups );
 
   aItE = pSubMeshDS->GetElements();
   while ( aItE->more() ) {
@@ -6148,7 +6393,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
       SMESH_MeshEditor_PathPoint PP2 = currList.front();
       gp_Dir D1 = PP1.Tangent();
       gp_Dir D2 = PP2.Tangent();
-      gp_Dir Dnew( ( D1.XYZ() + D2.XYZ() ) / 2 );
+      gp_Dir Dnew( D1.XYZ() + D2.XYZ() );
       PP1.SetTangent(Dnew);
       fullList.push_back(PP1);
       fullList.splice( fullList.end(), currList, ++currList.begin(), currList.end() );
@@ -6213,7 +6458,7 @@ SMESH_MeshEditor::MakeEdgePathPoints(std::list<double>&                aPrms,
     aL2 = aVec.SquareMagnitude();
     if ( aL2 < aTolVec2 )
       return EXTR_CANT_GET_TANGENT;
-    gp_Dir aTgt( aVec );
+    gp_Dir aTgt( FirstIsStart ? aVec : -aVec );
     aPP.SetPnt( aP3D );
     aPP.SetTangent( aTgt );
     aPP.SetParameter( aT );
@@ -6238,9 +6483,11 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet                  theElemSets
                                    const bool                        theMakeGroups)
 {
   const int aNbTP = fullList.size();
+
   // Angles
   if( theHasAngles && !theAngles.empty() && theLinearVariation )
     LinearAngleVariation(aNbTP-1, theAngles);
+
   // fill vector of path points with angles
   vector<SMESH_MeshEditor_PathPoint> aPPs;
   list<SMESH_MeshEditor_PathPoint>::iterator itPP = fullList.begin();
@@ -6270,10 +6517,10 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet                  theElemSets
     {
       TIDSortedElemSet& theElements = theElemSets[ is2ndSet ];
       itElem = theElements.begin();
-      for ( ; itElem != theElements.end(); itElem++ ) {
+      for ( ; itElem != theElements.end(); itElem++ )
+      {
         const SMDS_MeshElement* elem = *itElem;
-
-        SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+        SMDS_ElemIteratorPtr     itN = elem->nodesIterator();
         while ( itN->more() ) {
           const SMDS_MeshElement* node = itN->next();
           if ( newNodes.insert( node ).second )
@@ -6287,19 +6534,15 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet                  theElemSets
 
   // 4. Processing the elements
   SMESHDS_Mesh* aMesh = GetMeshDS();
+  list<const SMDS_MeshNode*> emptyList;
 
   setElemsFirst( theElemSets );
   for ( int is2ndSet = 0; is2ndSet < 2; ++is2ndSet )
   {
     TIDSortedElemSet& theElements = theElemSets[ is2ndSet ];
-    for ( itElem = theElements.begin(); itElem != theElements.end(); itElem++ ) {
-      // check element type
+    for ( itElem = theElements.begin(); itElem != theElements.end(); itElem++ )
+    {
       const SMDS_MeshElement* elem = *itElem;
-      if ( !elem )
-        continue;
-      // SMDSAbs_ElementType aTypeE = elem->GetType();
-      // if ( aTypeE != SMDSAbs_Face && aTypeE != SMDSAbs_Edge )
-      //   continue;
 
       vector<TNodeOfNodeListMapItr> & newNodesItVec = mapElemNewNodes[ elem ];
       newNodesItVec.reserve( elem->NbNodes() );
@@ -6311,13 +6554,11 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet                  theElemSets
       {
         ++nodeIndex;
         // check if a node has been already processed
-        const SMDS_MeshNode* node =
-          static_cast<const SMDS_MeshNode*>( itN->next() );
-        TNodeOfNodeListMap::iterator nIt = mapNewNodes.find( node );
-        if ( nIt == mapNewNodes.end() ) {
-          nIt = mapNewNodes.insert( make_pair( node, list<const SMDS_MeshNode*>() )).first;
-          list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
-
+        const SMDS_MeshNode* node = cast2Node( itN->next() );
+        TNodeOfNodeListMap::iterator nIt = mapNewNodes.insert( make_pair( node, emptyList )).first;
+        list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
+        if ( listNewNodes.empty() )
+        {
           // make new nodes
           Standard_Real aAngle1x, aAngleT1T0, aTolAng;
           gp_Pnt aP0x, aP1x, aPN0, aPN1, aV0x, aV1x;
@@ -6332,7 +6573,6 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet                  theElemSets
           const SMESH_MeshEditor_PathPoint& aPP0 = aPPs[0];
           aP0x = aPP0.Pnt();
           aDT0x= aPP0.Tangent();
-          //cout<<"j = 0   PP: Pnt("<<aP0x.X()<<","<<aP0x.Y()<<","<<aP0x.Z()<<")"<<endl;
 
           for ( int j = 1; j < aNbTP; ++j ) {
             const SMESH_MeshEditor_PathPoint& aPP1 = aPPs[j];
@@ -6351,7 +6591,8 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet                  theElemSets
 
             // rotation 1 [ T1,T0 ]
             aAngleT1T0=-aDT1x.Angle( aDT0x );
-            if (fabs(aAngleT1T0) > aTolAng) {
+            if (fabs(aAngleT1T0) > aTolAng)
+            {
               aDT1T0=aDT1x^aDT0x;
               anAxT1T0.SetLocation( aV1x );
               anAxT1T0.SetDirection( aDT1T0 );
@@ -6370,13 +6611,11 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet                  theElemSets
             }
 
             // make new node
-            //MESSAGE("elem->IsQuadratic " << elem->IsQuadratic() << " " << elem->IsMediumNode(node));
-            if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
+            if ( elem->IsQuadratic() && !elem->IsMediumNode(node) )
+            {
               // create additional node
-              double x = ( aPN1.X() + aPN0.X() )/2.;
-              double y = ( aPN1.Y() + aPN0.Y() )/2.;
-              double z = ( aPN1.Z() + aPN0.Z() )/2.;
-              const SMDS_MeshNode* newNode = aMesh->AddNode(x,y,z);
+              gp_XYZ midP = 0.5 * ( aPN1.XYZ() + aPN0.XYZ() );
+              const SMDS_MeshNode* newNode = aMesh->AddNode( midP.X(), midP.Y(), midP.Z() );
               myLastCreatedNodes.Append(newNode);
               srcNodes.Append( node );
               listNewNodes.push_back( newNode );
@@ -6392,42 +6631,40 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet                  theElemSets
             aDT0x = aDT1x;
           }
         }
-
-        else {
+        else if( elem->IsQuadratic() && !elem->IsMediumNode(node) )
+        {
           // if current elem is quadratic and current node is not medium
           // we have to check - may be it is needed to insert additional nodes
-          if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
-            list< const SMDS_MeshNode* > & listNewNodes = nIt->second;
-            if(listNewNodes.size()==aNbTP-1) {
-              vector<const SMDS_MeshNode*> aNodes(2*(aNbTP-1));
-              gp_XYZ P(node->X(), node->Y(), node->Z());
-              list< const SMDS_MeshNode* >::iterator it = listNewNodes.begin();
-              int i;
-              for(i=0; i<aNbTP-1; i++) {
-                const SMDS_MeshNode* N = *it;
-                double x = ( N->X() + P.X() )/2.;
-                double y = ( N->Y() + P.Y() )/2.;
-                double z = ( N->Z() + P.Z() )/2.;
-                const SMDS_MeshNode* newN = aMesh->AddNode(x,y,z);
-                srcNodes.Append( node );
-                myLastCreatedNodes.Append(newN);
-                aNodes[2*i] = newN;
-                aNodes[2*i+1] = N;
-                P = gp_XYZ(N->X(),N->Y(),N->Z());
-              }
-              listNewNodes.clear();
-              for(i=0; i<2*(aNbTP-1); i++) {
-                listNewNodes.push_back(aNodes[i]);
-              }
+          list< const SMDS_MeshNode* > & listNewNodes = nIt->second;
+          if ( listNewNodes.size() == aNbTP-1 )
+          {
+            vector<const SMDS_MeshNode*> aNodes(2*(aNbTP-1));
+            gp_XYZ P(node->X(), node->Y(), node->Z());
+            list< const SMDS_MeshNode* >::iterator it = listNewNodes.begin();
+            int i;
+            for(i=0; i<aNbTP-1; i++) {
+              const SMDS_MeshNode* N = *it;
+              double x = ( N->X() + P.X() )/2.;
+              double y = ( N->Y() + P.Y() )/2.;
+              double z = ( N->Z() + P.Z() )/2.;
+              const SMDS_MeshNode* newN = aMesh->AddNode(x,y,z);
+              srcNodes.Append( node );
+              myLastCreatedNodes.Append(newN);
+              aNodes[2*i] = newN;
+              aNodes[2*i+1] = N;
+              P = gp_XYZ(N->X(),N->Y(),N->Z());
+            }
+            listNewNodes.clear();
+            for(i=0; i<2*(aNbTP-1); i++) {
+              listNewNodes.push_back(aNodes[i]);
             }
           }
         }
 
         newNodesItVec.push_back( nIt );
       }
+
       // make new elements
-      //sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem],
-      //              newNodesItVec[0]->second.size(), myLastCreatedElems );
       sweepElement( elem, newNodesItVec, newElemsMap[elem], aNbTP-1, srcElems );
     }
   }
@@ -6551,10 +6788,12 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
     groupPostfix = "transformed";
   }
 
-  SMESH_MeshEditor targetMeshEditor( theTargetMesh );
   SMESHDS_Mesh* aTgtMesh = theTargetMesh ? theTargetMesh->GetMeshDS() : 0;
   SMESHDS_Mesh* aMesh    = GetMeshDS();
 
+  SMESH_MeshEditor targetMeshEditor( theTargetMesh );
+  SMESH_MeshEditor* editor = theTargetMesh ? & targetMeshEditor : theCopy ? this : 0;
+  SMESH_MeshEditor::ElemFeatures elemType;
 
   // map old node to new one
   TNodeNodeMap nodeMap;
@@ -6586,70 +6825,68 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
 
   // loop on elements to transform nodes : first orphan nodes then elems
   TIDSortedElemSet::iterator itElem;
-  TIDSortedElemSet *elements[] = {&orphanNode, &theElems };
+  TIDSortedElemSet *elements[] = { &orphanNode, &theElems };
   for (int i=0; i<2; i++)
-  for ( itElem = elements[i]->begin(); itElem != elements[i]->end(); itElem++ ) {
-    const SMDS_MeshElement* elem = *itElem;
-    if ( !elem )
-      continue;
-
-    // loop on elem nodes
-    SMDS_ElemIteratorPtr itN = elem->nodesIterator();
-    while ( itN->more() ) {
-
-      const SMDS_MeshNode* node = cast2Node( itN->next() );
-      // check if a node has been already transformed
-      pair<TNodeNodeMap::iterator,bool> n2n_isnew =
-        nodeMap.insert( make_pair ( node, node ));
-      if ( !n2n_isnew.second )
+    for ( itElem = elements[i]->begin(); itElem != elements[i]->end(); itElem++ )
+    {
+      const SMDS_MeshElement* elem = *itElem;
+      if ( !elem )
         continue;
 
+      // loop on elem nodes
       double coord[3];
-      coord[0] = node->X();
-      coord[1] = node->Y();
-      coord[2] = node->Z();
-      theTrsf.Transforms( coord[0], coord[1], coord[2] );
-      if ( theTargetMesh ) {
-        const SMDS_MeshNode * newNode = aTgtMesh->AddNode( coord[0], coord[1], coord[2] );
-        n2n_isnew.first->second = newNode;
-        myLastCreatedNodes.Append(newNode);
-        srcNodes.Append( node );
-      }
-      else if ( theCopy ) {
-        const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
-        n2n_isnew.first->second = newNode;
-        myLastCreatedNodes.Append(newNode);
-        srcNodes.Append( node );
-      }
-      else {
-        aMesh->MoveNode( node, coord[0], coord[1], coord[2] );
-        // node position on shape becomes invalid
-        const_cast< SMDS_MeshNode* > ( node )->SetPosition
-          ( SMDS_SpacePosition::originSpacePosition() );
-      }
+      SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+      while ( itN->more() )
+      {
+        const SMDS_MeshNode* node = cast2Node( itN->next() );
+        // check if a node has been already transformed
+        pair<TNodeNodeMap::iterator,bool> n2n_isnew =
+          nodeMap.insert( make_pair ( node, node ));
+        if ( !n2n_isnew.second )
+          continue;
 
-      // keep inverse elements
-      if ( !theCopy && !theTargetMesh && needReverse ) {
-        SMDS_ElemIteratorPtr invElemIt = node->GetInverseElementIterator();
-        while ( invElemIt->more() ) {
-          const SMDS_MeshElement* iel = invElemIt->next();
-          inverseElemSet.insert( iel );
+        node->GetXYZ( coord );
+        theTrsf.Transforms( coord[0], coord[1], coord[2] );
+        if ( theTargetMesh ) {
+          const SMDS_MeshNode * newNode = aTgtMesh->AddNode( coord[0], coord[1], coord[2] );
+          n2n_isnew.first->second = newNode;
+          myLastCreatedNodes.Append(newNode);
+          srcNodes.Append( node );
+        }
+        else if ( theCopy ) {
+          const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
+          n2n_isnew.first->second = newNode;
+          myLastCreatedNodes.Append(newNode);
+          srcNodes.Append( node );
+        }
+        else {
+          aMesh->MoveNode( node, coord[0], coord[1], coord[2] );
+          // node position on shape becomes invalid
+          const_cast< SMDS_MeshNode* > ( node )->SetPosition
+            ( SMDS_SpacePosition::originSpacePosition() );
+        }
+
+        // keep inverse elements
+        if ( !theCopy && !theTargetMesh && needReverse ) {
+          SMDS_ElemIteratorPtr invElemIt = node->GetInverseElementIterator();
+          while ( invElemIt->more() ) {
+            const SMDS_MeshElement* iel = invElemIt->next();
+            inverseElemSet.insert( iel );
+          }
         }
       }
-    }
-  }
+    } // loop on elems in { &orphanNode, &theElems };
 
   // either create new elements or reverse mirrored ones
   if ( !theCopy && !needReverse && !theTargetMesh )
     return PGroupIDs();
 
-  TIDSortedElemSet::iterator invElemIt = inverseElemSet.begin();
-  for ( ; invElemIt != inverseElemSet.end(); invElemIt++ )
-    theElems.insert( *invElemIt );
+  theElems.insert( inverseElemSet.begin(),inverseElemSet.end() );
 
   // Replicate or reverse elements
 
   std::vector<int> iForw;
+  vector<const SMDS_MeshNode*> nodes;
   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
   {
     const SMDS_MeshElement* elem = *itElem;
@@ -6659,123 +6896,45 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
     int                  nbNodes  = elem->NbNodes();
     if ( geomType == SMDSGeom_NONE ) continue; // node
 
-    switch ( geomType ) {
+    nodes.resize( nbNodes );
 
-    case SMDSGeom_POLYGON:  // ---------------------- polygon
+    if ( geomType == SMDSGeom_POLYHEDRA )  // ------------------ polyhedral volume
+    {
+      const SMDS_VtkVolume* aPolyedre = dynamic_cast<const SMDS_VtkVolume*>( elem );
+      if (!aPolyedre)
+        continue;
+      nodes.clear();
+      bool allTransformed = true;
+      int nbFaces = aPolyedre->NbFaces();
+      for (int iface = 1; iface <= nbFaces && allTransformed; iface++)
       {
-        vector<const SMDS_MeshNode*> poly_nodes (nbNodes);
-        int iNode = 0;
-        SMDS_ElemIteratorPtr itN = elem->nodesIterator();
-        while (itN->more()) {
-          const SMDS_MeshNode* node =
-            static_cast<const SMDS_MeshNode*>(itN->next());
+        int nbFaceNodes = aPolyedre->NbFaceNodes(iface);
+        for (int inode = 1; inode <= nbFaceNodes && allTransformed; inode++)
+        {
+          const SMDS_MeshNode* node = aPolyedre->GetFaceNode(iface, inode);
           TNodeNodeMap::iterator nodeMapIt = nodeMap.find(node);
-          if (nodeMapIt == nodeMap.end())
-            break; // not all nodes transformed
-          if (needReverse) {
-            // reverse mirrored faces and volumes
-            poly_nodes[nbNodes - iNode - 1] = (*nodeMapIt).second;
-          } else {
-            poly_nodes[iNode] = (*nodeMapIt).second;
-          }
-          iNode++;
-        }
-        if ( iNode != nbNodes )
-          continue; // not all nodes transformed
-
-        if ( theTargetMesh ) {
-          myLastCreatedElems.Append(aTgtMesh->AddPolygonalFace(poly_nodes));
-          srcElems.Append( elem );
-        }
-        else if ( theCopy ) {
-          myLastCreatedElems.Append(aMesh->AddPolygonalFace(poly_nodes));
-          srcElems.Append( elem );
-        }
-        else {
-          aMesh->ChangePolygonNodes(elem, poly_nodes);
-        }
-      }
-      break;
-
-    case SMDSGeom_POLYHEDRA:  // ------------------ polyhedral volume
-      {
-        const SMDS_VtkVolume* aPolyedre =
-          dynamic_cast<const SMDS_VtkVolume*>( elem );
-        if (!aPolyedre) {
-          MESSAGE("Warning: bad volumic element");
-          continue;
-        }
-
-        vector<const SMDS_MeshNode*> poly_nodes; poly_nodes.reserve( nbNodes );
-        vector<int> quantities; quantities.reserve( nbNodes );
-
-        bool allTransformed = true;
-        int nbFaces = aPolyedre->NbFaces();
-        for (int iface = 1; iface <= nbFaces && allTransformed; iface++) {
-          int nbFaceNodes = aPolyedre->NbFaceNodes(iface);
-          for (int inode = 1; inode <= nbFaceNodes && allTransformed; inode++) {
-            const SMDS_MeshNode* node = aPolyedre->GetFaceNode(iface, inode);
-            TNodeNodeMap::iterator nodeMapIt = nodeMap.find(node);
-            if (nodeMapIt == nodeMap.end()) {
-              allTransformed = false; // not all nodes transformed
-            } else {
-              poly_nodes.push_back((*nodeMapIt).second);
-            }
-            if ( needReverse && allTransformed )
-              std::reverse( poly_nodes.end() - nbFaceNodes, poly_nodes.end() );
-          }
-          quantities.push_back(nbFaceNodes);
-        }
-        if ( !allTransformed )
-          continue; // not all nodes transformed
-
-        if ( theTargetMesh ) {
-          myLastCreatedElems.Append(aTgtMesh->AddPolyhedralVolume(poly_nodes, quantities));
-          srcElems.Append( elem );
-        }
-        else if ( theCopy ) {
-          myLastCreatedElems.Append(aMesh->AddPolyhedralVolume(poly_nodes, quantities));
-          srcElems.Append( elem );
-        }
-        else {
-          aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities);
-        }
-      }
-      break;
-
-    case SMDSGeom_BALL: // -------------------- Ball
-      {
-        if ( !theCopy && !theTargetMesh ) continue;
-
-        TNodeNodeMap::iterator nodeMapIt = nodeMap.find( elem->GetNode(0) );
-        if (nodeMapIt == nodeMap.end())
-          continue; // not all nodes transformed
-
-        double diameter = static_cast<const SMDS_BallElement*>(elem)->GetDiameter();
-        if ( theTargetMesh ) {
-          myLastCreatedElems.Append(aTgtMesh->AddBall( nodeMapIt->second, diameter ));
-          srcElems.Append( elem );
-        }
-        else {
-          myLastCreatedElems.Append(aMesh->AddBall( nodeMapIt->second, diameter ));
-          srcElems.Append( elem );
+          if ( nodeMapIt == nodeMap.end() )
+            allTransformed = false; // not all nodes transformed
+          else
+            nodes.push_back((*nodeMapIt).second);
         }
+        if ( needReverse && allTransformed )
+          std::reverse( nodes.end() - nbFaceNodes, nodes.end() );
       }
-      break;
-
-    default: // ----------------------- Regular elements
-
+      if ( !allTransformed )
+        continue; // not all nodes transformed
+    }
+    else // ----------------------- the rest element types
+    {
       while ( iForw.size() < nbNodes ) iForw.push_back( iForw.size() );
-      const std::vector<int>& iRev = SMDS_MeshCell::reverseSmdsOrder( elem->GetEntityType() );
-      const std::vector<int>& i = needReverse ? iRev : iForw;
+      const vector<int>& iRev = SMDS_MeshCell::reverseSmdsOrder( elem->GetEntityType(), nbNodes );
+      const vector<int>&    i = needReverse ? iRev : iForw;
 
       // find transformed nodes
-      vector<const SMDS_MeshNode*> nodes(nbNodes);
       int iNode = 0;
       SMDS_ElemIteratorPtr itN = elem->nodesIterator();
       while ( itN->more() ) {
-        const SMDS_MeshNode* node =
-          static_cast<const SMDS_MeshNode*>( itN->next() );
+        const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( itN->next() );
         TNodeNodeMap::iterator nodeMapIt = nodeMap.find( node );
         if ( nodeMapIt == nodeMap.end() )
           break; // not all nodes transformed
@@ -6783,27 +6942,24 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
       }
       if ( iNode != nbNodes )
         continue; // not all nodes transformed
+    }
 
-      if ( theTargetMesh ) {
-        if ( SMDS_MeshElement* copy =
-             targetMeshEditor.AddElement( nodes, elem->GetType(), elem->IsPoly() )) {
-          myLastCreatedElems.Append( copy );
-          srcElems.Append( elem );
-        }
-      }
-      else if ( theCopy ) {
-        if ( AddElement( nodes, elem->GetType(), elem->IsPoly() ))
-          srcElems.Append( elem );
-      }
-      else {
-        // reverse element as it was reversed by transformation
-        if ( nbNodes > 2 )
-          aMesh->ChangeElementNodes( elem, &nodes[0], nbNodes );
-      }
-    } // switch ( geomType )
+    if ( editor ) {
+      // copy in this or a new mesh
+      if ( editor->AddElement( nodes, elemType.Init( elem, /*basicOnly=*/false )))
+        srcElems.Append( elem );
+    }
+    else {
+      // reverse element as it was reversed by transformation
+      if ( nbNodes > 2 )
+        aMesh->ChangeElementNodes( elem, &nodes[0], nbNodes );
+    }
 
   } // loop on elements
 
+  if ( editor && editor != this )
+    myLastCreatedElems = editor->myLastCreatedElems;
+
   PGroupIDs newGroupIDs;
 
   if ( ( theMakeGroups && theCopy ) ||
@@ -7007,32 +7163,72 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens,
 
 //================================================================================
 /*!
- * \brief Return list of group of nodes close to each other within theTolerance
- *        Search among theNodes or in the whole mesh if theNodes is empty using
- *        an Octree algorithm
+ *  * \brief Return list of group of nodes close to each other within theTolerance
+ *  *        Search among theNodes or in the whole mesh if theNodes is empty using
+ *  *        an Octree algorithm
+ *  \param [in,out] theNodes - the nodes to treat
+ *  \param [in]     theTolerance - the tolerance
+ *  \param [out]    theGroupsOfNodes - the result groups of coincident nodes
+ *  \param [in]     theSeparateCornersAndMedium - if \c true, in quadratic mesh puts 
+ *         corner and medium nodes in separate groups
  */
 //================================================================================
 
 void SMESH_MeshEditor::FindCoincidentNodes (TIDSortedNodeSet &   theNodes,
                                             const double         theTolerance,
-                                            TListOfListOfNodes & theGroupsOfNodes)
+                                            TListOfListOfNodes & theGroupsOfNodes,
+                                            bool                 theSeparateCornersAndMedium)
 {
   myLastCreatedElems.Clear();
   myLastCreatedNodes.Clear();
 
-  if ( theNodes.empty() )
-  { // get all nodes in the mesh
+  if ( myMesh->NbEdges  ( ORDER_QUADRATIC ) +
+       myMesh->NbFaces  ( ORDER_QUADRATIC ) +
+       myMesh->NbVolumes( ORDER_QUADRATIC ) == 0 )
+    theSeparateCornersAndMedium = false;
+
+  TIDSortedNodeSet& corners = theNodes;
+  TIDSortedNodeSet  medium;
+
+  if ( theNodes.empty() ) // get all nodes in the mesh
+  {
+    TIDSortedNodeSet* nodes[2] = { &corners, &medium };
     SMDS_NodeIteratorPtr nIt = GetMeshDS()->nodesIterator(/*idInceasingOrder=*/true);
-    while ( nIt->more() )
-      theNodes.insert( theNodes.end(),nIt->next());
+    if ( theSeparateCornersAndMedium )
+      while ( nIt->more() )
+      {
+        const SMDS_MeshNode* n = nIt->next();
+        TIDSortedNodeSet* & nodeSet = nodes[ SMESH_MesherHelper::IsMedium( n )];
+        nodeSet->insert( nodeSet->end(), n );
+      }
+    else
+      while ( nIt->more() )
+        theNodes.insert( theNodes.end(),nIt->next() );
+  }
+  else if ( theSeparateCornersAndMedium ) // separate corners from medium nodes
+  {
+    TIDSortedNodeSet::iterator nIt = corners.begin();
+    while ( nIt != corners.end() )
+      if ( SMESH_MesherHelper::IsMedium( *nIt ))
+      {
+        medium.insert( medium.end(), *nIt );
+        corners.erase( nIt++ );
+      }
+      else
+      {
+        ++nIt;
+      }
   }
 
-  SMESH_OctreeNode::FindCoincidentNodes ( theNodes, &theGroupsOfNodes, theTolerance);
+  if ( !corners.empty() )
+    SMESH_OctreeNode::FindCoincidentNodes ( corners, &theGroupsOfNodes, theTolerance );
+  if ( !medium.empty() )
+    SMESH_OctreeNode::FindCoincidentNodes ( medium, &theGroupsOfNodes, theTolerance );
 }
 
 //=======================================================================
 //function : SimplifyFace
-//purpose  :
+//purpose  : split a chain of nodes into several closed chains
 //=======================================================================
 
 int SMESH_MeshEditor::SimplifyFace (const vector<const SMDS_MeshNode *>& faceNodes,
@@ -7047,19 +7243,17 @@ int SMESH_MeshEditor::SimplifyFace (const vector<const SMDS_MeshNode *>& faceNod
   set<const SMDS_MeshNode*> nodeSet;
 
   // get simple seq of nodes
-  //const SMDS_MeshNode* simpleNodes[ nbNodes ];
   vector<const SMDS_MeshNode*> simpleNodes( nbNodes );
-  int iSimple = 0, nbUnique = 0;
+  int iSimple = 0;
 
   simpleNodes[iSimple++] = faceNodes[0];
-  nbUnique++;
   for (int iCur = 1; iCur < nbNodes; iCur++) {
     if (faceNodes[iCur] != simpleNodes[iSimple - 1]) {
       simpleNodes[iSimple++] = faceNodes[iCur];
-      if (nodeSet.insert( faceNodes[iCur] ).second)
-        nbUnique++;
+      nodeSet.insert( faceNodes[iCur] );
     }
   }
+  int nbUnique = nodeSet.size();
   int nbSimple = iSimple;
   if (simpleNodes[nbSimple - 1] == simpleNodes[0]) {
     nbSimple--;
@@ -7135,16 +7329,17 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
   // Fill nodeNodeMap and elems
 
   TListOfListOfNodes::iterator grIt = theGroupsOfNodes.begin();
-  for ( ; grIt != theGroupsOfNodes.end(); grIt++ ) {
+  for ( ; grIt != theGroupsOfNodes.end(); grIt++ )
+  {
     list<const SMDS_MeshNode*>& nodes = *grIt;
     list<const SMDS_MeshNode*>::iterator nIt = nodes.begin();
     const SMDS_MeshNode* nToKeep = *nIt;
-    //MESSAGE("node to keep " << nToKeep->GetID());
-    for ( ++nIt; nIt != nodes.end(); nIt++ ) {
+    for ( ++nIt; nIt != nodes.end(); nIt++ )
+    {
       const SMDS_MeshNode* nToRemove = *nIt;
-      nodeNodeMap.insert( TNodeNodeMap::value_type( nToRemove, nToKeep ));
-      if ( nToRemove != nToKeep ) {
-        //MESSAGE("  node to remove " << nToRemove->GetID());
+      nodeNodeMap.insert( make_pair( nToRemove, nToKeep ));
+      if ( nToRemove != nToKeep )
+      {
         rmNodeIds.push_back( nToRemove->GetID() );
         AddToSameGroups( nToKeep, nToRemove, aMesh );
         // set _alwaysComputed to a sub-mesh of VERTEX to enable mesh computing
@@ -7154,7 +7349,6 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
           if ( SMESH_subMesh* sm = myMesh->GetSubMeshContaining( nToRemove->getshapeId() ))
             sm->SetIsAlwaysComputed( true );
       }
-
       SMDS_ElemIteratorPtr invElemIt = nToRemove->GetInverseElementIterator();
       while ( invElemIt->more() ) {
         const SMDS_MeshElement* elem = invElemIt->next();
@@ -7164,29 +7358,34 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
   }
   // Change element nodes or remove an element
 
+  set<const SMDS_MeshNode*> nodeSet;
+  vector< const SMDS_MeshNode*> curNodes, uniqueNodes;
+  vector<int> iRepl;
+  ElemFeatures elemType;
+
   set<const SMDS_MeshElement*>::iterator eIt = elems.begin();
-  for ( ; eIt != elems.end(); eIt++ ) {
+  for ( ; eIt != elems.end(); eIt++ )
+  {
     const SMDS_MeshElement* elem = *eIt;
-    //MESSAGE(" ---- inverse elem on node to remove " << elem->GetID());
-    int nbNodes = elem->NbNodes();
-    int aShapeId = FindShape( elem );
+    const           int  nbNodes = elem->NbNodes();
+    const           int aShapeId = FindShape( elem );
 
-    set<const SMDS_MeshNode*> nodeSet;
-    vector< const SMDS_MeshNode*> curNodes( nbNodes ), uniqueNodes( nbNodes );
+    nodeSet.clear();
+    curNodes.resize( nbNodes );
+    uniqueNodes.resize( nbNodes );
+    iRepl.resize( nbNodes );
     int iUnique = 0, iCur = 0, nbRepl = 0;
-    vector<int> iRepl( nbNodes );
 
     // get new seq of nodes
     SMDS_ElemIteratorPtr itN = elem->nodesIterator();
-    while ( itN->more() ) {
-      const SMDS_MeshNode* n =
-        static_cast<const SMDS_MeshNode*>( itN->next() );
+    while ( itN->more() )
+    {
+      const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( itN->next() );
 
       TNodeNodeMap::iterator nnIt = nodeNodeMap.find( n );
       if ( nnIt != nodeNodeMap.end() ) { // n sticks
         n = (*nnIt).second;
-        // BUG 0020185: begin
-        {
+        { ////////// BUG 0020185: begin
           bool stopRecur = false;
           set<const SMDS_MeshNode*> nodesRecur;
           nodesRecur.insert(n);
@@ -7202,8 +7401,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
             else
               stopRecur = true;
           }
-        }
-        // BUG 0020185: end
+        } ////////// BUG 0020185: end
       }
       curNodes[ iCur ] = n;
       bool isUnique = nodeSet.insert( n ).second;
@@ -7218,64 +7416,64 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
 
     bool isOk = true;
     int nbUniqueNodes = nodeSet.size();
-    //MESSAGE("nbNodes nbUniqueNodes " << nbNodes << " " << nbUniqueNodes);
-    if ( nbNodes != nbUniqueNodes ) { // some nodes stick
-      // Polygons and Polyhedral volumes
-      if (elem->IsPoly()) {
-
-        if (elem->GetType() == SMDSAbs_Face) {
-          // Polygon
-          vector<const SMDS_MeshNode *> face_nodes (nbNodes);
-          int inode = 0;
-          for (; inode < nbNodes; inode++) {
-            face_nodes[inode] = curNodes[inode];
-          }
+    if ( nbNodes != nbUniqueNodes ) // some nodes stick
+    {
+      if (elem->IsPoly()) // Polygons and Polyhedral volumes
+      {
+        if (elem->GetType() == SMDSAbs_Face) // Polygon
+        {
+          elemType.Init( elem );
+          const bool isQuad = elemType.myIsQuad;
+          if ( isQuad )
+            SMDS_MeshCell::applyInterlace // interlace medium and corner nodes
+              ( SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Quad_Polygon, nbNodes ), curNodes );
 
+          // a polygon can divide into several elements
           vector<const SMDS_MeshNode *> polygons_nodes;
           vector<int> quantities;
-          int nbNew = SimplifyFace(face_nodes, polygons_nodes, quantities);
-          if (nbNew > 0) {
-            inode = 0;
-            for (int iface = 0; iface < nbNew; iface++) {
-              int nbNodes = quantities[iface];
-              vector<const SMDS_MeshNode *> poly_nodes (nbNodes);
-              for (int ii = 0; ii < nbNodes; ii++, inode++) {
-                poly_nodes[ii] = polygons_nodes[inode];
+          int nbNew = SimplifyFace( curNodes, polygons_nodes, quantities );
+          if (nbNew > 0)
+          {
+            vector<const SMDS_MeshNode *> face_nodes;
+            int inode = 0;
+            for (int iface = 0; iface < nbNew; iface++)
+            {
+              int nbNewNodes = quantities[iface];
+              face_nodes.assign( polygons_nodes.begin() + inode,
+                                 polygons_nodes.begin() + inode + nbNewNodes );
+              inode += nbNewNodes;
+              if ( isQuad ) // check if a result elem is a valid quadratic polygon
+              {
+                bool isValid = ( nbNewNodes % 2 == 0 );
+                for ( int i = 0; i < nbNewNodes && isValid; ++i )
+                  isValid = ( elem->IsMediumNode( face_nodes[i]) == bool( i % 2 ));
+                elemType.SetQuad( isValid );
+                if ( isValid ) // put medium nodes after corners
+                  SMDS_MeshCell::applyInterlaceRev
+                    ( SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Quad_Polygon,
+                                                          nbNewNodes ), face_nodes );
               }
-              SMDS_MeshElement* newElem = aMesh->AddPolygonalFace(poly_nodes);
-              myLastCreatedElems.Append(newElem);
-              if (aShapeId)
+              elemType.SetPoly(( nbNewNodes / ( elemType.myIsQuad + 1 ) > 4 ));
+
+              SMDS_MeshElement* newElem = AddElement( face_nodes, elemType );
+              if ( aShapeId )
                 aMesh->SetMeshElementOnShape(newElem, aShapeId);
             }
-
-            MESSAGE("ChangeElementNodes MergeNodes Polygon");
-            //aMesh->ChangeElementNodes(elem, &polygons_nodes[inode], quantities[nbNew - 1]);
-            vector<const SMDS_MeshNode *> polynodes(polygons_nodes.begin()+inode,polygons_nodes.end());
-            int quid =0;
-            if (nbNew > 0) quid = nbNew - 1;
-            vector<int> newquant(quantities.begin()+quid, quantities.end());
-            const SMDS_MeshElement* newElem = 0;
-            newElem = aMesh->AddPolyhedralVolume(polynodes, newquant);
-            myLastCreatedElems.Append(newElem);
-            if ( aShapeId && newElem )
-              aMesh->SetMeshElementOnShape( newElem, aShapeId );
-            rmElemIds.push_back(elem->GetID());
-          }
-          else {
-            rmElemIds.push_back(elem->GetID());
           }
+          rmElemIds.push_back(elem->GetID());
 
-        }
-        else if (elem->GetType() == SMDSAbs_Volume) {
-          // Polyhedral volume
+        } // Polygon
+
+        else if (elem->GetType() == SMDSAbs_Volume) // Polyhedral volume
+        {
           if (nbUniqueNodes < 4) {
             rmElemIds.push_back(elem->GetID());
           }
           else {
             // each face has to be analyzed in order to check volume validity
-            const SMDS_VtkVolume* aPolyedre =
-              dynamic_cast<const SMDS_VtkVolume*>( elem );
-            if (aPolyedre) {
+            const SMDS_VtkVolume* aPolyedre = dynamic_cast<const SMDS_VtkVolume*>( elem );
+            if (aPolyedre)
+            {
               int nbFaces = aPolyedre->NbFaces();
 
               vector<const SMDS_MeshNode *> poly_nodes;
@@ -7302,16 +7500,14 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
               }
 
               if (quantities.size() > 3)
-                {
-                  MESSAGE("ChangeElementNodes MergeNodes Polyhedron");
-                  //aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities);
-                  const SMDS_MeshElement* newElem = 0;
-                  newElem = aMesh->AddPolyhedralVolume(poly_nodes, quantities);
-                  myLastCreatedElems.Append(newElem);
-                  if ( aShapeId && newElem )
-                    aMesh->SetMeshElementOnShape( newElem, aShapeId );
-                  rmElemIds.push_back(elem->GetID());
-                }
+              {
+                const SMDS_MeshElement* newElem =
+                  aMesh->AddPolyhedralVolume(poly_nodes, quantities);
+                myLastCreatedElems.Append(newElem);
+                if ( aShapeId && newElem )
+                  aMesh->SetMeshElementOnShape( newElem, aShapeId );
+                rmElemIds.push_back(elem->GetID());
+              }
             }
             else {
               rmElemIds.push_back(elem->GetID());
@@ -7710,46 +7906,18 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
 
     } // if ( nbNodes != nbUniqueNodes ) // some nodes stick
 
-    if ( isOk ) { // the elem remains valid after sticking nodes
-      if (elem->IsPoly() && elem->GetType() == SMDSAbs_Volume)
-      {
-        // Change nodes of polyedre
-        const SMDS_VtkVolume* aPolyedre =
-          dynamic_cast<const SMDS_VtkVolume*>( elem );
-        if (aPolyedre) {
-          int nbFaces = aPolyedre->NbFaces();
-
-          vector<const SMDS_MeshNode *> poly_nodes;
-          vector<int> quantities (nbFaces);
-
-          for (int iface = 1; iface <= nbFaces; iface++) {
-            int inode, nbFaceNodes = aPolyedre->NbFaceNodes(iface);
-            quantities[iface - 1] = nbFaceNodes;
-
-            for (inode = 1; inode <= nbFaceNodes; inode++) {
-              const SMDS_MeshNode* curNode = aPolyedre->GetFaceNode(iface, inode);
-
-              TNodeNodeMap::iterator nnIt = nodeNodeMap.find( curNode );
-              if (nnIt != nodeNodeMap.end()) { // curNode sticks
-                curNode = (*nnIt).second;
-              }
-              poly_nodes.push_back(curNode);
-            }
-          }
-          aMesh->ChangePolyhedronNodes( elem, poly_nodes, quantities );
-        }
-      }
-      else // replace non-polyhedron elements
+    if ( isOk ) // the non-poly elem remains valid after sticking nodes
+    {
+      if ( nbNodes != nbUniqueNodes ||
+           !aMesh->ChangeElementNodes( elem, & curNodes[0], nbNodes ))
       {
-        const SMDSAbs_ElementType etyp = elem->GetType();
-        const int elemId               = elem->GetID();
-        const bool isPoly              = (elem->GetEntityType() == SMDSEntity_Polygon);
-        uniqueNodes.resize(nbUniqueNodes);
+        elemType.Init( elem ).SetID( elem->GetID() );
 
         SMESHDS_SubMesh * sm = aShapeId > 0 ? aMesh->MeshElements(aShapeId) : 0;
-
         aMesh->RemoveFreeElement(elem, sm, /*fromGroups=*/false);
-        SMDS_MeshElement* newElem = this->AddElement(uniqueNodes, etyp, isPoly, elemId);
+
+        uniqueNodes.resize(nbUniqueNodes);
+        SMDS_MeshElement* newElem = this->AddElement( uniqueNodes, elemType );
         if ( sm && newElem )
           sm->AddElement( newElem );
         if ( elem != newElem )
@@ -7768,6 +7936,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
   Remove( rmElemIds, false );
   Remove( rmNodeIds, true );
 
+  return;
 }
 
 
@@ -7790,10 +7959,6 @@ public:
   const SMDS_MeshElement* Get() const
   { return myElem; }
 
-  void Set(const SMDS_MeshElement* e) const
-  { myElem = e; }
-
-
 private:
   mutable const SMDS_MeshElement* myElem;
 };
@@ -7817,7 +7982,7 @@ void SMESH_MeshEditor::FindEqualElements(TIDSortedElemSet &        theElements,
   { // get all elements in the mesh
     SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator();
     while ( eIt->more() )
-      theElements.insert( theElements.end(), eIt->next());
+      theElements.insert( theElements.end(), eIt->next() );
   }
 
   vector< TGroupOfElems > arrayOfGroups;
@@ -7825,31 +7990,32 @@ void SMESH_MeshEditor::FindEqualElements(TIDSortedElemSet &        theElements,
   TMapOfNodeSet mapOfNodeSet;
 
   TIDSortedElemSet::iterator elemIt = theElements.begin();
-  for ( int i = 0, j=0; elemIt != theElements.end(); ++elemIt, ++j ) {
+  for ( int i = 0; elemIt != theElements.end(); ++elemIt )
+  {
     const SMDS_MeshElement* curElem = *elemIt;
     SortableElement SE(curElem);
-    int ind = -1;
     // check uniqueness
     pair< TMapOfNodeSet::iterator, bool> pp = mapOfNodeSet.insert(make_pair(SE, i));
-    if( !(pp.second) ) {
+    if ( !pp.second ) { // one more coincident elem
       TMapOfNodeSet::iterator& itSE = pp.first;
-      ind = (*itSE).second;
-      arrayOfGroups[ind].push_back(curElem->GetID());
+      int ind = (*itSE).second;
+      arrayOfGroups[ind].push_back( curElem->GetID() );
     }
     else {
-      groupOfElems.clear();
-      groupOfElems.push_back(curElem->GetID());
-      arrayOfGroups.push_back(groupOfElems);
+      arrayOfGroups.push_back( groupOfElems );
+      arrayOfGroups.back().push_back( curElem->GetID() );
       i++;
     }
   }
 
+  groupOfElems.clear();
   vector< TGroupOfElems >::iterator groupIt = arrayOfGroups.begin();
-  for ( ; groupIt != arrayOfGroups.end(); ++groupIt ) {
-    groupOfElems = *groupIt;
-    if ( groupOfElems.size() > 1 ) {
-      groupOfElems.sort();
-      theGroupsOfElementsID.push_back(groupOfElems);
+  for ( ; groupIt != arrayOfGroups.end(); ++groupIt )
+  {
+    if ( groupIt->size() > 1 ) {
+      //groupOfElems.sort(); -- theElements is sorted already
+      theGroupsOfElementsID.push_back( groupOfElems );
+      theGroupsOfElementsID.back().splice( theGroupsOfElementsID.back().end(), *groupIt );
     }
   }
 }
@@ -7920,6 +8086,24 @@ static const SMDS_MeshElement* findAdjacentFace(const SMDS_MeshNode* n1,
   return SMESH_MeshAlgos::FindFaceInSet( n1, n2, elemSet, avoidSet );
 }
 
+//=======================================================================
+//function : findSegment
+//purpose  : Return a mesh segment by two nodes one of which can be medium
+//=======================================================================
+
+static const SMDS_MeshElement* findSegment(const SMDS_MeshNode* n1,
+                                           const SMDS_MeshNode* n2)
+{
+  SMDS_ElemIteratorPtr it = n1->GetInverseElementIterator( SMDSAbs_Edge );
+  while ( it->more() )
+  {
+    const SMDS_MeshElement* seg = it->next();
+    if ( seg->GetNodeIndex( n2 ) >= 0 )
+      return seg;
+  }
+  return 0;
+}
+
 //=======================================================================
 //function : FindFreeBorder
 //purpose  :
@@ -7944,7 +8128,6 @@ bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode*             theFirst
   theNodes.push_back( theFirstNode );
   theNodes.push_back( theSecondNode );
 
-  //vector<const SMDS_MeshNode*> nodes;
   const SMDS_MeshNode *nIgnore = theFirstNode, *nStart = theSecondNode;
   TIDSortedElemSet foundElems;
   bool needTheLast = ( theLastNode != 0 );
@@ -7956,17 +8139,16 @@ bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode*             theFirst
     // find all free border faces sharing form nStart
 
     list< const SMDS_MeshElement* > curElemList;
-    list< const SMDS_MeshNode* > nStartList;
+    list< const SMDS_MeshNode* >    nStartList;
     SMDS_ElemIteratorPtr invElemIt = nStart->GetInverseElementIterator(SMDSAbs_Face);
     while ( invElemIt->more() ) {
       const SMDS_MeshElement* e = invElemIt->next();
       if ( e == curElem || foundElems.insert( e ).second ) {
         // get nodes
         int iNode = 0, nbNodes = e->NbNodes();
-        //const SMDS_MeshNode* nodes[nbNodes+1];
         vector<const SMDS_MeshNode*> nodes(nbNodes+1);
 
-        if(e->IsQuadratic()) {
+        if ( e->IsQuadratic() ) {
           const SMDS_VtkFace* F =
             dynamic_cast<const SMDS_VtkFace*>(e);
           if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
@@ -8083,6 +8265,8 @@ bool SMESH_MeshEditor::CheckFreeBorderNodes(const SMDS_MeshNode* theNode1,
 //=======================================================================
 //function : SewFreeBorder
 //purpose  :
+//warning  : for border-to-side sewing theSideSecondNode is considered as
+//           the last side node and theSideThirdNode is not used
 //=======================================================================
 
 SMESH_MeshEditor::Sew_Error
@@ -8106,9 +8290,9 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
   //    find side nodes and elements
   // ====================================
 
-  list< const SMDS_MeshNode* > nSide[ 2 ];
+  list< const SMDS_MeshNode* >    nSide[ 2 ];
   list< const SMDS_MeshElement* > eSide[ 2 ];
-  list< const SMDS_MeshNode* >::iterator nIt[ 2 ];
+  list< const SMDS_MeshNode* >::iterator    nIt[ 2 ];
   list< const SMDS_MeshElement* >::iterator eIt[ 2 ];
 
   // Free border 1
@@ -8347,9 +8531,23 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
   int nbNodes[]  = { nSide[0].size(), nSide[1].size() };
   int maxNbNodes = Max( nbNodes[0], nbNodes[1] );
 
+  bool toMergeConformal = ( nbNodes[0] == nbNodes[1] );
+  if ( toMergeConformal && toCreatePolygons )
+  {
+    // do not merge quadrangles if polygons are OK (IPAL0052824)
+    eIt[0] = eSide[0].begin();
+    eIt[1] = eSide[1].begin();
+    bool allQuads[2] = { true, true };
+    for ( int iBord = 0; iBord < 2; iBord++ ) { // loop on 2 borders
+      for ( ; allQuads[iBord] && eIt[iBord] != eSide[iBord].end(); ++eIt[iBord] )
+        allQuads[iBord] = ( (*eIt[iBord])->NbCornerNodes() == 4 );
+    }
+    toMergeConformal = ( !allQuads[0] && !allQuads[1] );
+  }
+
   TListOfListOfNodes nodeGroupsToMerge;
-  if ( nbNodes[0] == nbNodes[1] ||
-       ( theSideIsFreeBorder && !theSideThirdNode)) {
+  if (( toMergeConformal ) ||
+      ( theSideIsFreeBorder && !theSideThirdNode )) {
 
     // all nodes are to be merged
 
@@ -8367,10 +8565,9 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
     // insert new nodes into the border and the side to get equal nb of segments
 
     // get normalized parameters of nodes on the borders
-    //double param[ 2 ][ maxNbNodes ];
-    double* param[ 2 ];
-    param[0] = new double [ maxNbNodes ];
-    param[1] = new double [ maxNbNodes ];
+    vector< double > param[ 2 ];
+    param[0].resize( maxNbNodes );
+    param[1].resize( maxNbNodes );
     int iNode, iBord;
     for ( iBord = 0; iBord < 2; iBord++ ) { // loop on 2 borders
       list< const SMDS_MeshNode* >& nodes = nSide[ iBord ];
@@ -8415,8 +8612,8 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
         if ( i[ iBord ] > 0 )
           prevParam = Max( prevParam, param[iBord][ i[iBord] - 1 ]);
       }
-      double minParam = Min( param[ 0 ][ i[0] ], param[ 1 ][ i[1] ]);
-      double maxParam = Max( param[ 0 ][ i[0] ], param[ 1 ][ i[1] ]);
+      double  minParam = Min( param[ 0 ][ i[0] ], param[ 1 ][ i[1] ]);
+      double  maxParam = Max( param[ 0 ][ i[0] ], param[ 1 ][ i[1] ]);
       double minSegLen = Min( nextParam - minParam, maxParam - prevParam );
 
       // choose to insert or to merge nodes
@@ -8440,10 +8637,10 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
         // insert
         // ------
         int intoBord = ( du < 0 ) ? 0 : 1;
-        const SMDS_MeshElement* elem = *eIt[ intoBord ];
+        const SMDS_MeshElement* elem = *eIt [ intoBord ];
         const SMDS_MeshNode*    n1   = nPrev[ intoBord ];
-        const SMDS_MeshNode*    n2   = *nIt[ intoBord ];
-        const SMDS_MeshNode*    nIns = *nIt[ 1 - intoBord ];
+        const SMDS_MeshNode*    n2   = *nIt [ intoBord ];
+        const SMDS_MeshNode*    nIns = *nIt [ 1 - intoBord ];
         if ( intoBord == 1 ) {
           // move node of the border to be on a link of elem of the side
           gp_XYZ p1 (n1->X(), n1->Y(), n1->Z());
@@ -8453,7 +8650,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
           GetMeshDS()->MoveNode( nIns, p.X(), p.Y(), p.Z() );
         }
         insertMapIt = insertMap.find( elem );
-        bool notFound = ( insertMapIt == insertMap.end() );
+        bool  notFound = ( insertMapIt == insertMap.end() );
         bool otherLink = ( !notFound && (*insertMapIt).second.front() != n1 );
         if ( otherLink ) {
           // insert into another link of the same element:
@@ -8463,12 +8660,11 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
           const SMDS_MeshNode* n22 = nodeList.front(); nodeList.pop_front();
           InsertNodesIntoLink( elem, n12, n22, nodeList, toCreatePolygons );
           // 2. perform insertion into the link of adjacent faces
-          while (true) {
-            const SMDS_MeshElement* adjElem = findAdjacentFace( n12, n22, elem );
-            if ( adjElem )
-              InsertNodesIntoLink( adjElem, n12, n22, nodeList, toCreatePolygons );
-            else
-              break;
+          while ( const SMDS_MeshElement* adjElem = findAdjacentFace( n12, n22, elem )) {
+            InsertNodesIntoLink( adjElem, n12, n22, nodeList, toCreatePolygons );
+          }
+          while ( const SMDS_MeshElement* seg = findSegment( n12, n22 )) {
+            InsertNodesIntoLink( seg, n12, n22, nodeList );
           }
           if (toCreatePolyedrs) {
             // perform insertion into the links of adjacent volumes
@@ -8480,8 +8676,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
         }
         if ( notFound || otherLink ) {
           // add element and nodes of the side into the insertMap
-          insertMapIt = insertMap.insert
-            ( TElemOfNodeListMap::value_type( elem, list<const SMDS_MeshNode*>() )).first;
+          insertMapIt = insertMap.insert( make_pair( elem, list<const SMDS_MeshNode*>() )).first;
           (*insertMapIt).second.push_back( n1 );
           (*insertMapIt).second.push_back( n2 );
         }
@@ -8515,14 +8710,14 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
 
       InsertNodesIntoLink( elem, n1, n2, nodeList, toCreatePolygons );
 
+      while ( const SMDS_MeshElement* seg = findSegment( n1, n2 )) {
+        InsertNodesIntoLink( seg, n1, n2, nodeList );
+      }
+
       if ( !theSideIsFreeBorder ) {
         // look for and insert nodes into the faces adjacent to elem
-        while (true) {
-          const SMDS_MeshElement* adjElem = findAdjacentFace( n1, n2, elem );
-          if ( adjElem )
-            InsertNodesIntoLink( adjElem, n1, n2, nodeList, toCreatePolygons );
-          else
-            break;
+        while ( const SMDS_MeshElement* adjElem = findAdjacentFace( n1, n2, elem )) {
+          InsertNodesIntoLink( adjElem, n1, n2, nodeList, toCreatePolygons );
         }
       }
       if (toCreatePolyedrs) {
@@ -8530,69 +8725,155 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
         UpdateVolumes(n1, n2, nodeList);
       }
     }
-
-    delete param[0];
-    delete param[1];
   } // end: insert new nodes
 
   MergeNodes ( nodeGroupsToMerge );
 
+
+  // Remove coincident segments
+
+  // get new segments
+  TIDSortedElemSet segments;
+  SMESH_SequenceOfElemPtr newFaces;
+  for ( int i = 1; i <= myLastCreatedElems.Length(); ++i )
+  {
+    if ( !myLastCreatedElems(i) ) continue;
+    if ( myLastCreatedElems(i)->GetType() == SMDSAbs_Edge )
+      segments.insert( segments.end(), myLastCreatedElems(i) );
+    else
+      newFaces.Append( myLastCreatedElems(i) );
+  }
+  // get segments adjacent to merged nodes
+  TListOfListOfNodes::iterator groupIt = nodeGroupsToMerge.begin();
+  for ( ; groupIt != nodeGroupsToMerge.end(); groupIt++ )
+  {
+    const list<const SMDS_MeshNode*>& nodes = *groupIt;
+    SMDS_ElemIteratorPtr segIt = nodes.front()->GetInverseElementIterator( SMDSAbs_Edge );
+    while ( segIt->more() )
+      segments.insert( segIt->next() );
+  }
+
+  // find coincident
+  TListOfListOfElementsID equalGroups;
+  if ( !segments.empty() )
+    FindEqualElements( segments, equalGroups );
+  if ( !equalGroups.empty() )
+  {
+    // remove from segments those that will be removed
+    TListOfListOfElementsID::iterator itGroups = equalGroups.begin();
+    for ( ; itGroups != equalGroups.end(); ++itGroups )
+    {
+      list< int >& group = *itGroups;
+      list< int >::iterator id = group.begin();
+      for ( ++id; id != group.end(); ++id )
+        if ( const SMDS_MeshElement* seg = GetMeshDS()->FindElement( *id ))
+          segments.erase( seg );
+    }
+    // remove equal segments
+    MergeElements( equalGroups );
+
+    // restore myLastCreatedElems
+    myLastCreatedElems = newFaces;
+    TIDSortedElemSet::iterator seg = segments.begin();
+    for ( ; seg != segments.end(); ++seg )
+      myLastCreatedElems.Append( *seg );
+  }
+
   return aResult;
 }
 
 //=======================================================================
 //function : InsertNodesIntoLink
-//purpose  : insert theNodesToInsert into theFace between theBetweenNode1
+//purpose  : insert theNodesToInsert into theElement between theBetweenNode1
 //           and theBetweenNode2 and split theElement
 //=======================================================================
 
-void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement*     theFace,
+void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement*     theElement,
                                            const SMDS_MeshNode*        theBetweenNode1,
                                            const SMDS_MeshNode*        theBetweenNode2,
                                            list<const SMDS_MeshNode*>& theNodesToInsert,
                                            const bool                  toCreatePoly)
 {
+  if ( !theElement ) return;
+
+  SMESHDS_Mesh *aMesh = GetMeshDS();
+  vector<const SMDS_MeshElement*> newElems;
+
+  if ( theElement->GetType() == SMDSAbs_Edge )
+  {
+    theNodesToInsert.push_front( theBetweenNode1 );
+    theNodesToInsert.push_back ( theBetweenNode2 );
+    list<const SMDS_MeshNode*>::iterator n = theNodesToInsert.begin();
+    const SMDS_MeshNode* n1 = *n;
+    for ( ++n; n != theNodesToInsert.end(); ++n )
+    {
+      const SMDS_MeshNode* n2 = *n;
+      if ( const SMDS_MeshElement* seg = aMesh->FindEdge( n1, n2 ))
+        AddToSameGroups( seg, theElement, aMesh );
+      else
+        newElems.push_back( aMesh->AddEdge ( n1, n2 ));
+      n1 = n2;
+    }
+    theNodesToInsert.pop_front();
+    theNodesToInsert.pop_back();
+
+    if ( theElement->IsQuadratic() ) // add a not split part
+    {
+      vector<const SMDS_MeshNode*> nodes( theElement->begin_nodes(),
+                                          theElement->end_nodes() );
+      int iOther = 0, nbN = nodes.size();
+      for ( ; iOther < nbN; ++iOther )
+        if ( nodes[iOther] != theBetweenNode1 &&
+             nodes[iOther] != theBetweenNode2 )
+          break;
+      if      ( iOther == 0 )
+      {
+        if ( const SMDS_MeshElement* seg = aMesh->FindEdge( nodes[0], nodes[1] ))
+          AddToSameGroups( seg, theElement, aMesh );
+        else
+          newElems.push_back( aMesh->AddEdge ( nodes[0], nodes[1] ));
+      }
+      else if ( iOther == 2 )
+      {
+        if ( const SMDS_MeshElement* seg = aMesh->FindEdge( nodes[1], nodes[2] ))
+          AddToSameGroups( seg, theElement, aMesh );
+        else
+          newElems.push_back( aMesh->AddEdge ( nodes[1], nodes[2] ));
+      }
+    }
+    // treat new elements
+    for ( size_t i = 0; i < newElems.size(); ++i )
+      if ( newElems[i] )
+      {
+        aMesh->SetMeshElementOnShape( newElems[i], theElement->getshapeId() );
+        myLastCreatedElems.Append( newElems[i] );
+      }
+    ReplaceElemInGroups( theElement, newElems, aMesh );
+    aMesh->RemoveElement( theElement );
+    return;
+
+  } // if ( theElement->GetType() == SMDSAbs_Edge )
+
+  const SMDS_MeshElement* theFace = theElement;
   if ( theFace->GetType() != SMDSAbs_Face ) return;
 
   // find indices of 2 link nodes and of the rest nodes
   int iNode = 0, il1, il2, i3, i4;
   il1 = il2 = i3 = i4 = -1;
-  //const SMDS_MeshNode* nodes[ theFace->NbNodes() ];
   vector<const SMDS_MeshNode*> nodes( theFace->NbNodes() );
 
-  if(theFace->IsQuadratic()) {
-    const SMDS_VtkFace* F =
-      dynamic_cast<const SMDS_VtkFace*>(theFace);
-    if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
-    // use special nodes iterator
-    SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
-    while( anIter->more() ) {
-      const SMDS_MeshNode* n = cast2Node(anIter->next());
-      if ( n == theBetweenNode1 )
-        il1 = iNode;
-      else if ( n == theBetweenNode2 )
-        il2 = iNode;
-      else if ( i3 < 0 )
-        i3 = iNode;
-      else
-        i4 = iNode;
-      nodes[ iNode++ ] = n;
-    }
-  }
-  else {
-    SMDS_ElemIteratorPtr nodeIt = theFace->nodesIterator();
-    while ( nodeIt->more() ) {
-      const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
-      if ( n == theBetweenNode1 )
-        il1 = iNode;
-      else if ( n == theBetweenNode2 )
-        il2 = iNode;
-      else if ( i3 < 0 )
-        i3 = iNode;
-      else
-        i4 = iNode;
-      nodes[ iNode++ ] = n;
-    }
+  SMDS_NodeIteratorPtr nodeIt = theFace->interlacedNodesIterator();
+  while ( nodeIt->more() ) {
+    const SMDS_MeshNode* n = nodeIt->next();
+    if ( n == theBetweenNode1 )
+      il1 = iNode;
+    else if ( n == theBetweenNode2 )
+      il2 = iNode;
+    else if ( i3 < 0 )
+      i3 = iNode;
+    else
+      i4 = iNode;
+    nodes[ iNode++ ] = n;
   }
   if ( il1 < 0 || il2 < 0 || i3 < 0 )
     return ;
@@ -8622,9 +8903,8 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement*     theFace,
     // add nodes of face up to first node of link
     bool isFLN = false;
 
-    if(theFace->IsQuadratic()) {
-      const SMDS_VtkFace* F =
-        dynamic_cast<const SMDS_VtkFace*>(theFace);
+    if ( theFace->IsQuadratic() ) {
+      const SMDS_VtkFace* F = dynamic_cast<const SMDS_VtkFace*>(theFace);
       if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
       // use special nodes iterator
       SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
@@ -8666,28 +8946,12 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement*     theFace,
       }
     }
 
-    // edit or replace the face
-    SMESHDS_Mesh *aMesh = GetMeshDS();
-
-    if (theFace->IsPoly()) {
-      aMesh->ChangePolygonNodes(theFace, poly_nodes);
-    }
-    else {
-      int aShapeId = FindShape( theFace );
-
-      SMDS_MeshElement* newElem = aMesh->AddPolygonalFace(poly_nodes);
-      myLastCreatedElems.Append(newElem);
-      if ( aShapeId && newElem )
-        aMesh->SetMeshElementOnShape( newElem, aShapeId );
-
-      aMesh->RemoveElement(theFace);
-    }
-    return;
+    // make a new face
+    newElems.push_back( aMesh->AddPolygonalFace( poly_nodes ));
   }
 
-  SMESHDS_Mesh *aMesh = GetMeshDS();
-  if( !theFace->IsQuadratic() ) {
-
+  else if ( !theFace->IsQuadratic() )
+  {
     // put aNodesToInsert between theBetweenNode1 and theBetweenNode2
     int nbLinkNodes = 2 + aNodesToInsert.size();
     //const SMDS_MeshNode* linkNodes[ nbLinkNodes ];
@@ -8736,41 +9000,32 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement*     theFace,
     }
 
     // create new elements
-    int aShapeId = FindShape( theFace );
-
     i1 = 0; i2 = 1;
     for ( iSplit = 0; iSplit < nbSplits - 1; iSplit++ ) {
       SMDS_MeshElement* newElem = 0;
       if ( iSplit == iBestQuad )
-        newElem = aMesh->AddFace (linkNodes[ i1++ ],
-                                  linkNodes[ i2++ ],
-                                  nodes[ i3 ],
-                                  nodes[ i4 ]);
+        newElems.push_back( aMesh->AddFace (linkNodes[ i1++ ],
+                                            linkNodes[ i2++ ],
+                                            nodes[ i3 ],
+                                            nodes[ i4 ]));
       else
-        newElem = aMesh->AddFace (linkNodes[ i1++ ],
-                                  linkNodes[ i2++ ],
-                                  nodes[ iSplit < iBestQuad ? i4 : i3 ]);
-      myLastCreatedElems.Append(newElem);
-      if ( aShapeId && newElem )
-        aMesh->SetMeshElementOnShape( newElem, aShapeId );
+        newElems.push_back( aMesh->AddFace (linkNodes[ i1++ ],
+                                            linkNodes[ i2++ ],
+                                            nodes[ iSplit < iBestQuad ? i4 : i3 ]));
     }
 
-    // change nodes of theFace
     const SMDS_MeshNode* newNodes[ 4 ];
     newNodes[ 0 ] = linkNodes[ i1 ];
     newNodes[ 1 ] = linkNodes[ i2 ];
     newNodes[ 2 ] = nodes[ iSplit >= iBestQuad ? i3 : i4 ];
     newNodes[ 3 ] = nodes[ i4 ];
-    //aMesh->ChangeElementNodes( theFace, newNodes, iSplit == iBestQuad ? 4 : 3 );
-    const SMDS_MeshElement* newElem = 0;
     if (iSplit == iBestQuad)
-      newElem = aMesh->AddFace( newNodes[0], newNodes[1], newNodes[2], newNodes[3] );
+      newElems.push_back( aMesh->AddFace( newNodes[0], newNodes[1], newNodes[2], newNodes[3] ));
     else
-      newElem = aMesh->AddFace( newNodes[0], newNodes[1], newNodes[2] );
-    myLastCreatedElems.Append(newElem);
-    if ( aShapeId && newElem )
-      aMesh->SetMeshElementOnShape( newElem, aShapeId );
-} // end if(!theFace->IsQuadratic())
+      newElems.push_back( aMesh->AddFace( newNodes[0], newNodes[1], newNodes[2] ));
+
+  } // end if(!theFace->IsQuadratic())
+
   else { // theFace is quadratic
     // we have to split theFace on simple triangles and one simple quadrangle
     int tmp = il1/2;
@@ -8797,66 +9052,38 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement*     theFace,
     //           n4           n6      n5     n4
 
     // create new elements
-    int aShapeId = FindShape( theFace );
-
     int n1,n2,n3;
-    if(nbFaceNodes==6) { // quadratic triangle
-      SMDS_MeshElement* newElem =
-        aMesh->AddFace(nodes[3],nodes[4],nodes[5]);
-      myLastCreatedElems.Append(newElem);
-      if ( aShapeId && newElem )
-        aMesh->SetMeshElementOnShape( newElem, aShapeId );
-      if(theFace->IsMediumNode(nodes[il1])) {
+    if ( nbFaceNodes == 6 ) { // quadratic triangle
+      newElems.push_back( aMesh->AddFace( nodes[3], nodes[4], nodes[5] ));
+      if ( theFace->IsMediumNode(nodes[il1]) ) {
         // create quadrangle
-        newElem = aMesh->AddFace(nodes[0],nodes[1],nodes[3],nodes[5]);
-        myLastCreatedElems.Append(newElem);
-        if ( aShapeId && newElem )
-          aMesh->SetMeshElementOnShape( newElem, aShapeId );
+        newElems.push_back( aMesh->AddFace( nodes[0], nodes[1], nodes[3], nodes[5] ));
         n1 = 1;
         n2 = 2;
         n3 = 3;
       }
       else {
         // create quadrangle
-        newElem = aMesh->AddFace(nodes[1],nodes[2],nodes[3],nodes[5]);
-        myLastCreatedElems.Append(newElem);
-        if ( aShapeId && newElem )
-          aMesh->SetMeshElementOnShape( newElem, aShapeId );
+        newElems.push_back( aMesh->AddFace( nodes[1], nodes[2], nodes[3], nodes[5] ));
         n1 = 0;
         n2 = 1;
         n3 = 5;
       }
     }
     else { // nbFaceNodes==8 - quadratic quadrangle
-      SMDS_MeshElement* newElem =
-        aMesh->AddFace(nodes[3],nodes[4],nodes[5]);
-      myLastCreatedElems.Append(newElem);
-      if ( aShapeId && newElem )
-        aMesh->SetMeshElementOnShape( newElem, aShapeId );
-      newElem = aMesh->AddFace(nodes[5],nodes[6],nodes[7]);
-      myLastCreatedElems.Append(newElem);
-      if ( aShapeId && newElem )
-        aMesh->SetMeshElementOnShape( newElem, aShapeId );
-      newElem = aMesh->AddFace(nodes[5],nodes[7],nodes[3]);
-      myLastCreatedElems.Append(newElem);
-      if ( aShapeId && newElem )
-        aMesh->SetMeshElementOnShape( newElem, aShapeId );
-      if(theFace->IsMediumNode(nodes[il1])) {
+      newElems.push_back( aMesh->AddFace( nodes[3], nodes[4], nodes[5] ));
+      newElems.push_back( aMesh->AddFace( nodes[5], nodes[6], nodes[7] ));
+      newElems.push_back( aMesh->AddFace( nodes[5], nodes[7], nodes[3] ));
+      if ( theFace->IsMediumNode( nodes[ il1 ])) {
         // create quadrangle
-        newElem = aMesh->AddFace(nodes[0],nodes[1],nodes[3],nodes[7]);
-        myLastCreatedElems.Append(newElem);
-        if ( aShapeId && newElem )
-          aMesh->SetMeshElementOnShape( newElem, aShapeId );
+        newElems.push_back( aMesh->AddFace( nodes[0], nodes[1], nodes[3], nodes[7] ));
         n1 = 1;
         n2 = 2;
         n3 = 3;
       }
       else {
         // create quadrangle
-        newElem = aMesh->AddFace(nodes[1],nodes[2],nodes[3],nodes[7]);
-        myLastCreatedElems.Append(newElem);
-        if ( aShapeId && newElem )
-          aMesh->SetMeshElementOnShape( newElem, aShapeId );
+        newElems.push_back( aMesh->AddFace( nodes[1], nodes[2], nodes[3], nodes[7] ));
         n1 = 0;
         n2 = 1;
         n3 = 7;
@@ -8864,30 +9091,34 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement*     theFace,
     }
     // create needed triangles using n1,n2,n3 and inserted nodes
     int nbn = 2 + aNodesToInsert.size();
-    //const SMDS_MeshNode* aNodes[nbn];
     vector<const SMDS_MeshNode*> aNodes(nbn);
-    aNodes[0] = nodes[n1];
+    aNodes[0    ] = nodes[n1];
     aNodes[nbn-1] = nodes[n2];
     list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
     for ( iNode = 1; nIt != aNodesToInsert.end(); nIt++ ) {
       aNodes[iNode++] = *nIt;
     }
-    for(i=1; i<nbn; i++) {
-      SMDS_MeshElement* newElem =
-        aMesh->AddFace(aNodes[i-1],aNodes[i],nodes[n3]);
-      myLastCreatedElems.Append(newElem);
-      if ( aShapeId && newElem )
-        aMesh->SetMeshElementOnShape( newElem, aShapeId );
-    }
+    for ( i = 1; i < nbn; i++ )
+      newElems.push_back( aMesh->AddFace( aNodes[i-1], aNodes[i], nodes[n3] ));
   }
-  // remove old face
+
+  // remove the old face
+  for ( size_t i = 0; i < newElems.size(); ++i )
+    if ( newElems[i] )
+    {
+      aMesh->SetMeshElementOnShape( newElems[i], theFace->getshapeId() );
+      myLastCreatedElems.Append( newElems[i] );
+    }
+  ReplaceElemInGroups( theFace, newElems, aMesh );
   aMesh->RemoveElement(theFace);
-}
+
+} // InsertNodesIntoLink()
 
 //=======================================================================
 //function : UpdateVolumes
 //purpose  :
 //=======================================================================
+
 void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode*        theBetweenNode1,
                                       const SMDS_MeshNode*        theBetweenNode2,
                                       list<const SMDS_MeshNode*>& theNodesToInsert)
@@ -8949,24 +9180,16 @@ void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode*        theBetweenNode
       quantities[iface] = nbFaceNodes + nbInserted;
     }
 
-    // Replace or update the volume
+    // Replace the volume
     SMESHDS_Mesh *aMesh = GetMeshDS();
 
-    if (elem->IsPoly()) {
-      aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities);
-
-    }
-    else {
-      int aShapeId = FindShape( elem );
-
-      SMDS_MeshElement* newElem =
-        aMesh->AddPolyhedralVolume(poly_nodes, quantities);
-      myLastCreatedElems.Append(newElem);
-      if (aShapeId && newElem)
-        aMesh->SetMeshElementOnShape(newElem, aShapeId);
-
-      aMesh->RemoveElement(elem);
+    if ( SMDS_MeshElement* newElem = aMesh->AddPolyhedralVolume( poly_nodes, quantities ))
+    {
+      aMesh->SetMeshElementOnShape( newElem, elem->getshapeId() );
+      myLastCreatedElems.Append( newElem );
+      ReplaceElemInGroups( elem, newElem, aMesh );
     }
+    aMesh->RemoveElement( elem );
   }
 }
 
@@ -8996,7 +9219,7 @@ namespace
 
 //=======================================================================
 /*!
- * \brief Convert elements contained in a submesh to quadratic
+ * \brief Convert elements contained in a sub-mesh to quadratic
  * \return int - nb of checked elements
  */
 //=======================================================================
@@ -9519,6 +9742,8 @@ int SMESH_MeshEditor::removeQuadElem(SMESHDS_SubMesh *    theSm,
 {
   int nbElem = 0;
   SMESHDS_Mesh* meshDS = GetMeshDS();
+  ElemFeatures elemType;
+  vector<const SMDS_MeshNode *> nodes;
 
   while( theItr->more() )
   {
@@ -9526,11 +9751,11 @@ int SMESH_MeshEditor::removeQuadElem(SMESHDS_SubMesh *    theSm,
     nbElem++;
     if( elem && elem->IsQuadratic())
     {
-      int id                    = elem->GetID();
-      int nbCornerNodes         = elem->NbCornerNodes();
-      SMDSAbs_ElementType aType = elem->GetType();
+      // get elem data
+      int nbCornerNodes = elem->NbCornerNodes();
+      nodes.assign( elem->begin_nodes(), elem->end_nodes() );
 
-      vector<const SMDS_MeshNode *> nodes( elem->begin_nodes(), elem->end_nodes() );
+      elemType.Init( elem, /*basicOnly=*/false ).SetID( elem->GetID() ).SetQuad( false );
 
       //remove a quadratic element
       if ( !theSm || !theSm->Contains( elem ))
@@ -9538,13 +9763,13 @@ int SMESH_MeshEditor::removeQuadElem(SMESHDS_SubMesh *    theSm,
       meshDS->RemoveFreeElement( elem, theSm, /*fromGroups=*/false );
 
       // remove medium nodes
-      for ( unsigned i = nbCornerNodes; i < nodes.size(); ++i )
+      for ( size_t i = nbCornerNodes; i < nodes.size(); ++i )
         if ( nodes[i]->NbInverseElements() == 0 )
           meshDS->RemoveFreeNode( nodes[i], theSm );
 
       // add a linear element
       nodes.resize( nbCornerNodes );
-      SMDS_MeshElement * newElem = AddElement( nodes, aType, false, id );
+      SMDS_MeshElement * newElem = AddElement( nodes, elemType );
       ReplaceElemInGroups(elem, newElem, meshDS);
       if( theSm && newElem )
         theSm->AddElement( newElem );
@@ -10135,11 +10360,15 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
   if ( aResult != SEW_OK)
     return aResult;
 
-  list< int > nodeIDsToRemove/*, elemIDsToRemove*/;
+  list< int > nodeIDsToRemove;
+  vector< const SMDS_MeshNode*> nodes;
+  ElemFeatures elemType;
+
   // loop on nodes replacement map
   TNodeNodeMap::iterator nReplaceMapIt = nReplaceMap.begin(), nnIt;
   for ( ; nReplaceMapIt != nReplaceMap.end(); nReplaceMapIt++ )
-    if ( (*nReplaceMapIt).first != (*nReplaceMapIt).second ) {
+    if ( (*nReplaceMapIt).first != (*nReplaceMapIt).second )
+    {
       const SMDS_MeshNode* nToRemove = (*nReplaceMapIt).first;
       nodeIDsToRemove.push_back( nToRemove->GetID() );
       // loop on elements sharing nToRemove
@@ -10148,11 +10377,10 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
         const SMDS_MeshElement* e = invElemIt->next();
         // get a new suite of nodes: make replacement
         int nbReplaced = 0, i = 0, nbNodes = e->NbNodes();
-        vector< const SMDS_MeshNode*> nodes( nbNodes );
+        nodes.resize( nbNodes );
         SMDS_ElemIteratorPtr nIt = e->nodesIterator();
         while ( nIt->more() ) {
-          const SMDS_MeshNode* n =
-            static_cast<const SMDS_MeshNode*>( nIt->next() );
+          const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nIt->next() );
           nnIt = nReplaceMap.find( n );
           if ( nnIt != nReplaceMap.end() ) {
             nbReplaced++;
@@ -10164,21 +10392,17 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
         //         elemIDsToRemove.push_back( e->GetID() );
         //       else
         if ( nbReplaced )
+        {
+          elemType.Init( e, /*basicOnly=*/false ).SetID( e->GetID() );
+          aMesh->RemoveElement( e );
+
+          if ( SMDS_MeshElement* newElem = this->AddElement( nodes, elemType ))
           {
-            SMDSAbs_ElementType etyp = e->GetType();
-            SMDS_MeshElement* newElem = this->AddElement(nodes, etyp, false);
-            if (newElem)
-              {
-                myLastCreatedElems.Append(newElem);
-                AddToSameGroups(newElem, e, aMesh);
-                int aShapeId = e->getshapeId();
-                if ( aShapeId )
-                  {
-                    aMesh->SetMeshElementOnShape( newElem, aShapeId );
-                  }
-              }
-            aMesh->RemoveElement(e);
+            AddToSameGroups( newElem, e, aMesh );
+            if ( int aShapeId = e->getshapeId() )
+              aMesh->SetMeshElementOnShape( newElem, aShapeId );
           }
+        }
       }
     }
 
@@ -10408,44 +10632,19 @@ void SMESH_MeshEditor::DoubleElements( const TIDSortedElemSet& theElements )
 
   // duplicate elements
 
-  if ( type == SMDSAbs_Ball )
-  {
-    SMDS_UnstructuredGrid* vtkGrid = mesh->getGrid();
-    while ( elemIt->more() )
-    {
-      const SMDS_MeshElement* elem = elemIt->next();
-      if ( elem->GetType() != SMDSAbs_Ball )
-        continue;
-      if (( elem = mesh->AddBall( elem->GetNode(0),
-                                  vtkGrid->GetBallDiameter( elem->getVtkId() ))))
-        myLastCreatedElems.Append( elem );
-    }
-  }
-  else
+  ElemFeatures elemType;
+
+  vector< const SMDS_MeshNode* > nodes;
+  while ( elemIt->more() )
   {
-    vector< const SMDS_MeshNode* > nodes;
-    while ( elemIt->more() )
-    {
-      const SMDS_MeshElement* elem = elemIt->next();
-      if ( elem->GetType() != type )
-        continue;
+    const SMDS_MeshElement* elem = elemIt->next();
+    if ( elem->GetType() != type )
+      continue;
 
-      nodes.assign( elem->begin_nodes(), elem->end_nodes() );
+    elemType.Init( elem, /*basicOnly=*/false );
+    nodes.assign( elem->begin_nodes(), elem->end_nodes() );
 
-      if ( type == SMDSAbs_Volume  && elem->GetVtkType() == VTK_POLYHEDRON )
-      {
-        std::vector<int> quantities =
-          static_cast< const SMDS_VtkVolume* >( elem )->GetQuantities();
-        elem = mesh->AddPolyhedralVolume( nodes, quantities );
-      }
-      else
-      {
-        AddElement( nodes, type, elem->IsPoly() );
-        elem = 0; // myLastCreatedElems is already filled
-      }
-      if ( elem )
-        myLastCreatedElems.Append( elem );
-    }
+    AddElement( nodes, elemType );
   }
 }
 
@@ -10476,7 +10675,7 @@ bool SMESH_MeshEditor::DoubleNodes( const TIDSortedElemSet& theElems,
     return false;
 
   bool res = false;
-  std::map< const SMDS_MeshNode*, const SMDS_MeshNode* > anOldNodeToNewNode;
+  TNodeNodeMap anOldNodeToNewNode;
   // duplicate elements and nodes
   res = doubleNodes( aMeshDS, theElems, theNodesNot, anOldNodeToNewNode, true );
   // replce nodes by duplications
@@ -10496,16 +10695,18 @@ bool SMESH_MeshEditor::DoubleNodes( const TIDSortedElemSet& theElems,
 */
 //================================================================================
 
-bool SMESH_MeshEditor::doubleNodes( SMESHDS_Mesh*     theMeshDS,
-                                    const TIDSortedElemSet& theElems,
-                                    const TIDSortedElemSet& theNodesNot,
-                                    std::map< const SMDS_MeshNode*,
-                                    const SMDS_MeshNode* >& theNodeNodeMap,
-                                    const bool theIsDoubleElem )
+bool SMESH_MeshEditor::doubleNodes(SMESHDS_Mesh*           theMeshDS,
+                                   const TIDSortedElemSet& theElems,
+                                   const TIDSortedElemSet& theNodesNot,
+                                   TNodeNodeMap&           theNodeNodeMap,
+                                   const bool              theIsDoubleElem )
 {
   MESSAGE("doubleNodes");
-  // iterate on through element and duplicate them (by nodes duplication)
+  // iterate through element and duplicate them (by nodes duplication)
   bool res = false;
+  std::vector<const SMDS_MeshNode*> newNodes;
+  ElemFeatures elemType;
+
   TIDSortedElemSet::const_iterator elemItr = theElems.begin();
   for ( ;  elemItr != theElems.end(); ++elemItr )
   {
@@ -10513,19 +10714,21 @@ bool SMESH_MeshEditor::doubleNodes( SMESHDS_Mesh*     theMeshDS,
     if (!anElem)
       continue;
 
-    bool isDuplicate = false;
     // duplicate nodes to duplicate element
-    std::vector<const SMDS_MeshNode*> newNodes( anElem->NbNodes() );
+    bool isDuplicate = false;
+    newNodes.resize( anElem->NbNodes() );
     SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
     int ind = 0;
     while ( anIter->more() )
     {
-
-      SMDS_MeshNode* aCurrNode = (SMDS_MeshNode*)anIter->next();
-      SMDS_MeshNode* aNewNode = aCurrNode;
-      if ( theNodeNodeMap.find( aCurrNode ) != theNodeNodeMap.end() )
-        aNewNode = (SMDS_MeshNode*)theNodeNodeMap[ aCurrNode ];
-      else if ( theIsDoubleElem && theNodesNot.find( aCurrNode ) == theNodesNot.end() )
+      const SMDS_MeshNode* aCurrNode = static_cast<const SMDS_MeshNode*>( anIter->next() );
+      const SMDS_MeshNode*  aNewNode = aCurrNode;
+      TNodeNodeMap::iterator     n2n = theNodeNodeMap.find( aCurrNode );
+      if ( n2n != theNodeNodeMap.end() )
+      {
+        aNewNode = n2n->second;
+      }
+      else if ( theIsDoubleElem && !theNodesNot.count( aCurrNode ))
       {
         // duplicate node
         aNewNode = theMeshDS->AddNode( aCurrNode->X(), aCurrNode->Y(), aCurrNode->Z() );
@@ -10540,9 +10743,9 @@ bool SMESH_MeshEditor::doubleNodes( SMESHDS_Mesh*     theMeshDS,
       continue;
 
     if ( theIsDoubleElem )
-      AddElement(newNodes, anElem->GetType(), anElem->IsPoly());
+      AddElement( newNodes, elemType.Init( anElem, /*basicOnly=*/false ));
     else
-      theMeshDS->ChangeElementNodes( anElem, &newNodes[ 0 ], anElem->NbNodes() );
+      theMeshDS->ChangeElementNodes( anElem, &newNodes[ 0 ], newNodes.size() );
 
     res = true;
   }
@@ -11459,7 +11662,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
             }
           else
             {
-              INFOS("Quadratic multiple joints not implemented");
+              //INFOS("Quadratic multiple joints not implemented");
               // TODO quadratic nodes
             }
         }
@@ -12273,7 +12476,8 @@ bool SMESH_MeshEditor::Make2DMeshFrom3D()
   SMESHDS_Mesh* aMesh = GetMeshDS();
   if (!aMesh)
     return false;
-  //bool res = false;
+
+  ElemFeatures faceType( SMDSAbs_Face );
   int nbFree = 0, nbExisted = 0, nbCreated = 0;
   SMDS_VolumeIteratorPtr vIt = aMesh->volumesIterator();
   while(vIt->more())
@@ -12281,8 +12485,8 @@ bool SMESH_MeshEditor::Make2DMeshFrom3D()
     const SMDS_MeshVolume* volume = vIt->next();
     SMDS_VolumeTool vTool( volume, /*ignoreCentralNodes=*/false );
     vTool.SetExternalNormal();
-    //const bool isPoly = volume->IsPoly();
     const int iQuad = volume->IsQuadratic();
+    faceType.SetQuad( iQuad );
     for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ )
     {
       if (!vTool.IsFreeFace(iface))
@@ -12294,22 +12498,27 @@ bool SMESH_MeshEditor::Make2DMeshFrom3D()
       int inode = 0;
       for ( ; inode < nbFaceNodes; inode += iQuad+1)
         nodes.push_back(faceNodes[inode]);
-      if (iQuad) { // add medium nodes
+
+      if (iQuad) // add medium nodes
+      {
         for ( inode = 1; inode < nbFaceNodes; inode += 2)
           nodes.push_back(faceNodes[inode]);
         if ( nbFaceNodes == 9 ) // bi-quadratic quad
           nodes.push_back(faceNodes[8]);
       }
       // add new face based on volume nodes
-      if (aMesh->FindElement( nodes, SMDSAbs_Face, /*noMedium=*/false) ) {
-        nbExisted++;
-        continue; // face already exsist
+      if (aMesh->FindElement( nodes, SMDSAbs_Face, /*noMedium=*/false) )
+      {
+        nbExisted++; // face already exsist
+      }
+      else
+      {
+        AddElement( nodes, faceType.SetPoly( nbFaceNodes/(iQuad+1) > 4 ));
+        nbCreated++;
       }
-      AddElement(nodes, SMDSAbs_Face, ( !iQuad && nbFaceNodes/(iQuad+1) > 4 ));
-      nbCreated++;
     }
   }
-  return ( nbFree==(nbExisted+nbCreated) );
+  return ( nbFree == ( nbExisted + nbCreated ));
 }
 
 namespace
@@ -12371,9 +12580,16 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
   SMDS_VolumeTool vTool;
   TIDSortedElemSet avoidSet;
   const TIDSortedElemSet emptySet, *elemSet = aroundElements ? &elements : &emptySet;
-  int inode;
+  size_t inode;
 
   typedef vector<const SMDS_MeshNode*> TConnectivity;
+  TConnectivity tgtNodes;
+  ElemFeatures elemKind( missType ), elemToCopy;
+
+  vector<const SMDS_MeshElement*> presentBndElems;
+  vector<TConnectivity>           missingBndElems;
+  vector<int>                     freeFacets;
+  TConnectivity nodes, elemNodes;
 
   SMDS_ElemIteratorPtr eIt;
   if (elements.empty()) eIt = aMesh->elementsIterator(elemType);
@@ -12383,33 +12599,40 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
   {
     const SMDS_MeshElement* elem = eIt->next();
     const int              iQuad = elem->IsQuadratic();
+    elemKind.SetQuad( iQuad );
 
     // ------------------------------------------------------------------------------------
     // 1. For an elem, get present bnd elements and connectivities of missing bnd elements
     // ------------------------------------------------------------------------------------
-    vector<const SMDS_MeshElement*> presentBndElems;
-    vector<TConnectivity>           missingBndElems;
-    TConnectivity nodes, elemNodes;
+    presentBndElems.clear();
+    missingBndElems.clear();
+    freeFacets.clear(); nodes.clear(); elemNodes.clear();
     if ( vTool.Set(elem, /*ignoreCentralNodes=*/true) ) // elem is a volume --------------
     {
-      vTool.SetExternalNormal();
       const SMDS_MeshElement* otherVol = 0;
       for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ )
       {
         if ( !vTool.IsFreeFace(iface, &otherVol) &&
              ( !aroundElements || elements.count( otherVol )))
           continue;
+        freeFacets.push_back( iface );
+      }
+      if ( missType == SMDSAbs_Face )
+        vTool.SetExternalNormal();
+      for ( size_t i = 0; i < freeFacets.size(); ++i )
+      {
+        int                iface = freeFacets[i];
         const SMDS_MeshNode** nn = vTool.GetFaceNodes(iface);
-        const int    nbFaceNodes = vTool.NbFaceNodes (iface);
+        const size_t nbFaceNodes = vTool.NbFaceNodes (iface);
         if ( missType == SMDSAbs_Edge ) // boundary edges
         {
           nodes.resize( 2+iQuad );
           for ( int i = 0; i < nbFaceNodes; i += 1+iQuad)
           {
             for ( int j = 0; j < nodes.size(); ++j )
-              nodes[j] =nn[i+j];
+              nodes[j] = nn[ i+j ];
             if ( const SMDS_MeshElement* edge =
-                 aMesh->FindElement(nodes,SMDSAbs_Edge,/*noMedium=*/false))
+                 aMesh->FindElement( nodes, SMDSAbs_Edge, /*noMedium=*/false ))
               presentBndElems.push_back( edge );
             else
               missingBndElems.push_back( nodes );
@@ -12480,17 +12703,17 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
     if ( targetMesh != myMesh )
       // instead of making a map of nodes in this mesh and targetMesh,
       // we create nodes with same IDs.
-      for ( int i = 0; i < missingBndElems.size(); ++i )
+      for ( size_t i = 0; i < missingBndElems.size(); ++i )
       {
         TConnectivity& srcNodes = missingBndElems[i];
-        TConnectivity  nodes( srcNodes.size() );
-        for ( inode = 0; inode < nodes.size(); ++inode )
-          nodes[inode] = getNodeWithSameID( tgtMeshDS, srcNodes[inode] );
-        if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( nodes,
+        tgtNodes.resize( srcNodes.size() );
+        for ( inode = 0; inode < srcNodes.size(); ++inode )
+          tgtNodes[inode] = getNodeWithSameID( tgtMeshDS, srcNodes[inode] );
+        if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( tgtNodes,
                                                                    missType,
                                                                    /*noMedium=*/false))
           continue;
-        tgtEditor.AddElement(nodes, missType, !iQuad && nodes.size()/(iQuad+1)>4);
+        tgtEditor.AddElement( tgtNodes, elemKind.SetPoly( tgtNodes.size()/(iQuad+1) > 4 ));
         ++nbAddedBnd;
       }
     else
@@ -12501,16 +12724,16 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
                                                                    missType,
                                                                    /*noMedium=*/false))
           continue;
-        SMDS_MeshElement* elem =
-          tgtEditor.AddElement(nodes, missType, !iQuad && nodes.size()/(iQuad+1)>4);
-        ++nbAddedBnd;
+        SMDS_MeshElement* newElem = 
+          tgtEditor.AddElement( nodes, elemKind.SetPoly( nodes.size()/(iQuad+1) > 4 ));
+        nbAddedBnd += bool( newElem );
 
         // try to set a new element to a shape
         if ( myMesh->HasShapeToMesh() )
         {
           bool ok = true;
           set< pair<TopAbs_ShapeEnum, int > > mediumShapes;
-          const int nbN = nodes.size() / (iQuad+1 );
+          const size_t nbN = nodes.size() / (iQuad+1 );
           for ( inode = 0; inode < nbN && ok; ++inode )
           {
             pair<int, TopAbs_ShapeEnum> i_stype =
@@ -12530,7 +12753,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
             }
           }
           if ( ok && mediumShapes.begin()->first == missShapeType )
-            aMesh->SetMeshElementOnShape( elem, mediumShapes.begin()->second );
+            aMesh->SetMeshElementOnShape( newElem, mediumShapes.begin()->second );
         }
       }
 
@@ -12541,15 +12764,15 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
       for ( int i = 0 ; i < presentBndElems.size(); ++i )
       {
         const SMDS_MeshElement* e = presentBndElems[i];
-        TConnectivity nodes( e->NbNodes() );
+        tgtNodes.resize( e->NbNodes() );
         for ( inode = 0; inode < nodes.size(); ++inode )
-          nodes[inode] = getNodeWithSameID( tgtMeshDS, e->GetNode(inode) );
-        presentEditor->AddElement(nodes, e->GetType(), e->IsPoly());
+          tgtNodes[inode] = getNodeWithSameID( tgtMeshDS, e->GetNode(inode) );
+        presentEditor->AddElement( tgtNodes, elemToCopy.Init( e ));
       }
     else // store present elements to add them to a group
       for ( int i = 0 ; i < presentBndElems.size(); ++i )
       {
-        presentEditor->myLastCreatedElems.Append(presentBndElems[i]);
+        presentEditor->myLastCreatedElems.Append( presentBndElems[i] );
       }
 
   } // loop on given elements
@@ -12576,10 +12799,10 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
     while (eIt->more())
     {
       const SMDS_MeshElement* elem = eIt->next();
-      TConnectivity nodes( elem->NbNodes() );
-      for ( inode = 0; inode < nodes.size(); ++inode )
-        nodes[inode] = getNodeWithSameID( tgtMeshDS, elem->GetNode(inode) );
-      tgtEditor.AddElement(nodes, elemType, elem->IsPoly());
+      tgtNodes.resize( elem->NbNodes() );
+      for ( inode = 0; inode < tgtNodes.size(); ++inode )
+        tgtNodes[inode] = getNodeWithSameID( tgtMeshDS, elem->GetNode(inode) );
+      tgtEditor.AddElement( tgtNodes, elemToCopy.Init( elem ));
 
       tgtEditor.myLastCreatedElems.Clear();
     }
index 25c01f81d250281ac9b0d087ef8d777de801e1dc..13bf425ab52c4e64225e600fe7261134d4893268 100644 (file)
@@ -73,21 +73,49 @@ public:
   void                           ClearLastCreated();
   SMESH_ComputeErrorPtr &        GetError() { return myError; }
 
+  // --------------------------------------------------------------------------------
+  struct ElemFeatures //!< Features of element to create
+  {
+    SMDSAbs_ElementType myType;
+    bool                myIsPoly, myIsQuad;
+    int                 myID;
+    double              myBallDiameter;
+    std::vector<int>    myPolyhedQuantities;
+
+    SMESH_EXPORT ElemFeatures( SMDSAbs_ElementType type=SMDSAbs_All, bool isPoly=false, bool isQuad=false )
+      :myType( type ), myIsPoly(isPoly), myIsQuad(isQuad), myID(-1), myBallDiameter(0) {}
+
+    SMESH_EXPORT ElemFeatures& Init( SMDSAbs_ElementType type, bool isPoly=false, bool isQuad=false )
+    { myType = type; myIsPoly = isPoly; myIsQuad = isQuad; return *this; }
+
+    SMESH_EXPORT ElemFeatures& Init( const SMDS_MeshElement* elem, bool basicOnly=true );
+
+    SMESH_EXPORT ElemFeatures& Init( double diameter )
+    { myType = SMDSAbs_Ball; myBallDiameter = diameter; return *this; }
+
+    SMESH_EXPORT ElemFeatures& Init( vector<int>& quanities, bool isQuad=false )
+    { myType = SMDSAbs_Volume; myIsPoly = 1; myIsQuad = isQuad;
+      myPolyhedQuantities.swap( quanities ); return *this; }
+
+    SMESH_EXPORT ElemFeatures& Init( const vector<int>& quanities, bool isQuad=false )
+    { myType = SMDSAbs_Volume; myIsPoly = 1; myIsQuad = isQuad;
+      myPolyhedQuantities = quanities; return *this; }
+
+    SMESH_EXPORT ElemFeatures& SetPoly(bool isPoly) { myIsPoly = isPoly; return *this; }
+    SMESH_EXPORT ElemFeatures& SetQuad(bool isQuad) { myIsQuad = isQuad; return *this; }
+    SMESH_EXPORT ElemFeatures& SetID  (int ID)      { myID = ID; return *this; }
+  };
+
   /*!
    * \brief Add element
    */
   SMDS_MeshElement* AddElement(const std::vector<const SMDS_MeshNode*> & nodes,
-                               const SMDSAbs_ElementType                 type,
-                               const bool                                isPoly,
-                               const int                                 ID = -1,
-                               const double                              ballDiameter=0.);
+                               const ElemFeatures&                       features);
   /*!
    * \brief Add element
    */
-  SMDS_MeshElement* AddElement(const std::vector<int>  & nodeIDs,
-                               const SMDSAbs_ElementType type,
-                               const bool                isPoly,
-                               const int                 ID = -1);
+  SMDS_MeshElement* AddElement(const std::vector<int> & nodeIDs,
+                               const ElemFeatures&      features);
 
   int Remove (const std::list< int >& theElemIDs, const bool isNodes);
   // Remove a node or an element.
@@ -193,7 +221,7 @@ public:
 
   /*!
    * \brief For hexahedra that will be split into prisms, finds facets to
-   *        split into triangles 
+   *        split into triangles
    *  \param [in,out] theHexas - the hexahedra
    *  \param [in]     theFacetNormal - facet normal
    *  \param [out]    theFacets - the hexahedra and found facet IDs
@@ -202,6 +230,16 @@ public:
                              const gp_Ax1&     theFacetNormal,
                              TFacetOfElem &    theFacets);
 
+  /*!
+   * \brief Split bi-quadratic elements into linear ones without creation of additional nodes
+   *   - bi-quadratic triangle will be split into 3 linear quadrangles;
+   *   - bi-quadratic quadrangle will be split into 4 linear quadrangles;
+   *   - tri-quadratic hexahedron will be split into 8 linear hexahedra;
+   *   Quadratic elements of lower dimension  adjacent to the split bi-quadratic element
+   *   will be split in order to keep the mesh conformal.
+   *  \param elems - elements to split
+   */
+  void SplitBiQuadraticIntoLinear(TIDSortedElemSet& theElems);
 
   enum SmoothMethod { LAPLACIAN = 0, CENTROIDAL };
 
@@ -412,7 +450,8 @@ public:
 
   void FindCoincidentNodes (TIDSortedNodeSet &   theNodes,
                             const double         theTolerance,
-                            TListOfListOfNodes & theGroupsOfNodes);
+                            TListOfListOfNodes & theGroupsOfNodes,
+                            bool                 theSeparateCornersAndMedium);
   // Return list of group of nodes close to each other within theTolerance.
   // Search among theNodes or in the whole mesh if theNodes is empty.
 
@@ -741,11 +780,11 @@ public:
   void LinearAngleVariation(const int     NbSteps,
                             list<double>& theAngles);
 
-  bool doubleNodes( SMESHDS_Mesh*                                           theMeshDS,
-                    const TIDSortedElemSet&                                 theElems,
-                    const TIDSortedElemSet&                                 theNodesNot,
-                    std::map< const SMDS_MeshNode*, const SMDS_MeshNode* >& theNodeNodeMap,
-                    const bool                                              theIsDoubleElem );
+  bool doubleNodes( SMESHDS_Mesh*           theMeshDS,
+                    const TIDSortedElemSet& theElems,
+                    const TIDSortedElemSet& theNodesNot,
+                    TNodeNodeMap&           theNodeNodeMap,
+                    const bool              theIsDoubleElem );
 
   void copyPosition( const SMDS_MeshNode* from,
                      const SMDS_MeshNode* to );
index 7537bf8a8b969383fa62b618213f10f8cb08d1bb..3ceea9fa34ca191c0b8aed017df5ff22f2b41a06 100644 (file)
@@ -191,12 +191,13 @@ bool SMESH_MesherHelper::IsQuadraticSubMesh(const TopoDS_Shape& aSh)
     }
   }
 
-  if ( nbOldLinks == myTLinkNodeMap.size() )
+  // if ( nbOldLinks == myTLinkNodeMap.size() ) -- 0023068
+  if ( myTLinkNodeMap.empty() )
     myCreateQuadratic = false;
 
-  if(!myCreateQuadratic) {
+  if ( !myCreateQuadratic )
     myTLinkNodeMap.clear();
-  }
+
   SetSubShape( aSh );
 
   return myCreateQuadratic;
@@ -648,10 +649,10 @@ gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face&   F,
       }
       catch (Standard_Failure& exc) {
       }
-      if ( !uvOK ) {
-        for ( TopExp_Explorer vert(F,TopAbs_VERTEX); !uvOK && vert.More(); vert.Next() )
-          uvOK = ( V == vert.Current() );
-        if ( !uvOK ) {
+      if ( !uvOK )
+      {
+        if ( !IsSubShape( V, F ))
+        {
           MESSAGE ( "SMESH_MesherHelper::GetNodeUV(); Vertex " << vertexID
                     << " not in face " << GetMeshDS()->ShapeToIndex( F ) );
           // get UV of a vertex closest to the node
@@ -668,7 +669,8 @@ gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face&   F,
             }
           }
         }
-        else {
+        else
+        {
           uvOK = false;
           TopTools_ListIteratorOfListOfShape it( myMesh->GetAncestors( V ));
           for ( ; it.More(); it.Next() ) {
@@ -677,13 +679,23 @@ gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face&   F,
               double f,l;
               Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edge, F, f, l);
               if ( !C2d.IsNull() ) {
-                double u = ( V == TopExp::FirstVertex( edge ) ) ?  f : l;
+                double u = ( V == IthVertex( 0, edge )) ?  f : l;
                 uv = C2d->Value( u );
                 uvOK = true;
                 break;
               }
             }
           }
+          if ( !uvOK && V.Orientation() == TopAbs_INTERNAL )
+          {
+            Handle(ShapeAnalysis_Surface) projector = GetSurface( F );
+            if ( n2 ) uv = GetNodeUV( F, n2 );
+            if ( Precision::IsInfinite( uv.X() ))
+              uv = projector->NextValueOfUV( uv, BRep_Tool::Pnt( V ), BRep_Tool::Tolerance( F ));
+            else
+              uv = projector->ValueOfUV( BRep_Tool::Pnt( V ), BRep_Tool::Tolerance( F ));
+            uvOK = ( projector->Gap() < getFaceMaxTol( F ));
+          }
         }
       }
       if ( n2 && IsSeamShape( vertexID ))
@@ -806,6 +818,24 @@ GeomAPI_ProjectPointOnSurf& SMESH_MesherHelper::GetProjector(const TopoDS_Face&
   return *( i_proj->second );
 }
 
+//=======================================================================
+//function : GetSurface
+//purpose  : Return a cached ShapeAnalysis_Surface of a FACE
+//=======================================================================
+
+Handle(ShapeAnalysis_Surface) SMESH_MesherHelper::GetSurface(const TopoDS_Face& F ) const
+{
+  Handle(Geom_Surface) surface = BRep_Tool::Surface( F );
+  int faceID = GetMeshDS()->ShapeToIndex( F );
+  TID2Surface::iterator i_surf = myFace2Surface.find( faceID );
+  if ( i_surf == myFace2Surface.end() && faceID )
+  {
+    Handle(ShapeAnalysis_Surface) surf( new ShapeAnalysis_Surface( surface ));
+    i_surf = myFace2Surface.insert( make_pair( faceID, surf )).first;
+  }
+  return i_surf->second;
+}
+
 namespace
 {
   gp_XY AverageUV(const gp_XY& uv1, const gp_XY& uv2) { return ( uv1 + uv2 ) / 2.; }
@@ -1329,23 +1359,34 @@ const SMDS_MeshNode* SMESH_MesherHelper::GetCentralNode(const SMDS_MeshNode* n1,
   bool toCheck = true;
   if ( !F.IsNull() && !force3d )
   {
-    gp_XY uv[8] = {
-      GetNodeUV( F,n1,  n3, &toCheck ),
-      GetNodeUV( F,n2,  n4, &toCheck ),
-      GetNodeUV( F,n3,  n1, &toCheck ),
-      GetNodeUV( F,n4,  n2, &toCheck ),
-      GetNodeUV( F,n12, n3 ),
-      GetNodeUV( F,n23, n4 ),
-      GetNodeUV( F,n34, n2 ),
-      GetNodeUV( F,n41, n2 )
-    };
-    AdjustByPeriod( F, uv, 8 ); // put uv[] within a period (IPAL52698)
-
-    uvAvg = calcTFI (0.5, 0.5, uv[0],uv[1],uv[2],uv[3], uv[4],uv[5],uv[6],uv[7] );
+    Handle(ShapeAnalysis_Surface) surface = GetSurface( F );
+    if ( HasDegeneratedEdges() || surface->HasSingularities( 1e-7 ))
+    {
+      gp_Pnt center = calcTFI (0.5, 0.5, // IPAL0052863
+                               SMESH_TNodeXYZ(n1),  SMESH_TNodeXYZ(n2),
+                               SMESH_TNodeXYZ(n3),  SMESH_TNodeXYZ(n4),
+                               SMESH_TNodeXYZ(n12), SMESH_TNodeXYZ(n23),
+                               SMESH_TNodeXYZ(n34), SMESH_TNodeXYZ(n41));
+      gp_Pnt2d uv12 = GetNodeUV( F, n12, n3, &toCheck );
+      uvAvg = surface->NextValueOfUV( uv12, center, BRep_Tool::Tolerance( F )).XY();
+    }
+    else
+    {
+      gp_XY uv[8] = {
+        GetNodeUV( F,n1,  n3, &toCheck ),
+        GetNodeUV( F,n2,  n4, &toCheck ),
+        GetNodeUV( F,n3,  n1, &toCheck ),
+        GetNodeUV( F,n4,  n2, &toCheck ),
+        GetNodeUV( F,n12, n3 ),
+        GetNodeUV( F,n23, n4 ),
+        GetNodeUV( F,n34, n2 ),
+        GetNodeUV( F,n41, n2 )
+      };
+      AdjustByPeriod( F, uv, 8 ); // put uv[] within a period (IPAL52698)
 
-    TopLoc_Location loc;
-    Handle( Geom_Surface ) S = BRep_Tool::Surface( F, loc );
-    P = S->Value( uvAvg.X(), uvAvg.Y() ).Transformed( loc );
+      uvAvg = calcTFI (0.5, 0.5, uv[0],uv[1],uv[2],uv[3], uv[4],uv[5],uv[6],uv[7] );
+    }
+    P = surface->Value( uvAvg );
     centralNode = meshDS->AddNode( P.X(), P.Y(), P.Z() );
     // if ( mySetElemOnShape ) node is not elem!
     meshDS->SetNodeOnFace( centralNode, faceID, uvAvg.X(), uvAvg.Y() );
@@ -1580,6 +1621,28 @@ const SMDS_MeshNode* SMESH_MesherHelper::GetMediumNode(const SMDS_MeshNode* n1,
   {
     F = TopoDS::Face(meshDS->IndexToShape( faceID = pos.first ));
     uv[0] = GetNodeUV(F,n1,n2, force3d ? 0 : &uvOK[0]);
+    if (( !force3d ) &&
+        ( HasDegeneratedEdges() || GetSurface( F )->HasSingularities( 1e-7 )))
+    {
+      // IPAL52850 (degen VERTEX not at singularity)
+      // project middle point to a surface
+      SMESH_TNodeXYZ p1( n1 ), p2( n2 );
+      gp_Pnt pMid = 0.5 * ( p1 + p2 );
+      Handle(ShapeAnalysis_Surface) projector = GetSurface( F );
+      gp_Pnt2d uvMid;
+      if ( uvOK[0] )
+        uvMid = projector->NextValueOfUV( uv[0], pMid, BRep_Tool::Tolerance( F ));
+      else
+        uvMid = projector->ValueOfUV( pMid, getFaceMaxTol( F ));
+      if ( projector->Gap() * projector->Gap() < ( p1 - p2 ).SquareModulus() / 4 )
+      {
+        gp_Pnt pProj = projector->Value( uvMid );
+        n12  = meshDS->AddNode( pProj.X(), pProj.Y(), pProj.Z() );
+        meshDS->SetNodeOnFace( n12, faceID, uvMid.X(), uvMid.Y() );
+        myTLinkNodeMap.insert( make_pair ( link, n12 ));
+        return n12;
+      }
+    }
     uv[1] = GetNodeUV(F,n2,n1, force3d ? 0 : &uvOK[1]);
   }
   else if ( pos.second == TopAbs_EDGE )
@@ -1996,26 +2059,28 @@ SMDS_MeshFace* SMESH_MesherHelper::AddPolygonalFace (const vector<const SMDS_Mes
   SMESHDS_Mesh * meshDS = GetMeshDS();
   SMDS_MeshFace* elem = 0;
 
-  if(!myCreateQuadratic) {
+  if(!myCreateQuadratic)
+  {
     if(id)
       elem = meshDS->AddPolygonalFaceWithID(nodes, id);
     else
       elem = meshDS->AddPolygonalFace(nodes);
   }
-  else {
-    vector<const SMDS_MeshNode*> newNodes;
+  else
+  {
+    vector<const SMDS_MeshNode*> newNodes( nodes.size() * 2 );
+    newNodes = nodes;
     for ( int i = 0; i < nodes.size(); ++i )
     {
       const SMDS_MeshNode* n1 = nodes[i];
       const SMDS_MeshNode* n2 = nodes[(i+1)%nodes.size()];
       const SMDS_MeshNode* n12 = GetMediumNode( n1, n2, force3d, TopAbs_FACE );
-      newNodes.push_back( n1 );
       newNodes.push_back( n12 );
     }
     if(id)
-      elem = meshDS->AddPolygonalFaceWithID(newNodes, id);
+      elem = meshDS->AddQuadPolygonalFaceWithID(newNodes, id);
     else
-      elem = meshDS->AddPolygonalFace(newNodes);
+      elem = meshDS->AddQuadPolygonalFace(newNodes);
   }
   if ( mySetElemOnShape && myShapeID > 0 )
     meshDS->SetMeshElementOnShape( elem, myShapeID );
@@ -3395,13 +3460,13 @@ namespace { // Structures used by FixQuadraticElements()
     }
     void SetContinuesFaces() const;
     const QFace* GetContinuesFace( const QFace* face ) const;
-    bool OnBoundary() const;
+    bool   OnBoundary() const;
     gp_XYZ MiddlePnt() const { return ( XYZ( node1() ) + XYZ( node2() )) / 2.; }
     gp_XYZ MediumPnt() const { return XYZ( _mediumNode ); }
 
-    SMDS_TypeOfPosition MediumPos() const
+    SMDS_TypeOfPosition  MediumPos() const
     { return _mediumNode->GetPosition()->GetTypeOfPosition(); }
-    SMDS_TypeOfPosition EndPos(bool isSecond) const
+    SMDS_TypeOfPosition  EndPos(bool isSecond) const
     { return (isSecond ? node2() : node1())->GetPosition()->GetTypeOfPosition(); }
     const SMDS_MeshNode* EndPosNode(SMDS_TypeOfPosition pos) const
     { return EndPos(0) == pos ? node1() : EndPos(1) == pos ? node2() : 0; }
@@ -4950,7 +5015,7 @@ void SMESH_MesherHelper::FixQuadraticElements(SMESH_ComputeErrorPtr& compError,
               face = TopoDS::Face( f );
               faceHlp.SetSubShape( face );
               Handle(Geom_Surface) surf = BRep_Tool::Surface(face,loc);
-              bool isStraight[2];
+              //bool isStraight[2]; // commented for issue 0023118
               for ( int is1 = 0; is1 < 2; ++is1 ) // move0 or move1
               {
                 TChainLink& link = is1 ? chain.back() : chain.front();
@@ -4963,13 +5028,13 @@ void SMESH_MesherHelper::FixQuadraticElements(SMESH_ComputeErrorPtr& compError,
                 ( is1 ? move1 : move0 ).SetCoord( uvMove.X(), uvMove.Y(), 0 );
                 if ( !is1 ) // correct nodeOnFace for move1 (issue 0020919)
                   nodeOnFace = (*(++chain.rbegin()))->_mediumNode;
-                isStraight[is1] = isStraightLink( (uv2-uv1).SquareModulus(),
-                                                  10 * uvMove.SquareModulus());
-              }
-              if ( isStraight[0] && isStraight[1] ) {
-                MSG("2D straight - ignore");
-                continue; // straight - no need to move nodes of internal links
+                // isStraight[is1] = isStraightLink( (uv2-uv1).SquareModulus(),
+                //                                   10 * uvMove.SquareModulus());
               }
+              // if ( isStraight[0] && isStraight[1] ) {
+              //   MSG("2D straight - ignore");
+              //   continue; // straight - no need to move nodes of internal links
+              // }
 
               // check if a chain is already fixed
               gp_XY uvm  = faceHlp.GetNodeUV( face, linkOnFace->_mediumNode, 0, &checkUV );
index 05173ae0656f6eecd150cef7a0a80c9cd8132aea..fdf863f033e94d0792d75204853661e5ee932545 100644 (file)
@@ -34,6 +34,7 @@
 #include <SMDS_QuadraticEdge.hxx>
 
 #include <Geom_Surface.hxx>
+#include <ShapeAnalysis_Surface.hxx>
 #include <TopoDS_Face.hxx>
 #include <TopoDS_Shape.hxx>
 #include <gp_Pnt2d.hxx>
@@ -258,12 +259,9 @@ public:
    * quadratic elements will be created. Also fill myTLinkNodeMap
    */
   bool IsQuadraticSubMesh(const TopoDS_Shape& theShape);
-  /*!
-   * \brief Set order of elements to create without calling IsQuadraticSubMesh()
-   */
 
   /*!
-   * \brief Set myCreateQuadratic flag
+   * \brief Set order of elements to create without calling IsQuadraticSubMesh()
    */
   void SetIsQuadratic(const bool theBuildQuadratic)
   { myCreateQuadratic = theBuildQuadratic; }
@@ -531,13 +529,17 @@ public:
   GeomAPI_ProjectPointOnSurf& GetProjector(const TopoDS_Face& F,
                                            TopLoc_Location&   loc,
                                            double             tol=0 ) const; 
+  /*!
+   * \brief Return a cached ShapeAnalysis_Surface of a FACE
+   */
+  Handle(ShapeAnalysis_Surface) GetSurface(const TopoDS_Face& F ) const;
 
   /*!
    * \brief Check if shape is a degenerated edge or it's vertex
-    * \param subShape - edge or vertex index in SMESHDS
-    * \retval bool - true if subShape is a degenerated shape
-    *
-    * It works only if IsQuadraticSubMesh() or SetSubShape() has been called
+    \param subShape - edge or vertex index in SMESHDS
+    \retval bool - true if subShape is a degenerated shape
+   *
+   * It works only if IsQuadraticSubMesh() or SetSubShape() has been called
    */
   bool IsDegenShape(const int subShape) const
   { return myDegenShapeIds.find( subShape ) != myDegenShapeIds.end(); }
@@ -734,8 +736,10 @@ public:
 
   std::map< int, double > myFaceMaxTol;
 
+  typedef std::map< int, Handle(ShapeAnalysis_Surface)> TID2Surface;
   typedef std::map< int, GeomAPI_ProjectPointOnSurf* >  TID2ProjectorOnSurf;
   typedef std::map< int, GeomAPI_ProjectPointOnCurve* > TID2ProjectorOnCurve;
+  mutable TID2Surface  myFace2Surface;
   TID2ProjectorOnSurf  myFace2Projector;
   TID2ProjectorOnCurve myEdge2Projector;
 
index 5db170d7bedf5006c9cedea05295f6fee5b8db3c..eae5aee77376184e0c0b280ba077ec7d2b506e7a 100644 (file)
@@ -103,7 +103,7 @@ inline int getInt( const char * theSring )
   int val = strtol( theSring, &ptr, 10 );
   if ( ptr == theSring ||
       // there must not be neither '.' nor ',' nor 'E' ...
-      (*ptr != ' ' && *ptr != '\n' && *ptr != '\0'))
+      (*ptr != ' ' && *ptr != '\n' && *ptr != '\0' && *ptr != '\r'))
     return -1;
 
   return val;
@@ -620,39 +620,26 @@ bool SMESH_Pattern::Load (SMESH_Mesh*        theMesh,
     // ---------------------------------------------------------------
 
     // get all faces
-    list< const SMDS_MeshElement* > faces;
-    if ( nbElems > 0 ) {
-      SMDS_ElemIteratorPtr fIt = fSubMesh->GetElements();
-      while ( fIt->more() ) {
-        const SMDS_MeshElement* f = fIt->next();
-        if ( f && f->GetType() == SMDSAbs_Face )
-          faces.push_back( f );
-      }
-    }
-    else {
-      SMDS_FaceIteratorPtr fIt = aMeshDS->facesIterator();
-      while ( fIt->more() )
-        faces.push_back( fIt->next() );
-    }
+    SMDS_ElemIteratorPtr fIt;
+    if ( nbElems > 0 )
+      fIt = fSubMesh->GetElements();
+    else
+      fIt = aMeshDS->elementsIterator( SMDSAbs_Face );
 
     // put nodes of all faces into the nodePointIDMap and fill myElemPointIDs
-    list< const SMDS_MeshElement* >::iterator fIt = faces.begin();
-    for ( ; fIt != faces.end(); ++fIt )
+    while ( fIt->more() )
     {
+      const SMDS_MeshElement* face = fIt->next();
       myElemPointIDs.push_back( TElemDef() );
       TElemDef& elemPoints = myElemPointIDs.back();
-      int nbNodes = (*fIt)->NbCornerNodes();
+      int nbNodes = face->NbCornerNodes();
       for ( int i = 0;i < nbNodes; ++i )
       {
-        const SMDS_MeshElement* node = (*fIt)->GetNode( i );
+        const SMDS_MeshElement* node = face->GetNode( i );
         TNodePointIDMap::iterator nIdIt = nodePointIDMap.insert( make_pair( node, -1 )).first;
         if ( nIdIt->second == -1 )
-        {
-          elemPoints.push_back( iPoint );
           nIdIt->second = iPoint++;
-        }
-        else
-          elemPoints.push_back( (*nIdIt).second );
+        elemPoints.push_back( (*nIdIt).second );
       }
     }
     myPoints.resize( iPoint );
@@ -3554,13 +3541,7 @@ void SMESH_Pattern::
   myPolyElems.reserve( myIdsOnBoundary.size() );
 
   // make a set of refined elements
-  TIDSortedElemSet avoidSet, elemSet;
-  std::vector<const SMDS_MeshElement*>::iterator itv =  myElements.begin();
-  for(; itv!=myElements.end(); itv++) {
-    const SMDS_MeshElement* el = (*itv);
-    avoidSet.insert( el );
-  }
-  //avoidSet.insert( myElements.begin(), myElements.end() );
+  TIDSortedElemSet elemSet, avoidSet( myElements.begin(), myElements.end() );
 
   map< TNodeSet, list< list< int > > >::iterator indListIt, nn_IdList;
 
index 3745a2b77afe3dcce5911f5de6506c17cef6f2fc..be6345c937f7697ebf36eb3284fc3be398e69f03 100644 (file)
@@ -403,146 +403,48 @@ int SMESH_subMesh::computeCost() const
 
 //=============================================================================
 /*!
- *
- */
-//=============================================================================
-
-// bool SMESH_subMesh::SubMeshesReady()
-// {
-//   bool subMeshesReady = true;
-//   SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,true);
-//   while ( smIt->more() ) {
-//     SMESH_subMesh *sm = smIt->next();
-//     bool computeOk = (sm->GetComputeState() == COMPUTE_OK ||
-//                       sm->GetComputeState() == READY_TO_COMPUTE);
-//     if (!computeOk)
-//     {
-//       subMeshesReady = false;
-//       SCRUTE(sm->GetId());
-//       break;
-//     }
-//   }
-//   return subMeshesReady;
-// }
-
-//=============================================================================
-/*!
- * Construct dependence on first level subMeshes. complex shapes (compsolid,
- * shell, wire) are not analysed the same way as simple shapes (solid, face,
- * edge).
- * For collection shapes (compsolid, shell, wire) prepare a list of submeshes
- * with possible multiples occurences. Multiples occurences corresponds to
- * internal frontiers within shapes of the collection and must not be keeped.
- * See FinalizeDependence.
+ * Returns all sub-meshes this one depend on
  */
 //=============================================================================
 
 const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
 {
-  if (_dependenceAnalysed)
+  if ( _dependenceAnalysed || !_father->HasShapeToMesh() )
     return _mapDepend;
 
-  //MESSAGE("SMESH_subMesh::DependsOn");
-
   int type = _subShape.ShapeType();
-  //SCRUTE(type);
   switch (type)
   {
   case TopAbs_COMPOUND:
+  {
+    list< TopoDS_Shape > compounds( 1, _subShape );
+    list< TopoDS_Shape >::iterator comp = compounds.begin();
+    for ( ; comp != compounds.end(); ++comp )
     {
-      //MESSAGE("compound");
-      for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More();exp.Next())
-      {
-        insertDependence(exp.Current());
-      }
-      for (TopExp_Explorer exp(_subShape, TopAbs_SHELL, TopAbs_SOLID); exp.More(); exp.Next())
-      {
-        if ( BRep_Tool::IsClosed(exp.Current() ))
-          insertDependence(exp.Current());      //only shell not in solid
-        else
-          for (TopExp_Explorer expF(exp.Current(), TopAbs_FACE); expF.More();expF.Next())
-            insertDependence(expF.Current());    // issue 0020959: HEXA_3D fails on shell
-
-      }
-      for (TopExp_Explorer exp(_subShape, TopAbs_FACE, TopAbs_SHELL); exp.More();exp.Next())
-      {
-        insertDependence(exp.Current());
-      }
-      for (TopExp_Explorer exp(_subShape, TopAbs_EDGE, TopAbs_FACE); exp.More();exp.Next())
-      {
-        insertDependence(exp.Current());
-      }
-      for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX, TopAbs_EDGE); exp.More();exp.Next())
-      {
-        insertDependence(exp.Current());
-      }
-      break;
-    }
-  case TopAbs_COMPSOLID:
-    {
-      //MESSAGE("compsolid");
-      for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More(); exp.Next())
-      {
-        insertDependence(exp.Current());
-      }
-      break;
-    }
-  case TopAbs_SHELL:
-    {
-      //MESSAGE("shell");
-      for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More(); exp.Next())
-      {
-        insertDependence(exp.Current());
-      }
-      break;
-    }
-  case TopAbs_WIRE:
-    {
-      //MESSAGE("wire");
-      for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More(); exp.Next())
-      {
-        insertDependence(exp.Current());
-      }
-      break;
-    }
-  case TopAbs_SOLID:
-    {
-      //MESSAGE("solid");
-      if(_father->HasShapeToMesh()) {
-        for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();exp.Next())
+      for ( TopoDS_Iterator sub( *comp ); sub.More(); sub.Next() )
+        switch ( sub.Value().ShapeType() )
         {
-          insertDependence(exp.Current());
+        case TopAbs_COMPOUND:  compounds.push_back( sub.Value() ); break;
+        case TopAbs_COMPSOLID: insertDependence( sub.Value(), TopAbs_SOLID ); break;
+        case TopAbs_SOLID:     insertDependence( sub.Value(), TopAbs_SOLID ); break;
+        case TopAbs_SHELL:     insertDependence( sub.Value(), TopAbs_FACE ); break;
+        case TopAbs_FACE:      insertDependence( sub.Value(), TopAbs_FACE ); break;
+        case TopAbs_WIRE:      insertDependence( sub.Value(), TopAbs_EDGE ); break;
+        case TopAbs_EDGE:      insertDependence( sub.Value(), TopAbs_EDGE ); break;
+        case TopAbs_VERTEX:    insertDependence( sub.Value(), TopAbs_VERTEX ); break;
+        default:;
         }
-      }
-      break;
-    }
-  case TopAbs_FACE:
-    {
-      //MESSAGE("face");
-      for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More();exp.Next())
-      {
-        insertDependence(exp.Current());
-      }
-      break;
-    }
-  case TopAbs_EDGE:
-    {
-      //MESSAGE("edge");
-      for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX); exp.More(); exp.Next())
-      {
-        insertDependence(exp.Current());
-      }
-      break;
-    }
-  case TopAbs_VERTEX:
-    {
-      break;
-    }
-  default:
-    {
-      break;
     }
   }
+  break;
+  case TopAbs_COMPSOLID: insertDependence( _subShape, TopAbs_SOLID ); break;
+  case TopAbs_SOLID:     insertDependence( _subShape, TopAbs_FACE ); break;
+  case TopAbs_SHELL:     insertDependence( _subShape, TopAbs_FACE ); break;
+  case TopAbs_FACE:      insertDependence( _subShape, TopAbs_EDGE ); break;
+  case TopAbs_WIRE:      insertDependence( _subShape, TopAbs_EDGE ); break;
+  case TopAbs_EDGE:      insertDependence( _subShape, TopAbs_VERTEX ); break;
+  default:;
+  }
   _dependenceAnalysed = true;
   return _mapDepend;
 }
@@ -553,7 +455,8 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
  */
 //================================================================================
 
-namespace {
+namespace
+{
   int dependsOnMapKey( const SMESH_subMesh* sm )
   {
     int type = sm->GetSubShape().ShapeType();
@@ -566,19 +469,26 @@ namespace {
 
 //=============================================================================
 /*!
- * For simple Shapes (solid, face, edge): add subMesh into dependence list.
+ * Add sub-meshes on sub-shapes of a given type into the dependence map.
  */
 //=============================================================================
 
-void SMESH_subMesh::insertDependence(const TopoDS_Shape aSubShape)
+void SMESH_subMesh::insertDependence(const TopoDS_Shape aShape,
+                                     TopAbs_ShapeEnum   aSubType)
 {
-  SMESH_subMesh *aSubMesh = _father->GetSubMesh(aSubShape);
-  int cle = dependsOnMapKey( aSubMesh );
-  if ( _mapDepend.find( cle ) == _mapDepend.end())
+  TopExp_Explorer sub( aShape, aSubType );
+  for ( ; sub.More(); sub.Next() )
   {
-    _mapDepend[cle] = aSubMesh;
-    const map < int, SMESH_subMesh * > & subMap = aSubMesh->DependsOn();
-    _mapDepend.insert( subMap.begin(), subMap.end() );
+    SMESH_subMesh *aSubMesh = _father->GetSubMesh( sub.Current() );
+    if ( aSubMesh->GetId() == 0 )
+      continue;  // not a sub-shape of the shape to mesh
+    int cle = dependsOnMapKey( aSubMesh );
+    if ( _mapDepend.find( cle ) == _mapDepend.end())
+    {
+      _mapDepend[cle] = aSubMesh;
+      const map < int, SMESH_subMesh * > & subMap = aSubMesh->DependsOn();
+      _mapDepend.insert( subMap.begin(), subMap.end() );
+    }
   }
 }
 
@@ -690,6 +600,7 @@ SMESH_Hypothesis::Hypothesis_Status
   // le retour des evenement father n'indiquent pas que add ou remove fait
 
   SMESH_Hypothesis::Hypothesis_Status aux_ret, ret = SMESH_Hypothesis::HYP_OK;
+  if ( _Id == 0 ) return ret; // not a sub-shape of the shape to mesh
 
   SMESHDS_Mesh* meshDS =_father->GetMeshDS();
   SMESH_Algo*   algo   = 0;
@@ -979,7 +890,7 @@ SMESH_Hypothesis::Hypothesis_Status
         f.AndNot( SMESH_HypoFilter::Is( algo ));
         const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( this, f, true );
         if (prevAlgo &&
-            string(algo->GetName()) != string(prevAlgo->GetName()) )
+            string( algo->GetName()) != prevAlgo->GetName())
           modifiedHyp = true;
       }
       else
@@ -1096,8 +1007,8 @@ SMESH_Hypothesis::Hypothesis_Status
 
   // detect algorithm hiding
   //
-  if ( ret == SMESH_Hypothesis::HYP_OK &&
-       ( event == ADD_ALGO || event == ADD_FATHER_ALGO ) &&
+  if ( ret == SMESH_Hypothesis::HYP_OK && 
+       ( event == ADD_ALGO || event == ADD_FATHER_ALGO ) && algo && 
        algo->GetName() == anHyp->GetName() )
   {
     // is algo hidden?
@@ -1305,7 +1216,7 @@ void SMESH_subMesh::cleanDependsOn( SMESH_Algo* algoRequiringCleaning/*=0*/ )
       if ( !sm->IsEmpty() )
       {
         const bool sameShapeType = ( prevShapeType == sm->GetSubShape().ShapeType() );
-        bool keepSubMeshes = ( sameShapeType && toKeepPrevShapeType );
+        bool       keepSubMeshes = ( sameShapeType && toKeepPrevShapeType );
         if ( !sameShapeType )
         {
           // check if the algo allows presence of global algos of dimension the algo
@@ -1328,7 +1239,7 @@ void SMESH_subMesh::cleanDependsOn( SMESH_Algo* algoRequiringCleaning/*=0*/ )
         // remember all sub-meshes of sm
         if ( keepSubMeshes )
         {
-          SMESH_subMeshIteratorPtr smIt2 = getDependsOnIterator(false,true);
+          SMESH_subMeshIteratorPtr smIt2 = getDependsOnIterator(false);
           while ( smIt2->more() )
             smToKeep.insert( smIt2->next() );
         }
@@ -1353,48 +1264,32 @@ void SMESH_subMesh::cleanDependsOn( SMESH_Algo* algoRequiringCleaning/*=0*/ )
 
 void SMESH_subMesh::DumpAlgoState(bool isMain)
 {
-  // if (dim < 1) return;
-        if (isMain)
-        {
-                const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
-
-                map < int, SMESH_subMesh * >::const_iterator itsub;
-                for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
-                {
-                        SMESH_subMesh *sm = (*itsub).second;
-                        sm->DumpAlgoState(false);
-                }
-        }
-        //int type = _subShape.ShapeType();
-        MESSAGE("dim = " << SMESH_Gen::GetShapeDim(_subShape) <<
-                " type of shape " << _subShape.ShapeType());
-        switch (_algoState)
-        {
-        case NO_ALGO:
-                MESSAGE(" AlgoState = NO_ALGO");
-                break;
-        case MISSING_HYP:
-                MESSAGE(" AlgoState = MISSING_HYP");
-                break;
-        case HYP_OK:
-                MESSAGE(" AlgoState = HYP_OK");
-                break;
-        }
-        switch (_computeState)
-        {
-        case NOT_READY:
-                MESSAGE(" ComputeState = NOT_READY");
-                break;
-        case READY_TO_COMPUTE:
-                MESSAGE(" ComputeState = READY_TO_COMPUTE");
-                break;
-        case COMPUTE_OK:
-                MESSAGE(" ComputeState = COMPUTE_OK");
-                break;
-        case FAILED_TO_COMPUTE:
-                MESSAGE(" ComputeState = FAILED_TO_COMPUTE");
-                break;
-        }
+  if (isMain)
+  {
+    const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
+
+    map < int, SMESH_subMesh * >::const_iterator itsub;
+    for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
+    {
+      SMESH_subMesh *sm = (*itsub).second;
+      sm->DumpAlgoState(false);
+    }
+  }
+  MESSAGE("dim = " << SMESH_Gen::GetShapeDim(_subShape) <<
+          " type of shape " << _subShape.ShapeType());
+  switch (_algoState)
+  {
+  case NO_ALGO          : MESSAGE(" AlgoState = NO_ALGO"); break;
+  case MISSING_HYP      : MESSAGE(" AlgoState = MISSING_HYP"); break;
+  case HYP_OK           : MESSAGE(" AlgoState = HYP_OK");break;
+  }
+  switch (_computeState)
+  {
+  case NOT_READY        : MESSAGE(" ComputeState = NOT_READY");break;
+  case READY_TO_COMPUTE : MESSAGE(" ComputeState = READY_TO_COMPUTE");break;
+  case COMPUTE_OK       : MESSAGE(" ComputeState = COMPUTE_OK");break;
+  case FAILED_TO_COMPUTE: MESSAGE(" ComputeState = FAILED_TO_COMPUTE");break;
+  }
 }
 
 //================================================================================
@@ -1927,12 +1822,12 @@ bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap)
   SMESH_Hypothesis::Hypothesis_Status hyp_status;
 
   algo = GetAlgo();
-  if(algo && !aResMap.count(this) )
+  if( algo && !aResMap.count( this ))
   {
     ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
     if (!ret) return false;
 
-    if (_father->HasShapeToMesh() && algo->NeedDiscreteBoundary())
+    if (_father->HasShapeToMesh() && algo->NeedDiscreteBoundary() )
     {
       // check submeshes needed
       bool subMeshEvaluated = true;
@@ -1950,8 +1845,23 @@ bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap)
         return false;
     }
     _computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo);
-    ret = algo->Evaluate((*_father), _subShape, aResMap);
 
+    if ( IsMeshComputed() )
+    {
+      vector<int> & nbEntities = aResMap[ this ];
+      nbEntities.resize( SMDSEntity_Last, 0 );
+      if ( SMESHDS_SubMesh* sm = GetSubMeshDS() )
+      {
+        nbEntities[ SMDSEntity_Node ] = sm->NbNodes();
+        SMDS_ElemIteratorPtr   elemIt = sm->GetElements();
+        while ( elemIt->more() )
+          nbEntities[ elemIt->next()->GetEntityType() ]++;
+      }
+    }
+    else
+    {
+      ret = algo->Evaluate((*_father), _subShape, aResMap);
+    }
     aResMap.insert( make_pair( this,vector<int>(0)));
   }
 
@@ -2080,11 +1990,10 @@ void SMESH_subMesh::updateDependantsState(const compute_event theEvent)
   }
 }
 
-//=============================================================================
-/*!
- *
- */
-//=============================================================================
+//=======================================================================
+//function : cleanDependants
+//purpose  : 
+//=======================================================================
 
 void SMESH_subMesh::cleanDependants()
 {
@@ -2105,11 +2014,10 @@ void SMESH_subMesh::cleanDependants()
   }
 }
 
-//=============================================================================
-/*!
- *
- */
-//=============================================================================
+//=======================================================================
+//function : removeSubMeshElementsAndNodes
+//purpose  : 
+//=======================================================================
 
 void SMESH_subMesh::removeSubMeshElementsAndNodes()
 {
@@ -2659,16 +2567,18 @@ void SMESH_subMesh::ClearAncestors()
  */
 //================================================================================
 
-bool SMESH_subMesh::FindIntersection(const SMESH_subMesh* theOther,
+bool SMESH_subMesh::FindIntersection(const SMESH_subMesh*            theOther,
                                      std::set<const SMESH_subMesh*>& theSetOfCommon ) const
 {
   int oldNb = theSetOfCommon.size();
+
   // check main submeshes
   const map <int, SMESH_subMesh*>::const_iterator otherEnd = theOther->_mapDepend.end();
   if ( theOther->_mapDepend.find(this->GetId()) != otherEnd )
     theSetOfCommon.insert( this );
   if ( _mapDepend.find(theOther->GetId()) != _mapDepend.end() )
     theSetOfCommon.insert( theOther );
+
   // check common submeshes
   map <int, SMESH_subMesh*>::const_iterator mapIt = _mapDepend.begin();
   for( ; mapIt != _mapDepend.end(); mapIt++ )
index 4d408033cef42de25bccb111cc5bb037e151515b..249784c081196746c632c475cf01e1e9ebf0a650 100644 (file)
@@ -280,7 +280,7 @@ public:
 
 protected:
   // ==================================================================
-  void insertDependence(const TopoDS_Shape aSubShape);
+  void insertDependence(const TopoDS_Shape aShape, TopAbs_ShapeEnum aSubType );
 
   void removeSubMeshElementsAndNodes();
   void updateDependantsState(const compute_event theEvent);
index 6787e0043de7e0cb9e867b3ca76503af81c1b1ec..f360512c63f1b2de891fb1f2fd785bd14b9247c5 100644 (file)
@@ -244,6 +244,33 @@ namespace
   }
 
 
+  //=======================================================================
+  //function : AddQaudPolygonsWithID
+  //=======================================================================
+  inline void AddQuadPolygonsWithID(SMDS_Mesh* theMesh,
+                                    SMESH::log_array_var& theSeq,
+                                    CORBA::Long theId)
+  {
+    const SMESH::long_array& anIndexes = theSeq[theId].indexes;
+    CORBA::Long anIndexId = 0, aNbElems = theSeq[theId].number;
+
+    for (CORBA::Long anElemId = 0; anElemId < aNbElems; anElemId++) {
+      int aFaceId = anIndexes[anIndexId++];
+
+      int aNbNodes = anIndexes[anIndexId++];
+      std::vector<int> nodes_ids (aNbNodes);
+      for (int i = 0; i < aNbNodes; i++) {
+        nodes_ids[i] = anIndexes[anIndexId++];
+      }
+
+      SMDS_MeshElement* anElem = theMesh->AddQuadPolygonalFaceWithID(nodes_ids, aFaceId);
+      if (!anElem)
+        EXCEPTION(runtime_error, "SMDS_Mesh::FindElement - cannot AddQaudPolygonalFaceWithID for ID = "
+                  << anElemId);
+    }
+  }
+
+
   //=======================================================================
   //function : AddTetrasWithID
   //=======================================================================
@@ -903,6 +930,7 @@ SMESH_Client::Update(bool theIsClear)
         case SMESH::ADD_QUADEDGE         : AddQuadEdgesWithID   ( mySMDSMesh, aSeq, anId ); break;
         case SMESH::ADD_QUADTRIANGLE     : AddQuadTriasWithID   ( mySMDSMesh, aSeq, anId ); break;
         case SMESH::ADD_QUADQUADRANGLE   : AddQuadQuadsWithID   ( mySMDSMesh, aSeq, anId ); break;
+        case SMESH::ADD_QUADPOLYGON      : AddQuadPolygonsWithID( mySMDSMesh, aSeq, anId ); break;
         case SMESH::ADD_QUADTETRAHEDRON  : AddQuadTetrasWithID  ( mySMDSMesh, aSeq, anId ); break;
         case SMESH::ADD_QUADPYRAMID      : AddQuadPiramidsWithID( mySMDSMesh, aSeq, anId ); break;
         case SMESH::ADD_QUADPENTAHEDRON  : AddQuadPentasWithID  ( mySMDSMesh, aSeq, anId ); break;
index 4fbd5464e1c6c22d86dadf521a10a9fb0ea78dae..b22079e6af166b84198e8a08d1352f743959a744 100644 (file)
@@ -295,6 +295,28 @@ void SMESHDS_Command::AddPolygonalFace (const int               ElementID,
   myNumber++;
 }
 
+//=======================================================================
+//function : AddQuadPolygonalFace
+//purpose  :
+//=======================================================================
+void SMESHDS_Command::AddQuadPolygonalFace (const int               ElementID,
+                                            const std::vector<int>& nodes_ids)
+{
+  if ( myType != SMESHDS_AddQuadPolygon) {
+    MESSAGE("SMESHDS_Command::AddQuadraticPolygonalFace : Bad Type");
+    return;
+  }
+  myIntegers.push_back(ElementID);
+
+  int i, nbNodes = nodes_ids.size();
+  myIntegers.push_back(nbNodes);
+  for (i = 0; i < nbNodes; i++) {
+    myIntegers.push_back(nodes_ids[i]);
+  }
+
+  myNumber++;
+}
+
 //=======================================================================
 //function : AddPolyhedralVolume
 //purpose  : 
index e52e4b7ac9ef6aefa58177aec0892c5075809dde..583cebe4a3a9e62b589c485257955862dd8afc56 100644 (file)
@@ -57,6 +57,8 @@ class SMESHDS_EXPORT SMESHDS_Command
                        int idnode9, int idnode10, int idnode11, int idnode12);
         void AddPolygonalFace (const int               ElementID,
                                const std::vector<int>& nodes_ids);
+        void AddQuadPolygonalFace (const int               ElementID,
+                                   const std::vector<int>& nodes_ids);
         void AddPolyhedralVolume (const int               ElementID,
                                   const std::vector<int>& nodes_ids,
                                   const std::vector<int>& quantities);
index a53532ddffb5182b01e8ae3c9bd912beb1b0bff2..c355386e54d9f508cbaaff717bde02ef51a026b7 100644 (file)
@@ -49,6 +49,7 @@ enum SMESHDS_CommandType {
   SMESHDS_AddQuadEdge,
   SMESHDS_AddQuadTriangle,
   SMESHDS_AddQuadQuadrangle,
+  SMESHDS_AddQuadPolygon,
   SMESHDS_AddQuadTetrahedron,
   SMESHDS_AddQuadPyramid,
   SMESHDS_AddQuadPentahedron,
index 239c1c89f1828142f0932dc70d3c9178a27b592a..98c9b494c8320440fe2ad5a8ab06c6ea8b08bd34 100644 (file)
@@ -68,22 +68,22 @@ SMESHDS_Mesh * SMESHDS_Document::NewMesh(bool theIsEmbeddedMode, int MeshID)
 
 //=======================================================================
 //function : GetMesh
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMESHDS_Mesh *SMESHDS_Document::GetMesh(int MeshID)
 {
-        map<int,SMESHDS_Mesh*>::iterator it=myMeshes.find(MeshID);
-        if (it==myMeshes.end())
-        {
-                MESSAGE("SMESHDS_Document::GetMesh : ID not found");
-                return NULL;
-        }
-        else return (*it).second;
+  map<int,SMESHDS_Mesh*>::iterator it=myMeshes.find(MeshID);
+  if (it==myMeshes.end())
+  {
+    MESSAGE("SMESHDS_Document::GetMesh : ID not found");
+    return NULL;
+  }
+  else return (*it).second;
 }
 
 //=======================================================================
 //function : RemoveMesh
-//purpose  : 
+//purpose  :
 //=======================================================================
 void SMESHDS_Document::RemoveMesh(int MeshID)
 {
@@ -107,99 +107,99 @@ void SMESHDS_Document::AddHypothesis(SMESHDS_Hypothesis * H)
 //=======================================================================
 SMESHDS_Hypothesis * SMESHDS_Document::GetHypothesis(int HypID)
 {
-        map<int,SMESHDS_Hypothesis*>::iterator it=myHypothesis.find(HypID);
-        if (it==myHypothesis.end())
-        {
-                MESSAGE("SMESHDS_Document::GetHypothesis : ID not found");
-                return NULL;
-        }
-        else return (*it).second;
+  map<int,SMESHDS_Hypothesis*>::iterator it=myHypothesis.find(HypID);
+  if (it==myHypothesis.end())
+  {
+    MESSAGE("SMESHDS_Document::GetHypothesis : ID not found");
+    return NULL;
+  }
+  else return (*it).second;
 }
 
 //=======================================================================
 //function : RemoveHypothesis
-//purpose  : 
+//purpose  :
 //=======================================================================
 void SMESHDS_Document::RemoveHypothesis(int HypID)
 {
-        map<int,SMESHDS_Hypothesis*>::iterator it=myHypothesis.find(HypID);
-        if (it==myHypothesis.end())
-                MESSAGE("SMESHDS_Document::RemoveHypothesis : ID not found");   
-        myHypothesis.erase(it);
+  map<int,SMESHDS_Hypothesis*>::iterator it=myHypothesis.find(HypID);
+  if (it==myHypothesis.end())
+    MESSAGE("SMESHDS_Document::RemoveHypothesis : ID not found");
+  myHypothesis.erase(it);
 }
 
 //=======================================================================
 //function : NbMeshes
-//purpose  : 
+//purpose  :
 //=======================================================================
 int SMESHDS_Document::NbMeshes()
 {
-        return myMeshes.size();
+  return myMeshes.size();
 }
 
 //=======================================================================
 //function : NbHypothesis
-//purpose  : 
+//purpose  :
 //=======================================================================
 int SMESHDS_Document::NbHypothesis()
 {
-        return myHypothesis.size();
+  return myHypothesis.size();
 }
 
 //=======================================================================
 //function : InitMeshesIterator
-//purpose  : 
+//purpose  :
 //=======================================================================
 void SMESHDS_Document::InitMeshesIterator()
 {
-        myMeshesIt=myMeshes.begin();
+  myMeshesIt=myMeshes.begin();
 }
 
 //=======================================================================
 //function : NextMesh
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMESHDS_Mesh * SMESHDS_Document::NextMesh()
 {
-        SMESHDS_Mesh * toReturn=(*myMeshesIt).second;
-        myMeshesIt++;
-        return toReturn;
+  SMESHDS_Mesh * toReturn=(*myMeshesIt).second;
+  myMeshesIt++;
+  return toReturn;
 }
 
 //=======================================================================
 //function : MoreMesh
-//purpose  : 
+//purpose  :
 //=======================================================================
 bool SMESHDS_Document::MoreMesh()
 {
-        return myMeshesIt!=myMeshes.end();
+  return myMeshesIt!=myMeshes.end();
 }
 
 //=======================================================================
 //function : InitHypothesisIterator
-//purpose  : 
+//purpose  :
 //=======================================================================
 void SMESHDS_Document::InitHypothesisIterator()
 {
-        myHypothesisIt=myHypothesis.begin();
+  myHypothesisIt=myHypothesis.begin();
 }
 
 //=======================================================================
 //function : NextMesh
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMESHDS_Hypothesis * SMESHDS_Document::NextHypothesis()
 {
-        SMESHDS_Hypothesis * toReturn=(*myHypothesisIt).second;
-        myHypothesisIt++;
-        return toReturn;
+  SMESHDS_Hypothesis * toReturn=(*myHypothesisIt).second;
+  myHypothesisIt++;
+  return toReturn;
 }
 
 //=======================================================================
 //function : MoreMesh
-//purpose  : 
+//purpose  :
 //=======================================================================
 bool SMESHDS_Document::MoreHypothesis()
 {
-        return myHypothesisIt!=myHypothesis.end();
+  return myHypothesisIt!=myHypothesis.end();
 }
index dc1e094b02c31ed4ee97b1e0e4d64d48e8ca8a16..a66f4482fe5a0f7c4523187dd12c57e5fa7c0815 100644 (file)
@@ -213,7 +213,7 @@ void SMESHDS_Mesh::MoveNode(const SMDS_MeshNode *n, double x, double y, double z
 
 //=======================================================================
 //function : ChangeElementNodes
-//purpose  : 
+//purpose  : Changed nodes of an element provided that nb of nodes does not change
 //=======================================================================
 
 bool SMESHDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * elem,
@@ -708,9 +708,9 @@ SMDS_MeshFace* SMESHDS_Mesh::AddPolygonalFaceWithID (const std::vector<int>& nod
   return anElem;
 }
 
-SMDS_MeshFace* SMESHDS_Mesh::AddPolygonalFaceWithID
-                             (const std::vector<const SMDS_MeshNode*>& nodes,
-                              const int                                ID)
+SMDS_MeshFace*
+SMESHDS_Mesh::AddPolygonalFaceWithID (const std::vector<const SMDS_MeshNode*>& nodes,
+                                      const int                                ID)
 {
   SMDS_MeshFace *anElem = SMDS_Mesh::AddPolygonalFaceWithID(nodes, ID);
   if (anElem) {
@@ -724,8 +724,8 @@ SMDS_MeshFace* SMESHDS_Mesh::AddPolygonalFaceWithID
   return anElem;
 }
 
-SMDS_MeshFace* SMESHDS_Mesh::AddPolygonalFace
-                             (const std::vector<const SMDS_MeshNode*>& nodes)
+SMDS_MeshFace*
+SMESHDS_Mesh::AddPolygonalFace (const std::vector<const SMDS_MeshNode*>& nodes)
 {
   SMDS_MeshFace *anElem = SMDS_Mesh::AddPolygonalFace(nodes);
   if (anElem) {
@@ -739,6 +739,53 @@ SMDS_MeshFace* SMESHDS_Mesh::AddPolygonalFace
   return anElem;
 }
 
+
+//=======================================================================
+//function : AddQuadPolygonalFace
+//purpose  : 
+//=======================================================================
+SMDS_MeshFace* SMESHDS_Mesh::AddQuadPolygonalFaceWithID (const std::vector<int>& nodes_ids,
+                                                         const int               ID)
+{
+  SMDS_MeshFace *anElem = SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes_ids, ID);
+  if (anElem) {
+    myScript->AddQuadPolygonalFace(ID, nodes_ids);
+  }
+  return anElem;
+}
+
+SMDS_MeshFace*
+SMESHDS_Mesh::AddQuadPolygonalFaceWithID (const std::vector<const SMDS_MeshNode*>& nodes,
+                                          const int                                ID)
+{
+  SMDS_MeshFace *anElem = SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes, ID);
+  if (anElem) {
+    int i, len = nodes.size();
+    std::vector<int> nodes_ids (len);
+    for (i = 0; i < len; i++) {
+      nodes_ids[i] = nodes[i]->GetID();
+    }
+    myScript->AddQuadPolygonalFace(ID, nodes_ids);
+  }
+  return anElem;
+}
+
+SMDS_MeshFace*
+SMESHDS_Mesh::AddQuadPolygonalFace (const std::vector<const SMDS_MeshNode*>& nodes)
+{
+  SMDS_MeshFace *anElem = SMDS_Mesh::AddQuadPolygonalFace(nodes);
+  if (anElem) {
+    int i, len = nodes.size();
+    std::vector<int> nodes_ids (len);
+    for (i = 0; i < len; i++) {
+      nodes_ids[i] = nodes[i]->GetID();
+    }
+    myScript->AddQuadPolygonalFace(anElem->GetID(), nodes_ids);
+  }
+  return anElem;
+}
+
+
 //=======================================================================
 //function : AddPolyhedralVolume
 //purpose  : 
@@ -918,7 +965,7 @@ void SMESHDS_Mesh::RemoveElement(const SMDS_MeshElement * elt)
     if ( elt->getshapeId() > 0 )
       subMesh = MeshElements( elt->getshapeId() );
 
-    RemoveFreeElement( elt, subMesh, true);
+    RemoveFreeElement( elt, subMesh, true );
     return;
   }
  
@@ -927,7 +974,7 @@ void SMESHDS_Mesh::RemoveElement(const SMDS_MeshElement * elt)
   list<const SMDS_MeshElement *> removedElems;
   list<const SMDS_MeshElement *> removedNodes;
 
-  SMDS_Mesh::RemoveElement(elt, removedElems, removedNodes, false);
+  SMDS_Mesh::RemoveElement(elt, removedElems, removedNodes, false );
   
   removeFromContainers( this, myGroups, removedElems, false );
 }
@@ -953,7 +1000,7 @@ void SMESHDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elt,
   myScript->RemoveElement(elt->GetID());
 
   // Rm from group
-  // Node can belong to several groups
+  // Element can belong to several groups
   if ( fromGroups && !myGroups.empty() ) {
     set<SMESHDS_GroupBase*>::iterator GrIt = myGroups.begin();
     for (; GrIt != myGroups.end(); GrIt++) {
@@ -965,10 +1012,12 @@ void SMESHDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elt,
 
   // Rm from sub-mesh
   // Element should belong to only one sub-mesh
-  if( subMesh )
-    subMesh->RemoveElement(elt, /*deleted=*/false);
+  if ( !subMesh && elt->getshapeId() > 0 )
+    subMesh = MeshElements( elt->getshapeId() );
+  if ( subMesh )
+    subMesh->RemoveElement( elt, /*deleted=*/false );
 
-  SMDS_Mesh::RemoveFreeElement(elt);
+  SMDS_Mesh::RemoveFreeElement( elt );
 }
 
 //================================================================================
index d7cf62597e9fa9ede07ecda7565ecb1839f9ab7d..6ec2d3d9cabf5c1438c63fbcf0cb005cbcb8a79c 100644 (file)
@@ -511,6 +511,14 @@ public:
 
   virtual SMDS_MeshFace* AddPolygonalFace (const std::vector<const SMDS_MeshNode*>& nodes);
 
+  virtual SMDS_MeshFace* AddQuadPolygonalFaceWithID(const std::vector<int> & nodes_ids,
+                                                    const int                ID);
+
+  virtual SMDS_MeshFace* AddQuadPolygonalFaceWithID(const std::vector<const SMDS_MeshNode*> & nodes,
+                                                    const int                                 ID);
+
+  virtual SMDS_MeshFace* AddQuadPolygonalFace(const std::vector<const SMDS_MeshNode*> & nodes);
+
   virtual SMDS_MeshVolume* AddPolyhedralVolumeWithID
                            (const std::vector<int>& nodes_ids,
                             const std::vector<int>& quantities,
index 5a5dac83bee45a40324ae79cea1872a6dc650131..e01109c3f254c9fc4909dc62614f43b74c32881e 100644 (file)
@@ -255,6 +255,19 @@ void SMESHDS_Script::AddPolygonalFace (int NewFaceID, const std::vector<int>& no
   getCommand(SMESHDS_AddPolygon)->AddPolygonalFace(NewFaceID, nodes_ids);
 }
 
+//=======================================================================
+//function : AddQuadPolygonalFace
+//purpose  : 
+//=======================================================================
+void SMESHDS_Script::AddQuadPolygonalFace(int NewFaceID, const std::vector<int>& nodes_ids)
+{
+  if(myIsEmbeddedMode){
+    myIsModified = true;
+    return;
+  }
+  getCommand(SMESHDS_AddQuadPolygon)->AddQuadPolygonalFace(NewFaceID, nodes_ids);
+}
+
 //=======================================================================
 //function : AddPolyhedralVolume
 //purpose  : 
index 72f7a44956249efb34a6caf3840bc9fb0b26cc99..3401ca6acd5cfc18d8bf07bc5693d77af02617cd 100644 (file)
@@ -64,6 +64,8 @@ class SMESHDS_EXPORT SMESHDS_Script
 
         void AddPolygonalFace (const int               NewFaceID,
                                const std::vector<int>& nodes_ids);
+        void AddQuadPolygonalFace (const int               NewFaceID,
+                                        const std::vector<int>& nodes_ids);
         void AddPolyhedralVolume (const int               NewVolID,
                                   const std::vector<int>& nodes_ids,
                                   const std::vector<int>& quantities);
index f06ec6e315433c8f6a4472d2cd0968ef15068805..04a0021fc0fc2ef501ec1209d7c075c485fe3e8f 100644 (file)
@@ -46,8 +46,6 @@ using namespace std;
 SMESHDS_SubMesh::SMESHDS_SubMesh(SMESHDS_Mesh *parent, int index)
 {
   myParent = parent;
-  myElements.clear();
-  myNodes.clear();
   myIndex = index;
   myUnusedIdNodes = 0;
   myUnusedIdElements = 0;
@@ -65,61 +63,54 @@ SMESHDS_SubMesh::~SMESHDS_SubMesh()
 
 //=======================================================================
 //function : AddElement
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 void SMESHDS_SubMesh::AddElement(const SMDS_MeshElement * ME)
 {
   if (!IsComplexSubmesh())
+  {
+    if ( ME->GetType() == SMDSAbs_Node )
+    {
+      AddNode( static_cast< const SMDS_MeshNode* >( ME ));
+      return;
+    }
+    int oldShapeId = ME->getshapeId();
+    if ( oldShapeId > 0 )
     {
-      if ( ME->GetType() == SMDSAbs_Node )
+      if (oldShapeId != myIndex)
       {
-        AddNode( static_cast< const SMDS_MeshNode* >( ME ));
-        return;
+        throw SALOME_Exception
+          (LOCALIZED("add element in subshape already belonging to a subshape"));
       }
-      int oldShapeId = ME->getshapeId();
-      if ( oldShapeId > 0 )
+      int idInSubShape = ME->getIdInShape();
+      if (idInSubShape >= 0)
+      {
+        MESSAGE("add element in subshape already belonging to that subshape "
+                << ME->GetID() << " " << oldShapeId << " " << idInSubShape);
+        // check if ok: do nothing if ok
+        if (idInSubShape >= myElements.size())
         {
-          if (oldShapeId != myIndex)
-            {
-              MESSAGE("add element in subshape already belonging to another subshape "
-                << ME->GetID() << " " << oldShapeId << " " << myIndex);
-              throw SALOME_Exception(LOCALIZED("add element in subshape already belonging to a subshape"));
-            }
-          else
-            {
-              int idInSubShape = ME->getIdInShape();
-              if (idInSubShape >= 0)
-                {
-                  MESSAGE("add element in subshape already belonging to that subshape "
-                      << ME->GetID() << " " << oldShapeId << " " << idInSubShape);
-                  // check if ok: do nothing if ok
-                  if (idInSubShape >= myElements.size())
-                    {
-                      MESSAGE("out of bounds " << idInSubShape << " " << myElements.size());
-                      throw SALOME_Exception(LOCALIZED("out of bounds"));
-                    }
-                  if (ME != myElements[idInSubShape])
-                    {
-                      MESSAGE("not the same element");
-                      throw SALOME_Exception(LOCALIZED("not the same element"));
-                    }
-                  MESSAGE("already done, OK, nothing to do");
-                  return;
-                }
-            }
+          throw SALOME_Exception(LOCALIZED("out of bounds"));
         }
-
-      SMDS_MeshElement* elem = (SMDS_MeshElement*) (ME);
-      elem->setShapeId(myIndex);
-      elem->setIdInShape(myElements.size());
-      myElements.push_back(ME);
+        if (ME != myElements[idInSubShape])
+        {
+          throw SALOME_Exception(LOCALIZED("not the same element"));
+        }
+        return;
+      }
     }
+
+    SMDS_MeshElement* elem = (SMDS_MeshElement*) (ME);
+    elem->setShapeId(myIndex);
+    elem->setIdInShape(myElements.size());
+    myElements.push_back(ME);
+  }
 }
 
 //=======================================================================
 //function : RemoveElement
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 bool SMESHDS_SubMesh::RemoveElement(const SMDS_MeshElement * ME, bool isElemDeleted)
@@ -183,7 +174,7 @@ void SMESHDS_SubMesh::AddNode(const SMDS_MeshNode * N)
 
 //=======================================================================
 //function : RemoveNode
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 bool SMESHDS_SubMesh::RemoveNode(const SMDS_MeshNode * N, bool isNodeDeleted)
@@ -385,29 +376,52 @@ bool SMESHDS_SubMesh::Contains(const SMDS_MeshElement * ME) const
   if (!ME)
     return false;
 
-  if (IsComplexSubmesh())
-    {
-      set<const SMESHDS_SubMesh*>::const_iterator aSubIt = mySubMeshes.begin();
-      for (; aSubIt != mySubMeshes.end(); aSubIt++)
-        if ((*aSubIt)->Contains(ME))
-          return true;
-      return false;
-    }
+  if ( IsComplexSubmesh() )
+  {
+    set<const SMESHDS_SubMesh*>::const_iterator aSubIt = mySubMeshes.begin();
+    for (; aSubIt != mySubMeshes.end(); aSubIt++)
+      if ((*aSubIt)->Contains(ME))
+        return true;
+    return false;
+  }
 
   if (ME->GetType() == SMDSAbs_Node)
-    {
-      int idInShape = ME->getIdInShape();
-      if ((idInShape >= 0) && (idInShape < myNodes.size()))
-        if (myNodes[idInShape] == ME)
-          return true;
-    }
+  {
+    int idInShape = ME->getIdInShape();
+    if ((idInShape >= 0) && (idInShape < myNodes.size()))
+      if (myNodes[idInShape] == ME)
+        return true;
+  }
   else
-    {
-      int idInShape = ME->getIdInShape();
-      if ((idInShape >= 0) && (idInShape < myElements.size()))
-        if (myElements[idInShape] == ME)
-          return true;
-    }
+  {
+    int idInShape = ME->getIdInShape();
+    if ((idInShape >= 0) && (idInShape < myElements.size()))
+      if (myElements[idInShape] == ME)
+        return true;
+  }
+  return false;
+}
+
+//=======================================================================
+//function : IsQuadratic
+//purpose  : Return true if my 1st element is quadratic
+//=======================================================================
+
+bool SMESHDS_SubMesh::IsQuadratic() const
+{
+  if ( IsComplexSubmesh() )
+  {
+    set<const SMESHDS_SubMesh*>::const_iterator aSubIt = mySubMeshes.begin();
+    for (; aSubIt != mySubMeshes.end(); aSubIt++)
+      if ((*aSubIt)->IsQuadratic())
+        return true;
+    return false;
+  }
+
+  for ( size_t i = 0; i < myElements.size(); ++i )
+    if ( myElements[i] )
+      return myElements[i]->IsQuadratic();
+
   return false;
 }
 
index d583d29210366a12bdca0804e9f5ebacfe864aed..c70857c6028dbb30952e6fa6671643a764a11e23 100644 (file)
@@ -67,19 +67,20 @@ class SMESHDS_EXPORT SMESHDS_SubMesh
   virtual int NbNodes() const;
   virtual SMDS_NodeIteratorPtr GetNodes() const;
   virtual bool Contains(const SMDS_MeshElement * ME) const;      // check if elem or node is in
+  virtual bool IsQuadratic() const;
 
   // clear the contents
   virtual void Clear();
-  int getSize();
+  int  getSize();
   void compactList();
 
-  SMESHDS_Mesh *GetParent()   { return myParent; }
-  int           GetID() const { return myIndex; }
+  SMESHDS_Mesh* GetParent() const { return const_cast< SMESHDS_Mesh*>( myParent ); }
+  int           GetID()     const { return myIndex; }
 
  private:
-  SMESHDS_Mesh * myParent;
+  SMESHDS_Mesh *                       myParent;
   std::vector<const SMDS_MeshElement*> myElements;
-  std::vector<const SMDS_MeshNode*> myNodes;
+  std::vector<const SMDS_MeshNode*>    myNodes;
 
   int myUnusedIdNodes;
   int myUnusedIdElements;
index ed8b7836e5572cb8d5ca4769e38d341d5495e16c..c62f185e4593c49b09599e619c4fbcade64fefc7 100644 (file)
@@ -141,6 +141,9 @@ SET(_moc_HEADERS
   SMESHGUI_Add0DElemsOnAllNodesDlg.h
   SMESHGUI_FieldSelectorWdg.h
   SMESHGUI_DisplayEntitiesDlg.h
+  SMESHGUI_SplitBiQuad.h
+  SMESHGUI_PreVisualObj.h
+  SMESHGUI_IdPreview.h
 )
 
 # header files / no moc processing
@@ -249,6 +252,9 @@ SET(_other_SOURCES
   SMESHGUI_FileValidator.cxx
   SMESHGUI_FieldSelectorWdg.cxx
   SMESHGUI_DisplayEntitiesDlg.cxx
+  SMESHGUI_SplitBiQuad.cxx
+  SMESHGUI_PreVisualObj.cxx
+  SMESHGUI_IdPreview.cxx
 )
 
 # sources / to compile
index 5db6d9e10f3524814875f95bf975f2c5a7e454aa..4de86fc5de86e697971eb893e0c3f3bbd097e5d5 100644 (file)
@@ -82,6 +82,7 @@
 #include "SMESHGUI_TranslationDlg.h"
 #include "SMESHGUI_TransparencyDlg.h"
 #include "SMESHGUI_DisplayEntitiesDlg.h"
+#include "SMESHGUI_SplitBiQuad.h"
 
 #include "SMESHGUI_FilterUtils.h"
 #include "SMESHGUI_GEOMGenUtils.h"
 
 #include <VTKViewer_Algorithm.h>
 
-#include <PyInterp_Interp.h>
-
 #include <SUIT_Desktop.h>
 #include <SUIT_FileDlg.h>
 #include <SUIT_MessageBox.h>
 // OCCT includes
 #include <Standard_ErrorHandler.hxx>
 #include <NCollection_DataMap.hxx>
+#include <NCollection_DoubleMap.hxx>
 
 #include <Basics_Utils.hxx>
 
@@ -200,6 +200,8 @@ namespace
 
   void SetDisplayEntity(int theCommandID);
 
+  int ActionToControl( int theID, bool theReversed = false );
+
   void Control( int theCommandID );
 
   // Definitions
@@ -534,7 +536,6 @@ namespace
     {
       format = "CGNS";
       notSupportedElemTypes.push_back( SMESH::Entity_Ball );
-      notSupportedElemTypes.push_back( SMESH::Entity_BiQuad_Triangle );
     }
     else if ( isSAUV )
     {
@@ -545,6 +546,7 @@ namespace
       notSupportedElemTypes.push_back( SMESH::Entity_TriQuad_Hexa );
       notSupportedElemTypes.push_back( SMESH::Entity_Hexagonal_Prism );
       notSupportedElemTypes.push_back( SMESH::Entity_Polygon );
+      notSupportedElemTypes.push_back( SMESH::Entity_Quad_Polygon );
       notSupportedElemTypes.push_back( SMESH::Entity_Polyhedra );
     }
     else if ( isGMF )
@@ -1581,89 +1583,43 @@ namespace
     }
   }
 
+  int ActionToControl( int theID, bool theReversed )
+  {
+    NCollection_DoubleMap<int,int> ActionControl;
+    ActionControl.Bind( 0,                                SMESH_Actor::eNone );
+    ActionControl.Bind( SMESHOp::OpFreeNode,              SMESH_Actor::eFreeNodes );
+    ActionControl.Bind( SMESHOp::OpEqualNode,             SMESH_Actor::eCoincidentNodes );
+    ActionControl.Bind( SMESHOp::OpFreeEdge,              SMESH_Actor::eFreeEdges );
+    ActionControl.Bind( SMESHOp::OpFreeBorder,            SMESH_Actor::eFreeBorders );
+    ActionControl.Bind( SMESHOp::OpLength,                SMESH_Actor::eLength );
+    ActionControl.Bind( SMESHOp::OpConnection,            SMESH_Actor::eMultiConnection );
+    ActionControl.Bind( SMESHOp::OpEqualEdge,             SMESH_Actor::eCoincidentElems1D );
+    ActionControl.Bind( SMESHOp::OpFreeFace,              SMESH_Actor::eFreeFaces );
+    ActionControl.Bind( SMESHOp::OpBareBorderFace,        SMESH_Actor::eBareBorderFace );
+    ActionControl.Bind( SMESHOp::OpOverConstrainedFace,   SMESH_Actor::eOverConstrainedFace );
+    ActionControl.Bind( SMESHOp::OpLength2D,              SMESH_Actor::eLength2D );
+    ActionControl.Bind( SMESHOp::OpConnection2D,          SMESH_Actor::eMultiConnection2D );
+    ActionControl.Bind( SMESHOp::OpArea,                  SMESH_Actor::eArea );
+    ActionControl.Bind( SMESHOp::OpTaper,                 SMESH_Actor::eTaper );
+    ActionControl.Bind( SMESHOp::OpAspectRatio,           SMESH_Actor::eAspectRatio );
+    ActionControl.Bind( SMESHOp::OpMinimumAngle,          SMESH_Actor::eMinimumAngle );
+    ActionControl.Bind( SMESHOp::OpWarpingAngle,          SMESH_Actor::eWarping );
+    ActionControl.Bind( SMESHOp::OpSkew,                  SMESH_Actor::eSkew );
+    ActionControl.Bind( SMESHOp::OpMaxElementLength2D,    SMESH_Actor::eMaxElementLength2D );
+    ActionControl.Bind( SMESHOp::OpEqualFace,             SMESH_Actor::eCoincidentElems2D );
+    ActionControl.Bind( SMESHOp::OpAspectRatio3D,         SMESH_Actor::eAspectRatio3D );
+    ActionControl.Bind( SMESHOp::OpVolume,                SMESH_Actor::eVolume3D );
+    ActionControl.Bind( SMESHOp::OpMaxElementLength3D,    SMESH_Actor::eMaxElementLength3D );
+    ActionControl.Bind( SMESHOp::OpBareBorderVolume,      SMESH_Actor::eBareBorderVolume );
+    ActionControl.Bind( SMESHOp::OpOverConstrainedVolume, SMESH_Actor::eOverConstrainedVolume );
+    ActionControl.Bind( SMESHOp::OpEqualVolume,           SMESH_Actor::eCoincidentElems3D );
+
+    return theReversed ? ActionControl.Find2( theID ) : ActionControl.Find1( theID );
+  }
+
   void Control( int theCommandID )
   {
-    SMESH_Actor::eControl aControl = SMESH_Actor::eNone;
-    switch ( theCommandID ){
-    case SMESHOp::OpFreeNode:
-      aControl = SMESH_Actor::eFreeNodes;
-      break;
-    case SMESHOp::OpEqualNode:
-      aControl = SMESH_Actor::eCoincidentNodes;
-      break;
-    case SMESHOp::OpFreeEdge:
-      aControl = SMESH_Actor::eFreeEdges;
-      break;
-    case SMESHOp::OpFreeBorder:
-      aControl = SMESH_Actor::eFreeBorders;
-      break;
-    case SMESHOp::OpLength:
-      aControl = SMESH_Actor::eLength;
-      break;
-    case SMESHOp::OpConnection:
-      aControl = SMESH_Actor::eMultiConnection;
-      break;
-    case SMESHOp::OpEqualEdge:
-      aControl = SMESH_Actor::eCoincidentElems1D;
-      break;
-    case SMESHOp::OpFreeFace:
-      aControl = SMESH_Actor::eFreeFaces;
-      break;
-    case SMESHOp::OpBareBorderFace:
-      aControl = SMESH_Actor::eBareBorderFace;
-      break;
-    case SMESHOp::OpOverConstrainedFace:
-      aControl = SMESH_Actor::eOverConstrainedFace;
-      break;
-    case SMESHOp::OpLength2D:
-      aControl = SMESH_Actor::eLength2D;
-      break;
-    case SMESHOp::OpConnection2D:
-      aControl = SMESH_Actor::eMultiConnection2D;
-      break;
-    case SMESHOp::OpArea:
-      aControl = SMESH_Actor::eArea;
-      break;
-    case SMESHOp::OpTaper:
-      aControl = SMESH_Actor::eTaper;
-      break;
-    case SMESHOp::OpAspectRatio:
-      aControl = SMESH_Actor::eAspectRatio;
-      break;
-    case SMESHOp::OpMinimumAngle:
-      aControl = SMESH_Actor::eMinimumAngle;
-      break;
-    case SMESHOp::OpWarpingAngle:
-      aControl = SMESH_Actor::eWarping;
-      break;
-    case SMESHOp::OpSkew:
-      aControl = SMESH_Actor::eSkew;
-      break;
-    case SMESHOp::OpMaxElementLength2D:
-      aControl = SMESH_Actor::eMaxElementLength2D;
-      break;
-    case SMESHOp::OpEqualFace:
-      aControl = SMESH_Actor:: eCoincidentElems2D;
-      break;
-    case SMESHOp::OpAspectRatio3D:
-      aControl = SMESH_Actor::eAspectRatio3D;
-      break;
-    case SMESHOp::OpVolume:
-      aControl = SMESH_Actor::eVolume3D;
-      break;
-    case SMESHOp::OpMaxElementLength3D:
-      aControl = SMESH_Actor::eMaxElementLength3D;
-      break;
-    case SMESHOp::OpBareBorderVolume:
-      aControl = SMESH_Actor::eBareBorderVolume;
-      break;
-    case SMESHOp::OpOverConstrainedVolume:
-      aControl = SMESH_Actor::eOverConstrainedVolume;
-      break;
-    case SMESHOp::OpEqualVolume:
-      aControl = SMESH_Actor::eCoincidentElems3D;
-      break;
-    }
+    SMESH_Actor::eControl aControl = SMESH_Actor::eControl( ActionToControl( theCommandID ) );
     _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
     LightApp_SelectionMgr *aSel = SMESHGUI::selectionMgr();
     SALOME_ListIO selected;
@@ -1678,7 +1634,7 @@ namespace
         if(!anIO.IsNull()){
           _PTR(SObject) SO = aStudy->FindObjectID( It.Value()->getEntry() );
           if ( SO ) {
-            CORBA::Object_var aObject = SMESH::SObjectToObject( SO );
+            CORBA::Object_var           aObject = SMESH::SObjectToObject( SO );
             SMESH::SMESH_Mesh_var      aMesh    = SMESH::SMESH_Mesh::_narrow( aObject );
             SMESH::SMESH_subMesh_var   aSubMesh = SMESH::SMESH_subMesh::_narrow( aObject );
             SMESH::SMESH_GroupBase_var aGroup   = SMESH::SMESH_GroupBase::_narrow( aObject );
@@ -2081,7 +2037,7 @@ bool SMESHGUI::automaticUpdate( SMESH::SMESH_IDSource_ptr theMesh,
   long nbEdges   = info[SMDSEntity_Edge] + info[SMDSEntity_Quad_Edge];
   long nbFaces   = info[SMDSEntity_Triangle]   + info[SMDSEntity_Quad_Triangle]   + info[SMDSEntity_BiQuad_Triangle] + 
                    info[SMDSEntity_Quadrangle] + info[SMDSEntity_Quad_Quadrangle] + info[SMDSEntity_BiQuad_Quadrangle] + 
-                   info[SMDSEntity_Polygon];
+                   info[SMDSEntity_Polygon] + info[SMDSEntity_Quad_Polygon];
   long nbVolumes = info[SMDSEntity_Tetra]   + info[SMDSEntity_Quad_Tetra] + 
                    info[SMDSEntity_Hexa]    + info[SMDSEntity_Quad_Hexa] + info[SMDSEntity_TriQuad_Hexa] + 
                    info[SMDSEntity_Pyramid] + info[SMDSEntity_Quad_Pyramid] + 
@@ -2264,6 +2220,26 @@ void SMESHGUI::EmitSignalVisibilityChanged()
   emit SignalVisibilityChanged();
 }
 
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+void SMESHGUI::EmitSignalCloseView()
+{
+  emit SignalCloseView();
+}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+void SMESHGUI::EmitSignalActivatedViewManager()
+{
+  emit SignalActivatedViewManager();
+}
+
 //=============================================================================
 /*!
  *
@@ -2468,8 +2444,9 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       if( aSel )
         aSel->selectedObjects( selected );
 
-      if( selected.Extent() ) {
-        Handle(SALOME_InteractiveObject) anIO = selected.First();
+      SALOME_ListIteratorOfListIO it(selected);
+      for( ; it.More(); it.Next()) {
+        Handle(SALOME_InteractiveObject) anIO = it.Value();
         if( anIO->hasEntry() ) {
           if( SMESH_Actor* anActor = SMESH::FindActorByEntry( anIO->getEntry() ) ) {
             anActor->SetControlMode( SMESH_Actor::eNone );
@@ -2479,6 +2456,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
           }
         }
       }
+      SMESH::UpdateView();
       break;
     }
   case SMESHOp::OpScalarBarProperties:
@@ -2606,8 +2584,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
     {
       SMESH::EDisplaing anAction;
       switch (theCommandID) {
-      case SMESHOp::OpHide: anAction = SMESH::eErase; break;
-      case SMESHOp::OpShow: anAction = SMESH::eDisplay; break;
+      case SMESHOp::OpHide:     anAction = SMESH::eErase; break;
+      case SMESHOp::OpShow:     anAction = SMESH::eDisplay; break;
       case SMESHOp::OpShowOnly: anAction = SMESH::eDisplayOnly; break;
       }
 
@@ -2616,7 +2594,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       if (aSel)
         aSel->selectedObjects( sel_objects );
 
-      if( theCommandID==SMESHOp::OpShowOnly )
+      if ( theCommandID==SMESHOp::OpShowOnly )
       {
         MESSAGE("anAction = SMESH::eDisplayOnly");
         startOperation( myEraseAll );
@@ -2630,20 +2608,17 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
 #endif
         if (vtkwnd) {
           SALOME_ListIteratorOfListIO It( to_process );
-          for ( ; It.More(); It.Next()) {
-            MESSAGE("---");
+          for ( ; It.More(); It.Next())
+          {
             Handle(SALOME_InteractiveObject) IOS = It.Value();
-            if (IOS->hasEntry()) {
-              MESSAGE("---");
-              if (!SMESH::UpdateView(anAction, IOS->getEntry())) {
+            if ( IOS->hasEntry() )
+            {
+              if ( !SMESH::UpdateView( anAction, IOS->getEntry() )) {
                 SMESHGUI::GetSMESHGUI()->EmitSignalVisibilityChanged();
                 break; // PAL16774 (Crash after display of many groups)
               }
               if (anAction == SMESH::eDisplayOnly)
-              {
-                MESSAGE("anAction = SMESH::eDisplayOnly");
                 anAction = SMESH::eDisplay;
-              }
             }
           }
         }
@@ -2835,6 +2810,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
+  case SMESHOp::OpSplitBiQuadratic:
   case SMESHOp::OpConvertMeshToQuadratic:
   case SMESHOp::OpCreateBoundaryElements: // create 2D mesh from 3D
   case SMESHOp::OpReorientFaces:
@@ -3256,6 +3232,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpBiQuadraticTriangle:
   case SMESHOp::OpQuadraticQuadrangle:
   case SMESHOp::OpBiQuadraticQuadrangle:
+  case SMESHOp::OpQuadraticPolygon:
   case SMESHOp::OpQuadraticTetrahedron:
   case SMESHOp::OpQuadraticPyramid:
   case SMESHOp::OpQuadraticPentahedron:
@@ -3268,15 +3245,16 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
         SMDSAbs_EntityType type = SMDSEntity_Last;
 
         switch (theCommandID) {
-        case SMESHOp::OpQuadraticEdge: type = SMDSEntity_Quad_Edge; break;
-        case SMESHOp::OpQuadraticTriangle: type = SMDSEntity_Quad_Triangle; break;
-        case SMESHOp::OpBiQuadraticTriangle: type = SMDSEntity_BiQuad_Triangle; break;
-        case SMESHOp::OpQuadraticQuadrangle: type = SMDSEntity_Quad_Quadrangle; break;
-        case SMESHOp::OpBiQuadraticQuadrangle: type = SMDSEntity_BiQuad_Quadrangle; break;
-        case SMESHOp::OpQuadraticTetrahedron: type = SMDSEntity_Quad_Tetra; break;
-        case SMESHOp::OpQuadraticPyramid: type = SMDSEntity_Quad_Pyramid; break;
-        case SMESHOp::OpQuadraticPentahedron: type = SMDSEntity_Quad_Penta; break;
-        case SMESHOp::OpQuadraticHexahedron: type = SMDSEntity_Quad_Hexa; break;
+        case SMESHOp::OpQuadraticEdge:          type = SMDSEntity_Quad_Edge; break;
+        case SMESHOp::OpQuadraticTriangle:      type = SMDSEntity_Quad_Triangle; break;
+        case SMESHOp::OpBiQuadraticTriangle:    type = SMDSEntity_BiQuad_Triangle; break;
+        case SMESHOp::OpQuadraticQuadrangle:    type = SMDSEntity_Quad_Quadrangle; break;
+        case SMESHOp::OpBiQuadraticQuadrangle:  type = SMDSEntity_BiQuad_Quadrangle; break;
+        case SMESHOp::OpQuadraticPolygon:       type = SMDSEntity_Quad_Polygon; break;
+        case SMESHOp::OpQuadraticTetrahedron:   type = SMDSEntity_Quad_Tetra; break;
+        case SMESHOp::OpQuadraticPyramid:       type = SMDSEntity_Quad_Pyramid; break;
+        case SMESHOp::OpQuadraticPentahedron:   type = SMDSEntity_Quad_Penta; break;
+        case SMESHOp::OpQuadraticHexahedron:    type = SMDSEntity_Quad_Hexa; break;
         case SMESHOp::OpTriQuadraticHexahedron: type = SMDSEntity_TriQuad_Hexa; break;
         default: break;
         }
@@ -3891,6 +3869,7 @@ void SMESHGUI::initialize( CAM_Application* app )
   createSMESHAction( SMESHOp::OpBiQuadraticTriangle,    "BIQUADRATIC_TRIANGLE",    "ICON_DLG_BIQUADRATIC_TRIANGLE" );
   createSMESHAction( SMESHOp::OpQuadraticQuadrangle,    "QUADRATIC_QUADRANGLE",    "ICON_DLG_QUADRATIC_QUADRANGLE" );
   createSMESHAction( SMESHOp::OpBiQuadraticQuadrangle,  "BIQUADRATIC_QUADRANGLE",  "ICON_DLG_BIQUADRATIC_QUADRANGLE" );
+  createSMESHAction( SMESHOp::OpQuadraticPolygon,       "QUADRATIC_POLYGON",       "ICON_DLG_QUADRATIC_POLYGON" );
   createSMESHAction( SMESHOp::OpQuadraticTetrahedron,   "QUADRATIC_TETRAHEDRON",   "ICON_DLG_QUADRATIC_TETRAHEDRON" );
   createSMESHAction( SMESHOp::OpQuadraticPyramid,       "QUADRATIC_PYRAMID",       "ICON_DLG_QUADRATIC_PYRAMID" );
   createSMESHAction( SMESHOp::OpQuadraticPentahedron,   "QUADRATIC_PENTAHEDRON",   "ICON_DLG_QUADRATIC_PENTAHEDRON" );
@@ -3921,6 +3900,7 @@ void SMESHGUI::initialize( CAM_Application* app )
   createSMESHAction( SMESHOp::OpUnionOfTriangles,       "UNION",           "ICON_UNIONTRI" );
   createSMESHAction( SMESHOp::OpCuttingOfQuadrangles,   "CUT",             "ICON_CUTQUAD" );
   createSMESHAction( SMESHOp::OpSplitVolumes,           "SPLIT_TO_TETRA",  "ICON_SPLIT_TO_TETRA" );
+  createSMESHAction( SMESHOp::OpSplitBiQuadratic,       "SPLIT_BIQUAD",    "ICON_SPLIT_BIQUAD" );
   createSMESHAction( SMESHOp::OpSmoothing,              "SMOOTH",          "ICON_DLG_SMOOTHING" );
   createSMESHAction( SMESHOp::OpExtrusion,              "EXTRUSION",       "ICON_EXTRUSION" );
   createSMESHAction( SMESHOp::OpExtrusionAlongAPath,    "EXTRUSION_ALONG", "ICON_EXTRUSION_ALONG" );
@@ -4005,12 +3985,14 @@ void SMESHGUI::initialize( CAM_Application* app )
 
   createMenu( separator(), fileId );
 
+  QMenu* nodeMenu = new QMenu(); QMenu* edgeMenu = new QMenu();
+  QMenu* faceMenu = new QMenu(); QMenu* volumeMenu = new QMenu();
   int importId = createMenu( tr( "MEN_IMPORT" ), fileId, -1, 10 ),
       exportId = createMenu( tr( "MEN_EXPORT" ), fileId, -1, 10 ),
-      nodeId   = createMenu( tr( "MEN_NODE_CTRL" ), ctrlId, -1, 10 ),
-      edgeId   = createMenu( tr( "MEN_EDGE_CTRL" ), ctrlId, -1, 10 ),
-      faceId   = createMenu( tr( "MEN_FACE_CTRL" ), ctrlId, -1, 10 ),
-      volumeId = createMenu( tr( "MEN_VOLUME_CTRL" ), ctrlId, -1, 10 ),
+      nodeId   = createMenu( tr( "MEN_NODE_CTRL" ), ctrlId, -1, 10, -1, nodeMenu ),
+      edgeId   = createMenu( tr( "MEN_EDGE_CTRL" ), ctrlId, -1, 10, -1, edgeMenu ),
+      faceId   = createMenu( tr( "MEN_FACE_CTRL" ), ctrlId, -1, 10, -1, faceMenu ),
+      volumeId = createMenu( tr( "MEN_VOLUME_CTRL" ), ctrlId, -1, 10, -1, volumeMenu ),
       addId    = createMenu( tr( "MEN_ADD" ),    modifyId, 402 ),
       removeId = createMenu( tr( "MEN_REMOVE" ), modifyId, 403 ),
     //renumId  = createMenu( tr( "MEN_RENUM" ),  modifyId, 404 ),
@@ -4072,11 +4054,11 @@ void SMESHGUI::initialize( CAM_Application* app )
 
   createMenu( SMESHOp::OpFreeNode,              nodeId,   -1 );
   createMenu( SMESHOp::OpEqualNode,             nodeId,   -1 );
-  createMenu( SMESHOp::OpFreeEdge,              edgeId,   -1 );
   createMenu( SMESHOp::OpFreeBorder,            edgeId,   -1 );
   createMenu( SMESHOp::OpLength,                edgeId,   -1 );
   createMenu( SMESHOp::OpConnection,            edgeId,   -1 );
   createMenu( SMESHOp::OpEqualEdge,             edgeId,   -1 );
+  createMenu( SMESHOp::OpFreeEdge,              faceId,   -1 );
   createMenu( SMESHOp::OpFreeFace,              faceId,   -1 );
   createMenu( SMESHOp::OpBareBorderFace,        faceId,   -1 );
   createMenu( SMESHOp::OpOverConstrainedFace,   faceId,   -1 );
@@ -4121,6 +4103,7 @@ void SMESHGUI::initialize( CAM_Application* app )
   createMenu( SMESHOp::OpBiQuadraticTriangle ,   addId, -1 );
   createMenu( SMESHOp::OpQuadraticQuadrangle,    addId, -1 );
   createMenu( SMESHOp::OpBiQuadraticQuadrangle,  addId, -1 );
+  createMenu( SMESHOp::OpQuadraticPolygon,       addId, -1 );
   createMenu( SMESHOp::OpQuadraticTetrahedron,   addId, -1 );
   createMenu( SMESHOp::OpQuadraticPyramid,       addId, -1 );
   createMenu( SMESHOp::OpQuadraticPentahedron,   addId, -1 );
@@ -4155,6 +4138,7 @@ void SMESHGUI::initialize( CAM_Application* app )
   createMenu( SMESHOp::OpUnionOfTriangles,       modifyId, -1 );
   createMenu( SMESHOp::OpCuttingOfQuadrangles,   modifyId, -1 );
   createMenu( SMESHOp::OpSplitVolumes,           modifyId, -1 );
+  createMenu( SMESHOp::OpSplitBiQuadratic,       modifyId, -1 );
   createMenu( SMESHOp::OpSmoothing,              modifyId, -1 );
   createMenu( SMESHOp::OpExtrusion,              modifyId, -1 );
   createMenu( SMESHOp::OpExtrusionAlongAPath ,   modifyId, -1 );
@@ -4170,6 +4154,11 @@ void SMESHGUI::initialize( CAM_Application* app )
   createMenu( SMESHOp::OpPropertiesVolume, basicPropId, -1 );
   createMenu( SMESHOp::OpUpdate,           viewId,      -1 );
 
+  connect( nodeMenu, SIGNAL( aboutToShow() ), this, SLOT( onUpdateControlActions() ) );
+  connect( edgeMenu, SIGNAL( aboutToShow() ), this, SLOT( onUpdateControlActions() ) );
+  connect( faceMenu, SIGNAL( aboutToShow() ), this, SLOT( onUpdateControlActions() ) );
+  connect( volumeMenu, SIGNAL( aboutToShow() ), this, SLOT( onUpdateControlActions() ) );
+
   // ----- create toolbars --------------
   int meshTb       = createTool( tr( "TB_MESH" ),      QString( "SMESHMeshToolbar" ) ),
       info         = createTool( tr( "TB_INFO" ),      QString( "SMESHInformationToolbar" ) ),
@@ -4211,12 +4200,12 @@ void SMESHGUI::initialize( CAM_Application* app )
   createTool( SMESHOp::OpFreeNode,  ctrl0dTb );
   createTool( SMESHOp::OpEqualNode, ctrl0dTb );
 
-  createTool( SMESHOp::OpFreeEdge,   ctrl1dTb );
   createTool( SMESHOp::OpFreeBorder, ctrl1dTb );
   createTool( SMESHOp::OpLength,     ctrl1dTb );
   createTool( SMESHOp::OpConnection, ctrl1dTb );
   createTool( SMESHOp::OpEqualEdge,  ctrl1dTb );
 
+  createTool( SMESHOp::OpFreeEdge,            ctrl2dTb );
   createTool( SMESHOp::OpFreeFace,            ctrl2dTb );
   createTool( SMESHOp::OpBareBorderFace,      ctrl2dTb );
   createTool( SMESHOp::OpOverConstrainedFace, ctrl2dTb );
@@ -4258,6 +4247,7 @@ void SMESHGUI::initialize( CAM_Application* app )
   createTool( SMESHOp::OpBiQuadraticTriangle,    addNonElemTb );
   createTool( SMESHOp::OpQuadraticQuadrangle,    addNonElemTb );
   createTool( SMESHOp::OpBiQuadraticQuadrangle,  addNonElemTb );
+  createTool( SMESHOp::OpQuadraticPolygon,       addNonElemTb );
   createTool( SMESHOp::OpQuadraticTetrahedron,   addNonElemTb );
   createTool( SMESHOp::OpQuadraticPyramid,       addNonElemTb );
   createTool( SMESHOp::OpQuadraticPentahedron,   addNonElemTb );
@@ -4289,6 +4279,7 @@ void SMESHGUI::initialize( CAM_Application* app )
   createTool( SMESHOp::OpUnionOfTriangles,       modifyTb );
   createTool( SMESHOp::OpCuttingOfQuadrangles,   modifyTb );
   createTool( SMESHOp::OpSplitVolumes,           modifyTb );
+  createTool( SMESHOp::OpSplitBiQuadratic,       modifyTb );
   createTool( SMESHOp::OpSmoothing,              modifyTb );
   createTool( SMESHOp::OpExtrusion,              modifyTb );
   createTool( SMESHOp::OpExtrusionAlongAPath,    modifyTb );
@@ -4338,38 +4329,39 @@ void SMESHGUI::initialize( CAM_Application* app )
     hasElems0d("({'Elem0d'} in elemTypes)"),
     hasEdges("({'Edge'} in elemTypes)"),
     hasFaces("({'Face'} in elemTypes)"),
-    hasVolumes("({'Volume'} in elemTypes)");
+    hasVolumes("({'Volume'} in elemTypes)"),
+    hasFacesOrVolumes("(({'Face'} in elemTypes) || ({'Volume'} in elemTypes)) ");
 
   createPopupItem( SMESHOp::OpFileInformation,      OB, mesh, "&& selcount=1 && isImported" );
-  createPopupItem( SMESHOp::OpCreateSubMesh,        OB, mesh, "&& isComputable");
-  createPopupItem( SMESHOp::OpEditMeshOrSubMesh,    OB, mesh, "&& isComputable");
-  createPopupItem( SMESHOp::OpEditMeshOrSubMesh,    OB, subMesh, "&& isComputable" );
+  createPopupItem( SMESHOp::OpCreateSubMesh,        OB, mesh, "&& hasGeomReference");
+  createPopupItem( SMESHOp::OpEditMeshOrSubMesh,    OB, mesh );
+  createPopupItem( SMESHOp::OpEditMeshOrSubMesh,    OB, subMesh, "&& hasGeomReference" );
   createPopupItem( SMESHOp::OpEditGroup,            OB, group );
   createPopupItem( SMESHOp::OpEditGeomGroupAsGroup, OB, group, "&& groupType != 'Group'" );
 
   popupMgr()->insert( separator(), -1, 0 );
   createPopupItem( SMESHOp::OpCompute,                OB, mesh, "&& isComputable" );
-  createPopupItem( SMESHOp::OpPreCompute,             OB, mesh, "&& isComputable && isPreComputable" );
+  createPopupItem( SMESHOp::OpPreCompute,             OB, mesh, "&& isPreComputable" );
   createPopupItem( SMESHOp::OpEvaluate,               OB, mesh, "&& isComputable" );
-  createPopupItem( SMESHOp::OpMeshOrder,              OB, mesh, "&& isComputable" );
+  createPopupItem( SMESHOp::OpMeshOrder,              OB, mesh, "&& isComputable && hasGeomReference" );
   createPopupItem( SMESHOp::OpUpdate,                 OB, mesh_part );
   createPopupItem( SMESHOp::OpMeshInformation,        OB, mesh_part );
   createPopupItem( SMESHOp::OpFindElementByPoint,     OB, mesh_group );
   createPopupItem( SMESHOp::OpOverallMeshQuality,     OB, mesh_part );
   popupMgr()->insert( separator(), -1, 0 );
   createPopupItem( SMESHOp::OpCreateGroup,            OB, mesh );
-  createPopupItem( SMESHOp::OpCreateGeometryGroup,    OB, mesh );
+  createPopupItem( SMESHOp::OpCreateGeometryGroup,    OB, mesh, "&& hasGeomReference" );
   createPopupItem( SMESHOp::OpConstructGroup,         OB, subMesh );
   popupMgr()->insert( separator(), -1, 0 );
   createPopupItem( SMESHOp::OpEditHypothesis,         OB, hypo);
   createPopupItem( SMESHOp::OpUnassign,               OB, hyp_alg );     // REMOVE HYPOTHESIS / ALGORITHMS
   popupMgr()->insert( separator(), -1, 0 );
-  createPopupItem( SMESHOp::OpClearMesh,              OB, mesh );
-  popupMgr()->insert( separator(), -1, 0 );
   createPopupItem( SMESHOp::OpConvertMeshToQuadratic, OB, mesh + " " + subMesh );  // convert to quadratic
   createPopupItem( SMESHOp::OpCreateBoundaryElements, OB, mesh + " " + group,      // create 2D mesh from 3D
                    "&& dim>=2");
   popupMgr()->insert( separator(), -1, 0 );
+  createPopupItem( SMESHOp::OpClearMesh,              OB, mesh );
+  popupMgr()->insert( separator(), -1, 0 );
 
   QString only_one_non_empty = QString( " && %1=1 && numberOfNodes>0" ).arg( dc );
   QString multiple_non_empty = QString( " && %1>0 && numberOfNodes>0" ).arg( dc );
@@ -4549,12 +4541,8 @@ void SMESHGUI::initialize( CAM_Application* app )
 
   aSubId = popupMgr()->insert( tr( "MEN_EDGE_CTRL" ), anId, -1 ); // EDGE CONTROLS
 
-  popupMgr()->insert( action( SMESHOp::OpFreeEdge ), aSubId, -1 );
-  popupMgr()->setRule( action( SMESHOp::OpFreeEdge ), aMeshInVtkHasEdges, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( SMESHOp::OpFreeEdge ), "controlMode = 'eFreeEdges'", QtxPopupMgr::ToggleRule );
-
   popupMgr()->insert( action( SMESHOp::OpFreeBorder ), aSubId, -1 );
-  popupMgr()->setRule( action( SMESHOp::OpFreeBorder ), aMeshInVtkHasEdges, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpFreeBorder ), aMeshInVTK + "&&" + hasEdges + "&&" + hasFacesOrVolumes, QtxPopupMgr::VisibleRule );
   popupMgr()->setRule( action( SMESHOp::OpFreeBorder ), "controlMode = 'eFreeBorders'", QtxPopupMgr::ToggleRule );
 
   popupMgr()->insert( action( SMESHOp::OpLength ), aSubId, -1 );
@@ -4570,6 +4558,10 @@ void SMESHGUI::initialize( CAM_Application* app )
 
   aSubId = popupMgr()->insert( tr( "MEN_FACE_CTRL" ), anId, -1 ); // FACE CONTROLS
 
+  popupMgr()->insert( action( SMESHOp::OpFreeEdge ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpFreeEdge ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpFreeEdge ), "controlMode = 'eFreeEdges'", QtxPopupMgr::ToggleRule );
+
   popupMgr()->insert ( action( SMESHOp::OpFreeFace ), aSubId, -1 );
   popupMgr()->setRule( action( SMESHOp::OpFreeFace ), aMeshInVtkHasFaces /*aMeshInVtkHasVolumes*/,
                                        QtxPopupMgr::VisibleRule );
@@ -4748,14 +4740,15 @@ bool SMESHGUI::activateModule( SUIT_Study* study )
 
   // import Python module that manages SMESH plugins (need to be here because SalomePyQt API uses active module)
   PyGILState_STATE gstate = PyGILState_Ensure();
-  PyObjWrapper pluginsmanager = PyImport_ImportModuleNoBlock((char*)"salome_pluginsmanager");
+  PyObject* pluginsmanager = PyImport_ImportModuleNoBlock((char*)"salome_pluginsmanager");
   if ( !pluginsmanager ) {
     PyErr_Print();
   }
   else {
-    PyObjWrapper result = PyObject_CallMethod( pluginsmanager, (char*)"initialize", (char*)"isss",1,"smesh",tr("MEN_MESH").toUtf8().data(),tr("SMESH_PLUGINS_OTHER").toUtf8().data());
+    PyObject* result = PyObject_CallMethod( pluginsmanager, (char*)"initialize", (char*)"isss",1,"smesh",tr("MEN_MESH").toUtf8().data(),tr("SMESH_PLUGINS_OTHER").toUtf8().data());
     if ( !result )
       PyErr_Print();
+    Py_XDECREF(result);
   }
   PyGILState_Release(gstate);
   // end of SMESH plugins loading
@@ -4765,11 +4758,10 @@ bool SMESHGUI::activateModule( SUIT_Study* study )
 
   //  0020210. Make SMESH_Gen update meshes at switching GEOM->SMESH
   GetSMESHGen()->SetCurrentStudy(SALOMEDS::Study::_nil());
-  if ( SalomeApp_Study* s = dynamic_cast<SalomeApp_Study*>( study ))
-    if ( _PTR(Study) aStudy = s->studyDS()) {
+  if ( SalomeApp_Study* s = dynamic_cast<SalomeApp_Study*>( study )) {
+    if ( _PTR(Study) aStudy = s->studyDS() )
       GetSMESHGen()->SetCurrentStudy( _CAST(Study,aStudy)->GetStudy() );
-      updateObjBrowser(); // objects can be removed
-    }
+  }
 
   // get all view currently opened in the study and connect their signals  to
   // the corresponding slots of the class.
@@ -4781,6 +4773,7 @@ bool SMESHGUI::activateModule( SUIT_Study* study )
       connectView( wnd );
   }
 
+  Py_XDECREF(pluginsmanager);
   return res;
 }
 
@@ -4865,7 +4858,9 @@ void SMESHGUI::windows( QMap<int, int>& aMap ) const
 {
   aMap.insert( SalomeApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
   aMap.insert( SalomeApp_Application::WT_NoteBook, Qt::LeftDockWidgetArea );
+#ifndef DISABLE_PYCONSOLE
   aMap.insert( SalomeApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
+#endif
 }
 
 void SMESHGUI::viewManagers( QStringList& list ) const
@@ -4883,6 +4878,7 @@ void SMESHGUI::onViewManagerActivated( SUIT_ViewManager* mgr )
       SUIT_ViewWindow *sf = aViews[i];
       connectView( sf );
     }
+    EmitSignalActivatedViewManager();
   }
 }
 
@@ -5453,6 +5449,9 @@ LightApp_Operation* SMESHGUI::createOperation( const int id ) const
   // to do : create operation here
   switch( id )
   {
+    case SMESHOp::OpSplitBiQuadratic:
+      op = new SMESHGUI_SplitBiQuadOp();
+    break;
     case SMESHOp::OpConvertMeshToQuadratic:
       op = new SMESHGUI_ConvToQuadOp();
     break;
@@ -6813,6 +6812,47 @@ void SMESHGUI::onHypothesisEdit( int result )
   updateObjBrowser( true );
 }
 
+/*!
+  \brief Actions after choosing menu of control modes
+  Updates control mode actions according to current selection
+*/
+void SMESHGUI::onUpdateControlActions()
+{
+  LightApp_SelectionMgr* aSel = SMESHGUI::selectionMgr();
+  SALOME_ListIO selected;
+  if ( aSel )
+    aSel->selectedObjects( selected );
+
+  SMESH_Actor::eControl aControl = SMESH_Actor::eNone;
+  if ( selected.Extent() ) {
+    if ( selected.First()->hasEntry() ) {
+      aControl = SMESH::FindActorByEntry( selected.First()->getEntry() )->GetControlMode();
+      SALOME_ListIteratorOfListIO it(selected);
+      for ( ; it.More(); it.Next() ) {
+        Handle(SALOME_InteractiveObject) anIO = it.Value();
+        if ( anIO->hasEntry() ) {
+          if ( SMESH_Actor* anActor = SMESH::FindActorByEntry( anIO->getEntry() ) ) {
+            if ( aControl != anActor->GetControlMode() ) {
+              aControl = SMESH_Actor::eNone;
+              break;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  int anAction = ActionToControl( aControl, true );
+  if ( anAction)
+    action( anAction )->setChecked( true );
+  else {
+    QMenu* send = (QMenu*)sender();
+    QList<QAction*> actions = send->actions();
+    for ( int i = 0; i < actions.size(); i++ )
+      actions[i]->setChecked( false );
+  }
+}
+
 
 /*!
   \brief Signal handler closing(SUIT_ViewWindow*) of a view
@@ -6823,6 +6863,7 @@ void SMESHGUI::onViewClosed( SUIT_ViewWindow* pview ) {
   //Crear all Plot2d Viewers if need.
   SMESH::ClearPlot2Viewers(pview);
 #endif
+  EmitSignalCloseView();
 }
 
 void SMESHGUI::message( const QString& msg )
index 2f8dfdc0f7375d5e39f133aa707f65e1bfe8a05d..12d43fc6d37e9713e2efc733552477ea5f0c122f 100644 (file)
@@ -133,6 +133,8 @@ public :
   void                            EmitSignalStudyFrameChanged();
   void                            EmitSignalCloseAllDialogs();
   void                            EmitSignalVisibilityChanged();
+  void                            EmitSignalCloseView();
+  void                            EmitSignalActivatedViewManager();
 
   virtual void                    contextMenuPopup( const QString&, QMenu*, QString& );
   virtual void                    createPreferences();
@@ -169,12 +171,15 @@ private slots:
   void                            onOperationCommited( SUIT_Operation* );
   void                            onOperationAborted( SUIT_Operation* );
   void                            onHypothesisEdit( int result );
+  void                            onUpdateControlActions();
 
 signals:
   void                            SignalDeactivateActiveDialog();
   void                            SignalStudyFrameChanged();
   void                            SignalCloseAllDialogs();
   void                            SignalVisibilityChanged();
+  void                            SignalCloseView();
+  void                            SignalActivatedViewManager();
 
 protected:
   void                            createSMESHAction( const int,
index 3ee1841ba693d852fa8ef951766bcc8da1e7fef7..96fca0d9f0f4e658cf0e94ae1e8d60964a707c9e 100644 (file)
@@ -223,6 +223,7 @@ SMESHGUI_Add0DElemsOnAllNodesOp::SMESHGUI_Add0DElemsOnAllNodesOp()
 
   connect( myDlg,              SIGNAL( selTypeChanged(int) ), SLOT( onSelTypeChange(int)));
   connect( myDlg->myFilterBtn, SIGNAL( clicked()),            SLOT( onSetFilter() ));
+  connect( myDlg->myGroupBox,  SIGNAL( clicked(bool)),        SLOT( updateButtons() ));
 }
 
 //================================================================================
@@ -270,6 +271,7 @@ void SMESHGUI_Add0DElemsOnAllNodesOp::selectionDone()
 
   myIO.Nullify();
   myDlg->setObjectText( 0, "");
+  updateButtons();
 
   SALOME_ListIO aList;
   selectionMgr()->selectedObjects( aList );
@@ -297,12 +299,14 @@ void SMESHGUI_Add0DElemsOnAllNodesOp::selectionDone()
   // fill the list of existing groups
   myDlg->myGroupListCmBox->clear();
   myDlg->myGroupListCmBox->addItem( QString() );
-  if ( !myIO.IsNull() && myIO->hasEntry()) {
-    _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
-    _PTR(SObject) meshSO = aStudy->FindObjectID( myIO->getEntry() );
+  if ( !myIO.IsNull() && myIO->hasEntry())
+  {
+    SMESH::SMESH_Mesh_var mesh = SMESH::GetMeshByIO( myIO );
+    _PTR(SObject)       meshSO = SMESH::ObjectToSObject( mesh );
     _PTR(SObject) group0DRoot;
-    if ( meshSO->FindSubObject( SMESH::Tag_0DElementsGroups, group0DRoot ))
+    if ( meshSO && meshSO->FindSubObject( SMESH::Tag_0DElementsGroups, group0DRoot ))
     {
+      _PTR(Study)              aStudy = SMESH::GetActiveStudyDocument();
       _PTR(ChildIterator) group0DIter = aStudy->NewChildIterator( group0DRoot );
       for ( ; group0DIter->More(); group0DIter->Next() )
       {
@@ -312,9 +316,44 @@ void SMESHGUI_Add0DElemsOnAllNodesOp::selectionDone()
           myDlg->myGroupListCmBox->addItem( groupName.c_str() );
       }
     }
+    // enable buttons
+    updateButtons();
   }
 }
 
+//=======================================================================
+//function : updateButtons
+//purpose  : enable [Apply]
+//=======================================================================
+
+void SMESHGUI_Add0DElemsOnAllNodesOp::updateButtons()
+{
+  bool ok = false;
+
+  if (( !myIO.IsNull() && myIO->hasEntry() && !myDlg->objectText( 0 ).isEmpty() ) &&
+      ( !myDlg->myGroupBox->isChecked() || !myDlg->myGroupListCmBox->currentText().isEmpty() ))
+  {
+    SMESH::SMESH_Mesh_var mesh = SMESH::GetMeshByIO( myIO );
+    if ( !mesh->_is_nil() )
+    {
+      if ( myDlg->getSelectionType() == SEL_OBJECT )
+        ok = true;
+      else
+      {
+        QString        ids = myDlg->objectText( 0 );
+        QStringList idList = ids.split( " ", QString::SkipEmptyParts );
+        const bool  isElem = ( myDlg->getSelectionType() == SEL_ELEMENTS );
+        QStringList::iterator idIt = idList.begin();
+        for ( ; idIt != idList.end() && !ok; ++idIt )
+          ok = ( mesh->GetElementType( idIt->toLong(), isElem ) != SMESH::ALL );
+      }
+    }
+  }
+
+  myDlg->button( QtxDialog::Apply )->setEnabled( ok );
+  myDlg->button( QtxDialog::OK    )->setEnabled( ok );
+}
+
 //================================================================================
 /*!
  * \brief Return a filter of objects
@@ -495,3 +534,14 @@ void SMESHGUI_Add0DElemsOnAllNodesOp::onSetFilter()
 
   myFilterDlg->show();
 }
+
+//=======================================================================
+//function : onTextChanged
+//purpose  : SLOT called when the user types IDs
+//=======================================================================
+
+void SMESHGUI_Add0DElemsOnAllNodesOp::onTextChanged( int obj, const QStringList& text )
+{
+  SMESHGUI_SelectionOp::onTextChanged( obj, text );
+  updateButtons();
+}
index 49ae8724a086f827340fe4b58a24a44c6cdb4014..805b9316ba90962bcb24809958b96e0a28c641b7 100644 (file)
@@ -99,6 +99,8 @@ class SMESHGUI_EXPORT SMESHGUI_Add0DElemsOnAllNodesOp : public SMESHGUI_Selectio
   virtual bool                   onApply();
   void                           onSelTypeChange(int);
   void                           onSetFilter();
+  virtual void                   onTextChanged( int, const QStringList& );
+  void                           updateButtons();
 
  private:
   SMESHGUI_Add0DElemsOnAllNodesDlg* myDlg;
index 35bc44b9b1d4c1fd02c4b5251c1d6c837f558693..a93494cc31eddf83720949befb879ed860283448 100644 (file)
@@ -214,12 +214,13 @@ namespace SMESH
       SetVisibility(true, theActor->GetFacesOriented(), false);
     }
 
-    void SetBallPosition(SMESH_Actor* theActor,TVTKIds& theIds, double theDiameter) {
+    void SetBallPosition(SMESH_Actor* theActor,TVTKIds& theIds, double theDiameter)
+    {
       vtkUnstructuredGrid *aGrid = theActor->GetUnstructuredGrid();
       myBallPolyData->Reset();
       myBallPolyData->DeleteCells();
       myBallPolyData->SetPoints(aGrid->GetPoints());
-      
+
       vtkDataArray* aScalars = vtkDataArray::CreateDataArray(VTK_DOUBLE);
       aScalars->SetNumberOfComponents(1);
       aScalars->SetNumberOfTuples(theIds.size());
@@ -235,7 +236,7 @@ namespace SMESH
         aScalars->SetTuple(anId,&d);
         anIds->Reset();
       }
-      
+
       anIds->Delete();
       myBallPolyData->Modified();
       SetVisibility (false, false, true);
@@ -515,10 +516,13 @@ void SMESHGUI_AddMeshElementDlg::Init()
   connect(SelectButtonC1A1,SIGNAL(clicked()),                     SLOT(SetEditCurrentArgument()));
   connect(LineEditC1A1,    SIGNAL(textChanged(const QString&)),   SLOT(onTextChange(const QString&)));
   connect(mySMESHGUI,      SIGNAL(SignalDeactivateActiveDialog()),SLOT(DeactivateActiveDialog()));
+
   connect(mySelectionMgr,  SIGNAL(currentSelectionChanged()),     SLOT(SelectionIntoArgument()));
   /* to close dialog if study frame change */
   connect(mySMESHGUI,      SIGNAL(SignalStudyFrameChanged()),     SLOT(reject()));
-  connect(mySMESHGUI,      SIGNAL(SignalCloseAllDialogs()),       SLOT(reject()));    
+  connect(mySMESHGUI,      SIGNAL(SignalCloseAllDialogs()),       SLOT(reject()));
+  connect(mySMESHGUI,      SIGNAL(SignalActivatedViewManager()),  SLOT(onOpenView()));
+  connect(mySMESHGUI,      SIGNAL(SignalCloseView()),             SLOT(onCloseView()));
 
   if (Reverse)
     connect(Reverse,       SIGNAL(stateChanged(int)),             SLOT(CheckBox(int)));
@@ -579,6 +583,13 @@ void SMESHGUI_AddMeshElementDlg::ClickOnApply()
                                                tr( "SMESH_BUT_YES" ), tr( "SMESH_BUT_NO" ), 0, 1 );
           if ( res == 1 ) return;
         }
+        SMESH::SMESH_GroupOnFilter_var aFilterGroup = SMESH::SMESH_GroupOnFilter::_narrow( myGroups[idx-1] );
+        if ( !aFilterGroup->_is_nil() ) {
+          int res = SUIT_MessageBox::question( this, tr( "SMESH_WRN_WARNING" ),
+                                               tr( "MESH_FILTER_GRP_CHOSEN" ).arg( aGroupName ),
+                                               tr( "SMESH_BUT_YES" ), tr( "SMESH_BUT_NO" ), 0, 1 );
+          if ( res == 1 ) return;
+        }
         aGroup = myGroups[idx-1];
       }
     }
@@ -587,16 +598,19 @@ void SMESHGUI_AddMeshElementDlg::ClickOnApply()
     SMESH::long_array_var anIdList = new SMESH::long_array;
     anIdList->length( 1 );
     anIdList[0] = -1;
-    const bool onlyNodesInMesh = ( myMesh->NbElements() == 0 );
+    //const bool onlyNodesInMesh = ( myMesh->NbElements() == 0 );
+    int nbElemsBefore = 0;
 
     switch (myElementType) {
     case SMDSAbs_0DElement:
+      nbElemsBefore = myMesh->Nb0DElements();
       anIdList->length( anArrayOfIndices->length() );
       for ( size_t i = 0; i < anArrayOfIndices->length(); ++i )
         anIdList[i] = aMeshEditor->Add0DElement(anArrayOfIndices[i]);
       break;
     case SMDSAbs_Ball:
       if ( myGeomType == SMDSEntity_Ball ) {
+        nbElemsBefore = myMesh->NbBalls();
         anIdList->length( anArrayOfIndices->length() );
         for ( size_t i = 0; i < anArrayOfIndices->length(); ++i )
           anIdList[i] = aMeshEditor->AddBall(anArrayOfIndices[i],
@@ -604,21 +618,24 @@ void SMESHGUI_AddMeshElementDlg::ClickOnApply()
       }
       break;
     case SMDSAbs_Edge:
+      nbElemsBefore = myMesh->NbEdges();
       anIdList[0] = aMeshEditor->AddEdge(anArrayOfIndices.inout()); break;
     case SMDSAbs_Face:
+      nbElemsBefore = myMesh->NbFaces();
       if ( myIsPoly )
         anIdList[0] = aMeshEditor->AddPolygonalFace(anArrayOfIndices.inout());
       else
         anIdList[0] = aMeshEditor->AddFace(anArrayOfIndices.inout());
       break;
     default:
+      nbElemsBefore = myMesh->NbVolumes();
       anIdList[0] = aMeshEditor->AddVolume(anArrayOfIndices.inout()); break;
     }
 
     if ( anIdList[0] > 0 && addToGroup && !aGroupName.isEmpty() ) {
       SMESH::SMESH_Group_var aGroupUsed;
       if ( aGroup->_is_nil() ) {
-        // create new group 
+        // create new group
         aGroupUsed = SMESH::AddGroup( myMesh, (SMESH::ElementType)myElementType, aGroupName );
         if ( !aGroupUsed->_is_nil() ) {
           myGroups.append(SMESH::SMESH_GroupBase::_duplicate(aGroupUsed));
@@ -626,7 +643,8 @@ void SMESHGUI_AddMeshElementDlg::ClickOnApply()
         }
       }
       else {
-        SMESH::SMESH_GroupOnGeom_var aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( aGroup );
+        SMESH::SMESH_GroupOnGeom_var     aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( aGroup );
+        SMESH::SMESH_GroupOnFilter_var aFilterGroup = SMESH::SMESH_GroupOnFilter::_narrow( aGroup );
         if ( !aGeomGroup->_is_nil() ) {
           aGroupUsed = myMesh->ConvertToStandalone( aGeomGroup );
           if ( !aGroupUsed->_is_nil() && idx > 0 ) {
@@ -634,6 +652,13 @@ void SMESHGUI_AddMeshElementDlg::ClickOnApply()
             SMESHGUI::GetSMESHGUI()->getApp()->updateObjectBrowser();
           }
         }
+        else if ( !aFilterGroup->_is_nil() ) {
+          aGroupUsed = myMesh->ConvertToStandalone( aFilterGroup );
+          if ( !aGroupUsed->_is_nil() && idx > 0 ) {
+            myGroups[idx-1] = SMESH::SMESH_GroupBase::_duplicate(aGroupUsed);
+            SMESHGUI::GetSMESHGUI()->getApp()->updateObjectBrowser();
+          }
+        }
         else
           aGroupUsed = SMESH::SMESH_Group::_narrow( aGroup );
       }
@@ -647,8 +672,24 @@ void SMESHGUI_AddMeshElementDlg::ClickOnApply()
     mySelectionMgr->setSelectedObjects( aList, false );
 
     mySimulation->SetVisibility(false);
-    if ( onlyNodesInMesh )
-      myActor->SetRepresentation( SMESH_Actor::eEdge ); // wireframe
+    // if ( onlyNodesInMesh )
+    //   myActor->SetRepresentation( SMESH_Actor::eEdge ); // wireframe
+    if ( nbElemsBefore == 0  )
+    {
+      // 1st element of the type has been added, update actor to show this entity
+      unsigned int aMode = myActor->GetEntityMode();
+      switch ( myElementType ) {
+      case SMDSAbs_Edge:
+        myActor->SetRepresentation(SMESH_Actor::eEdge);
+        myActor->SetEntityMode( aMode |= SMESH_Actor::eEdges ); break;
+      case SMDSAbs_Face:
+        myActor->SetRepresentation(SMESH_Actor::eSurface);
+        myActor->SetEntityMode( aMode |= SMESH_Actor::eFaces ); break;
+      case SMDSAbs_Volume:
+        myActor->SetRepresentation(SMESH_Actor::eSurface);
+        myActor->SetEntityMode( aMode |= SMESH_Actor::eVolumes ); break;
+      }
+    }
     SMESH::UpdateView();
 
     buttonOk->setEnabled(false);
@@ -942,9 +983,15 @@ void SMESHGUI_AddMeshElementDlg::ActivateThisDialog()
 //=================================================================================
 void SMESHGUI_AddMeshElementDlg::enterEvent (QEvent*)
 {
-  if (GroupConstructors->isEnabled())
-    return;
-  ActivateThisDialog();
+  if ( !GroupConstructors->isEnabled() ) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector && !mySimulation) {
+      mySelector = aViewWindow->GetSelector();
+      mySimulation = new SMESH::TElementSimulation(
+        dynamic_cast<SalomeApp_Application*>( mySMESHGUI->application() ) );
+    }
+    ActivateThisDialog();
+  }
 }
 
 //=================================================================================
@@ -979,7 +1026,7 @@ void SMESHGUI_AddMeshElementDlg::keyPressEvent( QKeyEvent* e )
 }
 
 //=================================================================================
-// function : isValid
+// function : onDiameterChanged()
 // purpose  :
 //=================================================================================
 void SMESHGUI_AddMeshElementDlg::onDiameterChanged(){
@@ -987,7 +1034,37 @@ void SMESHGUI_AddMeshElementDlg::onDiameterChanged(){
 }
 
 //=================================================================================
-// function : isValid
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_AddMeshElementDlg::onOpenView()
+{
+  if ( mySelector && mySimulation ) {
+    mySimulation->SetVisibility(false);
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    mySimulation = new SMESH::TElementSimulation(
+      dynamic_cast<SalomeApp_Application*>( mySMESHGUI->application() ) );
+    ActivateThisDialog();
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_AddMeshElementDlg::onCloseView()
+{
+  DeactivateActiveDialog();
+  mySelector = 0;
+  delete mySimulation;
+  mySimulation = 0;
+}
+
+//=================================================================================
+// function : isValid()
 // purpose  :
 //=================================================================================
 bool SMESHGUI_AddMeshElementDlg::isValid()
index 41a4d8516ee563d974478f7f21eb452a982879bb..9b19e3b064b984bb46385c5b78cf678cdd78689e 100644 (file)
@@ -130,6 +130,8 @@ private slots:
   void                        ActivateThisDialog();
   void                        CheckBox( int );
   void                        onTextChange( const QString& );
+  void                        onOpenView();
+  void                        onCloseView();
 };
 
 #endif // SMESHGUI_ADDMESHELEMENTDLG_H
index 6ee198e7bfacdf3623648e9201478dab831a37fe..5cfddb9ce8850d6010519951a9d9cb24e90ef2fb 100644 (file)
 
 namespace
 {
+
+  // Define the sequences of ids
+  static int FirstEdgeIds[] = {0};
+  static int LastEdgeIds[] =  {1};
+
+  static int FirstTriangleIds[] = {0,1,2};
+  static int LastTriangleIds[] =  {1,2,0};
+
+  static int FirstQuadrangleIds[] = {0,1,2,3};
+  static int LastQuadrangleIds[] =  {1,2,3,0};
+
+  static int FirstTetrahedronIds[] = {0,1,2,3,3,3};
+  static int LastTetrahedronIds[] =  {1,2,0,0,1,2};
+
+  static int FirstPyramidIds[] = {0,1,2,3,4,4,4,4};
+  static int LastPyramidIds[] =  {1,2,3,0,0,1,2,3};
+
+  static int FirstPentahedronIds[] = {0,1,2,3,4,5,0,1,2};
+  static int LastPentahedronIds[] =  {1,2,0,4,5,3,3,4,5};
+
+  static int FirstHexahedronIds[] = {0,1,2,3,4,5,6,7,0,1,2,3};
+  static int LastHexahedronIds[] =  {1,2,3,0,5,6,7,4,4,5,6,7};
+
+  static vector<int> FirstPolygonIds;
+  static vector<int> LastPolygonIds;
+
   void ReverseConnectivity( std::vector<vtkIdType> & ids, SMDSAbs_EntityType type,
                             bool toReverse, // inverse element
                             bool toVtkOrder ) // smds connectivity to vtk one
   {
     if ( toReverse ) // first reverse smds order
     {
-      const std::vector<int>& index = SMDS_MeshCell::reverseSmdsOrder(type);
+      const std::vector<int>& index = SMDS_MeshCell::reverseSmdsOrder(type, ids.size());
       SMDS_MeshCell::applyInterlace( index, ids );
     }
     if ( toVtkOrder ) // from smds to vtk connectivity
@@ -113,7 +139,8 @@ namespace
 }
 namespace SMESH
 {
-  class TElementSimulationQuad {
+  class TElementSimulationQuad
+  {
     SalomeApp_Application* myApplication;
     SUIT_ViewWindow* myViewWindow;
     SVTK_ViewWindow* myVTKViewWindow;
@@ -148,7 +175,7 @@ namespace SMESH
       myPreviewActor->PickableOff();
       myPreviewActor->VisibilityOff();
       myPreviewActor->SetMapper(myMapper);
-      
+
       QColor ffc, bfc;
       int delta;
       vtkProperty* myProp = vtkProperty::New();
@@ -249,35 +276,12 @@ namespace SMESH
 
       myGrid->Delete();
 
-//       myProp->Delete();
-//       myBackProp->Delete();
+      //       myProp->Delete();
+      //       myBackProp->Delete();
     }
   };
 }
 
-
-// Define the sequences of ids
-static int FirstEdgeIds[] = {0};
-static int LastEdgeIds[] =  {1};
-
-static int FirstTriangleIds[] = {0,1,2};
-static int LastTriangleIds[] =  {1,2,0};
-
-static int FirstQuadrangleIds[] = {0,1,2,3};
-static int LastQuadrangleIds[] =  {1,2,3,0};
-
-static int FirstTetrahedronIds[] = {0,1,2,3,3,3};
-static int LastTetrahedronIds[] =  {1,2,0,0,1,2};
-
-static int FirstPyramidIds[] = {0,1,2,3,4,4,4,4};
-static int LastPyramidIds[] =  {1,2,3,0,0,1,2,3};
-
-static int FirstPentahedronIds[] = {0,1,2,3,4,5,0,1,2};
-static int LastPentahedronIds[] =  {1,2,0,4,5,3,3,4,5};
-
-static int FirstHexahedronIds[] = {0,1,2,3,4,5,6,7,0,1,2,3};
-static int LastHexahedronIds[] =  {1,2,3,0,5,6,7,4,4,5,6,7};
-
 /*!
   \class BusyLocker
   \brief Simple 'busy state' flag locker.
@@ -335,7 +339,6 @@ SMESHGUI_AddQuadraticElementDlg::SMESHGUI_AddQuadraticElementDlg( SMESHGUI* theM
     mySMESHGUI( theModule ),
     mySelectionMgr( SMESH::GetSelectionMgr( theModule ) ),
     myGeomType( theType ),
-    //myType( theType ),
     myBusy( false )
 {
   setModal( false );
@@ -359,6 +362,9 @@ SMESHGUI_AddQuadraticElementDlg::SMESHGUI_AddQuadraticElementDlg( SMESHGUI* theM
   case SMDSEntity_Quad_Quadrangle:
     anElementName = QString("QUADRATIC_QUADRANGLE");
     break;
+  case SMDSEntity_Quad_Polygon:
+    anElementName = QString("QUADRATIC_POLYGON");
+    break;
   case SMDSEntity_BiQuad_Quadrangle:
     anElementName = QString("BIQUADRATIC_QUADRANGLE");
     break;
@@ -561,6 +567,11 @@ void SMESHGUI_AddQuadraticElementDlg::Init()
     myNbCenterNodes = 1;
     myHelpFileName = "adding_quadratic_elements_page.html#?"; //Adding_quadrangles
     break;
+  case SMDSEntity_Quad_Polygon:
+    aNumRows = 5;
+    myNbCorners = 0; // no limit
+    myHelpFileName = "adding_quadratic_elements_page.html#?"; //Adding_polygons
+    break;
   case SMDSEntity_Quad_Tetra:
     aNumRows = 6;
     myNbCorners = 4;
@@ -650,6 +661,8 @@ void SMESHGUI_AddQuadraticElementDlg::Init()
   connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), SLOT(DeactivateActiveDialog()));
   connect(mySMESHGUI, SIGNAL (SignalStudyFrameChanged()), SLOT(reject()));
   connect(mySMESHGUI, SIGNAL (SignalCloseAllDialogs()), SLOT(reject()));
+  connect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), SLOT(onOpenView()));
+  connect(mySMESHGUI, SIGNAL (SignalCloseView()), SLOT(onCloseView()));
 
   myCurrentLineEdit = myCornerNodes;
 
@@ -687,6 +700,7 @@ bool SMESHGUI_AddQuadraticElementDlg::ClickOnApply()
     break;
   case SMDSEntity_Quad_Triangle:
   case SMDSEntity_Quad_Quadrangle:
+  case SMDSEntity_Quad_Polygon:
   case SMDSEntity_BiQuad_Triangle:
   case SMDSEntity_BiQuad_Quadrangle:
   case SMDSEntity_Quad_Tetra:
@@ -714,7 +728,7 @@ bool SMESHGUI_AddQuadraticElementDlg::ClickOnApply()
   if ( myReverseCB->isChecked())
     ReverseConnectivity( anIds, myGeomType, /*toReverse=*/true, /*toVtkOrder=*/false );
 
-  int aNumberOfIds =  anIds.size();
+  int aNumberOfIds = anIds.size();
   SMESH::long_array_var anArrayOfIdeces = new SMESH::long_array;
   anArrayOfIdeces->length( aNumberOfIds );
 
@@ -737,7 +751,14 @@ bool SMESHGUI_AddQuadraticElementDlg::ClickOnApply()
       SMESH::SMESH_GroupOnGeom_var aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( myGroups[idx-1] );
       if ( !aGeomGroup->_is_nil() ) {
         int res = SUIT_MessageBox::question( this, tr( "SMESH_WRN_WARNING" ),
-                                             tr( "MESH_STANDALONE_GRP_CHOSEN" ).arg( aGroupName ),
+                                             tr( "MESH_GEOM_GRP_CHOSEN" ).arg( aGroupName ),
+                                             tr( "SMESH_BUT_YES" ), tr( "SMESH_BUT_NO" ), 0, 1 );
+        if ( res == 1 ) return false;
+      }
+      SMESH::SMESH_GroupOnFilter_var aFilterGroup = SMESH::SMESH_GroupOnFilter::_narrow( myGroups[idx-1] );
+      if ( !aFilterGroup->_is_nil() ) {
+        int res = SUIT_MessageBox::question( this, tr( "SMESH_WRN_WARNING" ),
+                                             tr( "MESH_FILTER_GRP_CHOSEN" ).arg( aGroupName ),
                                              tr( "SMESH_BUT_YES" ), tr( "SMESH_BUT_NO" ), 0, 1 );
         if ( res == 1 ) return false;
       }
@@ -746,24 +767,31 @@ bool SMESHGUI_AddQuadraticElementDlg::ClickOnApply()
   }
 
   SMESH::ElementType anElementType;
-  long anElemId = -1;
+  long anElemId = -1, nbElemsBefore = 0;
   SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
   switch (myGeomType) {
   case SMDSEntity_Quad_Edge:
     anElementType = SMESH::EDGE;
+    nbElemsBefore = myMesh->NbEdges();
     anElemId = aMeshEditor->AddEdge(anArrayOfIdeces.inout()); break;
   case SMDSEntity_Quad_Triangle:
   case SMDSEntity_Quad_Quadrangle:
   case SMDSEntity_BiQuad_Triangle:
   case SMDSEntity_BiQuad_Quadrangle:
     anElementType = SMESH::FACE;
+    nbElemsBefore = myMesh->NbFaces();
     anElemId = aMeshEditor->AddFace(anArrayOfIdeces.inout()); break;
+  case SMDSEntity_Quad_Polygon:
+    anElementType = SMESH::FACE;
+    nbElemsBefore = myMesh->NbFaces();
+    anElemId = aMeshEditor->AddQuadPolygonalFace(anArrayOfIdeces.inout()); break;
   case SMDSEntity_Quad_Tetra:
   case SMDSEntity_Quad_Pyramid:
   case SMDSEntity_Quad_Penta:
   case SMDSEntity_Quad_Hexa:
   case SMDSEntity_TriQuad_Hexa:
     anElementType = SMESH::VOLUME;
+    nbElemsBefore = myMesh->NbVolumes();
     anElemId = aMeshEditor->AddVolume(anArrayOfIdeces.inout()); break;
   default: break;
   }
@@ -779,7 +807,8 @@ bool SMESHGUI_AddQuadraticElementDlg::ClickOnApply()
       }
     }
     else {
-      SMESH::SMESH_GroupOnGeom_var aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( aGroup );
+      SMESH::SMESH_GroupOnGeom_var     aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( aGroup );
+      SMESH::SMESH_GroupOnFilter_var aFilterGroup = SMESH::SMESH_GroupOnFilter::_narrow( aGroup );
       if ( !aGeomGroup->_is_nil() ) {
         aGroupUsed = myMesh->ConvertToStandalone( aGeomGroup );
         if ( !aGroupUsed->_is_nil() && idx > 0 ) {
@@ -787,6 +816,13 @@ bool SMESHGUI_AddQuadraticElementDlg::ClickOnApply()
           SMESHGUI::GetSMESHGUI()->getApp()->updateObjectBrowser();
         }
       }
+      else if ( !aFilterGroup->_is_nil() ) {
+        aGroupUsed = myMesh->ConvertToStandalone( aFilterGroup );
+        if ( !aGroupUsed->_is_nil() && idx > 0 ) {
+          myGroups[idx-1] = SMESH::SMESH_GroupBase::_duplicate(aGroupUsed);
+          SMESHGUI::GetSMESHGUI()->getApp()->updateObjectBrowser();
+        }
+      }
       else
         aGroupUsed = SMESH::SMESH_Group::_narrow( aGroup );
     }
@@ -799,6 +835,23 @@ bool SMESHGUI_AddQuadraticElementDlg::ClickOnApply()
     }
   }
 
+  if ( nbElemsBefore == 0  )
+  {
+    // 1st element of the type has been added, update actor to show this entity
+    unsigned int aMode = myActor->GetEntityMode();
+    switch ( anElementType ) {
+    case SMESH::EDGE:
+      myActor->SetRepresentation(SMESH_Actor::eEdge);
+      myActor->SetEntityMode( aMode |= SMESH_Actor::eEdges ); break;
+    case SMESH::FACE:
+      myActor->SetRepresentation(SMESH_Actor::eSurface);
+      myActor->SetEntityMode( aMode |= SMESH_Actor::eFaces ); break;
+    case SMESH::VOLUME:
+      myActor->SetRepresentation(SMESH_Actor::eSurface);
+      myActor->SetEntityMode( aMode |= SMESH_Actor::eVolumes ); break;
+    }
+  }
+
   SALOME_ListIO aList; aList.Append( myActor->getIO() );
   mySelector->ClearIndex();
   mySelectionMgr->setSelectedObjects( aList, false );
@@ -844,6 +897,35 @@ void SMESHGUI_AddQuadraticElementDlg::reject()
   QDialog::reject();
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_AddQuadraticElementDlg::onOpenView()
+{
+  if ( mySelector && mySimulation ) {
+    mySimulation->SetVisibility(false);
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    mySimulation = new SMESH::TElementSimulationQuad(
+      dynamic_cast<SalomeApp_Application*>( mySMESHGUI->application() ) );
+    ActivateThisDialog();
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_AddQuadraticElementDlg::onCloseView()
+{
+  DeactivateActiveDialog();
+  mySelector = 0;
+  delete mySimulation;
+  mySimulation = 0;
+}
 //=================================================================================
 // function : ClickOnHelp()
 // purpose  :
@@ -976,6 +1058,7 @@ void SMESHGUI_AddQuadraticElementDlg::SelectionIntoArgument()
       anElementType = SMESH::EDGE; break;
     case SMDSEntity_Quad_Triangle:
     case SMDSEntity_Quad_Quadrangle:
+    case SMDSEntity_Quad_Polygon:
     case SMDSEntity_BiQuad_Triangle:
     case SMDSEntity_BiQuad_Quadrangle:
       anElementType = SMESH::FACE; break;
@@ -1157,12 +1240,17 @@ void SMESHGUI_AddQuadraticElementDlg::ActivateThisDialog()
 // function : enterEvent()
 // purpose  :
 //=================================================================================
-
 void SMESHGUI_AddQuadraticElementDlg::enterEvent (QEvent*)
 {
-  if (GroupConstructors->isEnabled())
-    return;
-  ActivateThisDialog();
+  if ( !GroupConstructors->isEnabled() ) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector && !mySimulation) {
+      mySelector = aViewWindow->GetSelector();
+      mySimulation = new SMESH::TElementSimulationQuad(
+        dynamic_cast<SalomeApp_Application*>( mySMESHGUI->application() ) );
+    }
+    ActivateThisDialog();
+  }
 }
 
 //=================================================================================
@@ -1233,6 +1321,44 @@ void SMESHGUI_AddQuadraticElementDlg::UpdateTable( bool theConersValidity )
 {
   QStringList aListCorners = myCornerNodes->text().split(" ", QString::SkipEmptyParts);
 
+  if ( myGeomType == SMDSEntity_Quad_Polygon )        // POLYGON
+  {
+    if ( aListCorners.count() < 3 )
+      theConersValidity = false;
+
+    if ( aListCorners.count() != myTable->rowCount() && theConersValidity )
+    {
+      // adjust nb of rows for the polygon
+      int oldNbRows = myTable->rowCount();
+      myTable->setRowCount( aListCorners.count() );
+      for ( int row = oldNbRows; row < myTable->rowCount(); row++ )
+      {
+        myTable->setItem( row, 0, new QTableWidgetItem( "" ) );
+        myTable->item( row, 0 )->setFlags(0);
+
+        IdEditItem* anEditItem = new IdEditItem( "" );
+        anEditItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
+        myTable->setItem(row, 1, anEditItem);
+
+        myTable->setItem( row, 2, new QTableWidgetItem( "" ) );
+        myTable->item( row, 2 )->setFlags(0);
+      }
+      myNbCorners = aListCorners.count();
+
+      // fill FirstPolygonIds and LastPolygonIds
+      FirstPolygonIds.resize( aListCorners.count() );
+      LastPolygonIds .resize( aListCorners.count() );
+      for ( int i = 0; i < aListCorners.count(); ++i )
+      {
+        FirstPolygonIds[i] = i;
+        LastPolygonIds [i] = i+1;
+      }
+      LastPolygonIds.back() = 0;
+
+      myNbCorners = aListCorners.count();
+    }
+  }
+
   if ( aListCorners.count() == myNbCorners && theConersValidity )
   {
     myTable->setEnabled( true );
@@ -1259,6 +1385,10 @@ void SMESHGUI_AddQuadraticElementDlg::UpdateTable( bool theConersValidity )
       aFirstColIds = FirstQuadrangleIds;
       aLastColIds  = LastQuadrangleIds;
       break;
+    case SMDSEntity_Quad_Polygon:
+      aFirstColIds = & FirstPolygonIds[0];
+      aLastColIds  = & LastPolygonIds[0];
+      break;
     case SMDSEntity_Quad_Tetra:
       aFirstColIds = FirstTetrahedronIds;
       aLastColIds  = LastTetrahedronIds;
index 1aee0dc9eae9490cfd408b7be7561bc5a5931353..7a36de47b8048c1cb06693acf0cfed35ba7e3c14 100644 (file)
@@ -142,6 +142,8 @@ private slots:
   void                        SelectionIntoArgument();
   void                        DeactivateActiveDialog();
   void                        ActivateThisDialog();
+  void                        onOpenView();
+  void                        onCloseView();
 };
 
 #endif // SMESHGUI_ADDQUADRATICELEMENTDLG_H
index e2dd40b889f6671783a93c87243c67e65fad60a7..429531fd28919106e398c59cf2775f7339b2e467 100644 (file)
 //
 #include "SMESHGUI_ComputeDlg.h"
 
+#include "SMDS_Mesh.hxx"
+#include "SMDS_SetIterator.hxx"
 #include "SMESHGUI.h"
 #include "SMESHGUI_GEOMGenUtils.h"
-#include "SMESHGUI_MeshUtils.h"
-#include "SMESHGUI_VTKUtils.h"
-#include "SMESHGUI_MeshInfosBox.h"
 #include "SMESHGUI_HypothesesUtils.h"
 #include "SMESHGUI_MeshEditPreview.h"
-#include "SMESHGUI_MeshOrderOp.h"
+#include "SMESHGUI_MeshInfosBox.h"
 #include "SMESHGUI_MeshOrderDlg.h"
-
+#include "SMESHGUI_MeshOrderOp.h"
+#include "SMESHGUI_MeshUtils.h"
+#include "SMESHGUI_VTKUtils.h"
 #include "SMESH_Actor.h"
 #include "SMESH_ActorUtils.h"
 
-#include <SMDS_SetIterator.hxx>
-#include <SMDS_Mesh.hxx>
-
 // SALOME GEOM includes
 #include <GEOMBase.h>
 #include <GEOM_Actor.h>
 #include CORBA_SERVER_HEADER(SMESH_Group)
 
 // OCCT includes
+#include <BRepBndLib.hxx>
+#include <BRepMesh_IncrementalMesh.hxx>
 #include <BRep_Tool.hxx>
+#include <Bnd_Box.hxx>
+#include <Poly_Triangulation.hxx>
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
+#include <TopLoc_Location.hxx>
 #include <TopTools_IndexedMapOfShape.hxx>
 #include <TopoDS.hxx>
 
-#include <TopLoc_Location.hxx>
-#include <Poly_Triangulation.hxx>
-#include <Bnd_Box.hxx>
-#include <BRepBndLib.hxx>
-#include <BRepMesh_IncrementalMesh.hxx>
-
 #include <Standard_ErrorHandler.hxx>
 
 // Qt includes
@@ -490,7 +487,7 @@ namespace SMESH
 //=======================================================================
 
 SMESHGUI_ComputeDlg::SMESHGUI_ComputeDlg( QWidget* parent, bool ForEval )
- : SMESHGUI_Dialog( parent, false, true, Close/* | Help*/ )
+ : SMESHGUI_Dialog( parent, false, true, Close | Help )
 {
   QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame());
   aDlgLay->setMargin( 0 );
@@ -1485,6 +1482,7 @@ QTableWidget* SMESHGUI_BaseComputeOp::table()
 SMESHGUI_ComputeOp::SMESHGUI_ComputeOp()
  : SMESHGUI_BaseComputeOp()
 {
+  myHelpFileName = "constructing_meshes_page.html#compute_anchor";
 }
 
 
@@ -1548,13 +1546,12 @@ LightApp_Dialog* SMESHGUI_ComputeOp::dlg() const
 //================================================================================
 
 SMESHGUI_PrecomputeOp::SMESHGUI_PrecomputeOp()
- : SMESHGUI_BaseComputeOp(),
- myDlg( 0 ),
- myOrderMgr( 0 ),
- myActiveDlg( 0 ),
- myPreviewDisplayer( 0 )
 : SMESHGUI_BaseComputeOp(),
   myDlg( 0 ),
   myOrderMgr( 0 ),
   myActiveDlg( 0 ),
   myPreviewDisplayer( 0 )
 {
-  myHelpFileName = "constructing_meshes_page.html#preview_mesh_anchor";
 }
 
 //================================================================================
@@ -1595,6 +1592,8 @@ LightApp_Dialog* SMESHGUI_PrecomputeOp::dlg() const
 
 void SMESHGUI_PrecomputeOp::startOperation()
 {
+  myHelpFileName = "constructing_meshes_page.html#preview_anchor"; // other anchor onCompute()
+
   if ( !myDlg )
   {
     myDlg = new SMESHGUI_PrecomputeDlg( desktop() );
@@ -1729,13 +1728,14 @@ void SMESHGUI_PrecomputeOp::initDialog()
 void SMESHGUI_PrecomputeOp::getAssignedAlgos(_PTR(SObject) theMesh,
                                              QMap<int,int>& theModeMap)
 {
-  _PTR(SObject)          aHypRoot;
+  if ( !theMesh ) return;
+  _PTR(SObject)          aHypFolder;
   _PTR(GenericAttribute) anAttr;
   int aPart = SMESH::Tag_RefOnAppliedAlgorithms;
-  if ( theMesh && theMesh->FindSubObject( aPart, aHypRoot ) )
+  if ( theMesh->FindSubObject( aPart, aHypFolder ) )
   {
     _PTR(ChildIterator) anIter =
-      SMESH::GetActiveStudyDocument()->NewChildIterator( aHypRoot );
+      SMESH::GetActiveStudyDocument()->NewChildIterator( aHypFolder );
     for ( ; anIter->More(); anIter->Next() )
     {
       _PTR(SObject) anObj = anIter->Value();
@@ -1744,16 +1744,60 @@ void SMESHGUI_PrecomputeOp::getAssignedAlgos(_PTR(SObject) theMesh,
         anObj = aRefObj;
       else
         continue;
-      
+
       if ( anObj->FindAttribute( anAttr, "AttributeName" ) )
       {
         CORBA::Object_var aVar = _CAST(SObject,anObj)->GetObject();
         if ( CORBA::is_nil( aVar ) )
           continue;
-        
+
+        SMESH::SMESH_Algo_var algo;
+        for( int dim = SMESH::DIM_1D; dim <= SMESH::DIM_3D; dim++ )
+        {
+          switch(dim) {
+          case SMESH::DIM_1D: algo = SMESH::SMESH_1D_Algo::_narrow( aVar ); break;
+          case SMESH::DIM_2D: algo = SMESH::SMESH_2D_Algo::_narrow( aVar ); break;
+          case SMESH::DIM_3D: algo = SMESH::SMESH_3D_Algo::_narrow( aVar ); break;
+          default: break;
+          }
+          if ( !algo->_is_nil() )
+          {
+            theModeMap[ dim ] = 0;
+            if ( theModeMap.size() == 3 )
+              return;
+            break;
+          }
+        }
+      }
+    }
+  }
+
+  // check sub-meshes
+  for ( aPart = SMESH::Tag_SubMeshOnEdge; aPart < SMESH::Tag_LastSubMesh; ++aPart )
+  {
+    if ( !theMesh->FindSubObject( aPart, aHypFolder ))
+      continue;
+
+    _PTR(ChildIterator) anIter =
+      SMESH::GetActiveStudyDocument()->NewChildIterator( aHypFolder );
+    for ( anIter->InitEx(true); anIter->More(); anIter->Next() )
+    {
+      _PTR(SObject) anObj = anIter->Value();
+      _PTR(SObject) aRefObj;
+      if ( anObj->ReferencedObject( aRefObj ) )
+        anObj = aRefObj;
+      else
+        continue;
+
+      if ( anObj->FindAttribute( anAttr, "AttributeName" ))
+      {
+        CORBA::Object_var aVar = _CAST(SObject,anObj)->GetObject();
+        if ( CORBA::is_nil( aVar ) )
+          continue;
+
+        SMESH::SMESH_Algo_var algo;
         for( int dim = SMESH::DIM_1D; dim <= SMESH::DIM_3D; dim++ )
         {
-          SMESH::SMESH_Algo_var algo;
           switch(dim) {
           case SMESH::DIM_1D: algo = SMESH::SMESH_1D_Algo::_narrow( aVar ); break;
           case SMESH::DIM_2D: algo = SMESH::SMESH_2D_Algo::_narrow( aVar ); break;
@@ -1761,7 +1805,12 @@ void SMESHGUI_PrecomputeOp::getAssignedAlgos(_PTR(SObject) theMesh,
           default: break;
           }
           if ( !algo->_is_nil() )
+          {
             theModeMap[ dim ] = 0;
+            if ( theModeMap.size() == 3 )
+              return;
+            break;
+          }
         }
       }
     }
@@ -1781,6 +1830,7 @@ void SMESHGUI_PrecomputeOp::onCompute()
     myOrderMgr->SetMeshOrder();
   myMapShapeId.clear();
   myActiveDlg = computeDlg();
+  myHelpFileName = "constructing_meshes_page.html#compute_anchor";
   computeMesh();
 }
 
@@ -1811,7 +1861,7 @@ void SMESHGUI_PrecomputeOp::onCancel()
       // remove all submeshes for collected shapes
       QMap<int,int>::const_iterator it = myMapShapeId.constBegin();
       for ( ; it != myMapShapeId.constEnd(); ++it )
-        myMesh->ClearSubMesh( *it );
+        myMesh->ClearSubMesh( it.key() );
       isRestoreOrder = true;
     }
   }
@@ -1853,19 +1903,19 @@ void SMESHGUI_PrecomputeOp::onPreview()
   if (myOrderMgr && myOrderMgr->IsOrderChanged())
     myOrderMgr->SetMeshOrder();
 
-  // Compute preview of mesh, 
+  // Compute preview of mesh,
   // i.e. compute mesh till indicated dimension
   int dim = myDlg->getPreviewMode();
-  
+
   SMESH::MemoryReserve aMemoryReserve;
-  
+
   SMESH::compute_error_array_var aCompErrors;
   QString                        aHypErrors;
 
   bool computeFailed = true, memoryLack = false;
 
   SMESHGUI_ComputeDlg* aCompDlg = computeDlg();
-    aCompDlg->myMeshName->setText( aMeshSObj->GetName().c_str() );
+  aCompDlg->myMeshName->setText( aMeshSObj->GetName().c_str() );
 
   SMESHGUI* gui = getSMESHGUI();
   SMESH::SMESH_Gen_var gen = gui->GetSMESHGen();
@@ -1965,6 +2015,7 @@ SMESHGUI_PrecomputeDlg::SMESHGUI_PrecomputeDlg( QWidget* parent )
 
   setButtonText( OK, tr( "COMPUTE" ) );
   QFrame* main = mainFrame();
+  main->setMinimumWidth( 300 );
 
   QVBoxLayout* layout = new QVBoxLayout( main );
 
@@ -2048,6 +2099,7 @@ SMESHGUI_MeshOrderBox* SMESHGUI_PrecomputeDlg::getMeshOrderBox() const
 SMESHGUI_EvaluateOp::SMESHGUI_EvaluateOp()
  : SMESHGUI_BaseComputeOp()
 {
+  myHelpFileName = "constructing_meshes_page.html#evaluate_anchor";
 }
 
 
index bc2629a213f422f3f7fff848781a23dac5d11c7c..cc60fc47115f115e3ee26bedcf2be90059df158f 100644 (file)
@@ -346,6 +346,7 @@ SMESHGUI_ConvToQuadOp::DestinationMesh( const SMESH::SMESH_IDSource_var& idSourc
                    nbElemOfType[SMDSEntity_Quad_Tetra     ] ||
                    nbElemOfType[SMDSEntity_Quad_Hexa      ] ||
                    nbElemOfType[SMDSEntity_Quad_Pyramid   ] ||
+                   nbElemOfType[SMDSEntity_Quad_Polygon   ] ||
                    nbElemOfType[SMDSEntity_Quad_Penta     ] );
 
   bool hasLin  = ( nbElemOfType[SMDSEntity_Edge      ] ||
@@ -354,6 +355,7 @@ SMESHGUI_ConvToQuadOp::DestinationMesh( const SMESH::SMESH_IDSource_var& idSourc
                    nbElemOfType[SMDSEntity_Tetra     ] ||
                    nbElemOfType[SMDSEntity_Hexa      ] ||
                    nbElemOfType[SMDSEntity_Pyramid   ] ||
+                   nbElemOfType[SMDSEntity_Polygon   ] ||
                    nbElemOfType[SMDSEntity_Penta     ] );
 
   int tgtType = 0;
index 1c8d4dbdc73d3b0803009ea0e62ed67a7da0b8b1..5da5ff109b67ac350b4e13a7969f07c005de999e 100644 (file)
@@ -234,6 +234,10 @@ SMESHGUI_CopyMeshDlg::SMESHGUI_CopyMeshDlg( SMESHGUI* theModule )
           this,           SLOT   (SelectionIntoArgument()));
   connect(mySMESHGUI,     SIGNAL (SignalCloseAllDialogs()),/* to close dialog if study change */
           this,           SLOT   (reject()));
+  connect(mySMESHGUI,     SIGNAL (SignalActivatedViewManager()),
+          this,           SLOT   (onOpenView()));
+  connect(mySMESHGUI,     SIGNAL (SignalCloseView()),
+          this,           SLOT   (onCloseView()));
 
   connect(myLineEditElements, SIGNAL(textChanged(const QString&)),
           this,               SLOT  (onTextChange(const QString&)));
@@ -381,6 +385,31 @@ void SMESHGUI_CopyMeshDlg::reject()
   QDialog::reject();
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_CopyMeshDlg::onOpenView()
+{
+  if ( mySelector ) {
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    ActivateThisDialog();
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_CopyMeshDlg::onCloseView()
+{
+  DeactivateActiveDialog();
+  mySelector = 0;
+}
+
 //=================================================================================
 // function : ClickOnHelp()
 // purpose  :
@@ -602,16 +631,21 @@ void SMESHGUI_CopyMeshDlg::ActivateThisDialog()
   SelectionIntoArgument();
 }
 
+
 //=================================================================================
 // function : enterEvent()
 // purpose  :
 //=================================================================================
 void SMESHGUI_CopyMeshDlg::enterEvent (QEvent*)
 {
-  if (!ConstructorsBox->isEnabled())
+  if ( !ConstructorsBox->isEnabled() ) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector ) {
+      mySelector = aViewWindow->GetSelector();
+    }
     ActivateThisDialog();
+  }
 }
-
 //=================================================================================
 // function : keyPressEvent()
 // purpose  :
index 730d5e637d8db49f296c6f27ddf52db93b8916d5..54347e18ad4e8f8caf1af04946c4c4846f0ddfaf 100644 (file)
@@ -125,6 +125,8 @@ private slots:
   void                   onTextChange( const QString& );
   void                   onSelectIdSource( bool );
   void                   setFilters();
+  void                   onOpenView();
+  void                   onCloseView();
 };
 
 #endif // SMESHGUI_CopyMeshDLG_H
index a39a62ed01c10296ea14e30c0d3be66d2ab3d71b..47c2f8eecbd27236c838df8a9d1da1b3c0f61d13 100755 (executable)
@@ -105,9 +105,6 @@ SMESHGUI_CreatePatternDlg::SMESHGUI_CreatePatternDlg( SMESHGUI*   theModule,
 
   aDlgLay->setStretchFactor( aMainFrame, 1 );
 
-  if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ) )
-    mySelector = aViewWindow->GetSelector();
-
   myHelpFileName = "pattern_mapping_page.html";
 
   Init( theType );
@@ -572,7 +569,7 @@ void SMESHGUI_CreatePatternDlg::onSelectionDone()
 {
   try {
     SALOME_ListIO aList;
-    mySelectionMgr->selectedObjects( aList, SVTK_Viewer::Type() );
+    mySelectionMgr->selectedObjects( aList );
     if ( aList.Extent() != 1 )
       return;
 
index 18cec4286ca7a0952e581d944306b29f6cfebb3d..840f09cfb062bdcca875a27733d02050aa7d1930 100755 (executable)
@@ -115,7 +115,6 @@ private:
   QCheckBox*               myProjectChk;
 
   SMESHGUI*                mySMESHGUI;
-  SVTK_Selector*           mySelector;
   LightApp_SelectionMgr*   mySelectionMgr;
   int                      myType;
 
index f4050368807cdd51a4f4dd4afdcb6194672f3b6a..bdbb2d95da478b1c3b6f1a179cdec60f7013fe8e 100644 (file)
@@ -353,8 +353,9 @@ void SMESHGUI_CreatePolyhedralVolumeDlg::Init()
   connect( mySelectionMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( SelectionIntoArgument() ) );
   connect( Preview, SIGNAL(toggled(bool)), this, SLOT(ClickOnPreview(bool)));
   /* to close dialog if study change */
-  connect( mySMESHGUI, SIGNAL ( SignalCloseAllDialogs() ), this, SLOT( reject() ) );
-  
+  connect( mySMESHGUI, SIGNAL ( SignalCloseAllDialogs() ),      this, SLOT( reject() ) );
+  connect( mySMESHGUI, SIGNAL ( SignalActivatedViewManager() ), this, SLOT( onOpenView() ) );
+  connect( mySMESHGUI, SIGNAL ( SignalCloseView() ),            this, SLOT( onCloseView() ) );
   ConstructorsClicked(0);
   SelectionIntoArgument();
 }
@@ -613,6 +614,36 @@ void SMESHGUI_CreatePolyhedralVolumeDlg::reject()
   QDialog::reject();
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_CreatePolyhedralVolumeDlg::onOpenView()
+{
+  if ( mySelector && mySimulation ) {
+    mySimulation->SetVisibility(false);
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    mySimulation = new SMESH::TPolySimulation(
+      dynamic_cast<SalomeApp_Application*>( mySMESHGUI->application() ) );
+    ActivateThisDialog();
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_CreatePolyhedralVolumeDlg::onCloseView()
+{
+  DeactivateActiveDialog();
+  mySelector = 0;
+  delete mySimulation;
+  mySimulation = 0;
+}
+
 //=================================================================================
 // function : ClickOnHelp()
 // purpose  :
@@ -1027,16 +1058,21 @@ void SMESHGUI_CreatePolyhedralVolumeDlg::ActivateThisDialog()
   SelectionIntoArgument();
 }
 
-
 //=================================================================================
 // function : enterEvent()
 // purpose  :
 //=================================================================================
-void SMESHGUI_CreatePolyhedralVolumeDlg::enterEvent(QEvent* e)
+void SMESHGUI_CreatePolyhedralVolumeDlg::enterEvent (QEvent*)
 {
-  if ( ConstructorsBox->isEnabled() )
-    return;  
-  ActivateThisDialog();
+  if ( !ConstructorsBox->isEnabled() ) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector && !mySimulation) {
+      mySelector = aViewWindow->GetSelector();
+      mySimulation = new SMESH::TPolySimulation(
+        dynamic_cast<SalomeApp_Application*>( mySMESHGUI->application() ) );
+    }
+    ActivateThisDialog();
+  }
 }
 
 //=================================================================================
index b213344d38e0ccd5f454d195091d2ccc9a23ed65..85343ee0f2d845436f8f092b5095950a09dc1f1f 100644 (file)
@@ -138,6 +138,8 @@ private slots:
   void                     ActivateThisDialog();
   void                     onTextChange( const QString& );
   void                     onListSelectionChanged();
+  void                     onOpenView();
+  void                     onCloseView();
 };
 
 #endif // SMESHGUI_CREATEPOLYHEDRALVOLUMEDLG_H
index b042f8adde0774e5f85ad1b6abfa1f7a045fea3c..0f98bda2d4fe70dbd89d2c7f3debc1cd2401299a 100644 (file)
@@ -39,7 +39,7 @@ public:
 
 private:
   void InverseEntityMode( unsigned int& theOutputMode,
-                         unsigned int theMode );
+                          unsigned int theMode );
 
 private slots:
   void              onOk();
index 488fddd219cc9e0d4ec288845b6327cd9de18d98..2779ce68917e4d004fd4017040187263bb5373eb 100644 (file)
@@ -253,7 +253,7 @@ SMESHGUI_ExtrusionAlongPathDlg::SMESHGUI_ExtrusionAlongPathDlg( SMESHGUI* theMod
   OkButton->setAutoDefault(true);
   OkButton->setDefault(true);
 
-  ApplyButton = new QPushButton(tr("SMESH_BUT_APPLY"), GroupButtons);
+  ApplyButton = new QPushButton(tr("SMESH_BUT_APPLY"), GroupButtons); 
   ApplyButton->setAutoDefault(true);
 
   CloseButton = new QPushButton(tr("SMESH_BUT_CLOSE"), GroupButtons);
@@ -309,6 +309,8 @@ SMESHGUI_ExtrusionAlongPathDlg::SMESHGUI_ExtrusionAlongPathDlg( SMESHGUI* theMod
   connect(BasePointGrp,       SIGNAL(toggled(bool)), this, SLOT(SetEditCurrentArgument()));
 
   connect(mySMESHGUI,  SIGNAL(SignalCloseAllDialogs()),        SLOT(reject()));
+  connect(mySMESHGUI,  SIGNAL(SignalActivatedViewManager()),   SLOT(onOpenView()));
+  connect(mySMESHGUI,  SIGNAL(SignalCloseView()),              SLOT(onCloseView()));
   connect(mySMESHGUI,  SIGNAL(SignalDeactivateActiveDialog()), SLOT(DeactivateActiveDialog()));
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()),   SLOT(SelectionIntoArgument()));
   connect(SelectorWdg,    SIGNAL(selectionChanged()), this,    SLOT(toDisplaySimulation()));
@@ -442,64 +444,64 @@ bool SMESHGUI_ExtrusionAlongPathDlg::ClickOnApply()
 
     mesh->SetParameters( aParameters.join(":").toLatin1().constData() );
 
-      SMESH::ListOfIDSources_var nodes = new SMESH::ListOfIDSources();
-      SMESH::ListOfIDSources_var edges = new SMESH::ListOfIDSources();
-      SMESH::ListOfIDSources_var faces = new SMESH::ListOfIDSources();
-      maxSelType = SelectorWdg->GetSelected( nodes, edges, faces );
-
-      // is it necessary to switch on the next Display Mode?
-      SMESH::ElementType newType = (SMESH::ElementType)( maxSelType + 1 );
-      SMESH::array_of_ElementType_var oldTypes = mesh->GetTypes();
-      meshHadNewTypeBefore = false;
-      for ( size_t i = 0; i < oldTypes->length() && !meshHadNewTypeBefore; ++i )
-        meshHadNewTypeBefore = ( oldTypes[i] >= newType );
-
-      SMESH::SMESH_MeshEditor_var aMeshEditor = mesh->GetMeshEditor();
-      SMESH::SMESH_MeshEditor::Extrusion_Error retVal;
-
-      SMESH::ListOfGroups_var groups =
-        aMeshEditor->ExtrusionAlongPathObjects( nodes, edges, faces, myPath,
-                                                GEOM::GEOM_Object::_nil(),
-                                                aNodeStart, AnglesGrp->isChecked(),
-                                                anAngles, LinearAnglesCheck->isChecked(),
-                                                BasePointGrp->isChecked(), aBasePoint,
-                                                makeGroups, retVal );
-
-      wc.suspend();
-      switch (retVal) {
-      case SMESH::SMESH_MeshEditor::EXTR_NO_ELEMENTS:
-        SUIT_MessageBox::warning(this,
-                                 tr("SMESH_ERROR"),
-                                 tr("NO_ELEMENTS_SELECTED"));
-        return false; break;
-      case SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE:
-        SUIT_MessageBox::warning(this,
-                                 tr("SMESH_ERROR"),
-                                 tr("SELECTED_PATH_IS_NOT_EDGE"));
-        return false; break;
-      case SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE:
-        SUIT_MessageBox::warning(this,
-                                 tr("SMESH_ERROR"),
-                                 tr("BAD_SHAPE_TYPE"));
-        return false; break;
-      case SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE:
-        SUIT_MessageBox::warning(this,
-                                 tr("SMESH_ERROR"),
-                                 tr("EXTR_BAD_STARTING_NODE"));
-        return false; break;
-      case SMESH::SMESH_MeshEditor::EXTR_BAD_ANGLES_NUMBER:
-        SUIT_MessageBox::warning(this,
-                                 tr("SMESH_ERROR"),
-                                 tr("WRONG_ANGLES_NUMBER"));
-        return false; break;
-      case SMESH::SMESH_MeshEditor::EXTR_CANT_GET_TANGENT:
-        SUIT_MessageBox::warning(this,
-                                 tr("SMESH_ERROR"),
-                                 tr("CANT_GET_TANGENT"));
-        return false; break;
-      case SMESH::SMESH_MeshEditor::EXTR_OK:
-        break;
-      }
+    SMESH::ListOfIDSources_var nodes = new SMESH::ListOfIDSources();
+    SMESH::ListOfIDSources_var edges = new SMESH::ListOfIDSources();
+    SMESH::ListOfIDSources_var faces = new SMESH::ListOfIDSources();
+    maxSelType = SelectorWdg->GetSelected( nodes, edges, faces );
+
+    // is it necessary to switch on the next Display Mode?
+    SMESH::ElementType newType = (SMESH::ElementType)( maxSelType + 1 );
+    SMESH::array_of_ElementType_var oldTypes = mesh->GetTypes();
+    meshHadNewTypeBefore = false;
+    for ( size_t i = 0; i < oldTypes->length() && !meshHadNewTypeBefore; ++i )
+      meshHadNewTypeBefore = ( oldTypes[i] >= newType );
+
+    SMESH::SMESH_MeshEditor_var aMeshEditor = mesh->GetMeshEditor();
+    SMESH::SMESH_MeshEditor::Extrusion_Error retVal;
+
+    SMESH::ListOfGroups_var groups =
+      aMeshEditor->ExtrusionAlongPathObjects( nodes, edges, faces, myPath,
+                                              GEOM::GEOM_Object::_nil(),
+                                              aNodeStart, AnglesGrp->isChecked(),
+                                              anAngles, LinearAnglesCheck->isChecked(),
+                                              BasePointGrp->isChecked(), aBasePoint,
+                                              makeGroups, retVal );
+
+    wc.suspend();
+    switch (retVal) {
+    case SMESH::SMESH_MeshEditor::EXTR_NO_ELEMENTS:
+      SUIT_MessageBox::warning(this,
+                               tr("SMESH_ERROR"),
+                               tr("NO_ELEMENTS_SELECTED"));
+      return false; break;
+    case SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE:
+      SUIT_MessageBox::warning(this,
+                               tr("SMESH_ERROR"),
+                               tr("SELECTED_PATH_IS_NOT_EDGE"));
+      return false; break;
+    case SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE:
+      SUIT_MessageBox::warning(this,
+                               tr("SMESH_ERROR"),
+                               tr("BAD_SHAPE_TYPE"));
+      return false; break;
+    case SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE:
+      SUIT_MessageBox::warning(this,
+                               tr("SMESH_ERROR"),
+                               tr("EXTR_BAD_STARTING_NODE"));
+      return false; break;
+    case SMESH::SMESH_MeshEditor::EXTR_BAD_ANGLES_NUMBER:
+      SUIT_MessageBox::warning(this,
+                               tr("SMESH_ERROR"),
+                               tr("WRONG_ANGLES_NUMBER"));
+      return false; break;
+    case SMESH::SMESH_MeshEditor::EXTR_CANT_GET_TANGENT:
+      SUIT_MessageBox::warning(this,
+                               tr("SMESH_ERROR"),
+                               tr("CANT_GET_TANGENT"));
+      return false; break;
+    case SMESH::SMESH_MeshEditor::EXTR_OK:
+      break;
+    }
   } catch (...) {
     return false;
   }
@@ -587,6 +589,31 @@ void SMESHGUI_ExtrusionAlongPathDlg::reject()
   QDialog::reject();
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_ExtrusionAlongPathDlg::onOpenView()
+{
+  if ( mySelector ) {
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    ActivateThisDialog();
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_ExtrusionAlongPathDlg::onCloseView()
+{
+  DeactivateActiveDialog();
+  mySelector = 0;
+}
+
 //=======================================================================
 // function : onTextChange()
 // purpose  :
@@ -799,7 +826,7 @@ void SMESHGUI_ExtrusionAlongPathDlg::SetEditCurrentArgument (QPushButton* button
     if (!myPath->_is_nil()) {
       SMESH_Actor* aPathActor = SMESH::FindActorByObject(myPath);
       if (aPathActor) {
-        SMESH::SetPointRepresentation(true);
+        aPathActor->SetPointRepresentation( true );
         if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
           aViewWindow->SetSelectionMode(NodeSelection);
         SMESH::SetPickable(aPathActor);
@@ -865,12 +892,17 @@ void SMESHGUI_ExtrusionAlongPathDlg::ActivateThisDialog()
 
 //=================================================================================
 // function : enterEvent()
-// purpose  : Mouse enter event
+// purpose  :
 //=================================================================================
 void SMESHGUI_ExtrusionAlongPathDlg::enterEvent (QEvent*)
 {
-  if (!GroupButtons->isEnabled())
+  if ( !GroupButtons->isEnabled() ) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector) {
+      mySelector = aViewWindow->GetSelector();
+    }
     ActivateThisDialog();
+  }
 }
 
 //=======================================================================
@@ -1016,11 +1048,19 @@ bool SMESHGUI_ExtrusionAlongPathDlg::isValuesValid()
   if ( type != SMESH::NODE )
     return false;
 
-  SMESH::long_array_var elems = mesh->GetNodeInverseElements( aNodeStart );
-  if ( elems->length() != 1 ||
-       mesh->GetElementType( elems[0], true ) != SMESH::EDGE )
-    return false;
-
+  if ( mesh->HasShapeToMesh() )
+  {
+    SMESH::NodePosition_var pos = mesh->GetNodePosition( aNodeStart );
+    if ( pos->shapeType != GEOM::VERTEX )
+      return false;
+  }
+  else
+  {
+    SMESH::long_array_var elems = mesh->GetNodeInverseElements( aNodeStart );
+    if ( elems->length() != 1 ||
+         mesh->GetElementType( elems[0], true ) != SMESH::EDGE )
+      return false;
+  }
   return true;
 }
 
index 199c8752eb67e3e02fc3688d72cf4771eb8ce5dd..0a5f150e2c3609fd9b7096c51c1c3074075a5e6f 100644 (file)
@@ -140,6 +140,8 @@ private slots:
   void                      onTextChange( const QString& );
   void                      OnAngleAdded();
   void                      OnAngleRemoved();
+  void                      onOpenView();
+  void                      onCloseView();
 };
 
 #endif // SMESHGUI_EXTRUSIONALONGPATHDLG_H
index 0a7901267b630e6cb8e1900e3a7fbda257f10be7..5a62c1de60021b8662d8efd89a7445c0e9f5a4eb 100644 (file)
@@ -777,7 +777,9 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule)
   connect(SelectorWdg,          SIGNAL(selectionChanged()), this, SLOT(toDisplaySimulation()));
   connect(SelectorWdg,          SIGNAL(selectionChanged()), this, SLOT(CheckIsEnable()));
   /* to close dialog if study change */
-  connect(mySMESHGUI,           SIGNAL(SignalCloseAllDialogs()),   this, SLOT(reject()));
+  connect(mySMESHGUI,           SIGNAL(SignalCloseAllDialogs()),      this, SLOT(reject()));
+  connect(mySMESHGUI,           SIGNAL(SignalActivatedViewManager()), this, SLOT(onOpenView()));
+  connect(mySMESHGUI,           SIGNAL(SignalCloseView()),            this, SLOT(onCloseView()));
 
   connect(SpinBox_Dx,      SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
   connect(SpinBox_Dy,      SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
@@ -1119,6 +1121,31 @@ void SMESHGUI_ExtrusionDlg::reject()
   QDialog::reject();
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_ExtrusionDlg::onOpenView()
+{
+  if ( mySelector ) {
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    ActivateThisDialog();
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_ExtrusionDlg::onCloseView()
+{
+  DeactivateActiveDialog();
+  mySelector = 0;
+}
+
 //=================================================================================
 // function : ClickOnHelp()
 // purpose  :
@@ -1240,12 +1267,17 @@ void SMESHGUI_ExtrusionDlg::ActivateThisDialog()
 
 //=================================================================================
 // function : enterEvent()
-// purpose  : Mouse enter event
+// purpose  :
 //=================================================================================
 void SMESHGUI_ExtrusionDlg::enterEvent (QEvent*)
 {
-  if (!GroupButtons->isEnabled())
+  if ( !GroupButtons->isEnabled() ) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector) {
+      mySelector = aViewWindow->GetSelector();
+    }
     ActivateThisDialog();
+  }
 }
 
 //=================================================================================
index 80eaeacfa258f37d374621094b95706a89f54c14..64173209f852b3ce76e2734ce5c4b5afa220ec3f 100644 (file)
@@ -203,6 +203,9 @@ private slots:
   void                            SelectionIntoArgument();
   void                            DeactivateActiveDialog();
   void                            ActivateThisDialog();
+  void                            onOpenView();
+  void                            onCloseView();
+
 };
 
 #endif // SMESHGUI_EXTRUSIONDLG_H
index 4e39b5da5d9a2acd1f9e31e84768304598a6248e..97f1df847d47671462c6830e5880de2cc680197a 100755 (executable)
@@ -1012,6 +1012,7 @@ void SMESHGUI_FilterTable::Init (const QList<int>& theTypes)
         Table* aTable = createTable(mySwitchTableGrp, *typeIt);
         myTables[ *typeIt ] = aTable;
         ((QVBoxLayout*)mySwitchTableGrp->layout())->addWidget(myTables[ *typeIt ]);
+        myEntityType = -1;
       }
     }
   }
@@ -1740,7 +1741,7 @@ static QList<int> entityTypes( const int theType )
     typeIds.append( SMDSEntity_Quad_Quadrangle );
     typeIds.append( SMDSEntity_BiQuad_Quadrangle );
     typeIds.append( SMDSEntity_Polygon );
-    //typeIds.append( SMDSEntity_Quad_Polygon );
+    typeIds.append( SMDSEntity_Quad_Polygon );
     break;
   case SMESH::VOLUME:
     typeIds.append( SMDSEntity_Tetra );
@@ -2891,6 +2892,11 @@ void SMESHGUI_FilterDlg::Init (const int type, const bool setInViewer)
 //=======================================================================
 void SMESHGUI_FilterDlg::Init (const QList<int>& theTypes, const bool setInViewer)
 {
+  if ( theTypes.empty() )
+  {
+    Init( SMESH::ALL, setInViewer );
+    return;
+  }
   mySourceWg  = 0;
   myTypes     = theTypes;
   myMesh      = SMESH::SMESH_Mesh::_nil();
@@ -2925,6 +2931,8 @@ void SMESHGUI_FilterDlg::Init (const QList<int>& theTypes, const bool setInViewe
 
   connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), SLOT(onDeactivate()));
   connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()), SLOT(reject()));
+  connect(mySMESHGUI, SIGNAL(SignalActivatedViewManager()), SLOT(onOpenView()));
+  connect(mySMESHGUI, SIGNAL(SignalCloseView()), SLOT(onCloseView()));
   
   updateMainButtons();
   updateSelection();
@@ -3010,6 +3018,29 @@ void SMESHGUI_FilterDlg::reject()
   QDialog::reject();
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_FilterDlg::onOpenView()
+{
+  if ( mySelector ) {
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_FilterDlg::onCloseView()
+{
+  mySelector = 0;
+}
+
 //=================================================================================
 // function : onHelp()
 // purpose  :
@@ -3333,7 +3364,7 @@ bool SMESHGUI_FilterDlg::onApply()
     insertFilterInViewer();
 
     if (!myFilter[ aCurrType ]->GetPredicate()->_is_nil()) {
-      // 
+      //
       bool toFilter = (( SMESH::FindActorByObject( myMesh )) ||
                        ( myInitSourceWgOnApply && mySourceWg ) ||
                        ( mySourceGrp->checkedId() == Dialog && mySourceWg ));
@@ -3342,6 +3373,9 @@ bool SMESHGUI_FilterDlg::onApply()
         filterSource(aCurrType, aResultIds);
         // select in viewer
         selectInViewer(aCurrType, aResultIds);
+        // set ids to the dialog
+        if ( myInitSourceWgOnApply || mySourceGrp->checkedId() == Dialog )
+          setIdsToWg(mySourceWg, aResultIds);
       }
     }
 
@@ -3517,9 +3551,6 @@ void SMESHGUI_FilterDlg::filterSource (const int theType,
       if (aPred->IsSatisfy(*anIter))
         theResIds.append(*anIter);
   }
-  // set ids to the dialog
-  if (myInitSourceWgOnApply || aSourceId == Dialog)
-    setIdsToWg(mySourceWg, theResIds);
 }
 
 //=======================================================================
index 55d854c17162dc532f8a2c16d9d09d2ce4c79b9b..50dabdaa192be632bd58c655239e0adbbeb86827 100755 (executable)
@@ -255,6 +255,8 @@ private slots:
   void                      onCriterionChanged( const int, const int );
   void                      onThresholdChanged( const int, const int );
   void                      onCurrentChanged( int, int );
+  void                      onOpenView();
+  void                      onCloseView();
 
 private:
 
index c5a4e447ab3aabe3dfd9c20329e818fd992f5525..fc4304500cff44a28641f5505dc693f87b504b31 100644 (file)
@@ -238,6 +238,7 @@ SMESHGUI_FindElemByPointOp::SMESHGUI_FindElemByPointOp()
   :SMESHGUI_SelectionOp()
 {
   mySimulation = 0;
+  mySMESHGUI = 0;
   myDlg = new SMESHGUI_FindElemByPointDlg;
   myHelpFileName = "find_element_by_point_page.html";
 
@@ -279,7 +280,10 @@ void SMESHGUI_FindElemByPointOp::startOperation()
 {
   // init simulation with a current View
   if ( mySimulation ) delete mySimulation;
-  mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( getSMESHGUI() ));
+  mySMESHGUI = getSMESHGUI();
+  mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ) );
+  connect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView()));
+  connect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView()));
   vtkProperty* aProp = vtkProperty::New();
   aProp->SetRepresentationToWireframe();
   aProp->SetColor(250, 0, 250);
@@ -309,10 +313,37 @@ void SMESHGUI_FindElemByPointOp::stopOperation()
     delete mySimulation;
     mySimulation = 0;
   }
+  disconnect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView()));
+  disconnect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView()));
   selectionMgr()->removeFilter( myFilter );
   SMESHGUI_SelectionOp::stopOperation();
 }
 
+//=================================================================================
+/*!
+ * \brief SLOT called when the viewer opened
+ */
+//=================================================================================
+void SMESHGUI_FindElemByPointOp::onOpenView()
+{
+  if ( mySimulation ) {
+    mySimulation->SetVisibility(false);
+  }
+  else {
+    mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ));
+  }
+}
+
+//=================================================================================
+/*!
+ * \brief SLOT called when the viewer closed
+ */
+//=================================================================================
+void SMESHGUI_FindElemByPointOp::onCloseView()
+{
+  delete mySimulation;
+  mySimulation = 0;
+}
 //================================================================================
 /*!
  * \brief hilight found selected elements
@@ -503,7 +534,8 @@ void SMESHGUI_FindElemByPointOp::redisplayPreview()
   myPreview->nodesXYZ[0].x = myDlg->myX->GetValue();
   myPreview->nodesXYZ[0].y = myDlg->myY->GetValue();
   myPreview->nodesXYZ[0].z = myDlg->myZ->GetValue();
-
+  if (!mySimulation)
+    mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ));
   mySimulation->SetData(&myPreview.in());
 }
 
index 7ec86a2ea3ac382045ca643b4111fc75d4a85191..a3418e8ec5d0b5b0dcda3d238b9d501d5f022986 100644 (file)
@@ -68,11 +68,14 @@ private slots:
   void                           onElemSelected();
   void                           onElemTypeChange(int);
   void                           redisplayPreview();
+  void                           onOpenView();
+  void                           onCloseView();
 
 private:
   SMESHGUI_FindElemByPointDlg*     myDlg;
 
   SUIT_SelectionFilter*            myFilter;
+  SMESHGUI*                        mySMESHGUI;
   SMESHGUI_MeshEditPreview*        mySimulation; // to show point coordinates
   SMESH::SMESH_IDSource_var        myMeshOrPart;
   SMESH::MeshPreviewStruct_var     myPreview;
index c0dcd49d338459546727b1266f03784931eac334..7b1ad6ec92a35cdd376a4c38424dd473b9f45d21 100644 (file)
@@ -462,7 +462,8 @@ void SMESHGUI_GroupDlg::initDialog( bool create)
   connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()),        this, SLOT(reject()));
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()),  this, SLOT(onObjectSelectionChanged()));
   connect(mySMESHGUI, SIGNAL(SignalVisibilityChanged()),      this, SLOT(onVisibilityChanged()));
-
+  connect(mySMESHGUI, SIGNAL(SignalActivatedViewManager()),   this, SLOT(onOpenView()));
+  connect(mySMESHGUI, SIGNAL(SignalCloseView()),              this, SLOT(onCloseView()));
   rb1->setChecked(true); // VSR !!!
   onGrpTypeChanged(0); // VSR!!!
 
@@ -1826,6 +1827,8 @@ void SMESHGUI_GroupDlg::onAdd()
 
   if (aNbSel == 0 || myActorsList.count() == 0 || myMesh->_is_nil()) return;
 
+  SUIT_OverrideCursor wc;
+
   myIsBusy = true;
   int sizeBefore = myElements->count();
 
@@ -2248,6 +2251,32 @@ void SMESHGUI_GroupDlg::reject()
   if ( myFilterDlg ) myFilterDlg->UnRegisterFilters();
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_GroupDlg::onOpenView()
+{
+  if ( mySelector ) {
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    mySMESHGUI->EmitSignalDeactivateDialog();
+    setEnabled(true);
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_GroupDlg::onCloseView()
+{
+  onDeactivate();
+  mySelector = 0;
+}
+
 //=================================================================================
 // function : onHelp()
 // purpose  :
@@ -2289,6 +2318,10 @@ void SMESHGUI_GroupDlg::onDeactivate()
 void SMESHGUI_GroupDlg::enterEvent (QEvent*)
 {
   if (!isEnabled()) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector) {
+      mySelector = aViewWindow->GetSelector();
+    }
     mySMESHGUI->EmitSignalDeactivateDialog();
     setEnabled(true);
     mySelectionMode = grpNoSelection;
@@ -2540,7 +2573,7 @@ void SMESHGUI_GroupDlg::setDefaultGroupColor()
 // function : SetAppropriateActor()
 // purpose  : Find more appropriate of visible actors, set it to myActor, allow picking
 //            NPAL19389: create a group with a selection in another group.
-//            if mesh actor is not visible - find any first visible group or submesh
+//            if mesh actor is not visible - find any first visible group or sub-mesh
 //=================================================================================
 bool SMESHGUI_GroupDlg::SetAppropriateActor()
 {
@@ -2551,21 +2584,23 @@ bool SMESHGUI_GroupDlg::SetAppropriateActor()
 
   SVTK_ViewWindow* aViewWindow = SMESH::GetCurrentVtkView();
 
-  if (myGeomGroupBtn->isChecked()) {   // try current group on geometry actor
-    if (!isActor) {
-      if (!myGroupOnGeom->_is_nil()) {
-        SMESH_Actor* anActor = SMESH::FindActorByObject(myGroupOnGeom);
-        if (anActor && anActor->hasIO())
-          {
-            isActor = true;
-            if (aViewWindow && !aViewWindow->isVisible(anActor->getIO()))
-              isActor = false;
-            else
-              myActorsList.append(anActor);
-          }
-      }
+  if (myGrpTypeGroup->checkedId() > 0) {   // try current group on geometry actor
+    SMESH_Actor* anActor = 0;
+    if (!myGroupOnGeom->_is_nil())
+      anActor = SMESH::FindActorByObject(myGroupOnGeom);
+    if (!myGroupOnFilter->_is_nil())
+      anActor = SMESH::FindActorByObject(myGroupOnFilter);
+    if (anActor && anActor->hasIO())
+    {
+      isActor = true;
+      if (aViewWindow && !aViewWindow->isVisible(anActor->getIO()))
+        isActor = false;
+      else
+        myActorsList.append(anActor);
     }
-  } else {
+    return anActor;
+  }
+  else {
     // try mesh actor
     SMESH_Actor* anActor = SMESH::FindActorByObject(myMesh);
     if (anActor && anActor->hasIO()) {
@@ -2575,42 +2610,50 @@ bool SMESHGUI_GroupDlg::SetAppropriateActor()
       else
         myActorsList.append(anActor);
     }
-    
+
     // try group actor
+    SMESH_Actor* aGroupActor = 0;
     if (!isActor && !myGroup->_is_nil()) {
-      SMESH_Actor* anActor = SMESH::FindActorByObject(myGroup);
-      if (anActor && anActor->hasIO())
-        myActorsList.append(anActor);
+      aGroupActor = SMESH::FindActorByObject(myGroup);
+      if (aGroupActor && aGroupActor->hasIO())
+        myActorsList.append(aGroupActor);
     }
-    
-    // try any visible actor of group or submesh of current mesh
+
+    // try any visible actor of group or sub-mesh of current mesh
     if (aViewWindow) {
       // mesh entry
       _PTR(SObject) aSObject = SMESH::FindSObject(myMesh);
       if (aSObject) {
         CORBA::String_var meshEntry = aSObject->GetID().c_str();
         int len = strlen(meshEntry);
-        
+
         // iterate on all actors in current view window, search for
         // any visible actor, that belongs to group or submesh of current mesh
         VTK::ActorCollectionCopy aCopy(aViewWindow->getRenderer()->GetActors());
         vtkActorCollection *aCollection = aCopy.GetActors();
         int nbItems = aCollection->GetNumberOfItems();
         for (int i=0; i<nbItems && !isActor; i++)
-          {
-            SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(aCollection->GetItemAsObject(i));
-            if (anActor && anActor->hasIO()) {
-              Handle(SALOME_InteractiveObject) anIO = anActor->getIO();
-              if (aViewWindow->isVisible(anIO)) {
-                if (anIO->hasEntry() && strncmp(anIO->getEntry(), meshEntry, len) == 0 && !myActorsList.contains(anActor) )
-                  myActorsList.append(anActor);
-              }
+        {
+          SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(aCollection->GetItemAsObject(i));
+          if (anActor && anActor->hasIO()) {
+            Handle(SALOME_InteractiveObject) anIO = anActor->getIO();
+            if (aViewWindow->isVisible(anIO)) {
+              if (anIO->hasEntry() && strncmp(anIO->getEntry(), meshEntry, len) == 0 && !myActorsList.contains(anActor) )
+                myActorsList.append(anActor);
             }
           }
+        }
       }
     }
+
+    // Show a standalone group if nothing else is visible (IPAL52227)
+    if ( myActorsList.count() == 1 &&
+         myActorsList[0] == aGroupActor &&
+         aViewWindow && !aViewWindow->isVisible(aGroupActor->getIO()))
+      SMESH::UpdateView( aViewWindow, SMESH::eDisplay, aGroupActor->getIO()->getEntry() );
   }
-  
+
+
   if (myActorsList.count() > 0) {
     QListIterator<SMESH_Actor*> it( myActorsList );
     while ( it.hasNext() ) {
@@ -2619,10 +2662,10 @@ bool SMESHGUI_GroupDlg::SetAppropriateActor()
         anActor->SetPickable(true);
     }
   }
-  
+
   return ( isActor || (myActorsList.count() > 0) );
 }
-  
+
 //=======================================================================
 //function : setShowEntityMode
 //purpose  : make shown only entity corresponding to my type
index 6e9aa992c9d611c804223ee60ab7dc8b86637da1..8819d24f0be6b22ac4aa4b4b6b5c5858e4c2f1fb 100644 (file)
@@ -120,6 +120,9 @@ private slots:
   void                          onPublishShapeByMeshDlg( SUIT_Operation* );
   void                          onCloseShapeByMeshDlg( SUIT_Operation* );
 
+  void                          onOpenView();
+  void                          onCloseView();
+
 private:
   void                          initDialog( bool );
   void                          init( SMESH::SMESH_Mesh_ptr );
index bfcf3189502170562df58bd22adcedb98fdf9983..69077f967f5ef8ec291f55ad8706943d2ef6b401 100644 (file)
@@ -225,6 +225,8 @@ void SMESHGUI_GroupOpDlg::Init()
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone()));
   connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), SLOT(onDeactivate()));
   connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()), SLOT(reject()));
+  connect(mySMESHGUI, SIGNAL(SignalActivatedViewManager()), SLOT(onOpenView()));
+  connect(mySMESHGUI, SIGNAL(SignalCloseView()), SLOT(onCloseView()));
 
   // set selection mode
   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
@@ -331,6 +333,32 @@ void SMESHGUI_GroupOpDlg::reject()
   QDialog::reject();
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_GroupOpDlg::onOpenView()
+{
+  if ( mySelector ) {
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    mySMESHGUI->EmitSignalDeactivateDialog();
+    setEnabled(true);
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_GroupOpDlg::onCloseView()
+{
+  onDeactivate();
+  mySelector = 0;
+}
+
 /*!
   \brief SLOT called when "Help" button pressed shows "Help" page
 */
@@ -459,8 +487,12 @@ void SMESHGUI_GroupOpDlg::enterEvent(QEvent*)
 {
   mySMESHGUI->EmitSignalDeactivateDialog();
   setEnabled(true);
-  if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+  SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+  if ( aViewWindow ) {
     aViewWindow->SetSelectionMode(ActorSelection);
+    if (!mySelector)
+      mySelector = aViewWindow->GetSelector();
+  }
   mySelectionMgr->installFilter(new SMESH_TypeFilter (SMESH::GROUP));
 }
 
@@ -496,7 +528,7 @@ void SMESHGUI_GroupOpDlg::setName( const QString& theName )
 }
 
 /*!
-  \brief Provides reaction on \93F1\94 button pressing
+  \brief Provides reaction on �F1� button pressing
   \param e  key press event
 */
 void SMESHGUI_GroupOpDlg::keyPressEvent( QKeyEvent* e )
index 4acb86821b703b45665217594cdd4ee2d6c79500..6f6b70175f49c3402cf7cca13d1464c57057719c 100644 (file)
@@ -105,6 +105,9 @@ private slots:
 
   void                      onDeactivate();
 
+  void                      onOpenView();
+  void                      onCloseView();
+
 private:
   QWidget*                  createButtonFrame( QWidget* );
   QWidget*                  createMainFrame  ( QWidget* );
index 36b29d8453ba4d8d12e9c697d0bcb1051690ce75..06d9172e43f2560ee9c8085c573681e4811a30a2 100644 (file)
@@ -665,6 +665,7 @@ void SMESHGUI_HypothesisDlg::setCustomFrame( QFrame* f )
 
 void SMESHGUI_HypothesisDlg::accept()
 {
+  SUIT_OverrideCursor wc; // some creators temporary set params to a hyp which can be long
   QString msg;
   if ( myCreator && !myCreator->checkParams( msg ) )
   {
index c431014e7f675204479ba03f1617d65fb3924443..44997d0e617257de1b1f350a234d5e0e25ca1436 100644 (file)
@@ -158,20 +158,19 @@ public:
 protected slots:
   virtual void accept();
   virtual void reject();
-  void onHelp(); 
+  void onHelp();
 
-private:
+ private:
   SMESHGUI_GenericHypothesisCreator* myCreator;
   QLabel *myIconLabel, *myTypeLabel;
   QString myHelpFileName;
 };
 
 /*!
- * \brief Class containing information about hypothesis
-*/
-class HypothesisData
+ * \brief Information about a hypothesis
+ */
+struct HypothesisData
 {
-public:
   HypothesisData( const QString&, const QString&, const QString&,
                   const QString&, const QString&, const QString&,
                   const QString&, const QList<int>&, const bool,
diff --git a/src/SMESHGUI/SMESHGUI_IdPreview.cxx b/src/SMESHGUI/SMESHGUI_IdPreview.cxx
new file mode 100644 (file)
index 0000000..7999bee
--- /dev/null
@@ -0,0 +1,202 @@
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// 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 "SMESHGUI_IdPreview.h"
+
+#include <SALOME_Actor.h>
+#include <SMDS_Mesh.hxx>
+#include <SVTK_ViewWindow.h>
+
+#include <TColStd_MapOfInteger.hxx>
+#include <TColStd_MapIteratorOfMapOfInteger.hxx>
+
+#include <vtkActor2D.h>
+#include <vtkDataSetMapper.h>
+#include <vtkLabeledDataMapper.h>
+#include <vtkMaskPoints.h>
+#include <vtkPointData.h>
+#include <vtkProperty2D.h>
+#include <vtkRenderer.h>
+#include <vtkSelectVisiblePoints.h>
+#include <vtkTextProperty.h>
+#include <vtkUnstructuredGrid.h>
+
+// Extracted from SMESHGUI_MergeDlg.cxx
+
+SMESHGUI_IdPreview::SMESHGUI_IdPreview(SVTK_ViewWindow* theViewWindow):
+  myViewWindow(theViewWindow)
+{
+  myIdGrid = vtkUnstructuredGrid::New();
+
+  // Create and display actor
+  vtkDataSetMapper* aMapper = vtkDataSetMapper::New();
+  aMapper->SetInputData( myIdGrid );
+
+  myIdActor = SALOME_Actor::New();
+  myIdActor->SetInfinitive(true);
+  myIdActor->VisibilityOff();
+  myIdActor->PickableOff();
+
+  myIdActor->SetMapper( aMapper );
+  aMapper->Delete();
+
+  myViewWindow->AddActor(myIdActor);
+
+  //Definition of points numbering pipeline
+  myPointsNumDataSet = vtkUnstructuredGrid::New();
+
+  myPtsMaskPoints = vtkMaskPoints::New();
+  myPtsMaskPoints->SetInputData(myPointsNumDataSet);
+  myPtsMaskPoints->SetOnRatio(1);
+
+  myPtsSelectVisiblePoints = vtkSelectVisiblePoints::New();
+  myPtsSelectVisiblePoints->SetInputConnection(myPtsMaskPoints->GetOutputPort());
+  myPtsSelectVisiblePoints->SelectInvisibleOff();
+  myPtsSelectVisiblePoints->SetTolerance(0.1);
+    
+  myPtsLabeledDataMapper = vtkLabeledDataMapper::New();
+  myPtsLabeledDataMapper->SetInputConnection(myPtsSelectVisiblePoints->GetOutputPort());
+  myPtsLabeledDataMapper->SetLabelModeToLabelScalars();
+    
+  vtkTextProperty* aPtsTextProp = vtkTextProperty::New();
+  aPtsTextProp->SetFontFamilyToTimes();
+  static int aPointsFontSize = 12;
+  aPtsTextProp->SetFontSize(aPointsFontSize);
+  aPtsTextProp->SetBold(1);
+  aPtsTextProp->SetItalic(0);
+  aPtsTextProp->SetShadow(0);
+  myPtsLabeledDataMapper->SetLabelTextProperty(aPtsTextProp);
+  aPtsTextProp->Delete();
+  
+  myIsPointsLabeled = false;
+
+  myPointLabels = vtkActor2D::New();
+  myPointLabels->SetMapper(myPtsLabeledDataMapper);
+  myPointLabels->GetProperty()->SetColor(1,1,1);
+  myPointLabels->SetVisibility(myIsPointsLabeled);
+
+  AddToRender(myViewWindow->getRenderer());
+}
+
+void SMESHGUI_IdPreview::SetPointsData ( SMDS_Mesh*                   theMesh,
+                                         const TColStd_MapOfInteger & theNodesIdMap )
+{
+  vtkPoints* aPoints = vtkPoints::New();
+  aPoints->SetNumberOfPoints(theNodesIdMap.Extent());
+  myIDs.clear();
+
+  TColStd_MapIteratorOfMapOfInteger idIter( theNodesIdMap );
+  for( int i = 0; idIter.More(); idIter.Next(), i++ )
+  {
+    const SMDS_MeshNode* aNode = theMesh->FindNode(idIter.Key());
+    aPoints->SetPoint( i, aNode->X(), aNode->Y(), aNode->Z() );
+    myIDs.push_back(idIter.Key());
+  }
+
+  myIdGrid->SetPoints(aPoints);
+
+  aPoints->Delete();
+
+  myIdActor->GetMapper()->Update();
+}
+
+void SMESHGUI_IdPreview::SetElemsData( const std::vector<int> & theElemsIdMap,
+                                       const std::list<gp_XYZ> & aGrCentersXYZ )
+{
+  vtkPoints* aPoints = vtkPoints::New();
+  aPoints->SetNumberOfPoints( theElemsIdMap.size() );
+  myIDs = theElemsIdMap;
+
+  std::list<gp_XYZ>::const_iterator coordIt = aGrCentersXYZ.begin();
+  for( int i = 0; coordIt != aGrCentersXYZ.end(); coordIt++, i++ )
+    aPoints->SetPoint( i, coordIt->X(), coordIt->Y(), coordIt->Z() );
+
+  myIdGrid->SetPoints(aPoints);
+  aPoints->Delete();
+
+  myIdActor->GetMapper()->Update();
+}
+
+void SMESHGUI_IdPreview::AddToRender(vtkRenderer* theRenderer)
+{
+  myIdActor->AddToRender(theRenderer);
+
+  myPtsSelectVisiblePoints->SetRenderer(theRenderer);
+  theRenderer->AddActor2D(myPointLabels);
+}
+
+void SMESHGUI_IdPreview::RemoveFromRender(vtkRenderer* theRenderer)
+{
+  myIdActor->RemoveFromRender(theRenderer);
+
+  myPtsSelectVisiblePoints->SetRenderer(theRenderer);
+  theRenderer->RemoveActor(myPointLabels);
+}
+
+void SMESHGUI_IdPreview::SetPointsLabeled( bool theIsPointsLabeled, bool theIsActorVisible )
+{
+  myIsPointsLabeled = theIsPointsLabeled && myIdGrid->GetNumberOfPoints();
+
+  if ( myIsPointsLabeled ) {
+    myPointsNumDataSet->ShallowCopy(myIdGrid);
+    vtkDataSet *aDataSet = myPointsNumDataSet;
+    int aNbElem = myIDs.size();
+    vtkIntArray *anArray = vtkIntArray::New();
+    anArray->SetNumberOfValues( aNbElem );
+    for ( int i = 0; i < aNbElem; i++ )
+      anArray->SetValue( i, myIDs[i] );
+    aDataSet->GetPointData()->SetScalars( anArray );
+    anArray->Delete();
+    myPtsMaskPoints->SetInputData( aDataSet );
+    myPointLabels->SetVisibility( theIsActorVisible );
+  }
+  else {
+    myPointLabels->SetVisibility( false );
+  }
+}
+
+SMESHGUI_IdPreview::~SMESHGUI_IdPreview()
+{
+  RemoveFromRender(myViewWindow->getRenderer());
+
+  myIdGrid->Delete();
+
+  myViewWindow->RemoveActor(myIdActor);
+  myIdActor->Delete();
+
+  //Deleting of points numbering pipeline
+  //---------------------------------------
+  myPointsNumDataSet->Delete();
+
+  //myPtsLabeledDataMapper->RemoveAllInputs();        //vtk 5.0 porting
+  myPtsLabeledDataMapper->Delete();
+
+  //myPtsSelectVisiblePoints->UnRegisterAllOutputs(); //vtk 5.0 porting
+  myPtsSelectVisiblePoints->Delete();
+
+  //myPtsMaskPoints->UnRegisterAllOutputs();          //vtk 5.0 porting
+  myPtsMaskPoints->Delete();
+
+  myPointLabels->Delete();
+
+  //       myTimeStamp->Delete();
+}
diff --git a/src/SMESHGUI/SMESHGUI_IdPreview.h b/src/SMESHGUI/SMESHGUI_IdPreview.h
new file mode 100644 (file)
index 0000000..ac547ee
--- /dev/null
@@ -0,0 +1,79 @@
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef SMESHGUI_IdPreview_H
+#define SMESHGUI_IdPreview_H
+
+#include "SMESH_SMESHGUI.hxx"
+
+#include <list>
+#include <vector>
+
+#include <gp_XYZ.hxx>
+
+class SALOME_Actor;
+class SMDS_Mesh;
+class SVTK_ViewWindow;
+class TColStd_MapOfInteger;
+class vtkActor2D;
+class vtkLabeledDataMapper;
+class vtkMaskPoints;
+class vtkRenderer;
+class vtkSelectVisiblePoints;
+class vtkTextProperty;
+class vtkUnstructuredGrid;
+
+/*!
+ * \brief To display in the viewer IDs of selected elements or nodes
+ */
+class SMESHGUI_IdPreview
+{
+public:
+  SMESHGUI_IdPreview(SVTK_ViewWindow* theViewWindow);
+  ~SMESHGUI_IdPreview();
+
+  void SetPointsData( SMDS_Mesh* theMesh, const TColStd_MapOfInteger & theNodesIdMap );
+  void SetElemsData ( const std::vector<int> &  theElemsIdMap,
+                      const std::list<gp_XYZ> & theGrCentersXYZ );
+  void SetPointsLabeled( bool theIsPointsLabeled, bool theIsActorVisible = true );
+
+  void AddToRender     ( vtkRenderer* theRenderer );
+  void RemoveFromRender( vtkRenderer* theRenderer );
+
+protected:
+
+  SVTK_ViewWindow*        myViewWindow;
+
+  vtkUnstructuredGrid*    myIdGrid;
+  SALOME_Actor*           myIdActor;
+
+  vtkUnstructuredGrid*    myPointsNumDataSet;
+  vtkMaskPoints*          myPtsMaskPoints;
+  vtkSelectVisiblePoints* myPtsSelectVisiblePoints;
+  vtkLabeledDataMapper*   myPtsLabeledDataMapper;
+  bool                    myIsPointsLabeled;
+  vtkActor2D*             myPointLabels;
+
+  std::vector<int>        myIDs;
+};
+
+#endif
index f67581cff16c54d3c5608a9b732b70915e76070f..89034c8a6782b23aa6d4937d66ce61c8dadbc0be 100644 (file)
@@ -326,7 +326,8 @@ void SMESHGUI_MakeNodeAtPointDlg::ConstructorsClicked (int constructorId)
       myDestDX->hide();
       myDestDY->hide();
       myDestDZ->hide();
-      if (myNodeToMoveGrp->isVisible()) {myNodeToMoveGrp->hide();}
+      if (myNodeToMoveGrp->isVisible()) myNodeToMoveGrp->hide();
+      myDestBtn->setChecked( true );
       break;
     }
   }
@@ -346,6 +347,7 @@ void SMESHGUI_MakeNodeAtPointDlg::ConstructorsClicked (int constructorId)
 SMESHGUI_MakeNodeAtPointOp::SMESHGUI_MakeNodeAtPointOp()
 {
   mySimulation = 0;
+  mySMESHGUI = 0;
   myDlg = new SMESHGUI_MakeNodeAtPointDlg;
   myFilter = 0;
   myHelpFileName = "mesh_through_point_page.html";
@@ -355,14 +357,15 @@ SMESHGUI_MakeNodeAtPointOp::SMESHGUI_MakeNodeAtPointOp()
   myDestCoordChanged = true;
 
   // connect signals and slots
-  connect(myDlg->myDestinationX, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
-  connect(myDlg->myDestinationY, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
-  connect(myDlg->myDestinationZ, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
-  connect(myDlg->myDestDX, SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged()));
-  connect(myDlg->myDestDY, SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged()));
-  connect(myDlg->myDestDZ, SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged()));
-  connect(myDlg->myId,SIGNAL (textChanged(const QString&)),SLOT(redisplayPreview()));
-  connect(myDlg->myPreviewChkBox,   SIGNAL (toggled(bool)),SLOT(redisplayPreview()));
+  connect(myDlg->myDestinationX,  SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
+  connect(myDlg->myDestinationY,  SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
+  connect(myDlg->myDestinationZ,  SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
+  connect(myDlg->myDestDX,        SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged()));
+  connect(myDlg->myDestDY,        SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged()));
+  connect(myDlg->myDestDZ,        SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged()));
+  connect(myDlg->myId,            SIGNAL (textChanged(const QString&)),SLOT(redisplayPreview()));
+  connect(myDlg->myPreviewChkBox, SIGNAL (toggled(bool)),              SLOT(redisplayPreview()));
+  connect(myDlg->myButtonGroup,   SIGNAL (buttonClicked(int)),         SLOT(redisplayPreview()));
 
   // IPAL22913: TC6.5.0: selected in "Move node" dialog box node is not highlighted
   // note: this slot seems to be lost together with removed obsolete SMESHGUI_MoveNodesDlg class
@@ -395,7 +398,10 @@ void SMESHGUI_MakeNodeAtPointOp::startOperation()
 
   // init simulation with a current View
   if ( mySimulation ) delete mySimulation;
-  mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( getSMESHGUI() ));
+  mySMESHGUI = getSMESHGUI();
+  mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ) );
+  connect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView()));
+  connect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView()));
   vtkProperty* aProp = vtkProperty::New();
   aProp->SetRepresentationToWireframe();
   aProp->SetColor(250, 0, 250);
@@ -436,13 +442,6 @@ void SMESHGUI_MakeNodeAtPointOp::startOperation()
   myDlg->show();
 
   onSelectionDone(); // init myMeshActor
-
-  if ( myMeshActor ) {
-//     myMeshActor->SetRepresentation( VTK_WIREFRAME );
-    myMeshActor->SetPointRepresentation(true);
-    SMESH::RepaintCurrentView();
-    redisplayPreview();
-  }
 }
 
 //=================================================================================
@@ -463,12 +462,19 @@ int SMESHGUI_MakeNodeAtPointOp::GetConstructorId()
 void SMESHGUI_MakeNodeAtPointOp::stopOperation()
 {
   myNoPreview = true;
-  mySimulation->SetVisibility(false);
+  if ( mySimulation )
+  {
+    mySimulation->SetVisibility(false);
+    delete mySimulation;
+    mySimulation = 0;
+  }
   if ( myMeshActor ) {
     myMeshActor->SetPointRepresentation(false);
     SMESH::RepaintCurrentView();
     myMeshActor = 0;
   }
+  disconnect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView()));
+  disconnect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView()));
   selectionMgr()->removeFilter( myFilter );
   SMESHGUI_SelectionOp::stopOperation();
 }
@@ -593,6 +599,8 @@ void SMESHGUI_MakeNodeAtPointOp::onSelectionDone()
 {
   if ( !myDlg->isVisible() || !myDlg->isEnabled() )
     return;
+
+  myNoPreview = true;
   try {
     SALOME_ListIO aList;
     selectionMgr()->selectedObjects(aList, SVTK_Viewer::Type());
@@ -601,6 +609,10 @@ void SMESHGUI_MakeNodeAtPointOp::onSelectionDone()
     Handle(SALOME_InteractiveObject) anIO = aList.First();
     SMESH_Actor* aMeshActor = SMESH::FindActorByEntry(anIO->getEntry());
 
+    if (( myDlg->myIdBtn->isChecked() && myDlg->myIdBtn->isEnabled() ) ||
+        ( !myDlg->myNodeToMoveGrp->isVisible() ))
+      myMeshActor = aMeshActor;
+
     if (!aMeshActor) { // coord by geom
       if ( myDlg->myDestBtn->isChecked() ) {
         GEOM::GEOM_Object_var geom = SMESH::IObjectToInterface<GEOM::GEOM_Object>(anIO);
@@ -609,63 +621,56 @@ void SMESHGUI_MakeNodeAtPointOp::onSelectionDone()
           if ( GEOMBase::GetShape(geom, aShape) &&
                aShape.ShapeType() == TopAbs_VERTEX ) {
             gp_Pnt P = BRep_Tool::Pnt(aShape);
-            myNoPreview = true;
             myDlg->myDestinationX->SetValue(P.X());
             myDlg->myDestinationY->SetValue(P.Y());
             myDlg->myDestinationZ->SetValue(P.Z());
-            myNoPreview = false;
-            redisplayPreview();
           }
         }
+        myNoPreview = false;
+        redisplayPreview();
         return;
       }
     }
 
-    if ( !myMeshActor )
-      myMeshActor = aMeshActor;
-
     QString aString;
     int nbElems = SMESH::GetNameOfSelectedElements(selector(),anIO, aString);
     if (nbElems == 1) {
       if (SMDS_Mesh* aMesh = aMeshActor->GetObject()->GetMesh()) {
         if (const SMDS_MeshNode* aNode = aMesh->FindNode(aString.toInt())) {
-          myNoPreview = true;
           if ( myDlg->myDestBtn->isChecked() ) { // set coord
             myDlg->myDestinationX->SetValue(aNode->X());
             myDlg->myDestinationY->SetValue(aNode->Y());
             myDlg->myDestinationZ->SetValue(aNode->Z());
-            myNoPreview = false;
-            redisplayPreview();
           }
           else if ( myDlg->myIdBtn->isChecked() &&
                     myDlg->myIdBtn->isEnabled() ) { // set node to move
             myDlg->myId->setText(aString);
-            myNoPreview = false;
+            myDlg->myCurrentX->SetValue( aNode->X() );
+            myDlg->myCurrentY->SetValue( aNode->Y() );
+            myDlg->myCurrentZ->SetValue( aNode->Z() );
             redisplayPreview();
           }
 
-          if (const SMDS_MeshNode* aCurrentNode = aMesh->FindNode(myDlg->myId->text().toInt())) {
-            double x = aCurrentNode->X();
-            double y = aCurrentNode->Y();
-            double z = aCurrentNode->Z();
-            double dx = myDlg->myDestinationX->GetValue() - x;
-            double dy = myDlg->myDestinationY->GetValue() - y;
-            double dz = myDlg->myDestinationZ->GetValue() - z;
-            myDlg->myCurrentX->SetValue(x);
-            myDlg->myCurrentY->SetValue(y);
-            myDlg->myCurrentZ->SetValue(z);
-            myDlg->myDestDX->SetValue(dx);
-            myDlg->myDestDY->SetValue(dy);
-            myDlg->myDestDZ->SetValue(dz);
-            myDlg->myDestDX->setReadOnly(false);
-            myDlg->myDestDY->setReadOnly(false);
-            myDlg->myDestDZ->setReadOnly(false);
-          }
+          double x = myDlg->myCurrentX->GetValue();
+          double y = myDlg->myCurrentY->GetValue();
+          double z = myDlg->myCurrentZ->GetValue();
+          double dx = myDlg->myDestinationX->GetValue() - x;
+          double dy = myDlg->myDestinationY->GetValue() - y;
+          double dz = myDlg->myDestinationZ->GetValue() - z;
+          myDlg->myDestDX->SetValue(dx);
+          myDlg->myDestDY->SetValue(dy);
+          myDlg->myDestDZ->SetValue(dz);
+          myDlg->myDestDX->setReadOnly(false);
+          myDlg->myDestDY->setReadOnly(false);
+          myDlg->myDestDZ->setReadOnly(false);
         }
       }
     }
   } catch (...) {
   }
+
+  myNoPreview = false;
+  redisplayPreview();
 }
 
 //================================================================================
@@ -685,7 +690,7 @@ void SMESHGUI_MakeNodeAtPointOp::redisplayPreview()
   bool moveShown = false;
   if ( myMeshActor)
   {
-    const bool isPreview = myDlg->myPreviewChkBox->isChecked();
+    const bool  isPreview = myDlg->myPreviewChkBox->isChecked();
     const bool isMoveNode = myDlg->myRButMoveWithoutNode->isChecked();
     QString msg;
     if ( isValid( msg ) )
@@ -714,22 +719,28 @@ void SMESHGUI_MakeNodeAtPointOp::redisplayPreview()
                 myDlg->myDestinationX->SetValue(x);
                 myDlg->myDestinationY->SetValue(y);
                 myDlg->myDestinationZ->SetValue(z);
-              }
-              if ( myDestCoordChanged ) {
-                dx = myDlg->myDestinationX->GetValue() - x;
-                dy = myDlg->myDestinationY->GetValue() - y;
-                dz = myDlg->myDestinationZ->GetValue() - z;
                 myDlg->myDestDX->SetValue(dx);
                 myDlg->myDestDY->SetValue(dy);
                 myDlg->myDestDZ->SetValue(dz);
               }
-              else {
-                dx = myDlg->myDestDX->GetValue() + x;
-                dy = myDlg->myDestDY->GetValue() + y;
-                dz = myDlg->myDestDZ->GetValue() + z;
-                myDlg->myDestinationX->SetValue(dx);
-                myDlg->myDestinationY->SetValue(dy);
-                myDlg->myDestinationZ->SetValue(dz);
+              else
+              {
+                if ( myDestCoordChanged ) {
+                  dx = myDlg->myDestinationX->GetValue() - x;
+                  dy = myDlg->myDestinationY->GetValue() - y;
+                  dz = myDlg->myDestinationZ->GetValue() - z;
+                  myDlg->myDestDX->SetValue(dx);
+                  myDlg->myDestDY->SetValue(dy);
+                  myDlg->myDestDZ->SetValue(dz);
+                }
+                else {
+                  dx = myDlg->myDestDX->GetValue() + x;
+                  dy = myDlg->myDestDY->GetValue() + y;
+                  dz = myDlg->myDestDZ->GetValue() + z;
+                  myDlg->myDestinationX->SetValue(dx);
+                  myDlg->myDestinationY->SetValue(dy);
+                  myDlg->myDestinationZ->SetValue(dz);
+                }
               }
               myDlg->myCurrentX->SetValue(x);
               myDlg->myCurrentY->SetValue(y);
@@ -787,7 +798,8 @@ void SMESHGUI_MakeNodeAtPointOp::redisplayPreview()
     aMeshPreviewStruct->elementConnectivities.length(1);
     aMeshPreviewStruct->elementConnectivities[0] = 0;
   }
-
+  if (!mySimulation)
+    mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ));
   // display data
   if ( aMeshPreviewStruct.operator->() )
   {
@@ -801,6 +813,33 @@ void SMESHGUI_MakeNodeAtPointOp::redisplayPreview()
   myNoPreview = false;
 }
 
+//=================================================================================
+/*!
+ * \brief SLOT called when the viewer opened
+ */
+//=================================================================================
+void SMESHGUI_MakeNodeAtPointOp::onOpenView()
+{
+  if ( mySimulation ) {
+    mySimulation->SetVisibility(false);
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ));
+  }
+}
+
+//=================================================================================
+/*!
+ * \brief SLOT called when the viewer closed
+ */
+//=================================================================================
+void SMESHGUI_MakeNodeAtPointOp::onCloseView()
+{
+  delete mySimulation;
+  mySimulation = 0;
+}
+
 //================================================================================
 /*!
  * \brief SLOT called when the node id is manually changed
@@ -839,7 +878,7 @@ void SMESHGUI_MakeNodeAtPointOp::onTextChange( const QString& theText )
 void SMESHGUI_MakeNodeAtPointOp::activateSelection()
 {
   selectionMgr()->clearFilters();
-  SMESH::SetPointRepresentation(false);
+  SMESH::SetPointRepresentation( true );
   selectionMgr()->installFilter( myFilter );
   setSelectionMode( NodeSelection );
 }
index 5af0a815ba8cf91c596a9dd1bf1468ad5f98c288..805f9505ec3a43e5e9a79dc75c853c74bcd34d22 100644 (file)
@@ -73,6 +73,8 @@ private slots:
   void                           onTextChange( const QString& );
   void                           onUpdateDestination();
   void                           onDestCoordChanged();
+  void                           onOpenView();
+  void                           onCloseView();
 
 private:
   int                           GetConstructorId();
@@ -81,6 +83,7 @@ private:
 
   SUIT_SelectionFilter*         myFilter;
   int                           myMeshOldDisplayMode;
+  SMESHGUI*                     mySMESHGUI;
   SMESHGUI_MeshEditPreview*     mySimulation;
   SMESH_Actor*                  myMeshActor;
   bool                          myNoPreview;
index 08fca6b6ae197f2e969ad1998e2113ffc5b0eb09..f594f650d623db168922ce2979574f6915b265db 100644 (file)
 #include "SMESHGUI_MergeDlg.h"
 
 #include "SMESHGUI.h"
-#include "SMESHGUI_Utils.h"
-#include "SMESHGUI_VTKUtils.h"
+#include "SMESHGUI_IdPreview.h"
 #include "SMESHGUI_MeshUtils.h"
 #include "SMESHGUI_SpinBox.h"
+#include "SMESHGUI_Utils.h"
+#include "SMESHGUI_VTKUtils.h"
 
 #include <SMESH_Actor.h>
 #include <SMESH_TypeFilter.hxx>
 #include CORBA_SERVER_HEADER(SMESH_Group)
 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
 
-// VTK includes
-#include <vtkUnstructuredGrid.h>
-#include <vtkRenderer.h>
-#include <vtkActor2D.h>
-#include <vtkPoints.h>
-#include <vtkDataSetMapper.h>
-#include <vtkMaskPoints.h>
-#include <vtkSelectVisiblePoints.h>
-#include <vtkLabeledDataMapper.h>
-#include <vtkTextProperty.h>
-#include <vtkIntArray.h>
-#include <vtkProperty2D.h>
-#include <vtkPointData.h>
-
 // Qt includes
 #include <QApplication>
+#include <QButtonGroup>
+#include <QCheckBox>
+#include <QGridLayout>
 #include <QGroupBox>
+#include <QHBoxLayout>
+#include <QKeyEvent>
 #include <QLabel>
 #include <QLineEdit>
 #include <QListWidget>
 #include <QPushButton>
 #include <QRadioButton>
-#include <QCheckBox>
-#include <QHBoxLayout>
 #include <QVBoxLayout>
-#include <QGridLayout>
-#include <QKeyEvent>
-#include <QButtonGroup>
 
 #define SPACING 6
 #define MARGIN  11
 
-namespace SMESH
+namespace
 {
-  class TIdPreview
-  { // to display in the viewer IDs of the selected elements
-    SVTK_ViewWindow* myViewWindow;
-
-    vtkUnstructuredGrid* myIdGrid;
-    SALOME_Actor* myIdActor;
-
-    vtkUnstructuredGrid* myPointsNumDataSet;
-    vtkMaskPoints* myPtsMaskPoints;
-    vtkSelectVisiblePoints* myPtsSelectVisiblePoints;
-    vtkLabeledDataMapper* myPtsLabeledDataMapper;
-    vtkTextProperty* aPtsTextProp;
-    bool myIsPointsLabeled;
-    vtkActor2D* myPointLabels;
-
-    std::vector<int> myIDs;
-
-  public:
-    TIdPreview(SVTK_ViewWindow* theViewWindow):
-      myViewWindow(theViewWindow)
-    {
-      myIdGrid = vtkUnstructuredGrid::New();
-
-      // Create and display actor
-      vtkDataSetMapper* aMapper = vtkDataSetMapper::New();
-      aMapper->SetInputData( myIdGrid );
-
-      myIdActor = SALOME_Actor::New();
-      myIdActor->SetInfinitive(true);
-      myIdActor->VisibilityOff();
-      myIdActor->PickableOff();
-
-      myIdActor->SetMapper( aMapper );
-      aMapper->Delete();
-
-      myViewWindow->AddActor(myIdActor);
-
-      //Definition of points numbering pipeline
-      myPointsNumDataSet = vtkUnstructuredGrid::New();
-
-      myPtsMaskPoints = vtkMaskPoints::New();
-      myPtsMaskPoints->SetInputData(myPointsNumDataSet);
-      myPtsMaskPoints->SetOnRatio(1);
-
-      myPtsSelectVisiblePoints = vtkSelectVisiblePoints::New();
-      myPtsSelectVisiblePoints->SetInputConnection(myPtsMaskPoints->GetOutputPort());
-      myPtsSelectVisiblePoints->SelectInvisibleOff();
-      myPtsSelectVisiblePoints->SetTolerance(0.1);
-    
-      myPtsLabeledDataMapper = vtkLabeledDataMapper::New();
-      myPtsLabeledDataMapper->SetInputConnection(myPtsSelectVisiblePoints->GetOutputPort());
-      myPtsLabeledDataMapper->SetLabelModeToLabelScalars();
-    
-      vtkTextProperty* aPtsTextProp = vtkTextProperty::New();
-      aPtsTextProp->SetFontFamilyToTimes();
-      static int aPointsFontSize = 12;
-      aPtsTextProp->SetFontSize(aPointsFontSize);
-      aPtsTextProp->SetBold(1);
-      aPtsTextProp->SetItalic(0);
-      aPtsTextProp->SetShadow(0);
-      myPtsLabeledDataMapper->SetLabelTextProperty(aPtsTextProp);
-      aPtsTextProp->Delete();
-  
-      myIsPointsLabeled = false;
-
-      myPointLabels = vtkActor2D::New();
-      myPointLabels->SetMapper(myPtsLabeledDataMapper);
-      myPointLabels->GetProperty()->SetColor(1,1,1);
-      myPointLabels->SetVisibility(myIsPointsLabeled);
-
-      AddToRender(myViewWindow->getRenderer());
-    }
-
-    void SetPointsData ( SMDS_Mesh* theMesh, 
-                         TColStd_MapOfInteger & theNodesIdMap )
-    {
-      vtkPoints* aPoints = vtkPoints::New();
-      aPoints->SetNumberOfPoints(theNodesIdMap.Extent());
-      myIDs.clear();
-      
-      TColStd_MapIteratorOfMapOfInteger idIter( theNodesIdMap );
-      for( int i = 0; idIter.More(); idIter.Next(), i++ ) {
-        const SMDS_MeshNode* aNode = theMesh->FindNode(idIter.Key());
-        aPoints->SetPoint( i, aNode->X(), aNode->Y(), aNode->Z() );
-        myIDs.push_back(idIter.Key());
-      }
-
-      myIdGrid->SetPoints(aPoints);
-
-      aPoints->Delete();
-
-      myIdActor->GetMapper()->Update();
-    }
-
-    void SetElemsData( TColStd_MapOfInteger & theElemsIdMap, 
-                       std::list<gp_XYZ> & aGrCentersXYZ )
-    {
-      vtkPoints* aPoints = vtkPoints::New();
-      aPoints->SetNumberOfPoints(theElemsIdMap.Extent());
-      myIDs.clear();
-      
-      TColStd_MapIteratorOfMapOfInteger idIter( theElemsIdMap );
-      for( ; idIter.More(); idIter.Next() ) {
-        myIDs.push_back(idIter.Key());
-      }
-
-      gp_XYZ aXYZ;
-      std::list<gp_XYZ>::iterator coordIt = aGrCentersXYZ.begin();
-      for( int i = 0; coordIt != aGrCentersXYZ.end(); coordIt++, i++ ) {
-        aXYZ = *coordIt;
-        aPoints->SetPoint( i, aXYZ.X(), aXYZ.Y(), aXYZ.Z() );
-      }
-      myIdGrid->SetPoints(aPoints);
-      aPoints->Delete();
-      
-      myIdActor->GetMapper()->Update();
-    }
-
-    void AddToRender(vtkRenderer* theRenderer)
-    {
-      myIdActor->AddToRender(theRenderer);
-
-      myPtsSelectVisiblePoints->SetRenderer(theRenderer);
-      theRenderer->AddActor2D(myPointLabels);
-    }
-
-    void RemoveFromRender(vtkRenderer* theRenderer)
-    {
-      myIdActor->RemoveFromRender(theRenderer);
-
-      myPtsSelectVisiblePoints->SetRenderer(theRenderer);
-      theRenderer->RemoveActor(myPointLabels);
-    }
-
-    void SetPointsLabeled( bool theIsPointsLabeled, bool theIsActorVisible = true )
-    {
-      myIsPointsLabeled = theIsPointsLabeled && myIdGrid->GetNumberOfPoints();
-      
-      if ( myIsPointsLabeled ) {
-        myPointsNumDataSet->ShallowCopy(myIdGrid);
-        vtkDataSet *aDataSet = myPointsNumDataSet;
-        int aNbElem = myIDs.size();
-        vtkIntArray *anArray = vtkIntArray::New();
-        anArray->SetNumberOfValues( aNbElem );
-        for ( int i = 0; i < aNbElem; i++ )
-          anArray->SetValue( i, myIDs[i] );
-        aDataSet->GetPointData()->SetScalars( anArray );
-        anArray->Delete();
-        myPtsMaskPoints->SetInputData( aDataSet );
-        myPointLabels->SetVisibility( theIsActorVisible );
-      }
-      else {
-        myPointLabels->SetVisibility( false );
-      }
-    }
-    
-    ~TIdPreview()
-    {
-      RemoveFromRender(myViewWindow->getRenderer());
-
-      myIdGrid->Delete();
-
-      myViewWindow->RemoveActor(myIdActor);
-      myIdActor->Delete();
-
-      //Deleting of points numbering pipeline
-      //---------------------------------------
-      myPointsNumDataSet->Delete();
-      
-      //myPtsLabeledDataMapper->RemoveAllInputs();        //vtk 5.0 porting
-      myPtsLabeledDataMapper->Delete();
-
-      //myPtsSelectVisiblePoints->UnRegisterAllOutputs(); //vtk 5.0 porting
-      myPtsSelectVisiblePoints->Delete();
-
-      //myPtsMaskPoints->UnRegisterAllOutputs();          //vtk 5.0 porting
-      myPtsMaskPoints->Delete();
+  enum ActionType { MERGE_NODES, MERGE_ELEMENTS, TYPE_AUTO=0, TYPE_MANUAL };
+}
 
-      myPointLabels->Delete();
 
-//       myTimeStamp->Delete();
-    }
-  };
+QPixmap SMESHGUI_MergeDlg::IconFirst()
+{
+  static const char * iconFirst[] = {
+    "18 10 2 1",
+    "       g None",
+    ".      g #000000",
+    "         .     .  ",
+    "  ..    ..    ..  ",
+    "  ..   ...   ...  ",
+    "  ..  ....  ....  ",
+    "  .. ..... .....  ",
+    "  .. ..... .....  ",
+    "  ..  ....  ....  ",
+    "  ..   ...   ...  ",
+    "  ..    ..    ..  ",
+    "         .     .  "};
+  return iconFirst;
 }
 
-static const char * IconFirst[] = {
-"18 10 2 1",
-"       g None",
-".      g #000000",
-"         .     .  ",
-"  ..    ..    ..  ",
-"  ..   ...   ...  ",
-"  ..  ....  ....  ",
-"  .. ..... .....  ",
-"  .. ..... .....  ",
-"  ..  ....  ....  ",
-"  ..   ...   ...  ",
-"  ..    ..    ..  ",
-"         .     .  "};
-
 //=================================================================================
 // class    : SMESHGUI_MergeDlg()
 // purpose  :
@@ -307,42 +117,40 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction)
 {
   setModal(false);
   setAttribute(Qt::WA_DeleteOnClose, true);
-  setWindowTitle(myAction == 1 ? tr("SMESH_MERGE_ELEMENTS") : tr("SMESH_MERGE_NODES"));
+  setWindowTitle(myAction == MERGE_ELEMENTS ? tr("SMESH_MERGE_ELEMENTS") : tr("SMESH_MERGE_NODES"));
 
-  myIdPreview = new SMESH::TIdPreview(SMESH::GetViewWindow( mySMESHGUI ));
+  myIdPreview = new SMESHGUI_IdPreview(SMESH::GetViewWindow( mySMESHGUI ));
 
   SUIT_ResourceMgr* aResMgr = SMESH::GetResourceMgr( mySMESHGUI );
-  QPixmap IconMergeNodes (aResMgr->loadPixmap("SMESH", tr("ICON_SMESH_MERGE_NODES")));
-  QPixmap IconMergeElems (aResMgr->loadPixmap("SMESH", tr("ICON_DLG_MERGE_ELEMENTS")));
+  // QPixmap IconMergeNodes (aResMgr->loadPixmap("SMESH", tr("ICON_SMESH_MERGE_NODES")));
+  // QPixmap IconMergeElems (aResMgr->loadPixmap("SMESH", tr("ICON_DLG_MERGE_ELEMENTS")));
   QPixmap IconSelect     (aResMgr->loadPixmap("SMESH", tr("ICON_SELECT")));
   QPixmap IconAdd        (aResMgr->loadPixmap("SMESH", tr("ICON_APPEND")));
   QPixmap IconRemove     (aResMgr->loadPixmap("SMESH", tr("ICON_REMOVE")));
 
   setSizeGripEnabled(true);
 
-  QVBoxLayout* DlgLayout = new QVBoxLayout(this);
-  DlgLayout->setSpacing(SPACING);
-  DlgLayout->setMargin(MARGIN);
-
   /***************************************************************/
-  GroupConstructors = new QGroupBox(myAction == 1 ? 
-                                    tr("SMESH_MERGE_ELEMENTS") : 
-                                    tr("SMESH_MERGE_NODES"), 
-                                    this);
-
-  QButtonGroup* ButtonGroup = new QButtonGroup(this);
-  QHBoxLayout* GroupConstructorsLayout = new QHBoxLayout(GroupConstructors);
-  GroupConstructorsLayout->setSpacing(SPACING);
-  GroupConstructorsLayout->setMargin(MARGIN);
-
-  RadioButton = new QRadioButton(GroupConstructors);
-  RadioButton->setIcon(myAction == 1 ? IconMergeElems : IconMergeNodes);
-  RadioButton->setChecked(true);
-  GroupConstructorsLayout->addWidget(RadioButton);
-  ButtonGroup->addButton(RadioButton, 0);
+  // Controls to switch dialog behaviour (myTypeId)
+
+  TypeBox   = new QGroupBox( tr("SMESH_MODE"), this );
+  GroupType = new QButtonGroup( this );
+  QHBoxLayout* aTypeBoxLayout = new QHBoxLayout( TypeBox );
+  aTypeBoxLayout->setMargin( MARGIN );
+  aTypeBoxLayout->setSpacing( SPACING );
+
+  QRadioButton* rb1 = new QRadioButton( tr( "SMESH_AUTOMATIC" ), TypeBox );
+  QRadioButton* rb2 = new QRadioButton( tr( "SMESH_MANUAL" ),   TypeBox );
+  GroupType->addButton( rb1, 0 );
+  GroupType->addButton( rb2, 1 );
+  aTypeBoxLayout->addWidget( rb1 );
+  aTypeBoxLayout->addWidget( rb2 );
+
+  myTypeId = TYPE_AUTO;
 
   /***************************************************************/
   // Controls for mesh defining
+
   GroupMesh = new QGroupBox(tr("SMESH_SELECT_WHOLE_MESH"), this);
   QHBoxLayout* GroupMeshLayout = new QHBoxLayout(GroupMesh);
   GroupMeshLayout->setSpacing(SPACING);
@@ -358,42 +166,44 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction)
   GroupMeshLayout->addWidget(SelectMeshButton);
   GroupMeshLayout->addWidget(LineEditMesh);
 
-  /***************************************************************/
-  // Controls for switch dialog behaviour
-
-  TypeBox = new QGroupBox( tr( "SMESH_MODE" ), this );
-  GroupType = new QButtonGroup( this );
-  QHBoxLayout* aTypeBoxLayout = new QHBoxLayout( TypeBox );
-  aTypeBoxLayout->setMargin( MARGIN );
-  aTypeBoxLayout->setSpacing( SPACING );
-
-  QRadioButton* rb1 = new QRadioButton( tr( "SMESH_AUTOMATIC" ), TypeBox );
-  QRadioButton* rb2 = new QRadioButton( tr( "SMESH_MANUAL" ),   TypeBox );
-  GroupType->addButton( rb1, 0 );
-  GroupType->addButton( rb2, 1 );
-  aTypeBoxLayout->addWidget( rb1 );
-  aTypeBoxLayout->addWidget( rb2 );
-
-  myTypeId = 0;
-
   /***************************************************************/
   // Controls for coincident elements detecting
-  GroupCoincident = new QGroupBox(myAction == 1 ? 
-                                  tr("COINCIDENT_ELEMENTS") : 
-                                  tr("COINCIDENT_NODES"), 
+
+  GroupCoincident = new QGroupBox(myAction == MERGE_ELEMENTS ?
+                                  tr("COINCIDENT_ELEMENTS") :
+                                  tr("COINCIDENT_NODES"),
                                   this);
 
-  QVBoxLayout* aCoincidentLayout = new QVBoxLayout(GroupCoincident);
+  QGridLayout* aCoincidentLayout = new QGridLayout(GroupCoincident);
   aCoincidentLayout->setSpacing(SPACING);
   aCoincidentLayout->setMargin(MARGIN);
 
-  if (myAction == 0) { // case merge nodes
-    QWidget* foo = new QWidget(GroupCoincident);
-    TextLabelTolerance = new QLabel(tr("SMESH_TOLERANCE"), foo);
-    SpinBoxTolerance = new SMESHGUI_SpinBox(foo);
+  if (myAction == MERGE_NODES) // case merge nodes
+  {
+    /***************************************************************/
+    // Node specific Controls: tolerance, ...
+
+    NodeSpecWidget = new QWidget( this );
+
+    QLabel* TextLabelTolerance = new QLabel(tr("SMESH_TOLERANCE"), NodeSpecWidget);
+    SpinBoxTolerance = new SMESHGUI_SpinBox( NodeSpecWidget );
     SpinBoxTolerance->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
 
-    GroupExclude = new QGroupBox(tr("EXCLUDE_GROUPS"), foo);
+    SeparateCornersAndMedium = new QCheckBox(tr("SEPARATE_CORNERS_AND_MEDIUM"), NodeSpecWidget );
+    SeparateCornersAndMedium->setEnabled( false );
+
+    QGridLayout* NodeSpecLayout = new QGridLayout(NodeSpecWidget);
+    NodeSpecLayout->setSpacing(SPACING);
+    NodeSpecLayout->setMargin(0);
+
+    NodeSpecLayout->addWidget(TextLabelTolerance,       0, 0 );
+    NodeSpecLayout->addWidget(SpinBoxTolerance,         0, 1 );
+    NodeSpecLayout->addWidget(SeparateCornersAndMedium, 1, 0, 1, 2 );
+
+    /***************************************************************/
+    // Exclude groups
+
+    GroupExclude = new QGroupBox(tr("EXCLUDE_GROUPS"), this );
     GroupExclude->setCheckable( true );
     GroupExclude->setChecked( false );
     ListExclude = new QListWidget( GroupExclude );
@@ -402,50 +212,81 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction)
     GroupExcludeLayout->setMargin(MARGIN);
     GroupExcludeLayout->addWidget(ListExclude);
 
-    QGridLayout* fooLayout = new QGridLayout( foo );
-    fooLayout->setSpacing(SPACING);
-    fooLayout->setMargin(0);
-    fooLayout->addWidget(TextLabelTolerance, 0, 0 );
-    fooLayout->addWidget(SpinBoxTolerance,   0, 1 );
-    fooLayout->addWidget(GroupExclude,       1, 0, 1, 2 );
-    aCoincidentLayout->addWidget(foo);
+    /***************************************************************/
+    // Nodes to keep
+
+    GroupKeep = new QGroupBox(tr("KEEP_NODES"), this);
+    SelectKeepNodesButton = new QPushButton( GroupKeep );
+    SelectKeepNodesButton->setIcon( IconSelect );
+    QLabel*       selectLabel = new QLabel(tr("SELECT"));
+    QRadioButton*   idsButton = new QRadioButton(tr("SMESH_NODES"), GroupKeep);
+    QRadioButton* groupButton = new QRadioButton(tr("GROUP_SUBMESH"), GroupKeep);
+    KeepFromButGroup = new QButtonGroup( this );
+    KeepFromButGroup->addButton( idsButton,   0 );
+    KeepFromButGroup->addButton( groupButton, 1 );
+    groupButton->setChecked( true );
+    KeepList = new QListWidget( GroupKeep );
+    KeepList->setSelectionMode(QAbstractItemView::ExtendedSelection);
+    KeepList->setFlow(QListView::TopToBottom);
+    AddKeepNodesButton    = new QPushButton(tr("SMESH_BUT_ADD"), GroupKeep );
+    RemoveKeepNodesButton = new QPushButton(tr("SMESH_BUT_REMOVE"), GroupKeep );
+    QGridLayout* GroupKeepLayout = new QGridLayout(GroupKeep);
+    GroupKeepLayout->setSpacing( SPACING );
+    GroupKeepLayout->setMargin ( MARGIN );
+    GroupKeepLayout->addWidget( SelectKeepNodesButton, 0, 0 );
+    GroupKeepLayout->addWidget( selectLabel,           0, 1 );
+    GroupKeepLayout->addWidget( idsButton,             0, 2 );
+    GroupKeepLayout->addWidget( groupButton,           0, 3, 1, 2 );
+    GroupKeepLayout->addWidget( KeepList,              1, 0, 3, 4 );
+    GroupKeepLayout->addWidget( AddKeepNodesButton,    1, 4, 1, 1 );
+    GroupKeepLayout->addWidget( RemoveKeepNodesButton, 2, 4, 1, 1 );
+    GroupKeepLayout->setRowStretch(3, 5);
+
+    // Costruction of the logical filter
+    QList<SUIT_SelectionFilter*> aListOfFilters;
+    aListOfFilters << new SMESH_TypeFilter (SMESH::SUBMESH)
+                   << new SMESH_TypeFilter (SMESH::GROUP);
+    mySubMeshOrGroupFilter =
+      new SMESH_LogicalFilter (aListOfFilters, SMESH_LogicalFilter::LO_OR, /*takeOwnership=*/true);
   }
   else {
-    TextLabelTolerance = 0;
-    SpinBoxTolerance = 0;
-    GroupExclude = 0;
-    ListExclude = 0;
+    NodeSpecWidget         = 0;
+    SpinBoxTolerance       = 0;
+    GroupExclude           = 0;
+    ListExclude            = 0;
+    KeepFromButGroup       = 0;
+    SelectKeepNodesButton  = 0;
+    AddKeepNodesButton     = 0;
+    RemoveKeepNodesButton  = 0;
+    KeepList               = 0;
+    mySubMeshOrGroupFilter = 0;
   }
 
-  GroupCoincidentWidget = new QWidget(GroupCoincident);
-  QGridLayout* GroupCoincidentLayout = new QGridLayout(GroupCoincidentWidget);
-  GroupCoincidentLayout->setSpacing(SPACING);
-  GroupCoincidentLayout->setMargin(0);
-
-  ListCoincident = new QListWidget(GroupCoincidentWidget);
+  ListCoincident = new QListWidget(GroupCoincident);
   ListCoincident->setSelectionMode(QListWidget::ExtendedSelection);
 
-  DetectButton      = new QPushButton(tr("DETECT"),           GroupCoincidentWidget);
-  AddGroupButton    = new QPushButton(tr("SMESH_BUT_ADD"),    GroupCoincidentWidget);
-  RemoveGroupButton = new QPushButton(tr("SMESH_BUT_REMOVE"), GroupCoincidentWidget);
-
-  SelectAllCB = new QCheckBox(tr("SELECT_ALL"), GroupCoincidentWidget);
-  ShowIDs = new QCheckBox(myAction == 1 ? tr("SHOW_ELEMS_IDS") : tr("SHOW_NODES_IDS"), GroupCoincidentWidget);
+  DetectButton      = new QPushButton(tr("DETECT"),           GroupCoincident);
+  AddGroupButton    = new QPushButton(tr("SMESH_BUT_ADD"),    GroupCoincident);
+  RemoveGroupButton = new QPushButton(tr("SMESH_BUT_REMOVE"), GroupCoincident);
 
-  GroupCoincidentLayout->addWidget(ListCoincident,    0,   0, 4, 2);
-  GroupCoincidentLayout->addWidget(DetectButton,      0,   2);
-  GroupCoincidentLayout->addWidget(AddGroupButton,    2, 2);
-  GroupCoincidentLayout->addWidget(RemoveGroupButton, 3, 2);
-  GroupCoincidentLayout->addWidget(SelectAllCB,       4, 0);
-  GroupCoincidentLayout->addWidget(ShowIDs,           4, 1);
-  GroupCoincidentLayout->setRowMinimumHeight(1, 10);
-  GroupCoincidentLayout->setRowStretch(1, 5);
+  SelectAllCB = new QCheckBox(tr("SELECT_ALL"), GroupCoincident);
+  ShowIDs = new QCheckBox(myAction == MERGE_ELEMENTS ? tr("SHOW_ELEMS_IDS") : tr("SHOW_NODES_IDS"), GroupCoincident);
 
-  aCoincidentLayout->addWidget(GroupCoincidentWidget);
+  aCoincidentLayout->addWidget(ListCoincident,    0, 0, 4, 2);
+  aCoincidentLayout->addWidget(DetectButton,      0, 2);
+  aCoincidentLayout->addWidget(AddGroupButton,    2, 2);
+  aCoincidentLayout->addWidget(RemoveGroupButton, 3, 2);
+  aCoincidentLayout->addWidget(SelectAllCB,       4, 0);
+  aCoincidentLayout->addWidget(ShowIDs,           4, 1);
+  aCoincidentLayout->setRowMinimumHeight(1, 10);
+  aCoincidentLayout->setRowStretch(1, 5);
 
   /***************************************************************/
   // Controls for editing the selected group
-  GroupEdit = new QGroupBox(tr("EDIT_SELECTED_GROUP"), this);
+
+  GroupEdit = new QGroupBox(myAction == MERGE_NODES ?
+                            tr("EDIT_SELECTED_NODE_GROUP") :
+                            tr("EDIT_SELECTED_ELEM_GROUP"), this);
   QGridLayout* GroupEditLayout = new QGridLayout(GroupEdit);
   GroupEditLayout->setSpacing(SPACING);
   GroupEditLayout->setMargin(MARGIN);
@@ -462,7 +303,7 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction)
   RemoveElemButton = new QPushButton(GroupEdit);
   RemoveElemButton->setIcon(IconRemove);
   SetFirstButton = new QPushButton(GroupEdit);
-  SetFirstButton->setIcon(QPixmap(IconFirst));
+  SetFirstButton->setIcon(IconFirst());
 
   GroupEditLayout->addWidget(ListEdit,         0, 0, 2, 1);
   GroupEditLayout->addWidget(AddElemButton,    0, 1);
@@ -494,16 +335,49 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction)
   GroupButtonsLayout->addWidget(buttonHelp);
 
   /***************************************************************/
-  DlgLayout->addWidget(GroupConstructors);
-  DlgLayout->addWidget(GroupMesh);
-  DlgLayout->addWidget(TypeBox);
-  DlgLayout->addWidget(GroupCoincident);
-  DlgLayout->addWidget(GroupEdit);
-  DlgLayout->addWidget(GroupButtons);
-
-  GroupCoincidentWidget->setVisible( myAction != 0 );
-  GroupCoincident->setVisible( myAction == 0 );
-  //if GroupExclude->setVisible( myAction == 0 );
+  if (myAction == MERGE_NODES)
+  {
+    QWidget* LeftWdg = new QWidget( this );
+    QVBoxLayout* LeftLayout = new QVBoxLayout(LeftWdg);
+    LeftLayout->setSpacing(SPACING);
+    LeftLayout->setMargin(0);
+    LeftLayout->addWidget(TypeBox);
+    LeftLayout->addWidget(GroupMesh);
+    LeftLayout->addWidget(NodeSpecWidget);
+    LeftLayout->addWidget(GroupCoincident);
+    LeftLayout->addStretch();
+    LeftLayout->addWidget(GroupButtons);
+    LeftLayout->setStretch( 3, 10 );
+
+    QWidget* RightWdg = new QWidget( this );
+    QVBoxLayout* RightLayout = new QVBoxLayout(RightWdg);
+    RightLayout->setSpacing(SPACING);
+    RightLayout->setMargin(0);
+    RightLayout->addWidget(GroupExclude);
+    RightLayout->addWidget(GroupKeep);
+    RightLayout->addWidget(GroupEdit);
+    RightLayout->setStretch( 0, 4 );
+    RightLayout->setStretch( 1, 5 );
+
+    QHBoxLayout* DlgLayout = new QHBoxLayout(this);
+    DlgLayout->setSpacing(SPACING*2);
+    DlgLayout->setMargin(MARGIN);
+    DlgLayout->addWidget( LeftWdg );
+    DlgLayout->addWidget( RightWdg );
+  }
+  else
+  {
+    QVBoxLayout* DlgLayout = new QVBoxLayout(this);
+    DlgLayout->setSpacing(SPACING);
+    DlgLayout->setMargin(MARGIN);
+    DlgLayout->addWidget(TypeBox);
+    DlgLayout->addWidget(GroupMesh);
+    DlgLayout->addWidget(GroupCoincident);
+    DlgLayout->addWidget(GroupEdit);
+    DlgLayout->addWidget(GroupButtons);
+  }
+
+  GroupCoincident->hide();
   GroupEdit->hide();
 
   this->resize(10,10);
@@ -528,16 +402,14 @@ SMESHGUI_MergeDlg::~SMESHGUI_MergeDlg()
 //=================================================================================
 void SMESHGUI_MergeDlg::Init()
 {
-  if (myAction == 0) {
+  if ( myAction == MERGE_NODES ) {
     SpinBoxTolerance->RangeStepAndValidator(0.0, COORD_MAX, 0.00001, "len_tol_precision");
     SpinBoxTolerance->SetValue(1e-05);
   }
 
-  RadioButton->setChecked(true);
-
   GroupType->button(0)->setChecked(true);
 
-  myEditCurrentArgument = (QWidget*)LineEditMesh; 
+  myEditCurrentArgument = (QWidget*)LineEditMesh;
 
   myActor = 0;
   mySubMeshOrGroup = SMESH::SMESH_subMesh::_nil();
@@ -546,13 +418,21 @@ void SMESHGUI_MergeDlg::Init()
 
   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
   myIsBusy = false;
-  
+
   /* signals and slots connections */
   connect(buttonOk,     SIGNAL(clicked()), this, SLOT(ClickOnOk()));
   connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject()));
   connect(buttonApply,  SIGNAL(clicked()), this, SLOT(ClickOnApply()));
   connect(buttonHelp,   SIGNAL(clicked()), this, SLOT(ClickOnHelp()));
 
+  if ( KeepList )
+  {
+    connect(SelectKeepNodesButton, SIGNAL (clicked()), this, SLOT(SetEditCurrentArgument()));
+    connect(KeepFromButGroup, SIGNAL (buttonClicked(int)), SLOT(onKeepNodeSourceChanged(int)));
+    connect(AddKeepNodesButton, SIGNAL (clicked()), this, SLOT(onAddKeepNode()));
+    connect(RemoveKeepNodesButton, SIGNAL (clicked()), this, SLOT(onRemoveKeepNode()));
+    connect(KeepList, SIGNAL (itemSelectionChanged()), this, SLOT(onSelectKeepNode()));
+  }
   connect(SelectMeshButton, SIGNAL (clicked()), this, SLOT(SetEditCurrentArgument()));
   connect(DetectButton, SIGNAL (clicked()), this, SLOT(onDetect()));
   connect(ListCoincident, SIGNAL (itemSelectionChanged()), this, SLOT(onSelectGroup()));
@@ -563,21 +443,22 @@ void SMESHGUI_MergeDlg::Init()
   connect(ListEdit, SIGNAL (itemSelectionChanged()), this, SLOT(onSelectElementFromGroup()));
   connect(AddElemButton, SIGNAL (clicked()), this, SLOT(onAddElement()));
   connect(RemoveElemButton, SIGNAL (clicked()), this, SLOT(onRemoveElement()));
-  connect(SetFirstButton, SIGNAL( clicked() ), this, SLOT( onSetFirst() ) );
+  connect(SetFirstButton, SIGNAL( clicked() ), this, SLOT( onSetFirst()));
   connect(GroupType, SIGNAL(buttonClicked(int)), this, SLOT(onTypeChanged(int)));
 
   connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
   /* to close dialog if study change */
   connect(mySMESHGUI, SIGNAL (SignalCloseAllDialogs()), this, SLOT(reject()));
-
+  connect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this,  SLOT(onOpenView()));
+  connect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView()));
   // Init Mesh field from selection
   SelectionIntoArgument();
 
   // Update Buttons
   updateControls();
   
-  if (myAction == 0)
+  if ( myAction == MERGE_NODES )
     myHelpFileName = "merging_nodes_page.html";
   else
     myHelpFileName = "merging_elements_page.html";
@@ -587,8 +468,9 @@ void SMESHGUI_MergeDlg::Init()
 // function : FindGravityCenter()
 // purpose  :
 //=================================================================================
-void SMESHGUI_MergeDlg::FindGravityCenter(TColStd_MapOfInteger & theElemsIdMap, 
-                                          std::list< gp_XYZ > & theGrCentersXYZ)
+void SMESHGUI_MergeDlg::FindGravityCenter(TColStd_MapOfInteger & theElemsIdMap,
+                                          std::vector<int>&      theIDs,
+                                          std::list< gp_XYZ > &  theGrCentersXYZ)
 {
   if (!myActor)
     return;
@@ -600,11 +482,13 @@ void SMESHGUI_MergeDlg::FindGravityCenter(TColStd_MapOfInteger & theElemsIdMap,
 
   int nbNodes;
 
+  theIDs.reserve( theElemsIdMap.Extent() );
   TColStd_MapIteratorOfMapOfInteger idIter( theElemsIdMap );
   for( ; idIter.More(); idIter.Next() ) {
     const SMDS_MeshElement* anElem = aMesh->FindElement(idIter.Key());
     if ( !anElem )
       continue;
+    theIDs.push_back( idIter.Key() );
 
     gp_XYZ anXYZ(0., 0., 0.);
     SMDS_ElemIteratorPtr nodeIt = anElem->nodesIterator();
@@ -628,7 +512,7 @@ bool SMESHGUI_MergeDlg::ClickOnApply()
     return false;
 
   try {
-    if (myTypeId == 0)
+    if (myTypeId == TYPE_AUTO)
       onDetect();
 
     SUIT_OverrideCursor aWaitCursor;
@@ -638,7 +522,7 @@ bool SMESHGUI_MergeDlg::ClickOnApply()
     SMESH::array_of_long_array_var aGroupsOfElements = new SMESH::array_of_long_array;
 
     if ( ListCoincident->count() == 0) {
-      if (myAction == 0)
+      if ( myAction == MERGE_NODES )
         SUIT_MessageBox::warning(this,
                                  tr("SMESH_WARNING"),
                                  tr("SMESH_NO_NODES_DETECTED"));
@@ -662,31 +546,72 @@ bool SMESHGUI_MergeDlg::ClickOnApply()
       aGroupsOfElements[anArrayNum++] = anIds.inout();
     }
 
-    if( myAction == 0 )
-      aMeshEditor->MergeNodes (aGroupsOfElements.inout());
+    SMESH::ListOfIDSources_var nodesToKeep;
+    SMESH::IDSource_wrap tmpIdSource;
+    if ( myAction == MERGE_NODES )
+    {
+      nodesToKeep = new SMESH::ListOfIDSources();
+      int i, nb = KeepList->count();
+      if ( isKeepNodesIDsSelection() )
+      {
+        SMESH::long_array_var anIdList = new SMESH::long_array();
+        anIdList->length(nb);
+        for (i = 0; i < nb; i++)
+          anIdList[i] = KeepList->item(i)->text().toInt();
+
+        if ( nb > 0 )
+        {
+          tmpIdSource = aMeshEditor->MakeIDSource( anIdList, SMESH::NODE );
+          nodesToKeep->length( 1 );
+          nodesToKeep[0] = SMESH::SMESH_IDSource::_duplicate( tmpIdSource.in() );
+        }
+      }
+      else
+      {
+        nodesToKeep->length( nb );
+        int nbObj = 0;
+        for (i = 0; i < nb; i++)
+        {
+          QString entry = KeepList->item( i )->data( Qt::UserRole ).toString();
+          Handle(SALOME_InteractiveObject) anIO =
+            new SALOME_InteractiveObject( entry.toStdString().c_str(), "SMESH" );
+          SMESH::SMESH_IDSource_var idSrc =
+            SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( anIO );
+          if ( !idSrc->_is_nil() )
+            nodesToKeep[ nbObj++ ] = SMESH::SMESH_IDSource::_duplicate( idSrc );
+        }
+        nodesToKeep->length( nbObj );
+      }
+      KeepList->clear();
+    }
+
+    if( myAction == MERGE_NODES )
+      aMeshEditor->MergeNodes (aGroupsOfElements.inout(), nodesToKeep);
     else
       aMeshEditor->MergeElements (aGroupsOfElements.inout());
 
-    if ( myTypeId == 0 ) {
-      if (myAction == 0 )
+    if ( myTypeId == TYPE_AUTO ) {
+      if (myAction == MERGE_NODES )
         SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INFORMATION"),
                                      tr("SMESH_MERGED_NODES").arg(QString::number(ListCoincident->count()).toLatin1().data()));
       else
         SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INFORMATION"),
                                      tr("SMESH_MERGED_ELEMENTS").arg(QString::number(ListCoincident->count()).toLatin1().data()));
     }
-      
+    if ( & nodesToKeep.in() )
+      nodesToKeep->length(0); // release before tmpIdSource calls UnRegister()
 
-  } catch(...) {
   }
-  
+  catch(...) {
+  }
+
   ListCoincident->clear();
-  
+
   myEditCurrentArgument = (QWidget*)LineEditMesh;
 
   SMESH::UpdateView();
   SMESHGUI::Modified();
-  
+
   return true;
 }
 
@@ -721,6 +646,31 @@ void SMESHGUI_MergeDlg::reject()
   QDialog::reject();
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_MergeDlg::onOpenView()
+{
+  if ( mySelector ) {
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    ActivateThisDialog();
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_MergeDlg::onCloseView()
+{
+  DeactivateActiveDialog();
+  mySelector = 0;
+}
+
 //=================================================================================
 // function : ClickOnHelp()
 // purpose  :
@@ -775,10 +725,33 @@ void SMESHGUI_MergeDlg::updateControls()
 {
   if (ListEdit->count() == 0)
     SetFirstButton->setEnabled(false);
-  bool enable = !(myMesh->_is_nil()) && (ListCoincident->count() || (myTypeId == 0));
+
+  bool groupsEmpty = ( myTypeId != TYPE_AUTO );
+  for (int i = 0; i < ListCoincident->count() && groupsEmpty; i++) {
+    QStringList aListIds = ListCoincident->item(i)->text().split(" ", QString::SkipEmptyParts);
+    groupsEmpty = ( aListIds.count() < 2 );
+  }
+  bool enable = ( !myMesh->_is_nil() && !groupsEmpty );
   buttonOk->setEnabled(enable);
   buttonApply->setEnabled(enable);
   DetectButton->setEnabled( !myMesh->_is_nil() );
+
+  if ( myAction == MERGE_NODES )
+  {
+    bool has2ndOrder = (( !myMesh->_is_nil() ) &&
+                        ( myMesh->NbEdgesOfOrder( SMESH::ORDER_QUADRATIC ) > 0 ||
+                          myMesh->NbFacesOfOrder( SMESH::ORDER_QUADRATIC ) > 0 ||
+                          myMesh->NbVolumesOfOrder( SMESH::ORDER_QUADRATIC ) > 0 ));
+
+    SeparateCornersAndMedium->setEnabled( has2ndOrder );
+
+    if ( myEditCurrentArgument != KeepList )
+    {
+      AddKeepNodesButton->setEnabled( false );
+      RemoveKeepNodesButton->setEnabled( false );
+      KeepList->clearSelection();
+    }
+  }
 }
 
 //=================================================================================
@@ -802,10 +775,10 @@ void SMESHGUI_MergeDlg::onDetect()
 
     SMESH::SMESH_IDSource_var src;
     if ( mySubMeshOrGroup->_is_nil() ) src = SMESH::SMESH_IDSource::_duplicate( myMesh );
-    else src = SMESH::SMESH_IDSource::_duplicate( mySubMeshOrGroup );
+    else                               src = SMESH::SMESH_IDSource::_duplicate( mySubMeshOrGroup );
 
     switch (myAction) {
-    case 0 :
+    case MERGE_NODES :
       for ( int i = 0; GroupExclude->isChecked() && i < ListExclude->count(); i++ ) {
         if ( ListExclude->item( i )->checkState() == Qt::Checked ) {
           aExcludeGroups->length( aExcludeGroups->length()+1 );
@@ -815,9 +788,11 @@ void SMESHGUI_MergeDlg::onDetect()
       aMeshEditor->FindCoincidentNodesOnPartBut(src.in(),
                                                 SpinBoxTolerance->GetValue(), 
                                                 aGroupsArray.out(),
-                                                aExcludeGroups.in());
+                                                aExcludeGroups.in(),
+                                                SeparateCornersAndMedium->isEnabled() &&
+                                                SeparateCornersAndMedium->isChecked());
       break;
-    case 1 :
+    case MERGE_ELEMENTS :
       aMeshEditor->FindEqualElements(src.in(), aGroupsArray.out());
       break;
     }
@@ -831,7 +806,7 @@ void SMESHGUI_MergeDlg::onDetect()
 
       ListCoincident->addItem(anIDs.join(" "));
     }
-   } catch(...) {
+  } catch(...) {
   }
 
   ListCoincident->selectAll();
@@ -851,11 +826,22 @@ void SMESHGUI_MergeDlg::onSelectGroup()
   if( ListCoincident->count() != ListCoincident->selectedItems().count() )
     SelectAllCB->setChecked( false );
 
+  if ( myEditCurrentArgument == (QWidget*)KeepList && KeepList &&
+       !isKeepNodesIDsSelection() )
+  {
+    // restore selection of nodes after selection of sub-meshes
+    mySelectionMgr->clearFilters();
+    if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+      aViewWindow->SetSelectionMode( NodeSelection );
+    SMESH::SetPointRepresentation( true );
+    myEditCurrentArgument = ListCoincident;
+  }
+
   myEditCurrentArgument = (QWidget*)ListCoincident;
 
   myIsBusy = true;
   ListEdit->clear();
-  
+
   TColStd_MapOfInteger anIndices;
   QList<QListWidgetItem*> selItems = ListCoincident->selectedItems();
   QListWidgetItem* anItem;
@@ -868,7 +854,7 @@ void SMESHGUI_MergeDlg::onSelectGroup()
     for (int i = 0; i < aListIds.count(); i++)
       anIndices.Add(aListIds[i].toInt());
   }
-  
+
   if (selItems.count() == 1) {
     ListEdit->addItems(aListIds);
     ListEdit->selectAll();
@@ -880,14 +866,15 @@ void SMESHGUI_MergeDlg::onSelectGroup()
   mySelectionMgr->setSelectedObjects(aList,false);
   
   if (ShowIDs->isChecked()) 
-    if (myAction == 0) {
+    if ( myAction == MERGE_NODES ) {
       myIdPreview->SetPointsData(myActor->GetObject()->GetMesh(), anIndices);
       myIdPreview->SetPointsLabeled(!anIndices.IsEmpty(), myActor->GetVisibility());
     }
     else {
       std::list< gp_XYZ > aGrCentersXYZ;
-      FindGravityCenter(anIndices, aGrCentersXYZ);
-      myIdPreview->SetElemsData( anIndices, aGrCentersXYZ);
+      std::vector<int>    anIDs;
+      FindGravityCenter(anIndices, anIDs, aGrCentersXYZ);
+      myIdPreview->SetElemsData( anIDs, aGrCentersXYZ );
       myIdPreview->SetPointsLabeled(!anIndices.IsEmpty(), myActor->GetVisibility());
     }
   else
@@ -933,18 +920,30 @@ void SMESHGUI_MergeDlg::onSelectElementFromGroup()
   mySelectionMgr->setSelectedObjects(aList);
   
   if (ShowIDs->isChecked())
-    if (myAction == 0) {
+    if (myAction == MERGE_NODES) {
       myIdPreview->SetPointsData(myActor->GetObject()->GetMesh(), anIndices);
       myIdPreview->SetPointsLabeled(!anIndices.IsEmpty(), myActor->GetVisibility());
     }
     else {
       std::list< gp_XYZ > aGrCentersXYZ;
-      FindGravityCenter(anIndices, aGrCentersXYZ);
-      myIdPreview->SetElemsData(anIndices, aGrCentersXYZ);
+      std::vector<int>    anIDs;
+      FindGravityCenter(anIndices, anIDs, aGrCentersXYZ);
+      myIdPreview->SetElemsData(anIDs, aGrCentersXYZ);
       myIdPreview->SetPointsLabeled(!anIndices.IsEmpty(), myActor->GetVisibility());
     }
   else 
     myIdPreview->SetPointsLabeled(false);
+
+  if ( myEditCurrentArgument == (QWidget*)KeepList && KeepList &&
+       !isKeepNodesIDsSelection() )
+  {
+    // restore selection of nodes after selection of sub-meshes
+    mySelectionMgr->clearFilters();
+    if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+      aViewWindow->SetSelectionMode( NodeSelection );
+    SMESH::SetPointRepresentation( true );
+    myEditCurrentArgument = ListCoincident;
+  }
 }
 
 //=================================================================================
@@ -1102,14 +1101,33 @@ void SMESHGUI_MergeDlg::SetEditCurrentArgument()
   mySelectionMgr->clearSelected();
   mySelectionMgr->clearFilters();
 
-  if (send == SelectMeshButton) {
+  if (send == SelectMeshButton)
+  {
     myEditCurrentArgument = (QWidget*)LineEditMesh;
     SMESH::SetPointRepresentation(false);
     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
       aViewWindow->SetSelectionMode(ActorSelection);
-    if (myTypeId == 1)
+    if (myTypeId == TYPE_MANUAL)
       mySelectionMgr->installFilter(myMeshOrSubMeshOrGroupFilter);
   }
+  else if ( send == SelectKeepNodesButton && send )
+  {
+    myEditCurrentArgument = (QWidget*)KeepList;
+    KeepList->setWrapping( isKeepNodesIDsSelection() );
+    if ( isKeepNodesIDsSelection() )
+    {
+      SMESH::SetPointRepresentation( true );
+      if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+        aViewWindow->SetSelectionMode( NodeSelection );
+    }
+    else
+    {
+      SMESH::SetPointRepresentation( false );
+      if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+        aViewWindow->SetSelectionMode( ActorSelection );
+      mySelectionMgr->installFilter( mySubMeshOrGroupFilter );
+    }
+  }
 
   myEditCurrentArgument->setFocus();
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
@@ -1118,11 +1136,12 @@ void SMESHGUI_MergeDlg::SetEditCurrentArgument()
 
 //=================================================================================
 // function : SelectionIntoArgument()
-// purpose  : Called when selection as changed or other case
+// purpose  : Called when selection has changed or other case
 //=================================================================================
 void SMESHGUI_MergeDlg::SelectionIntoArgument()
 {
-  if (myEditCurrentArgument == (QWidget*)LineEditMesh) {
+  if (myEditCurrentArgument == (QWidget*)LineEditMesh)
+  {
     QString aString = "";
     LineEditMesh->setText(aString);
 
@@ -1149,6 +1168,9 @@ void SMESHGUI_MergeDlg::SelectionIntoArgument()
     myEntry = IO->getEntry();
     myMesh = SMESH::GetMeshByIO(IO);
 
+    if ( myEntry != aCurrentEntry && KeepList )
+      KeepList->clear();
+
     if (myMesh->_is_nil())
       return;
 
@@ -1158,16 +1180,16 @@ void SMESHGUI_MergeDlg::SelectionIntoArgument()
     if (!myActor)
       myActor = SMESH::FindActorByObject(myMesh);
 
-    if ( myActor && myTypeId == 1 && mySelector->IsSelectionEnabled() ) {
+    if ( myActor && myTypeId == TYPE_MANUAL && mySelector->IsSelectionEnabled() ) {
       mySubMeshOrGroup = SMESH::SMESH_IDSource::_nil();
       mySelectionMgr->installFilter(myMeshOrSubMeshOrGroupFilter);
-      
+
       if ((!SMESH::IObjectToInterface<SMESH::SMESH_subMesh>(IO)->_is_nil() || //SUBMESH OR GROUP
            !SMESH::IObjectToInterface<SMESH::SMESH_GroupBase>(IO)->_is_nil()) &&
           !SMESH::IObjectToInterface<SMESH::SMESH_IDSource>(IO)->_is_nil())
         mySubMeshOrGroup = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>(IO);
-      
-      if (myAction == 0) {
+
+      if (myAction == MERGE_NODES) {
         SMESH::SetPointRepresentation(true);
         if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
           aViewWindow->SetSelectionMode(NodeSelection);
@@ -1178,10 +1200,11 @@ void SMESHGUI_MergeDlg::SelectionIntoArgument()
     }
 
     // process groups
-    if ( myAction == 0 && !myMesh->_is_nil() && myEntry != aCurrentEntry ) {
+    if ( myAction == MERGE_NODES && !myMesh->_is_nil() && myEntry != aCurrentEntry ) {
       myGroups.clear();
       ListExclude->clear();
       SMESH::ListOfGroups_var aListOfGroups = myMesh->GetGroups();
+      GroupExclude->setEnabled( aListOfGroups->length() > 0 );
       for( int i = 0, n = aListOfGroups->length(); i < n; i++ ) {
         SMESH::SMESH_GroupBase_var aGroup = aListOfGroups[i];
         if ( !aGroup->_is_nil() ) { // && aGroup->GetType() == SMESH::NODE
@@ -1199,6 +1222,59 @@ void SMESHGUI_MergeDlg::SelectionIntoArgument()
 
     updateControls();
   }
+
+  else if (myEditCurrentArgument == (QWidget*)KeepList && KeepList)
+  {
+    AddKeepNodesButton->setEnabled( false );
+    RemoveKeepNodesButton->setEnabled( false );
+    if ( isKeepNodesIDsSelection() )
+    {
+      if (!myMesh->_is_nil() && !myActor)
+        myActor = SMESH::FindActorByObject(myMesh);
+
+      if ( mySelector && myActor )
+      {
+        KeepList->clearSelection();
+        QString anIDs = "";
+        int aNbNodes = SMESH::GetNameOfSelectedNodes(mySelector, myActor->getIO(), anIDs);
+        if (aNbNodes > 0)
+        {
+          QStringList anNodes = anIDs.split( " ", QString::SkipEmptyParts);
+          QList<QListWidgetItem*> listItemsToSel;
+          QListWidgetItem* anItem;
+          int nbFound = 0;
+          for (QStringList::iterator it = anNodes.begin(); it != anNodes.end(); ++it)
+          {
+            QList<QListWidgetItem*> found = KeepList->findItems(*it, Qt::MatchExactly);
+            foreach(anItem, found)
+              if (!anItem->isSelected())
+                listItemsToSel.push_back(anItem);
+            nbFound += found.count();
+          }
+          bool blocked = KeepList->signalsBlocked();
+          KeepList->blockSignals(true);
+          foreach(anItem, listItemsToSel) anItem->setSelected(true);
+          KeepList->blockSignals(blocked);
+          //onSelectKeepNode();
+          AddKeepNodesButton->setEnabled( nbFound < aNbNodes );
+          RemoveKeepNodesButton->setEnabled( nbFound > 0 );
+        }
+      }
+    }
+    else if ( !myMesh->_is_nil() )
+    {
+      SALOME_ListIO aList;
+      mySelectionMgr->selectedObjects(aList);
+      bool hasNewSelected = false;
+      SALOME_ListIteratorOfListIO anIt (aList);
+      for ( ; anIt.More() && !hasNewSelected; anIt.Next())
+        if ( anIt.Value()->hasEntry() )
+          hasNewSelected = isNewKeepNodesGroup( anIt.Value()->getEntry() );
+
+      AddKeepNodesButton->setEnabled( hasNewSelected );
+      //RemoveKeepNodesButton->setEnabled( KeepList->selectedItems().count() );
+    }
+  }
 }
 
 //=================================================================================
@@ -1207,13 +1283,17 @@ void SMESHGUI_MergeDlg::SelectionIntoArgument()
 //=================================================================================
 void SMESHGUI_MergeDlg::DeactivateActiveDialog()
 {
-  if (GroupConstructors->isEnabled()) {
-    GroupConstructors->setEnabled(false);
+  if (TypeBox->isEnabled()) {
     TypeBox->setEnabled(false);
     GroupMesh->setEnabled(false);
     GroupCoincident->setEnabled(false);
     GroupEdit->setEnabled(false);
     GroupButtons->setEnabled(false);
+    if (myAction == MERGE_NODES)
+    {
+      GroupExclude->setEnabled(false);
+      GroupKeep->setEnabled(false);
+    }
     mySMESHGUI->ResetState();
     mySMESHGUI->SetActiveDialogBox(0);
   }
@@ -1230,12 +1310,16 @@ void SMESHGUI_MergeDlg::ActivateThisDialog()
 {
   /* Emit a signal to deactivate the active dialog */
   mySMESHGUI->EmitSignalDeactivateDialog();
-  GroupConstructors->setEnabled(true);
   TypeBox->setEnabled(true);
   GroupMesh->setEnabled(true);
   GroupCoincident->setEnabled(true);
   GroupEdit->setEnabled(true);
   GroupButtons->setEnabled(true);
+  if (myAction == MERGE_NODES)
+  {
+    GroupExclude->setEnabled(false);
+    GroupKeep->setEnabled(false);
+  }
 
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
@@ -1246,10 +1330,15 @@ void SMESHGUI_MergeDlg::ActivateThisDialog()
 // function : enterEvent()
 // purpose  :
 //=================================================================================
-void SMESHGUI_MergeDlg::enterEvent(QEvent*)
+void SMESHGUI_MergeDlg::enterEvent (QEvent*)
 {
-  if (!GroupConstructors->isEnabled())
+  if ( !TypeBox->isEnabled() ) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector) {
+      mySelector = aViewWindow->GetSelector();
+    }
     ActivateThisDialog();
+  }
 }
 
 //=================================================================================
@@ -1280,20 +1369,22 @@ void SMESHGUI_MergeDlg::onTypeChanged (int id)
   myTypeId = id;
   switch (id)
   {
-  case 0: // automatic
+  case TYPE_AUTO: // automatic
+
     myIdPreview->SetPointsLabeled(false);
     SMESH::SetPointRepresentation(false);
     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
       aViewWindow->SetSelectionMode(ActorSelection);
     mySelectionMgr->clearFilters();
-    if (myAction == 0)
-      GroupCoincidentWidget->hide();
-    else
-      GroupCoincident->hide();
+    GroupCoincident->hide();
     GroupEdit->hide();
+
+    GroupMesh->hide(); // <--- a trick to make the dialog take a minimal size
+    GroupMesh->show();
     break;
 
-  case 1: // manual
+  case TYPE_MANUAL: // manual
+
     SMESH::UpdateView();
 
     // Costruction of the logical filter
@@ -1305,29 +1396,193 @@ void SMESHGUI_MergeDlg::onTypeChanged (int id)
     if (aSmeshGroupFilter)    aListOfFilters.append(aSmeshGroupFilter);
     
     myMeshOrSubMeshOrGroupFilter =
-      new SMESH_LogicalFilter (aListOfFilters, SMESH_LogicalFilter::LO_OR);
+      new SMESH_LogicalFilter (aListOfFilters, SMESH_LogicalFilter::LO_OR, true);
 
-    if (myAction == 0) {
-      GroupCoincidentWidget->show();
+    if (myAction == MERGE_NODES) {
       SMESH::SetPointRepresentation(true);
       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
         if( mySelector->IsSelectionEnabled() )
           aViewWindow->SetSelectionMode(NodeSelection);
     }
     else {
-      GroupCoincident->show();
       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
         if( mySelector->IsSelectionEnabled() )
           aViewWindow->SetSelectionMode(CellSelection);
     }
+    GroupCoincident->show();
     GroupEdit->show();
     break;
   }
+  SelectionIntoArgument();
+
   updateControls();
 
   qApp->processEvents();
   updateGeometry();
   resize(10,10);
+}
 
-  SelectionIntoArgument();
+//=======================================================================
+//function : isKeepNodesIDsSelection
+//purpose  : Return true of Nodes to keep are selected by IDs
+//=======================================================================
+
+bool SMESHGUI_MergeDlg::isKeepNodesIDsSelection()
+{
+  return KeepFromButGroup && KeepFromButGroup->checkedId() == 0;
+}
+
+//=======================================================================
+//function : isNewKeepNodesGroup
+//purpose  : Return true if an object with given entry is NOT present in KeepList
+//=======================================================================
+
+bool SMESHGUI_MergeDlg::isNewKeepNodesGroup( const char* entry )
+{
+  if ( !entry || isKeepNodesIDsSelection() )
+    return false;
+
+  for ( int i = 0; i < KeepList->count(); i++ )
+    if ( KeepList->item( i )->data( Qt::UserRole ).toString() == entry )
+      return false;
+
+  return true;
+}
+
+//=======================================================================
+//function : onAddKeepNode
+//purpose  : SLOT called when [Add] of Nodes To Keep group is pressed
+//=======================================================================
+
+void SMESHGUI_MergeDlg::onAddKeepNode()
+{
+  if ( myIsBusy )
+    return;
+  myIsBusy = true;
+
+  if ( isKeepNodesIDsSelection() )
+  {
+    //KeepList->clearSelection();
+    QString anIDs = "";
+    int aNbNodes = 0;
+    if ( myActor )
+      aNbNodes = SMESH::GetNameOfSelectedNodes(mySelector, myActor->getIO(), anIDs);
+    if (aNbNodes > 0)
+    {
+      QStringList anNodes = anIDs.split( " ", QString::SkipEmptyParts);
+      QList<QListWidgetItem*> listItemsToSel;
+      QListWidgetItem* anItem;
+      for (QStringList::iterator it = anNodes.begin(); it != anNodes.end(); ++it)
+      {
+        QList<QListWidgetItem*> found = KeepList->findItems(*it, Qt::MatchExactly);
+        if (found.count() == 0) {
+          anItem = new QListWidgetItem(*it);
+          KeepList->addItem(anItem);
+          if (!anItem->isSelected())
+            listItemsToSel.push_back(anItem);
+        }
+        else {
+          foreach(anItem, found)
+            if (!anItem->isSelected())
+              listItemsToSel.push_back(anItem);
+        }
+      }
+      bool blocked = KeepList->signalsBlocked();
+      KeepList->blockSignals(true);
+      foreach(anItem, listItemsToSel) anItem->setSelected(true);
+      KeepList->blockSignals(blocked);
+      //onSelectKeepNode();
+    }
+    RemoveKeepNodesButton->setEnabled( aNbNodes > 0 );
+  }
+  else
+  {
+    SALOME_ListIO aList;
+    mySelectionMgr->selectedObjects(aList);
+    SALOME_ListIteratorOfListIO anIt (aList);
+    for ( ; anIt.More(); anIt.Next()) {
+      Handle(SALOME_InteractiveObject) anIO = anIt.Value();
+      if ( isNewKeepNodesGroup( anIO->getEntry() ))
+      {
+        QListWidgetItem* anItem = new QListWidgetItem( anIO->getName() );
+        anItem->setData( Qt::UserRole, QString( anIO->getEntry() ));
+        KeepList->addItem(anItem);
+      }
+    }
+    //RemoveKeepNodesButton->setEnabled( KeepList->selectedItems().count() );
+  }
+
+  AddKeepNodesButton->setEnabled( false );
+
+  myIsBusy = false;
+}
+
+//=======================================================================
+//function : onRemoveKeepNode
+//purpose  : SLOT called when [Remove] of Nodes To Keep group is pressed
+//=======================================================================
+
+void SMESHGUI_MergeDlg::onRemoveKeepNode()
+{
+  // if ( isKeepNodesIDsSelection() )
+  // {
+  // }
+  // else
+  {
+    QList<QListWidgetItem*> selItems = KeepList->selectedItems();
+    QListWidgetItem* item;
+    foreach(item, selItems) delete item;
+  }
+  if ( isKeepNodesIDsSelection() )
+  {
+    AddKeepNodesButton->setEnabled( false );
+  }
+  RemoveKeepNodesButton->setEnabled( false );
+}
+
+//=======================================================================
+//function : onSelectKeepNode
+//purpose  : SLOT called when selection in KeepList changes
+//=======================================================================
+
+void SMESHGUI_MergeDlg::onSelectKeepNode()
+{
+  if ( myIsBusy || !isEnabled() ) return;
+  myIsBusy = true;
+
+  if ( isKeepNodesIDsSelection() )
+  {
+    if ( myActor )
+    {
+      mySelectionMgr->clearSelected();
+      TColStd_MapOfInteger aIndexes;
+      QList<QListWidgetItem*> selItems = KeepList->selectedItems();
+      QListWidgetItem* anItem;
+      foreach(anItem, selItems) aIndexes.Add(anItem->text().toInt());
+      mySelector->AddOrRemoveIndex(myActor->getIO(), aIndexes, false);
+      SALOME_ListIO aList;
+      aList.Append(myActor->getIO());
+      mySelectionMgr->setSelectedObjects(aList,false);
+
+      AddKeepNodesButton->setEnabled( false );
+      RemoveKeepNodesButton->setEnabled( aIndexes.Extent() > 0 );
+    }
+  }
+  else
+  {
+    RemoveKeepNodesButton->setEnabled( KeepList->selectedItems().count() );
+  }
+  myIsBusy = false;
+}
+
+//=======================================================================
+//function : onKeepNodeSourceChanged
+//purpose  : SLOT called when type of source of Nodes To Keep change from
+//           IDs to groups or vice versa
+//=======================================================================
+
+void SMESHGUI_MergeDlg::onKeepNodeSourceChanged(int isGroup)
+{
+  KeepList->clear();
+  SelectKeepNodesButton->click();
 }
index 1e5ad080d65845bbe84ce1ef2223d9a545d444b4..86595b82a1295d217d3c22220855feaff6966215 100644 (file)
 
 // STL includes
 #include <list>
+#include <vector>
 
 // IDL includes
 #include <SALOMEconfig.h>
 #include CORBA_SERVER_HEADER(SMESH_Mesh)
 
+class LightApp_SelectionMgr;
+class QButtonGroup;
+class QCheckBox;
 class QGroupBox;
 class QLabel;
 class QLineEdit;
+class QListWidget;
 class QPushButton;
 class QRadioButton;
-class QCheckBox;
-class QListWidget;
-class QButtonGroup;
 class SMESHGUI;
+class SMESHGUI_IdPreview;
 class SMESHGUI_SpinBox;
 class SMESH_Actor;
-class SVTK_Selector;
-class LightApp_SelectionMgr;
 class SUIT_SelectionFilter;
+class SVTK_Selector;
 class TColStd_MapOfInteger;
 
 namespace SMESH
@@ -76,13 +78,18 @@ public:
   SMESHGUI_MergeDlg( SMESHGUI*, int );
   ~SMESHGUI_MergeDlg();
 
+  static QPixmap IconFirst();
+
 private:
   void                      Init();
   void                      enterEvent( QEvent* );              /* mouse enter the QWidget */
   void                      keyPressEvent( QKeyEvent* );
   void                      onEditGroup();
+  bool                      isKeepNodesIDsSelection();
+  bool                      isNewKeepNodesGroup( const char* entry );
 
-  void                      FindGravityCenter( TColStd_MapOfInteger&, 
+  void                      FindGravityCenter( TColStd_MapOfInteger&,
+                                               std::vector<int>& , 
                                                std::list<gp_XYZ>& );
   // add the centers of gravity of ElemsIdMap elements to the GrCentersXYZ list
 
@@ -99,16 +106,15 @@ private:
   SMESH::SMESH_IDSource_var mySubMeshOrGroup;
   SMESH_Actor*              myActor;
   SUIT_SelectionFilter*     myMeshOrSubMeshOrGroupFilter;
+  SUIT_SelectionFilter*     mySubMeshOrGroupFilter;
 
-  SMESH::TIdPreview*        myIdPreview;
+  SMESHGUI_IdPreview*       myIdPreview;
 
   int                       myAction;
   bool                      myIsBusy;
-  int                       myTypeId;
+  int                       myTypeId; // manual(1) or automatic(0)
 
   // Widgets
-  QGroupBox*                GroupConstructors;
-  QRadioButton*             RadioButton;
 
   QGroupBox*                GroupButtons;
   QPushButton*              buttonOk;
@@ -121,10 +127,12 @@ private:
   QPushButton*              SelectMeshButton;
   QLineEdit*                LineEditMesh;
 
-  QGroupBox*                GroupCoincident;
-  QWidget*                  GroupCoincidentWidget;
-  QLabel*                   TextLabelTolerance;
+  QWidget*                  NodeSpecWidget;
   SMESHGUI_SpinBox*         SpinBoxTolerance;
+  QCheckBox*                SeparateCornersAndMedium;
+
+  QGroupBox*                GroupCoincident;
+  //QWidget*                  GroupCoincidentWidget;
   QPushButton*              DetectButton;
   QListWidget*              ListCoincident;
   QPushButton*              AddGroupButton;
@@ -141,6 +149,13 @@ private:
   QGroupBox*                GroupExclude;
   QListWidget*              ListExclude;
 
+  QGroupBox*                GroupKeep;
+  QButtonGroup*             KeepFromButGroup;
+  QPushButton*              SelectKeepNodesButton;
+  QPushButton*              AddKeepNodesButton;
+  QPushButton*              RemoveKeepNodesButton;
+  QListWidget*              KeepList;
+
   QGroupBox*                TypeBox;
   QButtonGroup*             GroupType;
     
@@ -158,6 +173,10 @@ protected slots:
   void                      ClickOnHelp();
   void                      updateControls();
   void                      onDetect();
+  void                      onAddKeepNode();
+  void                      onRemoveKeepNode();
+  void                      onSelectKeepNode();
+  void                      onKeepNodeSourceChanged(int);
   void                      onAddGroup();
   void                      onRemoveGroup();
   void                      onSelectGroup();
@@ -171,6 +190,8 @@ protected slots:
   void                      DeactivateActiveDialog();
   void                      ActivateThisDialog();
   void                      onTypeChanged(int);
+  void                      onOpenView();
+  void                      onCloseView();
 };
 
 #endif // SMESHGUI_MergeDlg_H
index 1cc3df96a30de8497c48b9dda8fc9c0547e2b74d..6fb07fb4fa16e5da7914cfcfa1a2c6da541a2acc 100644 (file)
@@ -231,9 +231,11 @@ SMESHGUI_MeshInfo::SMESHGUI_MeshInfo( QWidget* parent )
   // object
   QLabel* aNameLab     = new QLabel( tr( "NAME_LAB" ), this );
   QLabel* aName        = createField();
+  aName->setObjectName("meshName");
   aName->setMinimumWidth( 150 );
   QLabel* aObjLab      = new QLabel( tr( "OBJECT_LAB" ), this );
   QLabel* aObj         = createField();
+  aObj->setObjectName("meshType");
   aObj->setMinimumWidth( 150 );
   myWidgets[ index++ ] << aNameLab << aName;
   myWidgets[ index++ ] << aObjLab  << aObj;
@@ -242,6 +244,7 @@ SMESHGUI_MeshInfo::SMESHGUI_MeshInfo( QWidget* parent )
   QWidget* aNodesLine  = createLine();
   QLabel*  aNodesLab   = new QLabel( tr( "NODES_LAB" ), this );
   QLabel*  aNodes      = createField();
+  aNodes->setObjectName("nbNodes");
   myWidgets[ index++ ] << aNodesLine;
   myWidgets[ index++ ] << aNodesLab << aNodes;
 
@@ -258,9 +261,13 @@ SMESHGUI_MeshInfo::SMESHGUI_MeshInfo( QWidget* parent )
   // ... Number elements
   QWidget* aNbLine     = createLine(); 
   QLabel*  aNbTotal    = createField();
+  aNbTotal->setObjectName("totalNbElems");
   QLabel*  aNbLin      = createField();
+  aNbLin->setObjectName("totalNbLinearElems");
   QLabel*  aNbQuad     = createField();
+  aNbQuad->setObjectName("totalNbQuadraticElems");
   QLabel*  aNbBiQuad   = createField();
+  aNbBiQuad->setObjectName("totalNbBiQuadraticElems");
   myWidgets[ index++ ] << aNbLine;
   myWidgets[ index++ ] << new QLabel( "", this ) << aNbTotal << aNbLin << aNbQuad << aNbBiQuad;
 
@@ -268,6 +275,8 @@ SMESHGUI_MeshInfo::SMESHGUI_MeshInfo( QWidget* parent )
   QWidget* a0DLine     = createLine();
   QLabel*  a0DLab      = new QLabel( tr( "0D_LAB" ), this );
   QLabel*  a0DTotal    = createField();
+  a0DTotal->setObjectName("nb0D");
+
   myWidgets[ index++ ] << a0DLine;
   myWidgets[ index++ ] << a0DLab << a0DTotal;
 
@@ -275,6 +284,7 @@ SMESHGUI_MeshInfo::SMESHGUI_MeshInfo( QWidget* parent )
   QWidget* aBallLine     = createLine();
   QLabel*  aBallLab      = new QLabel( tr( "BALL_LAB" ), this );
   QLabel*  aBallTotal    = createField();
+  aBallTotal->setObjectName("nbBall");
   myWidgets[ index++ ] << aBallLine;
   myWidgets[ index++ ] << aBallLab << aBallTotal;
 
@@ -282,8 +292,11 @@ SMESHGUI_MeshInfo::SMESHGUI_MeshInfo( QWidget* parent )
   QWidget* a1DLine     = createLine();
   QLabel*  a1DLab      = new QLabel( tr( "1D_LAB" ), this );
   QLabel*  a1DTotal    = createField();
+  a1DTotal->setObjectName("nb1D");
   QLabel*  a1DLin      = createField();
+  a1DLin->setObjectName("nbLinear1D");
   QLabel*  a1DQuad     = createField();
+  a1DQuad->setObjectName("nbQuadratic1D");
   myWidgets[ index++ ] << a1DLine;
   myWidgets[ index++ ] << a1DLab << a1DTotal << a1DLin << a1DQuad;
 
@@ -291,55 +304,91 @@ SMESHGUI_MeshInfo::SMESHGUI_MeshInfo( QWidget* parent )
   QWidget* a2DLine      = createLine();
   QLabel*  a2DLab       = new QLabel( tr( "2D_LAB" ), this );
   QLabel*  a2DTotal     = createField();
+  a2DTotal->setObjectName("nb2D");
   QLabel*  a2DLin       = createField();
+  a2DLin->setObjectName("nbLinear2D");
   QLabel*  a2DQuad      = createField();
+  a2DQuad->setObjectName("nbQuadratic2D");
   QLabel*  a2DBiQuad    = createField();
+  a2DBiQuad->setObjectName("nbBiQuadratic2D");
   QLabel*  a2DTriLab    = new QLabel( tr( "TRIANGLES_LAB" ), this );
   QLabel*  a2DTriTotal  = createField();
+  a2DTriTotal->setObjectName("nbTriangle");
   QLabel*  a2DTriLin    = createField();
+  a2DTriLin->setObjectName("nbLinearTriangle");
   QLabel*  a2DTriQuad   = createField();
+  a2DTriQuad->setObjectName("nbQuadraticTriangle");
   QLabel*  a2DTriBiQuad = createField();
+    a2DTriBiQuad->setObjectName("nbBiQuadraticTriangle");
   QLabel*  a2DQuaLab    = new QLabel( tr( "QUADRANGLES_LAB" ), this );
   QLabel*  a2DQuaTotal  = createField();
+  a2DQuaTotal->setObjectName("nbQuadrangle");
   QLabel*  a2DQuaLin    = createField();
+  a2DQuaLin->setObjectName("nbLinearQuadrangle");
   QLabel*  a2DQuaQuad   = createField();
+  a2DQuaQuad->setObjectName("nbQuadraticQuadrangle");
   QLabel*  a2DQuaBiQuad = createField();
+  a2DQuaBiQuad->setObjectName("nbBiQuadraticQuadrangle");
   QLabel*  a2DPolLab    = new QLabel( tr( "POLYGONS_LAB" ), this );
   QLabel*  a2DPolTotal  = createField();
+  a2DPolTotal->setObjectName("nbPolygon");
+  QLabel*  a2DPolLin    = createField();
+  a2DPolLin->setObjectName("nbLinearPolygon");
+  QLabel*  a2DPolQuad   = createField();
+  a2DPolQuad->setObjectName("nbQuadraticPolygon");
   myWidgets[ index++ ] << a2DLine;
   myWidgets[ index++ ] << a2DLab    << a2DTotal    << a2DLin    << a2DQuad    << a2DBiQuad;
   myWidgets[ index++ ] << a2DTriLab << a2DTriTotal << a2DTriLin << a2DTriQuad << a2DTriBiQuad;
   myWidgets[ index++ ] << a2DQuaLab << a2DQuaTotal << a2DQuaLin << a2DQuaQuad << a2DQuaBiQuad;
-  myWidgets[ index++ ] << a2DPolLab << a2DPolTotal;
+  myWidgets[ index++ ] << a2DPolLab << a2DPolTotal << a2DPolLin << a2DPolQuad;
 
   // ... 3D elements
   QWidget* a3DLine      = createLine();
   QLabel*  a3DLab       = new QLabel( tr( "3D_LAB" ), this );
   QLabel*  a3DTotal     = createField();
+  a3DTotal->setObjectName("nb3D");
   QLabel*  a3DLin       = createField();
+  a3DLin->setObjectName("nbLinear3D");
   QLabel*  a3DQuad      = createField();
+  a3DQuad->setObjectName("nbQuadratic3D");
   QLabel*  a3DBiQuad    = createField();
+  a3DBiQuad->setObjectName("nbBiQuadratic3D");
   QLabel*  a3DTetLab    = new QLabel( tr( "TETRAHEDRONS_LAB" ), this );
   QLabel*  a3DTetTotal  = createField();
+  a3DTetTotal->setObjectName("nbTetrahedron");
   QLabel*  a3DTetLin    = createField();
+  a3DTetLin->setObjectName("nbLinearTetrahedron");
   QLabel*  a3DTetQuad   = createField();
+  a3DTetQuad->setObjectName("nbQudraticTetrahedron");
   QLabel*  a3DHexLab    = new QLabel( tr( "HEXAHEDONRS_LAB" ), this );
   QLabel*  a3DHexTotal  = createField();
+  a3DHexTotal->setObjectName("nbHexahedron");
   QLabel*  a3DHexLin    = createField();
+  a3DHexLin->setObjectName("nbLinearHexahedron");
   QLabel*  a3DHexQuad   = createField();
+  a3DHexQuad->setObjectName("nbQuadraticHexahedron");
   QLabel*  a3DHexBiQuad = createField();
+  a3DHexBiQuad->setObjectName("nbBiQuadraticHexahedron");
   QLabel*  a3DPyrLab    = new QLabel( tr( "PYRAMIDS_LAB" ), this );
   QLabel*  a3DPyrTotal  = createField();
+  a3DPyrTotal->setObjectName("nbPyramid");
   QLabel*  a3DPyrLin    = createField();
+  a3DPyrLin->setObjectName("nbLinearPyramid");
   QLabel*  a3DPyrQuad   = createField();
+  a3DPyrQuad->setObjectName("nbQuadraticPyramid");
   QLabel*  a3DPriLab    = new QLabel( tr( "PRISMS_LAB" ), this );
   QLabel*  a3DPriTotal  = createField();
+  a3DPriTotal->setObjectName("nbPrism");
   QLabel*  a3DPriLin    = createField();
+  a3DPriLin->setObjectName("nbLinearPrism");
   QLabel*  a3DPriQuad   = createField();
+  a3DPriQuad->setObjectName("nbQuadraticPrism");
   QLabel*  a3DHexPriLab   = new QLabel( tr( "HEX_PRISMS_LAB" ), this );
   QLabel*  a3DHexPriTotal = createField();
+  a3DHexPriTotal->setObjectName("nbHexagonalPrism");
   QLabel*  a3DPolLab    = new QLabel( tr( "POLYHEDRONS_LAB" ), this );
   QLabel*  a3DPolTotal  = createField();
+  a3DPolTotal->setObjectName("nbPolyhedron");
   myWidgets[ index++ ] << a3DLine;
   myWidgets[ index++ ] << a3DLab    << a3DTotal    << a3DLin    << a3DQuad    << a3DBiQuad;
   myWidgets[ index++ ] << a3DTetLab << a3DTetTotal << a3DTetLin << a3DTetQuad;
@@ -414,6 +463,8 @@ SMESHGUI_MeshInfo::SMESHGUI_MeshInfo( QWidget* parent )
   l->addWidget( a2DQuaBiQuad, 17, 4 );
   l->addWidget( a2DPolLab,    18, 0 );
   l->addWidget( a2DPolTotal,  18, 1 );
+  l->addWidget( a2DPolLin,    18, 2 );
+  l->addWidget( a2DPolQuad,   18, 3 );
   l->addWidget( a3DLine,      19, 1, 1, 4 );
   l->addWidget( a3DLab,       20, 0 );
   l->addWidget( a3DTotal,     20, 1 );
@@ -503,8 +554,9 @@ void SMESHGUI_MeshInfo::showInfo( SMESH::SMESH_IDSource_ptr obj )
     myWidgets[i1D][iQuadratic]->setProperty( "text", QString::number( info[SMDSEntity_Quad_Edge] ) );
     long nbTriangles     = info[SMDSEntity_Triangle]   + info[SMDSEntity_Quad_Triangle]   + info[SMDSEntity_BiQuad_Triangle];
     long nbQuadrangles   = info[SMDSEntity_Quadrangle] + info[SMDSEntity_Quad_Quadrangle] + info[SMDSEntity_BiQuad_Quadrangle];
+    long nb2DPolygons    = info[SMDSEntity_Polygon]    + info[SMDSEntity_Quad_Polygon];
     long nb2DLinear      = info[SMDSEntity_Triangle]        + info[SMDSEntity_Quadrangle] + info[SMDSEntity_Polygon];
-    long nb2DQuadratic   = info[SMDSEntity_Quad_Triangle]   + info[SMDSEntity_Quad_Quadrangle];
+    long nb2DQuadratic   = info[SMDSEntity_Quad_Triangle]   + info[SMDSEntity_Quad_Quadrangle] + info[SMDSEntity_Quad_Polygon];
     long nb2DBiQuadratic = info[SMDSEntity_BiQuad_Triangle] + info[SMDSEntity_BiQuad_Quadrangle];
     long nb2DTotal       = nb2DLinear + nb2DQuadratic + nb2DBiQuadratic;
 
@@ -520,7 +572,9 @@ void SMESHGUI_MeshInfo::showInfo( SMESH::SMESH_IDSource_ptr obj )
     myWidgets[i2DQuadrangles][iLinear]      ->setProperty( "text", QString::number( info[SMDSEntity_Quadrangle] ) );
     myWidgets[i2DQuadrangles][iQuadratic]   ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Quadrangle] ) );
     myWidgets[i2DQuadrangles][iBiQuadratic] ->setProperty( "text", QString::number( info[SMDSEntity_BiQuad_Quadrangle] ) );
-    myWidgets[i2DPolygons][iTotal]          ->setProperty( "text", QString::number( info[SMDSEntity_Polygon] ) );
+    myWidgets[i2DPolygons][iTotal]          ->setProperty( "text", QString::number( nb2DPolygons ));
+    myWidgets[i2DPolygons][iLinear]         ->setProperty( "text", QString::number( info[SMDSEntity_Polygon] ) );
+    myWidgets[i2DPolygons][iQuadratic]      ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Polygon] ) );
     long nbTetrahedrons  = info[SMDSEntity_Tetra]   + info[SMDSEntity_Quad_Tetra];
     long nbHexahedrons   = info[SMDSEntity_Hexa]    + info[SMDSEntity_Quad_Hexa] + info[SMDSEntity_TriQuad_Hexa];
     long nbPyramids      = info[SMDSEntity_Pyramid] + info[SMDSEntity_Quad_Pyramid];
@@ -583,6 +637,8 @@ void SMESHGUI_MeshInfo::showInfo( SMESH::SMESH_IDSource_ptr obj )
           myWidgets[i2DQuadrangles][iLinear]      ->setProperty( "text", "?" );
           myWidgets[i2DQuadrangles][iQuadratic]   ->setProperty( "text", "?" );
           myWidgets[i2DQuadrangles][iBiQuadratic] ->setProperty( "text", "?" );
+          myWidgets[i2DPolygons][iLinear]         ->setProperty( "text", "?" );
+          myWidgets[i2DPolygons][iQuadratic]      ->setProperty( "text", "?" );
           myWidgets[i2DPolygons][iTotal]          ->setProperty( "text", "?" );
           myWidgets[iNb][iTotal]                  ->setProperty( "text", "?" );
           myWidgets[iNb][iLinear]                 ->setProperty( "text", "?" );
@@ -712,6 +768,8 @@ void SMESHGUI_MeshInfo::clear()
   myWidgets[i2DQuadrangles][iLinear]      ->setProperty( "text", QString::number( 0 ) );
   myWidgets[i2DQuadrangles][iQuadratic]   ->setProperty( "text", QString::number( 0 ) );
   myWidgets[i2DQuadrangles][iBiQuadratic] ->setProperty( "text", QString::number( 0 ) );
+  myWidgets[i2DPolygons][iLinear]         ->setProperty( "text", QString::number( 0 ) );
+  myWidgets[i2DPolygons][iQuadratic]      ->setProperty( "text", QString::number( 0 ) );
   myWidgets[i2DPolygons][iTotal]          ->setProperty( "text", QString::number( 0 ) );
   myWidgets[i3D][iTotal]                  ->setProperty( "text", QString::number( 0 ) );
   myWidgets[i3D][iLinear]                 ->setProperty( "text", QString::number( 0 ) );
@@ -836,6 +894,8 @@ void SMESHGUI_MeshInfo::saveInfo( QTextStream &out )
   out << QString( SPACING_INFO*3, ' ' ) << tr( "BI_QUADRATIC_LAB" ) << ": " << ( myWidgets[i2DQuadrangles][iBiQuadratic]->property( "text" ) ).toString() << "\n";
   out << QString( SPACING_INFO*2, ' ' ) << tr( "POLYGONS_LAB" )     << "\n";
   out << QString( SPACING_INFO*3, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i2DPolygons][iTotal]->property( "text" ) ).toString() << "\n";
+  out << QString( SPACING_INFO*3, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i2DPolygons][iLinear]->property( "text" ) ).toString() << "\n";
+  out << QString( SPACING_INFO*3, ' ' ) << tr( "QUADRATIC_LAB" )    << ": " << ( myWidgets[i2DPolygons][iQuadratic]->property( "text" ) ).toString() << "\n";
   out << QString( SPACING_INFO,   ' ' ) << tr( "3D_LAB" )           << "\n";
   out << QString( SPACING_INFO*2, ' ' ) << tr( "TOTAL_LAB" )        << ": " << ( myWidgets[i3D][iTotal]->property( "text" ) ).toString() << "\n";
   out << QString( SPACING_INFO*2, ' ' ) << tr( "LINEAR_LAB" )       << ": " << ( myWidgets[i3D][iLinear]->property( "text" ) ).toString() << "\n";
@@ -2245,8 +2305,11 @@ void SMESHGUI_TreeElemInfo::saveInfo( QTextStream &out )
 /*!
   \brief Contructor
 */
-GrpComputor::GrpComputor( SMESH::SMESH_GroupBase_ptr grp, QTreeWidgetItem* item, QObject* parent )
-  : QObject( parent ), myItem( item )
+GrpComputor::GrpComputor( SMESH::SMESH_GroupBase_ptr grp,
+                          QTreeWidgetItem*           item,
+                          QObject*                   parent,
+                          bool                       toComputeSize)
+  : QObject( parent ), myItem( item ), myToComputeSize( toComputeSize )
 {
   myGroup = SMESH::SMESH_GroupBase::_narrow( grp );
 }
@@ -2259,9 +2322,9 @@ void GrpComputor::compute()
   if ( !CORBA::is_nil( myGroup ) && myItem ) {
     QTreeWidgetItem* item = myItem;
     myItem = 0;
-    int nbNodes = myGroup->GetNumberOfNodes();
+    int nb = myToComputeSize ? myGroup->Size() : myGroup->GetNumberOfNodes();
     item->treeWidget()->removeItemWidget( item, 1 );
-    item->setText( 1, QString::number( nbNodes ));
+    item->setText( 1, QString::number( nb ));
   }
 }
 
@@ -2493,10 +2556,28 @@ void SMESHGUI_AddInfo::groupInfo( SMESH::SMESH_GroupBase_ptr grp, QTreeWidgetIte
     etypeItem->setText( 1, etype );
   }
 
-  // size
+  SMESH::SMESH_Mesh_var mesh = grp->GetMesh();
+  bool            meshLoaded = mesh->IsLoaded();
+
+  // size. Don't call grp->Size() for GroupOnFilter - issue IPAL52831
+  int groupSize = -1;
+  if ( grp->IsNodeInfoAvailable() || CORBA::is_nil( aFltGroup ))
+    groupSize = grp->Size();
+
   QTreeWidgetItem* sizeItem = createItem( parent, Bold );
   sizeItem->setText( 0, tr( "SIZE" ) );
-  sizeItem->setText( 1, QString::number( grp->Size() ) );
+  if ( groupSize > -1 ) {
+    sizeItem->setText( 1, QString::number( groupSize ) );
+  }
+  else {
+    QPushButton* btn = new QPushButton( tr( meshLoaded ? "COMPUTE" : "LOAD"), this );
+    setItemWidget( sizeItem, 1, btn );
+    GrpComputor* comp = new GrpComputor( grp, sizeItem, this, /*size=*/true );
+    connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
+    myComputors.append( comp );
+    if ( !meshLoaded )
+      connect( btn, SIGNAL( clicked() ), this, SLOT( changeLoadToCompute() ) );
+  }
 
   // color
   SALOMEDS::Color color = grp->GetColor();
@@ -2509,9 +2590,7 @@ void SMESHGUI_AddInfo::groupInfo( SMESH::SMESH_GroupBase_ptr grp, QTreeWidgetIte
     QTreeWidgetItem* nodesItem = createItem( parent, Bold );
     nodesItem->setText( 0, tr( "NB_NODES" ) );
     int nbNodesLimit = SMESHGUI::resourceMgr()->integerValue( "SMESH", "info_groups_nodes_limit", 100000 );
-    SMESH::SMESH_Mesh_var mesh = grp->GetMesh();
-    bool meshLoaded = mesh->IsLoaded();
-    bool toShowNodes = ( grp->IsNodeInfoAvailable() || nbNodesLimit <= 0 || grp->Size() <= nbNodesLimit );
+    bool toShowNodes = groupSize >= 0 ? ( grp->IsNodeInfoAvailable() || nbNodesLimit <= 0 || groupSize <= nbNodesLimit ) : false;
     if ( toShowNodes && meshLoaded ) {
       // already calculated and up-to-date
       nodesItem->setText( 1, QString::number( grp->GetNumberOfNodes() ) );
@@ -2833,8 +2912,8 @@ void SMESHGUI_MeshInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& IO
 {
   SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( IO );
   if ( !CORBA::is_nil( obj ) ) {
-    myBaseInfo->showInfo( obj );
-    myAddInfo->showInfo( obj );
+    myAddInfo->showInfo( obj );  // nb of nodes in a group can be computed by myAddInfo,
+    myBaseInfo->showInfo( obj ); // and it will be used by myBaseInfo (IPAL52871)
     myCtrlInfo->showInfo( obj );
 
     myActor = SMESH::FindActorByEntry( IO->getEntry() );
@@ -3414,6 +3493,11 @@ void SMESHGUI_CtrlInfo::showInfo( SMESH::SMESH_IDSource_ptr obj )
       myButtons[4]->setEnabled( true );
       myButtons[5]->setEnabled( true );
     }
+#ifdef DISABLE_PLOT2DVIEWER
+    myMainLayout->setRowStretch(11,0);
+    for( int i=22; i<=24; i++)
+      myMainLayout->itemAt(i)->widget()->setVisible( false );
+#endif
   }
   else {
     myMainLayout->setRowStretch(11,0);
@@ -3436,6 +3520,11 @@ void SMESHGUI_CtrlInfo::showInfo( SMESH::SMESH_IDSource_ptr obj )
        myButtons[7]->setEnabled( true );
        myButtons[8]->setEnabled( true );
      }
+#ifdef DISABLE_PLOT2DVIEWER
+    myMainLayout->setRowStretch(16,0);
+    for( int i=32; i<=34; i++)
+      myMainLayout->itemAt(i)->widget()->setVisible( false );
+#endif
   }
   else {
     myMainLayout->setRowStretch(16,0);
@@ -3515,6 +3604,7 @@ void SMESHGUI_CtrlInfo::computeOverConstrainedVolumesInfo()
 
 void SMESHGUI_CtrlInfo::computeAspectRatio()
 {
+#ifndef DISABLE_PLOT2DVIEWER
   myButtons[5]->setEnabled( false );
 
   if ( myObject->_is_nil() ) return;
@@ -3528,10 +3618,12 @@ void SMESHGUI_CtrlInfo::computeAspectRatio()
     myPlot->replot();
   }
   delete aHistogram;
+#endif
 }
 
 void SMESHGUI_CtrlInfo::computeAspectRatio3D()
 {
+#ifndef DISABLE_PLOT2DVIEWER
   myButtons[8]->setEnabled( false );
 
   if ( myObject->_is_nil() ) return;
@@ -3545,6 +3637,7 @@ void SMESHGUI_CtrlInfo::computeAspectRatio3D()
     myPlot3D->replot();
   }
   delete aHistogram;
+#endif
 }
 
 /*!
@@ -3574,6 +3667,7 @@ void SMESHGUI_CtrlInfo::setTolerance( double theTolerance )
   myWidgets[2]->setText("");
 }
 
+#ifndef DISABLE_PLOT2DVIEWER
 Plot2d_Histogram* SMESHGUI_CtrlInfo::getHistogram( SMESH::NumericalFunctor_ptr aNumFun )
 {
   SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
@@ -3603,6 +3697,7 @@ Plot2d_Histogram* SMESHGUI_CtrlInfo::getHistogram( SMESH::NumericalFunctor_ptr a
   }
   return aHistogram;
 }
+#endif
 
 void SMESHGUI_CtrlInfo::saveInfo( QTextStream &out ) {
   out << QString( 20, '-' ) << "\n";
index 5b00585aa01044b362cb09fd4694cef055d70055..f06db38d25970f98f15e0f82723fd91571869cc7 100644 (file)
 #include "SMESH_SMESHGUI.hxx"
 #include "SMESH_ControlsDef.hxx"
 
-#include <Plot2d_Histogram.h>
+#ifndef DISABLE_PLOT2DVIEWER
+  #include <Plot2d_Histogram.h>
+#else
+  #include <qwt_plot.h>
+#endif
 
 #include <QFrame>
 #include <QDialog>
@@ -246,7 +250,7 @@ class GrpComputor: public QObject
   Q_OBJECT;
 
 public:
-  GrpComputor( SMESH::SMESH_GroupBase_ptr, QTreeWidgetItem*, QObject* );
+  GrpComputor( SMESH::SMESH_GroupBase_ptr, QTreeWidgetItem*, QObject*, bool = false);
   QTreeWidgetItem* getItem() { return myItem; }
 
 public slots:
@@ -255,6 +259,7 @@ public slots:
 private:
   SMESH::SMESH_GroupBase_var myGroup;
   QTreeWidgetItem*           myItem;
+  bool                       myToComputeSize;
 };
 
 class SMESHGUI_EXPORT SMESHGUI_AddInfo : public QTreeWidget
@@ -310,7 +315,9 @@ private:
   QwtPlot*              createPlot( QWidget* );
   void                  setFontAttributes( QWidget* );
   void                  clearInternal();
+#ifndef DISABLE_PLOT2DVIEWER
   Plot2d_Histogram*     getHistogram( SMESH::NumericalFunctor_ptr functor );
+#endif
   void                  computeNb( int ft, int iBut, int iWdg );
 
 private slots:
index 0a0ad9973c96847c6aca3e759f5554dba5760ff5..71590dc9687377fe224e8b064d0c0d83d5d2364c 100644 (file)
@@ -66,7 +66,7 @@ SMESHGUI_MeshInfosBox::SMESHGUI_MeshInfosBox(const bool full, QWidget* theParent
   myNbTrai(0), myNbLinTrai(0), myNbQuadTrai(0), myNbBiQuadTrai(0),
   myNbQuad(0), myNbLinQuad(0), myNbQuadQuad(0), myNbBiQuadQuad(0),
   myNbFace(0), myNbLinFace(0), myNbQuadFace(0), myNbBiQuadFace(0),
-  myNbPolyg(0),
+  myNbPolyg(0), myNbQuadPolyg(0),
   myNbHexa(0), myNbLinHexa(0), myNbQuadHexa(0), myNbBiQuadHexa(0),
   myNbTetra(0),myNbLinTetra(0),myNbQuadTetra(0),
   myNbPyra(0), myNbLinPyra(0), myNbQuadPyra(0),
@@ -219,8 +219,15 @@ SMESHGUI_MeshInfosBox::SMESHGUI_MeshInfosBox(const bool full, QWidget* theParent
     // ... poligones
     lab = new QLabel(COLONIZE(tr("SMESH_MESHINFO_POLYGONES")), this );
     l->addWidget( lab,           row, 0 );
+    // --
     myNbPolyg    = new QLabel( this );
     l->addWidget( myNbPolyg,     row, 1 );
+    // --
+    myNbLinPolyg = new QLabel( this );
+    l->addWidget( myNbLinPolyg,    row, 2 );
+    // --
+    myNbQuadPolyg = new QLabel( this );
+    l->addWidget( myNbQuadPolyg,   row, 3 );
 
     addSeparator(this);          // add separator
 
@@ -432,12 +439,14 @@ void SMESHGUI_MeshInfosBox::SetMeshInfo(const SMESH::long_array& theInfo)
                                                theInfo[SMDSEntity_Quadrangle] +
                                                theInfo[SMDSEntity_Quad_Quadrangle] +
                                                theInfo[SMDSEntity_BiQuad_Quadrangle] +
-                                               theInfo[SMDSEntity_Polygon] ));
+                                               theInfo[SMDSEntity_Polygon] +
+                                               theInfo[SMDSEntity_Quad_Polygon]));
   myNbLinFace    ->setText( QString("%1").arg( theInfo[SMDSEntity_Triangle] +
                                                theInfo[SMDSEntity_Quadrangle] +
                                                theInfo[SMDSEntity_Polygon] ));
   myNbQuadFace   ->setText( QString("%1").arg( theInfo[SMDSEntity_Quad_Triangle] +
-                                               theInfo[SMDSEntity_Quad_Quadrangle] ));
+                                               theInfo[SMDSEntity_Quad_Quadrangle] +
+                                               theInfo[SMDSEntity_Quad_Polygon] ));
   myNbBiQuadFace ->setText( QString("%1").arg( theInfo[SMDSEntity_BiQuad_Triangle] +
                                                theInfo[SMDSEntity_BiQuad_Quadrangle] ));
 
@@ -481,7 +490,10 @@ void SMESHGUI_MeshInfosBox::SetMeshInfo(const SMESH::long_array& theInfo)
     myNbQuadQuad   ->setText( QString("%1").arg( theInfo[SMDSEntity_Quad_Quadrangle] ));
     myNbBiQuadQuad ->setText( QString("%1").arg( theInfo[SMDSEntity_BiQuad_Quadrangle]));
     // poligones
-    myNbPolyg      ->setText( QString("%1").arg( theInfo[SMDSEntity_Polygon] ));
+    myNbPolyg      ->setText( QString("%1").arg( theInfo[SMDSEntity_Polygon] +
+                                                 theInfo[SMDSEntity_Quad_Polygon] ));
+    myNbLinPolyg   ->setText( QString("%1").arg( theInfo[SMDSEntity_Polygon] ));
+    myNbQuadPolyg  ->setText( QString("%1").arg( theInfo[SMDSEntity_Quad_Polygon] ));
 
     // tetras
     myNbTetra      ->setText( QString("%1").arg( theInfo[SMDSEntity_Tetra] +
index ffd8e9b854caf2c9ea1cab8612b3ee3214c714b2..b1d51256a0f5e5764f9c8ed779337b684dffbd1a 100644 (file)
@@ -69,6 +69,8 @@ private:
   QLabel* myNbQuadFace;
   QLabel* myNbBiQuadFace;
   QLabel* myNbPolyg;
+  QLabel* myNbLinPolyg;
+  QLabel* myNbQuadPolyg;
   QLabel* myNbHexa;
   QLabel* myNbLinHexa;
   QLabel* myNbQuadHexa;
index 67408d72002239ff23c172e0279a38d0556016d9..f4912f423c753877767ad74630ff7bc9bb8b21dc 100644 (file)
@@ -206,11 +206,11 @@ void SMESHGUI_MeshOp::startOperation()
     for ( int i = SMESH::DIM_0D; i <= SMESH::DIM_3D; i++ )
     {
       connect( myDlg->tab( i ), SIGNAL( createHyp( const int, const int ) ),
-              this, SLOT( onCreateHyp( const int, const int ) ) );
+               this, SLOT( onCreateHyp( const int, const int ) ) );
       connect( myDlg->tab( i ), SIGNAL( editHyp( const int, const int ) ),
-              this, SLOT( onEditHyp( const int, const int ) ) );
+               this, SLOT( onEditHyp( const int, const int ) ) );
       connect( myDlg->tab( i ), SIGNAL( selectAlgo( const int ) ),
-              this, SLOT( onAlgoSelected( const int ) ) );
+               this, SLOT( onAlgoSelected( const int ) ) );
     }
     connect( myDlg, SIGNAL( hypoSet( const QString& )), SLOT( onHypoSet( const QString& )));
     connect( myDlg, SIGNAL( geomSelectionByMesh( bool )), SLOT( onGeomSelectionByMesh( bool )));
@@ -859,6 +859,60 @@ static bool isCompatible(const HypothesisData* theAlgoData,
   return ( SMESH::IsAvailableHypothesis( theAlgoData, theHypData->TypeName, isOptional ));
 }
 
+//================================================================================
+/*!
+ * \brief check compatibility of the geometry
+  * \param theAlgoData - to select hypos able to be used by this algo
+  * \param theCurrentGeomToSelect - the current name of the selected geometry
+  * \param theGeomVar - currently selected geometry
+  * \retval bool - check result
+ */
+//================================================================================
+bool SMESHGUI_MeshOp::isCompatibleToGeometry(HypothesisData* theAlgoData,
+                                             QString theCurrentGeomToSelect,
+                                             GEOM::GEOM_Object_var theGeomVar)
+{
+  if ( theGeomVar->_is_nil() )
+    return true;
+
+  bool isApplicable = false;
+  if ( theCurrentGeomToSelect == myLastGeomToSelect && !theCurrentGeomToSelect.isEmpty() ) {
+    THypLabelIsAppMap::const_iterator iter = myHypMapIsApplicable.find( theAlgoData->Label );
+    if ( iter != myHypMapIsApplicable.end() && iter.key() == theAlgoData->Label ) {
+      isApplicable = iter.value();
+      return isApplicable;
+    }
+  }
+  bool toCheckIsApplicableToAll = !myIsMesh;
+  if ( toCheckIsApplicableToAll )
+    toCheckIsApplicableToAll = ( theGeomVar->GetType() == GEOM_GROUP );
+  isApplicable = SMESH::IsApplicable( theAlgoData->TypeName, theGeomVar, toCheckIsApplicableToAll );
+  myHypMapIsApplicable.insert( theAlgoData->Label, isApplicable );
+  return isApplicable;
+}
+
+//================================================================================
+/*!
+ * \brief check compatibility of the mesh type
+  * \param theAlgoData - to select hypos able to be used by this algo
+  * \param theMeshType - type of mesh for filtering algorithms
+  * \retval bool - check result
+ */
+//================================================================================
+bool SMESHGUI_MeshOp::isCompatibleToMeshType(HypothesisData* theAlgoData,
+                                             QString theMeshType)
+{
+  bool isAvailableAlgo = ( theAlgoData->OutputTypes.count() == 0 );
+  QStringList::const_iterator inElemType = theAlgoData->OutputTypes.begin();
+  for ( ; inElemType != theAlgoData->OutputTypes.end(); inElemType++ ) {
+    if ( *inElemType == theMeshType ) {
+      isAvailableAlgo = true;
+      break;
+    }
+  }
+  return isAvailableAlgo;
+}
+
 //================================================================================
 /*!
  * \brief Gets available hypotheses or algorithms
@@ -866,7 +920,9 @@ static bool isCompatible(const HypothesisData* theAlgoData,
   * \param theHypType - specifies whether algorims or hypotheses or additional ones
   * are retrieved (possible values are in HypType enumeration)
   * \param theHyps - Output list of hypotheses' names
-  * \param theAlgoData - to select hypos able to be used by this algo (optional)
+  * \param thePrevAlgoData - to select hypos able to be used by previously algo (optional)
+  * \param theNextAlgoData - to select hypos able to be used by next algo (optional)
+  * \param theMeshType - type of mesh for filtering algorithms (optional)
  *
  * Gets available hypotheses or algorithm in accordance with input parameters
  */
@@ -875,7 +931,9 @@ void SMESHGUI_MeshOp::availableHyps( const int       theDim,
                                      const int       theHypType,
                                      QStringList&    theHyps,
                                      THypDataList&   theDataList,
-                                     HypothesisData* theAlgoData ) const
+                                     HypothesisData* thePrevAlgoData,
+                                     HypothesisData* theNextAlgoData,
+                                     const QString&  theMeshType)
 {
   theDataList.clear();
   theHyps.clear();
@@ -884,14 +942,35 @@ void SMESHGUI_MeshOp::availableHyps( const int       theDim,
   QStringList aHypTypeNameList = SMESH::GetAvailableHypotheses( isAlgo, theDim, isAux, myIsOnGeometry, !myIsMesh );
 
   QStringList::const_iterator anIter;
+  GEOM::GEOM_Object_var aGeomVar;
+  QString aCurrentGeomToSelect;
+  if ( !theMeshType.isEmpty() ) {
+    aCurrentGeomToSelect = myDlg->selectedObject( myToCreate ? SMESHGUI_MeshDlg::Geom : SMESHGUI_MeshDlg::Obj );
+    if ( _PTR(SObject) so = studyDS()->FindObjectID( aCurrentGeomToSelect.toLatin1().data() )) {
+      aGeomVar = SMESH::GetGeom( so );
+    }
+   if ( aCurrentGeomToSelect != myLastGeomToSelect )
+     myHypMapIsApplicable.clear();
+  }
+
   for ( anIter = aHypTypeNameList.begin(); anIter != aHypTypeNameList.end(); ++anIter )
   {
     HypothesisData* aData = SMESH::GetHypothesisData( *anIter );
-    if ( isCompatible ( theAlgoData, aData, theHypType )) {
+    if ( ( isCompatible ( thePrevAlgoData, aData, theHypType ) &&
+           isCompatible ( theNextAlgoData, aData, theHypType ) ) ||
+           ( theMeshType == "ANY" && aData->InputTypes.isEmpty())) {
+      if ( !theMeshType.isEmpty() && theDim >= SMESH::DIM_2D &&
+           ( ( theMeshType != "ANY" && !isCompatibleToMeshType( aData, theMeshType )) ||
+           !isCompatibleToGeometry( aData, aCurrentGeomToSelect, aGeomVar )))
+        continue;
       theDataList.append( aData );
       theHyps.append( aData->Label );
     }
   }
+
+  if ( !theMeshType.isEmpty() && !aCurrentGeomToSelect.isEmpty() &&
+       myLastGeomToSelect != aCurrentGeomToSelect )
+    myLastGeomToSelect = aCurrentGeomToSelect;
 }
 
 //================================================================================
@@ -1421,42 +1500,41 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
   // check that tab enabled of one less dimension
   if ( aDim > SMESH::DIM_0D )
   {
-    if ( isAccessibleDim( aDim - 1 ) )
-    {
-      if (( myDlg->currentMeshType() != MT_ANY ) &&
-          ( !algoData || ( myIsOnGeometry && algoData->InputTypes.isEmpty() )))
-        for (int i = aDim - 1; i >= SMESH::DIM_0D; i--)
-          if ( isAccessibleDim( i ) ) {
+    if ( isAccessibleDim( aDim - 1 ) ) {
+      if ( algoData && myIsOnGeometry ) {
+        for (int i = aDim - 1; i >= SMESH::DIM_0D; i--) {
+          if ( isAccessibleDim( i ) && ( currentHyp( i, Algo ) < 0 ||
+             algoData->InputTypes.isEmpty() ) ) {
             myDlg->disableTab( i );
             setCurrentHyp(i, Algo, -1);
           }
+        }
+      }
     }
-    else if ( algoData && myIsOnGeometry && !algoData->InputTypes.isEmpty() )
-    {
+    if ( algoData && myIsOnGeometry && !algoData->InputTypes.isEmpty() ) {
       myDlg->enableTab( aDim - 1 );
     }
-  }
-
-  // check that algorithms of other dimentions are compatible with
-  // the selected one
-  if ( !algoData ) { // all algos becomes available
-    if (myDlg->currentMeshType() == MT_ANY || aDim == SMESH::DIM_1D || aDim == SMESH::DIM_0D)
-      availableHyps( aDim, Algo, anAvailable, myAvailableHypData[ aDim ][ Algo ]);
-    else{
-      anAvailable.clear();
-      for (int i = 0; i < myFilteredAlgoData[aDim].count(); ++i) {
-        HypothesisData* aCurAlgo = myFilteredAlgoData[aDim][ i ];
-        anAvailable.append( aCurAlgo->Label );
+    if ( !algoData ) {
+      if ( aDim != SMESH::DIM_2D || ( aDim == SMESH::DIM_2D &&
+         currentHyp( SMESH::DIM_2D, Algo ) < 0) ) {
+        for (int i = aDim - 1; i >= SMESH::DIM_0D; i--)
+          myDlg->enableTab( i );
+      }
+      else {
+        for (int i = aDim - 1; i >= SMESH::DIM_0D; i--)
+          myDlg->disableTab( i );
       }
     }
-    myDlg->tab( aDim )->setAvailableHyps( Algo, anAvailable );
   }
+
+  int algoDim = aDim;
+  HypothesisData* a3DAlgo = 0;
   // 2 loops: backward and forward from algo dimension
-  for ( int forward = false; forward <= true; ++forward )
+  for ( int forward = 0; forward <= 1; ++forward )
   {
-    int dim = aDim + 1, lastDim = SMESH::DIM_3D, dir = 1;
+    int dim = algoDim + 1, lastDim = SMESH::DIM_3D, dir = 1;
     if ( !forward ) {
-      dim = aDim - 1; lastDim = SMESH::DIM_0D; dir = -1;
+      dim = algoDim - 1; lastDim = SMESH::DIM_0D; dir = -1;
     }
     HypothesisData* prevAlgo = algoData;
     bool noCompatible = false;
@@ -1471,47 +1549,47 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
         algoByDim[ dim ] = 0;
         continue;
       }
+      HypothesisData* nextAlgo = 0;
+      if ( myMaxShapeDim == SMESH::DIM_3D && a3DAlgo && dim == SMESH::DIM_2D ) {
+        nextAlgo = a3DAlgo;
+      }
       // get currently selected algo
       int algoIndex = currentHyp( dim, Algo );
       HypothesisData* curAlgo = hypData( dim, Algo, algoIndex );
-      if ( curAlgo ) { // some algo selected
-        if ( !isCompatible( prevAlgo, curAlgo, Algo ))
-          curAlgo = 0;
+
+      QString anCompareType = currentMeshTypeName(myDlg->currentMeshType());
+      QString anCurrentCompareType = "";
+      if ( dim == SMESH::DIM_3D || anCompareType == "ANY" )
+        anCurrentCompareType = anCompareType;
+      else if ( dim == SMESH::DIM_2D ) {
+        anCurrentCompareType = (anCompareType == "HEXA" || anCompareType == "QUAD") ? "QUAD" : "TRIA";
+        nextAlgo = 0;
       }
+
       // set new available algoritms
-      if (myDlg->currentMeshType() == MT_ANY || dim == SMESH::DIM_1D || dim == SMESH::DIM_0D)
-        availableHyps( dim, Algo, anAvailable, myAvailableHypData[dim][Algo], prevAlgo );
-      else{
-        anAvailable.clear();
-        myAvailableHypData[dim][Algo].clear();
-        for (int i = 0; i < myFilteredAlgoData[dim].count(); ++i) {
-          HypothesisData* aCurAlgo = myFilteredAlgoData[dim][ i ];
-          if ( isCompatible ( prevAlgo, aCurAlgo, Algo )) {
-            anAvailable.append( aCurAlgo->Label );
-            myAvailableHypData[dim][Algo].append( aCurAlgo );
-          }
-        }
-      }
+      availableHyps( dim, Algo, anAvailable, myAvailableHypData[dim][Algo], prevAlgo, nextAlgo, anCurrentCompareType);
       HypothesisData* soleCompatible = 0;
       if ( anAvailable.count() == 1 )
         soleCompatible = myAvailableHypData[dim][Algo][0];
-      if ( dim == aTopDim && prevAlgo ) {// all available algoritms should be selectable any way
-        if (myDlg->currentMeshType() == MT_ANY)
-          availableHyps( dim, Algo, anAvailable, myAvailableHypData[dim][Algo], 0 );
-      }
       myDlg->tab( dim )->setAvailableHyps( Algo, anAvailable );
       noCompatible = anAvailable.isEmpty();
-
-      // restore previously selected algo
       algoIndex = myAvailableHypData[dim][Algo].indexOf( curAlgo );
-      if ( !isSubmesh && algoIndex < 0 && soleCompatible && !forward && dim != SMESH::DIM_0D)
+      if ( !isSubmesh && algoIndex < 0 && soleCompatible && !forward && dim != SMESH::DIM_0D) {
         // select the sole compatible algo
         algoIndex = myAvailableHypData[dim][Algo].indexOf( soleCompatible );
+      }
       setCurrentHyp( dim, Algo, algoIndex);
 
       // remember current algo
       prevAlgo = algoByDim[ dim ] = hypData( dim, Algo, algoIndex );
     }
+    if ( myMaxShapeDim == SMESH::DIM_3D && forward && algoDim == SMESH::DIM_1D )
+    {
+      algoDim = SMESH::DIM_3D;
+      forward = -1;
+      a3DAlgo = prevAlgo;
+      continue;
+    }
   }
 
   // set hypotheses corresponding to the found algoritms
@@ -1553,7 +1631,7 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
              myObjHyps[ dim ][ type ].count() > 0 &&
              curHypType == SMESH::toQStr( myObjHyps[ dim ][ type ].first().first->GetName()) )
         {
-          HypothesisData* hypData = SMESH::GetHypothesisData( curHyp->GetName() );
+          HypothesisData* hypData = SMESH::GetHypothesisData( SMESH::toQStr( curHyp->GetName() ));
           for (int i = 0; i < myAvailableHypData[ dim ][ Algo ].count(); ++i) {
             curAlgo = myAvailableHypData[ dim ][ Algo ][ i ];
             if (curAlgo && hypData && isCompatible(curAlgo, hypData, type))
@@ -1569,7 +1647,7 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
       {
         // check if a selected hyp is compatible with the curAlgo
         if ( !curHyp->_is_nil() ) {
-          HypothesisData* hypData = SMESH::GetHypothesisData( curHyp->GetName() );
+          HypothesisData* hypData = SMESH::GetHypothesisData( SMESH::toQStr( curHyp->GetName() ));
           if ( !isCompatible( curAlgo, hypData, type ))
             curHyp = SMESH::SMESH_Hypothesis::_nil();
         }
@@ -2162,7 +2240,7 @@ void SMESHGUI_MeshOp::readMesh()
     if ( myObjHyps[ dim ][ Algo ].count() > 0 )
     {
       SMESH::SMESH_Hypothesis_var aVar = myObjHyps[ dim ][ Algo ].first().first;
-      HypothesisData* algoData = SMESH::GetHypothesisData( aVar->GetName() );
+      HypothesisData* algoData = SMESH::GetHypothesisData( SMESH::toQStr( aVar->GetName() ));
       aHypIndex = myAvailableHypData[ dim ][ Algo ].indexOf ( algoData );
       //       if ( aHypIndex < 0 && algoData ) {
       //         // assigned algo is incompatible with other algorithms
@@ -2300,12 +2378,12 @@ bool SMESHGUI_MeshOp::editMeshOrSubMesh( QString& theMess )
   // First, remove old algos in order to avoid messages on algorithm hiding
   for ( int dim = aDim; dim <= SMESH::DIM_3D; dim++ )
   {
-    if ( isAccessibleDim( dim ) && myObjHyps[ dim ][ Algo ].count() > 0 )
+    if ( /*isAccessibleDim( dim ) &&*/ myObjHyps[ dim ][ Algo ].count() > 0 )
     {
       SMESH::SMESH_Hypothesis_var anOldAlgo = myObjHyps[ dim ][ Algo ].first().first;
       SMESH::SMESH_Hypothesis_var anAlgoVar = getAlgo( dim );
       if ( anAlgoVar->_is_nil() || // no new algo selected or
-           strcmp(anOldAlgo->GetName(), anAlgoVar->GetName()) ) // algo change
+           SMESH::toQStr(anOldAlgo->GetName()) != SMESH::toQStr(anAlgoVar->GetName())) // algo change
       {
         // remove old algorithm
         SMESH::RemoveHypothesisOrAlgorithmOnMesh ( pObj, myObjHyps[ dim ][ Algo ].first().first );
@@ -2590,96 +2668,46 @@ void SMESHGUI_MeshOp::onAlgoSetByMeshType( const int theTabIndex, const int theI
 //================================================================================
 void SMESHGUI_MeshOp::setFilteredAlgoData( const int theTabIndex, const int theIndex)
 {
-  int aDim;
-  THypDataList anAvailableAlgsData;
   QStringList anAvailableAlgs;
-  QString anCompareType = "";
-  bool isAvailableChoiceAlgo = false;
-  int anCurrentAvailableAlgo = 0;
+  QString anCompareType = currentMeshTypeName( theIndex );
+  int anCurrentAvailableAlgo = -1;
   bool isNone = true;
-  switch ( theIndex ) {
-  case MT_ANY:
-    anCompareType = "ANY";
-    aDim = SMESH::DIM_3D;
-    break;
-  case MT_TRIANGULAR:
+  int aDim = SMESH::DIM_3D;
+  if ( theIndex == MT_TRIANGULAR || theIndex == MT_QUADRILATERAL)
     aDim = SMESH::DIM_2D;
-    anCompareType = "TRIA";
-    break;
-  case MT_QUADRILATERAL:
-    aDim = SMESH::DIM_2D;
-    anCompareType = "QUAD";
-    break;
-  case MT_TETRAHEDRAL:
-    aDim = SMESH::DIM_3D;
-    anCompareType = "TETRA";
-    break;
-  case MT_HEXAHEDRAL:
-    aDim = SMESH::DIM_3D;
-    anCompareType = "HEXA";
-    break;
-  default:;
-  }
-
-  bool toCheckIsApplicableToAll = !myIsMesh;
-  GEOM::GEOM_Object_var aGeomVar;
-  QString anEntry =
-    myDlg->selectedObject( myToCreate ? SMESHGUI_MeshDlg::Geom : SMESHGUI_MeshDlg::Obj );
-  if ( _PTR(SObject) so = studyDS()->FindObjectID( anEntry.toLatin1().data() ))
-  {
-    aGeomVar = SMESH::GetGeom( so );
-    if ( !aGeomVar->_is_nil() && toCheckIsApplicableToAll )
-      toCheckIsApplicableToAll = ( aGeomVar->GetType() == GEOM_GROUP );
-  }
-
   if ( anCompareType == "ANY" )
   {
+    bool isReqDisBound = false;
+    int aReqDim = SMESH::DIM_3D;
     for ( int dim = SMESH::DIM_3D; dim >= SMESH::DIM_2D; dim-- )
     {
+      anCurrentAvailableAlgo = -1;
       isNone = currentHyp( dim, Algo ) < 0;
-      isAvailableChoiceAlgo = false;
-      // retrieves a list of available algorithms from resources
-      availableHyps( dim, Algo, anAvailableAlgs, anAvailableAlgsData );
       //return current algo in current tab and set new algorithm list
       HypothesisData* algoCur;
       if ( !isNone && !myAvailableHypData[dim][Algo].empty() ) {
         algoCur = myAvailableHypData[dim][Algo].at( currentHyp( dim, Algo ) );
       }
-      myAvailableHypData[dim][Algo].clear();
-      anAvailableAlgs.clear();
-      if ( dim != SMESH::DIM_2D || currentHyp( SMESH::DIM_3D, Algo ) < 0 ||
-           myAvailableHypData[SMESH::DIM_3D][Algo].empty() ||
-           !myAvailableHypData[SMESH::DIM_3D][Algo].at( currentHyp( SMESH::DIM_3D, Algo ) )->InputTypes.isEmpty() )
-      {
-        for (int i = 0 ; i < anAvailableAlgsData.count(); i++)
-        {
-          HypothesisData* curAlgo = anAvailableAlgsData.at(i);
-          if ( aGeomVar->_is_nil() ||
-              SMESH::IsApplicable( curAlgo->TypeName, aGeomVar, toCheckIsApplicableToAll ))
-          {
-            anAvailableAlgs.append( curAlgo->Label );
-            myAvailableHypData[dim][Algo].append( curAlgo );
-          }
-        }
-        if ( !isNone && algoCur ) {
-          for (int i = 0 ; i < myAvailableHypData[dim][Algo].count(); i++)
-          {
-            HypothesisData* algoAny = myAvailableHypData[dim][Algo].at(i);
-            if ( algoAny->Label == algoCur->Label ){
-              isAvailableChoiceAlgo = true;
-              anCurrentAvailableAlgo = i;
-              break;
-            }
-          }
-        }
-        else if ( !isNone ) {
-          isAvailableChoiceAlgo = true;
-          anCurrentAvailableAlgo = currentHyp( dim, Algo );
-        }
+      HypothesisData* prevAlgo = 0;
+      HypothesisData* nextAlgo = 0;
+      if ( dim == SMESH::DIM_2D ) {
+        prevAlgo = hypData( SMESH::DIM_1D, Algo, currentHyp( SMESH::DIM_1D, Algo ) );
+        if ( aDim == SMESH::DIM_3D )
+          nextAlgo = hypData( SMESH::DIM_3D, Algo, currentHyp( SMESH::DIM_3D, Algo ) );
       }
+      // retrieves a list of available algorithms from resources
+      availableHyps( dim, Algo, anAvailableAlgs, myAvailableHypData[dim][Algo], prevAlgo, nextAlgo, anCompareType);
+      anCurrentAvailableAlgo = myAvailableHypData[dim][Algo].indexOf( algoCur );
       myDlg->tab( dim )->setAvailableHyps( Algo, anAvailableAlgs );
-      if ( isAvailableChoiceAlgo )
-        setCurrentHyp( dim, Algo, anCurrentAvailableAlgo );
+      setCurrentHyp( dim, Algo, anCurrentAvailableAlgo );
+      if ( anCurrentAvailableAlgo > -1 )
+        isReqDisBound = algoCur->InputTypes.isEmpty();
+      else if ( dim != SMESH::DIM_3D && currentHyp( SMESH::DIM_3D, Algo ) >= 0 )
+        isReqDisBound = true;
+      if ( isReqDisBound ) {
+        aReqDim = dim;
+        break;
+      }
     }
     if ( !myIsOnGeometry )
       for ( int i = SMESH::DIM_0D; i <= SMESH::DIM_3D; i++ ) {
@@ -2688,142 +2716,100 @@ void SMESHGUI_MeshOp::setFilteredAlgoData( const int theTabIndex, const int theI
       }
     else
       for ( int i = SMESH::DIM_0D; i <= SMESH::DIM_3D; i++ ) {
-        if ( i > myMaxShapeDim ) myDlg->disableTab( i );
-        else                     myDlg->enableTab( i );
+        if ( i > myMaxShapeDim || ( isReqDisBound && i < aReqDim ) ) myDlg->disableTab( i );
+        else                                                         myDlg->enableTab( i );
       }
     myDlg->setCurrentTab( theTabIndex );
   }
   else
   {
-    QString anCurrentAlgo;
+    HypothesisData* anCurrentAlgo;
     bool isReqDisBound = true;
     QString anCurrentCompareType = anCompareType;
     isNone = currentHyp( aDim, Algo ) < 0;
-    if ( !isNone && !myAvailableHypData[aDim][Algo].empty() &&
-        myAvailableHypData[aDim][Algo].count() != anAvailableAlgsData.count() )
+    if ( !isNone && !myAvailableHypData[aDim][Algo].empty() )
       isReqDisBound = myAvailableHypData[aDim][Algo].at( currentHyp( aDim, Algo ) )->InputTypes.isEmpty();
-    else if ( !isNone )
-      isReqDisBound = anAvailableAlgsData.at( currentHyp( aDim, Algo ) )->InputTypes.isEmpty();
     for ( int dim = aDim; dim >= SMESH::DIM_2D; dim-- )
     {
       bool isNoneAlg = currentHyp( dim, Algo ) < 0;
-      isAvailableChoiceAlgo = false;
-      // retrieves a list of available algorithms from resources
-      availableHyps( dim, Algo, anAvailableAlgs, anAvailableAlgsData );
+      anCurrentAvailableAlgo = -1;
+      HypothesisData* prevAlgo = 0;
+      HypothesisData* nextAlgo = 0;
+      if ( dim == SMESH::DIM_2D ) {
+        prevAlgo = hypData( SMESH::DIM_1D, Algo, currentHyp( SMESH::DIM_1D, Algo ) );
+        if ( aDim == SMESH::DIM_3D )
+          nextAlgo = hypData( SMESH::DIM_3D, Algo, currentHyp( SMESH::DIM_3D, Algo ) );
+      }
       // finding algorithm which is selected
-      if ( !isNoneAlg && !myAvailableHypData[dim][Algo].empty() &&
-          myAvailableHypData[dim][Algo].count() != anAvailableAlgsData.count() )
-        anCurrentAlgo = myAvailableHypData[dim][Algo].at( currentHyp( dim, Algo ) )->Label;
-      else if ( !isNoneAlg )
-        anCurrentAlgo = anAvailableAlgsData.at( currentHyp( dim, Algo ) )->Label;
-      anAvailableAlgs.clear();
-      myAvailableHypData[dim][Algo].clear();
-      myFilteredAlgoData[dim].clear();
-      // finding and adding algorithm depending on the type mesh
-      for ( int i = 0 ; i < anAvailableAlgsData.count(); i++ )
-      {
-        HypothesisData* algoIn = anAvailableAlgsData.at( i );
-        bool isAvailableAlgo = ( algoIn->OutputTypes.count() == 0 );
-        QStringList::const_iterator inElemType = algoIn->OutputTypes.begin();
-        for ( ; inElemType != algoIn->OutputTypes.end(); inElemType++ )
-        {
-          if ( *inElemType == anCurrentCompareType ) {
-            isAvailableAlgo = true;
-            break;
-          }
-        }
-        if ( isAvailableAlgo || algoIn->OutputTypes.count()==0 ) {
-          if ( aGeomVar->_is_nil() || myMaxShapeDim != dim ||
-               SMESH::IsApplicable( algoIn->TypeName, aGeomVar, toCheckIsApplicableToAll ))
-          {
-            anAvailableAlgs.append( algoIn->Label );
-            myAvailableHypData[dim][Algo].append( algoIn );
-            myFilteredAlgoData[dim].append( algoIn );
-          }
-        }
-        //algorithm will be active, if the chosen algorithm available in the current mesh type
-        if ( !isNoneAlg &&  isAvailableAlgo && algoIn->Label == anCurrentAlgo ) {
-          isAvailableChoiceAlgo = true;
-          anCurrentAvailableAlgo = anAvailableAlgs.count() - 1 ;
-        }
+      if ( !isNoneAlg ) {
+        anCurrentAlgo = myAvailableHypData[dim][Algo].at( currentHyp( dim, Algo ) );
       }
+      // retrieves a list of available algorithms from resources
+      availableHyps( dim, Algo, anAvailableAlgs, myAvailableHypData[dim][Algo], prevAlgo, nextAlgo, anCurrentCompareType );
+      // finding and adding algorithm depending on the type mesh
+      anCurrentAvailableAlgo = myAvailableHypData[dim][Algo].indexOf( anCurrentAlgo );
       //set new algorithm list and select the current algorithm
       myDlg->tab( dim )->setAvailableHyps( Algo, anAvailableAlgs );
-      anCurrentCompareType = ( anCompareType == "HEXA" ) ? "QUAD" : "TRIA";
-      if ( isAvailableChoiceAlgo )
-        setCurrentHyp( dim, Algo, anCurrentAvailableAlgo );
-      else
-        setCurrentHyp( dim, Algo, -1 );
+      anCurrentCompareType = ( anCompareType == "HEXA" || anCompareType == "QUAD" ) ? "QUAD" : "TRIA";
+      setCurrentHyp( dim, Algo, anCurrentAvailableAlgo );
     }
 
     if ( isNone || isReqDisBound ) {
       for ( int i = SMESH::DIM_0D; i <= myMaxShapeDim; i++ ) {
         if ( aDim != i ) {
           myDlg->disableTab( i );
-          setCurrentHyp(i, Algo, -1);
         }
       }
     }
     else if ( !isNone ) {
-      if ( aDim == SMESH::DIM_2D){
+      if ( aDim == SMESH::DIM_2D) {
         myDlg->disableTab( SMESH::DIM_3D );
         setCurrentHyp( SMESH::DIM_3D, Algo, -1);
       }
-      for ( int i = myMaxShapeDim; i > SMESH::DIM_0D; i-- )
-      {
-        isReqDisBound = ( currentHyp( i, Algo ) < 0 ) ? true :
-            myAvailableHypData[i][Algo].at( currentHyp( i, Algo ) )->InputTypes.isEmpty();
-        if ( isReqDisBound ) {
-          for (int j = i - 1; j >= SMESH::DIM_0D; j--){
-            myDlg->disableTab( j );
-            setCurrentHyp( j , Algo, -1 );
+      for ( int i = myMaxShapeDim; i > SMESH::DIM_0D; i-- ) {
+        bool isNoneAlg = currentHyp( i, Algo ) < 0;
+        if ( !isNoneAlg )
+          isReqDisBound = myAvailableHypData[i][Algo].at( currentHyp( i, Algo ) )->InputTypes.isEmpty();
+        else
+          isReqDisBound = true;
+        if ( isReqDisBound && isNoneAlg ) {
+          for (int j = i - 1; j >= SMESH::DIM_0D; j--) {
+            if ( j < aDim && currentHyp( j+1, Algo ) < 0 ) {
+              myDlg->disableTab( j );
+              setCurrentHyp( j , Algo, -1 );
+            }
           }
           break;
         }
+        else if ( isNoneAlg ) {
+          myDlg->disableTab( i );
+        }
       }
     }
     myDlg->enableTab( aDim );
     myDlg->setCurrentTab( aDim );
   }
+  THypDataList anAvailableAlgsData;
   QStringList aHypothesesSetsList = SMESH::GetHypothesesSets( aDim );
   QStringList aFilteredHypothesesSetsList;
   aFilteredHypothesesSetsList.clear();
   QStringList::const_iterator inHypoSetName = aHypothesesSetsList.begin();
-  for ( ; inHypoSetName != aHypothesesSetsList.end(); ++inHypoSetName )
-  {
+  for ( ; inHypoSetName != aHypothesesSetsList.end(); ++inHypoSetName ) {
     HypothesesSet* currentHypoSet = SMESH::GetHypothesesSet( *inHypoSetName );
     bool isAvailable = false;
     currentHypoSet->init( true );
-    while ( currentHypoSet->next(), currentHypoSet->more() )
-    {
+    while ( currentHypoSet->next(), currentHypoSet->more() ) {
       isAvailable = false;
-      if ( HypothesisData* algoDataIn = SMESH::GetHypothesisData( currentHypoSet->current() ))
-      {
-        for (int i = SMESH::DIM_0D; i <= myMaxShapeDim; i++)
-        {
-          if ( myAvailableHypData[i][Algo].count() == 0 ) {
-            availableHyps( i, Algo, anAvailableAlgs, anAvailableAlgsData );
-            for ( int j = 0 ; j < anAvailableAlgsData.count(); j++ )
-            {
-              HypothesisData* aCurAlgo = anAvailableAlgsData.at( j );
-              if ( aCurAlgo->Label == algoDataIn->Label ){
-                isAvailable = true;
-                break;
-              }
-            }
-          }
-          else {
-            for (int j = 0; j < myAvailableHypData[i][Algo].count(); ++j) {
-              HypothesisData* aCurAlgo = hypData( i, Algo, j );
-              if ( aCurAlgo->Label == algoDataIn->Label ){
-                isAvailable = true;
-                break;
-              }
-            }
+      if ( HypothesisData* algoDataIn = SMESH::GetHypothesisData( currentHypoSet->current() )) {
+        for (int i = SMESH::DIM_0D; i <= myMaxShapeDim; i++) {
+          int anCurrentAvailableAlgo = myAvailableHypData[i][Algo].indexOf( algoDataIn );
+          if ( anCurrentAvailableAlgo > -1 ) {
+            isAvailable = true;
+            break;
           }
-          if ( isAvailable ) break;
         }
-        if ( !isAvailable ) break;
+        if ( !isAvailable )
+          break;
       }
     }
     if ( isAvailable )
@@ -2831,3 +2817,35 @@ void SMESHGUI_MeshOp::setFilteredAlgoData( const int theTabIndex, const int theI
   }
   myDlg->setHypoSets( aFilteredHypothesesSetsList );
 }
+
+//================================================================================
+/*!
+ * \brief Get current name types of mesh
+  * \param theIndex - current index types of mesh
+  * \retval QString - result
+ */
+//================================================================================
+QString SMESHGUI_MeshOp::currentMeshTypeName( const int theIndex ) const
+{
+  QString aMeshType = "";
+  switch ( theIndex ) {
+  case MT_ANY:
+    aMeshType = "ANY";
+    break;
+  case MT_TRIANGULAR:
+    aMeshType = "TRIA";
+    break;
+  case MT_QUADRILATERAL:
+    aMeshType = "QUAD";
+    break;
+  case MT_TETRAHEDRAL:
+    aMeshType = "TETRA";
+    break;
+  case MT_HEXAHEDRAL:
+    aMeshType = "HEXA";
+    break;
+  default:;
+  }
+  return aMeshType;
+}
+
index 8ca98864e66f2aec446b911d5fef3e9552ec5f33..206f4504e97784ff74d3f3a85b681b7d1b72172d 100644 (file)
@@ -89,13 +89,21 @@ protected slots:
 
 private:
   typedef QList<HypothesisData*> THypDataList; // typedef: list of hypothesis data
+  typedef QMap<QString, bool>    THypLabelIsAppMap; // typedef: map of hypothesis is applicable
 
   bool                           isValid( QString& ) const;
+  bool                           isCompatibleToGeometry( HypothesisData* ,
+                                                         QString,
+                                                         GEOM::GEOM_Object_var);
+  bool                           isCompatibleToMeshType( HypothesisData* ,
+                                                         QString);
   void                           availableHyps( const int, 
                                                 const int,
                                                 QStringList&,
                                                 THypDataList&,
-                                                HypothesisData* = 0 ) const;
+                                                HypothesisData* = 0,
+                                                HypothesisData* = 0,
+                                                const QString& = "");
   void                           existingHyps( const int, 
                                                const int, 
                                                _PTR(SObject),
@@ -137,6 +145,7 @@ private:
   void                           createMeshTypeList( QStringList& );
   void                           setAvailableMeshType( const QStringList& );
   void                           setFilteredAlgoData( const int, const int );
+  QString                        currentMeshTypeName( const int ) const;
 
 private:
 
@@ -152,7 +161,8 @@ private:
                                                  //   edited mesh/sub-mesh
   // hypdata corresponding to hypotheses present in myDlg
   THypDataList                   myAvailableHypData[4][NbHypTypes];
-  THypDataList                   myFilteredAlgoData[4];
+  QString                        myLastGeomToSelect;
+  THypLabelIsAppMap              myHypMapIsApplicable;
   bool                           myIgnoreAlgoSelection;
   HypothesesSet* myHypoSet;
   int myDim, myType, myMaxShapeDim;
index 11a84fdae5e91b30534ac6cb7dc18e92341f3123..dd4d753377e5abe513a2ca41257535fde408d23f 100755 (executable)
@@ -391,6 +391,8 @@ void SMESHGUI_MeshPatternDlg::Init()
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone()));
   connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), SLOT(onDeactivate()));
   connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()), SLOT(reject()));
+  connect(mySMESHGUI, SIGNAL(SignalActivatedViewManager()), SLOT( onOpenView()));
+  connect(mySMESHGUI, SIGNAL(SignalCloseView()), SLOT( onCloseView()));
 
   myTypeGrp->button(Type_2d)->setChecked(true);
   onTypeChanged(Type_2d);
@@ -558,6 +560,32 @@ void SMESHGUI_MeshPatternDlg::reject()
   QDialog::reject();
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_MeshPatternDlg::onOpenView()
+{
+  if(!mySelector) {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    mySMESHGUI->EmitSignalDeactivateDialog();
+    setEnabled(true);
+    activateSelection();
+    connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone()));
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_MeshPatternDlg::onCloseView()
+{
+  onDeactivate();
+  mySelector = 0;
+}
+
+
 //=================================================================================
 // function : onHelp()
 // purpose  :
@@ -715,8 +743,13 @@ void SMESHGUI_MeshPatternDlg::enterEvent (QEvent*)
   if (myIsCreateDlgOpen)
     return;
 
-  if (myReverseChk->isChecked())
+  if (myReverseChk->isChecked()) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector) {
+      mySelector = aViewWindow->GetSelector();
+    }
     displayPreview();
+  }
   mySMESHGUI->EmitSignalDeactivateDialog();
   setEnabled(true);
   activateSelection();
index b3f81fd1b60625ba45b4520f9de1fa129ab0378c..5b656f726cdb8543f32958ab6bcacb74ff06ce50 100755 (executable)
@@ -98,6 +98,8 @@ private slots:
   void                                onCloseCreationDlg();
   void                                onTextChanged( const QString& );
   void                                onNodeChanged( int );
+  void                                onOpenView();
+  void                                onCloseView();
 
 private:
   QWidget*                            createButtonFrame( QWidget* );
index 7498047feedc8099c9b0c744b6e6ab4463e89fde..f123ea17ea7ccf412e128ea3c31e095fe446fd6a 100755 (executable)
@@ -397,6 +397,8 @@ void SMESHGUI_MultiEditDlg::Init()
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone()));
   connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), SLOT(onDeactivate()));
   connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()), SLOT(reject()));
+  connect(mySMESHGUI, SIGNAL(SignalActivatedViewManager()), SLOT( onOpenView()));
+  connect(mySMESHGUI, SIGNAL(SignalCloseView()), SLOT( onCloseView()));
 
   // dialog controls
   connect(myFilterBtn, SIGNAL(clicked()), SLOT(onFilterBtn()  ));
@@ -476,6 +478,30 @@ void SMESHGUI_MultiEditDlg::reject()
   QDialog::reject();
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_MultiEditDlg::onOpenView()
+{
+  if(!mySelector) {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    mySMESHGUI->EmitSignalDeactivateDialog();
+    setEnabled(true);
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_MultiEditDlg::onCloseView()
+{
+  onDeactivate();
+  mySelector = 0;
+}
+
+
 //=================================================================================
 // function : onHelp()
 // purpose  :
@@ -588,6 +614,10 @@ void SMESHGUI_MultiEditDlg::onDeactivate()
 void SMESHGUI_MultiEditDlg::enterEvent (QEvent*)
 {
   if (!isEnabled()) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector) {
+      mySelector = aViewWindow->GetSelector();
+    }
     mySMESHGUI->EmitSignalDeactivateDialog();
     setEnabled(true);
     setSelectionMode();
index 1b4a8ffa930c8051a997c3c889fba742a9d4d594..2f92d6b00dfdc4d125cc0f22b2c30d47ede6e881 100755 (executable)
@@ -102,6 +102,8 @@ protected slots:
   virtual void              onToAllChk();
   void                      onFilterAccepted();
   virtual void              on3d2dChanged(int);
+  void                      onOpenView();
+  void                      onCloseView();
 
   SMESH::NumericalFunctor_ptr getNumericalFunctor();
 
index 69bdb257e5ef71194835e7b50b4b2f256b29f86e..e163699d4fc9921378360e394f3f1a8ad23c6dc0 100644 (file)
@@ -382,8 +382,9 @@ void SMESHGUI_NodesDlg::Init()
   connect( mySMESHGUI,     SIGNAL( SignalDeactivateActiveDialog() ), SLOT( DeactivateActiveDialog() ) );
   /* to close dialog if study frame change */
   connect( mySMESHGUI,     SIGNAL( SignalStudyFrameChanged() ),      SLOT( reject() ) );
-  connect(mySMESHGUI,      SIGNAL(SignalCloseAllDialogs()),          SLOT(reject()));
-
+  connect( mySMESHGUI,     SIGNAL( SignalCloseAllDialogs() ),        SLOT( reject() ) );
+  connect( mySMESHGUI,     SIGNAL( SignalActivatedViewManager() ),   SLOT( onOpenView() ) );
+  connect( mySMESHGUI,     SIGNAL( SignalCloseView() ),              SLOT( onCloseView() ) );
   // set selection mode
   SMESH::SetPointRepresentation( true );
   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ) )
@@ -402,7 +403,6 @@ void SMESHGUI_NodesDlg::ValueChangedInSpinBox( double newValue )
     double vx = SpinBox_X->GetValue();
     double vy = SpinBox_Y->GetValue();
     double vz = SpinBox_Z->GetValue();
-
     mySimulation->SetPosition( vx, vy, vz );
   }
 }
@@ -547,7 +547,6 @@ void SMESHGUI_NodesDlg::reject()
   disconnect( mySelectionMgr, 0, this, 0 );
   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ) )
     aViewWindow->SetSelectionMode( ActorSelection );
-
   mySimulation->SetVisibility( false );
   SMESH::SetPointRepresentation( false );
   mySMESHGUI->ResetState();
@@ -555,6 +554,36 @@ void SMESHGUI_NodesDlg::reject()
   QDialog::reject();
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_NodesDlg::onOpenView()
+{
+  if ( mySelector && mySimulation ) {
+    mySimulation->SetVisibility(false);
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    mySelector = aViewWindow->GetSelector();
+    mySimulation = new SMESH::TNodeSimulation(aViewWindow);
+    ActivateThisDialog();
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_NodesDlg::onCloseView()
+{
+  DeactivateActiveDialog();
+  mySelector = 0;
+  delete mySimulation;
+  mySimulation = 0;
+}
+
 //=================================================================================
 // function : ClickOnHelp()
 // purpose  :
@@ -644,8 +673,14 @@ void SMESHGUI_NodesDlg::SelectionIntoArgument()
 //=================================================================================
 void SMESHGUI_NodesDlg::enterEvent( QEvent* )
 {
-  if ( !GroupConstructors->isEnabled() )
+  if ( !GroupConstructors->isEnabled() ) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector && !mySimulation) {
+      mySelector = aViewWindow->GetSelector();
+      mySimulation = new SMESH::TNodeSimulation(aViewWindow);
+    }
     ActivateThisDialog();
+  }
 }
 
 //=================================================================================
@@ -678,7 +713,6 @@ void SMESHGUI_NodesDlg::ActivateThisDialog()
   SMESH::SetPointRepresentation( true );
   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ) )
     aViewWindow->SetSelectionMode( NodeSelection );
-
   SelectionIntoArgument();
 }
 
index dca335a00a733e550711673a754df17b8a01b734..5843d3bf1087edf2156d0924d1c61a1e799ee7f7 100644 (file)
@@ -117,6 +117,8 @@ private slots:
   void                    ActivateThisDialog();
   void                    SelectionIntoArgument();
   void                    ValueChangedInSpinBox( double );
+  void                    onOpenView();
+  void                    onCloseView();
 };
 
 #endif // SMESHGUI_NODESDLG_H
index c9b3a2f58e38a8800f8f91673f052579c477819b..9f492bf17024f1552b8233880eeda004220edd96 100644 (file)
@@ -145,6 +145,7 @@ namespace SMESHOp {
     OpQuadraticPentahedron   = 4107,   // MENU MODIFICATION - ADD - QUADRATIC PENTAHEDRON
     OpQuadraticHexahedron    = 4108,   // MENU MODIFICATION - ADD - QUADRATIC HEXAHEDRON
     OpTriQuadraticHexahedron = 4109,   // MENU MODIFICATION - ADD - TRIQUADRATIC HEXAHEDRON
+    OpQuadraticPolygon       = 4110,   // MENU MODIFICATION - ADD - QUADRATIC POLYGON
     OpRemoveNodes            = 4200,   // MENU MODIFICATION - REMOVE - NODE
     OpRemoveElements         = 4201,   // MENU MODIFICATION - REMOVE - ELEMENTS
     OpRemoveOrphanNodes      = 4202,   // MENU MODIFICATION - REMOVE - ORPHAN NODES
@@ -175,6 +176,7 @@ namespace SMESHOp {
     OpPatternMapping         = 4512,   // MENU MODIFICATION - PATTERN MAPPING
     OpConvertMeshToQuadratic = 4513,   // MENU MODIFICATION - CONVERT TO/FROM QUADRATIC
     OpCreateBoundaryElements = 4514,   // MENU MODIFICATION - CREATE BOUNDARY ELEMENTS
+    OpSplitBiQuadratic       = 4515,   // MENU MODIFICATION - SPLIT BI-QUADRATIC TO LINEAR
     // Measurements -------------------//--------------------------------
     OpPropertiesLength       = 5000,   // MENU MEASUREMENTS - BASIC PROPERTIES - LENGTH
     OpPropertiesArea         = 5001,   // MENU MEASUREMENTS - BASIC PROPERTIES - AREA
diff --git a/src/SMESHGUI/SMESHGUI_PreVisualObj.cxx b/src/SMESHGUI/SMESHGUI_PreVisualObj.cxx
new file mode 100644 (file)
index 0000000..8107a11
--- /dev/null
@@ -0,0 +1,142 @@
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// 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 "SMESHGUI_PreVisualObj.h"
+
+#include <SMDS_Mesh.hxx>
+#include <SMESH_Actor.h>
+
+SMESHGUI_PreVisualObj::SMESHGUI_PreVisualObj()
+{
+  myMesh = new SMDS_Mesh();
+}
+
+bool SMESHGUI_PreVisualObj::Update( int theIsClear = true )
+{
+  return false;
+}
+
+void SMESHGUI_PreVisualObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunctor )
+{
+  if ( theFunctor ) theFunctor->SetMesh( GetMesh() );
+}
+
+int SMESHGUI_PreVisualObj::GetElemDimension( const int theObjId )
+{
+  if ( const SMDS_MeshElement* anElem = myMesh->FindElement( theObjId ))
+  {
+    switch ( anElem->GetType() )
+    {
+    case SMDSAbs_Edge  :     return 1;
+    case SMDSAbs_Face  :     return 2;
+    case SMDSAbs_Volume:     return 3;
+    // case SMDSAbs_0DElement : return 0;
+    // case SMDSAbs_Ball :      return 0;
+    default            :     return 0;
+    }
+  }
+  return -1;
+}
+
+int SMESHGUI_PreVisualObj::GetNbEntities( const SMDSAbs_ElementType theType ) const
+{
+  return myMesh->GetMeshInfo().NbElements( theType );
+}
+
+SMESH::SMESH_Mesh_ptr SMESHGUI_PreVisualObj::GetMeshServer()
+{
+  return SMESH::SMESH_Mesh::_nil();
+}
+
+//=================================================================================
+// function : GetEdgeNodes
+// purpose  : Retrieve ids of nodes from edge of elements ( edge is numbered from 1 )
+//=================================================================================
+
+bool SMESHGUI_PreVisualObj::GetEdgeNodes( const int theElemId,
+                                          const int theEdgeNum,
+                                          int&      theNodeId1,
+                                          int&      theNodeId2 ) const
+{
+  const SMDS_MeshElement* e = myMesh->FindElement( theElemId );
+  if ( !e || e->GetType() != SMDSAbs_Face )
+    return false;
+
+  int nbNodes = e->NbCornerNodes();
+  if ( theEdgeNum < 0 || theEdgeNum > nbNodes )
+    return false;
+
+  theNodeId1 = e->GetNode( theEdgeNum-1 )->GetID();
+  theNodeId2 = e->GetNode( theEdgeNum % nbNodes )->GetID();
+
+  return true;
+}
+
+bool SMESHGUI_PreVisualObj::IsValid() const
+{
+  return GetNbEntities( SMDSAbs_All ) > 0;
+}
+
+vtkUnstructuredGrid* SMESHGUI_PreVisualObj::GetUnstructuredGrid()
+{
+  return myMesh->getGrid();
+}
+
+
+vtkIdType SMESHGUI_PreVisualObj::GetNodeObjId( int theVTKID )
+{
+  const SMDS_MeshNode* aNode = myMesh->FindNodeVtk( theVTKID );
+  return aNode ? aNode->GetID() : -1;
+}
+
+vtkIdType SMESHGUI_PreVisualObj::GetNodeVTKId( int theObjID )
+{
+  const SMDS_MeshNode* aNode = myMesh->FindNode( theObjID );
+  return aNode ? aNode->GetID() : -1;
+}
+
+vtkIdType SMESHGUI_PreVisualObj::GetElemObjId( int theVTKID )
+{
+  return this->GetMesh()->fromVtkToSmds(theVTKID);
+}
+
+vtkIdType SMESHGUI_PreVisualObj::GetElemVTKId( int theObjID )
+{
+  const SMDS_MeshElement* e = myMesh->FindElement(theObjID);
+  return e ? e->getVtkId() : -1;
+}
+
+void SMESHGUI_PreVisualObj::ClearEntitiesFlags()
+{
+  myEntitiesState = SMESH_Actor::eAllEntity;
+  myEntitiesFlag = false;
+}
+
+bool SMESHGUI_PreVisualObj::GetEntitiesFlag()
+{
+  return myEntitiesFlag;
+}
+
+unsigned int SMESHGUI_PreVisualObj::GetEntitiesState()
+{
+  return myEntitiesState;
+}
diff --git a/src/SMESHGUI/SMESHGUI_PreVisualObj.h b/src/SMESHGUI/SMESHGUI_PreVisualObj.h
new file mode 100644 (file)
index 0000000..dcbfac9
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// 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
+//
+//  File   : SMESHGUI_PreVisualObj.h
+//  Module : SMESH
+//
+#ifndef SMESHGUI_PreVisualObj_H
+#define SMESHGUI_PreVisualObj_H
+
+#include "SMESH_SMESHGUI.hxx"
+
+#include "SMESH_Object.h"
+
+/*!
+ * \brief Incarnation of SMESH_VisualObj allowing usage of SMESH_Actor
+ *        to show arbitrary mesh data. SMESHGUI_PreVisualObj encapsulates
+ *        a instance of SMDS_Mesh that can be filled by its user.
+ *        Main usage: to initialize a SMESH_Actor to display some preview
+ */
+class SMESHGUI_EXPORT SMESHGUI_PreVisualObj : public SMESH_VisualObj
+{
+  mutable SMDS_Mesh* myMesh;
+  bool               myEntitiesFlag;
+  unsigned int       myEntitiesState;
+
+ public:
+  SMESHGUI_PreVisualObj();
+  virtual SMDS_Mesh* GetMesh() const { return myMesh; }
+
+  virtual bool Update( int theIsClear );
+  virtual bool NulData() { return false; }
+  virtual void UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunctor );
+  virtual int  GetElemDimension( const int theObjId );
+  virtual int  GetNbEntities( const SMDSAbs_ElementType theType) const;
+  virtual bool IsValid() const;
+  virtual bool GetEdgeNodes( const int theElemId,
+                             const int theEdgeNum,
+                             int&      theNodeId1,
+                             int&      theNodeId2 ) const;
+
+  virtual vtkIdType GetNodeObjId( int theVTKID );
+  virtual vtkIdType GetNodeVTKId( int theObjID );
+  virtual vtkIdType GetElemObjId( int theVTKID );
+  virtual vtkIdType GetElemVTKId( int theObjID );
+  virtual void                  ClearEntitiesFlags();
+  virtual bool                  GetEntitiesFlag();
+  virtual unsigned int          GetEntitiesState();
+
+  virtual SMESH::SMESH_Mesh_ptr GetMeshServer();
+  virtual vtkUnstructuredGrid*  GetUnstructuredGrid();
+};
+
+#endif
index 7710d161bcc0193ac82e0fa2b4ac782e2bf8ac31..d466dedf32efe535dd17667d2ca2420039641735 100644 (file)
@@ -50,6 +50,8 @@ SMESHGUI_PreviewDlg::SMESHGUI_PreviewDlg(SMESHGUI* theModule) :
   myIsApplyAndClose( false )
 {
   mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ));
+  connect(mySMESHGUI, SIGNAL(SignalCloseView()),            this, SLOT(onCloseView()));
+  connect(mySMESHGUI, SIGNAL(SignalActivatedViewManager()), this, SLOT(onOpenView()));
 }
 
 //=================================================================================
@@ -66,7 +68,7 @@ SMESHGUI_PreviewDlg::~SMESHGUI_PreviewDlg()
 // purpose  : Show preview in the viewer
 //=================================================================================
 void SMESHGUI_PreviewDlg::showPreview(){
-  if(mySimulation)
+  if(mySimulation && mySimulation->GetActor())
     mySimulation->SetVisibility(true);
 }
 
@@ -75,7 +77,7 @@ void SMESHGUI_PreviewDlg::showPreview(){
 // purpose  : Hide preview in the viewer
 //=================================================================================
 void SMESHGUI_PreviewDlg::hidePreview(){
-  if(mySimulation)
+  if(mySimulation && mySimulation->GetActor())
     mySimulation->SetVisibility(false);
 }
 
@@ -87,7 +89,6 @@ void SMESHGUI_PreviewDlg::connectPreviewControl(){
   connect(myPreviewCheckBox, SIGNAL(toggled(bool)), this, SLOT(onDisplaySimulation(bool)));
 }
 
-
 //=================================================================================
 // function : toDisplaySimulation
 // purpose  : 
@@ -124,7 +125,27 @@ bool SMESHGUI_PreviewDlg::isApplyAndClose() const
   return myIsApplyAndClose;
 }
 
+//=================================================================================
+// function : onCloseView()
+// purpose  : SLOT called when close view
+//=================================================================================
+void SMESHGUI_PreviewDlg::onCloseView()
+{
+  if ( mySimulation && mySimulation->GetActor())
+    mySimulation->SetVisibility(false);
+  delete mySimulation;
+  mySimulation=0;
+}
 
+//=================================================================================
+// function : onOpenView()
+// purpose  : SLOT called when open view
+//=================================================================================
+void SMESHGUI_PreviewDlg::onOpenView()
+{
+  if ( !mySimulation)
+    mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ));
+}
 //=================================================================================
 // class    : SMESHGUI_SMESHGUI_MultiPreviewDlg()
 // purpose  :
@@ -134,6 +155,8 @@ SMESHGUI_MultiPreviewDlg::SMESHGUI_MultiPreviewDlg( SMESHGUI* theModule ) :
   QDialog( SMESH::GetDesktop( theModule ) ),
   myIsApplyAndClose( false )
 {
+  mySimulationList.clear();
+  connect(mySMESHGUI, SIGNAL(SignalCloseView()), this, SLOT(onCloseView()));
 }
 
 //=================================================================================
@@ -152,7 +175,8 @@ SMESHGUI_MultiPreviewDlg::~SMESHGUI_MultiPreviewDlg()
 void SMESHGUI_MultiPreviewDlg::showPreview()
 {
   for ( int i = 0; i < mySimulationList.count(); i++ )
-    mySimulationList[i]->SetVisibility( true );
+    if(mySimulationList[i] && mySimulationList[i]->GetActor())
+      mySimulationList[i]->SetVisibility( true );
 }
 
 //=================================================================================
@@ -162,7 +186,8 @@ void SMESHGUI_MultiPreviewDlg::showPreview()
 void SMESHGUI_MultiPreviewDlg::hidePreview()
 {
   for ( int i = 0; i < mySimulationList.count(); i++ )
-    mySimulationList[i]->SetVisibility( false );
+    if(mySimulationList[i] && mySimulationList[i]->GetActor())
+      mySimulationList[i]->SetVisibility( false );
 }
 
 //=================================================================================
@@ -174,7 +199,6 @@ void SMESHGUI_MultiPreviewDlg::connectPreviewControl()
   connect( myPreviewCheckBox, SIGNAL( toggled( bool ) ), this, SLOT( onDisplaySimulation( bool ) ) );
 }
 
-
 //=================================================================================
 // function : toDisplaySimulation
 // purpose  : 
@@ -227,3 +251,13 @@ void SMESHGUI_MultiPreviewDlg::setSimulationPreview( QList<SMESH::MeshPreviewStr
     mySimulationList[i]->SetData( theMeshPreviewStruct[i].operator->() );
   }
 }
+
+//=================================================================================
+// function : onCloseView()
+// purpose  : SLOT called when close view
+//=================================================================================
+void SMESHGUI_MultiPreviewDlg::onCloseView()
+{
+  qDeleteAll( mySimulationList );
+  mySimulationList.clear();
+}
index ce53b63bf4786b034b86ba020b7cc64ecc2d7ad5..32a277a6575e84b82d6b1ef78239c72550215173 100644 (file)
@@ -58,8 +58,9 @@ protected:
 
 protected slots:
  void                      toDisplaySimulation();
+ void                      onCloseView();
+ void                      onOpenView();
  virtual void              onDisplaySimulation( bool );
-
   
 protected:
   SMESHGUI*                 mySMESHGUI;              /* Current SMESHGUI object */  
@@ -87,6 +88,7 @@ protected:
 
 protected slots:
  void                      toDisplaySimulation();
+ void                      onCloseView();
  virtual void              onDisplaySimulation( bool );
 
   
index 9164ac57bcb0997c2c60e6b0dee2c2ce265dcef6..1decdeff61f3cad222877bc3958701877badba6f 100644 (file)
@@ -204,7 +204,9 @@ void SMESHGUI_RemoveElementsDlg::Init()
   connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
   /* to close dialog if study change */
-  connect(mySMESHGUI, SIGNAL (SignalCloseAllDialogs()), this, SLOT(reject()));
+  connect(mySMESHGUI, SIGNAL (SignalCloseAllDialogs()),      this, SLOT(reject()));
+  connect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView()));
+  connect(mySMESHGUI, SIGNAL (SignalCloseView()),            this, SLOT(onCloseView()));
   connect(myEditCurrentArgument, SIGNAL(textChanged(const QString&)),
           SLOT(onTextChange(const QString&)));
 
@@ -234,6 +236,10 @@ void SMESHGUI_RemoveElementsDlg::ClickOnApply()
     try {
       SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
       aResult = aMeshEditor->RemoveElements(anArrayOfIdeces.in());
+
+      if ( myActor && myMesh->NbElements() == 0 )
+        myActor->SetRepresentation(SMESH_Actor::ePoint);
+
     } catch (const SALOME::SALOME_Exception& S_ex) {
       SalomeApp_Tools::QtCatchCorbaException(S_ex);
       myEditCurrentArgument->clear();
@@ -277,6 +283,28 @@ void SMESHGUI_RemoveElementsDlg::reject()
   QDialog::reject();
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_RemoveElementsDlg::onOpenView()
+{
+  if(!mySelector) {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    ActivateThisDialog();
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_RemoveElementsDlg::onCloseView()
+{
+  DeactivateActiveDialog();
+  mySelector = 0;
+}
+
 //=================================================================================
 // function : ClickOnHelp()
 // purpose  :
@@ -458,8 +486,13 @@ void SMESHGUI_RemoveElementsDlg::ActivateThisDialog()
 //=================================================================================
 void SMESHGUI_RemoveElementsDlg::enterEvent(QEvent*)
 {
-  if (!GroupConstructors->isEnabled())
+  if (!GroupConstructors->isEnabled()) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector) {
+      mySelector = aViewWindow->GetSelector();
+    }
     ActivateThisDialog();
+  }
 }
 
 //=================================================================================
@@ -488,11 +521,20 @@ void SMESHGUI_RemoveElementsDlg::setFilters()
     SUIT_MessageBox::critical(this,
                               tr("SMESH_ERROR"),
                               tr("NO_MESH_SELECTED"));
-   return;
+    return;
   }
   if ( !myFilterDlg )
     myFilterDlg = new SMESHGUI_FilterDlg( mySMESHGUI, SMESH::ALL );
 
+  QList<int> types;
+  if ( myMesh->NbEdges()     ) types << SMESH::EDGE;
+  if ( myMesh->NbFaces()     ) types << SMESH::FACE;
+  if ( myMesh->NbVolumes()   ) types << SMESH::VOLUME;
+  if ( myMesh->NbBalls()     ) types << SMESH::BALL;
+  if ( myMesh->Nb0DElements()) types << SMESH::ELEM0D;
+  if ( types.count() > 1 )     types << SMESH::ALL;
+
+  myFilterDlg->Init( types );
   myFilterDlg->SetSelection();
   myFilterDlg->SetMesh( myMesh );
   myFilterDlg->SetSourceWg( LineEditC1A1 );
index dc20265f5c48262f29bdb1aa0f52ceb7e83e0674..2a614c09b9a0352b525e19b7db1a84da74cea63f 100644 (file)
@@ -106,6 +106,8 @@ private slots:
   void                   DeactivateActiveDialog();
   void                   ActivateThisDialog();
   void                   onTextChange( const QString& );
+  void                   onOpenView();
+  void                   onCloseView();
   void                   setFilters();
   void                   updateButtons();
 };
index 5fb9290fa4c0b8ebb57a5977bcc0ee0085477abf..5baaf4dc24aaa89b84dcafaeca93777a87498e71 100644 (file)
@@ -34,6 +34,7 @@
 #include "SMESHGUI_IdValidator.h"
 #include "SMESHGUI_FilterDlg.h"
 
+#include <SMESH_TypeFilter.hxx>
 #include <SMESH_Actor.h>
 #include <SMDS_Mesh.hxx>
 
@@ -204,16 +205,22 @@ void SMESHGUI_RemoveNodesDlg::Init()
   connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
   /* to close dialog if study change */
-  connect(mySMESHGUI, SIGNAL (SignalCloseAllDialogs()), this, SLOT(reject()));
+  connect(mySMESHGUI, SIGNAL (SignalCloseAllDialogs()),      this, SLOT(reject()));
+  connect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView()));
+  connect(mySMESHGUI, SIGNAL (SignalCloseView()),            this, SLOT(onCloseView()));
   connect(myEditCurrentArgument, SIGNAL(textChanged(const QString&)),
-          SLOT(onTextChange(const QString&)));
-  
+          this,                  SLOT (onTextChange(const QString&)));
+
   SMESH::SetPointRepresentation(true);
-  
+
+  mySelectionMgr->clearFilters();
+  mySelectionMgr->installFilter( new SMESH_TypeFilter( SMESH::IDSOURCE ));
+
   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
     aViewWindow->SetSelectionMode(NodeSelection);
 
-  SelectionIntoArgument();
+  //SelectionIntoArgument();
+  mySelectionMgr->setSelectedObjects( SALOME_ListIO() );
 }
 
 //=================================================================================
@@ -283,6 +290,32 @@ void SMESHGUI_RemoveNodesDlg::reject()
   QDialog::reject();
 }
 
+
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_RemoveNodesDlg::onOpenView()
+{
+  if ( mySelector) {
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    ActivateThisDialog();
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_RemoveNodesDlg::onCloseView()
+{
+  DeactivateActiveDialog();
+  mySelector = 0;
+}
+
 //=================================================================================
 // function : ClickOnHelp()
 // purpose  :
@@ -384,16 +417,16 @@ void SMESHGUI_RemoveNodesDlg::SelectionIntoArgument()
           myBusy = true;
           myEditCurrentArgument->setText(aString);
           myBusy = false;
-          
+
           // OK
-          
+
           myNbOkNodes = nbNodes;
         } // if (nbNodes > 0)
       } // if (myActor)
     } // if (!myMesh->_is_nil())
   } // if (nbSel == 1)
 
-  updateButtons();        
+  updateButtons();
 }
 
 //=================================================================================
@@ -446,6 +479,9 @@ void SMESHGUI_RemoveNodesDlg::ActivateThisDialog()
 
   mySMESHGUI->SetActiveDialogBox((QDialog*)this); // ??
 
+  mySelectionMgr->clearFilters();
+  mySelectionMgr->installFilter( new SMESH_TypeFilter( SMESH::IDSOURCE ));
+
   SMESH::SetPointRepresentation(true);
   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
     aViewWindow->SetSelectionMode(NodeSelection);
@@ -459,8 +495,13 @@ void SMESHGUI_RemoveNodesDlg::ActivateThisDialog()
 //=================================================================================
 void SMESHGUI_RemoveNodesDlg::enterEvent(QEvent*)
 {
-  if (!GroupConstructors->isEnabled())
+  if (!GroupConstructors->isEnabled()) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector) {
+      mySelector = aViewWindow->GetSelector();
+    }
     ActivateThisDialog();
+  }
 }
 
 //=================================================================================
index bee7971f5e75e68c8672d31812a4c37bcc227197..19efac9ddb8597ea99f295661e052e81f6990b45 100644 (file)
@@ -106,6 +106,8 @@ private slots:
   void                   DeactivateActiveDialog();
   void                   ActivateThisDialog();
   void                   onTextChange( const QString& );
+  void                   onOpenView();
+  void                   onCloseView();
   void                   setFilters();
   void                   updateButtons();
 };
index a62c7bfc87becdd59c902a6fb7a1a2c6abd03475..a91586798c0e9c657c4a93ec1a657a1502757fb9 100644 (file)
@@ -296,7 +296,9 @@ SMESHGUI_RevolutionDlg::SMESHGUI_RevolutionDlg( SMESHGUI* theModule )
   connect(SelectorWdg,    SIGNAL(selectionChanged()), this, SLOT(toDisplaySimulation()));
   connect(SelectorWdg,    SIGNAL(selectionChanged()), this, SLOT(CheckIsEnable()));
   /* to close dialog if study change */
-  connect(mySMESHGUI,       SIGNAL(SignalCloseAllDialogs()), this, SLOT(reject()));
+  connect(mySMESHGUI,       SIGNAL(SignalCloseAllDialogs()),      this, SLOT(reject()));
+  connect(mySMESHGUI,       SIGNAL(SignalActivatedViewManager()), this, SLOT(onOpenView()));
+  connect(mySMESHGUI,       SIGNAL(SignalCloseView()),            this, SLOT(onCloseView()));
 
   connect(GroupAngle,        SIGNAL(buttonClicked(int)),   this, SLOT(toDisplaySimulation()));
   connect(SpinBox_Angle,     SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
@@ -517,6 +519,32 @@ void SMESHGUI_RevolutionDlg::reject()
   QDialog::reject();
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_RevolutionDlg::onOpenView()
+{
+  if ( mySelector ) {
+    mySimulation->SetVisibility(false);
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    ActivateThisDialog();
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_RevolutionDlg::onCloseView()
+{
+  DeactivateActiveDialog();
+  mySelector = 0;
+}
+
 //=================================================================================
 // function : ClickOnHelp()
 // purpose  :
@@ -690,8 +718,13 @@ void SMESHGUI_RevolutionDlg::ActivateThisDialog()
 //=================================================================================
 void SMESHGUI_RevolutionDlg::enterEvent (QEvent*)
 {
-  if (!GroupButtons->isEnabled())
+  if (!GroupButtons->isEnabled()) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector) {
+      mySelector = aViewWindow->GetSelector();
+    }
     ActivateThisDialog();
+  }
 }
 
 //=================================================================================
index 3f85e932cc5b0804792843740c65db7b830844b7..ec29fc93072b2f2823da5ef47c584887532ec603 100644 (file)
@@ -151,6 +151,8 @@ private slots:
   void                      onAngleTextChange( const QString& );
   void                      onSelectVectorMenu( QAction* );
   void                      onSelectVectorButton();
+  void                      onOpenView();
+  void                      onCloseView();
 };
 
 #endif // SMESHGUI_REVOLUTIONDLG_H
index 4f24ff6db95352eeb1b9adf87dbb13c84d30697d..9531609ab967351f2706ee710467974516717fe3 100644 (file)
@@ -32,7 +32,6 @@
 #include "SMESHGUI_MeshUtils.h"
 #include "SMESHGUI_IdValidator.h"
 #include "SMESHGUI_FilterDlg.h"
-#include "SMESHGUI_MeshEditPreview.h"
 
 #include <SMESH_Actor.h>
 #include <SMESH_TypeFilter.hxx>
@@ -309,7 +308,9 @@ SMESHGUI_RotationDlg::SMESHGUI_RotationDlg( SMESHGUI* theModule ) :
   connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()),   this, SLOT(SelectionIntoArgument()));
   /* to close dialog if study change */
-  connect(mySMESHGUI,       SIGNAL (SignalCloseAllDialogs()), this, SLOT(reject()));
+  connect(mySMESHGUI,       SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView()));
+  connect(mySMESHGUI,       SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView()));
+  connect(mySMESHGUI,       SIGNAL (SignalCloseView()),            this, SLOT(onCloseView()));
   connect(LineEditElements, SIGNAL(textChanged(const QString&)),    SLOT(onTextChange(const QString&)));
   connect(CheckBoxMesh,     SIGNAL(toggled(bool)),                  SLOT(onSelectMesh(bool)));
   connect(ActionGroup,      SIGNAL(buttonClicked(int)),             SLOT(onActionClicked(int)));
@@ -360,9 +361,21 @@ void SMESHGUI_RotationDlg::Init (bool ResetControls)
   buttonOk->setEnabled(false);
   buttonApply->setEnabled(false);
 
+  if ( !ResetControls && !isApplyAndClose() && // make highlight move upon [Apply] (IPAL20729)
+       myActor && !myActor->getIO().IsNull() &&
+       ActionGroup->button( MOVE_ELEMS_BUTTON )->isChecked() &&
+       !CheckBoxMesh->isChecked() ) // move selected elements
+  {
+    if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+    {
+      aViewWindow->highlight( myActor->getIO(), false, false );
+      aViewWindow->highlight( myActor->getIO(), true, true );
+    }
+  }
   myActor = 0;
 
-  if (ResetControls) {
+  if (ResetControls)
+  {
     SpinBox_X->SetValue(0.0);
     SpinBox_Y->SetValue(0.0);
     SpinBox_Z->SetValue(0.0);
@@ -376,10 +389,6 @@ void SMESHGUI_RotationDlg::Init (bool ResetControls)
     CheckBoxMesh->setChecked(false);
     myPreviewCheckBox->setChecked(false);
     onDisplaySimulation(false);
-
-//     MakeGroupsCheck->setChecked(false);
-//     MakeGroupsCheck->setEnabled(false);
-//    onSelectMesh(false);
   }
 
   onSelectMesh(CheckBoxMesh->isChecked());
@@ -522,7 +531,6 @@ bool SMESHGUI_RotationDlg::ClickOnApply()
         anApp->browseObjects( anEntryList, isApplyAndClose() );
     }
     Init(false);
-    SelectionIntoArgument();
 
     SMESHGUI::Modified();
   }
@@ -560,6 +568,32 @@ void SMESHGUI_RotationDlg::reject()
   QDialog::reject();
 }
 
+
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_RotationDlg::onOpenView()
+{
+  if ( mySelector ) {
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    ActivateThisDialog();
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_RotationDlg::onCloseView()
+{
+  DeactivateActiveDialog();
+  mySelector = 0;
+}
+
 //=================================================================================
 // function : ClickOnHelp()
 // purpose  :
@@ -719,52 +753,13 @@ void SMESHGUI_RotationDlg::SelectionIntoArgument()
 
       if ( myMeshes.isEmpty() )
         return;
-      // get IDs from mesh
-        /*
-          SMDS_Mesh* aSMDSMesh = myActor->GetObject()->GetMesh();
-          if (!aSMDSMesh)
-          return;
-
-          for (int i = aSMDSMesh->MinElementID(); i <= aSMDSMesh->MaxElementID(); i++) {
-          const SMDS_MeshElement * e = aSMDSMesh->FindElement(i);
-          if (e) {
-            myElementsId += QString(" %1").arg(i);
-            aNbUnits++;
-          }
-        }
-      } else if (!SMESH::IObjectToInterface<SMESH::SMESH_subMesh>(IO)->_is_nil()) { //SUBMESH
-      // get submesh
-        SMESH::SMESH_subMesh_var aSubMesh = SMESH::IObjectToInterface<SMESH::SMESH_subMesh>(IO);
-
-        // get IDs from submesh
-        SMESH::long_array_var anElementsIds = new SMESH::long_array;
-        anElementsIds = aSubMesh->GetElementsId();
-        for (int i = 0; i < anElementsIds->length(); i++) {
-        myElementsId += QString(" %1").arg(anElementsIds[i]);
-          }
-        aNbUnits = anElementsIds->length();
-      } else { // GROUP
-        // get smesh group
-        SMESH::SMESH_GroupBase_var aGroup =
-        SMESH::IObjectToInterface<SMESH::SMESH_GroupBase>(IO);
-        if (aGroup->_is_nil())
-        return;
-
-          // get IDs from smesh group
-        SMESH::long_array_var anElementsIds = new SMESH::long_array;
-        anElementsIds = aGroup->GetListOfID();
-        for (int i = 0; i < anElementsIds->length(); i++) {
-        myElementsId += QString(" %1").arg(anElementsIds[i]);
-          }
-        aNbUnits = anElementsIds->length();
-        }
-        */
-      } else {
+    }
+    else {
       aNbUnits = SMESH::GetNameOfSelectedElements(mySelector, aList.First(), aString);
       myElementsId = aString;
       if (aNbUnits < 1)
         return;
-      }
+    }
 
     myNbOkElements = true;
 
@@ -772,13 +767,13 @@ void SMESHGUI_RotationDlg::SelectionIntoArgument()
     Handle(SALOME_InteractiveObject) IO = aList.First();
     if ((SMESH::GetMeshByIO(IO))->_is_nil())
       return;
-      
+
     SMESH_Actor* anActor = SMESH::FindActorByObject(SMESH::GetMeshByIO(IO));
     if (!anActor)
       anActor = SMESH::FindActorByEntry(IO->getEntry());
     if (!anActor && !CheckBoxMesh->isChecked())
       return;
-      
+
     aNbUnits = SMESH::GetNameOfSelectedNodes(mySelector, IO, aString);
     if (aNbUnits != 1)
       return;
@@ -912,8 +907,13 @@ void SMESHGUI_RotationDlg::ActivateThisDialog()
 //=================================================================================
 void SMESHGUI_RotationDlg::enterEvent (QEvent*)
 {
-  if (!GroupConstructors->isEnabled())
+  if (!GroupConstructors->isEnabled()) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector) {
+      mySelector = aViewWindow->GetSelector();
+    }
     ActivateThisDialog();
+  }
 }
 
 //=================================================================================
@@ -947,7 +947,6 @@ void SMESHGUI_RotationDlg::onSelectMesh (bool toSelectMesh)
       aViewWindow->SetSelectionMode( CellSelection );
     LineEditElements->setReadOnly(false);
     LineEditElements->setValidator(myIdValidator);
-    onTextChange(LineEditElements->text());
     hidePreview();
   }
 
index f6e84eca5df697e8423e3ea79638b840d6a7b21b..8b4be67e662d8e5c492f25c109eee76d81708f66 100644 (file)
@@ -148,6 +148,8 @@ private slots:
   void                   onSelectMesh( bool );
   void                   onVectorChanged();
   void                   onActionClicked( int );
+  void                   onOpenView();
+  void                   onCloseView();
   void                   setFilters();
 };
 
index df0989317ec2d6a9d0339e1ae721d6de35b19182..1e712f0a348148f80ff5c8ed8100e4de4835c852 100644 (file)
@@ -308,7 +308,10 @@ SMESHGUI_ScaleDlg::SMESHGUI_ScaleDlg( SMESHGUI* theModule ) :
   connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()),   this, SLOT(SelectionIntoArgument()));
   /* to close dialog if study change */
-  connect(mySMESHGUI,       SIGNAL (SignalCloseAllDialogs()), this, SLOT(reject()));
+  connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()),      this, SLOT(reject()));
+  connect(mySMESHGUI, SIGNAL(SignalActivatedViewManager()), this, SLOT(onOpenView()));
+  connect(mySMESHGUI, SIGNAL(SignalCloseView()),            this, SLOT(onCloseView()));
+
   connect(LineEditElements, SIGNAL(textChanged(const QString&)),    SLOT(onTextChange(const QString&)));
   connect(CheckBoxMesh,     SIGNAL(toggled(bool)),                  SLOT(onSelectMesh(bool)));
   connect(ActionGroup,      SIGNAL(buttonClicked(int)),             SLOT(onActionClicked(int)));
@@ -605,6 +608,31 @@ void SMESHGUI_ScaleDlg::reject()
   QDialog::reject();
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_ScaleDlg::onOpenView()
+{
+  if ( mySelector ) {
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    ActivateThisDialog();
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_ScaleDlg::onCloseView()
+{
+  DeactivateActiveDialog();
+  mySelector = 0;
+}
+
 //=================================================================================
 // function : ClickOnHelp()
 // purpose  :
@@ -944,8 +972,13 @@ void SMESHGUI_ScaleDlg::ActivateThisDialog()
 //=================================================================================
 void SMESHGUI_ScaleDlg::enterEvent (QEvent*)
 {
-  if (!ConstructorsBox->isEnabled())
+  if (!ConstructorsBox->isEnabled()) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector) {
+      mySelector = aViewWindow->GetSelector();
+    }
     ActivateThisDialog();
+  }
 }
 
 //=======================================================================
index 63162323976ccef600337dcf690760328d1d8827..a7a15d6ba98b4b6519679364bcd0c7ada3d26208 100644 (file)
@@ -144,6 +144,8 @@ private slots:
   void                   onTextChange( const QString& );
   void                   onSelectMesh( bool );
   void                   onActionClicked( int );
+  void                   onOpenView();
+  void                   onCloseView();
   void                   setFilters();
 };
 
index 1c99de1d85176c7e9cd25d17ce726f604f3c6cf3..3661fa85304ecae7834acfa364b28035977602ed 100644 (file)
@@ -128,7 +128,7 @@ QVariant SMESHGUI_Selection::parameter( const int ind, const QString& p ) const
   else if ( p=="displayMode" )          val = QVariant( displayMode( ind ) );
   else if ( p=="isComputable" )         val = QVariant( isComputable( ind ) );
   else if ( p=="isPreComputable" )      val = QVariant( isPreComputable( ind ) );
-  else if ( p=="hasReference" )         val = QVariant( hasReference( ind ) );
+  else if ( p=="hasGeomReference" )     val = QVariant( hasGeomReference( ind ) );
   else if ( p=="isImported" )           val = QVariant( isImported( ind ) );
   else if ( p=="facesOrientationMode" ) val = QVariant( facesOrientationMode( ind ) );
   else if ( p=="groupType" )            val = QVariant( groupType( ind ) );
@@ -355,7 +355,7 @@ QString SMESHGUI_Selection::controlMode() const
     QString mode = myControls[0];
     for( int ind = 1; ind < myControls.count(); ind++ ) {
       if( mode != myControls[ind] )
-        return "eNone";
+        return "eMixed"; // different controls used for different actors
     }
     return mode;
   }
@@ -492,62 +492,58 @@ int SMESHGUI_Selection::dim( int ind ) const
 
 //=======================================================================
 //function : isComputable
-//purpose  : 
+//purpose  : return true for a ready-to-compute mesh
 //=======================================================================
 
 QVariant SMESHGUI_Selection::isComputable( int ind ) const
 {
-  if ( ind >= 0 && ind < myTypes.count() && myTypes[ind] != "Unknown" )
+  if ( ind >= 0 && ind < myTypes.count() && myTypes[ind] == "Mesh" )
   {
+    QMap<int,int> modeMap;
     _PTR(SObject) so = SMESH::GetActiveStudyDocument()->FindObjectID( entry( ind ).toLatin1().data() );
-    CORBA::Object_var obj = SMESH::SObjectToObject( so, SMESH::GetActiveStudyDocument() );
-    if( !CORBA::is_nil( obj ) ) {
-      SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( obj );
-      if ( !CORBA::is_nil( mesh ) ) {
-        if ( mesh->HasShapeToMesh() ) {
-          GEOM::GEOM_Object_var shape = SMESH::GetShapeOnMeshOrSubMesh( so );
-          return QVariant( !shape->_is_nil() );
-        }
-        else
-        {
-          return QVariant( mesh->NbFaces() !=0 );
-        }
-      }
-      else
-      {
-        GEOM::GEOM_Object_var shape = SMESH::GetShapeOnMeshOrSubMesh( so );
-        return QVariant( !shape->_is_nil() );
-      }
-    }
+    SMESHGUI_PrecomputeOp::getAssignedAlgos( so, modeMap );
+    return QVariant( modeMap.size() > 0 );
   }
   return QVariant( false );
 }
 
 //=======================================================================
 //function : isPreComputable
-//purpose  : 
+//purpose  : returns true for a mesh with algorithms
 //=======================================================================
 
 QVariant SMESHGUI_Selection::isPreComputable( int ind ) const
 {
-  if ( ind >= 0 && ind < myTypes.count() && myTypes[ind] != "Unknown" )
+  if ( ind >= 0 && ind < myTypes.count() && myTypes[ind] == "Mesh" )
   {
-    QMap<int,int> modeMap;
-    _PTR(SObject) pMesh = SMESH::GetActiveStudyDocument()->FindObjectID( entry( ind ).toLatin1().data() );
-    SMESHGUI_PrecomputeOp::getAssignedAlgos( pMesh, modeMap );
-    return QVariant( modeMap.size() > 1 );
+    int maxDim = dim( ind );
+    if ( maxDim < 2 ) // we can preview 1D or 2D
+    {
+      QMap<int,int> modeMap;
+      _PTR(SObject) pMesh = SMESH::GetActiveStudyDocument()->FindObjectID( entry( ind ).toLatin1().data() );
+      SMESHGUI_PrecomputeOp::getAssignedAlgos( pMesh, modeMap );
+      if ( modeMap.size() > 1 )
+        return QVariant( ( modeMap.contains( SMESH::DIM_3D )) ||
+                         ( modeMap.contains( SMESH::DIM_2D ) && maxDim < 1 ));
+    }
   }
   return QVariant( false );
 }
 
 //=======================================================================
-//function : hasReference
-//purpose  : 
+//function : hasGeomReference
+//purpose  : returns true for a mesh or sub-mesh on geometry
 //=======================================================================
 
-QVariant SMESHGUI_Selection::hasReference( int ind ) const
+QVariant SMESHGUI_Selection::hasGeomReference( int ind ) const
 {
-  return QVariant( isReference( ind ) );
+  if ( ind >= 0 && ind < myTypes.count() && myTypes[ind] != "Unknown" )
+  {
+    _PTR(SObject) so = SMESH::GetActiveStudyDocument()->FindObjectID( entry( ind ).toLatin1().data() );
+    GEOM::GEOM_Object_var shape = SMESH::GetShapeOnMeshOrSubMesh( so );
+    return QVariant( !shape->_is_nil() );
+  }
+  return QVariant( false );
 }
 
 //=======================================================================
index f26b9979ce4f9f0d23c395e6e545262bd0933743..de0d0d12f1f73c02a8bc64e2623b77152d49c87a 100644 (file)
@@ -58,7 +58,7 @@ public:
   virtual int             dim( int ) const;
   virtual QVariant        isComputable( int ) const;
   virtual QVariant        isPreComputable( int ) const;
-  virtual QVariant        hasReference( int ) const;
+  virtual QVariant        hasGeomReference( int ) const;
   virtual QVariant        isVisible( int ) const;
 
   virtual QString         quadratic2DMode( int ) const;
index d739c83a28860ee511705aef5011fb650e679e44..d7a47f7d08a6bbf466eed370c439a137cd5ebf32 100644 (file)
 #include "SMESHGUI_SewingDlg.h"
 
 #include "SMESHGUI.h"
+#include "SMESHGUI_IdPreview.h"
+#include "SMESHGUI_IdValidator.h"
+#include "SMESHGUI_MergeDlg.h"
+#include "SMESHGUI_MeshUtils.h"
+#include "SMESHGUI_PreVisualObj.h"
+#include "SMESHGUI_SpinBox.h"
 #include "SMESHGUI_Utils.h"
 #include "SMESHGUI_VTKUtils.h"
-#include "SMESHGUI_MeshUtils.h"
-#include "SMESHGUI_IdValidator.h"
 
-#include <SMESH_Actor.h>
 #include <SMDS_Mesh.hxx>
+#include <SMESH_Actor.h>
+#include <SMESH_TypeDefs.hxx>
 
 // SALOME GUI includes
-#include <SUIT_Session.h>
-#include <SUIT_ResourceMgr.h>
+#include <LightApp_Application.h>
+#include <LightApp_SelectionMgr.h>
+#include <SALOMEDSClient_Study.hxx>
+#include <SALOME_ListIO.hxx>
 #include <SUIT_Desktop.h>
 #include <SUIT_MessageBox.h>
 #include <SUIT_OverrideCursor.h>
-
-#include <LightApp_Application.h>
-#include <LightApp_SelectionMgr.h>
-
+#include <SUIT_ResourceMgr.h>
+#include <SUIT_Session.h>
 #include <SVTK_ViewModel.h>
 #include <SVTK_ViewWindow.h>
-#include <SALOME_ListIO.hxx>
+#include <SalomeApp_IntSpinBox.h>
+#include <SalomeApp_Tools.h>
 
 // OCCT includes
 #include <TColStd_MapOfInteger.hxx>
 // Qt includes
 #include <QApplication>
 #include <QButtonGroup>
+#include <QCheckBox>
+#include <QGridLayout>
 #include <QGroupBox>
+#include <QHBoxLayout>
+#include <QKeyEvent>
 #include <QLabel>
 #include <QLineEdit>
+#include <QListWidget>
 #include <QPushButton>
 #include <QRadioButton>
-#include <QCheckBox>
-#include <QHBoxLayout>
+#include <QToolButton>
 #include <QVBoxLayout>
-#include <QGridLayout>
-#include <QKeyEvent>
-
-// IDL includes
-#include <SALOMEconfig.h>
-#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
 
 #define SPACING 6
 #define MARGIN  11
 
+namespace
+{
+  enum ActionType { MODE_AUTO=0, MODE_MANUAL,
+                    MOVE_LEFT_1=0, MOVE_RIGHT_1, MOVE_LEFT_2, MOVE_RIGHT_2,
+                    GROUP_COLOR=Qt::UserRole, GROUP_INDEX };
+}
+
+//=================================================================================
+/*!
+ * \brief Dispalayer of free borders
+ */
+//=================================================================================
+
+struct SMESHGUI_SewingDlg::BorderGroupDisplayer
+{
+  const SMESH::ListOfFreeBorders& myBorders;
+  const SMESH::FreeBordersGroup&  myGroup;
+  QColor                          myColor;
+  SMESH::SMESH_Mesh_ptr           myMesh;
+
+  std::vector< SMESH_Actor* >     myPartActors;
+  SVTK_ViewWindow*                myViewWindow;
+  SMESHGUI_IdPreview              myIdPreview;
+
+  BorderGroupDisplayer( const SMESH::CoincidentFreeBorders& borders,
+                        int                                 groupIndex,
+                        QColor                              color,
+                        SMESH::SMESH_Mesh_ptr               mesh);
+  ~BorderGroupDisplayer();
+  void Hide();
+  void ShowGroup( bool wholeBorders );
+  void ShowPart( int partIndex, bool toEdit );
+  void Update();
+
+private:
+  void getPartEnds( int partIndex, std::vector<int> & ids, std::list<gp_XYZ>& coords);
+};
+
 //=================================================================================
 // class    : SMESHGUI_SewingDlg()
 // purpose  :
@@ -89,6 +131,7 @@ SMESHGUI_SewingDlg::SMESHGUI_SewingDlg( SMESHGUI* theModule )
   QPixmap image2 (mgr->loadPixmap("SMESH", tr("ICON_SMESH_SEWING_BORDERTOSIDE")));
   QPixmap image3 (mgr->loadPixmap("SMESH", tr("ICON_SMESH_SEWING_SIDEELEMENTS")));
   QPixmap image4 (mgr->loadPixmap("SMESH", tr("ICON_SELECT")));
+  QPixmap IconRemove(mgr->loadPixmap("SMESH", tr("ICON_REMOVE")));
 
   setModal(false);
   setAttribute(Qt::WA_DeleteOnClose, true);
@@ -203,9 +246,166 @@ SMESHGUI_SewingDlg::SMESHGUI_SewingDlg( SMESHGUI* theModule )
   // Control for the polyedres creation to obtain conform mesh
   CheckBoxPolyedrs = new QCheckBox(tr("CREATE_POLYEDRS_NEAR_BOUNDARY"), GroupArguments);
 
+  /***************************************************************/
+  // Controls to switch free borders mode ( auto || manual )
+
+  ModeGroup = new QGroupBox( tr( "SMESH_MODE" ), GroupArguments );
+  ModeButGrp = new QButtonGroup( ModeGroup );
+  QHBoxLayout* aModeGroupLayout = new QHBoxLayout( ModeGroup );
+  aModeGroupLayout->setMargin( MARGIN );
+  aModeGroupLayout->setSpacing( SPACING );
+
+  QRadioButton* rb1 = new QRadioButton( tr( "SMESH_AUTOMATIC" ), ModeGroup );
+  QRadioButton* rb2 = new QRadioButton( tr( "SMESH_MANUAL"    ), ModeGroup );
+  ModeButGrp->addButton( rb1, MODE_AUTO );
+  ModeButGrp->addButton( rb2, MODE_MANUAL );
+  aModeGroupLayout->addWidget( rb1 );
+  aModeGroupLayout->addWidget( rb2 );
+  rb1->setChecked(true);
+
+  /***************************************************************/
+  // Controls for detecting coincident free borders
+
+  SewFreeBordersWidget = new QWidget( GroupArguments );
+  QVBoxLayout* aSewFreeBordersLayout = new QVBoxLayout( SewFreeBordersWidget );
+  aSewFreeBordersLayout->setMargin( 0 );
+  aSewFreeBordersLayout->setSpacing( SPACING );
+
+  // Tolerance
+  QWidget* TolAndAuto = new QWidget(SewFreeBordersWidget);
+  QLabel* TextLabelTolerance = new QLabel(tr("SMESH_TOLERANCE"), TolAndAuto);
+  SpinBoxTolerance = new SMESHGUI_SpinBox(TolAndAuto);
+  SpinBoxTolerance->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+  SpinBoxTolerance->RangeStepAndValidator(0.0, COORD_MAX, 0.00001, "len_tol_precision");
+  SpinBoxTolerance->SetValue(0.); // auto-tolerance
+
+  // Auto Sewing
+  AutoSewCheck = new QCheckBox(tr("AUTO_SEWING"), TolAndAuto);
+  AutoSewCheck->setChecked( true );
+
+  // mesh
+  QGroupBox* GroupMesh = new QGroupBox(tr("SMESH_MESH"), SewFreeBordersWidget);
+  QHBoxLayout* GroupMeshLayout = new QHBoxLayout(GroupMesh);
+  GroupMeshLayout->setSpacing(SPACING);
+  GroupMeshLayout->setMargin(MARGIN);
+
+  QLabel* TextLabelName = new QLabel(tr("SMESH_NAME"), GroupMesh);
+  //SelectMeshButton = new QPushButton(GroupMesh);
+  //SelectMeshButton->setIcon(IconSelect);
+  LineEditMesh = new QLineEdit(GroupMesh);
+  LineEditMesh->setReadOnly(true);
+
+  GroupMeshLayout->addWidget(TextLabelName);
+  //GroupMeshLayout->addWidget(SelectMeshButton);
+  GroupMeshLayout->addWidget(LineEditMesh);
+
+  QGridLayout* TolAndAutoLayout = new QGridLayout( TolAndAuto );
+  TolAndAutoLayout->setSpacing(SPACING);
+  TolAndAutoLayout->setMargin(0);
+  TolAndAutoLayout->addWidget(GroupMesh,          0, 0, 1, 2 );
+  TolAndAutoLayout->addWidget(TextLabelTolerance, 1, 0 );
+  TolAndAutoLayout->addWidget(SpinBoxTolerance,   1, 1 );
+  TolAndAutoLayout->addWidget(AutoSewCheck,       2, 0 );
+
+  aSewFreeBordersLayout->addWidget( TolAndAuto );
+
+  /******************/
+  // Coincident group
+  GroupCoincidentWidget = new QWidget(SewFreeBordersWidget);
+  QGridLayout* GroupCoincidentLayout = new QGridLayout(GroupCoincidentWidget);
+  GroupCoincidentLayout->setSpacing(SPACING);
+  GroupCoincidentLayout->setMargin(0);
+
+  QGroupBox* GroupCoincident = new QGroupBox(tr("COINCIDENT_FREE_BORDERS"), GroupCoincidentWidget);
+  QGridLayout* aCoincidentLayout = new QGridLayout(GroupCoincident);
+  aCoincidentLayout->setSpacing(SPACING);
+  aCoincidentLayout->setMargin(MARGIN);
+
+  /*******/
+  // borders
+  ListCoincident = new QListWidget(GroupCoincident);
+  ListCoincident->setSelectionMode(QListWidget::ExtendedSelection);
+
+  DetectButton      = new QPushButton(tr("DETECT"),           GroupCoincident);
+  RemoveGroupButton = new QPushButton(tr("SMESH_BUT_REMOVE"), GroupCoincident);
+
+  SelectAllCheck = new QCheckBox(tr("SELECT_ALL"), GroupCoincident);
+
+  aCoincidentLayout->addWidget(ListCoincident,    0, 0, 5, 2);
+  aCoincidentLayout->addWidget(DetectButton,      1, 2);
+  aCoincidentLayout->addWidget(RemoveGroupButton, 3, 2);
+  aCoincidentLayout->addWidget(SelectAllCheck,    5, 0);
+  aCoincidentLayout->setRowMinimumHeight(1, 10);
+  aCoincidentLayout->setRowStretch      (4, 5);
+  aCoincidentLayout->setRowStretch      (5, 0);
+
+  /*****************************************/
+  // Controls for editing the selected group
+
+  QGroupBox* GroupEdit = new QGroupBox(tr("EDIT_SELECTED_GROUP"), GroupCoincidentWidget);
+  QGridLayout* GroupEditLayout = new QGridLayout(GroupEdit);
+  GroupEditLayout->setSpacing(SPACING);
+  GroupEditLayout->setMargin(MARGIN);
+
+  ListEdit = new QListWidget(GroupEdit);
+  ListEdit->setFlow( QListView::LeftToRight );
+  ListEdit->setSelectionMode(QListWidget::ExtendedSelection);
+  SetFirstButton = new QPushButton(GroupEdit);
+  SetFirstButton->setIcon(QPixmap(SMESHGUI_MergeDlg::IconFirst()));
+  RemoveElemButton = new QPushButton(GroupEdit);
+  RemoveElemButton->setIcon(IconRemove);
+
+  MoveBorderEndsButGrp = new QButtonGroup( GroupEdit );
+  QToolButton* moveBut1 = new QToolButton( GroupEdit );
+  QToolButton* moveBut2 = new QToolButton( GroupEdit );
+  QToolButton* moveBut3 = new QToolButton( GroupEdit );
+  QToolButton* moveBut4 = new QToolButton( GroupEdit );
+  moveBut1->setArrowType( Qt::LeftArrow );
+  moveBut2->setArrowType( Qt::RightArrow );
+  moveBut3->setArrowType( Qt::LeftArrow );
+  moveBut4->setArrowType( Qt::RightArrow );
+  MoveBorderEndsButGrp->addButton( moveBut1, MOVE_LEFT_1 );
+  MoveBorderEndsButGrp->addButton( moveBut2, MOVE_RIGHT_1 );
+  MoveBorderEndsButGrp->addButton( moveBut3, MOVE_LEFT_2 );
+  MoveBorderEndsButGrp->addButton( moveBut4, MOVE_RIGHT_2 );
+
+  SwapBut  = new QPushButton( "<->", GroupEdit );
+  BorderEndLine[0] = new QLineEdit( GroupEdit );
+  BorderEndLine[1] = new QLineEdit( GroupEdit );
+  BorderEndLine[0]->setReadOnly(true);
+  BorderEndLine[1]->setReadOnly(true);
+  QLabel* StepLabel = new QLabel(tr("STEP"), GroupEdit );
+  StepSpin = new SalomeApp_IntSpinBox( 1, 100000, 1, GroupEdit,
+                                       /*acceptNames=*/false, /*showTip=*/false );
+  StepSpin->setValue( 1 );
+
+  GroupEditLayout->addWidget(ListEdit,         0, 0, 1, 8);
+  GroupEditLayout->addWidget(SetFirstButton,   0, 8);
+  GroupEditLayout->addWidget(RemoveElemButton, 0, 9);
+  GroupEditLayout->addWidget(moveBut1,         1, 0);
+  GroupEditLayout->addWidget(BorderEndLine[0], 1, 1);
+  GroupEditLayout->addWidget(moveBut2,         1, 2);
+  GroupEditLayout->addWidget(moveBut3,         1, 3);
+  GroupEditLayout->addWidget(BorderEndLine[1], 1, 4);
+  GroupEditLayout->addWidget(moveBut4,         1, 5);
+  GroupEditLayout->setColumnStretch(              6, 5 );
+  GroupEditLayout->addWidget(SwapBut,          1, 7);
+  GroupEditLayout->addWidget(StepLabel,        1, 8);
+  GroupEditLayout->addWidget(StepSpin,         1, 9);
+  GroupEditLayout->setRowStretch( 0, 1 );
+
+  GroupCoincidentLayout->addWidget( GroupCoincident );
+  GroupCoincidentLayout->addWidget( GroupEdit );
+  GroupCoincidentLayout->setRowStretch( 0, 10 );
+  GroupCoincidentLayout->setRowStretch( 1, 1 );
+
+  aSewFreeBordersLayout->addWidget( GroupCoincidentWidget );
+
   // layout
+  GroupArgumentsLayout->addWidget(ModeGroup);
   GroupArgumentsLayout->addWidget(SubGroup1);
   GroupArgumentsLayout->addWidget(SubGroup2);
+  GroupArgumentsLayout->addWidget(SewFreeBordersWidget);
   GroupArgumentsLayout->addWidget(CheckBoxMerge);
   GroupArgumentsLayout->addWidget(CheckBoxPolygons);
   GroupArgumentsLayout->addWidget(CheckBoxPolyedrs);
@@ -238,6 +438,7 @@ SMESHGUI_SewingDlg::SMESHGUI_SewingDlg( SMESHGUI* theModule )
   SMESHGUI_SewingDlgLayout->addWidget(ConstructorsBox);
   SMESHGUI_SewingDlgLayout->addWidget(GroupArguments);
   SMESHGUI_SewingDlgLayout->addWidget(GroupButtons);
+  //SMESHGUI_SewingDlgLayout->setStretch( 2, 10 );
 
   /* Initialisations */
   RadioButton1->setChecked(true);
@@ -253,6 +454,10 @@ SMESHGUI_SewingDlg::SMESHGUI_SewingDlg( SMESHGUI* theModule )
 
   myHelpFileName = "sewing_meshes_page.html";
 
+  myActor = 0;
+  myStoredEntityMode = 0;
+
+  setDisplayMode();
   Init();
 
   /* signals and slots connections */
@@ -272,7 +477,9 @@ SMESHGUI_SewingDlg::SMESHGUI_SewingDlg( SMESHGUI* theModule )
   connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
   /* to close dialog if study change */
-  connect(mySMESHGUI, SIGNAL (SignalCloseAllDialogs()), this, SLOT(reject()));
+  connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()),      this, SLOT(reject()));
+  connect(mySMESHGUI, SIGNAL(SignalActivatedViewManager()), this, SLOT(onOpenView()));
+  connect(mySMESHGUI, SIGNAL(SignalCloseView()),            this, SLOT(onCloseView()));
 
   connect(LineEdit1, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
   connect(LineEdit2, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
@@ -281,6 +488,18 @@ SMESHGUI_SewingDlg::SMESHGUI_SewingDlg( SMESHGUI* theModule )
   connect(LineEdit5, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
   connect(LineEdit6, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
 
+  connect(ModeButGrp,           SIGNAL(buttonClicked(int)),     SLOT(onModeChange(int)));
+  connect(AutoSewCheck,         SIGNAL(stateChanged(int)),      SLOT(onAutoSew(int)));
+  connect(DetectButton,         SIGNAL(clicked()),              SLOT(onDetectClicked()));
+  connect(RemoveGroupButton,    SIGNAL(clicked()),              SLOT(onRemoveGroupClicked()));
+  connect(ListCoincident,       SIGNAL(itemSelectionChanged()), SLOT(onSelectGroup()));
+  connect(SelectAllCheck,       SIGNAL(stateChanged(int)),      SLOT(onSelectAll(int)));
+  connect(ListEdit,             SIGNAL(itemSelectionChanged()), SLOT(onSelectBorderPartFromGroup()));
+  connect(SetFirstButton,       SIGNAL(clicked()),              SLOT(onSetFirstClicked()));
+  connect(RemoveElemButton,     SIGNAL(clicked()),              SLOT(onRemoveElemClicked()));
+  connect(MoveBorderEndsButGrp, SIGNAL(buttonClicked(int)),     SLOT(onMoveBorderEnd(int)));
+  connect(SwapBut,              SIGNAL(clicked()),              SLOT(onSwapClicked()));
+
   ConstructorsClicked(0);
 }
 
@@ -290,6 +509,12 @@ SMESHGUI_SewingDlg::SMESHGUI_SewingDlg( SMESHGUI* theModule )
 //=================================================================================
 SMESHGUI_SewingDlg::~SMESHGUI_SewingDlg()
 {
+  for ( size_t i = 0; i < myBorderDisplayers.size(); ++i )
+  {
+    delete myBorderDisplayers[ i ];
+    myBorderDisplayers[ i ] = 0;
+  }
+  myBorderDisplayers.clear();
 }
 
 //=================================================================================
@@ -300,13 +525,16 @@ void SMESHGUI_SewingDlg::Init()
 {
   myBusy = false;
 
-  myEditCurrentArgument = LineEdit1;
-  LineEdit1->setFocus();
-  myActor = 0;
+  if ( LineEdit1->isVisible() )
+    myEditCurrentArgument = LineEdit1;
+  else
+    myEditCurrentArgument = LineEditMesh;
+  myEditCurrentArgument->setFocus();
+  //myActor = 0;
   myMesh = SMESH::SMESH_Mesh::_nil();
-  CheckBoxMerge->setChecked(false);
-  CheckBoxPolygons->setChecked(false);
-  CheckBoxPolyedrs->setChecked(false);
+  // CheckBoxMerge->setChecked(false);
+  // CheckBoxPolygons->setChecked(false);
+  // CheckBoxPolyedrs->setChecked(false);
   SelectionIntoArgument();
 }
 
@@ -347,75 +575,100 @@ void SMESHGUI_SewingDlg::ConstructorsClicked (int constructorId)
       CheckBoxPolyedrs->hide();
   }
 
+  CheckBoxMerge->setVisible ( constructorId == 3 );
+
+  if (( !SubGroup1->isVisible() ) &&
+      ( constructorId != 0 || ModeButGrp->checkedId() == MODE_MANUAL ))
+  {
+    SubGroup1->show();
+    SubGroup2->show();
+  }
+
+  if ( constructorId != 0 )
+  {
+    ModeGroup->hide();
+    SewFreeBordersWidget->hide();
+    restoreDisplayMode();
+  }
+
+  bool isNodeSelection = true;
+
   switch (constructorId) {
   case 0:
-    {
-      GroupArguments->setTitle(tr("SEW_FREE_BORDERS"));
-      SubGroup1->setTitle(tr("BORDER_1"));
-      SubGroup2->setTitle(tr("BORDER_2"));
+  {
+    GroupArguments->setTitle(tr("SEW_FREE_BORDERS"));
+    SubGroup1->setTitle(tr("BORDER_1"));
+    SubGroup2->setTitle(tr("BORDER_2"));
 
-        if (!CheckBoxPolygons->isVisible())
-          CheckBoxPolygons->show();
-        if (!CheckBoxPolyedrs->isVisible())
-          CheckBoxPolyedrs->show();
+    if (!CheckBoxPolygons->isVisible())
+      CheckBoxPolygons->show();
+    if (!CheckBoxPolyedrs->isVisible())
+      CheckBoxPolyedrs->show();
 
-      break;
+    if ( !ModeGroup->isVisible() )
+    {
+      ModeGroup->show();
     }
+    onModeChange( ModeButGrp->checkedId() );
+
+    isNodeSelection = ( ModeButGrp->checkedId() == MODE_MANUAL );
+
+    break;
+  }
   case 1:
-    {
-      GroupArguments->setTitle(tr("SEW_CONFORM_FREE_BORDERS"));
-      SubGroup1->setTitle(tr("BORDER_1"));
-      SubGroup2->setTitle(tr("BORDER_2"));
+  {
+    GroupArguments->setTitle(tr("SEW_CONFORM_FREE_BORDERS"));
+    SubGroup1->setTitle(tr("BORDER_1"));
+    SubGroup2->setTitle(tr("BORDER_2"));
 
-      TextLabel6->setEnabled(false);
-      SelectButton6->setEnabled(false);
-      LineEdit6->setEnabled(false);
+    TextLabel6->setEnabled(false);
+    SelectButton6->setEnabled(false);
+    LineEdit6->setEnabled(false);
 
-      myOk6 = true;
+    myOk6 = true;
 
-      break;
-    }
+    break;
+  }
   case 2:
-    {
-      GroupArguments->setTitle(tr("SEW_BORDER_TO_SIDE"));
-      SubGroup1->setTitle(tr("BORDER"));
-      SubGroup2->setTitle(tr("SIDE"));
-
-      TextLabel5->setEnabled(false);
-      SelectButton5->setEnabled(false);
-      LineEdit5->setEnabled(false);
-
-      if (!CheckBoxPolygons->isVisible())
-        CheckBoxPolygons->show();
-      if (!CheckBoxPolyedrs->isVisible())
-        CheckBoxPolyedrs->show();
-      
-      myOk5 = true;
-
-      break;
-    }
-  case 3:
-    {
-      GroupArguments->setTitle(tr("SEW_SIDE_ELEMENTS"));
-      SubGroup1->setTitle(tr("SIDE_1"));
-      SubGroup2->setTitle(tr("SIDE_2"));
+  {
+    GroupArguments->setTitle(tr("SEW_BORDER_TO_SIDE"));
+    SubGroup1->setTitle(tr("BORDER"));
+    SubGroup2->setTitle(tr("SIDE"));
 
-      TextLabel1->setText(tr("SMESH_ID_ELEMENTS"));
-      TextLabel2->setText(tr("NODE1_TO_MERGE"));
-      TextLabel3->setText(tr("NODE2_TO_MERGE"));
-      TextLabel4->setText(tr("SMESH_ID_ELEMENTS"));
-      TextLabel5->setText(tr("NODE1_TO_MERGE"));
-      TextLabel6->setText(tr("NODE2_TO_MERGE"));
+    TextLabel5->setEnabled(false);
+    SelectButton5->setEnabled(false);
+    LineEdit5->setEnabled(false);
 
-      LineEdit1->setValidator(new SMESHGUI_IdValidator(this));
-      LineEdit4->setValidator(new SMESHGUI_IdValidator(this));
+    if (!CheckBoxPolygons->isVisible())
+      CheckBoxPolygons->show();
+    if (!CheckBoxPolyedrs->isVisible())
+      CheckBoxPolyedrs->show();
 
-      SMESH::SetPointRepresentation(false);
+    myOk5 = true;
 
-      if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
-        aViewWindow->SetSelectionMode(CellSelection);
-      break;
-    }
+    break;
+  }
+  case 3:
+  {
+    GroupArguments->setTitle(tr("SEW_SIDE_ELEMENTS"));
+    SubGroup1->setTitle(tr("SIDE_1"));
+    SubGroup2->setTitle(tr("SIDE_2"));
+
+    TextLabel1->setText(tr("SMESH_ID_ELEMENTS"));
+    TextLabel2->setText(tr("NODE1_TO_MERGE"));
+    TextLabel3->setText(tr("NODE2_TO_MERGE"));
+    TextLabel4->setText(tr("SMESH_ID_ELEMENTS"));
+    TextLabel5->setText(tr("NODE1_TO_MERGE"));
+    TextLabel6->setText(tr("NODE2_TO_MERGE"));
+
+    LineEdit1->setValidator(new SMESHGUI_IdValidator(this));
+    LineEdit4->setValidator(new SMESHGUI_IdValidator(this));
+
+    isNodeSelection = false;
+    if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+      aViewWindow->SetSelectionMode(CellSelection);
+    break;
+  }
   }
 
   if (constructorId != 3) {
@@ -428,21 +681,608 @@ void SMESHGUI_SewingDlg::ConstructorsClicked (int constructorId)
 
     LineEdit1->setValidator(new SMESHGUI_IdValidator(this, 1));
     LineEdit4->setValidator(new SMESHGUI_IdValidator(this, 1));
+  }
 
-    SMESH::SetPointRepresentation(true);
+  if ( myActor )
+    myActor->SetPointRepresentation( isNodeSelection );
 
-    if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
-      aViewWindow->SetSelectionMode(NodeSelection);
-  }
+  if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+    aViewWindow->SetSelectionMode( isNodeSelection ? NodeSelection : ActorSelection );
+
+  UpdateButtons();
 
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
   mySelectionMgr->setSelectedObjects( io );
 
   QApplication::instance()->processEvents();
   updateGeometry();
+
   resize(100,100);
 }
 
+//=======================================================================
+//function : storeDisplayMode
+//purpose  : save representation of a mesh and switch it to wireframe mode
+//=======================================================================
+
+void SMESHGUI_SewingDlg::setDisplayMode()
+{
+  if ( myStoredEntityMode )
+    return;
+  myStoredEntityMode = 0;
+  myStoredRepresentation = -1;
+
+  if ( myActor && AutoSewCheck->isVisible() && !AutoSewCheck->isChecked() )
+  {
+    myStoredEntityMode     = myActor->GetEntityMode();
+    myStoredRepresentation = myActor->GetRepresentation();
+
+    myActor->SetEntityMode( myStoredEntityMode & ~SMESH_Actor::eVolumes );
+    myActor->SetRepresentation( SMESH_Actor::eEdge );
+  }
+}
+
+//=======================================================================
+//function : restoreDisplayMode
+//purpose  : restore representation of a mesh
+//=======================================================================
+
+void SMESHGUI_SewingDlg::restoreDisplayMode()
+{
+  if ( myActor && myStoredEntityMode )
+  {
+    if ( myActor->GetEntityMode() == ( myStoredEntityMode & ~SMESH_Actor::eVolumes ))
+      myActor->SetEntityMode( myStoredEntityMode );
+
+    if ( myActor->GetRepresentation() == SMESH_Actor::eEdge )
+      myActor->SetRepresentation( myStoredRepresentation );
+
+    myStoredEntityMode = 0;
+    myStoredRepresentation = -1;
+  }
+  for ( size_t i = 0; i < myBorderDisplayers.size(); ++i )
+    if ( myBorderDisplayers[ i ])
+      myBorderDisplayers[ i ]->Hide();
+}
+
+//=======================================================================
+//function : onModeChange
+//purpose  : SLOT called when mode (auto or manual) of Sew free borders change
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onModeChange( int mode )
+{
+  if ( mode == MODE_MANUAL )
+  {
+    myEditCurrentArgument = LineEdit1;
+    if ( !SubGroup1->isVisible() )
+      SubGroup1->show(), SubGroup2->show();
+    SewFreeBordersWidget->hide();
+  }
+  else
+  {
+    myEditCurrentArgument = LineEditMesh;
+    SubGroup1->hide(), SubGroup2->hide();
+    if ( !SewFreeBordersWidget->isVisible() )
+      SewFreeBordersWidget->show();
+  }
+  if ( myActor )
+    myActor->SetPointRepresentation( mode == MODE_MANUAL );
+
+  if ( SVTK_ViewWindow* aViewWindow = SMESH::GetCurrentVtkView() )
+    aViewWindow->SetSelectionMode( mode == MODE_MANUAL ? NodeSelection : ActorSelection );
+
+  onAutoSew( AutoSewCheck->isChecked() );
+
+  QApplication::instance()->processEvents();
+  updateGeometry();
+
+  resize(100,100);
+}
+
+//=======================================================================
+//function : onAutoSew
+//purpose  : SLOT called when Auto Sewing check box is checked
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onAutoSew( int isAuto )
+{
+  GroupCoincidentWidget->setVisible( !isAuto );
+
+  QApplication::instance()->processEvents();
+
+  SewFreeBordersWidget->hide();
+  if ( ModeButGrp->checkedId() == MODE_AUTO )
+    SewFreeBordersWidget->show();
+
+  if ( isAuto )
+    restoreDisplayMode();
+  else
+    setDisplayMode();
+  SMESH::RepaintCurrentView();
+
+  UpdateButtons();
+
+  updateGeometry();
+  resize(minimumSizeHint());
+}
+
+//=======================================================================
+//function : haveBorders
+//purpose  : Returns true if myBorders have been initialized
+//=======================================================================
+
+bool SMESHGUI_SewingDlg::haveBorders()
+{
+  return ( & myBorders.in() &&
+           myBorders->borders.length() &&
+           myBorders->coincidentGroups.length() );
+}
+
+//=======================================================================
+//function : getGroupText
+//purpose  : Returns a text of a given group of coincident free borders
+//=======================================================================
+
+QString SMESHGUI_SewingDlg::getPartText(const SMESH::FreeBorderPart& aPART)
+{
+  QString text;
+  if ( 0 <= aPART.border && aPART.border < myBorders->borders.length() )
+  {
+    const SMESH::FreeBorder& aBRD = myBorders->borders[ aPART.border ];
+    if ( 0 <= aPART.node1    && aPART.node1 < aBRD.nodeIDs.length() &&
+         0 <= aPART.nodeLast && aPART.nodeLast < aBRD.nodeIDs.length() )
+    {
+      text += QString("( %1 %2 %3 ) ")
+        .arg( aBRD.nodeIDs[ aPART.node1 ] )
+        .arg( aBRD.nodeIDs[ aPART.node2 ] )
+        .arg( aBRD.nodeIDs[ aPART.nodeLast ] );
+    }
+  }
+  return text;
+}
+
+//=======================================================================
+//function : getGroupText
+//purpose  : Returns a text of a given group of coincident free borders
+//=======================================================================
+
+QString SMESHGUI_SewingDlg::getGroupText(int groupIndex)
+{
+  QString text;
+
+  if ( haveBorders()   &&
+       groupIndex >= 0 &&
+       groupIndex < myBorders->coincidentGroups.length() )
+  {
+    const SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ groupIndex ];
+
+    for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
+    {
+      QString partText = getPartText( aGRP[ iP ]);
+      if ( partText.isEmpty() )
+        return "";
+      text += partText;
+    }
+  }
+  return text;
+}
+
+//=======================================================================
+//function : onDetectClicked
+//purpose  : SLOT called when [Detect] is clicked
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onDetectClicked()
+{
+  myBusy = true;
+  ListCoincident->clear();
+
+  if ( myMesh->_is_nil() )
+    return;
+
+  SUIT_OverrideCursor wc;
+
+  SMESH::SMESH_MeshEditor_var editor = myMesh->GetMeshEditor();
+  myBorders = editor->FindCoincidentFreeBorders( SpinBoxTolerance->GetValue() );
+  if ( haveBorders() )
+  {
+    for ( size_t i = 0; i < myBorderDisplayers.size(); ++i )
+    {
+      delete myBorderDisplayers[ i ];
+      myBorderDisplayers[ i ] = 0;
+    }
+    myBorderDisplayers.resize( myBorders->coincidentGroups.length(), 0 );
+
+    for ( uint i = 0; i < myBorders->coincidentGroups.length(); ++i )
+    {
+      QString groupText = getGroupText( i );
+      if ( groupText.isEmpty() )
+        continue;
+
+      QColor groupColor;
+      groupColor.setHsvF( float(i) / myBorders->coincidentGroups.length(), 1., 1. );
+      QPixmap icon( QSize( 20, 20 ));
+      icon.fill( groupColor );
+
+      QListWidgetItem * item = new QListWidgetItem( icon, groupText, ListCoincident );
+      item->setData( GROUP_COLOR, groupColor );
+      item->setData( GROUP_INDEX, i );
+    }
+  }
+  myBusy = false;
+
+  onSelectGroup();
+
+  UpdateButtons();
+}
+
+//=======================================================================
+//function : onRemoveGroupClicked
+//purpose  :
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onRemoveGroupClicked()
+{
+  myBusy = true;
+  QList<QListWidgetItem*> selItems = ListCoincident->selectedItems();
+  for ( int i = 0; i < selItems.count(); ++i )
+  {
+    QListWidgetItem* item = selItems[ i ];
+    item->setSelected( false );
+    int groupIndex = item->data( GROUP_INDEX ).toInt();
+    delete item;
+    if ( myBorderDisplayers[ groupIndex ])
+      myBorderDisplayers[ groupIndex ]->Hide();
+    SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
+    aGRP.length( 0 );
+  }
+  myBusy = false;
+
+  onSelectGroup();
+  UpdateButtons();
+}
+
+//=======================================================================
+//function : showGroup
+//purpose  : display a group of coincident free borders in the Viewer
+//=======================================================================
+
+void SMESHGUI_SewingDlg::showGroup( QListWidgetItem* item )
+{
+  if ( !item ||
+       item->listWidget() != ListCoincident ||
+       !haveBorders())
+    return;
+
+  int    groupIndex = item->data( GROUP_INDEX ).toInt();
+  QColor groupColor = item->data( GROUP_COLOR ).value<QColor>();
+  if ( groupIndex >= 0       &&
+       groupIndex < myBorders->coincidentGroups.length() )
+  {
+    if ( !myBorderDisplayers[ groupIndex ] && SMESH::GetCurrentVtkView())
+      myBorderDisplayers[ groupIndex ] = new BorderGroupDisplayer( myBorders, groupIndex, groupColor, myMesh );
+    bool wholeBorders = setCurrentGroup();
+    if ( myBorderDisplayers[ groupIndex ])
+      myBorderDisplayers[ groupIndex ]->ShowGroup( wholeBorders );
+  }
+}
+
+//=======================================================================
+//function : setCurrentGroup
+//purpose  : set index of a current free border group to myCurGroupIndex
+//=======================================================================
+
+bool SMESHGUI_SewingDlg::setCurrentGroup()
+{
+  if ( !haveBorders() )
+    return false;
+
+  QList<QListWidgetItem*> selItems = ListCoincident->selectedItems();
+  if ( selItems.count() != 1 )
+    return false;
+  
+  myCurGroupIndex = selItems[0]->data( GROUP_INDEX ).toInt();
+
+  return ( myCurGroupIndex >= 0 && myCurGroupIndex < myBorders->coincidentGroups.length() );
+}
+
+//=======================================================================
+//function : setCurrentPart
+//purpose  : set index of a current free border of a current group to myCurPartIndex
+//=======================================================================
+
+bool SMESHGUI_SewingDlg::setCurrentPart()
+{
+  if ( !setCurrentGroup() )
+    return false;
+
+  if ( ListEdit->selectedItems().count() != 1 )
+    return false;
+
+  myCurPartIndex = ListEdit->currentRow();
+  const SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
+
+  return ( myCurPartIndex >= 0 && myCurPartIndex < aGRP.length() );
+}
+
+//=======================================================================
+//function : onSelectGroup
+//purpose  : SLOT called when selection of coincident free borders change
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onSelectGroup()
+{
+  if ( myBusy )
+    return;
+  ListEdit->clear();
+  BorderEndLine[0]->clear();
+  BorderEndLine[1]->clear();
+  for ( size_t i = 0; i < myBorderDisplayers.size(); ++i )
+    if ( myBorderDisplayers[ i ])
+      myBorderDisplayers[ i ]->Hide();
+
+  QList<QListWidgetItem*> selItems = ListCoincident->selectedItems();
+
+  RemoveGroupButton->setEnabled( selItems.count() > 0 );
+
+  onSelectBorderPartFromGroup(); // enable buttons
+
+  if ( !haveBorders() )
+    return;
+
+  SelectAllCheck->blockSignals( true );
+  if ( ListCoincident->count() != selItems.count() )
+    SelectAllCheck->setChecked( false );
+  SelectAllCheck->blockSignals( false );
+
+  if ( selItems.empty() ) // nothing selected - show all
+    for ( int i = 0; i < ListCoincident->count(); ++i )
+      showGroup( ListCoincident->item( i ));
+  else
+    for ( int i = 0; i < selItems.count(); ++i )
+      showGroup( selItems[ i ]);
+
+  if ( setCurrentGroup() ) // edit a selected group
+  {
+    const SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
+    for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
+      new QListWidgetItem( getPartText( aGRP[ iP ]), ListEdit );
+  }
+  SMESH::RepaintCurrentView();
+}
+
+//=======================================================================
+//function : onSelectAll
+//purpose  : SLOT called when Select All is checked
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onSelectAll(int isOn)
+{
+  if ( isOn )
+    ListCoincident->selectAll();
+  else
+    ListCoincident->clearSelection();
+}
+
+//=======================================================================
+//function : onSelectBorderPartFromGroup
+//purpose  : SLOT called when selection of borders in an edited group changes
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onSelectBorderPartFromGroup()
+{
+  if ( myBusy ) return;
+  BorderEndLine[0]->setText("");
+  BorderEndLine[1]->setText("");
+  MoveBorderEndsButGrp->button( MOVE_LEFT_1  )->setEnabled( false );
+  MoveBorderEndsButGrp->button( MOVE_RIGHT_1 )->setEnabled( false );
+  MoveBorderEndsButGrp->button( MOVE_LEFT_2  )->setEnabled( false );
+  MoveBorderEndsButGrp->button( MOVE_RIGHT_2 )->setEnabled( false );
+  SwapBut->setEnabled( false );
+  SetFirstButton->setEnabled( false );
+  RemoveElemButton->setEnabled ( ListEdit->count() > 2 );
+
+  if ( !setCurrentGroup() )
+    return;
+
+  if ( !myBorderDisplayers[ myCurGroupIndex ]) return;
+  myBorderDisplayers[ myCurGroupIndex ]->Hide();
+
+  QList<QListWidgetItem*> selItems = ListEdit->selectedItems();
+  bool editPart = ( setCurrentPart() );
+  for ( int i = 0; i < selItems.count(); ++i )
+    myBorderDisplayers[ myCurGroupIndex ]->ShowPart( ListEdit->row( selItems[i] ), editPart );
+
+  if ( selItems.isEmpty() )
+    myBorderDisplayers[ myCurGroupIndex ]->ShowGroup( /*wholeBorders=*/ true );
+
+  if ( editPart )
+  {
+    SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
+    SMESH::FreeBorderPart&   aPRT = aGRP[ myCurPartIndex ];
+    SMESH::FreeBorder&       aBRD = myBorders->borders[ aPRT.border ];
+
+    BorderEndLine[0]->setText( QString::number( aBRD.nodeIDs[ aPRT.node1 ]));
+    BorderEndLine[1]->setText( QString::number( aBRD.nodeIDs[ aPRT.nodeLast ]));
+    SwapBut->setEnabled( true );
+    SetFirstButton->setEnabled( myCurPartIndex > 0 );
+
+    int      size = (int) aBRD.nodeIDs.length();
+    bool isClosed = ( aBRD.nodeIDs[0] == aBRD.nodeIDs[ size-1 ]);
+    if ( !isClosed )
+    {
+      bool isFwd = ( Abs( aPRT.node2 - aPRT.node1 ) == 1 ) ? aPRT.node2 > aPRT.node1 : aPRT.node2 < aPRT.node1;
+      int dn     = ( isFwd ? +1 : -1 ) * StepSpin->value();
+      MoveBorderEndsButGrp->button( MOVE_LEFT_1  )->
+        setEnabled( 0 <= aPRT.node1-dn && aPRT.node1-dn < size );
+      MoveBorderEndsButGrp->button( MOVE_RIGHT_1 )->
+        setEnabled( 0 <= aPRT.node1+dn && aPRT.node1+dn < size );
+      MoveBorderEndsButGrp->button( MOVE_LEFT_2  )->
+        setEnabled( 0 <= aPRT.nodeLast-dn && aPRT.nodeLast-dn < size );
+      MoveBorderEndsButGrp->button( MOVE_RIGHT_2  )->
+        setEnabled( 0 <= aPRT.nodeLast+dn && aPRT.nodeLast+dn < size );
+    }
+    else
+    {
+      MoveBorderEndsButGrp->button( MOVE_LEFT_1  )->setEnabled( true );
+      MoveBorderEndsButGrp->button( MOVE_RIGHT_1 )->setEnabled( true );
+      MoveBorderEndsButGrp->button( MOVE_LEFT_2  )->setEnabled( true );
+      MoveBorderEndsButGrp->button( MOVE_RIGHT_2 )->setEnabled( true );
+    }
+  }
+  SMESH::RepaintCurrentView();
+}
+
+//=======================================================================
+//function : onGroupChange
+//purpose  : Update after modification of a current group by the user
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onGroupChange( bool partChange )
+{
+  ListCoincident->currentItem()->setText( getGroupText( myCurGroupIndex ));
+
+  const SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
+  for ( int i = 0; i < ListEdit->count(); ++i )
+    ListEdit->item( i )->setText( getPartText( aGRP[ i ]));
+
+  if ( myBorderDisplayers[ myCurGroupIndex ])
+    myBorderDisplayers[ myCurGroupIndex ]->Update();
+
+  if ( partChange )
+    onSelectBorderPartFromGroup();
+}
+
+//=======================================================================
+//function : onSetFirstClicked
+//purpose  : STOL called when |<< is clicked
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onSetFirstClicked()
+{
+  if ( !setCurrentPart() || myCurPartIndex == 0 || ListEdit->count() == 0 )
+    return;
+
+  SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
+
+  SMESH::FreeBorderPart new1st = aGRP[ myCurPartIndex ];
+  for ( ; myCurPartIndex > 0; --myCurPartIndex )
+    aGRP[ myCurPartIndex ] = aGRP[ myCurPartIndex - 1 ];
+
+  aGRP[ 0 ] = new1st;
+
+  onGroupChange();
+
+  myBusy = true;
+  ListEdit->clearSelection();
+  myBusy = false;
+  ListEdit->setCurrentItem( ListEdit->item(0) );//ListEdit->item(0)->setSelected(true);
+}
+
+//=======================================================================
+//function : onRemoveElemClicked
+//purpose  : 
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onRemoveElemClicked()
+{
+  if ( !setCurrentGroup() )
+    return;
+
+  SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
+
+  QList<QListWidgetItem*> selItems = ListEdit->selectedItems();
+  for ( int i = 0; i < selItems.count(); ++i )
+  {
+    int part = ListEdit->row( selItems[i] );
+    for ( ; part + 1 < aGRP.length(); ++part )
+      aGRP[ part ] = aGRP[ part + 1 ];
+    aGRP.length( aGRP.length() - 1 );
+    delete selItems[i];
+  }
+
+  if ( aGRP.length() == 0 )
+    onRemoveGroupClicked();
+  else
+    onGroupChange( /*partChange=*/true );
+}
+
+//=======================================================================
+//function : onMoveBorderEnd
+//purpose  : 
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onMoveBorderEnd(int button)
+{
+  if ( !setCurrentPart() )
+    return;
+
+  SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
+  SMESH::FreeBorderPart&   aPRT = aGRP[ myCurPartIndex ];
+  SMESH::FreeBorder&       aBRD = myBorders->borders[ aPRT.border ];
+  int size = (int) aBRD.nodeIDs.length();
+
+  bool isClosed = ( aBRD.nodeIDs[0] == aBRD.nodeIDs[ size-1 ]);
+  if ( isClosed ) --size;
+
+  bool isFwd = ( Abs( aPRT.node2 - aPRT.node1 ) == 1 ) ? aPRT.node2 > aPRT.node1 : aPRT.node2 < aPRT.node1;
+  int dn     = ( isFwd ? +1 : -1 ) * StepSpin->value();
+  if ( button == MOVE_LEFT_1 || button == MOVE_LEFT_2 )
+    dn *= -1;
+
+  switch ( button ) {
+  case MOVE_LEFT_1:
+  case MOVE_RIGHT_1:
+    if (( isClosed ) ||
+        ( 0 <= aPRT.node1+dn && aPRT.node1+dn < size ))
+    {
+      aPRT.node1 = ( aPRT.node1 + size + dn ) % size;
+      aPRT.node2 = ( aPRT.node2 + size + dn ) % size;
+      break;
+    }
+  case MOVE_LEFT_2:
+  case MOVE_RIGHT_2:
+    if (( isClosed ) ||
+        ( 0 <= aPRT.nodeLast+dn && aPRT.nodeLast+dn < size ))
+    {
+      aPRT.nodeLast = ( aPRT.nodeLast + size + dn ) % size;
+      break;
+    }
+  default:
+    return; // impossible to move
+  }
+  
+  onGroupChange( /*partChange=*/true );
+}
+
+//=======================================================================
+//function : onSwapClicked
+//purpose  : SLOT called when <-> is clicked
+//=======================================================================
+
+void SMESHGUI_SewingDlg::onSwapClicked()
+{
+  if ( !setCurrentPart() )
+    return;
+
+  SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
+  SMESH::FreeBorderPart&   aPRT = aGRP[ myCurPartIndex ];
+  SMESH::FreeBorder&       aBRD = myBorders->borders[ aPRT.border ];
+  int size = (int) aBRD.nodeIDs.length();
+
+  bool isClosed = ( aBRD.nodeIDs[0] == aBRD.nodeIDs[ size-1 ]);
+  if ( isClosed ) --size;
+
+  bool isFwd = ( Abs( aPRT.node2 - aPRT.node1 ) == 1 ) ? aPRT.node2 > aPRT.node1 : aPRT.node2 < aPRT.node1;
+
+  std::swap( aPRT.nodeLast, aPRT.node1 );
+
+  aPRT.node2 = ( aPRT.node1 + ( isFwd ? -1 : +1 ) + size ) % size;
+
+  onGroupChange( /*partChange=*/true );
+}
+
 //=================================================================================
 // function : ClickOnApply()
 // purpose  :
@@ -454,11 +1294,11 @@ bool SMESHGUI_SewingDlg::ClickOnApply()
 
   bool aResult = false;
 
-  if (IsValid()) {
-    bool toMerge = CheckBoxMerge->isChecked();
+  if (IsValid())
+  {
+    bool toMerge          = CheckBoxMerge->isChecked();
     bool toCreatePolygons = CheckBoxPolygons->isChecked();
     bool toCreatePolyedrs = CheckBoxPolyedrs->isChecked();
-
     try {
       SUIT_OverrideCursor aWaitCursor;
       SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
@@ -467,21 +1307,51 @@ bool SMESHGUI_SewingDlg::ClickOnApply()
       SMESH::SMESH_MeshEditor::Sew_Error anError;
 
       if (aConstructorId == 0)
-        anError = aMeshEditor->SewFreeBorders(LineEdit1->text().toLong(),
-                                              LineEdit2->text().toLong(),
-                                              LineEdit3->text().toLong(),
-                                              LineEdit4->text().toLong(),
-                                              LineEdit5->text().toLong(),
-                                              LineEdit6->text().toLong(),
-                                              toCreatePolygons,
-                                              toCreatePolyedrs);
+      {
+        if ( ModeButGrp->checkedId() == MODE_MANUAL )
+        {
+          anError = aMeshEditor->SewFreeBorders(LineEdit1->text().toLong(),
+                                                LineEdit2->text().toLong(),
+                                                LineEdit3->text().toLong(),
+                                                LineEdit4->text().toLong(),
+                                                LineEdit5->text().toLong(),
+                                                LineEdit6->text().toLong(),
+                                                toCreatePolygons,
+                                                toCreatePolyedrs);
+        }
+        else
+        {
+          int nbCoincGroups = ListCoincident->count();
+          if ( AutoSewCheck->isChecked() )
+          {
+            myBorders     = aMeshEditor->FindCoincidentFreeBorders( SpinBoxTolerance->GetValue() );
+            nbCoincGroups = myBorders->coincidentGroups.length();
+          }
+          CORBA::Short nbSewed = aMeshEditor->SewCoincidentFreeBorders( myBorders.inout(),
+                                                                        toCreatePolygons,
+                                                                        toCreatePolyedrs);
+          QString msg;
+          if ( nbCoincGroups == 0 )
+            msg = tr("NO_BORDERS_TO_SEW");
+          else if ( nbSewed < nbCoincGroups )
+            msg = tr("NOT_ALL_BORDERS_SEWED").arg( nbSewed ).arg( nbCoincGroups );
+          else
+            msg = tr("ALL_BORDERS_SEWED").arg( nbSewed );
+          SUIT_MessageBox::information( this, tr("SMESH_INFORMATION"), msg );
+
+          anError = SMESH::SMESH_MeshEditor::SEW_OK;
+        }
+      }
       else if (aConstructorId == 1)
+      {
         anError = aMeshEditor->SewConformFreeBorders(LineEdit1->text().toLong(),
                                                      LineEdit2->text().toLong(),
                                                      LineEdit3->text().toLong(),
                                                      LineEdit4->text().toLong(),
                                                      LineEdit5->text().toLong());
+      }
       else if (aConstructorId == 2)
+      {
         anError = aMeshEditor->SewBorderToSide(LineEdit1->text().toLong(),
                                                LineEdit2->text().toLong(),
                                                LineEdit3->text().toLong(),
@@ -489,6 +1359,7 @@ bool SMESHGUI_SewingDlg::ClickOnApply()
                                                LineEdit6->text().toLong(),
                                                toCreatePolygons,
                                                toCreatePolyedrs);
+      }
       else if (aConstructorId == 3) {
         QStringList aListElementsId1 = LineEdit1->text().split(" ", QString::SkipEmptyParts);
         QStringList aListElementsId2 = LineEdit4->text().split(" ", QString::SkipEmptyParts);
@@ -520,17 +1391,23 @@ bool SMESHGUI_SewingDlg::ClickOnApply()
         QString msg = tr(QString("ERROR_%1").arg(anError).toLatin1().data());
         SUIT_MessageBox::warning(this, tr("SMESH_WRN_WARNING"), msg);
       }
-    } catch (...) {
+    }
+    catch ( const SALOME::SALOME_Exception& S_ex )
+    {
+      SalomeApp_Tools::QtCatchCorbaException( S_ex );
+      return false;
     }
 
     if (aResult) {
-      Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
-
-      SALOME_ListIO aList;
-      aList.Append(anIO);
-      mySelectionMgr->setSelectedObjects(aList, false);
-      SMESH::UpdateView();
 
+      if ( myActor )
+      {
+        Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
+        SALOME_ListIO aList;
+        aList.Append(anIO);
+        mySelectionMgr->setSelectedObjects(aList, false);
+        SMESH::UpdateView();
+      }
       Init();
       ConstructorsClicked(GetConstructorId());
 
@@ -551,12 +1428,46 @@ void SMESHGUI_SewingDlg::ClickOnOk()
     reject();
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_SewingDlg::onOpenView()
+{
+  if ( mySelector ) {
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    ActivateThisDialog();
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_SewingDlg::onCloseView()
+{
+  DeactivateActiveDialog();
+  mySelector = 0;
+  myActor = 0;
+
+  for ( size_t i = 0; i < myBorderDisplayers.size(); ++i )
+  {
+    delete myBorderDisplayers[ i ];
+    myBorderDisplayers[ i ] = 0;
+  }
+  myBorderDisplayers.clear();
+}
+
 //=================================================================================
 // function : reject()
 // purpose  :
 //=================================================================================
 void SMESHGUI_SewingDlg::reject()
 {
+  restoreDisplayMode();
   //mySelectionMgr->clearSelected();
   SMESH::SetPointRepresentation(false);
   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
@@ -617,9 +1528,6 @@ void SMESHGUI_SewingDlg::onTextChange (const QString& theNewText)
   else if (send == LineEdit6)
     myOk6 = false;
 
-  buttonOk->setEnabled(false);
-  buttonApply->setEnabled(false);
-
   // hilight entered elements/nodes
   SMDS_Mesh* aMesh = 0;
 
@@ -676,7 +1584,6 @@ void SMESHGUI_SewingDlg::onTextChange (const QString& theNewText)
             isEvenOneExists = true;
       }
       
-
       mySelector->AddOrRemoveIndex(myActor->getIO(), newIndices, false);
       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
         aViewWindow->highlight( myActor->getIO(), true, true );
@@ -692,10 +1599,7 @@ void SMESHGUI_SewingDlg::onTextChange (const QString& theNewText)
     }
   }
 
-  if (IsValid()) {
-    buttonOk->setEnabled(true);
-    buttonApply->setEnabled(true);
-  }
+  UpdateButtons();
 
   myBusy = false;
 }
@@ -709,6 +1613,7 @@ void SMESHGUI_SewingDlg::SelectionIntoArgument (bool isSelectionChanged)
   if (myBusy) return;
 
   // clear
+  restoreDisplayMode();
   if (isSelectionChanged)
     myActor = 0;
 
@@ -716,13 +1621,18 @@ void SMESHGUI_SewingDlg::SelectionIntoArgument (bool isSelectionChanged)
 
   myBusy = true;
   myEditCurrentArgument->setText(aString);
+  ListCoincident->clear();
+  ListEdit->clear();
   myBusy = false;
 
+  onSelectGroup(); // erase preview
+
   if (!GroupButtons->isEnabled()) // inactive
     return;
 
   buttonOk->setEnabled(false);
   buttonApply->setEnabled(false);
+  DetectButton->setEnabled(false);
 
   // get selected mesh
   SALOME_ListIO aList;
@@ -733,21 +1643,41 @@ void SMESHGUI_SewingDlg::SelectionIntoArgument (bool isSelectionChanged)
     return;
 
   Handle(SALOME_InteractiveObject) IO = aList.First();
-  myMesh = SMESH::GetMeshByIO(IO); //@ SMESH::IObjectToInterface<SMESH::SMESH_Mesh>(IO);
+  myMesh  = SMESH::GetMeshByIO(IO);
   myActor = SMESH::FindActorByEntry(aList.First()->getEntry());
+  if (myMesh->_is_nil())
+    return;
+
+  CheckBoxPolyedrs->setEnabled( myMesh->NbVolumes() > 0 );
 
-  if (myMesh->_is_nil() || !myActor)
+  if ( myEditCurrentArgument == LineEditMesh )
+  {
+    if ( _PTR(SObject) meshSO = SMESH::FindSObject( myMesh ))
+      LineEditMesh->setText( meshSO->GetName().c_str() );
+    ListCoincident->clear();
+    if ( AutoSewCheck->isChecked() )
+    {
+      buttonOk->setEnabled(true);
+      buttonApply->setEnabled(true);
+    }
+    DetectButton->setEnabled( myMesh->NbFaces() > 0 );
+    setDisplayMode();
+    return;
+  }
+
+  if (!myActor)
     return;
 
   // get selected elements/nodes
   int aNbUnits = 0;
-
-  if (GetConstructorId() != 3 ||
-      (myEditCurrentArgument != LineEdit1 && myEditCurrentArgument != LineEdit4)) {
+  if (( GetConstructorId() != 3 ) ||
+      ( myEditCurrentArgument != LineEdit1 && myEditCurrentArgument != LineEdit4))
+  {
     aNbUnits = SMESH::GetNameOfSelectedNodes(mySelector, IO, aString);
     if (aNbUnits != 1)
       return;
-  } else {
+  }
+  else {
     aNbUnits = SMESH::GetNameOfSelectedElements(mySelector, IO, aString);
     if (aNbUnits < 1)
       return;
@@ -771,10 +1701,7 @@ void SMESHGUI_SewingDlg::SelectionIntoArgument (bool isSelectionChanged)
   else if (myEditCurrentArgument == LineEdit6)
     myOk6 = true;
 
-  if (IsValid()) {
-    buttonOk->setEnabled(true);
-    buttonApply->setEnabled(true);
-  }
+  UpdateButtons();
 }
 
 //=================================================================================
@@ -869,8 +1796,13 @@ void SMESHGUI_SewingDlg::ActivateThisDialog()
 //=================================================================================
 void SMESHGUI_SewingDlg::enterEvent (QEvent* e)
 {
-  if (!ConstructorsBox->isEnabled())
+  if (!ConstructorsBox->isEnabled()) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector) {
+      mySelector = aViewWindow->GetSelector();
+    }
     ActivateThisDialog();
+  }
 }
 
 //=================================================================================
@@ -888,9 +1820,38 @@ int SMESHGUI_SewingDlg::GetConstructorId()
 //=================================================================================
 bool SMESHGUI_SewingDlg::IsValid()
 {
+  if ( myMesh->_is_nil() )
+    return false;
+
+  if ( GetConstructorId() == 0 && ModeButGrp->checkedId() == MODE_AUTO )
+  {
+    if ( AutoSewCheck->isChecked() )
+      return true;
+
+    int nbGroups = 0;
+    if ( haveBorders() )
+      for ( int i = 0; i < ListCoincident->count(); ++i )
+      {
+        int groupIndex = ListCoincident->item(i)->data( GROUP_INDEX ).toInt();
+        nbGroups += ( !getGroupText( groupIndex ).isEmpty() );
+      }
+    return nbGroups > 0;
+  }
   return (myOk1 && myOk2 && myOk3 && myOk4 && myOk5 && myOk6);
 }
 
+//=======================================================================
+//function : UpdateButtons
+//purpose  : activate [Apply] buttons
+//=======================================================================
+
+void SMESHGUI_SewingDlg::UpdateButtons()
+{
+  bool ok = IsValid();
+  buttonOk->setEnabled( ok );
+  buttonApply->setEnabled( ok );
+}
+
 //=================================================================================
 // function : keyPressEvent()
 // purpose  :
@@ -906,3 +1867,155 @@ void SMESHGUI_SewingDlg::keyPressEvent( QKeyEvent* e )
     ClickOnHelp();
   }
 }
+
+SMESHGUI_SewingDlg::
+BorderGroupDisplayer::BorderGroupDisplayer( const SMESH::CoincidentFreeBorders& borders,
+                                            int                                 groupIndex,
+                                            QColor                              color,
+                                            SMESH::SMESH_Mesh_ptr               mesh):
+  myBorders   ( borders.borders ),
+  myGroup     ( borders.coincidentGroups[ groupIndex ]),
+  myColor     ( color ),
+  myMesh      ( mesh ),
+  myViewWindow( SMESH::GetCurrentVtkView() ),
+  myIdPreview ( myViewWindow )
+{
+  Update();
+}
+
+SMESHGUI_SewingDlg::BorderGroupDisplayer::~BorderGroupDisplayer()
+{
+  for ( size_t i = 0; i < myPartActors.size(); ++i )
+  {
+    if ( myPartActors[ i ]) {
+      myViewWindow->RemoveActor( myPartActors[i] );
+      myPartActors[i]->Delete();
+    }
+  }
+  myIdPreview.SetPointsLabeled(false);
+}
+
+void SMESHGUI_SewingDlg::BorderGroupDisplayer::Hide()
+{
+  for ( size_t i = 0; i < myPartActors.size(); ++i )
+    if ( myPartActors[ i ])
+      myPartActors[ i ]->SetVisibility(false);
+
+  myIdPreview.SetPointsLabeled(false);
+}
+
+void SMESHGUI_SewingDlg::BorderGroupDisplayer::ShowGroup( bool wholeBorders )
+{
+  std::vector<int> ids;
+  std::list<gp_XYZ> coords;
+  for ( size_t i = 0; i < myPartActors.size(); ++i )
+    if ( myPartActors[ i ])
+    {
+      myPartActors[ i ]->SetPointRepresentation( wholeBorders );
+      myPartActors[ i ]->SetVisibility( true );
+      if ( wholeBorders )
+        getPartEnds( i, ids, coords );
+    }
+  if ( wholeBorders )
+    myIdPreview.SetElemsData( ids, coords );
+  myIdPreview.SetPointsLabeled( wholeBorders, true );
+}
+
+void SMESHGUI_SewingDlg::BorderGroupDisplayer::ShowPart( int partIndex, bool toEdit )
+{
+  if ( partIndex < (int) myPartActors.size() )
+  {
+    myPartActors[partIndex]->SetVisibility(true);
+    myPartActors[partIndex]->SetPointRepresentation(toEdit);
+
+    if ( toEdit )
+    {
+      std::vector<int> ids;
+      std::list<gp_XYZ> coords;
+      getPartEnds( partIndex, ids, coords );
+
+      myIdPreview.SetElemsData( ids, coords );
+      myIdPreview.SetPointsLabeled( true, /*show=*/true );
+    }
+  }
+}
+
+void SMESHGUI_SewingDlg::BorderGroupDisplayer::getPartEnds( int                partIndex,
+                                                            std::vector<int> & ids,
+                                                            std::list<gp_XYZ>& coords)
+{
+  const SMESH::FreeBorderPart& aPART = myGroup  [ partIndex ];
+  const SMESH::FreeBorder&      aBRD = myBorders[ aPART.border ];
+
+  ids.push_back( aBRD.nodeIDs[ aPART.node1 ]);
+  ids.push_back( aBRD.nodeIDs[ aPART.nodeLast ]);
+
+  SMDS_Mesh* mesh = myPartActors[ partIndex ]->GetObject()->GetMesh();
+
+  coords.push_back( SMESH_TNodeXYZ( mesh->FindNode( aPART.node1+1 )));
+  coords.push_back( SMESH_TNodeXYZ( mesh->FindNode( aPART.nodeLast+1 )));
+}
+
+void SMESHGUI_SewingDlg::BorderGroupDisplayer::Update()
+{
+  Hide();
+  myPartActors.resize( myGroup.length(), 0 );
+
+  for ( size_t i = 0; i < myPartActors.size(); ++i )
+  {
+    TVisualObjPtr obj;
+    if ( myPartActors[ i ])
+      obj = myPartActors[ i ]->GetObject();
+    else
+      obj = TVisualObjPtr( new SMESHGUI_PreVisualObj() );
+    SMDS_Mesh* mesh = obj->GetMesh();
+    mesh->Clear();
+
+    // add nodes
+    const SMESH::FreeBorderPart& aPRT = myGroup[ i ];
+    const SMESH::FreeBorder&     aBRD = myBorders[ aPRT.border ];
+    for ( CORBA::ULong iN = 0; iN < aBRD.nodeIDs.length(); ++iN )
+    {
+      SMESH::double_array_var xyz = myMesh->GetNodeXYZ( aBRD.nodeIDs[ iN ]);
+      if ( xyz->length() == 3 )
+        mesh->AddNode( xyz[0], xyz[1], xyz[2] );
+    }
+
+    // add edges
+    bool isFwd = ( Abs( aPRT.node2 - aPRT.node1 ) == 1 ) ? aPRT.node2 > aPRT.node1 : aPRT.node2 < aPRT.node1;
+    int dn     = isFwd ? +1 : -1;
+    int size   = (int) aBRD.nodeIDs.length();
+    int n2, n1 = aPRT.node1;
+    for ( n2 = n1 + dn; ( n2 >= 0 && n2 < size ); n2 += dn )
+    {
+      mesh->AddEdgeWithID( n1+1, n2+1, mesh->NbEdges() + 1 );
+      n1 = n2;
+      if ( n2 == aPRT.nodeLast )
+        break;
+    }
+    if ( n2 % size != aPRT.nodeLast )
+    {
+      if ( n2 < 0 ) n1 = size;
+      else          n1 = 0;
+      for ( n2 = n1 + dn; ( n2 >= 0 && n2 < size ); n2 += dn )
+      {
+        mesh->AddEdgeWithID( n1+1, n2+1, mesh->NbEdges() + 1 );
+        n1 = n2;
+        if ( n2 == aPRT.nodeLast )
+          break;
+      }
+    }
+
+    if ( !myPartActors[ i ]) // TVisualObj must be filled before actor creation
+    {
+      myPartActors[ i ] = SMESH_Actor::New( obj, "", "", 1 );
+      myPartActors[ i ]->SetEdgeColor( myColor.redF(), myColor.greenF(), myColor.blueF() );
+      myPartActors[ i ]->SetLineWidth( 3 * SMESH::GetFloat("SMESH:element_width",1));
+      myPartActors[ i ]->SetNodeColor( myColor.redF(), myColor.greenF(), myColor.blueF() );
+      myPartActors[ i ]->SetMarkerStd( VTK::MT_POINT, 13 );
+      myPartActors[ i ]->SetPickable ( false );
+      myViewWindow->AddActor( myPartActors[ i ]);
+    }
+  }
+}
+
index 257852be056d37eb9d5a78f0a6d32c48ed911723..2bf5c591c128767ee73cfb2b3e35d61bd3dd841f 100644 (file)
@@ -36,6 +36,9 @@
 // IDL includes
 #include <SALOMEconfig.h>
 #include CORBA_SERVER_HEADER(SMESH_Mesh)
+#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
+
+#include <vector>
 
 class QButtonGroup;
 class QGroupBox;
@@ -48,6 +51,10 @@ class SMESHGUI;
 class SMESH_Actor;
 class SVTK_Selector;
 class LightApp_SelectionMgr;
+class SMESHGUI_SpinBox;
+class SalomeApp_IntSpinBox;
+class QListWidget;
+class QListWidgetItem;
 
 //=================================================================================
 // class    : SMESHGUI_SewingDlg
@@ -67,7 +74,8 @@ private:
   void                    keyPressEvent( QKeyEvent* );
   int                     GetConstructorId();
   bool                    IsValid();
-  
+  void                    UpdateButtons();
+
   SMESHGUI*               mySMESHGUI;              /* Current SMESHGUI object */
   LightApp_SelectionMgr*  mySelectionMgr;          /* User shape selection */
   int                     myOk1, myOk2, myOk3, myOk4, myOk5, myOk6;    
@@ -114,13 +122,67 @@ private:
   QCheckBox*              CheckBoxPolygons;
   QCheckBox*              CheckBoxPolyedrs;
 
+  QWidget*                SewFreeBordersWidget;
+  QGroupBox*              ModeGroup;
+  QButtonGroup*           ModeButGrp;
+  //QPushButton*            SelectMeshButton;
+  QLineEdit*              LineEditMesh;
+
+  SMESHGUI_SpinBox*       SpinBoxTolerance;
+  QCheckBox*              AutoSewCheck;
+
+  QWidget*                GroupCoincidentWidget;
+  QListWidget*            ListCoincident;
+  QPushButton*            DetectButton;
+  QPushButton*            RemoveGroupButton;
+  QCheckBox*              SelectAllCheck;
+
+  QListWidget*            ListEdit;
+  QButtonGroup*           MoveBorderEndsButGrp;
+  QLineEdit*              BorderEndLine[2];
+  QPushButton*            SwapBut;
+  QPushButton*            SetFirstButton;
+  QPushButton*            RemoveElemButton;
+  SalomeApp_IntSpinBox*   StepSpin;
+
   QString                 myHelpFileName;
 
-protected slots:
+
+  struct BorderGroupDisplayer;
+  std::vector< BorderGroupDisplayer* > myBorderDisplayers;
+  SMESH::CoincidentFreeBorders_var     myBorders;
+  int                                  myCurGroupIndex;
+  int                                  myCurPartIndex;
+  int                                  myStoredRepresentation;
+  unsigned int                         myStoredEntityMode;
+
+  bool                    haveBorders();
+  QString                 getGroupText( int groupIndex );
+  QString                 getPartText( const SMESH::FreeBorderPart& part );
+  void                    showGroup( QListWidgetItem* item );
+  bool                    setCurrentGroup();
+  bool                    setCurrentPart();
+  void                    onGroupChange(bool partChange=false);
+  void                    setDisplayMode();
+  void                    restoreDisplayMode();
+
+
+ protected slots:
   virtual void            reject();
 
-private slots:
+ private slots:
   void                    ConstructorsClicked( int );
+  void                    onModeChange( int );
+  void                    onAutoSew( int );
+  void                    onDetectClicked();
+  void                    onRemoveGroupClicked();
+  void                    onSelectGroup();
+  void                    onSelectAll(int);
+  void                    onSelectBorderPartFromGroup();
+  void                    onSetFirstClicked();
+  void                    onRemoveElemClicked();
+  void                    onMoveBorderEnd(int);
+  void                    onSwapClicked();
   void                    ClickOnOk();
   bool                    ClickOnApply();
   void                    ClickOnHelp();
@@ -129,6 +191,8 @@ private slots:
   void                    DeactivateActiveDialog();
   void                    ActivateThisDialog();
   void                    onTextChange( const QString& );
+  void                    onOpenView();
+  void                    onCloseView();
 };
 
 #endif // SMESHGUI_SEWINGDLG_H
index c1fafd68e9bbd227750c16881f6b961bdfb24c27..2ed7c02719bf82987fb8ede32372bde5956f88ff 100755 (executable)
@@ -223,6 +223,8 @@ void SMESHGUI_SingleEditDlg::Init()
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone()));
   connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), SLOT(onDeactivate()));
   connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()), SLOT(reject()));
+  connect(mySMESHGUI, SIGNAL(SignalActivatedViewManager()), SLOT(onOpenView()));
+  connect(mySMESHGUI, SIGNAL(SignalCloseView()),            SLOT(onCloseView()));
   connect(myEdge, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
 
   myOkBtn->setEnabled(false);
@@ -444,6 +446,29 @@ void SMESHGUI_SingleEditDlg::onDeactivate()
   setEnabled(false);
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_SingleEditDlg::onOpenView()
+{
+  if ( !mySelector ) {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    mySMESHGUI->EmitSignalDeactivateDialog();
+    setEnabled(true);
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_SingleEditDlg::onCloseView()
+{
+  onDeactivate();
+  mySelector = 0;
+}
+
 //=======================================================================
 // name    : enterEvent()
 // Purpose : Event filter
@@ -452,8 +477,12 @@ void SMESHGUI_SingleEditDlg::enterEvent (QEvent*)
 {
   if (!isEnabled()) {
     mySMESHGUI->EmitSignalDeactivateDialog();
-    if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow) {
       aViewWindow->SetSelectionMode(EdgeOfCellSelection);
+      if (!mySelector)
+        mySelector = aViewWindow->GetSelector();
+    }
     setEnabled(true);
   }
 }
index 564e0d711ec5242071d610745157e8d8c0171583..e9299eecba33b692366bef7e3c9ace8f3bdf1347 100755 (executable)
@@ -70,6 +70,11 @@ protected slots:
   void                    onSelectionDone();
   void                    onTextChange( const QString& );
 
+private slots:
+  void                    onOpenView();
+  void                    onCloseView();
+
+
 protected:
   void                    enterEvent( QEvent* );
   void                    keyPressEvent( QKeyEvent* );
index c16c64379720e3696c73971c8d5db4e42a62aa08..d752a128aa14b55783e5f57f20407b43f4966511 100644 (file)
@@ -284,7 +284,9 @@ SMESHGUI_SmoothingDlg::SMESHGUI_SmoothingDlg( SMESHGUI* theModule )
   connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
   /* to close dialog if study change */
-  connect(mySMESHGUI, SIGNAL (SignalCloseAllDialogs()), this, SLOT(reject()));
+  connect(mySMESHGUI, SIGNAL (SignalCloseAllDialogs()),      this, SLOT(reject()));
+  connect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView()));
+  connect(mySMESHGUI, SIGNAL (SignalCloseView()),            this, SLOT(onCloseView()));
   connect(LineEditElements, SIGNAL(textChanged(const QString&)),
            SLOT(onTextChange(const QString&)));
   connect(LineEditNodes, SIGNAL(textChanged(const QString&)),
@@ -404,10 +406,11 @@ bool SMESHGUI_SmoothingDlg::ClickOnApply()
 
     if (aResult) {
       SMESH::Update(myIO, SMESH::eDisplay);
+      SMESH::RepaintCurrentView();
       SMESHGUI::Modified();
-      Init();
+      //Init();
 
-      mySelectedObject = SMESH::SMESH_IDSource::_nil();
+      //mySelectedObject = SMESH::SMESH_IDSource::_nil();
     }
   }
 
@@ -444,6 +447,31 @@ void SMESHGUI_SmoothingDlg::reject()
   QDialog::reject();
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_SmoothingDlg::onOpenView()
+{
+  if ( mySelector ) {
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    ActivateThisDialog();
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_SmoothingDlg::onCloseView()
+{
+  DeactivateActiveDialog();
+  mySelector = 0;
+}
+
 //=================================================================================
 // function : ClickOnHelp()
 // purpose  :
@@ -533,7 +561,7 @@ void SMESHGUI_SmoothingDlg::onTextChange (const QString& theNewText)
 
 //=================================================================================
 // function : SelectionIntoArgument()
-// purpose  : Called when selection as changed or other case
+// purpose  : Called when selection has changed or other cases
 //=================================================================================
 void SMESHGUI_SmoothingDlg::SelectionIntoArgument()
 {
@@ -567,44 +595,44 @@ void SMESHGUI_SmoothingDlg::SelectionIntoArgument()
   SALOME_ListIO aList;
   mySelectionMgr->selectedObjects(aList);
   int nbSel = aList.Extent();
-  if (nbSel != 1)
-    return;
-
-  Handle(SALOME_InteractiveObject) IO = aList.First();
-
-  if (myEditCurrentArgument == LineEditElements) {
-    myMesh = SMESH::GetMeshByIO(IO);
-    if (myMesh->_is_nil())
-      return;
-    myIO = IO;
-    myActor = SMESH::FindActorByObject(myMesh);
-
-    if (CheckBoxMesh->isChecked()) {
-      SMESH::GetNameOfSelectedIObjects(mySelectionMgr, aString);
+  if (nbSel == 1)
+  {
+    Handle(SALOME_InteractiveObject) IO = aList.First();
 
-      SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( myIO );
-      if ( !CORBA::is_nil( obj ) )
-        mySelectedObject = obj;
-      else
+    if (myEditCurrentArgument == LineEditElements) {
+      myMesh = SMESH::GetMeshByIO(IO);
+      if (myMesh->_is_nil())
         return;
-      myNbOkElements = true;
-    } else {
-      // get indices of selected elements
-      TColStd_IndexedMapOfInteger aMapIndex;
-      mySelector->GetIndex(IO,aMapIndex);
-      myNbOkElements = aMapIndex.Extent();
+      myIO = IO;
+      myActor = SMESH::FindActorByObject(myMesh);
 
-      if (myNbOkElements < 1)
-        return;
+      if (CheckBoxMesh->isChecked()) {
+        SMESH::GetNameOfSelectedIObjects(mySelectionMgr, aString);
 
-      QStringList elements;
-      for ( int i = 0; i < myNbOkElements; ++i )
-        elements << QString::number( aMapIndex( i+1 ) );
-      aString = elements.join(" ");
+        SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( myIO );
+        if ( !CORBA::is_nil( obj ) )
+          mySelectedObject = obj;
+        else
+          return;
+        myNbOkElements = true;
+      } else {
+        // get indices of selected elements
+        TColStd_IndexedMapOfInteger aMapIndex;
+        mySelector->GetIndex(IO,aMapIndex);
+        myNbOkElements = aMapIndex.Extent();
+
+        if (myNbOkElements < 1)
+          return;
+
+        QStringList elements;
+        for ( int i = 0; i < myNbOkElements; ++i )
+          elements << QString::number( aMapIndex( i+1 ) );
+        aString = elements.join(" ");
+      }
+    } else if (myEditCurrentArgument == LineEditNodes && !myMesh->_is_nil() && myIO->isSame(IO) )
+    {
+      myNbOkNodes = SMESH::GetNameOfSelectedNodes(mySelector, IO, aString);
     }
-  } else if (myEditCurrentArgument == LineEditNodes && !myMesh->_is_nil() && myIO->isSame(IO) )
-  {
-    myNbOkNodes = SMESH::GetNameOfSelectedNodes(mySelector, IO, aString);
   }
 
   myEditCurrentArgument->setText(aString);
@@ -701,8 +729,13 @@ void SMESHGUI_SmoothingDlg::ActivateThisDialog()
 //=================================================================================
 void SMESHGUI_SmoothingDlg::enterEvent (QEvent*)
 {
-  if (!GroupConstructors->isEnabled())
+  if (!GroupConstructors->isEnabled()) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector) {
+      mySelector = aViewWindow->GetSelector();
+    }
     ActivateThisDialog();
+  }
 }
 
 //=======================================================================
index 0722395f47557fec2eb51b9e2376fdee7be6114d..875f4fa1b96417dbe103ad237e4d9618e13fd5cd 100644 (file)
@@ -125,6 +125,7 @@ private:
 protected slots:
   virtual void           reject();
 
+
 private slots:
   void                   ClickOnOk();
   bool                   ClickOnApply();
@@ -135,6 +136,8 @@ private slots:
   void                   ActivateThisDialog();
   void                   onTextChange( const QString& );
   void                   onSelectMesh( bool );
+  void                   onOpenView();
+  void                   onCloseView();
   void                   setElemFilters();
   void                   setNodeFilters();
 };
diff --git a/src/SMESHGUI/SMESHGUI_SplitBiQuad.cxx b/src/SMESHGUI/SMESHGUI_SplitBiQuad.cxx
new file mode 100644 (file)
index 0000000..a35f752
--- /dev/null
@@ -0,0 +1,255 @@
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// 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
+//
+
+// SMESH SMESHGUI : GUI for SMESH component
+// File   : SMESHGUI_SplitBiQuad.h
+// Author : Open CASCADE S.A.S.
+//
+
+#include "SMESHGUI_SplitBiQuad.h"
+
+#include "SMESHGUI.h"
+#include "SMESHGUI_Utils.h"
+#include "SMESH_LogicalFilter.hxx"
+#include "SMESH_TypeFilter.hxx"
+
+#include <SALOMEconfig.h>
+#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
+
+#include <LightApp_UpdateFlags.h>
+#include <SUIT_MessageBox.h>
+#include <SUIT_OverrideCursor.h>
+#include <SalomeApp_Tools.h>
+
+#include <QStringList>
+#include <QGridLayout>
+
+//================================================================================
+/*!
+ * \brief Dialog constructor
+ */
+//================================================================================
+
+SMESHGUI_SplitBiQuadDlg::SMESHGUI_SplitBiQuadDlg()
+  : SMESHGUI_Dialog( 0, /*modal=*/false, /*allowResize=*/true )
+{
+  setWindowTitle( tr( "CAPTION" ) );
+  setObjectPixmap( "SMESH", tr( "ICON_SELECT" ) );
+  createObject( tr( "MESH" ), mainFrame(), 0 );
+
+  QGridLayout* aLay = new QGridLayout( mainFrame() );
+  aLay->setMargin( 5 );
+  aLay->setSpacing( 5 );
+
+  aLay->addWidget( objectWg( 0,  Label ),   0, 0 );
+  //aLay->addWidget( objectWg( 0,  Btn ),     0, 1 );
+  aLay->addWidget( objectWg( 0,  Control ), 0, 1 );
+  objectWg( 0,  Btn )->hide();
+}
+
+//================================================================================
+/*!
+ * \brief Dialog destructor
+ */
+//================================================================================
+
+SMESHGUI_SplitBiQuadDlg::~SMESHGUI_SplitBiQuadDlg()
+{
+}
+
+//================================================================================
+/*!
+ * \brief SMESHGUI_SplitBiQuadOp constructor
+ */
+//================================================================================
+
+SMESHGUI_SplitBiQuadOp::SMESHGUI_SplitBiQuadOp()
+  : SMESHGUI_SelectionOp(), myDlg( 0 )
+{
+}
+
+//================================================================================
+/*!
+ * \brief SMESHGUI_SplitBiQuadOp destructor
+ */
+//================================================================================
+
+SMESHGUI_SplitBiQuadOp::~SMESHGUI_SplitBiQuadOp()
+{
+  if ( myDlg ) delete myDlg;
+}
+
+//================================================================================
+/*!
+ * \brief Gets dialog of this operation
+  * \retval LightApp_Dialog* - pointer to dialog of this operation
+*/
+//================================================================================
+
+LightApp_Dialog* SMESHGUI_SplitBiQuadOp::dlg() const
+{
+  return myDlg;
+}
+
+//================================================================================
+/*!
+ * \brief Creates dialog if necessary and shows it
+ *
+ * Virtual method redefined from base class called when operation is started creates
+ * dialog if necessary and shows it, activates selection
+ */
+//================================================================================
+
+void SMESHGUI_SplitBiQuadOp::startOperation()
+{
+  if( !myDlg )
+  {
+    myDlg = new SMESHGUI_SplitBiQuadDlg();
+  }
+  myHelpFileName = "split_biquad_to_linear_page.html";
+
+  SMESHGUI_SelectionOp::startOperation();
+
+  myDlg->activateObject( 0 );
+  myDlg->show();
+
+  selectionDone();
+}
+
+//================================================================================
+/*!
+ * \brief Updates dialog's look and feel
+ *
+ * Virtual method redefined from the base class updates dialog's look and feel
+ */
+//================================================================================
+
+// void SMESHGUI_SplitBiQuadOp::selectionDone()
+// {
+//   if ( !dlg()->isVisible() )
+//     return;
+
+//   SMESHGUI_SelectionOp::selectionDone();
+// }
+
+//================================================================================
+/*!
+ * \brief Creates selection filter
+  * \param theId - identifier of current selection widget
+  * \retval SUIT_SelectionFilter* - pointer to the created filter or null
+ *
+ * Creates selection filter in accordance with identifier of current selection widget
+ */
+//================================================================================
+
+SUIT_SelectionFilter* SMESHGUI_SplitBiQuadOp::createFilter( const int theId ) const
+{
+  if ( theId != 0 )
+    return 0;
+
+  QList<SUIT_SelectionFilter*> filters;
+  filters << new SMESH_TypeFilter( SMESH::IDSOURCE_FACE );
+  filters << new SMESH_TypeFilter( SMESH::IDSOURCE_VOLUME );
+  return new SMESH_LogicalFilter( filters,
+                                  SMESH_LogicalFilter::LO_OR,
+                                  /*takeOwnership=*/true );
+}
+
+//================================================================================
+/*!
+ * \brief Edits mesh
+ *
+ * Virtual slot redefined from the base class called when "Apply" button is clicked
+ */
+//================================================================================
+
+bool SMESHGUI_SplitBiQuadOp::onApply()
+{
+  SUIT_OverrideCursor aWaitCursor;
+
+  LightApp_Dialog::SelectedObjects selection;
+  myDlg->objectSelection( selection );
+  if ( selection.empty() || selection[0].empty() )
+  {
+    SUIT_MessageBox::warning( myDlg, tr( "SMESH_WRN_WARNING" ), tr("MESH_IS_NOT_SELECTED") );
+    return false;
+  }
+  QStringList& entries = selection[0];
+
+  SMESH::SMESH_Mesh_var mesh;
+  SMESH::ListOfIDSources_var idSource = new SMESH::ListOfIDSources();
+  idSource->length( entries.count() );
+
+  int nbObj = 0;
+  for ( int i = 0; i < entries.count() ; ++i )
+  {
+    _PTR(SObject) pObj = studyDS()->FindObjectID( entries[i].toLatin1().data() );
+    SMESH::SMESH_IDSource_var obj = SMESH::SObjectToInterface<SMESH::SMESH_IDSource>( pObj );
+    if( !CORBA::is_nil( obj ))
+    {
+      idSource[ nbObj++ ] = obj;
+      SMESH::SMESH_Mesh_var m = obj->GetMesh();
+      if ( !mesh->_is_nil() && mesh->GetId() != m->GetId() )
+      {
+        SUIT_MessageBox::warning( myDlg, tr( "SMESH_WRN_WARNING" ), tr("DIFFERENT_MESHES") );
+        return false;
+      }
+      mesh = m;
+    }
+  }
+  if ( CORBA::is_nil( mesh ))
+  {
+    SUIT_MessageBox::warning( myDlg, tr( "SMESH_WRN_WARNING" ), tr("REF_IS_NULL") );
+    return false;
+  }
+  if ( nbObj == 0 )
+  {
+    SUIT_MessageBox::warning( myDlg, tr( "SMESH_WRN_WARNING" ), tr("MESH_IS_NOT_SELECTED") );
+    return false;
+  }
+  idSource->length( nbObj );
+
+  bool aResult = false;
+
+  try
+  {
+    SMESH::SMESH_MeshEditor_var aEditor = mesh->GetMeshEditor();
+    aResult = true;
+    aEditor->SplitBiQuadraticIntoLinear( idSource );
+  }
+  catch ( const SALOME::SALOME_Exception& S_ex )
+  {
+    SalomeApp_Tools::QtCatchCorbaException( S_ex );
+    aResult = false;
+  }
+  catch ( ... )
+  {
+    aResult = false;
+  }
+  if( aResult )
+  {
+    SMESHGUI::Modified();
+    update( UF_ObjBrowser | UF_Model | UF_Viewer );
+    selectionDone();
+  }
+  return aResult;
+}
diff --git a/src/SMESHGUI/SMESHGUI_SplitBiQuad.h b/src/SMESHGUI/SMESHGUI_SplitBiQuad.h
new file mode 100644 (file)
index 0000000..13cbd71
--- /dev/null
@@ -0,0 +1,72 @@
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// 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
+//
+
+// SMESH SMESHGUI : GUI for SMESH component
+// File   : SMESHGUI_SplitBiQuad.h
+// Author : Open CASCADE S.A.S.
+//
+#ifndef SMESHGUI_SplitBiQuad_H
+#define SMESHGUI_SplitBiQuad_H
+
+#include "SMESH_SMESHGUI.hxx"
+#include "SMESHGUI_Dialog.h"
+#include "SMESHGUI_SelectionOp.h"
+
+class SMESHGUI_SplitBiQuadOp;
+
+/*!
+ * \brief Dialog performing SMESH_MeshEditor::SplitBiQuadraticIntoLinear()
+ */
+class SMESHGUI_EXPORT SMESHGUI_SplitBiQuadDlg : public SMESHGUI_Dialog
+{ 
+  Q_OBJECT       
+        
+    public:
+  SMESHGUI_SplitBiQuadDlg();
+  virtual ~SMESHGUI_SplitBiQuadDlg();
+
+  friend class SMESHGUI_SplitBiQuadOp;
+};
+
+class SMESHGUI_EXPORT SMESHGUI_SplitBiQuadOp : public SMESHGUI_SelectionOp
+{
+  Q_OBJECT
+
+public:      
+  SMESHGUI_SplitBiQuadOp();
+  virtual ~SMESHGUI_SplitBiQuadOp();
+  
+  virtual LightApp_Dialog*       dlg() const;  
+
+protected:
+  virtual void                   startOperation();
+  //virtual void                   selectionDone();
+  virtual SUIT_SelectionFilter*  createFilter( const int ) const;
+
+protected slots:
+  virtual bool                   onApply();
+
+private:
+  SMESHGUI_SplitBiQuadDlg*       myDlg;
+};
+
+#endif // SMESHGUI_SplitBiQuad_H
index 407389010f9e55ff872a5bc45231824415b6ee8f..7cc3006b8674226d1bf70d25bb1167569cc8e0b2 100644 (file)
@@ -32,7 +32,6 @@
 #include "SMESHGUI_MeshUtils.h"
 #include "SMESHGUI_IdValidator.h"
 #include "SMESHGUI_FilterDlg.h"
-#include "SMESHGUI_MeshEditPreview.h"
 
 #include <SMESH_Actor.h>
 #include <SMESH_TypeFilter.hxx>
@@ -312,7 +311,10 @@ SMESHGUI_SymmetryDlg::SMESHGUI_SymmetryDlg( SMESHGUI* theModule )
   connect(mySMESHGUI,     SIGNAL(SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()),      this, SLOT(SelectionIntoArgument()));
   /* to close dialog if study change */
-  connect(mySMESHGUI,       SIGNAL(SignalCloseAllDialogs()), this, SLOT(reject()));
+  connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()),      this, SLOT(reject()));
+  connect(mySMESHGUI, SIGNAL(SignalActivatedViewManager()), this, SLOT(onOpenView()));
+  connect(mySMESHGUI, SIGNAL(SignalCloseView()),            this, SLOT(onCloseView()));
+
   connect(LineEditElements, SIGNAL(textChanged(const QString&)),   SLOT(onTextChange(const QString&)));
   connect(CheckBoxMesh,     SIGNAL(toggled(bool)),                 SLOT(onSelectMesh(bool)));
   connect(ActionGroup,      SIGNAL(buttonClicked(int)),            SLOT(onActionClicked(int)));
@@ -355,14 +357,25 @@ void SMESHGUI_SymmetryDlg::Init (bool ResetControls)
   myObjects.clear();
   myObjectsNames.clear();
 
-  myEditCurrentArgument = 0;
-  LineEditElements->clear();
+  myEditCurrentArgument = LineEditElements;
+  LineEditElements->setFocus();
   myElementsId = "";
   myNbOkElements = 0;
 
   buttonOk->setEnabled(false);
   buttonApply->setEnabled(false);
 
+  if ( !ResetControls && !isApplyAndClose() && // make highlight move upon [Apply] (IPAL20729)
+       myActor && !myActor->getIO().IsNull() &&
+       ActionGroup->button( MOVE_ELEMS_BUTTON )->isChecked() &&
+       !CheckBoxMesh->isChecked() ) // move selected elements
+  {
+    if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+    {
+      aViewWindow->highlight( myActor->getIO(), false, false );
+      aViewWindow->highlight( myActor->getIO(), true, true );
+    }
+  }
   myActor = 0;
 
   if (ResetControls) {
@@ -377,11 +390,8 @@ void SMESHGUI_SymmetryDlg::Init (bool ResetControls)
     CheckBoxMesh->setChecked(false);
     myPreviewCheckBox->setChecked(false);
     onDisplaySimulation(false);
-
-//     MakeGroupsCheck->setChecked(false);
-//     MakeGroupsCheck->setEnabled(false);
-    onSelectMesh(false);
   }
+  onSelectMesh(CheckBoxMesh->isChecked());
 }
 
 //=================================================================================
@@ -581,8 +591,6 @@ bool SMESHGUI_SymmetryDlg::ClickOnApply()
         anApp->browseObjects( anEntryList, isApplyAndClose() );
     }
     Init(false);
-    ConstructorsClicked(GetConstructorId());
-    SelectionIntoArgument();
 
     SMESHGUI::Modified();
   }
@@ -619,6 +627,31 @@ void SMESHGUI_SymmetryDlg::reject()
   QDialog::reject();
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_SymmetryDlg::onOpenView()
+{
+  if ( mySelector ) {
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    ActivateThisDialog();
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_SymmetryDlg::onCloseView()
+{
+  DeactivateActiveDialog();
+  mySelector = 0;
+}
+
 //=================================================================================
 // function : ClickOnHelp()
 // purpose  :
@@ -968,8 +1001,13 @@ void SMESHGUI_SymmetryDlg::ActivateThisDialog()
 //=================================================================================
 void SMESHGUI_SymmetryDlg::enterEvent (QEvent*)
 {
-  if (!ConstructorsBox->isEnabled())
+  if (!ConstructorsBox->isEnabled()) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector) {
+      mySelector = aViewWindow->GetSelector();
+    }
     ActivateThisDialog();
+  }
 }
 
 //=======================================================================
index a65ed7f45f63c352e0dabfdc7efd0261f6cddfa3..1727b59f3714735491a7b3ff8c310664ac21eae2 100644 (file)
@@ -139,7 +139,7 @@ private:
 protected slots:
   virtual void           onDisplaySimulation( bool );
   virtual void           reject();
-   
+
 private slots:
   void                   ConstructorsClicked( int );
   void                   ClickOnOk();
@@ -153,6 +153,8 @@ private slots:
   void                   onSelectMesh( bool );
   void                   onVectorChanged();
   void                   onActionClicked( int );
+  void                   onOpenView();
+  void                   onCloseView();
   void                   setFilters();
 };
 
index 86d1caa508b1daf3e834fb6646c81860f843386b..32c94694a7c8947ebd02e8cfc6fea9e0275300db 100644 (file)
@@ -313,10 +313,13 @@ SMESHGUI_TranslationDlg::SMESHGUI_TranslationDlg( SMESHGUI* theModule ) :
   connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()),   this, SLOT(SelectionIntoArgument()));
   /* to close dialog if study change */
-  connect(mySMESHGUI,       SIGNAL (SignalCloseAllDialogs()), this, SLOT(reject()));
-  connect(LineEditElements, SIGNAL(textChanged(const QString&)),    SLOT(onTextChange(const QString&)));
-  connect(CheckBoxMesh,     SIGNAL(toggled(bool)),                  SLOT(onSelectMesh(bool)));
-  connect(ActionGroup,      SIGNAL(buttonClicked(int)),             SLOT(onActionClicked(int)));
+  connect(mySMESHGUI,       SIGNAL (SignalCloseAllDialogs()),      this, SLOT(reject()));
+  connect(mySMESHGUI,       SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView()));
+  connect(mySMESHGUI,       SIGNAL (SignalCloseView()),            this, SLOT(onCloseView()));
+
+  connect(LineEditElements, SIGNAL(textChanged(const QString&)),         SLOT(onTextChange(const QString&)));
+  connect(CheckBoxMesh,     SIGNAL(toggled(bool)),                       SLOT(onSelectMesh(bool)));
+  connect(ActionGroup,      SIGNAL(buttonClicked(int)),                  SLOT(onActionClicked(int)));
 
   connect(SpinBox1_1,  SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
   connect(SpinBox1_2,  SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
@@ -359,14 +362,25 @@ void SMESHGUI_TranslationDlg::Init (bool ResetControls)
   myObjectsNames.clear();
   myMeshes.clear();
 
-  myEditCurrentArgument = 0;
-  LineEditElements->clear();
+  myEditCurrentArgument = LineEditElements;
+  LineEditElements->setFocus();
   myElementsId = "";
   myNbOkElements = 0;
 
   buttonOk->setEnabled(false);
   buttonApply->setEnabled(false);
 
+  if ( !ResetControls && !isApplyAndClose() && // make highlight move upon [Apply] (IPAL20729)
+       myActor && !myActor->getIO().IsNull() &&
+       ActionGroup->button( MOVE_ELEMS_BUTTON )->isChecked() &&
+       !CheckBoxMesh->isChecked() ) // move selected elements
+  {
+    if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+    {
+      aViewWindow->highlight( myActor->getIO(), false, false );
+      aViewWindow->highlight( myActor->getIO(), true, true );
+    }
+  }
   myActor = 0;
 
   if (ResetControls) {
@@ -379,12 +393,10 @@ void SMESHGUI_TranslationDlg::Init (bool ResetControls)
 
     ActionGroup->button( MOVE_ELEMS_BUTTON )->setChecked(true);
     CheckBoxMesh->setChecked(false);
-//     MakeGroupsCheck->setChecked(false);
-//     MakeGroupsCheck->setEnabled(false);
     myPreviewCheckBox->setChecked(false);
     onDisplaySimulation(false);
-    onSelectMesh(false);
   }
+  onSelectMesh(CheckBoxMesh->isChecked());
 }
 
 //=================================================================================
@@ -590,7 +602,6 @@ bool SMESHGUI_TranslationDlg::ClickOnApply()
       
     Init(false);
     ConstructorsClicked(GetConstructorId());
-    SelectionIntoArgument();
 
     SMESHGUI::Modified();
   }
@@ -628,6 +639,31 @@ void SMESHGUI_TranslationDlg::reject()
   QDialog::reject();
 }
 
+//=================================================================================
+// function : onOpenView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_TranslationDlg::onOpenView()
+{
+  if ( mySelector ) {
+    SMESH::SetPointRepresentation(false);
+  }
+  else {
+    mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+    ActivateThisDialog();
+  }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose  :
+//=================================================================================
+void SMESHGUI_TranslationDlg::onCloseView()
+{
+  DeactivateActiveDialog();
+  mySelector = 0;
+}
+
 //=================================================================================
 // function : ClickOnHelp()
 // purpose  :
@@ -689,7 +725,6 @@ void SMESHGUI_TranslationDlg::onTextChange (const QString& theNewText)
         myNbOkElements++;
       }
     }
-
     mySelector->AddOrRemoveIndex( anIO, newIndices, false );
     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
       aViewWindow->highlight( anIO, true, true );
@@ -805,7 +840,6 @@ void SMESHGUI_TranslationDlg::SelectionIntoArgument()
       anActor = SMESH::FindActorByEntry(IO->getEntry());
     if (!anActor && !CheckBoxMesh->isChecked())
       return;
-
     aNbUnits = SMESH::GetNameOfSelectedNodes(mySelector, IO, aString);
     if (aNbUnits != 1)
       return;
@@ -933,8 +967,13 @@ void SMESHGUI_TranslationDlg::ActivateThisDialog()
 //=================================================================================
 void SMESHGUI_TranslationDlg::enterEvent (QEvent*)
 {
-  if (!ConstructorsBox->isEnabled())
+  if (!ConstructorsBox->isEnabled()) {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+    if ( aViewWindow && !mySelector) {
+      mySelector = aViewWindow->GetSelector();
+    }
     ActivateThisDialog();
+  }
 }
 
 //=======================================================================
@@ -968,7 +1007,6 @@ void SMESHGUI_TranslationDlg::onSelectMesh (bool toSelectMesh)
       aViewWindow->SetSelectionMode( CellSelection );
     LineEditElements->setReadOnly(false);
     LineEditElements->setValidator(myIdValidator);
-    onTextChange(LineEditElements->text());
     hidePreview();
   }
 
@@ -1107,12 +1145,13 @@ bool SMESHGUI_TranslationDlg::isValid()
 // function : onDisplaySimulation
 // purpose  : Show/Hide preview
 //=================================================================================
-void SMESHGUI_TranslationDlg::onDisplaySimulation( bool toDisplayPreview ) {
+void SMESHGUI_TranslationDlg::onDisplaySimulation( bool toDisplayPreview )
+{
   if (myPreviewCheckBox->isChecked() && toDisplayPreview) {
-    
+
     if (isValid() && myNbOkElements) {
       QStringList aListElementsId = myElementsId.split(" ", QString::SkipEmptyParts);
-      
+
       SMESH::long_array_var anElementsId = new SMESH::long_array;
 
       anElementsId->length(aListElementsId.count());
@@ -1148,7 +1187,7 @@ void SMESHGUI_TranslationDlg::onDisplaySimulation( bool toDisplayPreview ) {
         }
         setSimulationPreview( aMeshPreviewStruct );
       } catch (...) {
-        
+
       }
     }
     else {
index 46ff4610d9817bd2c2240ec04c1e8c7a731a5c2d..f625c61f4929ff89472c3b5fd4e20bcbd413c321 100644 (file)
@@ -146,7 +146,10 @@ private slots:
   void                   onTextChange( const QString& );
   void                   onSelectMesh( bool );
   void                   onActionClicked( int );
+  void                   onOpenView();
+  void                   onCloseView();
   void                   setFilters();
+
 };
 
 #endif // SMESHGUI_TRANSLATIONDLG_H
index 72e29e73790ac98683ffde3ec2e18135e1108170..30ddc010bbaa2248b260d8988c963399d45a9ad8 100644 (file)
@@ -305,6 +305,9 @@ namespace SMESH
         for ( ; anIter1->More(); anIter1->Next())
         {
           _PTR(SObject) aSObj1 = anIter1->Value();
+          _PTR(SObject) aSObjectRef;
+          if (aSObj1->ReferencedObject(aSObjectRef))
+            continue; // reference to an object
 
           anAttr = aBuilder->FindOrCreateAttribute(aSObj1, "AttributePixMap");
           aPixmap = anAttr;
@@ -322,7 +325,7 @@ namespace SMESH
             const bool isGroupOnFilter = !gof->_is_nil();
 
             bool isEmpty = false;
-            if ( !isGroupOnFilter ) // GetTypes() can be very long on isGroupOnFilter!
+            if ( !isGroupOnFilter ) // GetTypes() can be very long on GroupOnFilter!
             {
               SMESH::array_of_ElementType_var elemTypes = idSrc->GetTypes();
               isEmpty = ( elemTypes->length() == 0 );
index ead04a8829bdec481b0af84a52acb91ced8dcee8..a0c988e6c11c36ef49c160a5ad539f8f33255856 100644 (file)
             <source>ICON_DLG_BIQUADRATIC_QUADRANGLE</source>
             <translation>mesh_biquad_quadrangle.png</translation>
         </message>
+        <message>
+            <source>ICON_DLG_QUADRATIC_POLYGON</source>
+            <translation>mesh_quad_polygon.png</translation>
+        </message>
         <message>
             <source>ICON_DLG_QUADRATIC_TETRAHEDRON</source>
             <translation>mesh_quad_tetrahedron.png</translation>
             <source>ICON_SPLIT_TO_TETRA</source>
             <translation>split_into_tetra.png</translation>
         </message>
+        <message>
+            <source>ICON_SPLIT_BIQUAD</source>
+            <translation>split_biquad.png</translation>
+        </message>
        <message>
             <source>ICON_MEASURE_LENGTH</source>
             <translation>mesh_measure_length.png</translation>
index 28302f1b426652f5676bdd01ce91270b82e22bd8..a235b9cc9dc8cac5118d807d583cb4f9e970029b 100644 (file)
         <source>MEN_POLYGON</source>
         <translation>Polygon</translation>
     </message>
+    <message>
+        <source>MEN_QUADRATIC_POLYGON</source>
+        <translation>Quadratic Polygon</translation>
+    </message>
     <message>
         <source>MEN_POLYHEDRON</source>
         <translation>Polyhedron</translation>
         <source>STB_SPLIT_TO_TETRA</source>
         <translation>Split Volumes</translation>
     </message>
+    <message>
+        <source>MEN_SPLIT_BIQUAD</source>
+        <translation>Split bi-quadratic into linear</translation>
+    </message>
+    <message>
+        <source>TOP_SPLIT_BIQUAD</source>
+        <translation>Split bi-quadratic into linear</translation>
+    </message>
+    <message>
+        <source>STB_SPLIT_BIQUAD</source>
+        <translation>Split bi-quadratic into linear</translation>
+    </message>
     <message>
         <source>MESHERS_FILE_CANT_OPEN</source>
         <translation>Can not open resource file</translation>
@@ -1127,8 +1143,13 @@ Please, select a mesh and try again</translation>
 Please enter a name of new group to be created or choose an existing one.</translation>
     </message>
     <message>
-        <source>MESH_STANDALONE_GRP_CHOSEN</source>
+        <source>MESH_GEOM_GRP_CHOSEN</source>
         <translation>Group on geometry is chosen: %1.
+Do you want to convert it to the standalone group?</translation>
+    </message>
+    <message>
+        <source>MESH_FILTER_GRP_CHOSEN</source>
+        <translation>Group on filter is chosen: %1.
 Do you want to convert it to the standalone group?</translation>
     </message>
     <message>
@@ -1225,6 +1246,14 @@ Please enter correct values and try again</translation>
         <source>SMESH_ADD_POLYGON_TITLE</source>
         <translation>Add Polygon</translation>
     </message>
+    <message>
+        <source>SMESH_ADD_QUADRATIC_POLYGON</source>
+        <translation>Add Quadratic polygon</translation>
+    </message>
+    <message>
+        <source>SMESH_ADD_QUADRATIC_POLYGON_TITLE</source>
+        <translation>Add Quadratic Polygon</translation>
+    </message>
     <message>
         <source>SMESH_ADD_PENTA</source>
         <translation>Add pentahedron</translation>
@@ -1856,6 +1885,10 @@ Check algorithm documentation for supported geometry</translation>
         <source>SMESH_HYP_9</source>
         <translation>Such dimention hypothesis is already assigned to the shape</translation>
     </message>
+    <message>
+        <source>SMESH_ID_DIAGONAL</source>
+        <translation>Edges IDs</translation>
+    </message>
     <message>
         <source>SMESH_ID_EDGES</source>
         <translation>Edge IDs</translation>
@@ -3224,6 +3257,10 @@ Use Display Entity menu command to show them.
         <source>STB_POLYGON</source>
         <translation>Polygon</translation>
     </message>
+    <message>
+        <source>STB_QUADRATIC_POLYGON</source>
+        <translation>Quadratic Polygon</translation>
+    </message>
     <message>
         <source>STB_POLYHEDRON</source>
         <translation>Polyhedron</translation>
@@ -3300,6 +3337,10 @@ Use Display Entity menu command to show them.
         <source>STB_SHOW_DISTRIBUTION</source>
         <translation>Show Distribution</translation>
     </message>
+    <message>
+        <source>STB_SHOW_SCALAR_BAR</source>
+        <translation>Show Scalar bar</translation>
+    </message>
     <message>
         <source>STB_REVOLUTION</source>
         <translation>Revolution</translation>
@@ -3336,10 +3377,6 @@ Use Display Entity menu command to show them.
         <source>STB_SHOW</source>
         <translation>Show</translation>
     </message>
-    <message>
-        <source>STB_SHOW_SCALAR_BAR</source>
-        <translation>Show Scalar Bar</translation>
-    </message>
     <message>
         <source>STB_SHRINK</source>
         <translation>Shrink</translation>
@@ -3880,6 +3917,10 @@ Use Display Entity menu command to show them.
         <source>TOP_POLYGON</source>
         <translation>Polygon</translation>
     </message>
+    <message>
+        <source>TOP_QUADRATIC_POLYGON</source>
+        <translation>Quadratic Polygon</translation>
+    </message>
     <message>
         <source>TOP_POLYHEDRON</source>
         <translation>Polyhedron</translation>
@@ -4861,9 +4902,7 @@ Please, create VTK viewer and try again</translation>
     <name>SMESHGUI_PrecomputeOp</name>
     <message>
         <source>CLEAR_SUBMESH_QUESTION</source>
-        <translation>Temporary sub-meshes on the selected geometry
-were created during preview operation.
-Do you want to remove all these sub-meshes?</translation>
+        <translation>Do you want to remove mesh entities generated during preview operation?</translation>
     </message>
     <message>
         <source>SMESH_WRN_NOTHING_PREVIEW</source>
@@ -4875,6 +4914,33 @@ Do you want to remove all these sub-meshes?</translation>
 Do you want to restore original sub-mesh priority?</translation>
     </message>
 </context>
+<context>
+    <name>SMESHGUI_SplitBiQuadDlg</name>
+    <message>
+        <source>CAPTION</source>
+        <translation>Split bi-quadratic into linear</translation>
+    </message>
+    <message>
+        <source>MESH</source>
+        <translation>Mesh, Group or Sub-mesh</translation>
+    </message>
+</context>
+<context>
+    <name>SMESHGUI_SplitBiQuadOp</name>
+    <message>
+        <source>MESH_IS_NOT_SELECTED</source>
+        <translation>No object to split is selected.
+Please specify it and try again</translation>
+    </message>
+    <message>
+        <source>REF_IS_NULL</source>
+        <translation>No valid mesh object selected</translation>
+    </message>
+    <message>
+        <source>DIFFERENT_MESHES</source>
+        <translation>Selected objects belong to different meshes</translation>
+    </message>
+</context>
 <context>
     <name>SMESHGUI_ConvToQuadDlg</name>
     <message>
@@ -5056,8 +5122,12 @@ Please select a group and try again</translation>
         <translation>Detect</translation>
     </message>
     <message>
-        <source>EDIT_SELECTED_GROUP</source>
-        <translation>Edit selected group</translation>
+        <source>EDIT_SELECTED_NODE_GROUP</source>
+        <translation>Edit selected group of coincident nodes</translation>
+    </message>
+    <message>
+        <source>EDIT_SELECTED_ELEM_GROUP</source>
+        <translation>Edit selected group of coincident elements</translation>
     </message>
     <message>
         <source>SELECT_ALL</source>
@@ -5073,7 +5143,23 @@ Please select a group and try again</translation>
     </message>
     <message>
         <source>EXCLUDE_GROUPS</source>
-        <translation>Exclude Groups</translation>
+        <translation>Exclude groups from detection</translation>
+    </message>
+    <message>
+        <source>SEPARATE_CORNERS_AND_MEDIUM</source>
+        <translation>No merge of corner and medium nodes of quadratic cells</translation>
+    </message>
+    <message>
+        <source>KEEP_NODES</source>
+        <translation>Nodes to keep during the merge</translation>
+    </message>
+    <message>
+        <source>GROUP_SUBMESH</source>
+        <translation>Groups and sub-meshes</translation>
+    </message>
+    <message>
+        <source>SELECT</source>
+        <translation>Select: </translation>
     </message>
 </context>
 <context>
@@ -5227,7 +5313,7 @@ Please select valid object and try again</translation>
     </message>
     <message>
         <source>SHAPE_IS_NOT_A_CYLINDER</source>
-        <translation>&quot;%1&quot; is not a cylinderical face
+        <translation>&quot;%1&quot; is not a cylindrical face
 Please select a cylindrical face and try again</translation>
     </message>
     <message>
@@ -5654,7 +5740,7 @@ Please enter correct value and try again</translation>
     </message>
     <message>
         <source>ELEMENTS</source>
-        <translation>Elements</translation>
+        <translation>All</translation>
     </message>
     <message>
         <source>ENTITY_TYPE</source>
@@ -6581,6 +6667,42 @@ It is impossible to read point coordinates from file</translation>
         <source>SIDE_2</source>
         <translation>Side 2</translation>
     </message>
+    <message>
+        <source>AUTO_SEWING</source>
+        <translation>Auto Sewing</translation>
+    </message>
+    <message>
+        <source>COINCIDENT_FREE_BORDERS</source>
+        <translation>Coincident Free Borders</translation>
+    </message>
+    <message>
+        <source>DETECT</source>
+        <translation>Detect</translation>
+    </message>
+    <message>
+        <source>SELECT_ALL</source>
+        <translation>Select all</translation>
+    </message>
+    <message>
+        <source>EDIT_SELECTED_GROUP</source>
+        <translation>Edit Selected Group</translation>
+    </message>
+    <message>
+        <source>STEP</source>
+        <translation>Step</translation>
+    </message>
+    <message>
+        <source>NO_BORDERS_TO_SEW</source>
+        <translation>No free borders to sew found</translation>
+    </message>
+    <message>
+        <source>NOT_ALL_BORDERS_SEWED</source>
+        <translation>%1 of %2 groups of borders sewed</translation>
+    </message>
+    <message>
+        <source>ALL_BORDERS_SEWED</source>
+        <translation>%1 group(s) of borders sewed</translation>
+    </message>
 </context>
 <context>
     <name>SMESHGUI_ShapeByMeshDlg</name>
index 7636e748dea3676b31d673e318f96e1ea77fcda6..69a4022fb0ac4c39418f2aa36006d030769665ef 100755 (executable)
         <source>MEN_POLYGON</source>
         <translation>Polygone</translation>
     </message>
+    <message>
+        <source>MEN_QUADRATIC_POLYGON</source>
+        <translation>Polygone quadratique</translation>
+    </message>
     <message>
         <source>MEN_POLYHEDRON</source>
         <translation>Polyèdre</translation>
         <source>STB_SPLIT_TO_TETRA</source>
         <translation>Eclater en tétraèdres</translation>
     </message>
+    <message>
+        <source>MEN_SPLIT_BIQUAD</source>
+        <translation>Eclater les éléments bi-quadratiques en éléments linéaires</translation>
+    </message>
+    <message>
+        <source>TOP_SPLIT_BIQUAD</source>
+        <translation>Eclater les éléments bi-quadratiques en éléments linéaires</translation>
+    </message>
+    <message>
+        <source>STB_SPLIT_BIQUAD</source>
+        <translation>Eclater les éléments bi-quadratiques en éléments linéaire</translation>
+    </message>
     <message>
         <source>MESHERS_FILE_CANT_OPEN</source>
         <translation>Impossible d&apos;ouvrir le fichier de ressource</translation>
@@ -1127,8 +1143,13 @@ Choisissez un maillage et essayez de nouveau</translation>
 Indiquez le nom d&apos;un nouveau groupe à créer ou choisissez un groupe existant.</translation>
     </message>
     <message>
-        <source>MESH_STANDALONE_GRP_CHOSEN</source>
+        <source>MESH_GEOM_GRP_CHOSEN</source>
         <translation>Un groupe lié à la géométrie est choisi: %1.
+Voulez-vous le convertir en un groupe autonome ?</translation>
+    </message>
+    <message>
+        <source>MESH_FILTER_GRP_CHOSEN</source>
+        <translation>Un groupe lié à un filtre est choisi: %1.
 Voulez-vous le convertir en un groupe autonome ?</translation>
     </message>
     <message>
@@ -1225,6 +1246,14 @@ Merci de les corriger, puis essayez de nouveau</translation>
         <source>SMESH_ADD_POLYGON_TITLE</source>
         <translation>Ajouter un polygone</translation>
     </message>
+    <message>
+        <source>SMESH_ADD_QUADRATIC_POLYGON</source>
+        <translation>Ajouter un polygone quadratique</translation>
+    </message>
+    <message>
+        <source>SMESH_ADD_QUADRATIC_POLYGON_TITLE</source>
+        <translation>Ajouter un polygone quadratique</translation>
+    </message>
     <message>
         <source>SMESH_ADD_PENTA</source>
         <translation>Ajouter un pentaèdre</translation>
@@ -3229,6 +3258,10 @@ Utilisez le menu &quot;Visualiser une entité&quot; pour les afficher.
         <source>STB_POLYGON</source>
         <translation>Polygone</translation>
     </message>
+    <message>
+        <source>STB_QUADRATIC_POLYGON</source>
+        <translation>Polygone quadratique</translation>
+    </message>
     <message>
         <source>STB_POLYHEDRON</source>
         <translation>Polyèdre</translation>
@@ -3885,6 +3918,10 @@ Utilisez le menu &quot;Visualiser une entité&quot; pour les afficher.
         <source>TOP_POLYGON</source>
         <translation>Polygone</translation>
     </message>
+    <message>
+        <source>TOP_QUADRATIC_POLYGON</source>
+        <translation>Polygone quadratique</translation>
+    </message>
     <message>
         <source>TOP_POLYHEDRON</source>
         <translation>Polyèdre</translation>
@@ -4880,6 +4917,33 @@ Voulez-vous supprimer toutes ces sous-maillages ?</translation>
 Voulez-vous restaurer la priorité initiale ?</translation>
     </message>
 </context>
+<context>
+    <name>SMESHGUI_SplitBiQuadDlg</name>
+    <message>
+        <source>CAPTION</source>
+        <translation>Eclater les éléments bi-quadratiques en éléments linéaires</translation>
+    </message>
+    <message>
+        <source>MESH</source>
+        <translation>Maillage, groupe ou sous-maillage</translation>
+    </message>
+</context>
+<context>
+    <name>SMESHGUI_SplitBiQuadOp</name>
+    <message>
+        <source>MESH_IS_NOT_SELECTED</source>
+        <translation>Pas d'éléments à éclater.
+Sélectionner des éléments et essayer encore</translation>
+    </message>
+    <message>
+        <source>REF_IS_NULL</source>
+        <translation>Aucun maillage valide n'a été sélectionné</translation>
+    </message>
+    <message>
+        <source>DIFFERENT_MESHES</source>
+        <translation>Les éléments sélectionnés appartiennent à différents maillages</translation>
+    </message>
+</context>
 <context>
     <name>SMESHGUI_ConvToQuadDlg</name>
     <message>
@@ -5061,8 +5125,12 @@ Choisissez un groupe et essayez de nouveau</translation>
         <translation>Détecter</translation>
     </message>
     <message>
-        <source>EDIT_SELECTED_GROUP</source>
-        <translation>Editer le groupe sélectionné</translation>
+        <source>EDIT_SELECTED_NODE_GROUP</source>
+        <translation>Editer le groupe sélectionné de noeuds coïncidents</translation>
+    </message>
+    <message>
+        <source>EDIT_SELECTED_ELEM_GROUP</source>
+        <translation>Editer le groupe sélectionné d'éléments coïncidents</translation>
     </message>
     <message>
         <source>SELECT_ALL</source>
@@ -5078,7 +5146,23 @@ Choisissez un groupe et essayez de nouveau</translation>
     </message>
     <message>
         <source>EXCLUDE_GROUPS</source>
-        <translation>Exclure les groupes</translation>
+        <translation>Exclure les groupes de la détection</translation>
+    </message>
+    <message>
+        <source>SEPARATE_CORNERS_AND_MEDIUM</source>
+        <translation>Pas de fusion du coin et des noeuds moyens des cellules quadratiques</translation>
+    </message>
+    <message>
+        <source>KEEP_NODES</source>
+        <translation>Les noeuds à conserver pendant la fusion</translation>
+    </message>
+    <message>
+        <source>GROUP_SUBMESH</source>
+        <translation>Groupes et sous-maillages</translation>
+    </message>
+    <message>
+        <source>SELECT</source>
+        <translation>Selectionner: </translation>
     </message>
 </context>
 <context>
@@ -6586,6 +6670,42 @@ Il y a trop peu de points dans le fichier </translation>
         <source>SIDE_2</source>
         <translation>Bord 2</translation>
     </message>
+    <message>
+        <source>AUTO_SEWING</source>
+        <translation>Couture automatique</translation>
+    </message>
+    <message>
+        <source>COINCIDENT_FREE_BORDERS</source>
+        <translation>Frontières libres coïncidentes</translation>
+    </message>
+    <message>
+        <source>DETECT</source>
+        <translation>Détecter</translation>
+    </message>
+    <message>
+        <source>SELECT_ALL</source>
+        <translation>Sélectionner tous</translation>
+    </message>
+    <message>
+        <source>EDIT_SELECTED_GROUP</source>
+        <translation>Editer le groupe sélectionné</translation>
+    </message>
+    <message>
+        <source>STEP</source>
+        <translation>Pas</translation>
+    </message>
+    <message>
+        <source>NO_BORDERS_TO_SEW</source>
+        <translation>Pas de frontière libre à coudre</translation>
+    </message>
+    <message>
+        <source>NOT_ALL_BORDERS_SEWED</source>
+        <translation>%1 groupes sur %2 de frontières cousus</translation>
+    </message>
+    <message>
+        <source>ALL_BORDERS_SEWED</source>
+        <translation>%1 groupe(s) de frontières cousu(s)</translation>
+    </message>
 </context>
 <context>
     <name>SMESHGUI_ShapeByMeshDlg</name>
index 6b80b26b65ad3df29663632f3fc2868b0b3c21af..6b71493f4143573c303beb5919e265fc70d90bd7 100644 (file)
       <source>MEN_POLYGON</source>
       <translation>多角形</translation>
     </message>
+    <message>
+      <source>MEN_QUADRATIC_POLYGON</source>
+      <translation>2次ポリゴン</translation>
+    </message>
     <message>
       <source>MEN_POLYHEDRON</source>
       <translation>多面体</translation>
       <source>STB_SPLIT_TO_TETRA</source>
       <translation>四面体を爆発します。</translation>
     </message>
+    <message>
+      <source>MEN_SPLIT_BIQUAD</source>
+      <translation>線形に2次分割</translation>
+    </message>
+    <message>
+      <source>TOP_SPLIT_BIQUAD</source>
+      <translation>線形に2次分割</translation>
+    </message>
+    <message>
+      <source>STB_SPLIT_BIQUAD</source>
+      <translation>線形に2次分割</translation>
+    </message>
     <message>
       <source>MESHERS_FILE_CANT_OPEN</source>
       <translation>リソース ファイルを開くことができません。</translation>
       <translation>グループ名は表示されません。作成または既存のグループを選択して新しいグループの名前を指定します。</translation>
     </message>
     <message>
-      <source>MESH_STANDALONE_GRP_CHOSEN</source>
-      <translation>ジオメトリにリンクされているグループが選択されている: %1。スタンドアロン アレイに変換しますか。</translation>
+      <source>MESH_GEOM_GRP_CHOSEN</source>
+      <translation>ジオメトリグループは次のように選択されています: %1 それをスタンドアロングループに変換したいですか?</translation>
+    </message>
+    <message>
+      <source>MESH_FILTER_GRP_CHOSEN</source>
+      <translation>フィルタ上のグループは次のように選択されています: %1 それをスタンドアロングループに変換したいですか?</translation>
     </message>
     <message>
       <source>NODE_ID</source>
       <source>SMESH_ADD_POLYGON_TITLE</source>
       <translation>多角形を追加します。</translation>
     </message>
+    <message>
+      <source>SMESH_ADD_QUADRATIC_POLYGON</source>
+      <translation>2次ポリゴンの追加</translation>
+    </message>
+    <message>
+      <source>SMESH_ADD_QUADRATIC_POLYGON_TITLE</source>
+      <translation>2次ポリゴンの追加</translation>
+    </message>
     <message>
       <source>SMESH_ADD_PENTA</source>
       <translation>くさびを追加します。</translation>
       <source>STB_POLYGON</source>
       <translation>多角形</translation>
     </message>
+    <message>
+      <source>STB_QUADRATIC_POLYGON</source>
+      <translation>2次ポリゴン</translation>
+    </message>
     <message>
       <source>STB_POLYHEDRON</source>
       <translation>多面体</translation>
       <source>TOP_POLYGON</source>
       <translation>多角形</translation>
     </message>
+    <message>
+      <source>TOP_QUADRATIC_POLYGON</source>
+      <translation>2次ポリゴン</translation>
+    </message>
     <message>
       <source>TOP_POLYHEDRON</source>
       <translation>多面体</translation>
       <translation>サブメッシュの優先順位は、プレビュー時に変更されました。初期の優先度を復元しますか。</translation>
     </message>
   </context>
+  <context>
+    <name>SMESHGUI_SplitBiQuadDlg</name>
+    <message>
+      <source>CAPTION</source>
+      <translation>線形に2次分割</translation>
+    </message>
+    <message>
+      <source>MESH</source>
+      <translation>メッシュ、グループ、あるいはサブメッシュ</translation>
+    </message>
+  </context>
+  <context>
+    <name>SMESHGUI_SplitBiQuadOp</name>
+    <message>
+      <source>MESH_IS_NOT_SELECTED</source>
+      <translation>分割のためのオブジェクトは選択されていません。オブジェクトを指定してから再試行してください。</translation>
+    </message>
+    <message>
+      <source>REF_IS_NULL</source>
+      <translation>有効なメッシュオブジェクトは選択されていません</translation>
+    </message>
+    <message>
+      <source>DIFFERENT_MESHES</source>
+      <translation>異なるメッシュに属したオブジェクトが選択されています</translation>
+    </message>
+  </context>
   <context>
     <name>SMESHGUI_ConvToQuadDlg</name>
     <message>
       <source>EXCLUDE_GROUPS</source>
       <translation>グループを除外</translation>
     </message>
+    <message>
+      <source>SEPARATE_CORNERS_AND_MEDIUM</source>
+      <translation>2次セルのコーナ節点と中間節点をマージできません</translation>
+    </message>
+    <message>
+      <source>KEEP_NODES</source>
+      <translation>維持節点</translation>
+    </message>
+    <message>
+      <source>GROUP_SUBMESH</source>
+      <translation>グループとサブメッシュ</translation>
+    </message>
+    <message>
+      <source>SELECT</source>
+      <translation>Select: </translation>
+    </message>
   </context>
   <context>
     <name>SMESHGUI_ExtrusionAlongPathDlg</name>
     </message>
     <message>
       <source>ID</source>
-      <translation type="unfinished">ID</translation>
+      <translation>ID</translation>
     </message>
     <message>
       <source>INSERT</source>
       <source>SIDE_2</source>
       <translation>エッジ 2</translation>
     </message>
+    <message>
+      <source>AUTO_SEWING</source>
+      <translation>自動縫合</translation>
+    </message>
+    <message>
+      <source>COINCIDENT_FREE_BORDERS</source>
+      <translation>一致フリー境界</translation>
+    </message>
+    <message>
+      <source>DETECT</source>
+      <translation>検出</translation>
+    </message>
+    <message>
+      <source>SELECT_ALL</source>
+      <translation>すべてを選択</translation>
+    </message>
+    <message>
+      <source>EDIT_SELECTED_GROUP</source>
+      <translation>選択グループを編集</translation>
+    </message>
+    <message>
+      <source>STEP</source>
+      <translation>Step</translation>
+    </message>
+    <message>
+      <source>NO_BORDERS_TO_SEW</source>
+      <translation>縫合できるフリー境界はみつかりません</translation>
+    </message>
+    <message>
+      <source>NOT_ALL_BORDERS_SEWED</source>
+      <translation>境界の %2 グループの%1を縫合しました</translation>
+    </message>
+    <message>
+      <source>ALL_BORDERS_SEWED</source>
+      <translation>境界の %1 グループを縫合しました。</translation>
+    </message>
   </context>
   <context>
     <name>SMESHGUI_ShapeByMeshDlg</name>
index 8bafe47f4e7ec1808a0ab9bf40b510faf15e0a52..c79b29f2872ab9492ea6d30d827fb7586e42e349 100644 (file)
@@ -79,6 +79,7 @@ SET(SMESHUtils_SOURCES
   SMESH_File.cxx
   SMESH_MeshAlgos.cxx
   SMESH_MAT2d.cxx
+  SMESH_FreeBorders.cxx
 )
 
 # --- rules ---
index 4f7bc42cfe03790bece2f80f7625f8512a720a4a..b87928995d638f8bed1cdc61e8381c557b7cf492 100644 (file)
@@ -1799,8 +1799,11 @@ bool SMESH_Block::FindBlockShapes(const TopoDS_Shell&         theShell,
     for (  ; eIt.More(); eIt.Next() ) {
       const TopoDS_Edge& e = TopoDS::Edge( eIt.Value() );
       TopoDS_Vertex v = TopExp::FirstVertex( e );
-      if ( v.IsSame( V000 ))
+      if ( v.IsSame( V000 )) {
         v = TopExp::LastVertex( e );
+        if ( v.IsSame( V000 ))
+          return false;
+      }
       val = dir001 * gp_Vec( p000, BRep_Tool::Pnt( v )).Normalized();
       if ( val > maxVal ) {
         V001 = v;
diff --git a/src/SMESHUtils/SMESH_FreeBorders.cxx b/src/SMESHUtils/SMESH_FreeBorders.cxx
new file mode 100644 (file)
index 0000000..6d180f8
--- /dev/null
@@ -0,0 +1,751 @@
+// Copyright (C) 2007-2015  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
+//
+// File      : SMESH_FreeBorders.cxx
+// Created   : Tue Sep  8 17:08:39 2015
+// Author    : Edward AGAPOV (eap)
+
+//================================================================================
+// Implementation of SMESH_MeshAlgos::FindCoincidentFreeBorders()
+//================================================================================
+
+#include "SMESH_MeshAlgos.hxx"
+
+#include "SMDS_LinearEdge.hxx"
+#include "SMDS_Mesh.hxx"
+#include "SMDS_SetIterator.hxx"
+
+#include <algorithm>
+#include <limits>
+#include <set>
+#include <vector>
+
+#include <NCollection_DataMap.hxx>
+#include <gp_Pnt.hxx>
+
+using namespace SMESH_MeshAlgos;
+
+namespace
+{
+  struct BEdge;
+
+  /*!
+   * \brief Node on a free border
+   */
+  struct BNode : public SMESH_TNodeXYZ
+  {
+    mutable std::vector< BEdge* > myLinkedEdges;
+    mutable std::vector< std::pair < BEdge*, double > > myCloseEdges; // edge & U
+
+    BNode(const SMDS_MeshNode * node): SMESH_TNodeXYZ( node ) {}
+    const SMDS_MeshNode * Node() const { return _node; }
+    void   AddLinked( BEdge* e ) const;
+    void   AddClose ( const BEdge* e, double u ) const;
+    BEdge* GetCloseEdge( size_t i ) const { return myCloseEdges[i].first; }
+    double GetCloseU( size_t i ) const { return myCloseEdges[i].second; }
+    BEdge* GetCloseEdgeOfBorder( int borderID, double * u = 0 ) const;
+    bool   HasCloseEdgeWithNode( const BNode* n ) const;
+    bool   IsCloseEdge( const BEdge*, double * u = 0 ) const;
+    bool operator<(const BNode& other) const { return Node()->GetID() < other.Node()->GetID(); }
+  };
+  /*!
+   * \brief Edge of a free border
+   */
+  struct BEdge : public SMDS_LinearEdge
+  {
+    const BNode*            myBNode1;
+    const BNode*            myBNode2;
+    int                     myBorderID;
+    int                     myID; // within a border
+    BEdge*                  myPrev;
+    BEdge*                  myNext;
+    const SMDS_MeshElement* myFace;
+    std::set< int >         myCloseBorders;
+    int                     myInGroup;
+
+    BEdge():SMDS_LinearEdge( 0, 0 ), myBorderID(-1), myID(-1), myPrev(0), myNext(0), myInGroup(-1) {}
+
+    void Set( const BNode *           node1,
+              const BNode *           node2,
+              const SMDS_MeshElement* face,
+              const int               ID)
+    {
+      myBNode1   = node1;
+      myBNode2   = node2;
+      myNodes[0] = node1->Node();
+      myNodes[1] = node2->Node();
+      myFace     = face;
+      setId( ID ); // mesh element ID
+    }
+    bool IsInGroup() const
+    {
+      return myInGroup >= 0;
+    }
+    bool Contains( const BNode* n ) const
+    {
+      return ( n == myBNode1 || n == myBNode2 );
+    }
+    void AddLinked( BEdge* e )
+    {
+      if ( e->Contains( myBNode1 )) myPrev = e;
+      else                          myNext = e;
+    }
+    void RemoveLinked( BEdge* e )
+    {
+      if ( myPrev == e ) myPrev = 0;
+      if ( myNext == e ) myNext = 0;
+    }
+    void Reverse()
+    {
+      std::swap( myBNode1, myBNode2 );
+      myNodes[0] = myBNode1->Node();
+      myNodes[1] = myBNode2->Node();
+    }
+    void Orient()
+    {
+      if (( myPrev && !myPrev->Contains( myBNode1 )) ||
+          ( myNext && !myNext->Contains( myBNode2 )))
+        std::swap( myPrev, myNext );
+      if ( myPrev && myPrev->myBNode2 != myBNode1 ) myPrev->Reverse();
+      if ( myNext && myNext->myBNode1 != myBNode2 ) myNext->Reverse();
+    }
+    void SetID( int id )
+    {
+      if ( myID < 0 )
+      {
+        myID = id;
+        if ( myNext )
+          myNext->SetID( id + 1 );
+      }
+    }
+    bool IsOut( const gp_XYZ& point, const double tol, double& u ) const
+    {
+      gp_XYZ  me = *myBNode2 - *myBNode1;
+      gp_XYZ n1p = point     - *myBNode1;
+      u = ( me * n1p ) / me.SquareModulus(); // param [0,1] on this
+      if ( u < 0. ) return ( n1p.SquareModulus() > tol * tol );
+      if ( u > 1. ) return ( ( point - *myBNode2 ).SquareModulus() > tol * tol );
+
+      gp_XYZ  proj = ( 1. - u ) * *myBNode1 + u * *myBNode2; // projection of the point on this
+      double dist2 = ( point - proj ).SquareModulus();
+      return ( dist2 > tol * tol );
+    }
+    bool IsOverlappingProjection( const BEdge* toE, const double u, bool is1st ) const
+    {
+      // is1st shows which end of toE is projected on this at u
+      double u2;
+      const double eps = 0.1;
+      if ( myBNode1->IsCloseEdge( toE, &u2 ) ||
+           myBNode2->IsCloseEdge( toE, &u2 ))
+        return (( 0 < u2 && u2 < 1 ) &&     // u2 is proj param of myBNode's on toE
+                ( Abs( u2 - int( !is1st )) > eps ));
+
+      const BNode* n = is1st ? toE->myBNode2 : toE->myBNode1;
+      if ( this == n->GetCloseEdgeOfBorder( this->myBorderID, &u2 ))
+        return Abs( u - u2 ) > eps;
+      return false;
+    }
+    bool GetRangeOfSameCloseBorders(BEdge* eRange[2], const std::set< int >& bordIDs)
+    {
+      if ( this->myCloseBorders != bordIDs )
+        return false;
+
+      if ( bordIDs.size() == 1 && bordIDs.count( myBorderID )) // border close to self
+      {
+        double u;
+        eRange[0] = this;
+        while ( eRange[0]->myBNode1->GetCloseEdgeOfBorder( myBorderID, &u ))
+        {
+          if ( eRange[0]->myPrev == this || u < 0 || u > 1 )
+            break;
+          eRange[0] = eRange[0]->myPrev;
+        }
+        eRange[1] = this;
+        while ( eRange[1]->myBNode2->GetCloseEdgeOfBorder( myBorderID, &u ))
+        {
+          if ( eRange[1]->myNext == this || u < 0 || u > 1 )
+            break;
+          eRange[1] = eRange[1]->myNext;
+        }
+      }
+      else
+      {
+        eRange[0] = this;
+        while ( eRange[0]->myPrev && eRange[0]->myPrev->myCloseBorders == bordIDs )
+        {
+          if ( eRange[0]->myPrev == this )
+            break;
+          eRange[0] = eRange[0]->myPrev;
+        }
+
+        eRange[1] = this;
+        if ( eRange[0]->myPrev != this ) // not closed border
+          while ( eRange[1]->myNext && eRange[1]->myNext->myCloseBorders == bordIDs )
+          {
+            if ( eRange[1]->myNext == this )
+              break;
+            eRange[1] = eRange[1]->myNext;
+          }
+      }
+
+      if ( eRange[0] == eRange[1] )
+      {
+        std::set<int>::iterator closeBord = eRange[0]->myCloseBorders.begin();
+        for ( ; closeBord != eRange[0]->myCloseBorders.end(); ++closeBord )
+        {
+          if ( BEdge* be = eRange[0]->myBNode1->GetCloseEdgeOfBorder( *closeBord ))
+            if ( be->myCloseBorders == eRange[0]->myCloseBorders )
+              return true;
+          if ( BEdge* be = eRange[0]->myBNode2->GetCloseEdgeOfBorder( *closeBord ))
+            if ( be->myCloseBorders == eRange[0]->myCloseBorders )
+              return true;
+        }
+        return false;
+      }
+      return true;
+    }
+  }; // class BEdge
+
+  void extendPart( BEdge* & e1, BEdge* & e2, const std::set< int >& bordIDs, int groupID )
+  {
+    if (( e1->myPrev == e2 ) ||
+        ( e1 == e2 && e1->myPrev && e1->myPrev->myInGroup == groupID ))
+      return; // full free border already
+
+    double u;
+    BEdge* be;
+    std::set<int>::const_iterator bord;
+    if ( e1->myPrev )
+    {
+      for ( bord = bordIDs.begin(); bord != bordIDs.end(); ++bord )
+        if ((( be = e1->myBNode1->GetCloseEdgeOfBorder( *bord, &u ))) &&
+            (  be->myInGroup == groupID ) &&
+            (  0 < u && u < 1 ) &&
+            (  be->IsOverlappingProjection( e1->myPrev, u, false )))
+        {
+          e1 = e1->myPrev;
+          break;
+        }
+      if ( bord == bordIDs.end() && // not extended
+           e1->myBNode1->HasCloseEdgeWithNode( e1->myPrev->myBNode1 ))
+      {
+        e1 = e1->myPrev;
+      }
+      e1->myInGroup = groupID;
+    }
+    if ( e2->myNext )
+    {
+      for ( bord = bordIDs.begin(); bord != bordIDs.end(); ++bord )
+        if ((( be = e2->myBNode2->GetCloseEdgeOfBorder( *bord, &u ))) &&
+            (  be->myInGroup == groupID ) &&
+            (  0 < u && u < 1 ) &&
+            (  be->IsOverlappingProjection( e2->myNext, u, true )))
+        {
+          e2 = e2->myNext;
+          break;
+        }
+      if ( bord == bordIDs.end() && // not extended
+           e2->myBNode2->HasCloseEdgeWithNode( e2->myNext->myBNode2 ))
+      {
+        e2 = e2->myNext;
+      }
+      e2->myInGroup = groupID;
+    }
+  }
+
+  void BNode::AddLinked( BEdge* e ) const
+  {
+    myLinkedEdges.reserve(2);
+    myLinkedEdges.push_back( e );
+    if ( myLinkedEdges.size() < 2 ) return;
+
+    if ( myLinkedEdges.size() == 2 )
+    {
+      myLinkedEdges[0]->AddLinked( myLinkedEdges[1] );
+      myLinkedEdges[1]->AddLinked( myLinkedEdges[0] );
+    }
+    else
+    {
+      for ( size_t i = 0; i < myLinkedEdges.size(); ++i )
+        for ( size_t j = 0; j < myLinkedEdges.size(); ++j )
+          if ( i != j )
+            myLinkedEdges[i]->RemoveLinked( myLinkedEdges[j] );
+    }
+  }
+  void BNode::AddClose ( const BEdge* e, double u ) const
+  {
+    if ( ! e->Contains( this ))
+      myCloseEdges.push_back( make_pair( const_cast< BEdge* >( e ), u ));
+  }
+  BEdge* BNode::GetCloseEdgeOfBorder( int borderID, double * uPtr ) const
+  {
+    BEdge* e = 0;
+    double u = 0;
+    for ( size_t i = 0; i < myCloseEdges.size(); ++i )
+      if ( borderID == GetCloseEdge( i )->myBorderID )
+      {
+        if ( e && Abs( u - 0.5 ) < Abs( GetCloseU( i ) - 0.5 ))
+          continue;
+        u = GetCloseU( i );
+        e = GetCloseEdge ( i );
+      }
+    if ( uPtr ) *uPtr = u;
+    return e;
+  }
+  bool BNode::HasCloseEdgeWithNode( const BNode* n ) const
+  {
+    for ( size_t i = 0; i < myCloseEdges.size(); ++i )
+      if ( GetCloseEdge( i )->Contains( n ) &&
+           0 < GetCloseU( i ) && GetCloseU( i ) < 1 )
+        return true;
+    return false;
+  }
+  bool BNode::IsCloseEdge( const BEdge* e, double * uPtr ) const
+  {
+    for ( size_t i = 0; i < myCloseEdges.size(); ++i )
+      if ( e == GetCloseEdge( i ) )
+      {
+        if ( uPtr ) *uPtr = GetCloseU( i );
+        return true;
+      }
+    return false;
+  }
+
+  /// Accessor to SMDS_MeshElement* inherited by BEdge
+  struct ElemAcess
+  {
+    static const SMDS_MeshElement* value( std::vector< BEdge >::const_iterator it)
+    {
+      return & (*it);
+    }
+  };
+  /// Iterator over a vector of BEdge's
+  static SMDS_ElemIteratorPtr getElemIterator( const std::vector< BEdge > & bedges )
+  {
+    typedef SMDS_SetIterator
+      < const SMDS_MeshElement*, std::vector< BEdge >::const_iterator, ElemAcess > BEIter;
+    return SMDS_ElemIteratorPtr( new BEIter( bedges.begin(), bedges.end() ));
+  }
+
+} // namespace
+
+// struct needed for NCollection_Map
+struct TLinkHasher
+{
+  static int HashCode(const SMESH_TLink& link, int aLimit)
+  {
+    return ::HashCode( link.node1()->GetID() + link.node2()->GetID(), aLimit );
+  }
+  static Standard_Boolean IsEqual(const SMESH_TLink& l1, const SMESH_TLink& l2)
+  {
+    return ( l1.node1() == l2.node1() && l1.node2() == l2.node2() );
+  }
+};
+
+//================================================================================
+/*
+ * Returns groups of TFreeBorder's coincident within the given tolerance.
+ * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
+ * to free borders being compared is used.
+ */
+//================================================================================
+
+void SMESH_MeshAlgos::FindCoincidentFreeBorders(SMDS_Mesh&              mesh,
+                                                double                  tolerance,
+                                                CoincidentFreeBorders & foundFreeBordes)
+{
+  // find free links
+  typedef NCollection_DataMap<SMESH_TLink, const SMDS_MeshElement*, TLinkHasher > TLink2FaceMap;
+  TLink2FaceMap linkMap;
+  int nbSharedLinks = 0;
+  SMDS_FaceIteratorPtr faceIt = mesh.facesIterator();
+  while ( faceIt->more() )
+  {
+    const SMDS_MeshElement* face = faceIt->next();
+    if ( !face ) continue;
+
+    const SMDS_MeshNode*     n0 = face->GetNode( face->NbNodes() - 1 );
+    SMDS_NodeIteratorPtr nodeIt = face->interlacedNodesIterator();
+    while ( nodeIt->more() )
+    {
+      const SMDS_MeshNode* n1 = nodeIt->next();
+      SMESH_TLink link( n0, n1 );
+      if ( const SMDS_MeshElement** faceInMap = linkMap.ChangeSeek( link ))
+      {
+        nbSharedLinks += bool( *faceInMap );
+        *faceInMap = 0;
+      }
+      else
+      {
+        linkMap.Bind( link, face );
+      }
+      n0 = n1;
+    }
+  }
+  if ( linkMap.Extent() == nbSharedLinks )
+    return;
+
+  // form free borders
+  std::set   < BNode > bNodes;
+  std::vector< BEdge > bEdges( linkMap.Extent() - nbSharedLinks );
+
+  TLink2FaceMap::Iterator linkIt( linkMap );
+  for ( int iEdge = 0; linkIt.More(); linkIt.Next() )
+  {
+    if ( !linkIt.Value() ) continue;
+    const SMESH_TLink & link = linkIt.Key();
+    std::set< BNode >::iterator n1 = bNodes.insert( BNode( link.node1() )).first;
+    std::set< BNode >::iterator n2 = bNodes.insert( BNode( link.node2() )).first;
+    bEdges[ iEdge ].Set( &*n1, &*n2, linkIt.Value(), iEdge+1 );
+    n1->AddLinked( & bEdges[ iEdge ] );
+    n2->AddLinked( & bEdges[ iEdge ] );
+    ++iEdge;
+  }
+  linkMap.Clear();
+
+  // assign IDs to borders
+  std::vector< BEdge* > borders; // 1st of connected (via myPrev and myNext) edges
+  std::set< BNode >::iterator bn = bNodes.begin();
+  for ( ; bn != bNodes.end(); ++bn )
+  {
+    for ( size_t i = 0; i < bn->myLinkedEdges.size(); ++i )
+    {
+      if ( bn->myLinkedEdges[i]->myBorderID < 0 )
+      {
+        BEdge* be = bn->myLinkedEdges[i];
+        int borderID = borders.size();
+        borders.push_back( be );
+        for ( ; be && be->myBorderID < 0; be = be->myNext )
+        {
+          be->myBorderID = borderID;
+          be->Orient();
+        }
+        bool isClosed = ( be == bn->myLinkedEdges[i] );
+        be = bn->myLinkedEdges[i]->myPrev;
+        for ( ; be && be->myBorderID < 0; be = be->myPrev )
+        {
+          be->myBorderID = borderID;
+          be->Orient();
+        }
+        if ( !isClosed )
+          while ( borders.back()->myPrev )
+            borders.back() = borders.back()->myPrev;
+
+        borders.back()->SetID( 0 ); // set IDs to all edges of the border
+      }
+    }
+  }
+
+  // compute tolerance of each border
+  double maxTolerance = tolerance;
+  std::vector< double > bordToler( borders.size(), tolerance );
+  if ( maxTolerance < std::numeric_limits< double >::min() )
+  {
+    // no tolerance provided by the user; compute tolerance of each border
+    // as one tenth of an average size of faces adjacent to a border
+    for ( size_t i = 0; i < borders.size(); ++i )
+    {
+      double avgFaceSize = 0;
+      int    nbFaces     = 0;
+      BEdge* be = borders[ i ];
+      do {
+        double facePerimeter = 0;
+        gp_Pnt p0 = SMESH_TNodeXYZ( be->myFace->GetNode( be->myFace->NbNodes() - 1 ));
+        SMDS_NodeIteratorPtr nodeIt = be->myFace->interlacedNodesIterator();
+        while ( nodeIt->more() )
+        {
+          gp_Pnt p1 = SMESH_TNodeXYZ( nodeIt->next() );
+          facePerimeter += p0.Distance( p1 );
+          p0 = p1;
+        }
+        avgFaceSize += ( facePerimeter / be->myFace->NbCornerNodes() );
+        nbFaces++;
+
+        be = be->myNext;
+      }
+      while ( be && be != borders[i] );
+
+      bordToler[ i ] = 0.1 * avgFaceSize / nbFaces;
+      maxTolerance = Max( maxTolerance, bordToler[ i ]);
+    }
+  }
+
+  // for every border node find close border edges
+  SMESH_ElementSearcher* searcher =
+    GetElementSearcher( mesh, getElemIterator( bEdges ), maxTolerance );
+  SMESHUtils::Deleter< SMESH_ElementSearcher > searcherDeleter( searcher );
+  std::vector< const SMDS_MeshElement* > candidateEdges;
+  for ( bn = bNodes.begin(); bn != bNodes.end(); ++bn )
+  {
+    searcher->FindElementsByPoint( *bn, SMDSAbs_Edge, candidateEdges );
+    if ( candidateEdges.size() <= bn->myLinkedEdges.size() )
+      continue;
+
+    double nodeTol = 0, u;
+    for ( size_t i = 0; i < bn->myLinkedEdges.size(); ++i )
+      nodeTol = Max( nodeTol, bordToler[ bn->myLinkedEdges[ i ]->myBorderID ]);
+
+    for ( size_t i = 0; i < candidateEdges.size(); ++i )
+    {
+      const BEdge* be = static_cast< const BEdge* >( candidateEdges[ i ]);
+      double      tol = Max( nodeTol, bordToler[ be->myBorderID ]);
+      if ( !be->IsOut( *bn, tol, u ))
+        bn->AddClose( be, u );
+    }
+  }
+
+  // for every border edge find close borders
+
+  std::vector< BEdge* > closeEdges;
+  for ( size_t i = 0; i < bEdges.size(); ++i )
+  {
+    BEdge& be = bEdges[i];
+    if ( be.myBNode1->myCloseEdges.empty() ||
+         be.myBNode2->myCloseEdges.empty() )
+      continue;
+
+    closeEdges.clear();
+    for ( size_t iE1 = 0; iE1 < be.myBNode1->myCloseEdges.size(); ++iE1 )
+    {
+      // find edges of the same border close to both nodes of the edge
+      BEdge* closeE1 = be.myBNode1->GetCloseEdge( iE1 );
+      BEdge* closeE2 = be.myBNode2->GetCloseEdgeOfBorder( closeE1->myBorderID );
+      if ( !closeE2 )
+        continue;
+      // check that edges connecting closeE1 and closeE2 (if any) are also close to 'be'
+      if ( closeE1 != closeE2 )
+      {
+        bool coincide;
+        for ( int j = 0; j < 2; ++j ) // move closeE1 -> closeE2 or inversely
+        {
+          BEdge* ce = closeE1;
+          do {
+            coincide = ( ce->myBNode2->GetCloseEdgeOfBorder( be.myBorderID ));
+            ce       = ce->myNext;
+          } while ( coincide && ce && ce != closeE2 );
+
+          if ( coincide && ce == closeE2 )
+            break;
+          if ( j == 0 )
+            std::swap( closeE1, closeE2 );
+          coincide = false;
+        }
+        if ( !coincide )
+          continue;
+        closeEdges.push_back( closeE1 );
+        closeEdges.push_back( closeE2 );
+      }
+      else
+      {
+        closeEdges.push_back( closeE1 );
+      }
+      be.myCloseBorders.insert( closeE1->myBorderID );
+    }
+    if ( !closeEdges.empty() )
+    {
+      be.myCloseBorders.insert( be.myBorderID );
+      // for ( size_t iB = 0; iB < closeEdges.size(); ++iB )
+      //   closeEdges[ iB ]->myCloseBorders.insert( be.myCloseBorders.begin(),
+      //                                            be.myCloseBorders.end() );
+    }
+  }
+
+  // Fill in CoincidentFreeBorders
+
+  // save nodes of free borders
+  foundFreeBordes._borders.resize( borders.size() );
+  for ( size_t i = 0; i < borders.size(); ++i )
+  {
+    BEdge* be = borders[i];
+    foundFreeBordes._borders[i].push_back( be->myBNode1->Node() );
+    do {
+      foundFreeBordes._borders[i].push_back( be->myBNode2->Node() );
+      be = be->myNext;
+    }
+    while ( be && be != borders[i] );
+  }
+
+  // form groups of coincident parts of free borders
+
+  TFreeBorderPart  part;
+  TCoincidentGroup group;
+  vector< BEdge* > ranges; // couples of edges delimiting parts
+  BEdge* be = 0; // a current edge
+  int skipGroup = bEdges.size(); // a group ID used to avoid repeating treatment of edges
+
+  for ( int i = 0, nbBords = borders.size(); i < nbBords; i += bool(!be) )
+  {
+    if ( !be )
+      be = borders[i];
+
+    // look for an edge close to other borders
+    do {
+      if ( !be->IsInGroup() && !be->myCloseBorders.empty() )
+        break;
+      be = be->myNext;
+    } while ( be && be != borders[i] );
+
+    if ( !be || be->IsInGroup() || be->myCloseBorders.empty() )
+    {
+      be = 0;
+      continue; // all edges of a border are treated or non-coincident
+    }
+    group.clear();
+    ranges.clear();
+
+    // look for the 1st and last edge of a coincident group
+    BEdge* beRange[2];
+    if ( !be->GetRangeOfSameCloseBorders( beRange, be->myCloseBorders ))
+    {
+      be->myInGroup = skipGroup;
+      be = be->myNext;
+      continue;
+    }
+
+    ranges.push_back( beRange[0] );
+    ranges.push_back( beRange[1] );
+
+    int groupID = foundFreeBordes._coincidentGroups.size();
+    be = beRange[0];
+    be->myInGroup = groupID;
+    while ( be != beRange[1] )
+    {
+      be->myInGroup = groupID;
+      be = be->myNext;
+    }
+    beRange[1]->myInGroup = groupID;
+
+    // get starting edge of each close border
+    closeEdges.clear();
+    be = beRange[0];
+    if ( be->myCloseBorders.empty() )
+      be = beRange[0]->myNext;
+    std::set<int>::iterator closeBord = be->myCloseBorders.begin();
+    for ( ; closeBord != be->myCloseBorders.end(); ++closeBord )
+      if ( BEdge* e = be->myBNode2->GetCloseEdgeOfBorder( *closeBord ))
+        closeEdges.push_back( e );
+
+    for ( size_t iE = 0; iE < closeEdges.size(); ++iE )
+      if ( be->myCloseBorders != closeEdges[iE]->myCloseBorders )
+      {
+        closeBord = closeEdges[iE]->myCloseBorders.begin();
+        for ( ; closeBord != closeEdges[iE]->myCloseBorders.end(); ++closeBord )
+          if ( !be->myCloseBorders.count( *closeBord ))
+            if ( BEdge* e = closeEdges[iE]->myBNode2->GetCloseEdgeOfBorder( *closeBord ))
+              if ( std::find( closeEdges.begin(), closeEdges.end(), e ) == closeEdges.end() )
+                closeEdges.push_back( e );
+      }
+
+    // add parts of other borders
+
+    BEdge* be1st = beRange[0];
+    for ( size_t iE = 0; iE < closeEdges.size(); ++iE )
+    {
+      be = closeEdges[ iE ];
+      if ( !be ) continue;
+
+      bool ok = be->GetRangeOfSameCloseBorders( beRange, be->myCloseBorders );
+      // if ( !ok && be->myPrev )
+      //   ok = be->myPrev->GetRangeOfSameCloseBorders( beRange, be1st->myCloseBorders );
+      // if ( !ok && be->myNext )
+      //   ok = be->myNext->GetRangeOfSameCloseBorders( beRange, be1st->myCloseBorders );
+      if ( !ok )
+        continue;
+
+      be = beRange[0];
+
+      ranges.push_back( beRange[0] );
+      ranges.push_back( beRange[1] );
+
+      be->myInGroup = groupID;
+      while ( be != beRange[1] )
+      {
+        be->myInGroup = groupID;
+        be = be->myNext;
+      }
+      beRange[1]->myInGroup = groupID;
+    }
+
+    if ( ranges.size() > 2 )
+    {
+      for ( size_t iR = 1; iR < ranges.size(); iR += 2 )
+        extendPart( ranges[ iR-1 ], ranges[ iR ], be1st->myCloseBorders, groupID );
+
+      // fill in a group
+      beRange[0] = ranges[0];
+      beRange[1] = ranges[1];
+
+      part._border   = i;
+      part._node1    = beRange[0]->myID;
+      part._node2    = beRange[0]->myID + 1;
+      part._nodeLast = beRange[1]->myID + 1;
+      group.push_back( part );
+
+      be1st = beRange[0];
+      for ( size_t iR = 3; iR < ranges.size(); iR += 2 )
+      {
+        beRange[0] = ranges[iR-1];
+        beRange[1] = ranges[iR-0];
+
+        // find out mutual orientation of borders
+        double u1, u2;
+        be1st       ->IsOut( *beRange[ 0 ]->myBNode1, maxTolerance, u1 );
+        beRange[ 0 ]->IsOut( *be1st->myBNode1,        maxTolerance, u2 );
+        bool reverse = (( u1 < 0 || u1 > 1 ) && ( u2 < 0 || u2 > 1 ));
+
+        // fill in a group
+        part._border   = beRange[0]->myBorderID;
+        if ( reverse ) {
+          part._node1    = beRange[1]->myID + 1;
+          part._node2    = beRange[1]->myID;
+          part._nodeLast = beRange[0]->myID;
+        }
+        else  {
+          part._node1    = beRange[0]->myID;
+          part._node2    = beRange[0]->myID + 1;
+          part._nodeLast = beRange[1]->myID + 1;
+        }
+        // if ( group[0]._node2 != part._node2 )
+        group.push_back( part );
+      }
+      //if ( group.size() > 1 )
+        foundFreeBordes._coincidentGroups.push_back( group );
+    }
+    else
+    {
+      beRange[0] = ranges[0];
+      beRange[1] = ranges[1];
+
+      be = beRange[0];
+      be->myInGroup = skipGroup;
+      while ( be != beRange[1] )
+      {
+        be->myInGroup = skipGroup;
+        be = be->myNext;
+      }
+      beRange[1]->myInGroup = skipGroup;
+    }
+
+    be = ranges[1];
+
+  } // loop on free borders
+
+  return;
+
+} // SMESH_MeshAlgos::FindCoincidentFreeBorders()
+
index 66ac2ff309a0487e65c931b1aa78ff2fe2299294..dc445146cabf54a1947e184fa5f8a20f672b1227 100644 (file)
@@ -47,7 +47,7 @@
 #include <TopoDS_Wire.hxx>
 
 #ifdef _DEBUG_
-//#define _MYDEBUG_
+#define _MYDEBUG_
 #include "SMESH_File.hxx"
 #include "SMESH_Comment.hxx"
 #endif
@@ -96,6 +96,9 @@ namespace
       : _p0(p0), _p1(p1), _geomEdgeInd(iE) {}
     InSegment() : _p0(0), _p1(0), _geomEdgeInd(0) {}
 
+    const InPoint& point0() const { return *_p0; }
+    const InPoint& point1() const { return *_p1; }
+
     inline bool isConnected( const TVDEdge* edge );
 
     inline bool isExternal( const TVDEdge* edge );
@@ -258,8 +261,9 @@ namespace boost {
 
 namespace
 {
-  const int theNoBrachID = 0; // std::numeric_limits<int>::max();
-  double theScale[2]; // scale used in bndSegsToMesh()
+  const int    theNoBrachID = 0;
+  double       theScale[2]; // scale used in bndSegsToMesh()
+  const size_t theNoEdgeID = std::numeric_limits<size_t>::max() / 1000;
 
   // -------------------------------------------------------------------------------------
   /*!
@@ -277,17 +281,18 @@ namespace
   };
   // -------------------------------------------------------------------------------------
   /*!
-   * \brief A segment on EDGE, used to create BndPoints
+   * \brief Segment of EDGE, used to create BndPoints
    */
   struct BndSeg
   {
     InSegment*       _inSeg;
     const TVDEdge*   _edge;
     double           _uLast;
+    BndSeg*          _prev; // previous BndSeg in FACE boundary
     int              _branchID; // negative ID means reverse direction
 
     BndSeg( InSegment* seg, const TVDEdge* edge, double u ):
-      _inSeg(seg), _edge(edge), _uLast(u), _branchID( theNoBrachID ) {}
+      _inSeg(seg), _edge(edge), _uLast(u), _prev(0), _branchID( theNoBrachID ) {}
 
     void setIndexToEdge( size_t id )
     {
@@ -298,21 +303,39 @@ namespace
 
     size_t geomEdge() const { return _inSeg->_geomEdgeInd; }
 
-    void setBranch( int branchID, vector< BndSeg >& bndSegs )
+    static BndSeg* getBndSegOfEdge( const TVDEdge*              edge,
+                                    vector< vector< BndSeg > >& bndSegsPerEdge )
     {
-      _branchID = branchID;
-
-      if ( _edge ) // pass branch to an opposite BndSeg
+      BndSeg* seg = 0;
+      if ( edge )
       {
-        size_t oppSegIndex = SMESH_MAT2d::Branch::getBndSegment( _edge->twin() );
-        if ( oppSegIndex < bndSegs.size() && bndSegs[ oppSegIndex ]._branchID == theNoBrachID )
-          bndSegs[ oppSegIndex ]._branchID = -branchID;
+        size_t oppSegIndex  = SMESH_MAT2d::Branch::getBndSegment( edge );
+        size_t oppEdgeIndex = SMESH_MAT2d::Branch::getGeomEdge  ( edge );
+        if ( oppEdgeIndex < bndSegsPerEdge.size() &&
+             oppSegIndex < bndSegsPerEdge[ oppEdgeIndex ].size() )
+        {
+          seg = & bndSegsPerEdge[ oppEdgeIndex ][ oppSegIndex ];
+        }
       }
+      return seg;
+    }
+
+    void setBranch( int branchID, vector< vector< BndSeg > >& bndSegsPerEdge )
+    {
+      _branchID = branchID;
+
+      // pass branch to an opposite BndSeg
+      if ( _edge )
+        if ( BndSeg* oppSeg = getBndSegOfEdge( _edge->twin(), bndSegsPerEdge ))
+        {
+          if ( oppSeg->_branchID == theNoBrachID )
+            oppSeg->_branchID = -branchID;
+        }
     }
-    bool hasOppositeEdge( const size_t noEdgeID )
+    bool hasOppositeEdge()
     {
       if ( !_edge ) return false;
-      return ( _inSeg->getGeomEdge( _edge->twin()->cell() ) != noEdgeID );
+      return ( _inSeg->getGeomEdge( _edge->twin()->cell() ) != theNoEdgeID );
     }
 
     // check a next segment in CW order
@@ -321,6 +344,9 @@ namespace
       if ( !_edge || !seg2._edge )
         return true;
 
+      if ( _edge->twin() == seg2._edge )
+        return true;
+
       const TVDCell* cell1 = this->_edge->twin()->cell();
       const TVDCell* cell2 = seg2. _edge->twin()->cell();
       if ( cell1 == cell2 )
@@ -344,14 +370,44 @@ namespace
       else if ( edgeMedium1->is_primary() && edgeMedium2->is_primary() )
       {
         if ( edgeMedium1->twin() == edgeMedium2 &&
-             SMESH_MAT2d::Branch::getBndSegment( edgeMedium1 ) ==
-             SMESH_MAT2d::Branch::getBndSegment( edgeMedium2 ))
+             SMESH_MAT2d::Branch::getGeomEdge( edgeMedium1 ) ==
+             SMESH_MAT2d::Branch::getGeomEdge( edgeMedium2 ))
           // this is an ignored MA edge between inSegment's on one EDGE forming a convex corner
           return true;
       }
 
       return false;
     }
+  }; // struct BndSeg
+
+  // -------------------------------------------------------------------------------------
+  /*!
+   * \brief Iterator 
+   */
+  struct BranchIterator
+  {
+    int                                 _i, _size;
+    const std::vector<const TVDEdge*> & _edges;
+    bool                                _closed;
+
+    BranchIterator(const std::vector<const TVDEdge*> & edges, int i )
+      :_i( i ), _size( edges.size() ), _edges( edges )
+    {
+      _closed = ( edges[0]->vertex1() == edges.back()->vertex0() || // closed branch
+                  edges[0]->vertex0() == edges.back()->vertex1() );
+    }
+    const TVDEdge* operator++() { ++_i; return edge(); }
+    const TVDEdge* operator--() { --_i; return edge(); }
+    bool operator<( const BranchIterator& other ) { return _i < other._i; }
+    BranchIterator& operator=( const BranchIterator& other ) { _i = other._i; return *this; }
+    void set(int i) { _i = i; }
+    int  index() const { return _i; }
+    int  indexMod() const { return ( _i + _size ) % _size; }
+    const TVDEdge* edge() const {
+      return _closed ? _edges[ indexMod() ] : ( _i < 0 || _i >= _size ) ? 0 : _edges[ _i ];
+    }
+    const TVDEdge* edgePrev() { --_i; const TVDEdge* e = edge(); ++_i; return e; }
+    const TVDEdge* edgeNext() { ++_i; const TVDEdge* e = edge(); --_i; return e; }
   };
 
   //================================================================================
@@ -360,7 +416,7 @@ namespace
    */
   //================================================================================
 
-  void bndSegsToMesh( const vector< BndSeg >& bndSegs )
+  void bndSegsToMesh( const vector< vector< BndSeg > >& bndSegsPerEdge )
   {
 #ifdef _MYDEBUG_
     if ( !getenv("bndSegsToMesh")) return;
@@ -378,36 +434,40 @@ namespace
     text << "from salome.smesh import smeshBuilder\n";
     text << "smesh = smeshBuilder.New(salome.myStudy)\n";
     text << "m=smesh.Mesh()\n";
-    for ( size_t i = 0; i < bndSegs.size(); ++i )
+    for ( size_t iE = 0; iE < bndSegsPerEdge.size(); ++iE )
     {
-      if ( !bndSegs[i]._edge )
-        text << "# " << i << " NULL edge";
-      else if ( !bndSegs[i]._edge->vertex0() ||
-                !bndSegs[i]._edge->vertex1() )
-        text << "# " << i << " INFINITE edge";
-      else if ( addedEdges.insert( bndSegs[i]._edge ).second &&
-                addedEdges.insert( bndSegs[i]._edge->twin() ).second )
+      const vector< BndSeg >& bndSegs = bndSegsPerEdge[ iE ];
+      for ( size_t i = 0; i < bndSegs.size(); ++i )
       {
-        v2n = v2Node.insert( make_pair( bndSegs[i]._edge->vertex0(), v2Node.size() + 1 )).first;
-        int n0 = v2n->second;
-        if ( n0 == v2Node.size() )
-          text << "n" << n0 << " = m.AddNode( "
-               << bndSegs[i]._edge->vertex0()->x() / theScale[0] << ", "
-               << bndSegs[i]._edge->vertex0()->y() / theScale[1] << ", 0 )\n";
-
-        v2n = v2Node.insert( make_pair( bndSegs[i]._edge->vertex1(), v2Node.size() + 1 )).first;
-        int n1 = v2n->second;
-        if ( n1 == v2Node.size() )
-          text << "n" << n1 << " = m.AddNode( "
-               << bndSegs[i]._edge->vertex1()->x() / theScale[0] << ", "
-               << bndSegs[i]._edge->vertex1()->y() / theScale[1] << ", 0 )\n";
-
-        text << "e" << i << " = m.AddEdge([ n" << n0 << ", n" << n1 << " ])\n";
+        if ( !bndSegs[i]._edge )
+          text << "# E=" << iE << " i=" << i << " NULL edge\n";
+        else if ( !bndSegs[i]._edge->vertex0() ||
+                  !bndSegs[i]._edge->vertex1() )
+          text << "# E=" << iE << " i=" << i << " INFINITE edge\n";
+        else if ( addedEdges.insert( bndSegs[i]._edge ).second &&
+                  addedEdges.insert( bndSegs[i]._edge->twin() ).second )
+        {
+          v2n = v2Node.insert( make_pair( bndSegs[i]._edge->vertex0(), v2Node.size() + 1 )).first;
+          int n0 = v2n->second;
+          if ( n0 == v2Node.size() )
+            text << "n" << n0 << " = m.AddNode( "
+                 << bndSegs[i]._edge->vertex0()->x() / theScale[0] << ", "
+                 << bndSegs[i]._edge->vertex0()->y() / theScale[1] << ", 0 )\n";
+
+          v2n = v2Node.insert( make_pair( bndSegs[i]._edge->vertex1(), v2Node.size() + 1 )).first;
+          int n1 = v2n->second;
+          if ( n1 == v2Node.size() )
+            text << "n" << n1 << " = m.AddNode( "
+                 << bndSegs[i]._edge->vertex1()->x() / theScale[0] << ", "
+                 << bndSegs[i]._edge->vertex1()->y() / theScale[1] << ", 0 )\n";
+
+          text << "e" << i << " = m.AddEdge([ n" << n0 << ", n" << n1 << " ])\n";
+        }
       }
     }
     text << "\n";
     file.write( text.c_str(), text.size() );
-    cout << "Write " << fileName << endl;
+    cout << "execfile( '" << fileName << "')" << endl;
 #endif
   }
 
@@ -670,22 +730,25 @@ namespace
    */
   //================================================================================
 
-  void updateJoinedBranch( vector< const TVDEdge* > & branchEdges,
-                           const size_t               newID,
-                           vector< BndSeg > &         bndSegs,
-                           const bool                 reverse)
+  void updateJoinedBranch( vector< const TVDEdge* > &   branchEdges,
+                           const size_t                 newID,
+                           vector< vector< BndSeg > > & bndSegs,
+                           const bool                   reverse)
   {
+    BndSeg *seg1, *seg2;
     if ( reverse )
     {
       for ( size_t i = 0; i < branchEdges.size(); ++i )
       {
-        size_t seg1 = SMESH_MAT2d::Branch::getBndSegment( branchEdges[i] );
-        size_t seg2 = SMESH_MAT2d::Branch::getBndSegment( branchEdges[i]->twin() );
-        bndSegs[ seg1 ]._branchID /= bndSegs[ seg1 ].branchID();
-        bndSegs[ seg2 ]._branchID /= bndSegs[ seg2 ].branchID();
-        bndSegs[ seg1 ]._branchID *= -newID;
-        bndSegs[ seg2 ]._branchID *= -newID;
-        branchEdges[i] = branchEdges[i]->twin();
+        if (( seg1 = BndSeg::getBndSegOfEdge( branchEdges[i],         bndSegs )) &&
+            ( seg2 = BndSeg::getBndSegOfEdge( branchEdges[i]->twin(), bndSegs )))
+        {
+          seg1->_branchID /= seg1->branchID();
+          seg2->_branchID /= seg2->branchID();
+          seg1->_branchID *= -newID;
+          seg2->_branchID *= -newID;
+          branchEdges[i] = branchEdges[i]->twin();
+        }
       }
       std::reverse( branchEdges.begin(), branchEdges.end() );
     }
@@ -693,12 +756,14 @@ namespace
     {
       for ( size_t i = 0; i < branchEdges.size(); ++i )
       {
-        size_t seg1 = SMESH_MAT2d::Branch::getBndSegment( branchEdges[i] );
-        size_t seg2 = SMESH_MAT2d::Branch::getBndSegment( branchEdges[i]->twin() );
-        bndSegs[ seg1 ]._branchID /= bndSegs[ seg1 ].branchID();
-        bndSegs[ seg2 ]._branchID /= bndSegs[ seg2 ].branchID();
-        bndSegs[ seg1 ]._branchID *= newID;
-        bndSegs[ seg2 ]._branchID *= newID;
+        if (( seg1 = BndSeg::getBndSegOfEdge( branchEdges[i],         bndSegs )) &&
+            ( seg2 = BndSeg::getBndSegOfEdge( branchEdges[i]->twin(), bndSegs )))
+        {
+          seg1->_branchID /= seg1->branchID();
+          seg2->_branchID /= seg2->branchID();
+          seg1->_branchID *= newID;
+          seg2->_branchID *= newID;
+        }
       }
     }
   }
@@ -723,9 +788,7 @@ namespace
                vector< const SMESH_MAT2d::BranchEnd* >& branchPnt,
                SMESH_MAT2d::Boundary&                   boundary )
   {
-    const size_t noEdgeID = inSegments.size() + 1; // ID of non-existent geom EDGE
-
-    // Associate MA cells with inSegments
+    // Associate MA cells with geom EDGEs
     for (TVD::const_cell_iterator it = vd.cells().begin(); it != vd.cells().end(); ++it)
     {
       const TVDCell* cell = &(*it);
@@ -737,7 +800,7 @@ namespace
       }
       else
       {
-        InSegment::setGeomEdgeToCell( cell, noEdgeID );
+        InSegment::setGeomEdgeToCell( cell, theNoEdgeID );
       }
     }
 
@@ -806,7 +869,7 @@ namespace
         {
           if ( edge->is_primary() ) break; // this should not happen
           const TVDEdge* edge2 = edge->twin(); // we are in a neighbor cell, add MA edges to inPnt
-          if ( inSeg.getGeomEdge( edge2->cell() ) != noEdgeID )
+          if ( inSeg.getGeomEdge( edge2->cell() ) != theNoEdgeID )
             break; // cell of an InSegment
           bool hasInfinite = false;
           list< const TVDEdge* > pointEdges;
@@ -840,63 +903,96 @@ namespace
     if ( inPoints.front() == inPoints.back() /*&& !inPoints[0]._edges.empty()*/ )
     {
       inPntChecked[0] = false; // do not use the 1st point twice
-      //InSegment::setGeomEdgeToCell( inPoints[0]._edges.back()->cell(), noEdgeID );
+      //InSegment::setGeomEdgeToCell( inPoints[0]._edges.back()->cell(), theNoEdgeID );
       inPoints[0]._edges.clear();
     }
 
     // Divide InSegment's into BndSeg's (so that each BndSeg corresponds to one MA edge)
 
-    vector< BndSeg > bndSegs;
-    bndSegs.reserve( inSegments.size() * 3 );
-
-    list< const TVDEdge* >::reverse_iterator e;
-    for ( size_t i = 0; i < inSegments.size(); ++i )
+    vector< vector< BndSeg > > bndSegsPerEdge( boundary.nbEdges() ); // all BndSeg's
     {
-      InSegment& inSeg = inSegments[i];
+      vector< BndSeg > bndSegs; // bndSeg's of a current EDGE
+      size_t prevGeomEdge = theNoEdgeID;
+
+      list< const TVDEdge* >::reverse_iterator e;
+      for ( size_t i = 0; i < inSegments.size(); ++i )
+      {
+        InSegment& inSeg = inSegments[i];
 
-      // segments around 1st concave point
-      size_t ip0 = inSeg._p0->index( inPoints );
-      if ( inPntChecked[ ip0 ] )
-        for ( e = inSeg._p0->_edges.rbegin(); e != inSeg._p0->_edges.rend(); ++e )
-          bndSegs.push_back( BndSeg( &inSeg, *e, inSeg._p0->_param ));
-      inPntChecked[ ip0 ] = false;
-
-      // segments of InSegment's
-      const size_t nbMaEdges = inSeg._edges.size();
-      switch ( nbMaEdges ) {
-      case 0: // "around" circle center
-        bndSegs.push_back( BndSeg( &inSeg, 0, inSeg._p1->_param )); break;
-      case 1:
-        bndSegs.push_back( BndSeg( &inSeg, inSeg._edges.back(), inSeg._p1->_param )); break;
-      default:
-        gp_XY inSegDir( inSeg._p1->_a - inSeg._p0->_a,
-                        inSeg._p1->_b - inSeg._p0->_b );
-        const double inSegLen2 = inSegDir.SquareModulus();
-        e = inSeg._edges.rbegin();
-        for ( size_t iE = 1; iE < nbMaEdges; ++e, ++iE )
+        if ( inSeg._geomEdgeInd != prevGeomEdge )
         {
-          gp_XY toMA( (*e)->vertex0()->x() - inSeg._p0->_a,
-                      (*e)->vertex0()->y() - inSeg._p0->_b );
-          double r = toMA * inSegDir / inSegLen2;
-          double u = r * inSeg._p1->_param + ( 1. - r ) * inSeg._p0->_param;
-          bndSegs.push_back( BndSeg( &inSeg, *e, u ));
+          if ( !bndSegs.empty() )
+            bndSegsPerEdge[ prevGeomEdge ].swap( bndSegs );
+          prevGeomEdge = inSeg._geomEdgeInd;
         }
-        bndSegs.push_back( BndSeg( &inSeg, *e, inSeg._p1->_param ));
-      }
-      // segments around 2nd concave point
-      size_t ip1 = inSeg._p1->index( inPoints );
-      if ( inPntChecked[ ip1 ] )
-        for ( e = inSeg._p1->_edges.rbegin(); e != inSeg._p1->_edges.rend(); ++e )
+
+        // segments around 1st concave point
+        size_t ip0 = inSeg._p0->index( inPoints );
+        if ( inPntChecked[ ip0 ] )
+          for ( e = inSeg._p0->_edges.rbegin(); e != inSeg._p0->_edges.rend(); ++e )
+            bndSegs.push_back( BndSeg( &inSeg, *e, inSeg._p0->_param ));
+        inPntChecked[ ip0 ] = false;
+
+        // segments of InSegment's
+        const size_t nbMaEdges = inSeg._edges.size();
+        switch ( nbMaEdges ) {
+        case 0: // "around" circle center
+          bndSegs.push_back( BndSeg( &inSeg, 0, inSeg._p1->_param )); break;
+        case 1:
+          bndSegs.push_back( BndSeg( &inSeg, inSeg._edges.back(), inSeg._p1->_param )); break;
+        default:
+          gp_XY inSegDir( inSeg._p1->_a - inSeg._p0->_a,
+                          inSeg._p1->_b - inSeg._p0->_b );
+          const double inSegLen2 = inSegDir.SquareModulus();
+          e = inSeg._edges.rbegin();
+          for ( size_t iE = 1; iE < nbMaEdges; ++e, ++iE )
+          {
+            gp_XY toMA( (*e)->vertex0()->x() - inSeg._p0->_a,
+                        (*e)->vertex0()->y() - inSeg._p0->_b );
+            double r = toMA * inSegDir / inSegLen2;
+            double u = r * inSeg._p1->_param + ( 1. - r ) * inSeg._p0->_param;
+            bndSegs.push_back( BndSeg( &inSeg, *e, u ));
+          }
           bndSegs.push_back( BndSeg( &inSeg, *e, inSeg._p1->_param ));
-      inPntChecked[ ip1 ] = false;
+        }
+        // segments around 2nd concave point
+        size_t ip1 = inSeg._p1->index( inPoints );
+        if ( inPntChecked[ ip1 ] )
+          for ( e = inSeg._p1->_edges.rbegin(); e != inSeg._p1->_edges.rend(); ++e )
+            bndSegs.push_back( BndSeg( &inSeg, *e, inSeg._p1->_param ));
+        inPntChecked[ ip1 ] = false;
+      }
+      if ( !bndSegs.empty() )
+        bndSegsPerEdge[ prevGeomEdge ].swap( bndSegs );
     }
 
-    // make TVDEdge's know it's BndSeg to enable passing branchID to
-    // an opposite BndSeg in BndSeg::setBranch()
-    for ( size_t i = 0; i < bndSegs.size(); ++i )
-      bndSegs[i].setIndexToEdge( i );
+    // prepare to MA branch search
+    for ( size_t iE = 0; iE < bndSegsPerEdge.size(); ++iE )
+    {
+      // 1) make TVDEdge's know it's BndSeg to enable passing branchID to
+      // an opposite BndSeg in BndSeg::setBranch(); geom EDGE ID is known from TVDCell
+      // 2) connect bndSegs via BndSeg::_prev
+
+      vector< BndSeg >& bndSegs = bndSegsPerEdge[ iE ];
+      if ( bndSegs.empty() ) continue;
+
+      for ( size_t i = 1; i < bndSegs.size(); ++i )
+      {
+        bndSegs[i]._prev = & bndSegs[i-1];
+        bndSegs[i].setIndexToEdge( i );
+      }
+      // look for the last bndSeg of previous EDGE to set bndSegs[0]._prev
+      const InPoint& p0 = bndSegs[0]._inSeg->point0();
+      for ( size_t iE2 = 0; iE2 < bndSegsPerEdge.size(); ++iE2 )
+        if ( p0 == bndSegsPerEdge[ iE2 ].back()._inSeg->point1() )
+        {
+          bndSegs[0]._prev = & bndSegsPerEdge[ iE2 ].back();
+          break;
+        }
+      bndSegs[0].setIndexToEdge( 0 );
+    }
 
-    bndSegsToMesh( bndSegs ); // debug: visually check found MA edges
+    bndSegsToMesh( bndSegsPerEdge ); // debug: visually check found MA edges
 
 
     // Find TVDEdge's of Branches and associate them with bndSegs
@@ -907,71 +1003,69 @@ namespace
     map< const TVDVertex*, SMESH_MAT2d::BranchEndType > endType;
 
     int branchID = 1; // we code orientation as branchID sign
-    branchEdges.resize( branchID + 1 );
+    branchEdges.resize( branchID );
 
-    size_t i1st = 0;
-    while ( i1st < bndSegs.size() && !bndSegs[i1st].hasOppositeEdge( noEdgeID ))
-      ++i1st;
-    bndSegs[i1st].setBranch( branchID, bndSegs ); // set to the i-th and to the opposite bndSeg
-    branchEdges[ branchID ].push_back( bndSegs[i1st]._edge );
-
-    for ( size_t i = i1st+1; i < bndSegs.size(); ++i )
+    for ( size_t iE = 0; iE < bndSegsPerEdge.size(); ++iE )
     {
-      if ( bndSegs[i].branchID() )
+      vector< BndSeg >& bndSegs = bndSegsPerEdge[ iE ];
+      for ( size_t i = 0; i < bndSegs.size(); ++i )
       {
-        branchID = bndSegs[i]._branchID; // with sign
+        if ( bndSegs[i].branchID() )
+        {
+          if ( bndSegs[i]._prev &&
+               bndSegs[i]._branchID == -bndSegs[i]._prev->_branchID &&
+               bndSegs[i]._edge )
+          {
+            SMESH_MAT2d::BranchEndType type =
+              ( bndSegs[i]._inSeg->isConnected( bndSegs[i]._edge ) ?
+                SMESH_MAT2d::BE_ON_VERTEX :
+                SMESH_MAT2d::BE_END );
+            endType.insert( make_pair( bndSegs[i]._edge->vertex1(), type ));
+          }
+          continue;
+        }
+        if ( !bndSegs[i]._prev &&
+             !bndSegs[i].hasOppositeEdge() )
+          continue;
 
-        if ( bndSegs[i]._branchID == -bndSegs[i-1]._branchID &&
-             bndSegs[i]._edge )
+        if ( !bndSegs[i]._prev ||
+             !bndSegs[i]._prev->isSameBranch( bndSegs[i] ))
         {
-          SMESH_MAT2d::BranchEndType type =
-            ( bndSegs[i]._inSeg->isConnected( bndSegs[i]._edge ) ?
-              SMESH_MAT2d::BE_ON_VERTEX :
-              SMESH_MAT2d::BE_END );
-          endType.insert( make_pair( bndSegs[i]._edge->vertex1(), type ));
+          branchEdges.resize(( branchID = branchEdges.size()) + 1 );
+          if ( bndSegs[i]._edge && bndSegs[i]._prev )
+            endType.insert( make_pair( bndSegs[i]._edge->vertex1(), SMESH_MAT2d::BE_BRANCH_POINT ));
         }
-        continue;
-      }
-      if ( !bndSegs[i-1].isSameBranch( bndSegs[i] ))
-      {
-        branchEdges.resize(( branchID = branchEdges.size()) + 1 );
-        if ( bndSegs[i]._edge )
-          endType.insert( make_pair( bndSegs[i]._edge->vertex1(),
-                                     SMESH_MAT2d::BE_BRANCH_POINT ));
-      }
-      bndSegs[i].setBranch( branchID, bndSegs ); // set to i-th and to the opposite bndSeg
-      if ( bndSegs[i].hasOppositeEdge( noEdgeID ))
-        branchEdges[ bndSegs[i].branchID() ].push_back( bndSegs[i]._edge );
-    }
-    // define BranchEndType of the first TVDVertex
-    if ( bndSegs.front()._branchID == -bndSegs.back()._branchID )
-    {
-      if ( bndSegs[0]._edge )
-      {
-        SMESH_MAT2d::BranchEndType type =
-          ( bndSegs[0]._inSeg->isConnected( bndSegs[0]._edge ) ?
-            SMESH_MAT2d::BE_ON_VERTEX :
-            SMESH_MAT2d::BE_END );
-        endType.insert( make_pair( bndSegs[0]._edge->vertex1(), type ));
-      }
-      else if ( bndSegs.back()._edge )
-      {
-        SMESH_MAT2d::BranchEndType type =
-          ( bndSegs.back()._inSeg->isConnected( bndSegs.back()._edge ) ?
-            SMESH_MAT2d::BE_ON_VERTEX :
-            SMESH_MAT2d::BE_END );
-        endType.insert( make_pair( bndSegs.back()._edge->vertex0(), type ));
+        else if ( bndSegs[i]._prev->_branchID )
+        {
+          branchID = bndSegs[i]._prev->_branchID;  // with sign
+        }
+        else if ( bndSegs[i]._edge ) // 1st bndSeg of a WIRE
+        {
+          branchEdges.resize(( branchID = branchEdges.size()) + 1 );
+          if ( bndSegs[i]._inSeg->isConnected( bndSegs[i]._edge ))
+          {
+            if ( bndSegs[i]._inSeg->point0() == bndSegs[i]._edge->vertex1() )
+              endType.insert( make_pair( bndSegs[i]._edge->vertex1(), SMESH_MAT2d::BE_ON_VERTEX ));
+            else
+              endType.insert( make_pair( bndSegs[i]._edge->vertex0(), SMESH_MAT2d::BE_ON_VERTEX ));
+          }
+        }
+
+        bndSegs[i].setBranch( branchID, bndSegsPerEdge ); // set to i-th and to the opposite bndSeg
+        if ( bndSegs[i].hasOppositeEdge() )
+          branchEdges[ bndSegs[i].branchID() ].push_back( bndSegs[i]._edge );
       }
     }
+
     // join the 1st and the last branch edges if it is the same branch
-    if ( bndSegs.back().branchID() != bndSegs.front().branchID() &&
-         bndSegs.back().isSameBranch( bndSegs.front() ))
-    {
-      vector<const TVDEdge*> & br1 = branchEdges[ bndSegs.front().branchID() ];
-      vector<const TVDEdge*> & br2 = branchEdges[ bndSegs.back().branchID()  ];
-      br1.insert( br1.begin(), br2.begin(), br2.end() );
-      br2.clear();
-    }
+    // if ( bndSegs.back().branchID() != bndSegs.front().branchID() &&
+    //      bndSegs.back().isSameBranch( bndSegs.front() ))
+    // {
+    //   vector<const TVDEdge*> & br1 = branchEdges[ bndSegs.front().branchID() ];
+    //   vector<const TVDEdge*> & br2 = branchEdges[ bndSegs.back().branchID()  ];
+    //   br1.insert( br1.begin(), br2.begin(), br2.end() );
+    //   br2.clear();
+    // }
 
     // remove branches ending at BE_ON_VERTEX
 
@@ -1010,34 +1104,38 @@ namespace
         if ( !v0 && !v1 )
           continue;
 
-        size_t iBrToJoin = 0;
-        for ( size_t iB2 = 1; iB2 < branchEdges.size(); ++iB2 )
+        for ( int isV0 = 0; isV0 < 2; ++isV0 )
         {
-          if ( branchEdges[iB2].empty() || isBranchRemoved[iB2] || iB == iB2 )
-            continue;
-          const TVDVertex* v02 = branchEdges[iB2][0]->vertex1();
-          const TVDVertex* v12 = branchEdges[iB2].back()->vertex0();
-          if ( v0 == v02 || v0 == v12 || v1 == v02 || v1 == v12 )
+          const TVDVertex* v = isV0 ? v0 : v1;
+          size_t iBrToJoin = 0;
+          for ( size_t iB2 = 1; iB2 < branchEdges.size(); ++iB2 )
           {
-            if ( iBrToJoin > 0 )
+            if ( branchEdges[iB2].empty() || isBranchRemoved[iB2] || iB == iB2 )
+              continue;
+            const TVDVertex* v02 = branchEdges[iB2][0]->vertex1();
+            const TVDVertex* v12 = branchEdges[iB2].back()->vertex0();
+            if ( v == v02 || v == v12 )
             {
-              iBrToJoin = 0;
-              break; // more than 2 not removed branches meat at a TVDVertex
+              if ( iBrToJoin > 0 )
+              {
+                iBrToJoin = 0;
+                break; // more than 2 not removed branches meat at a TVDVertex
+              }
+              iBrToJoin = iB2;
             }
-            iBrToJoin = iB2;
           }
-        }
-        if ( iBrToJoin > 0 )
-        {
-          vector<const TVDEdge*>& branch = branchEdges[ iBrToJoin ];
-          const TVDVertex* v02 = branch[0]->vertex1();
-          const TVDVertex* v12 = branch.back()->vertex0();
-          updateJoinedBranch( branch, iB, bndSegs, /*reverse=*/(v0 == v02 || v1 == v12 ));
-          if ( v0 == v02 || v0 == v12 )
-            branchEdges[iB].insert( branchEdges[iB].begin(), branch.begin(), branch.end() );
-          else
-            branchEdges[iB].insert( branchEdges[iB].end(),   branch.begin(), branch.end() );
-          branch.clear();
+          if ( iBrToJoin > 0 )
+          {
+            vector<const TVDEdge*>& branch = branchEdges[ iBrToJoin ];
+            const TVDVertex* v02 = branch[0]->vertex1();
+            const TVDVertex* v12 = branch.back()->vertex0();
+            updateJoinedBranch( branch, iB, bndSegsPerEdge, /*reverse=*/(v0 == v02 || v1 == v12 ));
+            if ( v0 == v02 || v0 == v12 )
+              branchEdges[iB].insert( branchEdges[iB].begin(), branch.begin(), branch.end() );
+            else
+              branchEdges[iB].insert( branchEdges[iB].end(),   branch.begin(), branch.end() );
+            branch.clear();
+          }
         }
       } // loop on branchEdges
     } // if ( ignoreCorners )
@@ -1064,36 +1162,31 @@ namespace
 
     // Fill in BndPoints of each EDGE of the boundary
 
-    size_t iSeg = 0;
+    //size_t iSeg = 0;
     int edgeInd = -1, dInd = 0;
-    while ( iSeg < bndSegs.size() )
+    for ( size_t iE = 0; iE < bndSegsPerEdge.size(); ++iE )
     {
-      const size_t                geomID = bndSegs[ iSeg ].geomEdge();
-      SMESH_MAT2d::BndPoints & bndPoints = boundary.getPoints( geomID );
-
-      size_t nbSegs = 0;
-      for ( size_t i = iSeg; i < bndSegs.size() && geomID == bndSegs[ i ].geomEdge(); ++i )
-        ++nbSegs;
-      size_t iSegEnd = iSeg + nbSegs;
+      vector< BndSeg >&          bndSegs = bndSegsPerEdge[ iE ];
+      SMESH_MAT2d::BndPoints & bndPoints = boundary.getPoints( iE );
 
       // make TVDEdge know an index of bndSegs within BndPoints
-      for ( size_t i = iSeg; i < iSegEnd; ++i )
+      for ( size_t i = 0; i < bndSegs.size(); ++i )
         if ( bndSegs[i]._edge )
-          SMESH_MAT2d::Branch::setBndSegment( i - iSeg, bndSegs[i]._edge );
+          SMESH_MAT2d::Branch::setBndSegment( i, bndSegs[i]._edge );
 
       // parameters on EDGE
 
-      bndPoints._params.reserve( nbSegs + 1 );
-      bndPoints._params.push_back( bndSegs[ iSeg ]._inSeg->_p0->_param );
+      bndPoints._params.reserve( bndSegs.size() + 1 );
+      bndPoints._params.push_back( bndSegs[ 0 ]._inSeg->_p0->_param );
 
-      for ( size_t i = iSeg; i < iSegEnd; ++i )
+      for ( size_t i = 0; i < bndSegs.size(); ++i )
         bndPoints._params.push_back( bndSegs[ i ]._uLast );
 
       // MA edges
 
-      bndPoints._maEdges.reserve( nbSegs );
+      bndPoints._maEdges.reserve( bndSegs.size() );
 
-      for ( size_t i = iSeg; i < iSegEnd; ++i )
+      for ( size_t i = 0; i < bndSegs.size(); ++i )
       {
         const size_t              brID = bndSegs[ i ].branchID();
         const SMESH_MAT2d::Branch*  br = branchByID[ brID ];
@@ -1136,9 +1229,6 @@ namespace
         bndPoints._maEdges.push_back( make_pair( br, ( 1 + edgeInd ) * dInd ));
 
       } // loop on bndSegs of an EDGE
-
-      iSeg = iSegEnd;
-
     } // loop on all bndSegs to construct Boundary
 
     // Initialize branches
@@ -1291,6 +1381,15 @@ bool SMESH_MAT2d::Boundary::getBranchPoint( const std::size_t iEdge,
     while ( points._params[i+1] < u ) ++i;
   }
 
+  if ( points._params[i] == points._params[i+1] ) // coincident points at some end
+  {
+    int di = ( points._params[0] == points._params[i] ) ? +1 : -1;
+    while ( points._params[i] == points._params[i+1] )
+      i += di;
+    if ( i < 0 || i+1 >= points._params.size() )
+      i = 0;
+  }
+
   double edgeParam = ( u - points._params[i] ) / ( points._params[i+1] - points._params[i] );
 
   if ( !points._maEdges[ i ].second ) // no branch at the EDGE end, look for a closest branch
@@ -1318,6 +1417,21 @@ bool SMESH_MAT2d::Boundary::getBranchPoint( const std::size_t iEdge,
   return true;
 }
 
+//================================================================================
+/*!
+ * \brief Returns a BranchPoint corresponding to a given BoundaryPoint on a geom EDGE
+ *  \param [in] bp - the BoundaryPoint
+ *  \param [out] p - the found BranchPoint
+ *  \return bool - is OK
+ */
+//================================================================================
+
+bool SMESH_MAT2d::Boundary::getBranchPoint( const BoundaryPoint& bp,
+                                            BranchPoint&         p ) const
+{
+  return getBranchPoint( bp._edgeIndex, bp._param, p );
+}
+
 //================================================================================
 /*!
  * \brief Check if a given boundary segment is a null-length segment on a concave
@@ -1352,7 +1466,7 @@ bool SMESH_MAT2d::Boundary::moveToClosestEdgeEnd( BoundaryPoint& bp ) const
     return false;
 
   const BndPoints& points = _pointsPerEdge[ bp._edgeIndex ];
-  if ( bp._param - points._params[0] < points._params.back() - bp._param )
+  if ( Abs( bp._param - points._params[0]) < Abs( points._params.back() - bp._param ))
     bp._param = points._params[0];
   else 
     bp._param = points._params.back();
@@ -1658,7 +1772,7 @@ bool SMESH_MAT2d::Branch::addDivPntForConcaVertex( std::vector< std::size_t >&
                                                    std::vector< BranchPoint >&   divPoints,
                                                    const vector<const TVDEdge*>& maEdges,
                                                    const vector<const TVDEdge*>& maEdgesTwin,
-                                                   size_t &                    i) const
+                                                   int &                         i) const
 {
   // if there is a concave vertex between EDGEs
   // then position of a dividing BranchPoint is undefined, it is somewhere
@@ -1670,11 +1784,13 @@ bool SMESH_MAT2d::Branch::addDivPntForConcaVertex( std::vector< std::size_t >&
   BranchPoint divisionPnt;
   divisionPnt._branch = this;
 
+  BranchIterator iCur( maEdges, i );
+
   size_t ie1 = getGeomEdge( maEdges    [i] );
   size_t ie2 = getGeomEdge( maEdgesTwin[i] );
 
-  size_t iSeg1  = getBndSegment( maEdges[ i-1 ] );
-  size_t iSeg2  = getBndSegment( maEdges[ i ] );
+  size_t iSeg1  = getBndSegment( iCur.edgePrev() );
+  size_t iSeg2  = getBndSegment( iCur.edge() );
   bool isConcaPrev = _boundary->isConcaveSegment( edgeIDs1.back(), iSeg1 );
   bool isConcaNext = _boundary->isConcaveSegment( ie1,             iSeg2 );
   if ( !isConcaNext && !isConcaPrev )
@@ -1682,46 +1798,48 @@ bool SMESH_MAT2d::Branch::addDivPntForConcaVertex( std::vector< std::size_t >&
 
   bool isConcaveV = false;
 
-  int iPrev = i-1, iNext = i;
+  const TVDEdge* maE;
+  BranchIterator iPrev( maEdges, i ), iNext( maEdges, i );
+   --iPrev;
   if ( isConcaNext ) // all null-length segments follow
   {
     // look for a VERTEX of the opposite EDGE
-    ++iNext; // end of null-length segments
-    while ( iNext < maEdges.size() )
+    // iNext - next after all null-length segments
+    while ( maE = ++iNext )
     {
-      iSeg2 = getBndSegment( maEdges[ iNext ] );
-      if ( _boundary->isConcaveSegment( ie1, iSeg2 ))
-        ++iNext;
-      else
+      iSeg2 = getBndSegment( maE );
+      if ( !_boundary->isConcaveSegment( ie1, iSeg2 ))
         break;
     }
     bool vertexFound = false;
-    for ( size_t iE = i+1; iE < iNext; ++iE )
+    for ( ++iCur; iCur < iNext; ++iCur )
     {
-      ie2 = getGeomEdge( maEdgesTwin[iE] );
+      ie2 = getGeomEdge( maEdgesTwin[ iCur.indexMod() ] );
       if ( ie2 != edgeIDs2.back() )
       {
         // opposite VERTEX found
-        divisionPnt._iEdge = iE;
+        divisionPnt._iEdge = iCur.indexMod();
         divisionPnt._edgeParam = 0;
         divPoints.push_back( divisionPnt );
         edgeIDs1.push_back( ie1 );
         edgeIDs2.push_back( ie2 );
         vertexFound = true;
-        }
+      }
     }
     if ( vertexFound )
     {
-      iPrev = i = --iNext; // not to add a BP in the moddle
+      --iNext;
+      iPrev = iNext; // not to add a BP in the moddle
+      i = iNext.indexMod();
       isConcaveV = true;
     }
   }
   else if ( isConcaPrev )
   {
     // all null-length segments passed, find their beginning
-    while ( iPrev-1 >= 0 )
+    while ( maE = iPrev.edgePrev() )
     {
-      iSeg1 = getBndSegment( maEdges[ iPrev-1 ] );
+      iSeg1 = getBndSegment( maE );
       if ( _boundary->isConcaveSegment( edgeIDs1.back(), iSeg1 ))
         --iPrev;
       else
@@ -1729,17 +1847,18 @@ bool SMESH_MAT2d::Branch::addDivPntForConcaVertex( std::vector< std::size_t >&
     }
   }
 
-  if ( iPrev < i-1 || iNext > i )
+  if ( iPrev.index() < i-1 || iNext.index() > i )
   {
     // no VERTEX on the opposite EDGE, put the Branch Point in the middle
-    double par1 = _params[ iPrev+1 ], par2 = _params[ iNext ];
+    divisionPnt._iEdge = iPrev.indexMod();
+    ++iPrev;
+    double   par1 = _params[ iPrev.indexMod() ], par2 = _params[ iNext.indexMod() ];
     double midPar = 0.5 * ( par1 + par2 );
-    divisionPnt._iEdge = iPrev;
-    while ( _params[ divisionPnt._iEdge + 1 ] < midPar )
-      ++divisionPnt._iEdge;
+    for ( ; _params[ iPrev.indexMod() ] < midPar; ++iPrev )
+      divisionPnt._iEdge = iPrev.indexMod();
     divisionPnt._edgeParam =
-      ( _params[ divisionPnt._iEdge + 1 ] - midPar ) /
-      ( _params[ divisionPnt._iEdge + 1 ] - _params[ divisionPnt._iEdge ] );
+      ( _params[ iPrev.indexMod() ] - midPar ) /
+      ( _params[ iPrev.indexMod() ] - _params[ divisionPnt._iEdge ] );
     divPoints.push_back( divisionPnt );
     isConcaveV = true;
   }
@@ -1767,9 +1886,6 @@ void SMESH_MAT2d::Branch::getOppositeGeomEdges( std::vector< std::size_t >& edge
   edgeIDs2.clear();
   divPoints.clear();
 
-  edgeIDs1.push_back( getGeomEdge( _maEdges[0] ));
-  edgeIDs2.push_back( getGeomEdge( _maEdges[0]->twin() ));
-
   std::vector<const TVDEdge*> twins( _maEdges.size() );
   for ( size_t i = 0; i < _maEdges.size(); ++i )
     twins[i] = _maEdges[i]->twin();
@@ -1795,22 +1911,70 @@ void SMESH_MAT2d::Branch::getOppositeGeomEdges( std::vector< std::size_t >& edge
       if ( edgeIDs1.back() == ie1 && edgeIDs2.back() != ie2 )
       {
         isConcaveV = addDivPntForConcaVertex( edgeIDs2, edgeIDs1, divPoints, twins, _maEdges, i );
+  BranchIterator maIter ( _maEdges, 0 );
+  BranchIterator twIter ( twins, 0 );
+  // size_t lastConcaE1 = _boundary.nbEdges();
+  // size_t lastConcaE2 = _boundary.nbEdges();
+
+  // if ( maIter._closed ) // closed branch
+  // {
+  //   edgeIDs1.push_back( getGeomEdge( _maEdges.back() ));
+  //   edgeIDs2.push_back( getGeomEdge( _maEdges.back()->twin() ));
+  // }
+  // else
+  {
+    edgeIDs1.push_back( getGeomEdge( maIter.edge() ));
+    edgeIDs2.push_back( getGeomEdge( twIter.edge() ));
+  }
+
+  BranchPoint divisionPnt;
+  divisionPnt._branch = this;
+
+  for ( ++maIter, ++twIter; maIter.index() < _maEdges.size(); ++maIter, ++twIter )
+  {
+    size_t ie1 = getGeomEdge( maIter.edge() );
+    size_t ie2 = getGeomEdge( twIter.edge() );
+
+    bool otherE1 = ( edgeIDs1.back() != ie1 );
+    bool otherE2 = ( edgeIDs2.back() != ie2 );
+
+    if ( !otherE1 && !otherE2 && maIter._closed )
+    {
+      int iSegPrev1 = getBndSegment( maIter.edgePrev() );
+      int iSegCur1  = getBndSegment( maIter.edge() );
+      otherE1 = Abs( iSegPrev1 - iSegCur1 ) != 1;
+      int iSegPrev2 = getBndSegment( twIter.edgePrev() );
+      int iSegCur2  = getBndSegment( twIter.edge() );
+      otherE2 = Abs( iSegPrev2 - iSegCur2 ) != 1;
+    }
+
+    if ( otherE1 || otherE2 )
+    {
+      bool isConcaveV = false;
+      if ( otherE1 && !otherE2 )
+      {
+        isConcaveV = addDivPntForConcaVertex( edgeIDs1, edgeIDs2, divPoints,
+                                              _maEdges, twins, maIter._i );
+      }
+      if ( !otherE1 && otherE2 )
+      {
+        isConcaveV = addDivPntForConcaVertex( edgeIDs2, edgeIDs1, divPoints,
+                                              twins, _maEdges, maIter._i );
       }
 
       if ( isConcaveV )
       {
-        ie1 = getGeomEdge( _maEdges[i] );
-        ie2 = getGeomEdge( _maEdges[i]->twin() );
+        ie1 = getGeomEdge( maIter.edge() );
+        ie2 = getGeomEdge( twIter.edge() );
       }
-      if (( !isConcaveV ) ||
-          ( edgeIDs1.back() != ie1 || edgeIDs2.back() != ie2 ))
+      if ( !isConcaveV || otherE1 || otherE2 )
       {
         edgeIDs1.push_back( ie1 );
         edgeIDs2.push_back( ie2 );
       }
       if ( divPoints.size() < edgeIDs1.size() - 1 )
       {
-        divisionPnt._iEdge = i;
+        divisionPnt._iEdge = maIter.index();
         divisionPnt._edgeParam = 0;
         divPoints.push_back( divisionPnt );
       }
index 2ba0066c5efa9566c3a5bc82427de6be63c32df5..618608e07e73f5072d6256b71cd21d9075d60d1f 100644 (file)
@@ -82,7 +82,8 @@ namespace SMESH_MAT2d
     std::size_t   _iEdge; // MA edge index within the branch
     double        _edgeParam; // normalized param within the MA edge
 
-    BranchPoint(): _branch(0), _iEdge(0), _edgeParam(-1) {}
+    BranchPoint( const Branch* b = 0, std::size_t e = 0, double u = -1 ):
+      _branch(b), _iEdge(e), _edgeParam(u) {}
   };
   //-------------------------------------------------------------------------------------
   /*!
@@ -138,7 +139,7 @@ namespace SMESH_MAT2d
                                   std::vector< BranchPoint >&        divPoints,
                                   const std::vector<const TVDEdge*>& maEdges,
                                   const std::vector<const TVDEdge*>& maEdgesTwin,
-                                  size_t &                           i) const;
+                                  int &                              i) const;
 
     // association of _maEdges with boundary segments is stored in this way:
     // index of an EDGE:           TVDEdge->cell()->color()
@@ -180,6 +181,8 @@ namespace SMESH_MAT2d
 
     bool getBranchPoint( const std::size_t iEdge, double u, BranchPoint& p ) const;
 
+    bool getBranchPoint( const BoundaryPoint& bp, BranchPoint& p ) const;
+
     bool isConcaveSegment( std::size_t iEdge, std::size_t iSeg ) const;
 
     bool moveToClosestEdgeEnd( BoundaryPoint& bp ) const;
index 9f08445772bee7ece1218f67375608f320b24564..a5171703b8f692055813d3ef2a70c29d2d364510 100644 (file)
@@ -168,6 +168,18 @@ struct SMESH_NodeSearcherImpl: public SMESH_NodeSearcher
     return closestNode;
   }
 
+  //---------------------------------------------------------------------
+  /*!
+   * \brief Finds nodes located within a tolerance near a point 
+   */
+  int FindNearPoint(const gp_Pnt&                        point,
+                    const double                         tolerance,
+                    std::vector< const SMDS_MeshNode* >& foundNodes)
+  {
+    myOctreeNode->NodesAround( point.Coord(), foundNodes, tolerance );
+    return foundNodes.size();
+  }
+
   //---------------------------------------------------------------------
   /*!
    * \brief Destructor
@@ -427,8 +439,10 @@ struct SMESH_ElementSearcherImpl: public SMESH_ElementSearcher
   bool                         _outerFacesFound;
   set<const SMDS_MeshElement*> _outerFaces; // empty means "no internal faces at all"
 
-  SMESH_ElementSearcherImpl( SMDS_Mesh& mesh, SMDS_ElemIteratorPtr elemIt=SMDS_ElemIteratorPtr())
-    : _mesh(&mesh),_meshPartIt(elemIt),_ebbTree(0),_nodeSearcher(0),_tolerance(-1),_outerFacesFound(false) {}
+  SMESH_ElementSearcherImpl( SMDS_Mesh&           mesh,
+                             double               tol=-1,
+                             SMDS_ElemIteratorPtr elemIt=SMDS_ElemIteratorPtr())
+    : _mesh(&mesh),_meshPartIt(elemIt),_ebbTree(0),_nodeSearcher(0),_tolerance(tol),_outerFacesFound(false) {}
   virtual ~SMESH_ElementSearcherImpl()
   {
     if ( _ebbTree )      delete _ebbTree;      _ebbTree      = 0;
@@ -696,21 +710,21 @@ FindElementsByPoint(const gp_Pnt&                      point,
     if ( !_nodeSearcher )
       _nodeSearcher = new SMESH_NodeSearcherImpl( _mesh );
 
-    const SMDS_MeshNode* closeNode = _nodeSearcher->FindClosestTo( point );
-    if ( !closeNode ) return foundElements.size();
-
-    if ( point.Distance( SMESH_TNodeXYZ( closeNode )) > tolerance )
-      return foundElements.size(); // to far from any node
+    std::vector< const SMDS_MeshNode* > foundNodes;
+    _nodeSearcher->FindNearPoint( point, tolerance, foundNodes );
 
     if ( type == SMDSAbs_Node )
     {
-      foundElements.push_back( closeNode );
+      foundElements.assign( foundNodes.begin(), foundNodes.end() );
     }
     else
     {
-      SMDS_ElemIteratorPtr elemIt = closeNode->GetInverseElementIterator( type );
-      while ( elemIt->more() )
-        foundElements.push_back( elemIt->next() );
+      for ( size_t i = 0; i < foundNodes.size(); ++i )
+      {
+        SMDS_ElemIteratorPtr elemIt = foundNodes[i]->GetInverseElementIterator( type );
+        while ( elemIt->more() )
+          foundElements.push_back( elemIt->next() );
+      }
     }
   }
   // =================================================================================
@@ -1079,32 +1093,22 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
 
   // get ordered nodes
 
-  vector< gp_XYZ > xyz;
-  vector<const SMDS_MeshNode*> nodeList;
+  vector< SMESH_TNodeXYZ > xyz;
 
-  SMDS_ElemIteratorPtr nodeIt = element->nodesIterator();
-  if ( element->IsQuadratic() ) {
-    nodeIt = element->interlacedNodesElemIterator();
-    // if (const SMDS_VtkFace* f=dynamic_cast<const SMDS_VtkFace*>(element))
-    //   nodeIt = f->interlacedNodesElemIterator();
-    // else if (const SMDS_VtkEdge*  e =dynamic_cast<const SMDS_VtkEdge*>(element))
-    //   nodeIt = e->interlacedNodesElemIterator();
-  }
+  SMDS_ElemIteratorPtr nodeIt = element->interlacedNodesElemIterator();
   while ( nodeIt->more() )
   {
     SMESH_TNodeXYZ node = nodeIt->next();
     xyz.push_back( node );
-    nodeList.push_back(node._node);
   }
 
-  int i, nbNodes = (int) nodeList.size(); // central node of biquadratic is missing
+  int i, nbNodes = (int) xyz.size(); // central node of biquadratic is missing
 
   if ( element->GetType() == SMDSAbs_Face ) // --------------------------------------------------
   {
     // compute face normal
     gp_Vec faceNorm(0,0,0);
     xyz.push_back( xyz.front() );
-    nodeList.push_back( nodeList.front() );
     for ( i = 0; i < nbNodes; ++i )
     {
       gp_Vec edge1( xyz[i+1], xyz[i]);
@@ -1117,7 +1121,7 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
       // degenerated face: point is out if it is out of all face edges
       for ( i = 0; i < nbNodes; ++i )
       {
-        SMDS_LinearEdge edge( nodeList[i], nodeList[i+1] );
+        SMDS_LinearEdge edge( xyz[i]._node, xyz[i+1]._node );
         if ( !IsOut( &edge, point, tol ))
           return false;
       }
@@ -1204,13 +1208,22 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
     // (we consider quadratic edge as being composed of two straight parts)
     for ( i = 1; i < nbNodes; ++i )
     {
-      gp_Vec edge( xyz[i-1], xyz[i]);
-      gp_Vec n1p ( xyz[i-1], point);
-      double dist = ( edge ^ n1p ).Magnitude() / edge.Magnitude();
-      if ( dist > tol )
+      gp_Vec edge( xyz[i-1], xyz[i] );
+      gp_Vec n1p ( xyz[i-1], point  );
+      double u = ( edge * n1p ) / edge.SquareMagnitude(); // param [0,1] on the edge
+      if ( u <= 0. ) {
+        if ( n1p.SquareMagnitude() < tol * tol )
+          return false;
         continue;
-      gp_Vec n2p( xyz[i], point );
-      if ( fabs( edge.Magnitude() - n1p.Magnitude() - n2p.Magnitude()) > tol )
+      }
+      if ( u >= 1. ) {
+        if ( point.SquareDistance( xyz[i] ) < tol * tol )
+          return false;
+        continue;
+      }
+      gp_XYZ proj = ( 1. - u ) * xyz[i-1] + u * xyz[i]; // projection of the point on the edge
+      double dist2 = point.SquareDistance( proj );
+      if ( dist2 > tol * tol )
         continue;
       return false; // point is ON this part
     }
@@ -1219,7 +1232,7 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
   // Node or 0D element -------------------------------------------------------------------------
   {
     gp_Vec n2p ( xyz[0], point );
-    return n2p.Magnitude() <= tol;
+    return n2p.SquareMagnitude() <= tol * tol;
   }
   return true;
 }
@@ -1528,10 +1541,8 @@ SMESH_MeshAlgos::FindFaceInSet(const SMDS_MeshNode*    n1,
   const SMDS_MeshElement* face = 0;
 
   SMDS_ElemIteratorPtr invElemIt = n1->GetInverseElementIterator(SMDSAbs_Face);
-  //MESSAGE("n1->GetInverseElementIterator(SMDSAbs_Face) " << invElemIt);
   while ( invElemIt->more() && !face ) // loop on inverse faces of n1
   {
-    //MESSAGE("in while ( invElemIt->more() && !face )");
     const SMDS_MeshElement* elem = invElemIt->next();
     if (avoidSet.count( elem ))
       continue;
@@ -1550,9 +1561,6 @@ SMESH_MeshAlgos::FindFaceInSet(const SMDS_MeshNode*    n1,
     if ( !face && elem->IsQuadratic())
     {
       // analysis for quadratic elements using all nodes
-      // const SMDS_VtkFace* F = dynamic_cast<const SMDS_VtkFace*>(elem);
-      // if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
-      // use special nodes iterator
       SMDS_ElemIteratorPtr anIter = elem->interlacedNodesElemIterator();
       const SMDS_MeshNode* prevN = static_cast<const SMDS_MeshNode*>( anIter->next() );
       for ( i1 = -1, i2 = 0; anIter->more() && !face; i1++, i2++ )
@@ -1587,7 +1595,7 @@ bool SMESH_MeshAlgos::FaceNormal(const SMDS_MeshElement* F, gp_XYZ& normal, bool
     return false;
 
   normal.SetCoord(0,0,0);
-  int nbNodes = F->IsQuadratic() ? F->NbNodes()/2 : F->NbNodes();
+  int nbNodes = F->NbCornerNodes();
   for ( int i = 0; i < nbNodes-2; ++i )
   {
     gp_XYZ p[3];
@@ -1638,9 +1646,10 @@ SMESH_NodeSearcher* SMESH_MeshAlgos::GetNodeSearcher(SMDS_Mesh& mesh)
  */
 //=======================================================================
 
-SMESH_ElementSearcher* SMESH_MeshAlgos::GetElementSearcher(SMDS_Mesh& mesh)
+SMESH_ElementSearcher* SMESH_MeshAlgos::GetElementSearcher(SMDS_Mesh& mesh,
+                                                           double     tolerance)
 {
-  return new SMESH_ElementSearcherImpl( mesh );
+  return new SMESH_ElementSearcherImpl( mesh, tolerance );
 }
 
 //=======================================================================
@@ -1650,7 +1659,8 @@ SMESH_ElementSearcher* SMESH_MeshAlgos::GetElementSearcher(SMDS_Mesh& mesh)
 //=======================================================================
 
 SMESH_ElementSearcher* SMESH_MeshAlgos::GetElementSearcher(SMDS_Mesh&           mesh,
-                                                           SMDS_ElemIteratorPtr elemIt)
+                                                           SMDS_ElemIteratorPtr elemIt,
+                                                           double               tolerance)
 {
-  return new SMESH_ElementSearcherImpl( mesh, elemIt );
+  return new SMESH_ElementSearcherImpl( mesh, tolerance, elemIt );
 }
index 487f8d2016cc9163f0d345966f856f742242a48d..9b860a6ab1150ef5169e25d1b81a6d89d27ba68b 100644 (file)
@@ -55,6 +55,9 @@ struct SMESHUtils_EXPORT SMESH_NodeSearcher
 {
   virtual const SMDS_MeshNode* FindClosestTo( const gp_Pnt& pnt ) = 0;
   virtual void MoveNode( const SMDS_MeshNode* node, const gp_Pnt& toPnt ) = 0;
+  virtual int  FindNearPoint(const gp_Pnt&                        point,
+                             const double                         tolerance,
+                             std::vector< const SMDS_MeshNode* >& foundNodes) = 0;
 };
 
 //=======================================================================
@@ -153,10 +156,45 @@ namespace SMESH_MeshAlgos
    * \brief Return SMESH_ElementSearcher. The caller is responsible for deleting it
    */
   SMESHUtils_EXPORT
-  SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh );
+  SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh,
+                                             double     tolerance=-1.);
   SMESHUtils_EXPORT
   SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh,
-                                             SMDS_ElemIteratorPtr elemIt );
-}
+                                             SMDS_ElemIteratorPtr elemIt,
+                                             double     tolerance=-1. );
+
+
+
+  typedef std::vector<const SMDS_MeshNode*> TFreeBorder;
+  typedef std::vector<TFreeBorder>          TFreeBorderVec;
+  struct TFreeBorderPart
+  {
+    int _border; // border index within a TFreeBorderVec
+    int _node1;  // node index within the border-th TFreeBorder
+    int _node2;
+    int _nodeLast;
+  };
+  typedef std::vector<TFreeBorderPart>  TCoincidentGroup;
+  typedef std::vector<TCoincidentGroup> TCoincidentGroupVec;
+  struct CoincidentFreeBorders
+  {
+    TFreeBorderVec      _borders;          // nodes of all free borders
+    TCoincidentGroupVec _coincidentGroups; // groups of coincident parts of borders
+  };
+
+  /*!
+   * Returns TFreeBorder's coincident within the given tolerance.
+   * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
+   * to free borders being compared is used.
+   *
+   * (Implemented in ./SMESH_FreeBorders.cxx)
+   */
+  SMESHUtils_EXPORT
+  void FindCoincidentFreeBorders(SMDS_Mesh&              mesh,
+                                 double                  tolerance,
+                                 CoincidentFreeBorders & foundFreeBordes);
+  
+
+} // SMESH_MeshAlgos
 
 #endif
index 6225108bd4b952c865e1e74eb98781906e473dfc..e55128eb86c8b9c1165e3df8936c12eaabc86010 100644 (file)
@@ -189,6 +189,7 @@ void SMESH_OctreeNode::NodesAround (const SMDS_MeshNode * Node,
 //================================================================================
 /*!
  * \brief Return in dist2Nodes nodes mapped to their square distance from Node
+ *        Tries to find a closest node.
  *  \param node - node to find nodes closest to
  *  \param dist2Nodes - map of found nodes and their distances
  *  \param precision - radius of a sphere to check nodes inside
@@ -241,6 +242,44 @@ bool SMESH_OctreeNode::NodesAround(const gp_XYZ &node,
   return false;
 }
 
+//================================================================================
+/*!
+ * \brief Return a list of nodes close to a point
+ *  \param [in] point - point
+ *  \param [out] nodes - found nodes
+ *  \param [in] precision - allowed distance from \a point
+ */
+//================================================================================
+
+void SMESH_OctreeNode::NodesAround(const gp_XYZ&                      point,
+                                   std::vector<const SMDS_MeshNode*>& nodes,
+                                   double                             precision)
+{
+  if ( isInside( point, precision ))
+  {
+    if ( isLeaf() && NbNodes() )
+    {
+      double minDist2 = precision * precision;
+      TIDSortedNodeSet::iterator nIt = myNodes.begin();
+      for ( ; nIt != myNodes.end(); ++nIt )
+      {
+        SMESH_TNodeXYZ p2( *nIt );
+        double dist2 = ( point - p2 ).SquareModulus();
+        if ( dist2 <= minDist2 )
+          nodes.push_back( p2._node );
+      }
+    }
+    else if ( myChildren )
+    {
+      for (int i = 0; i < 8; i++)
+      {
+        SMESH_OctreeNode* myChild = dynamic_cast<SMESH_OctreeNode*> (myChildren[i]);
+        myChild->NodesAround( point, nodes, precision);
+      }
+    }
+  }
+}
+
 //=============================
 /*!
  * \brief  Return in theGroupsOfNodes a list of group of nodes close to each other within theTolerance
@@ -275,42 +314,33 @@ void SMESH_OctreeNode::FindCoincidentNodes (TIDSortedNodeSet& theSetOfNodes,
  * \param theGroupsOfNodes - list of nodes closed to each other returned
  */
 //=============================
-void SMESH_OctreeNode::FindCoincidentNodes ( TIDSortedNodeSet* theSetOfNodes,
-                                             const double               theTolerance,
+void SMESH_OctreeNode::FindCoincidentNodes ( TIDSortedNodeSet*                    theSetOfNodes,
+                                             const double                         theTolerance,
                                              list< list< const SMDS_MeshNode*> >* theGroupsOfNodes)
 {
   TIDSortedNodeSet::iterator it1 = theSetOfNodes->begin();
   list<const SMDS_MeshNode*>::iterator it2;
 
+  list<const SMDS_MeshNode*> ListOfCoincidentNodes;
+  TIDCompare idLess;
+
   while (it1 != theSetOfNodes->end())
   {
     const SMDS_MeshNode * n1 = *it1;
 
-    list<const SMDS_MeshNode*> ListOfCoincidentNodes;// Initialize the lists via a declaration, it's enough
-
-    list<const SMDS_MeshNode*> * groupPtr = 0;
-
     // Searching for Nodes around n1 and put them in ListofCoincidentNodes.
     // Found nodes are also erased from theSetOfNodes
     FindCoincidentNodes(n1, theSetOfNodes, &ListOfCoincidentNodes, theTolerance);
 
-    // We build a list {n1 + his neigbours} and add this list in theGroupsOfNodes
-    for (it2 = ListOfCoincidentNodes.begin(); it2 != ListOfCoincidentNodes.end(); it2++)
+    if ( !ListOfCoincidentNodes.empty() )
     {
-      const SMDS_MeshNode* n2 = *it2;
-      if ( !groupPtr )
-      {
-        theGroupsOfNodes->push_back( list<const SMDS_MeshNode*>() );
-        groupPtr = & theGroupsOfNodes->back();
-        groupPtr->push_back( n1 );
-      }
-      if (groupPtr->front() > n2)
-        groupPtr->push_front( n2 );
-      else
-        groupPtr->push_back( n2 );
+      // We build a list {n1 + his neigbours} and add this list in theGroupsOfNodes
+      if ( idLess( n1, ListOfCoincidentNodes.front() )) ListOfCoincidentNodes.push_front( n1 );
+      else                                              ListOfCoincidentNodes.push_back ( n1 );
+      ListOfCoincidentNodes.sort( idLess );
+      theGroupsOfNodes->push_back( list<const SMDS_MeshNode*>() );
+      theGroupsOfNodes->back().splice( theGroupsOfNodes->back().end(), ListOfCoincidentNodes );
     }
-    if (groupPtr != 0)
-      groupPtr->sort();
 
     theSetOfNodes->erase(it1);
     it1 = theSetOfNodes->begin();
index 51242bb27f74cec615b4dfc3b1731a43ea146962..2cd22a3c544d7230435f3c2184a447dc1bbed89e 100644 (file)
 #ifndef _SMESH_OCTREENODE_HXX_
 #define _SMESH_OCTREENODE_HXX_
 
-#include "SMESH_Utils.hxx"
+#include "SMDS_ElemIterator.hxx"
+#include "SMDS_MeshNode.hxx"
 #include "SMESH_Octree.hxx"
+#include "SMESH_Utils.hxx"
+
 #include <gp_Pnt.hxx>
-#include "SMDS_MeshNode.hxx"
 
 #include <list>
 #include <set>
 #include <map>
-
-#include "SMDS_ElemIterator.hxx"
+#include <vector>
 
 //forward declaration
 class SMDS_MeshNode;
@@ -49,34 +50,35 @@ typedef SMDS_Iterator<SMESH_OctreeNode*>              SMESH_OctreeNodeIterator;
 typedef boost::shared_ptr<SMESH_OctreeNodeIterator>   SMESH_OctreeNodeIteratorPtr;
 typedef std::set< const SMDS_MeshNode*, TIDCompare >  TIDSortedNodeSet;
 
-class SMESHUtils_EXPORT SMESH_OctreeNode : public SMESH_Octree {
-
-public:
+class SMESHUtils_EXPORT SMESH_OctreeNode : public SMESH_Octree
+{
+ public:
 
   // Constructor
   SMESH_OctreeNode (const TIDSortedNodeSet& theNodes, const int maxLevel = 8,
                     const int maxNbNodes = 5, const double minBoxSize = 0.);
 
-//=============================
-/*!
- * \brief Empty destructor
- */
-//=============================
+  // destructor
   virtual ~SMESH_OctreeNode () {};
 
   // Tells us if Node is inside the current box with the precision "precision"
   virtual const bool isInside(const gp_XYZ& p, const double precision = 0.);
 
   // Return in Result a list of Nodes potentials to be near Node
-  void               NodesAround(const SMDS_MeshNode *            Node,
-                                 std::list<const SMDS_MeshNode*>* Result,
+  void               NodesAround(const SMDS_MeshNode *            node,
+                                 std::list<const SMDS_MeshNode*>* result,
                                  const double                     precision = 0.);
 
   // Return in dist2Nodes nodes mapped to their square distance from Node
-  bool               NodesAround(const gp_XYZ& node,
+  bool               NodesAround(const gp_XYZ&                           point,
                                  std::map<double, const SMDS_MeshNode*>& dist2Nodes,
                                  double                                  precision);
 
+  // Return a list of Nodes close to a point
+  void               NodesAround(const gp_XYZ&                      point,
+                                 std::vector<const SMDS_MeshNode*>& nodes,
+                                 double                             precision);
+
   // Return in theGroupsOfNodes a list of group of nodes close to each other within theTolerance
   // Search for all the nodes in nodes
   void               FindCoincidentNodes ( TIDSortedNodeSet*           nodes,
index f5c44e79a944fc0a76e0684fb92a1fd82a944543..afef61b906c5ef24c1eb0a4c8e9db1aad8980281 100644 (file)
@@ -137,13 +137,20 @@ struct SMESH_TNodeXYZ : public gp_XYZ
 {
   const SMDS_MeshNode* _node;
   double               _xyz[3];
-  SMESH_TNodeXYZ( const SMDS_MeshElement* e=0):gp_XYZ(0,0,0),_node(0) {
+  SMESH_TNodeXYZ( const SMDS_MeshElement* e=0):gp_XYZ(0,0,0),_node(0)
+  {
+    Set(e);
+  }
+  bool Set( const SMDS_MeshElement* e=0 )
+  {
     if (e) {
       assert( e->GetType() == SMDSAbs_Node );
       _node = static_cast<const SMDS_MeshNode*>(e);
       _node->GetXYZ(_xyz); // - thread safe getting coords
       SetCoord( _xyz[0], _xyz[1], _xyz[2] );
+      return true;
     }
+    return false;
   }
   double Distance(const SMDS_MeshNode* n)       const { return (SMESH_TNodeXYZ( n )-*this).Modulus(); }
   double SquareDistance(const SMDS_MeshNode* n) const { return (SMESH_TNodeXYZ( n )-*this).SquareModulus(); }
index 097dd94b7f57fa21ebf7cfb523030d46964153b2..3ea0f6acdac068268bb55b99972634357c8fae8b 100644 (file)
@@ -692,6 +692,23 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand
   {
     //id_mesh->second->AddProcessedCmd( aCommand );
 
+    // Wrap Export*() into try-except
+    if ( aCommand->MethodStartsFrom("Export"))
+    {
+      _AString    tab = "\t";
+      _AString indent = aCommand->GetIndentation();
+      _AString tryStr = indent + "try:";
+      _AString newCmd = indent + tab + ( aCommand->GetString().ToCString() + indent.Length() );
+      _AString excStr = indent + "except:";
+      _AString msgStr = indent + "\tprint '"; msgStr += method + "() failed. Invalid file name?'";
+
+      myCommands.insert( --myCommands.end(), new _pyCommand( tryStr, myNbCommands ));
+      aCommand->Clear();
+      aCommand->GetString() = newCmd;
+      aCommand->SetOrderNb( ++myNbCommands );
+      myCommands.push_back( new _pyCommand( excStr, ++myNbCommands ));
+      myCommands.push_back( new _pyCommand( msgStr, ++myNbCommands ));
+    }
     // check for mesh editor object
     if ( aCommand->GetMethod() == "GetMeshEditor" ) { // MeshEditor creation
       _pyID editorID = aCommand->GetResultValue();
@@ -1872,7 +1889,7 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand )
     }
   }
   // ----------------------------------------------------------------------
-  else if ( method == "GetSubMesh" ) { // collect submeshes of the mesh
+  else if ( method == "GetSubMesh" ) { // collect sub-meshes of the mesh
     Handle(_pySubMesh) subMesh = theGen->FindSubMesh( theCommand->GetResultValue() );
     if ( !subMesh.IsNull() ) {
       subMesh->SetCreator( this );
@@ -1880,6 +1897,10 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand )
     }
   }
   // ----------------------------------------------------------------------
+  else if ( method == "GetSubMeshes" ) { // clear as the command does nothing (0023156)
+    theCommand->Clear();
+  }
+  // ----------------------------------------------------------------------
   else if ( method == "AddHypothesis" ) { // mesh.AddHypothesis(geom, HYPO )
     myAddHypCmds.push_back( theCommand );
     // set mesh to hypo
@@ -1894,7 +1915,8 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand )
   // ----------------------------------------------------------------------
   else if ( method == "CreateGroup" ||
             method == "CreateGroupFromGEOM" ||
-            method == "CreateGroupFromFilter" )
+            method == "CreateGroupFromFilter" ||
+            method == "CreateDimGroup" )
   {
     Handle(_pyGroup) group = new _pyGroup( theCommand );
     myGroups.push_back( group );
@@ -2413,6 +2435,7 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand)
       "Mirror","MirrorObject","Translate","TranslateObject","Rotate","RotateObject",
       "FindCoincidentNodes","MergeNodes","FindEqualElements",
       "MergeElements","MergeEqualElements","SewFreeBorders","SewConformFreeBorders",
+      "FindCoincidentFreeBorders", "SewCoincidentFreeBorders",
       "SewBorderToSide","SewSideElements","ChangeElemNodes","GetLastCreatedNodes",
       "GetLastCreatedElems",
       "MirrorMakeMesh","MirrorObjectMakeMesh","TranslateMakeMesh","TranslateObjectMakeMesh",
@@ -3562,11 +3585,11 @@ void _pyCommand::SetBegPos( int thePartIndex, int thePosition )
 TCollection_AsciiString _pyCommand::GetIndentation()
 {
   int end = 1;
-  if ( GetBegPos( RESULT_IND ) == UNKNOWN )
-    GetWord( myString, end, true );
-  else
-    end = GetBegPos( RESULT_IND );
-  return myString.SubString( 1, Max( end - 1, 1 ));
+  //while ( end <= Length() && isblank( myString.Value( end )))
+  //ANA: isblank() function isn't provided in VC2010 compiler
+  while ( end <= Length() && ( myString.Value( end ) == ' ' || myString.Value( end ) == '\t') )
+    ++end;
+  return ( end == 1 ) ? _AString("") : myString.SubString( 1, end - 1 );
 }
 
 //================================================================================
@@ -3721,12 +3744,15 @@ const TCollection_AsciiString & _pyCommand::GetMethod()
   if ( GetBegPos( METHOD_IND ) == UNKNOWN )
   {
     // beginning
-    int begPos = GetBegPos( OBJECT_IND ) + myObj.Length();
+    int begPos = GetBegPos( OBJECT_IND );
     bool forward = true;
     if ( begPos < 1 ) {
       begPos = myString.Location( "(", 1, Length() ) - 1;
       forward = false;
     }
+    else {
+      begPos += myObj.Length();
+    }
     // store
     myMeth = GetWord( myString, begPos, forward );
     SetBegPos( METHOD_IND, begPos );
index 20fea4abc1be928ac5d1887e098bc6f982a160a5..a676b7a167ff3fc0fccd19fe5d5e4dc66f3f1582 100644 (file)
@@ -547,6 +547,39 @@ namespace SMESH
     DumpArray( theList, *this );
     return *this;
   }
+  TPythonDump& TPythonDump::operator<<(const SMESH::CoincidentFreeBorders& theCFB)
+  {
+    // dump CoincidentFreeBorders as a list of lists, each enclosed list
+    // contains node IDs of a group of coincident free borders where
+    // each consequent triple of IDs describe a free border: (n1, n2, nLast)
+    // For example [[1, 2, 10, 20, 21, 40], [11, 12, 15, 55, 54, 41]] describes
+    // two groups of coincident free borders, each group including two borders
+
+    myStream << "[";
+    for ( CORBA::ULong i = 0; i < theCFB.coincidentGroups.length(); ++i )
+    {
+      const SMESH::FreeBordersGroup& aGRP = theCFB.coincidentGroups[ i ];
+      if ( i ) myStream << ",";
+      myStream << "[";
+      for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
+      {
+        const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
+        if ( 0 <= aPART.border && aPART.border < theCFB.borders.length() )
+        {
+          if ( iP ) myStream << ", ";
+          const SMESH::FreeBorder& aBRD = theCFB.borders[ aPART.border ];
+          myStream << aBRD.nodeIDs[ aPART.node1    ] << ",";
+          myStream << aBRD.nodeIDs[ aPART.node2    ] << ",";
+          myStream << aBRD.nodeIDs[ aPART.nodeLast ];
+        }
+      }
+      myStream << "]";
+    }
+    myStream << "]";
+
+    return *this;
+  }
+
   const char* TPythonDump::NotPublishedObjectName()
   {
     return theNotPublishedObjectName;
index 46a46b18dfa5a1886bf191925ca594a07dcd2013..7ceeb904fac40eabe1104e54b046fe5bbadb9a00 100644 (file)
@@ -510,7 +510,6 @@ FunctorType Length2D_i::GetFunctorType()
 
 SMESH::Length2D::Values* Length2D_i::GetValues()
 {
-  INFOS("Length2D_i::GetValues");
   SMESH::Controls::Length2D::TValues aValues;
   (dynamic_cast<SMESH::Controls::Length2D*>(myFunctorPtr.get()))->GetValues( aValues );
 
@@ -530,7 +529,6 @@ SMESH::Length2D::Values* Length2D_i::GetValues()
     aValue.myPnt2 = aVal.myPntId[ 1 ];
   }
 
-  INFOS("Length2D_i::GetValuess~");
   return aResult._retn();
 }
 
@@ -581,7 +579,6 @@ FunctorType MultiConnection2D_i::GetFunctorType()
 
 SMESH::MultiConnection2D::Values* MultiConnection2D_i::GetValues()
 {
-  INFOS("MultiConnection2D_i::GetValues");
   SMESH::Controls::MultiConnection2D::MValues aValues;
   (dynamic_cast<SMESH::Controls::MultiConnection2D*>(myFunctorPtr.get()))->GetValues( aValues );
   
@@ -601,7 +598,6 @@ SMESH::MultiConnection2D::Values* MultiConnection2D_i::GetValues()
     aValue.myNbConnects = (*anIter).second;
   }
 
-  INFOS("Multiconnection2D_i::GetValuess~");
   return aResult._retn();
 }
 
@@ -839,8 +835,8 @@ BelongToGeom_i::BelongToGeom_i()
 
 BelongToGeom_i::~BelongToGeom_i()
 {
-  delete myShapeName;
-  delete myShapeID;
+  CORBA::string_free( myShapeName );
+  CORBA::string_free( myShapeID );
 }
 
 void BelongToGeom_i::SetGeom( GEOM::GEOM_Object_ptr theGeom )
@@ -872,18 +868,18 @@ FunctorType BelongToGeom_i::GetFunctorType()
 
 void BelongToGeom_i::SetShapeName( const char* theName )
 {
-  delete myShapeName;
-  myShapeName = strdup( theName );
+  CORBA::string_free( myShapeName );
+  myShapeName = CORBA::string_dup( theName );
   myBelongToGeomPtr->SetGeom( getShapeByName( myShapeName ) );
   TPythonDump()<<this<<".SetShapeName('"<<theName<<"')";
 }
 
 void BelongToGeom_i::SetShape( const char* theID, const char* theName )
 {
-  delete myShapeName;
-  delete myShapeID;
-  myShapeName = strdup( theName );
-  myShapeID   = strdup( theID );
+  CORBA::string_free( myShapeName );
+  CORBA::string_free( myShapeID );
+  myShapeName = CORBA::string_dup( theName );
+  myShapeID   = CORBA::string_dup( theID );
   bool hasName = ( theName && theName[0] );
   bool hasID   = ( theID   && theID[0] );
 
@@ -937,8 +933,8 @@ BelongToSurface_i::BelongToSurface_i( const Handle(Standard_Type)& theSurfaceTyp
 
 BelongToSurface_i::~BelongToSurface_i()
 {
-  delete myShapeName;
-  delete myShapeID;
+  CORBA::string_free( myShapeName );
+  CORBA::string_free( myShapeID );
 }
 
 void BelongToSurface_i::SetSurface( GEOM::GEOM_Object_ptr theGeom, ElementType theType )
@@ -964,18 +960,18 @@ void BelongToSurface_i::SetSurface( GEOM::GEOM_Object_ptr theGeom, ElementType t
 
 void BelongToSurface_i::SetShapeName( const char* theName, ElementType theType )
 {
-  delete myShapeName;
-  myShapeName = strdup( theName );
+  CORBA::string_free( myShapeName );
+  myShapeName = CORBA::string_dup( theName );
   myElementsOnSurfacePtr->SetSurface( getShapeByName( myShapeName ), (SMDSAbs_ElementType)theType );
   TPythonDump()<<this<<".SetShapeName('"<<theName<<"',"<<theType<<")";
 }
 
 void BelongToSurface_i::SetShape( const char* theID,  const char* theName, ElementType theType )
 {
-  delete myShapeName;
-  delete myShapeID;
-  myShapeName = strdup( theName );
-  myShapeID   = strdup( theID );
+  CORBA::string_free( myShapeName );
+  CORBA::string_free( myShapeID );
+  myShapeName = CORBA::string_dup( theName );
+  myShapeID   = CORBA::string_dup( theID );
   bool hasName = ( theName && theName[0] );
   bool hasID   = ( theID   && theID[0] );
 
@@ -1109,8 +1105,8 @@ LyingOnGeom_i::LyingOnGeom_i()
 
 LyingOnGeom_i::~LyingOnGeom_i()
 {
-  delete myShapeName;
-  delete myShapeID;
+  CORBA::string_free( myShapeName );
+  CORBA::string_free( myShapeID );
 }
 
 void LyingOnGeom_i::SetGeom( GEOM::GEOM_Object_ptr theGeom )
@@ -1141,20 +1137,20 @@ FunctorType LyingOnGeom_i::GetFunctorType()
 
 void LyingOnGeom_i::SetShapeName( const char* theName )
 {
-  delete myShapeName;
-  myShapeName = strdup( theName );
+  CORBA::string_free( myShapeName );
+  myShapeName = CORBA::string_dup( theName );
   myLyingOnGeomPtr->SetGeom( getShapeByName( myShapeName ) );
   TPythonDump()<<this<<".SetShapeName('"<<theName<<"')";
 }
 
 void LyingOnGeom_i::SetShape( const char* theID, const char* theName )
 {
-  delete myShapeName;
-  delete myShapeID;
-  myShapeName = strdup( theName );
-  myShapeID   = strdup( theID );
+  CORBA::string_free( myShapeName );
+  CORBA::string_free( myShapeID   );
+  myShapeName = CORBA::string_dup( theName );
+  myShapeID   = CORBA::string_dup( theID   );
   bool hasName = ( theName && theName[0] );
-  bool hasID   = ( theID   && theID[0] );
+  bool hasID   = ( theID   && theID[0]   );
 
   TopoDS_Shape S;
   if ( hasName && hasID )
@@ -1218,7 +1214,6 @@ FreeEdges_i::FreeEdges_i()
 
 SMESH::FreeEdges::Borders* FreeEdges_i::GetBorders()
 {
-  INFOS("FreeEdges_i::GetBorders");
   SMESH::Controls::FreeEdges::TBorders aBorders;
   myFreeEdgesPtr->GetBoreders( aBorders );
 
@@ -1237,8 +1232,6 @@ SMESH::FreeEdges::Borders* FreeEdges_i::GetBorders()
     aBorder.myPnt1 = aBord.myPntId[ 0 ];
     aBorder.myPnt2 = aBord.myPntId[ 1 ];
   }
-
-  INFOS("FreeEdges_i::GetBorders~");
   return aResult._retn();
 }
 
@@ -3672,7 +3665,7 @@ static LDOM_Element createFilterItem( const char*       theName,
 //=======================================================================
 FilterLibrary_i::FilterLibrary_i( const char* theFileName )
 {
-  myFileName = strdup( theFileName );
+  myFileName = CORBA::string_dup( theFileName );
   SMESH::FilterManager_i* aFilterMgr = new SMESH::FilterManager_i();
   myFilterMgr = aFilterMgr->_this();
 
@@ -3713,7 +3706,7 @@ FilterLibrary_i::FilterLibrary_i()
 
 FilterLibrary_i::~FilterLibrary_i()
 {
-  delete myFileName;
+  CORBA::string_free( myFileName );
   //TPythonDump()<<this<<".UnRegister()";
 }
 
@@ -3765,7 +3758,7 @@ Filter_ptr FilterLibrary_i::Copy( const char* theFilterName )
     {
       char a[ 255 ];
       sprintf( a, "%d", val );
-      aCriterion.ThresholdStr = strdup( a );
+      aCriterion.ThresholdStr = CORBA::string_dup( a );
     }
     else
       aCriterion.ThresholdStr = str.GetString();
@@ -3796,8 +3789,8 @@ Filter_ptr FilterLibrary_i::Copy( const char* theFilterName )
 //=======================================================================
 void FilterLibrary_i::SetFileName( const char* theFileName )
 {
-  delete myFileName;
-  myFileName = strdup( theFileName );
+  CORBA::string_free( myFileName );
+  myFileName = CORBA::string_dup( theFileName );
   TPythonDump()<<this<<".SetFileName('"<<theFileName<<"')";
 }
 
index 92b1235b42b20837edeaeb36e50a30fe114510a3..a629f6791deef1fba5f9eadbe3d6885475ab1054 100644 (file)
@@ -1013,8 +1013,8 @@ namespace SMESH
 
     std::vector< SMESH_GroupBase_i* > myBaseGroups;
   };
-  
-  
+
+
   /*
     FILTER LIBRARY
   */
index 824655a8775c4ecb7d7f2d8052a879a2ed8cf4b0..e61aea50b597244139ffddd752a6fafaf66c47d2 100644 (file)
 #include <BRep_Tool.hxx>
 #include <TCollection_AsciiString.hxx>
 #include <OSD.hxx>
+#include <BRepPrimAPI_MakeSphere.hxx>
+#include <BRepPrimAPI_MakeCylinder.hxx>
+#include <BRepPrimAPI_MakeBox.hxx>
+
 
 #ifdef WIN32
  #include <windows.h>
@@ -93,6 +97,7 @@
 #include "SMESH_Mesh_i.hxx"
 #include "SMESH_PreMeshInfo.hxx"
 #include "SMESH_PythonDump.hxx"
+#include "SMESH_ControlsDef.hxx"
 #include "SMESH_TryCatch.hxx" // to include after OCC headers!
 
 #include CORBA_SERVER_HEADER(SMESH_Group)
 #include <OpUtil.hxx>
 #include <SALOMEDS_Tool.hxx>
 #include <SALOME_Container_i.hxx>
-#include <SALOME_DataContainer_i.hxx>
 #include <SALOME_LifeCycleCORBA.hxx>
 #include <SALOME_NamingService.hxx>
 #include <Utils_CorbaException.hxx>
@@ -264,7 +268,6 @@ GEOM::GEOM_Gen_var SMESH_Gen_i::GetGeomEngine() {
 
 SMESH_Gen_i::SMESH_Gen_i()
 {
-  INFOS( "SMESH_Gen_i::SMESH_Gen_i : default constructor" );
 }
 
 //=============================================================================
@@ -296,9 +299,6 @@ SMESH_Gen_i::SMESH_Gen_i( CORBA::ORB_ptr            orb,
   myIsHistoricalPythonDump = true;
   myToForgetMeshDataOnHypModif = false;
 
-  myImportedStudyChanged = true;
-  myImportedStudyId      = 0;
-
   // set it in standalone mode only
   //OSD::SetSignal( true );
 
@@ -338,10 +338,17 @@ SMESH_Gen_i::~SMESH_Gen_i()
   MESSAGE( "SMESH_Gen_i::~SMESH_Gen_i" );
 
   // delete hypothesis creators
-  map<string, GenericHypothesisCreator_i*>::iterator itHyp;
+  map<string, GenericHypothesisCreator_i*>::iterator itHyp, itHyp2;
   for (itHyp = myHypCreatorMap.begin(); itHyp != myHypCreatorMap.end(); itHyp++)
   {
-    delete (*itHyp).second;
+    // same creator can be mapped under different names
+    GenericHypothesisCreator_i* creator = (*itHyp).second;
+    if ( !creator )
+      continue;
+    delete creator;
+    for (itHyp2 = itHyp; itHyp2 != myHypCreatorMap.end(); itHyp2++)
+      if ( creator == (*itHyp2).second )
+        (*itHyp2).second = 0;
   }
   myHypCreatorMap.clear();
 
@@ -933,7 +940,7 @@ void SMESH_Gen_i::SetOption(const char* name, const char* value)
 {
   if ( name && value && strlen( value ) > 0 )
   {
-    string msgToGUI; 
+    string msgToGUI;
     if ( strcmp(name, "historical_python_dump") == 0 )
     {
       myIsHistoricalPythonDump = ( value[0] == '1' || toupper(value[0]) == 'T' ); // 1 || true
@@ -1868,9 +1875,9 @@ CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh,
   try {
     // get mesh servant
     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
-    meshServant->Load();
     ASSERT( meshServant );
     if ( meshServant ) {
+      meshServant->Load();
       // NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation"
       meshServant->CheckGeomModif();
       // get local TopoDS_Shape
@@ -2149,6 +2156,7 @@ SMESH::long_array* SMESH_Gen_i::Evaluate(SMESH::SMESH_Mesh_ptr theMesh,
     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
     ASSERT( meshServant );
     if ( meshServant ) {
+      meshServant->Load();
       // NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation"
       meshServant->CheckGeomModif();
       // get local TopoDS_Shape
@@ -2170,7 +2178,7 @@ SMESH::long_array* SMESH_Gen_i::Evaluate(SMESH::SMESH_Mesh_ptr theMesh,
           {
             SMESH_subMesh* sm = anIt->first;
             SMESH_ComputeErrorPtr& error = sm->GetComputeError();
-            const SMESH_Algo* algo = myGen.GetAlgo( myLocMesh, sm->GetSubShape());
+            const SMESH_Algo* algo = sm->GetAlgo();
             if ( (algo && !error.get()) || error->IsOK() )
               error.reset( new SMESH_ComputeError( COMPERR_ALGO_FAILED,"Failed to evaluate",algo));
           }
@@ -2422,6 +2430,7 @@ SMESH_Gen_i::ConcatenateCommon(const SMESH::ListOfIDSources& theMeshesArray,
   ::SMESH_MeshEditor aNewEditor(&aLocMesh);
   SMESH::ListOfGroups_var aListOfGroups;
 
+  ::SMESH_MeshEditor::ElemFeatures  elemType;
   std::vector<const SMDS_MeshNode*> aNodesArray;
 
   // loop on sub-meshes
@@ -2476,31 +2485,12 @@ SMESH_Gen_i::ConcatenateCommon(const SMESH::ListOfIDSources& theMeshesArray,
       }
 
       // creates a corresponding element on existent nodes in new mesh
-      aNewElem = 0;
-      switch ( anElem->GetEntityType() )
-      {
-      case SMDSEntity_Polyhedra:
-        if ( const SMDS_VtkVolume* aVolume =
-             dynamic_cast<const SMDS_VtkVolume*> (anElem))
-        {
-          aNewElem = aNewMeshDS->AddPolyhedralVolume( aNodesArray,
-                                                      aVolume->GetQuantities() );
-        }
-        break;
-      case SMDSEntity_Ball:
-        if ( const SMDS_BallElement* aBall =
-             dynamic_cast<const SMDS_BallElement*> (anElem))
-        {
-          aNewElem = aNewEditor.AddElement( aNodesArray, SMDSAbs_Ball,
-                                            /*isPoly=*/false, /*id=*/0,
-                                            aBall->GetDiameter() );
-        }
-        break;
-      case SMDSEntity_Node:
-        break;
-      default:
-        aNewElem = aNewEditor.AddElement( aNodesArray, anElem->GetType(), anElem->IsPoly() );
-      }
+      if ( anElem->GetType() == SMDSAbs_Node )
+        aNewElem = 0;
+      else
+        aNewElem =
+          aNewEditor.AddElement( aNodesArray, elemType.Init( anElem, /*basicOnly=*/false ));
+
       if ( aNewElem )
         elemsMap.insert( make_pair( anElem, aNewElem ));
 
@@ -2650,11 +2640,12 @@ SMESH_Gen_i::ConcatenateCommon(const SMESH::ListOfIDSources& theMeshesArray,
     } // if an IDSource is a mesh
   } //meshes loop
 
-  if (theMergeNodesAndElements) {
-    // merge nodes
+  if (theMergeNodesAndElements) // merge nodes
+  {
     TIDSortedNodeSet aMeshNodes; // no input nodes
     SMESH_MeshEditor::TListOfListOfNodes aGroupsOfNodes;
-    aNewEditor.FindCoincidentNodes( aMeshNodes, theMergeTolerance, aGroupsOfNodes );
+    aNewEditor.FindCoincidentNodes( aMeshNodes, theMergeTolerance, aGroupsOfNodes,
+                                    /*SeparateCornersAndMedium=*/ false );
     aNewEditor.MergeNodes( aGroupsOfNodes );
     // merge elements
     aNewEditor.MergeEqualElements();
@@ -2737,6 +2728,7 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart,
   }
   SMESHDS_Mesh* newMeshDS = newMesh_i->GetImpl().GetMeshDS();
   ::SMESH_MeshEditor editor( &newMesh_i->GetImpl() );
+  ::SMESH_MeshEditor::ElemFeatures elemType;
 
   // 3. Get elements to copy
 
@@ -2808,30 +2800,12 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart,
     // add elements
     if ( elem->GetType() != SMDSAbs_Node )
     {
-      int ID = toKeepIDs ? elem->GetID() : 0;
-      const SMDS_MeshElement * newElem;
-      switch ( elem->GetEntityType() ) {
-      case SMDSEntity_Polyhedra:
-        if ( toKeepIDs )
-          newElem = editor.GetMeshDS()->
-            AddPolyhedralVolumeWithID( nodes,
-                                       static_cast<const SMDS_VtkVolume*>(elem)->GetQuantities(),
-                                       ID);
-        else
-          newElem = editor.GetMeshDS()->
-            AddPolyhedralVolume( nodes,
-                                 static_cast<const SMDS_VtkVolume*>(elem)->GetQuantities());
-        break;
-      case SMDSEntity_Ball:
-        newElem = editor.AddElement( nodes, SMDSAbs_Ball, false, ID,
-                                     static_cast<const SMDS_BallElement*>(elem)->GetDiameter());
-        break;
-      default:
-        newElem = editor.AddElement( nodes,elem->GetType(),elem->IsPoly(),ID);
+      elemType.Init( elem, /*basicOnly=*/false );
+      if ( toKeepIDs ) elemType.SetID( elem->GetID() );
 
+      const SMDS_MeshElement * newElem = editor.AddElement( nodes, elemType );
       if ( toCopyGroups && !toKeepIDs )
         e2eMapByType[ elem->GetType() ].insert( make_pair( elem, newElem ));
-      }
     }
   } // while ( srcElemIt->more() )
 
@@ -2991,8 +2965,6 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                                       const char*              theURL,
                                       bool                     isMultiFile )
 {
-  INFOS( "SMESH_Gen_i::Save" );
-
   //  ASSERT( theComponent->GetStudy()->StudyId() == myCurrentStudy->StudyId() )
   // san -- in case <myCurrentStudy> differs from theComponent's study,
   // use that of the component
@@ -3717,7 +3689,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                         myWriter.AddGroup( aGeomGrp );
                       }
                     }
-                    else if ( SMESH_GroupOnFilter_i* aFilterGrp_i = 
+                    else if ( SMESH_GroupOnFilter_i* aFilterGrp_i =
                               dynamic_cast<SMESH_GroupOnFilter_i*>( myGroupImpl ))
                     {
                       std::string str = aFilterGrp_i->FilterToString();
@@ -3934,7 +3906,6 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
   if ( !isMultiFile )
     SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq.in(), true );
 
-  INFOS( "SMESH_Gen_i::Save() completed" );
   return aStreamFile._retn();
 }
 
@@ -4001,8 +3972,6 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
                         const char*              theURL,
                         bool                     isMultiFile )
 {
-  INFOS( "SMESH_Gen_i::Load" );
-
   if ( theComponent->GetStudy()->StudyId() != GetCurrentStudyID() )
     SetCurrentStudy( theComponent->GetStudy() );
 
@@ -4019,11 +3988,6 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
   TCollection_AsciiString tmpDir =
     ( char* )( isMultiFile ? theURL : SALOMEDS_Tool::GetTmpDir().c_str() );
 
-  INFOS( "THE URL++++++++++++++" );
-  INFOS( theURL );
-  INFOS( "THE TMP PATH+++++++++" );
-  INFOS( tmpDir );
-
   // Convert the stream into sequence of files to process
   SALOMEDS::ListOfFileNames_var aFileSeq = SALOMEDS_Tool::PutStreamToFiles( theStream,
                                                                             tmpDir.ToCString(),
@@ -4864,13 +4828,12 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
   if ( !useCaseBuilder->IsUseCaseNode( theComponent ) ) {
     useCaseBuilder->SetRootCurrent();
     useCaseBuilder->Append( theComponent ); // component object is added as the top level item
-    SALOMEDS::ChildIterator_wrap it = study->NewChildIterator( theComponent ); 
+    SALOMEDS::ChildIterator_wrap it = study->NewChildIterator( theComponent );
     for (it->InitEx(true); it->More(); it->Next()) {
       useCaseBuilder->AppendTo( it->Value()->GetFather(), it->Value() );
     }
   }
 
-  INFOS( "SMESH_Gen_i::Load completed" );
   return true;
 }
 
@@ -5019,8 +4982,6 @@ int SMESH_Gen_i::RegisterObject(CORBA::Object_ptr theObject)
 {
   StudyContext* myStudyContext = GetCurrentStudyContext();
   if ( myStudyContext && !CORBA::is_nil( theObject )) {
-    if (GetCurrentStudyID() == myImportedStudyId)
-      myImportedStudyChanged = true;
     CORBA::String_var iorString = GetORB()->object_to_string( theObject );
     return myStudyContext->addObject( string( iorString.in() ) );
   }
@@ -5081,7 +5042,7 @@ char* SMESH_Gen_i::getVersion()
 
 //=================================================================================
 // function : Move()
-// purpose  : Moves objects to the specified position. 
+// purpose  : Moves objects to the specified position.
 //            Is used in the drag-n-drop functionality.
 //=================================================================================
 void SMESH_Gen_i::Move( const SMESH::sobject_list& what,
@@ -5096,7 +5057,7 @@ void SMESH_Gen_i::Move( const SMESH::sobject_list& what,
   SALOMEDS::SComponent_var father = where->GetFatherComponent();
   std::string dataType = father->ComponentDataType();
   if ( dataType != "SMESH" ) return; // not a SMESH component
-  
+
   SALOMEDS::SObject_var objAfter;
   if ( row >= 0 && useCaseBuilder->HasChildren( where ) ) {
     // insert at given row -> find insertion position
@@ -5107,7 +5068,7 @@ void SMESH_Gen_i::Move( const SMESH::sobject_list& what,
       objAfter = useCaseIt->Value();
     }
   }
-  
+
   for ( int i = 0; i < what.length(); i++ ) {
     SALOMEDS::SObject_var sobj = what[i];
     if ( CORBA::is_nil( sobj ) ) continue; // skip bad object
@@ -5160,140 +5121,192 @@ CORBA::Boolean SMESH_Gen_i::IsApplicable ( const char*           theAlgoType,
 }
 
 //=================================================================================
-// function : importData
-// purpose  : imports mesh data file (the med one) into the SMESH internal data structure
+// function : GetInsideSphere
+// purpose  : Collect indices of elements, which are located inside the sphere
 //=================================================================================
-Engines::ListOfIdentifiers* SMESH_Gen_i::importData(CORBA::Long                   studyId,
-                                                    Engines::DataContainer_ptr    data,
-                                                    const Engines::ListOfOptions& options)
-{
-  Engines::ListOfIdentifiers_var aResultIds = new Engines::ListOfIdentifiers;
-  list<string> aResultList;
-
-  CORBA::Object_var aSMObject = myNS->Resolve( "/myStudyManager" );
-  SALOMEDS::StudyManager_var aStudyManager = SALOMEDS::StudyManager::_narrow( aSMObject );
-  SALOMEDS::Study_var aStudy = aStudyManager->GetStudyByID( studyId );
-  SetCurrentStudy(aStudy);
-
-  // load and store temporary imported file
-  string aFileName = Kernel_Utils::GetTmpFileName();
-  aFileName += string(".") + data->extension();
-  Engines::TMPFile* aFileStream = data->get();
-  const char *aBuffer = (const char*)aFileStream->NP_data();
-#ifdef WIN32
-  std::ofstream aFile(aFileName.c_str(), std::ios::binary);
-#else
-  std::ofstream aFile(aFileName.c_str());
-#endif
-  aFile.write(aBuffer, aFileStream->length());
-  aFile.close();
+SMESH::long_array* SMESH_Gen_i::GetInsideSphere( SMESH::SMESH_IDSource_ptr meshPart,
+                                                 SMESH::ElementType     theElemType,
+                                                 CORBA::Double         theX,
+                                                 CORBA::Double         theY,
+                                                 CORBA::Double         theZ,
+                                                 CORBA::Double         theR) {
+  SMESH::long_array_var aResult = new SMESH::long_array();
+  if(meshPart->_is_nil())
+    return aResult._retn();
 
-  // Retrieve mesh names from the file
-  DriverMED_R_SMESHDS_Mesh aReader;
-  aReader.SetFile( aFileName );
-  aReader.SetMeshId(-1);
-  Driver_Mesh::Status aStatus;
-  list<string> aNames = aReader.GetMeshNames(aStatus);
-  SMESH::mesh_array_var aResult = new SMESH::mesh_array();
-  SMESH::DriverMED_ReadStatus aStatus2 = (SMESH::DriverMED_ReadStatus)aStatus;
-  if (aStatus2 == SMESH::DRS_OK) {
-    // Iterate through all meshes and create mesh objects
-    for ( list<string>::iterator it = aNames.begin(); it != aNames.end(); it++ ) {
-      // create mesh
-      SMESH::SMESH_Mesh_var mesh = createMesh();
+  // 1. Create geometrical object
+  gp_Pnt aP( theX, theY, theZ );
+  TopoDS_Shape aShape = BRepPrimAPI_MakeSphere( aP, theR ).Shape();
 
-      // publish mesh in the study
-      SALOMEDS::SObject_var aSO;
-      if (CanPublishInStudy(mesh)) {
-        aSO = PublishMesh(aStudy, mesh.in(), (*it).c_str());
-        aResultList.push_back(aSO->GetID());
-      }
-      // Read mesh data (groups are published automatically by ImportMEDFile())
-      SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
-      ASSERT( meshServant );
-      meshServant->ImportMEDFile( aFileName.c_str(), (*it).c_str() );
-      //meshServant->GetImpl().GetMeshDS()->Modified();
+  std::vector<long> lst =_GetInside(meshPart, theElemType, aShape);
+
+  if( lst.size() > 0 ) {
+    aResult->length( lst.size() );
+    for ( long i = 0; i < lst.size(); i++ ) {
+      aResult[i] = lst[i];
     }
-  } else {
-    MESSAGE("Opening MED file problems "<<aFileName.c_str())
-    return aResultIds._retn();
   }
+  return aResult._retn();
+}
 
-  // remove temporary file 
-#ifdef WIN32
-  DeleteFileA(aFileName.c_str());
-#else
-  unlink(aFileName.c_str());
-#endif
+SMESH::long_array* SMESH_Gen_i::GetInsideBox( SMESH::SMESH_IDSource_ptr meshPart,
+                                              SMESH::ElementType        theElemType,
+                                              CORBA::Double             theX1,
+                                              CORBA::Double             theY1,
+                                              CORBA::Double             theZ1,
+                                              CORBA::Double             theX2,
+                                              CORBA::Double             theY2,
+                                              CORBA::Double             theZ2) {
+  SMESH::long_array_var aResult = new SMESH::long_array();
+  if( meshPart->_is_nil() )
+    return aResult._retn();
 
-  if (!aResultList.empty()) {
-    aResultIds->length(aResultList.size());
-    list<string>::iterator aListIter = aResultList.begin();
-    for(int a = 0; aListIter != aResultList.end(); aListIter++, a++)
-      aResultIds[a] = aListIter->c_str();
-  }
-  
-  myImportedStudyId = studyId;
-  myImportedStudyChanged = false;
+  TopoDS_Shape aShape = BRepPrimAPI_MakeBox( gp_Pnt( theX1, theY1, theZ1 ), gp_Pnt( theX2, theY2, theZ2 ) ).Shape();
+
+  std::vector<long> lst =_GetInside(meshPart, theElemType, aShape);
 
-  return aResultIds._retn();
+  if( lst.size() > 0 ) {
+    aResult->length( lst.size() );
+    for ( long i = 0; i < lst.size(); i++ ) {
+      aResult[i] = lst[i];
+    }
+  }
+  return aResult._retn();
 }
 
-//=================================================================================
-// function : getModifiedData
-// purpose  : exports all geometry of this GEOM module into one BRep file
-//=================================================================================
-Engines::ListOfData* SMESH_Gen_i::getModifiedData(CORBA::Long studyId)
-{
-  Engines::ListOfData_var aResult = new Engines::ListOfData;
-  
-  if (!myImportedStudyChanged) {
-    INFOS("SMESH module data was not changed")
+SMESH::long_array* SMESH_Gen_i::GetInsideCylinder( SMESH::SMESH_IDSource_ptr meshPart,
+                                                   SMESH::ElementType        theElemType,
+                                                   CORBA::Double             theX,
+                                                   CORBA::Double             theY,
+                                                   CORBA::Double             theZ,
+                                                   CORBA::Double             theDX,
+                                                   CORBA::Double             theDY,
+                                                   CORBA::Double             theDZ,
+                                                   CORBA::Double             theH,
+                                                   CORBA::Double             theR ){
+  SMESH::long_array_var aResult = new SMESH::long_array();
+  if( meshPart->_is_nil() )
     return aResult._retn();
+
+  gp_Pnt aP( theX, theY, theZ );
+  gp_Vec aV( theDX, theDY, theDZ );
+  gp_Ax2 anAxes (aP, aV);
+
+  TopoDS_Shape aShape = BRepPrimAPI_MakeCylinder(anAxes, theR, Abs(theH)).Shape();
+
+  std::vector<long> lst =_GetInside(meshPart, theElemType, aShape);
+
+  if( lst.size() > 0 ) {
+    aResult->length( lst.size() );
+    for ( long i = 0; i < lst.size(); i++ ) {
+      aResult[i] = lst[i];
+    }
   }
+  return aResult._retn();
+}
 
-  CORBA::Object_var aSMObject = myNS->Resolve("/myStudyManager");
-  SALOMEDS::StudyManager_var aStudyManager = SALOMEDS::StudyManager::_narrow(aSMObject);
-  SALOMEDS::Study_var aStudy = aStudyManager->GetStudyByID(studyId);
-  SetCurrentStudy(aStudy);
-  SALOMEDS::SComponent_var aComponent = aStudy->FindComponent("SMESH");
-  
-  if (CORBA::is_nil(aComponent))
+SMESH::long_array* SMESH_Gen_i::GetInside( SMESH::SMESH_IDSource_ptr meshPart,
+                                           SMESH::ElementType        theElemType,
+                                           GEOM::GEOM_Object_ptr     theGeom,
+                                           CORBA::Double             theTolerance ) {
+  SMESH::long_array_var aResult = new SMESH::long_array();
+  if( meshPart->_is_nil() || theGeom->_is_nil() )
     return aResult._retn();
 
-  std::string aFullPath(Kernel_Utils::GetTmpFileName());
-  aFullPath += ".med";
-  StudyContext* myStudyContext = GetCurrentStudyContext();
+  TopoDS_Shape aShape = GeomObjectToShape( theGeom );
+
+  std::vector<long> lst =_GetInside(meshPart, theElemType, aShape, &theTolerance);
+
+  if( lst.size() > 0 ) {
+    aResult->length( lst.size() );
+    for ( long i = 0; i < lst.size(); i++ ) {
+      aResult[i] = lst[i];
+    }
+  }
+  return aResult._retn();
+}
+
+
+
+std::vector<long> SMESH_Gen_i::_GetInside( SMESH::SMESH_IDSource_ptr meshPart,
+                                           SMESH::ElementType theElemType,
+                                           TopoDS_Shape& aShape,
+                                           double* theTolerance) {
+
+  std::vector<long> res;
+  SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
+
+  if ( mesh->_is_nil() )
+    return res;
+
+  SMESH_Mesh_i* anImpl = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
+  if ( !anImpl )
+    return res;
+
+  const SMDS_Mesh* meshDS = anImpl->GetImpl().GetMeshDS();
+
+  if ( !meshDS )
+    return res;
+
+  SMDSAbs_ElementType aType = SMDSAbs_ElementType(theElemType);
+  SMESH::Controls::ElementsOnShape* anElementsOnShape = new SMESH::Controls::ElementsOnShape();
+  anElementsOnShape->SetAllNodes( true );
+  anElementsOnShape->SetMesh( meshDS );
+  anElementsOnShape->SetShape( aShape, aType );
 
-  SALOMEDS::ChildIterator_var anIter = aStudy->NewChildIterator(aComponent); // check only published meshes
-  int aNumMeshes = 0; // number of meshes in result
-  for(; anIter->More(); anIter->Next()) {
-    SALOMEDS::SObject_var aSO = anIter->Value();
-    CORBA::Object_var anObj = aSO->GetObject();
-    if (!CORBA::is_nil(anObj)) {
-      SMESH::SMESH_Mesh_var aCORBAMesh = SMESH::SMESH_Mesh::_narrow(anObj);
-      if(!aCORBAMesh->_is_nil()) {
-        SMESH_Mesh_i* myImpl = dynamic_cast<SMESH_Mesh_i*>(GetServant(aCORBAMesh).in());
-        if (myImpl) {
-          myImpl->Load();
-          SMESH_Mesh& aMesh = myImpl->GetImpl();
-          CORBA::String_var objName = aSO->GetName();
-          aMesh.ExportMED(aFullPath.c_str(), objName.in(), false, MED::eV2_2, 0);
-          aNumMeshes++;
+  if(theTolerance)
+    anElementsOnShape->SetTolerance(*theTolerance);
+
+  SMESH::SMESH_Mesh_var msource = SMESH::SMESH_Mesh::_narrow(meshPart);
+  if ( !msource->_is_nil() ) { // Mesh case
+    SMDS_ElemIteratorPtr elemIt = meshDS->elementsIterator( aType );
+    if ( elemIt ) {
+      while ( elemIt->more() ) {
+        const SMDS_MeshElement* anElem = elemIt->next();
+        long anId = anElem->GetID();
+        if ( anElementsOnShape->IsSatisfy( anId ) )
+          res.push_back( anId );
+      }
+    }
+  }
+  SMESH::SMESH_Group_var gsource = SMESH::SMESH_Group::_narrow(meshPart);
+  if ( !gsource->_is_nil() ) {
+    if(theElemType == SMESH::NODE) {
+      SMESH::long_array_var nodes = gsource->GetNodeIDs();
+      for ( int i = 0; i < nodes->length(); ++i ) {
+        if ( const SMDS_MeshNode* node = meshDS->FindNode( nodes[i] ) ) {
+          long anId = node->GetID();
+          if ( anElementsOnShape->IsSatisfy( anId ) )
+            res.push_back( anId );
+        }
+      }
+    } else if (gsource->GetType() == theElemType || theElemType == SMESH::ALL ) {
+      SMESH::long_array_var elems = gsource->GetListOfID();
+      for ( int i = 0; i < elems->length(); ++i ) {
+        if ( const SMDS_MeshElement* elem = meshDS->FindElement( elems[i] ) ) {
+          long anId = elem->GetID();
+          if ( anElementsOnShape->IsSatisfy( anId ) )
+            res.push_back( anId );
         }
       }
     }
   }
-  if (aNumMeshes > 0) { // prepare a container to store files
-    INFOS("Write "<<aNumMeshes<<" meshes to "<<aFullPath.c_str());
-    aResult->length(1);
-    Engines::DataContainer_var aData = (new Engines_DataContainer_i(
-                    aFullPath.c_str(), "", "", true))->_this();
-    aResult[0] = aData;
+  SMESH::SMESH_subMesh_var smsource = SMESH::SMESH_subMesh::_narrow(meshPart);
+  if ( !smsource->_is_nil() ) {
+    SMESH::long_array_var elems = smsource->GetElementsByType( theElemType );
+    for ( int i = 0; i < elems->length(); ++i ) {
+      const SMDS_MeshElement* elem = ( theElemType == SMESH::NODE ) ? meshDS->FindNode( elems[i] ) : meshDS->FindElement( elems[i] );
+      if (elem) {
+        long anId = elem->GetID();
+        if ( anElementsOnShape->IsSatisfy( anId ) )
+          res.push_back( anId );
+      }
+    }
   }
-  return aResult._retn();
+  return res;
 }
 
+
 //=============================================================================
 /*!
  *  SMESHEngine_factory
index 1c33f73e555a237966ef80d4b9987608accfd25d..7f642720517fc7d3a7018437cd9877102002de74 100644 (file)
@@ -491,13 +491,6 @@ public:
 
   void CleanPythonTrace (int theStudyID);
 
-  // SIMAN-related functions (check out/check in) : import data to study
-  virtual Engines::ListOfIdentifiers* importData(CORBA::Long studyId,
-                                                 Engines::DataContainer_ptr data,
-                                                 const Engines::ListOfOptions& options);
-  // SIMAN-related functions (check out/check in) : get modified data
-  virtual Engines::ListOfData* getModifiedData(CORBA::Long studyId);
-
   // *****************************************
   // Internal methods
   // *****************************************
@@ -602,11 +595,44 @@ public:
   void Move( const SMESH::sobject_list& what,
              SALOMEDS::SObject_ptr where,
              CORBA::Long row );
+
   CORBA::Boolean IsApplicable ( const char*           theAlgoType,
                                 const char*           theLibName,
                                 GEOM::GEOM_Object_ptr theShapeObject,
                                 CORBA::Boolean        toCheckAll);
 
+  SMESH::long_array* GetInsideSphere( SMESH::SMESH_IDSource_ptr meshPart,
+                                      SMESH::ElementType        theElemType,
+                                      CORBA::Double             theX,
+                                      CORBA::Double             theY,
+                                      CORBA::Double             theZ,
+                                      CORBA::Double             theR);
+
+  SMESH::long_array* GetInsideBox( SMESH::SMESH_IDSource_ptr meshPart,
+                                   SMESH::ElementType        theElemType,
+                                   CORBA::Double             theX1,
+                                   CORBA::Double             theY1,
+                                   CORBA::Double             theZ1,
+                                   CORBA::Double             theX2,
+                                   CORBA::Double             theY2,
+                                   CORBA::Double             theZ2);
+
+  SMESH::long_array* GetInsideCylinder( SMESH::SMESH_IDSource_ptr meshPart,
+                                        SMESH::ElementType        theElemType,
+                                        CORBA::Double             theX,
+                                        CORBA::Double             theY,
+                                        CORBA::Double             theZ,
+                                        CORBA::Double             theDX,
+                                        CORBA::Double             theDY,
+                                        CORBA::Double             theDZ,
+                                        CORBA::Double             theH,
+                                        CORBA::Double             theR );
+
+  SMESH::long_array* GetInside( SMESH::SMESH_IDSource_ptr meshPart,
+                                SMESH::ElementType        theElemType,
+                                GEOM::GEOM_Object_ptr     theGeom,
+                                CORBA::Double             theTolerance );
+
 private:
   // Get hypothesis creator
   GenericHypothesisCreator_i* getHypothesisCreator( const char*  theHypName,
@@ -630,6 +656,11 @@ private:
   void setCurrentStudy( SALOMEDS::Study_ptr theStudy,
                         bool                theStudyIsBeingClosed=false);
 
+  std::vector<long> _GetInside(SMESH::SMESH_IDSource_ptr meshPart,
+                               SMESH::ElementType     theElemType,
+                               TopoDS_Shape& aShape,
+                               double* theTolerance = NULL);
+
 private:
   static GEOM::GEOM_Gen_var      myGeomGen;
   static CORBA::ORB_var          myOrb;         // ORB reference
@@ -657,8 +688,6 @@ private:
   std::vector< int >                                       myLastParamIndex;
   std::vector< std::string >                               myLastParameters;
   std::string                                              myLastObj;
-  int                                                      myImportedStudyId;      // SIMAN: identifier of the imported in importData study to keep no-modifiection flag for getModifiedData method
-  int                                                      myImportedStudyChanged; // SIMAN: flag that indicates that the imported study has been changed (by creation of the additional mesh)
 };
 
 
index 6fd7ec30d531003909204e6ad87ac2d2caf9eee9..76c2f35d64af727c971b07e3eb76a08226fced5d 100644 (file)
@@ -265,14 +265,17 @@ static SALOMEDS::SObject_ptr publish(SALOMEDS::Study_ptr   theStudy,
   SALOMEDS::StudyBuilder_var     aStudyBuilder = theStudy->NewBuilder();
   SALOMEDS::UseCaseBuilder_wrap useCaseBuilder = theStudy->GetUseCaseBuilder();
   SALOMEDS::SObject_wrap objAfter;
+  bool isNewSO = false;
   if ( SO->_is_nil() )
   {
     if ( theTag == 0 ) {
       SO = aStudyBuilder->NewObject( theFatherObject );
+      isNewSO = true;
     }
     else if ( !theFatherObject->FindSubObject( theTag, SO.inout() ))
     {
       SO = aStudyBuilder->NewObjectToTag( theFatherObject, theTag );
+      isNewSO = true;
 
       // define the next tag after given one in the data tree to insert SObject
       SALOMEDS::SObject_wrap curObj;
@@ -314,18 +317,19 @@ static SALOMEDS::SObject_ptr publish(SALOMEDS::Study_ptr   theStudy,
 
   // add object to the use case tree
   // (to support tree representation customization and drag-n-drop)
-  if ( !CORBA::is_nil( objAfter ) ) {
-    useCaseBuilder->InsertBefore( SO, objAfter );    // insert at given tag
-  } else if ( !useCaseBuilder->IsUseCaseNode( SO ) ) {
-    useCaseBuilder->AppendTo( theFatherObject, SO ); // append to the end of list
+  if ( isNewSO )
+  {
+    if ( !CORBA::is_nil( objAfter ) )
+      useCaseBuilder->InsertBefore( SO, objAfter );    // insert at given tag
+    else if ( !useCaseBuilder->IsUseCaseNode( SO ) )
+      useCaseBuilder->AppendTo( theFatherObject, SO ); // append to the end of list
   }
-
   return SO._retn();
 }
 
 //=======================================================================
 //function : setName
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 void SMESH_Gen_i::SetName(SALOMEDS::SObject_ptr theSObject,
@@ -421,7 +425,14 @@ static void addReference (SALOMEDS::Study_ptr   theStudy,
 
     // add reference to the use case tree
     // (to support tree representation customization and drag-n-drop)
-    SALOMEDS::UseCaseBuilder_wrap useCaseBuilder = theStudy->GetUseCaseBuilder();
+    SALOMEDS::UseCaseBuilder_wrap  useCaseBuilder = theStudy->GetUseCaseBuilder();
+    SALOMEDS::UseCaseIterator_wrap    useCaseIter = useCaseBuilder->GetUseCaseIterator(theSObject);
+    for ( ; useCaseIter->More(); useCaseIter->Next() )
+    {
+      SALOMEDS::SObject_wrap curSO = useCaseIter->Value();
+      if ( curSO->Tag() == theTag )
+        return;
+    }
     useCaseBuilder->AppendTo( theSObject, aReferenceSO );
   }
 }
@@ -760,9 +771,14 @@ SALOMEDS::SObject_ptr SMESH_Gen_i::PublishGroup (SALOMEDS::Study_ptr    theStudy
       }
       else if ( SMESH::DownCast< SMESH_Group_i* > ( theGroup ))
       {
-        SMESH::array_of_ElementType_var allElemTypes = theMesh->GetTypes();
-        for ( size_t i =0; i < allElemTypes->length() && isEmpty; ++i )
-          isEmpty = ( allElemTypes[i] != theGroup->GetType() );
+        if ( theGroup->GetType() == SMESH::NODE )
+          isEmpty = ( theMesh->NbNodes() == 0 );
+        else
+        {
+          SMESH::array_of_ElementType_var allElemTypes = theMesh->GetTypes();
+          for ( size_t i =0; i < allElemTypes->length() && isEmpty; ++i )
+            isEmpty = ( allElemTypes[i] != theGroup->GetType() );
+        }
       }
       aGroupSO = publish (theStudy, theGroup, aRootSO, 0, pm[isEmpty].c_str() );
     }
@@ -940,7 +956,7 @@ bool SMESH_Gen_i::RemoveHypothesisFromShape(SALOMEDS::Study_ptr         theStudy
 
   CORBA::String_var hypEntry = aHypSO->GetID();
 
-  // Find a mesh or submesh refering to theShape
+  // Find a mesh or sub-mesh referring to theShape
   SALOMEDS::SObject_wrap aMeshOrSubMesh =
     GetMeshOrSubmeshByShape( theStudy, theMesh, theShape );
   if ( aMeshOrSubMesh->_is_nil() )
index 6218de9f8ba5485d3cd07b398da23c30a280d9bd..d51714ae79a7d94929cba87714c2436f2470fd34 100644 (file)
@@ -947,7 +947,8 @@ std::string SMESH_GroupOnFilter_i::FilterToString() const
     {
       SMESH::Filter::Criterion& crit = criteria[ i ];
 
-      if ( SMESH::FunctorType( crit.Type ) == SMESH::FT_BelongToMeshGroup )
+      if ( SMESH::FunctorType( crit.Type ) == SMESH::FT_BelongToMeshGroup &&
+           crit.ThresholdID.in() && crit.ThresholdID.in()[0] )
       {
         CORBA::Object_var obj = SMESH_Gen_i::GetORB()->string_to_object( crit.ThresholdID );
         if ( SMESH_GroupBase_i * g = SMESH::DownCast< SMESH_GroupBase_i*>( obj ))
index e469b70393137718ceb3c7f453aa631e2ceb7b2b..0b927273c4ada665a02e6ea1013ad3285fcf220a 100644 (file)
@@ -154,20 +154,11 @@ namespace MeshEditor_I {
       }
 
       // creates a corresponding element on copied nodes
-      SMDS_MeshElement* anElemCopy = 0;
-      if ( anElem->IsPoly() && anElem->GetType() == SMDSAbs_Volume )
-      {
-        const SMDS_VtkVolume* ph =
-          dynamic_cast<const SMDS_VtkVolume*> (anElem);
-        if ( ph )
-          anElemCopy = _myMeshDS->AddPolyhedralVolumeWithID
-            (anElemNodesID, ph->GetQuantities(),anElem->GetID());
-      }
-      else {
-        anElemCopy = ::SMESH_MeshEditor(this).AddElement( anElemNodesID,
-                                                          anElem->GetType(),
-                                                          anElem->IsPoly() );
-      }
+      ::SMESH_MeshEditor::ElemFeatures elemType;
+      elemType.Init( anElem, /*basicOnly=*/false );
+      elemType.SetID( anElem->GetID() );
+      SMDS_MeshElement* anElemCopy =
+        ::SMESH_MeshEditor(this).AddElement( anElemNodesID, elemType );
       return anElemCopy;
     }
     //!< Copy a node
@@ -535,7 +526,7 @@ TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewEle
 
 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
   throw (SALOME::SALOME_Exception)
-{ 
+{
   SMESH_TRY;
   const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
 
@@ -557,7 +548,7 @@ SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
     myPreviewData = new SMESH::MeshPreviewStruct();
     myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
 
-    
+
     SMDSAbs_ElementType previewType = SMDSAbs_All;
     if ( !hasBadElems )
       if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) {
@@ -577,7 +568,10 @@ SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
 
     while ( itMeshElems->more() ) {
       const SMDS_MeshElement* aMeshElem = itMeshElems->next();
-      SMDS_NodeIteratorPtr itElemNodes = aMeshElem->nodeIterator();
+      SMDS_NodeIteratorPtr itElemNodes = 
+        (( aMeshElem->GetEntityType() == SMDSEntity_Quad_Polygon ) ?
+         aMeshElem->interlacedNodesIterator() :
+         aMeshElem->nodeIterator() );
       while ( itElemNodes->more() ) {
         const SMDS_MeshNode* aMeshNode = itElemNodes->next();
         int aNodeID = aMeshNode->GetID();
@@ -1059,6 +1053,7 @@ CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
  *  AddPolygonalFace
  */
 //=============================================================================
+
 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
   throw (SALOME::SALOME_Exception)
 {
@@ -1068,7 +1063,8 @@ CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsO
   int NbNodes = IDsOfNodes.length();
   std::vector<const SMDS_MeshNode*> nodes (NbNodes);
   for (int i = 0; i < NbNodes; i++)
-    nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
+    if ( ! ( nodes[i] = getMeshDS()->FindNode( IDsOfNodes[i] )))
+      return 0;
 
   const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
 
@@ -1082,6 +1078,35 @@ CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsO
   return 0;
 }
 
+//=============================================================================
+/*!
+ *  AddQuadPolygonalFace
+ */
+//=============================================================================
+
+CORBA::Long SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::long_array & IDsOfNodes)
+  throw (SALOME::SALOME_Exception)
+{
+  SMESH_TRY;
+  initData();
+
+  int NbNodes = IDsOfNodes.length();
+  std::vector<const SMDS_MeshNode*> nodes (NbNodes);
+  for (int i = 0; i < NbNodes; i++)
+    nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
+
+  const SMDS_MeshElement* elem = getMeshDS()->AddQuadPolygonalFace(nodes);
+
+  // Update Python script
+  TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
+
+  declareMeshModified( /*isReComputeSafe=*/false );
+  return elem ? elem->GetID() : 0;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
+}
+
 //=============================================================================
 /*!
  * Create volume, either linear and quadratic (this is determed
@@ -2062,7 +2087,7 @@ void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
  */
 //================================================================================
 
-void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms (SMESH::SMESH_IDSource_ptr  elems,
+void SMESH_MeshEditor_i::SplitHexahedraIntoPrismsSMESH::SMESH_IDSource_ptr  elems,
                                                    const SMESH::PointStruct & startHexPoint,
                                                    const SMESH::DirStruct&    facetToSplitNormal,
                                                    CORBA::Short               methodFlags,
@@ -2114,6 +2139,44 @@ void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms (SMESH::SMESH_IDSource_ptr  el
   SMESH_CATCH( SMESH::throwCorbaException );
 }
 
+//================================================================================
+/*!
+ * \brief Split bi-quadratic elements into linear ones without creation of additional nodes:
+ *   - bi-quadratic triangle will be split into 3 linear quadrangles;
+ *   - bi-quadratic quadrangle will be split into 4 linear quadrangles;
+ *   - tri-quadratic hexahedron will be split into 8 linear hexahedra.
+ *   Quadratic elements of lower dimension  adjacent to the split bi-quadratic element
+ *   will be split in order to keep the mesh conformal.
+ *  \param elems - elements to split
+ */
+//================================================================================
+
+void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems)
+  throw (SALOME::SALOME_Exception)
+{
+  SMESH_TRY;
+  initData();
+
+  TIDSortedElemSet elemSet;
+  for ( size_t i = 0; i < theElems.length(); ++i )
+  {
+    SMESH::SMESH_IDSource_ptr elems = theElems[i].in();
+    SMESH::SMESH_Mesh_var      mesh = elems->GetMesh();
+    if ( mesh->GetId() != myMesh_i->GetId() )
+      THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM);
+
+    idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All );
+  }
+  getEditor().SplitBiQuadraticIntoLinear( elemSet );
+
+  declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
+
+  TPythonDump() << this << ".SplitBiQuadraticIntoLinear( "
+                << theElems << " )";
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+}
+
 //=======================================================================
 //function : Smooth
 //purpose  :
@@ -2781,7 +2844,7 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the
     if ( !aMeshImp ) return aGroups._retn();
     TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
     aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
-    if ( !aSubMesh || !aSubMesh->GetSubMeshDS() )
+    if ( !aSubMesh /*|| !aSubMesh->GetSubMeshDS()*/ )
       return aGroups._retn();
   }
 
@@ -3928,25 +3991,24 @@ SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr  theObject,
 
 
 //=======================================================================
-//function : FindCoincidentNodes
+//function : findCoincidentNodes
 //purpose  :
 //=======================================================================
 
-void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double                  Tolerance,
-                                              SMESH::array_of_long_array_out GroupsOfNodes)
-  throw (SALOME::SALOME_Exception)
+void SMESH_MeshEditor_i::
+findCoincidentNodes (TIDSortedNodeSet &             Nodes,
+                     CORBA::Double                  Tolerance,
+                     SMESH::array_of_long_array_out GroupsOfNodes,
+                     CORBA::Boolean                 SeparateCornersAndMedium)
 {
-  SMESH_TRY;
-  initData();
-
   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
-  TIDSortedNodeSet nodes; // no input nodes
-  getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
+  getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
 
   GroupsOfNodes = new SMESH::array_of_long_array;
   GroupsOfNodes->length( aListOfListOfNodes.size() );
   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
-  for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
+  for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
+  {
     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
@@ -3954,8 +4016,28 @@ void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double                  Tol
     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
       aGroup[ j ] = (*lIt)->GetID();
   }
+}
+
+//=======================================================================
+//function : FindCoincidentNodes
+//purpose  :
+//=======================================================================
+
+void SMESH_MeshEditor_i::
+FindCoincidentNodes (CORBA::Double                  Tolerance,
+                     SMESH::array_of_long_array_out GroupsOfNodes,
+                     CORBA::Boolean                 SeparateCornersAndMedium)
+  throw (SALOME::SALOME_Exception)
+{
+  SMESH_TRY;
+  initData();
+
+  TIDSortedNodeSet nodes; // no input nodes
+  findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
+
   TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
-                << Tolerance << " )";
+                << Tolerance << ", "
+                << SeparateCornersAndMedium << " )";
 
   SMESH_CATCH( SMESH::throwCorbaException );
 }
@@ -3965,9 +4047,11 @@ void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double                  Tol
 //purpose  :
 //=======================================================================
 
-void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr      theObject,
-                                                   CORBA::Double                  Tolerance,
-                                                   SMESH::array_of_long_array_out GroupsOfNodes)
+void SMESH_MeshEditor_i::
+FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr      theObject,
+                          CORBA::Double                  Tolerance,
+                          SMESH::array_of_long_array_out GroupsOfNodes,
+                          CORBA::Boolean                 SeparateCornersAndMedium)
   throw (SALOME::SALOME_Exception)
 {
   SMESH_TRY;
@@ -3976,25 +4060,12 @@ void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr
   TIDSortedNodeSet nodes;
   idSourceToNodeSet( theObject, getMeshDS(), nodes );
 
-  ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
-  if(!nodes.empty())
-    getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
+  findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
 
-  GroupsOfNodes = new SMESH::array_of_long_array;
-  GroupsOfNodes->length( aListOfListOfNodes.size() );
-  ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
-  for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
-  {
-    list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
-    list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
-    SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
-    aGroup.length( aListOfNodes.size() );
-    for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
-      aGroup[ j ] = (*lIt)->GetID();
-  }
   TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
-                <<theObject<<", "
-                << Tolerance << " )";
+                << theObject <<", "
+                << Tolerance << ", "
+                << SeparateCornersAndMedium << " )";
 
   SMESH_CATCH( SMESH::throwCorbaException );
 }
@@ -4010,7 +4081,8 @@ void SMESH_MeshEditor_i::
 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr      theObject,
                              CORBA::Double                  theTolerance,
                              SMESH::array_of_long_array_out theGroupsOfNodes,
-                             const SMESH::ListOfIDSources&  theExceptSubMeshOrGroups)
+                             const SMESH::ListOfIDSources&  theExceptSubMeshOrGroups,
+                             CORBA::Boolean                 theSeparateCornersAndMedium)
   throw (SALOME::SALOME_Exception)
 {
   SMESH_TRY;
@@ -4021,32 +4093,18 @@ FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr      theObject,
 
   for ( int i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
   {
-    TIDSortedNodeSet exceptNodes;
-    idSourceToNodeSet( theExceptSubMeshOrGroups[i], getMeshDS(), exceptNodes );
-    TIDSortedNodeSet::iterator avoidNode = exceptNodes.begin();
-    for ( ; avoidNode != exceptNodes.end(); ++avoidNode)
-      nodes.erase( *avoidNode );
+    SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
+                                                         SMESH::NODE );
+    while ( nodeIt->more() )
+      nodes.erase( cast2Node( nodeIt->next() ));
   }
-  ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
-  if(!nodes.empty())
-    getEditor().FindCoincidentNodes( nodes, theTolerance, aListOfListOfNodes );
+  findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
 
-  theGroupsOfNodes = new SMESH::array_of_long_array;
-  theGroupsOfNodes->length( aListOfListOfNodes.size() );
-  ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
-  for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
-  {
-    list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
-    list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
-    SMESH::long_array& aGroup = (*theGroupsOfNodes)[ i ];
-    aGroup.length( aListOfNodes.size() );
-    for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
-      aGroup[ j ] = (*lIt)->GetID();
-  }
   TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
                 << theObject<<", "
                 << theTolerance << ", "
-                << theExceptSubMeshOrGroups << " )";
+                << theExceptSubMeshOrGroups << ", "
+                << theSeparateCornersAndMedium << " )";
 
   SMESH_CATCH( SMESH::throwCorbaException );
 }
@@ -4056,7 +4114,8 @@ FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr      theObject,
 //purpose  :
 //=======================================================================
 
-void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
+void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
+                                     const SMESH::ListOfIDSources&     NodesToKeep)
   throw (SALOME::SALOME_Exception)
 {
   SMESH_TRY;
@@ -4066,6 +4125,16 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN
 
   TPythonDump aTPythonDump;
   aTPythonDump << this << ".MergeNodes([";
+
+  TIDSortedNodeSet setOfNodesToKeep;
+  for ( int i = 0; i < NodesToKeep.length(); ++i )
+  {
+    prepareIdSource( NodesToKeep[i] );
+    SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE );
+    while ( nodeIt->more() )
+      setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
+  }
+
   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
   for (int i = 0; i < GroupsOfNodes.length(); i++)
   {
@@ -4075,9 +4144,13 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN
     for ( int j = 0; j < aNodeGroup.length(); j++ )
     {
       CORBA::Long index = aNodeGroup[ j ];
-      const SMDS_MeshNode * node = aMesh->FindNode(index);
-      if ( node )
-        aListOfNodes.push_back( node );
+      if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
+      {
+        if ( setOfNodesToKeep.count( node ))
+          aListOfNodes.push_front( node );
+        else
+          aListOfNodes.push_back( node );
+      }
     }
     if ( aListOfNodes.size() < 2 )
       aListOfListOfNodes.pop_back();
@@ -4085,9 +4158,10 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN
     if ( i > 0 ) aTPythonDump << ", ";
     aTPythonDump << aNodeGroup;
   }
+
   getEditor().MergeNodes( aListOfListOfNodes );
 
-  aTPythonDump <<  "])";
+  aTPythonDump << "], " << NodesToKeep << ")";
 
   declareMeshModified( /*isReComputeSafe=*/false );
 
@@ -4498,6 +4572,225 @@ static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Se
   return SMESH::SMESH_MeshEditor::SEW_OK;
 }
 
+//=======================================================================
+/*!
+ * Returns groups of FreeBorder's coincident within the given tolerance.
+ * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
+ * to free borders being compared is used.
+ */
+//=======================================================================
+
+SMESH::CoincidentFreeBorders*
+SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
+{
+  SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
+
+  SMESH_TRY;
+
+  SMESH_MeshAlgos::CoincidentFreeBorders cfb;
+  SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
+
+  // copy free borders
+  aCFB->borders.length( cfb._borders.size() );
+  for ( size_t i = 0; i < cfb._borders.size(); ++i )
+  {
+    SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
+    SMESH::FreeBorder&             aBRD = aCFB->borders[i];
+    aBRD.nodeIDs.length( nodes.size() );
+    for ( size_t iN = 0; iN < nodes.size(); ++iN )
+      aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
+  }
+
+  // copy coincident parts
+  aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
+  for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
+  {
+    SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
+    SMESH::FreeBordersGroup&          aGRP = aCFB->coincidentGroups[i];
+    aGRP.length( grp.size() );
+    for ( size_t iP = 0; iP < grp.size(); ++iP )
+    {
+      SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
+      SMESH::FreeBorderPart&           aPART = aGRP[ iP ];
+      aPART.border   = part._border;
+      aPART.node1    = part._node1;
+      aPART.node2    = part._node2;
+      aPART.nodeLast = part._nodeLast;
+    }
+  }
+  SMESH_CATCH( SMESH::doNothing );
+
+  TPythonDump() << "CoincidentFreeBorders = "
+                << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
+
+  return aCFB._retn();
+}
+
+//=======================================================================
+/*!
+ * Sew FreeBorder's of each group
+ */
+//=======================================================================
+
+CORBA::Short SMESH_MeshEditor_i::
+SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
+                         CORBA::Boolean                      createPolygons,
+                         CORBA::Boolean                      createPolyhedra)
+  throw (SALOME::SALOME_Exception)
+{
+  CORBA::Short nbSewed = 0;
+
+  SMESH_MeshAlgos::TFreeBorderVec groups;
+  SMESH_MeshAlgos::TFreeBorder    borderNodes; // triples of nodes for every FreeBorderPart
+
+  // check the input and collect nodes
+  for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
+  {
+    borderNodes.clear();
+    const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
+    for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
+    {
+      const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
+      if ( aPART.border < 0 || aPART.border >= freeBorders.borders.length() )
+        THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
+
+      const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
+
+      if ( aPART.node1 < 0 || aPART.node1 > aBRD.nodeIDs.length() )
+        THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
+      if ( aPART.node2 < 0 || aPART.node2 > aBRD.nodeIDs.length() )
+        THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
+      if ( aPART.nodeLast < 0 || aPART.nodeLast > aBRD.nodeIDs.length() )
+        THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
+
+      // do not keep these nodes for further sewing as nodes can be removed by the sewing
+      const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1    ]);
+      const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2    ]);
+      const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
+      if ( !n1)
+        THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
+      if ( !n2 )
+        THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
+      if ( !n3 )
+        THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
+
+      borderNodes.push_back( n1 );
+      borderNodes.push_back( n2 );
+      borderNodes.push_back( n3 );
+    }
+    groups.push_back( borderNodes );
+  }
+
+  // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
+  // to get nodes that replace other nodes during merge we create 0D elements
+  // on each node and MergeNodes() will replace underlying nodes of 0D elements by
+  // new ones.
+
+  vector< const SMDS_MeshElement* > tmp0Delems;
+  for ( size_t i = 0; i < groups.size(); ++i )
+  {
+    SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
+    for ( size_t iN = 0; iN < nodes.size(); ++iN )
+    {
+      SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
+      if ( it0D->more() )
+        tmp0Delems.push_back( it0D->next() );
+      else
+        tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
+    }
+  }
+
+  // cout << endl << "INIT" << endl;
+  // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
+  // {
+  //   cout << i << " ";
+  //   if ( i % 3 == 0 ) cout << "^ ";
+  //   tmp0Delems[i]->GetNode(0)->Print( cout );
+  // }
+
+  SMESH_TRY;
+
+  ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
+  int i0D = 0;
+  for ( size_t i = 0; i < groups.size(); ++i )
+  {
+    bool isBordToBord = true;
+    bool   groupSewed = false;
+    SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
+    for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
+    {
+      const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
+      const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
+      const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
+
+      const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
+      const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
+      const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
+
+      if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
+        continue;
+
+      // TIDSortedElemSet emptySet, avoidSet;
+      // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
+      // {
+      //   cout << "WRONG 2nd 1" << endl;
+      //   n0->Print( cout );
+      //   n1->Print( cout );
+      // }
+      // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
+      // {
+      //   cout << "WRONG 2nd 2" << endl;
+      //   n3->Print( cout );
+      //   n4->Print( cout );
+      // }
+
+      if ( !isBordToBord )
+      {
+        n1 = n2; // at border-to-side sewing only last side node (n1) is needed
+        n2 = 0;  //  and n2 is not used
+      }
+      // 1st border moves to 2nd
+      res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
+                                       n0 ,n1 ,n2 ,// 2nd
+                                       /*2ndIsFreeBorder=*/ isBordToBord,
+                                       createPolygons, createPolyhedra);
+      groupSewed = ( res == ok );
+
+      isBordToBord = false;
+      // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
+      // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
+      // {
+      //   cout << t << " ";
+      //   if ( t % 3 == 0 ) cout << "^ ";
+      //   tmp0Delems[t]->GetNode(0)->Print( cout );
+      // }
+    }
+    i0D += nodes.size();
+    nbSewed += groupSewed;
+  }
+
+  TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
+                << freeBorders     << ", "
+                << createPolygons  << ", "
+                << createPolyhedra << " )";
+
+  SMESH_CATCH( SMESH::doNothing );
+
+  declareMeshModified( /*isReComputeSafe=*/false );
+
+  // remove tmp 0D elements
+  SMESH_TRY;
+  set< const SMDS_MeshElement* > removed0D;
+  for ( size_t i = 0; i < tmp0Delems.size(); ++i )
+  {
+    if ( removed0D.insert( tmp0Delems[i] ).second )
+      getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
+  }
+  SMESH_CATCH( SMESH::throwCorbaException );
+
+  return nbSewed;
+}
+
 //=======================================================================
 //function : SewFreeBorders
 //purpose  :
@@ -4547,14 +4840,14 @@ SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
 
   SMESH::SMESH_MeshEditor::Sew_Error error =
     convError( getEditor().SewFreeBorder (aBorderFirstNode,
-                                       aBorderSecondNode,
-                                       aBorderLastNode,
-                                       aSide2FirstNode,
-                                       aSide2SecondNode,
-                                       aSide2ThirdNode,
-                                       true,
-                                       CreatePolygons,
-                                       CreatePolyedrs) );
+                                          aBorderSecondNode,
+                                          aBorderLastNode,
+                                          aSide2FirstNode,
+                                          aSide2SecondNode,
+                                          aSide2ThirdNode,
+                                          true,
+                                          CreatePolygons,
+                                          CreatePolyedrs) );
 
 
   declareMeshModified( /*isReComputeSafe=*/false );
@@ -4607,13 +4900,13 @@ SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
 
   SMESH::SMESH_MeshEditor::Sew_Error error =
     convError( getEditor().SewFreeBorder (aBorderFirstNode,
-                                       aBorderSecondNode,
-                                       aBorderLastNode,
-                                       aSide2FirstNode,
-                                       aSide2SecondNode,
-                                       aSide2ThirdNode,
-                                       true,
-                                       false, false) );
+                                          aBorderSecondNode,
+                                          aBorderLastNode,
+                                          aSide2FirstNode,
+                                          aSide2SecondNode,
+                                          aSide2ThirdNode,
+                                          true,
+                                          false, false) );
 
   declareMeshModified( /*isReComputeSafe=*/false );
   return error;
@@ -4669,14 +4962,14 @@ SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
 
   SMESH::SMESH_MeshEditor::Sew_Error error =
     convError( getEditor().SewFreeBorder (aBorderFirstNode,
-                                       aBorderSecondNode,
-                                       aBorderLastNode,
-                                       aSide2FirstNode,
-                                       aSide2SecondNode,
-                                       aSide2ThirdNode,
-                                       false,
-                                       CreatePolygons,
-                                       CreatePolyedrs) );
+                                          aBorderSecondNode,
+                                          aBorderLastNode,
+                                          aSide2FirstNode,
+                                          aSide2SecondNode,
+                                          aSide2ThirdNode,
+                                          false,
+                                          CreatePolygons,
+                                          CreatePolyedrs) );
 
   declareMeshModified( /*isReComputeSafe=*/false );
   return error;
@@ -6368,9 +6661,9 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
     THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
 
   // separate groups belonging to this and other mesh
-  SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
+  SMESH::ListOfIDSources_var groupsOfThisMesh  = new SMESH::ListOfIDSources;
   SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
-  groupsOfThisMesh->length( groups.length() );
+  groupsOfThisMesh ->length( groups.length() );
   groupsOfOtherMesh->length( groups.length() );
   int nbGroups = 0, nbGroupsOfOtherMesh = 0;
   for ( int i = 0; i < groups.length(); ++i )
index ec9ae9861f1a0766608eb4d3e9d18de23355b4f1..3c36508b84597492b031d77762214bdbf76464a6 100644 (file)
@@ -117,6 +117,8 @@ public:
     throw (SALOME::SALOME_Exception);
   CORBA::Long AddPolygonalFace(const SMESH::long_array & IDsOfNodes)
     throw (SALOME::SALOME_Exception);
+  CORBA::Long AddQuadPolygonalFace(const SMESH::long_array & IDsOfNodes)
+    throw (SALOME::SALOME_Exception);
   CORBA::Long AddVolume(const SMESH::long_array & IDsOfNodes)
     throw (SALOME::SALOME_Exception);
   CORBA::Long AddPolyhedralVolume(const SMESH::long_array & IDsOfNodes,
@@ -219,7 +221,7 @@ public:
                              CORBA::Boolean                 outsideNormal)
     throw (SALOME::SALOME_Exception);
 
-  // Split/Join faces
+  // Split/Join
   CORBA::Boolean TriToQuad       (const SMESH::long_array &   IDsOfElements,
                                   SMESH::NumericalFunctor_ptr Criterion,
                                   CORBA::Double               MaxAngle)
@@ -254,6 +256,8 @@ public:
                                           CORBA::Short               methodFlags,
                                           CORBA::Boolean             allDomains)
     throw (SALOME::SALOME_Exception);
+  void           SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& elems)
+    throw (SALOME::SALOME_Exception);
 
   CORBA::Boolean Smooth(const SMESH::long_array &              IDsOfElements,
                         const SMESH::long_array &              IDsOfFixedNodes,
@@ -470,18 +474,22 @@ public:
     throw (SALOME::SALOME_Exception);
 
   void FindCoincidentNodes (CORBA::Double                  Tolerance,
-                            SMESH::array_of_long_array_out GroupsOfNodes)
+                            SMESH::array_of_long_array_out GroupsOfNodes,
+                            CORBA::Boolean                 SeparateCornersAndMedium)
     throw (SALOME::SALOME_Exception);
   void FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr      Object,
                                  CORBA::Double                  Tolerance,
-                                 SMESH::array_of_long_array_out GroupsOfNodes)
+                                 SMESH::array_of_long_array_out GroupsOfNodes,
+                                 CORBA::Boolean                 SeparateCornersAndMedium)
     throw (SALOME::SALOME_Exception);
   void FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr      Object,
                                     CORBA::Double                  Tolerance,
                                     SMESH::array_of_long_array_out GroupsOfNodes,
-                                    const SMESH::ListOfIDSources&  ExceptSubMeshOrGroups)
+                                    const SMESH::ListOfIDSources&  ExceptSubMeshOrGroups,
+                                    CORBA::Boolean                 SeparateCornersAndMedium)
     throw (SALOME::SALOME_Exception);
-  void MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
+  void MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
+                   const SMESH::ListOfIDSources&     NodesToKeep )
     throw (SALOME::SALOME_Exception);
   void FindEqualElements(SMESH::SMESH_IDSource_ptr      Object,
                          SMESH::array_of_long_array_out GroupsOfElementsID)
@@ -530,6 +538,12 @@ public:
   CORBA::Short GetPointState(CORBA::Double x, CORBA::Double y, CORBA::Double z)
     throw (SALOME::SALOME_Exception);
 
+  SMESH::CoincidentFreeBorders* FindCoincidentFreeBorders(CORBA::Double tolerance);
+  CORBA::Short SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
+                                        CORBA::Boolean                      createPolygons,
+                                        CORBA::Boolean                      createPolyedrs)
+    throw (SALOME::SALOME_Exception);
+
   SMESH::SMESH_MeshEditor::Sew_Error
   SewFreeBorders(CORBA::Long FirstNodeID1,
                  CORBA::Long SecondNodeID1,
@@ -538,15 +552,13 @@ public:
                  CORBA::Long SecondNodeID2,
                  CORBA::Long LastNodeID2,
                  CORBA::Boolean CreatePolygons,
-                 CORBA::Boolean CreatePolyedrs)
-    throw (SALOME::SALOME_Exception);
+                 CORBA::Boolean CreatePolyedrs) throw (SALOME::SALOME_Exception);
   SMESH::SMESH_MeshEditor::Sew_Error
   SewConformFreeBorders(CORBA::Long FirstNodeID1,
                         CORBA::Long SecondNodeID1,
                         CORBA::Long LastNodeID1,
                         CORBA::Long FirstNodeID2,
-                        CORBA::Long SecondNodeID2)
-    throw (SALOME::SALOME_Exception);
+                        CORBA::Long SecondNodeID2) throw (SALOME::SALOME_Exception);
   SMESH::SMESH_MeshEditor::Sew_Error
   SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
                   CORBA::Long SecondNodeIDOnFreeBorder,
@@ -554,16 +566,14 @@ public:
                   CORBA::Long FirstNodeIDOnSide,
                   CORBA::Long LastNodeIDOnSide,
                   CORBA::Boolean CreatePolygons,
-                  CORBA::Boolean CreatePolyedrs)
-    throw (SALOME::SALOME_Exception);
+                  CORBA::Boolean CreatePolyedrs) throw (SALOME::SALOME_Exception);
   SMESH::SMESH_MeshEditor::Sew_Error
   SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
                   const SMESH::long_array& IDsOfSide2Elements,
                   CORBA::Long NodeID1OfSide1ToMerge,
                   CORBA::Long NodeID1OfSide2ToMerge,
                   CORBA::Long NodeID2OfSide1ToMerge,
-                  CORBA::Long NodeID2OfSide2ToMerge)
-    throw (SALOME::SALOME_Exception);
+                  CORBA::Long NodeID2OfSide2ToMerge) throw (SALOME::SALOME_Exception);
 
   /*!
    * Set new nodes for given element.
@@ -901,6 +911,12 @@ private: //!< private methods
                      const bool                 emptyIfIsMesh = false,
                      IDSource_Error*            error = 0);
 
+  void findCoincidentNodes( TIDSortedNodeSet &             Nodes,
+                            CORBA::Double                  Tolerance,
+                            SMESH::array_of_long_array_out GroupsOfNodes,
+                            CORBA::Boolean                 SeparateCornersAndMedium);
+
+
 
  private: //!< fields
 
index 03420b0e4001a06ed711c1d0a41a34f7a25a9e6f..b521af9ebbe4f3b76a02b569cc6d58c178c1e085 100644 (file)
@@ -3765,7 +3765,7 @@ CORBA::Long SMESH_Mesh_i::NbBiQuadQuadrangles()throw(SALOME::SALOME_Exception)
   return _impl->NbBiQuadQuadrangles();
 }
 
-CORBA::Long SMESH_Mesh_i::NbPolygons()throw(SALOME::SALOME_Exception)
+CORBA::Long SMESH_Mesh_i::NbPolygons() throw(SALOME::SALOME_Exception)
 {
   Unexpect aCatch(SALOME_SalomeException);
   if ( _preMeshInfo )
@@ -3774,6 +3774,15 @@ CORBA::Long SMESH_Mesh_i::NbPolygons()throw(SALOME::SALOME_Exception)
   return _impl->NbPolygons();
 }
 
+CORBA::Long SMESH_Mesh_i::NbPolygonsOfOrder(SMESH::ElementOrder order) throw(SALOME::SALOME_Exception)
+{
+  Unexpect aCatch(SALOME_SalomeException);
+  if ( _preMeshInfo )
+    return _preMeshInfo->NbPolygons((SMDSAbs_ElementOrder) order);
+
+  return _impl->NbPolygons((SMDSAbs_ElementOrder)order);
+}
+
 CORBA::Long SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
   throw(SALOME::SALOME_Exception)
 {
@@ -4851,6 +4860,7 @@ SMESH_Mesh_i::MakeGroupsOfBadInputElements( int         theSubShapeID,
     THROW_SALOME_CORBA_EXCEPTION( "empty group name",SALOME::BAD_PARAM );
 
   SMESH::ListOfGroups_var groups = new SMESH::ListOfGroups;
+  ::SMESH_MeshEditor::ElemFeatures elemType;
 
   // submesh by subshape id
   if ( !_impl->HasShapeToMesh() ) theSubShapeID = 1;
@@ -4883,7 +4893,7 @@ SMESH_Mesh_i::MakeGroupsOfBadInputElements( int         theSubShapeID,
           if ( elem )
           {
             ::SMESH_MeshEditor editor( _impl );
-            elem = editor.AddElement( nodes, elem->GetType(), elem->IsPoly() );
+            elem = editor.AddElement( nodes, elemType.Init( elem ));
           }
         }
         if ( elem )
@@ -5131,6 +5141,8 @@ SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
   if (_impl->NbVolumes())    types[nbTypes++] = SMESH::VOLUME;
   if (_impl->Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
   if (_impl->NbBalls())      types[nbTypes++] = SMESH::BALL;
+  if (_impl->NbNodes() &&
+      nbTypes == 0 )         types[nbTypes++] = SMESH::NODE;
   types->length( nbTypes );
 
   return types._retn();
index 45d01b10ed8a5e9a2ffc6af8e5af6b3575155219..2a67fd8a78815d20cf2a99bc68f6e15fb824267e 100644 (file)
@@ -318,6 +318,9 @@ public:
   CORBA::Long NbPolygons()
     throw (SALOME::SALOME_Exception);
 
+  CORBA::Long NbPolygonsOfOrder(SMESH::ElementOrder order=SMESH::ORDER_ANY)
+    throw (SALOME::SALOME_Exception);
+
   CORBA::Long NbVolumes()
     throw (SALOME::SALOME_Exception);
 
index 675b99f8a677c7110457a360c95bb2b6c521f33d..f7fcbb49308fd8db9482530e24e9856eae853c7c 100644 (file)
@@ -83,28 +83,31 @@ SMESH::SMESH_Pattern_ptr SMESH_Gen_i::GetPattern()
 //=======================================================================
 
 SMESH_Pattern_i::SMESH_Pattern_i( SMESH_Gen_i* theGen_i ):
-       myGen( theGen_i )
+  myGen( theGen_i )
 {
 }
 
 //=======================================================================
 //function : getMesh
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 ::SMESH_Mesh* SMESH_Pattern_i::getMesh( SMESH::SMESH_Mesh_ptr & theMesh )
 {
-  SMESH_Mesh_i* anImplPtr = 
+  SMESH_Mesh_i* anImplPtr =
     dynamic_cast<SMESH_Mesh_i*>( SMESH_Gen_i::GetServant( theMesh ).in() );
   if ( anImplPtr )
+  {
+    anImplPtr->Load();
     return & anImplPtr->GetImpl();
+  }
 
   return 0;
 }
 
 //=======================================================================
 //function : LoadFromFile
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 CORBA::Boolean SMESH_Pattern_i::LoadFromFile(const char* theFileContents)
index 4d4f6b728019f70cc40494a156b32746e0c67f58..696376297855ea7de8a9601a6446609a66f40c13 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <SALOMEconfig.h>
 #include CORBA_SERVER_HEADER(SMESH_Mesh)
+#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
 #include CORBA_SERVER_HEADER(GEOM_Gen)
 #include CORBA_SERVER_HEADER(SALOMEDS)
 
@@ -229,6 +230,9 @@ namespace SMESH
     TPythonDump&
     operator<<(const SMESH::ListOfIDSources& theList);
 
+    TPythonDump&
+    operator<<(const SMESH::CoincidentFreeBorders& theCFB);
+
     static const char* SMESHGenName() { return "smeshgen"; }
     static const char* MeshEditorName() { return "mesh_editor"; }
     static const char* NotPublishedObjectName();
index 2562e85432c549725641794dc93dc275d7b8fce0..02c2664f0807b56dfc86344d499473ab5a34c96d 100644 (file)
@@ -35,8 +35,9 @@
 #include "OpUtil.hxx"
 #include "Utils_ExceptHandlers.hxx"
 
-#include <TopoDS_Iterator.hxx>
 #include <TopExp_Explorer.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopoDS_Iterator.hxx>
 
 using namespace std;
 
@@ -99,50 +100,87 @@ bool getSubMeshes(::SMESH_subMesh*  theSubMesh,
   SMESH_Mesh*      aMesh      = theSubMesh->GetFather();
   SMESHDS_Mesh*    aMeshDS    = aMesh->GetMeshDS();
   SMESHDS_SubMesh* aSubMeshDS = theSubMesh->GetSubMeshDS();
+  ::SMESH_subMesh* sm;
 
   // nodes can be bound to either vertex, edge, face or solid_or_shell
-  TopoDS_Shape aShape = theSubMesh->GetSubShape();
-  switch ( aShape.ShapeType() )
+  TopoDS_Shape         aShape = theSubMesh->GetSubShape();
+  TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
+
+  // IPAL18558: Wrong information of the created sub-mesh is shown. (Sub-mesh on a FACE
+  // with only 1D algo assigned
+  // Find dimension of sub-meshes to return as highest dimension of the assigned algorithm
+  if ( theSubMesh->IsEmpty() && !theSubMesh->GetAlgo() )
   {
-  case TopAbs_SOLID: {
-    // add submesh of solid itself
-    aSubMeshDS = aMeshDS->MeshElements( aShape );
-    if ( aSubMeshDS )
+    // on father sub-meshes, check presence of an algo which will mesh this sub-mesh
+    // even if no algo is assigned to this sub-mesh
+    bool topAlgoPresent = false;
+    TopTools_ListIteratorOfListOfShape ancestors( aMesh->GetAncestors( aShape ));
+    for ( ; ancestors.More() && !topAlgoPresent; ancestors.Next() )
+      if (( sm = aMesh->GetSubMeshContaining( ancestors.Value() )))
+        topAlgoPresent = ( sm->GetAlgo() && !sm->GetAlgo()->NeedDiscreteBoundary() );
+
+    if ( !topAlgoPresent )
+    {
+      // look for a sub-mesh with an algo
+      SMESH_subMeshIteratorPtr smIt =
+        theSubMesh->getDependsOnIterator(/*includeSelf=*/false, /*complexShapeFirst=*/true);
+      TopAbs_ShapeEnum algoShape = TopAbs_SHAPE;
+      while ( smIt->more() && algoShape == TopAbs_SHAPE )
+      {
+        sm = smIt->next();
+        if ( sm->GetAlgo() )
+          algoShape = sm->GetSubShape().ShapeType();
+      }
+      if ( algoShape != TopAbs_SHAPE )
+      {
+        // return all sub-meshes on this shape type
+        smIt = theSubMesh->getDependsOnIterator(/*includeSelf=*/false, /*complexShapeFirst=*/true);
+        while ( smIt->more() )
+        {
+          sm = smIt->next();
+          if ( sm->GetSubShape().ShapeType() == algoShape && sm->GetSubMeshDS() )
+            theSubMeshList.push_back( sm->GetSubMeshDS() );
+        }
+        return size < theSubMeshList.size();
+      }
+    }
+  }
+
+  switch ( aShapeType )
+  {
+  case TopAbs_SOLID:
+  {
+    // add sub-mesh of solid itself
+    if (( aSubMeshDS = aMeshDS->MeshElements( aShape )))
       theSubMeshList.push_back( aSubMeshDS );
+
     // and of the first shell
     TopExp_Explorer exp( aShape, TopAbs_SHELL );
-    if ( exp.More() ) {
-      aSubMeshDS = aMeshDS->MeshElements( exp.Current() );
-      if ( aSubMeshDS )
+    if ( exp.More() )
+      if (( aSubMeshDS = aMeshDS->MeshElements( exp.Current() )))
         theSubMeshList.push_back( aSubMeshDS );
-    }
     break;
   }
   case TopAbs_WIRE:
   case TopAbs_COMPOUND:
-  case TopAbs_COMPSOLID: {
+  case TopAbs_COMPSOLID:
+  {
     // call getSubMeshes() for sub-shapes
     list<TopoDS_Shape> shapeList;
     shapeList.push_back( aShape );
     list<TopoDS_Shape>::iterator sh = shapeList.begin();
     for ( ; sh != shapeList.end(); ++sh ) {
       for ( TopoDS_Iterator it( *sh ); it.More(); it.Next() ) {
-        if ( ::SMESH_subMesh* aSubMesh = aMesh->GetSubMeshContaining( it.Value() ))
-          getSubMeshes( aSubMesh, theSubMeshList ); // add found submesh or explore deeper
+        if (( sm = aMesh->GetSubMeshContaining( it.Value() )))
+          getSubMeshes( sm, theSubMeshList ); // add found sub-mesh or explore deeper
         else
           // no submesh for a compound inside compound
           shapeList.push_back( it.Value() );
       }
     }
-    // return only unique submeshes
-    set<SMESHDS_SubMesh*> smSet;
-    TListOfSubMeshes::iterator sm = theSubMeshList.begin();
-    while ( sm != theSubMeshList.end() ) {
-      if ( !smSet.insert( *sm ).second )
-        sm = theSubMeshList.erase( sm );
-      else
-        ++sm;
-    }
+    // return only unique sub-meshes
+    set<SMESHDS_SubMesh*> smSet( theSubMeshList.begin(), theSubMeshList.end() );
+    theSubMeshList.assign( smSet.begin(), smSet.end() );
     break;
   }
   default:
index 52746336b1f7422ef585b7659c57a2d0eda4f9c1..d93e6ef98b6b368310aa65a4afd2aeefe96ea591 100644 (file)
@@ -89,6 +89,7 @@ SET(_bin_SCRIPTS
   PAL_MESH_043_2D.py
   PAL_MESH_043_3D.py
   SMESH_reg.py
+  smesh_selection.py
 )
 
 SET(smesh_SCRIPTS
index 3a07810ad8c7a488111e740e614a17d72043dc50..98acce5f6d38b3d3943984d5619d1d0ecf475b8b 100644 (file)
@@ -44,6 +44,8 @@ QUADRANGLE  = "Quadrangle_2D"
 RADIAL_QUAD = "RadialQuadrangle_1D2D"
 ## Algorithm type: Quadrangle (Medial Axis Projection) 1D-2D algorithm, see StdMeshersBuilder_QuadMA_1D2D
 QUAD_MA_PROJ = "QuadFromMedialAxis_1D2D"
+## Algorithm type: Polygon Per Face 2D algorithm, see StdMeshersBuilder_PolygonPerFace
+POLYGON     = "PolygonPerFace_2D"
 
 # import items of enums
 for e in StdMeshers.QuadType._items: exec('%s = StdMeshers.%s'%(e,e))
@@ -66,7 +68,7 @@ class StdMeshersBuilder_Segment(Mesh_Algorithm):
     ## type of algorithm used with helper function in smeshBuilder.Mesh class
     #  @internal
     algoType   = REGULAR
-    ## flag pointing either this algorithm should be used by default in dynamic method
+    ## flag pointing whether this algorithm should be used by default in dynamic method
     #  of smeshBuilder.Mesh class
     #  @internal
     isDefault  = True
@@ -424,7 +426,7 @@ class StdMeshersBuilder_CompositeSegment(StdMeshersBuilder_Segment):
     ## type of algorithm used with helper function in smeshBuilder.Mesh class
     #  @internal
     algoType   = COMPOSITE
-    ## flag pointing either this algorithm should be used by default in dynamic method
+    ## flag pointing whether this algorithm should be used by default in dynamic method
     #  of smeshBuilder.Mesh class
     #  @internal
     isDefault  = False
@@ -497,7 +499,7 @@ class StdMeshersBuilder_Triangle_MEFISTO(Mesh_Algorithm):
     ## type of algorithm used with helper function in smeshBuilder.Mesh class
     #  @internal
     algoType   = MEFISTO
-    ## flag pointing either this algorithm should be used by default in dynamic method
+    ## flag pointing whether this algorithm should be used by default in dynamic method
     #  of smeshBuilder.Mesh class
     #  @internal
     isDefault  = True
@@ -551,7 +553,7 @@ class StdMeshersBuilder_Quadrangle(Mesh_Algorithm):
     ## type of algorithm used with helper function in smeshBuilder.Mesh class
     #  @internal
     algoType   = QUADRANGLE
-    ## flag pointing either this algorithm should be used by default in dynamic method
+    ## flag pointing whether this algorithm should be used by default in dynamic method
     #  of smeshBuilder.Mesh class
     #  @internal
     isDefault  = True
@@ -698,7 +700,7 @@ class StdMeshersBuilder_Hexahedron(Mesh_Algorithm):
     ## type of algorithm used with helper function in smeshBuilder.Mesh class
     #  @internal
     algoType   = Hexa
-    ## flag pointing either this algorithm should be used by default in dynamic method
+    ## flag pointing whether this algorithm should be used by default in dynamic method
     #  of smeshBuilder.Mesh class
     #  @internal
     isDefault  = True
@@ -730,7 +732,7 @@ class StdMeshersBuilder_Projection1D(Mesh_Algorithm):
     ## type of algorithm used with helper function in smeshBuilder.Mesh class
     #  @internal
     algoType   = "Projection_1D"
-    ## flag pointing either this algorithm should be used by default in dynamic method
+    ## flag pointing whether this algorithm should be used by default in dynamic method
     #  of smeshBuilder.Mesh class
     #  @internal
     isDefault  = True
@@ -788,7 +790,7 @@ class StdMeshersBuilder_Projection2D(Mesh_Algorithm):
     ## type of algorithm used with helper function in smeshBuilder.Mesh class
     #  @internal
     algoType   = "Projection_2D"
-    ## flag pointing either this algorithm should be used by default in dynamic method
+    ## flag pointing whether this algorithm should be used by default in dynamic method
     #  of smeshBuilder.Mesh class
     #  @internal
     isDefault  = True
@@ -1098,8 +1100,7 @@ class StdMeshersBuilder_Prism3D(Mesh_Algorithm):
 
     pass # end of StdMeshersBuilder_Prism3D class
 
-## Defines a Prism 3D algorithm, which is either "Extrusion 3D" or "Radial Prism"
-#  depending on geometry
+## Defines a Prism 3D algorithm
 # 
 #  It is created by calling smeshBuilder.Mesh.Prism(geom=0)
 #
@@ -1131,30 +1132,12 @@ class StdMeshersBuilder_RadialPrism3D(StdMeshersBuilder_Prism3D):
         self.nbLayers = None
         return
 
-## Defines a Radial Quadrangle 1D-2D algorithm
+## Base class for algorithms supporting radial distribution hypotheses
 # 
-#  It is created by calling smeshBuilder.Mesh.Quadrangle(smeshBuilder.RADIAL_QUAD,geom=0)
-#
-#  @ingroup l2_algos_radialq
-class StdMeshersBuilder_RadialQuadrangle1D2D(Mesh_Algorithm):
+class StdMeshersBuilder_RadialAlgorithm(Mesh_Algorithm):
 
-    ## name of the dynamic method in smeshBuilder.Mesh class
-    #  @internal
-    meshMethod = "Quadrangle"
-    ## type of algorithm used with helper function in smeshBuilder.Mesh class
-    #  @internal
-    algoType   = RADIAL_QUAD
-    ## doc string of the method
-    #  @internal
-    docHelper  = "Creates quadrangle 1D-2D algorithm for faces having a shape of disk or a disk segment"
-
-    ## Private constructor.
-    #  @param mesh parent mesh object algorithm is assigned to
-    #  @param geom geometry (shape/sub-shape) algorithm is assigned to;
-    #              if it is @c 0 (default), the algorithm is assigned to the main shape
-    def __init__(self, mesh, geom=0):
+    def __init__(self):
         Mesh_Algorithm.__init__(self)
-        self.Create(mesh, geom, self.algoType)
 
         self.distribHyp = None #self.Hypothesis("LayerDistribution2D", UseExisting=0)
         self.nbLayers = None
@@ -1257,12 +1240,42 @@ class StdMeshersBuilder_RadialQuadrangle1D2D(Mesh_Algorithm):
 
     pass # end of StdMeshersBuilder_RadialQuadrangle1D2D class
 
+## Defines a Radial Quadrangle 1D-2D algorithm
+# 
+#  It is created by calling smeshBuilder.Mesh.Quadrangle(smeshBuilder.RADIAL_QUAD,geom=0)
+#
+#  @ingroup l2_algos_radialq
+class StdMeshersBuilder_RadialQuadrangle1D2D(StdMeshersBuilder_RadialAlgorithm):
+
+    ## name of the dynamic method in smeshBuilder.Mesh class
+    #  @internal
+    meshMethod = "Quadrangle"
+    ## type of algorithm used with helper function in smeshBuilder.Mesh class
+    #  @internal
+    algoType   = RADIAL_QUAD
+    ## doc string of the method
+    #  @internal
+    docHelper  = "Creates quadrangle 1D-2D algorithm for faces having a shape of disk or a disk segment"
+
+    ## Private constructor.
+    #  @param mesh parent mesh object algorithm is assigned to
+    #  @param geom geometry (shape/sub-shape) algorithm is assigned to;
+    #              if it is @c 0 (default), the algorithm is assigned to the main shape
+    def __init__(self, mesh, geom=0):
+        StdMeshersBuilder_RadialAlgorithm.__init__(self)
+        self.Create(mesh, geom, self.algoType)
+
+        self.distribHyp = None #self.Hypothesis("LayerDistribution2D", UseExisting=0)
+        self.nbLayers = None
+        pass
+
+
 ## Defines a Quadrangle (Medial Axis Projection) 1D-2D algorithm
 # 
 #  It is created by calling smeshBuilder.Mesh.Quadrangle(smeshBuilder.QUAD_MA_PROJ,geom=0)
 #
 #  @ingroup l2_algos_quad_ma
-class StdMeshersBuilder_QuadMA_1D2D(Mesh_Algorithm):
+class StdMeshersBuilder_QuadMA_1D2D(StdMeshersBuilder_RadialAlgorithm):
 
     ## name of the dynamic method in smeshBuilder.Mesh class
     #  @internal
@@ -1279,12 +1292,43 @@ class StdMeshersBuilder_QuadMA_1D2D(Mesh_Algorithm):
     #  @param geom geometry (shape/sub-shape) algorithm is assigned to;
     #              if it is @c 0 (default), the algorithm is assigned to the main shape
     def __init__(self, mesh, geom=0):
-        Mesh_Algorithm.__init__(self)
+        StdMeshersBuilder_RadialAlgorithm.__init__(self)
         self.Create(mesh, geom, self.algoType)
         pass
 
     pass
 
+## Defines a Polygon Per Face 2D algorithm
+# 
+#  It is created by calling smeshBuilder.Mesh.Polygon(geom=0)
+#
+#  @ingroup l2_algos_quad_ma
+class StdMeshersBuilder_PolygonPerFace(Mesh_Algorithm):
+
+    ## name of the dynamic method in smeshBuilder.Mesh class
+    #  @internal
+    meshMethod = "Polygon"
+    ## type of algorithm used with helper function in smeshBuilder.Mesh class
+    #  @internal
+    algoType   = POLYGON
+    ## flag pointing whether this algorithm should be used by default in dynamic method
+    #  of smeshBuilder.Mesh class
+    #  @internal
+    isDefault  = True
+    ## doc string of the method
+    #  @internal
+    docHelper  = "Creates polygon 2D algorithm for faces"
+
+    ## Private constructor.
+    #  @param mesh parent mesh object algorithm is assigned to
+    #  @param geom geometry (shape/sub-shape) algorithm is assigned to;
+    #              if it is @c 0 (default), the algorithm is assigned to the main shape
+    def __init__(self, mesh, geom=0):
+        Mesh_Algorithm.__init__(self)
+        self.Create(mesh, geom, self.algoType)
+        pass
+
+    pass
 
 ## Defines a Use Existing Elements 1D algorithm
 #
@@ -1299,7 +1343,7 @@ class StdMeshersBuilder_UseExistingElements_1D(Mesh_Algorithm):
     ## type of algorithm used with helper function in smeshBuilder.Mesh class
     #  @internal
     algoType   = "Import_1D"
-    ## flag pointing either this algorithm should be used by default in dynamic method
+    ## flag pointing whether this algorithm should be used by default in dynamic method
     #  of smeshBuilder.Mesh class
     #  @internal
     isDefault  = True
@@ -1349,7 +1393,7 @@ class StdMeshersBuilder_UseExistingElements_1D2D(Mesh_Algorithm):
     ## type of algorithm used with helper function in smeshBuilder.Mesh class
     #  @internal
     algoType   = "Import_1D2D"
-    ## flag pointing either this algorithm should be used by default in dynamic method
+    ## flag pointing whether this algorithm should be used by default in dynamic method
     #  of smeshBuilder.Mesh class
     #  @internal
     isDefault  = True
@@ -1397,7 +1441,7 @@ class StdMeshersBuilder_Cartesian_3D(Mesh_Algorithm):
     ## type of algorithm used with helper function in smeshBuilder.Mesh class
     #  @internal
     algoType   = "Cartesian_3D"
-    ## flag pointing either this algorithm should be used by default in dynamic method
+    ## flag pointing whether this algorithm should be used by default in dynamic method
     #  of smeshBuilder.Mesh class
     #  @internal
     isDefault  = True
index 07d46509b3362c896619414bcafe7749e41355a7..22ea69d836f27507b247dc6893f7b63a9adf056b 100644 (file)
@@ -235,7 +235,7 @@ def TreatHypoStatus(status, hypName, geomName, isAlgo, mesh):
     elif status == HYP_BAD_SUBSHAPE :
         reason = "the shape is neither the main one, nor its sub-shape, nor a valid group"
     elif status == HYP_BAD_GEOMETRY:
-        reason = "geometry mismatches the expectation of the algorithm"
+        reason = "the algorithm is not applicable to this geometry"
     elif status == HYP_HIDDEN_ALGO:
         reason = "it is hidden by an algorithm of an upper dimension, which generates elements of all dimensions"
     elif status == HYP_HIDING_ALGO:
@@ -689,15 +689,17 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
 
     ## Creates a criterion by the given parameters
     #  \n Criterion structures allow to define complex filters by combining them with logical operations (AND / OR) (see example below)
-    #  @param elementType the type of elements(NODE, EDGE, FACE, VOLUME)
-    #  @param CritType the type of criterion (FT_Taper, FT_Area, FT_RangeOfIds, FT_LyingOnGeom etc.)
-    #  @param Compare  belongs to {FT_LessThan, FT_MoreThan, FT_EqualTo}
+    #  @param elementType the type of elements(SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
+    #  @param CritType the type of criterion (SMESH.FT_Taper, SMESH.FT_Area, etc.)
+    #          Type SMESH.FunctorType._items in the Python Console to see all values.
+    #          Note that the items starting from FT_LessThan are not suitable for CritType.
+    #  @param Compare  belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
     #  @param Threshold the threshold value (range of ids as string, shape, numeric)
-    #  @param UnaryOp  FT_LogicalNOT or FT_Undefined
-    #  @param BinaryOp a binary logical operation FT_LogicalAND, FT_LogicalOR or
-    #                  FT_Undefined (must be for the last criterion of all criteria)
-    #  @param Tolerance the tolerance used by FT_BelongToGeom, FT_BelongToSurface,
-    #         FT_LyingOnGeom, FT_CoplanarFaces criteria
+    #  @param UnaryOp  SMESH.FT_LogicalNOT or SMESH.FT_Undefined
+    #  @param BinaryOp a binary logical operation SMESH.FT_LogicalAND, SMESH.FT_LogicalOR or
+    #                  SMESH.FT_Undefined
+    #  @param Tolerance the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
+    #         SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces criteria
     #  @return SMESH.Filter.Criterion
     #
     #  <a href="../tui_filters_page.html#combining_filters">Example of Criteria usage</a>
@@ -874,13 +876,15 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         return aCriterion
 
     ## Creates a filter with the given parameters
-    #  @param elementType the type of elements in the group
-    #  @param CritType the type of criterion ( FT_Taper, FT_Area, FT_RangeOfIds, FT_LyingOnGeom etc. )
-    #  @param Compare  belongs to {FT_LessThan, FT_MoreThan, FT_EqualTo}
-    #  @param Threshold the threshold value (range of id ids as string, shape, numeric)
-    #  @param UnaryOp  FT_LogicalNOT or FT_Undefined
-    #  @param Tolerance the tolerance used by FT_BelongToGeom, FT_BelongToSurface,
-    #         FT_LyingOnGeom, FT_CoplanarFaces and FT_EqualNodes criteria
+    #  @param elementType the type of elements (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
+    #  @param CritType the type of criterion (SMESH.FT_Taper, SMESH.FT_Area, etc.)
+    #          Type SMESH.FunctorType._items in the Python Console to see all values.
+    #          Note that the items starting from FT_LessThan are not suitable for CritType.
+    #  @param Compare  belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
+    #  @param Threshold the threshold value (range of ids as string, shape, numeric)
+    #  @param UnaryOp  SMESH.FT_LogicalNOT or SMESH.FT_Undefined
+    #  @param Tolerance the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
+    #         SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces and SMESH.FT_EqualNodes criteria
     #  @param mesh the mesh to initialize the filter with
     #  @return SMESH_Filter
     #
@@ -923,7 +927,9 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         return aFilter
 
     ## Creates a numerical functor by its type
-    #  @param theCriterion FT_...; functor type
+    #  @param theCriterion functor type - an item of SMESH.FunctorType enumeration.
+    #          Type SMESH.FunctorType._items in the Python Console to see all items.
+    #          Note that not all items correspond to numerical functors.
     #  @return SMESH_NumericalFunctor
     #  @ingroup l1_controls
     def GetFunctor(self,theCriterion):
@@ -1419,37 +1425,7 @@ class Mesh:
             # Treat compute errors
             computeErrors = self.smeshpyD.GetComputeErrors( self.mesh, geom )
             for err in computeErrors:
-                shapeText = ""
-                if self.mesh.HasShapeToMesh():
-                    try:
-                        mainIOR  = salome.orb.object_to_string(geom)
-                        for sname in salome.myStudyManager.GetOpenStudies():
-                            s = salome.myStudyManager.GetStudyByName(sname)
-                            if not s: continue
-                            mainSO = s.FindObjectIOR(mainIOR)
-                            if not mainSO: continue
-                            if err.subShapeID == 1:
-                                shapeText = ' on "%s"' % mainSO.GetName()
-                            subIt = s.NewChildIterator(mainSO)
-                            while subIt.More():
-                                subSO = subIt.Value()
-                                subIt.Next()
-                                obj = subSO.GetObject()
-                                if not obj: continue
-                                go = obj._narrow( geomBuilder.GEOM._objref_GEOM_Object )
-                                if not go: continue
-                                ids = go.GetSubShapeIndices()
-                                if len(ids) == 1 and ids[0] == err.subShapeID:
-                                    shapeText = ' on "%s"' % subSO.GetName()
-                                    break
-                        if not shapeText:
-                            shape = self.geompyD.GetSubShape( geom, [err.subShapeID])
-                            if shape:
-                                shapeText = " on %s #%s" % (shape.GetShapeType(), err.subShapeID)
-                            else:
-                                shapeText = " on subshape #%s" % (err.subShapeID)
-                    except:
-                        shapeText = " on subshape #%s" % (err.subShapeID)
+                shapeText = " on %s" % self.GetSubShapeName( err.subShapeID )
                 errText = ""
                 stdErrors = ["OK",                   #COMPERR_OK
                              "Invalid input mesh",   #COMPERR_BAD_INPUT_MESH
@@ -1527,14 +1503,101 @@ class Mesh:
             pass
         return ok
 
-    ## Return submesh objects list in meshing order
-    #  @return list of list of submesh objects
+    ## Return a name of a sub-shape by its ID
+    #  @param subShapeID a unique ID of a sub-shape
+    #  @return a string describing the sub-shape; possible variants:
+    #  - "Face_12"    (published sub-shape)
+    #  - FACE #3      (not published sub-shape)
+    #  - sub-shape #3 (invalid sub-shape ID)
+    #  - #3           (error in this function)
+    def GetSubShapeName(self, subShapeID ):
+        if not self.mesh.HasShapeToMesh():
+            return ""
+        try:
+            shapeText = ""
+            mainIOR  = salome.orb.object_to_string( self.GetShape() )
+            for sname in salome.myStudyManager.GetOpenStudies():
+                s = salome.myStudyManager.GetStudyByName(sname)
+                if not s: continue
+                mainSO = s.FindObjectIOR(mainIOR)
+                if not mainSO: continue
+                if subShapeID == 1:
+                    shapeText = '"%s"' % mainSO.GetName()
+                subIt = s.NewChildIterator(mainSO)
+                while subIt.More():
+                    subSO = subIt.Value()
+                    subIt.Next()
+                    obj = subSO.GetObject()
+                    if not obj: continue
+                    go = obj._narrow( geomBuilder.GEOM._objref_GEOM_Object )
+                    if not go: continue
+                    try:
+                        ids = self.geompyD.GetSubShapeID( self.GetShape(), go )
+                    except:
+                        continue
+                    if ids == subShapeID:
+                        shapeText = '"%s"' % subSO.GetName()
+                        break
+            if not shapeText:
+                shape = self.geompyD.GetSubShape( self.GetShape(), [subShapeID])
+                if shape:
+                    shapeText = '%s #%s' % (shape.GetShapeType(), subShapeID)
+                else:
+                    shapeText = 'sub-shape #%s' % (subShapeID)
+        except:
+            shapeText = "#%s" % (subShapeID)
+        return shapeText
+
+    ## Return a list of sub-shapes meshing of which failed, grouped into GEOM groups by
+    #  error of an algorithm
+    #  @param publish if @c True, the returned groups will be published in the study
+    #  @return a list of GEOM groups each named after a failed algorithm
+    def GetFailedShapes(self, publish=False):
+
+        algo2shapes = {}
+        computeErrors = self.smeshpyD.GetComputeErrors( self.mesh, self.GetShape() )
+        for err in computeErrors:
+            shape = self.geompyD.GetSubShape( self.GetShape(), [err.subShapeID])
+            if not shape: continue
+            if err.algoName in algo2shapes:
+                algo2shapes[ err.algoName ].append( shape )
+            else:
+                algo2shapes[ err.algoName ] = [ shape ]
+            pass
+
+        groups = []
+        for algoName, shapes in algo2shapes.items():
+            while shapes:
+                groupType = self.smeshpyD.EnumToLong( shapes[0].GetShapeType() )
+                otherTypeShapes = []
+                sameTypeShapes  = []
+                group = self.geompyD.CreateGroup( self.geom, groupType )
+                for shape in shapes:
+                    if shape.GetShapeType() == shapes[0].GetShapeType():
+                        sameTypeShapes.append( shape )
+                    else:
+                        otherTypeShapes.append( shape )
+                self.geompyD.UnionList( group, sameTypeShapes )
+                if otherTypeShapes:
+                    group.SetName( "%s %s" % ( algoName, shapes[0].GetShapeType() ))
+                else:
+                    group.SetName( algoName )
+                groups.append( group )
+                shapes = otherTypeShapes
+            pass
+        if publish:
+            for group in groups:
+                self.geompyD.addToStudyInFather( self.geom, group, group.GetName() )
+        return groups
+
+    ## Return sub-mesh objects list in meshing order
+    #  @return list of list of sub-meshes
     #  @ingroup l2_construct
     def GetMeshOrder(self):
         return self.mesh.GetMeshOrder()
 
-    ## Return submesh objects list in meshing order
-    #  @return list of list of submesh objects
+    ## Set order in which concurrent sub-meshes sould be meshed
+    #  @param submeshes list of sub-meshes
     #  @ingroup l2_construct
     def SetMeshOrder(self, submeshes):
         return self.mesh.SetMeshOrder(submeshes)
@@ -1603,6 +1666,8 @@ class Mesh:
     #  @return SMESH.Hypothesis_Status
     #  @ingroup l2_hypotheses
     def AddHypothesis(self, hyp, geom=0):
+        if isinstance( hyp, geomBuilder.GEOM._objref_GEOM_Object ):
+            hyp, geom = geom, hyp
         if isinstance( hyp, Mesh_Algorithm ):
             hyp = hyp.GetAlgorithm()
             pass
@@ -1828,7 +1893,8 @@ class Mesh:
     # ----------------------
 
     ## Creates an empty mesh group
-    #  @param elementType the type of elements in the group
+    #  @param elementType the type of elements in the group; either of 
+    #         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
     #  @param name the name of the mesh group
     #  @return SMESH_Group
     #  @ingroup l2_grps_create
@@ -1851,8 +1917,9 @@ class Mesh:
     #  the name is the same as the geometrical group name
     #  @param grp  a geometrical group, a vertex, an edge, a face or a solid
     #  @param name the name of the mesh group
-    #  @param typ  the type of elements in the group. If not set, it is
-    #              automatically detected by the type of the geometry
+    #  @param typ  the type of elements in the group; either of 
+    #         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME). If not set, it is
+    #         automatically detected by the type of the geometry
     #  @return SMESH_GroupOnGeom
     #  @ingroup l2_grps_create
     def GroupOnGeom(self, grp, name="", typ=None):
@@ -1887,7 +1954,8 @@ class Mesh:
     ## Creates a mesh group with given \a name based on the \a filter which
     ## is a special type of group dynamically updating it's contents during
     ## mesh modification
-    #  @param typ  the type of elements in the group
+    #  @param typ  the type of elements in the group; either of 
+    #         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
     #  @param name the name of the mesh group
     #  @param filter the filter defining group contents
     #  @return SMESH_GroupOnFilter
@@ -1897,7 +1965,8 @@ class Mesh:
 
     ## Creates a mesh group by the given ids of elements
     #  @param groupName the name of the mesh group
-    #  @param elementType the type of elements in the group
+    #  @param elementType the type of elements in the group; either of 
+    #         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
     #  @param elemIDs the list of ids
     #  @return SMESH_Group
     #  @ingroup l2_grps_create
@@ -1913,13 +1982,15 @@ class Mesh:
 
     ## Creates a mesh group by the given conditions
     #  @param groupName the name of the mesh group
-    #  @param elementType the type of elements in the group
-    #  @param CritType the type of criterion( FT_Taper, FT_Area, FT_RangeOfIds, FT_LyingOnGeom etc. )
-    #  @param Compare belongs to {FT_LessThan, FT_MoreThan, FT_EqualTo}
-    #  @param Threshold the threshold value (range of id ids as string, shape, numeric)
-    #  @param UnaryOp FT_LogicalNOT or FT_Undefined
-    #  @param Tolerance the tolerance used by FT_BelongToGeom, FT_BelongToSurface,
-    #         FT_LyingOnGeom, FT_CoplanarFaces criteria
+    #  @param elementType the type of elements(SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
+    #  @param CritType the type of criterion (SMESH.FT_Taper, SMESH.FT_Area, etc.)
+    #          Type SMESH.FunctorType._items in the Python Console to see all values.
+    #          Note that the items starting from FT_LessThan are not suitable for CritType.
+    #  @param Compare  belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
+    #  @param Threshold the threshold value (range of ids as string, shape, numeric)
+    #  @param UnaryOp  SMESH.FT_LogicalNOT or SMESH.FT_Undefined
+    #  @param Tolerance the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
+    #         SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces criteria
     #  @return SMESH_GroupOnFilter
     #  @ingroup l2_grps_create
     def MakeGroup(self,
@@ -1977,10 +2048,22 @@ class Mesh:
 
     ## Gets the list of groups existing in the mesh in the order
     #  of creation (starting from the oldest one)
+    #  @param elemType type of elements the groups contain; either of 
+    #         (SMESH.ALL, SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME);
+    #         by default groups of elements of all types are returned
     #  @return a sequence of SMESH_GroupBase
     #  @ingroup l2_grps_create
-    def GetGroups(self):
-        return self.mesh.GetGroups()
+    def GetGroups(self, elemType = SMESH.ALL):
+        groups = self.mesh.GetGroups()
+        if elemType == SMESH.ALL:
+            return groups
+        typedGroups = []
+        for g in groups:
+            if g.GetType() == elemType:
+                typedGroups.append( g )
+                pass
+            pass
+        return typedGroups
 
     ## Gets the number of groups existing in the mesh
     #  @return the quantity of groups as an integer value
@@ -1998,6 +2081,25 @@ class Mesh:
             names.append(group.GetName())
         return names
 
+    ## Finds groups by name and type
+    #  @param name name of the group of interest
+    #  @param elemType type of elements the groups contain; either of 
+    #         (SMESH.ALL, SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME);
+    #         by default one group of any type of elements is returned
+    #         if elemType == SMESH.ALL then all groups of any type are returned
+    #  @return a list of SMESH_GroupBase's
+    #  @ingroup l2_grps_create
+    def GetGroupByName(self, name, elemType = None):
+        groups = []
+        for group in self.GetGroups():
+            if group.GetName() == name:
+                if elemType is None:
+                    return [group]
+                if ( elemType == SMESH.ALL or 
+                     group.GetType() == elemType ):
+                    groups.append( group )
+        return groups
+
     ## Produces a union of two groups.
     #  A new group is created. All mesh elements that are
     #  present in the initial groups are added to the new one
@@ -2049,7 +2151,8 @@ class Mesh:
     ##
     #  Create a standalone group of entities basing on nodes of other groups.
     #  \param groups - list of groups, sub-meshes or filters, of any type.
-    #  \param elemType - a type of elements to include to the new group.
+    #  \param elemType - a type of elements to include to the new group; either of 
+    #         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
     #  \param name - a name of the new group.
     #  \param nbCommonNodes - a criterion of inclusion of an element to the new group
     #         basing on number of element nodes common with reference \a groups.
@@ -2134,9 +2237,17 @@ class Mesh:
 
     ## Wrap a list of IDs of elements or nodes into SMESH_IDSource which
     #  can be passed as argument to a method accepting mesh, group or sub-mesh
+    #  @param ids list of IDs
+    #  @param elemType type of elements; this parameter is used to distinguish
+    #         IDs of nodes from IDs of elements; by default ids are treated as
+    #         IDs of elements; use SMESH.NODE if ids are IDs of nodes.
     #  @return an instance of SMESH_IDSource
+    #  @warning call UnRegister() for the returned object as soon as it is no more useful:
+    #          idSrc = mesh.GetIDSource( [1,3,5], SMESH.NODE )
+    #          mesh.DoSomething( idSrc )
+    #          idSrc.UnRegister()
     #  @ingroup l1_auxiliary
-    def GetIDSource(self, ids, elemType):
+    def GetIDSource(self, ids, elemType = SMESH.ALL):
         return self.editor.MakeIDSource(ids, elemType)
 
 
@@ -2182,7 +2293,7 @@ class Mesh:
 
     ## Returns the number of edges with the given order in the mesh
     #  @param elementOrder the order of elements:
-    #         ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC
+    #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbEdgesOfOrder(self, elementOrder):
@@ -2196,7 +2307,7 @@ class Mesh:
 
     ## Returns the number of faces with the given order in the mesh
     #  @param elementOrder the order of elements:
-    #         ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC
+    #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbFacesOfOrder(self, elementOrder):
@@ -2210,7 +2321,7 @@ class Mesh:
 
     ## Returns the number of triangles with the given order in the mesh
     #  @param elementOrder is the order of elements:
-    #         ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC
+    #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbTrianglesOfOrder(self, elementOrder):
@@ -2230,7 +2341,7 @@ class Mesh:
 
     ## Returns the number of quadrangles with the given order in the mesh
     #  @param elementOrder the order of elements:
-    #         ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC
+    #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbQuadranglesOfOrder(self, elementOrder):
@@ -2242,11 +2353,13 @@ class Mesh:
     def NbBiQuadQuadrangles(self):
         return self.mesh.NbBiQuadQuadrangles()
 
-    ## Returns the number of polygons in the mesh
+    ## Returns the number of polygons of given order in the mesh
+    #  @param elementOrder the order of elements:
+    #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
     #  @ingroup l1_meshinfo
-    def NbPolygons(self):
-        return self.mesh.NbPolygons()
+    def NbPolygons(self, elementOrder = SMESH.ORDER_ANY):
+        return self.mesh.NbPolygonsOfOrder(elementOrder)
 
     ## Returns the number of volumes in the mesh
     #  @return an integer value
@@ -2256,7 +2369,7 @@ class Mesh:
 
     ## Returns the number of volumes with the given order in the mesh
     #  @param elementOrder  the order of elements:
-    #         ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC
+    #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbVolumesOfOrder(self, elementOrder):
@@ -2270,7 +2383,7 @@ class Mesh:
 
     ## Returns the number of tetrahedrons with the given order in the mesh
     #  @param elementOrder  the order of elements:
-    #         ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC
+    #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbTetrasOfOrder(self, elementOrder):
@@ -2284,7 +2397,7 @@ class Mesh:
 
     ## Returns the number of hexahedrons with the given order in the mesh
     #  @param elementOrder  the order of elements:
-    #         ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC
+    #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbHexasOfOrder(self, elementOrder):
@@ -2304,7 +2417,7 @@ class Mesh:
 
     ## Returns the number of pyramids with the given order in the mesh
     #  @param elementOrder  the order of elements:
-    #         ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC
+    #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbPyramidsOfOrder(self, elementOrder):
@@ -2318,7 +2431,7 @@ class Mesh:
 
     ## Returns the number of prisms with the given order in the mesh
     #  @param elementOrder  the order of elements:
-    #         ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC
+    #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbPrismsOfOrder(self, elementOrder):
@@ -2349,7 +2462,8 @@ class Mesh:
         return self.mesh.GetElementsId()
 
     ## Returns the list of IDs of mesh elements with the given type
-    #  @param elementType  the required type of elements (SMESH.NODE, SMESH.EDGE, SMESH.FACE or SMESH.VOLUME)
+    #  @param elementType  the required type of elements, either of
+    #         (SMESH.NODE, SMESH.EDGE, SMESH.FACE or SMESH.VOLUME)
     #  @return list of integer values
     #  @ingroup l1_meshinfo
     def GetElementsByType(self, elementType):
@@ -2366,18 +2480,21 @@ class Mesh:
 
     ## Returns the type of mesh element
     #  @return the value from SMESH::ElementType enumeration
+    #          Type SMESH.ElementType._items in the Python Console to see all possible values.
     #  @ingroup l1_meshinfo
-    def GetElementType(self, id, iselem):
+    def GetElementType(self, id, iselem=True):
         return self.mesh.GetElementType(id, iselem)
 
     ## Returns the geometric type of mesh element
     #  @return the value from SMESH::EntityType enumeration
+    #          Type SMESH.EntityType._items in the Python Console to see all possible values.
     #  @ingroup l1_meshinfo
     def GetElementGeomType(self, id):
         return self.mesh.GetElementGeomType(id)
 
     ## Returns the shape type of mesh element
-    #  @return the value from SMESH::GeometryType enumeration
+    #  @return the value from SMESH::GeometryType enumeration.
+    #          Type SMESH.GeometryType._items in the Python Console to see all possible values.
     #  @ingroup l1_meshinfo
     def GetElementShape(self, id):
         return self.mesh.GetElementShape(id)
@@ -2388,8 +2505,8 @@ class Mesh:
     #  @return the list of integer values
     #  @ingroup l1_meshinfo
     def GetSubMeshElementsId(self, Shape):
-        if ( isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object)):
-            ShapeID = Shape.GetSubShapeIndices()[0]
+        if isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object):
+            ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
         else:
             ShapeID = Shape
         return self.mesh.GetSubMeshElementsId(ShapeID)
@@ -2401,7 +2518,7 @@ class Mesh:
     #  @return the list of integer values
     #  @ingroup l1_meshinfo
     def GetSubMeshNodesId(self, Shape, all):
-        if ( isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object)):
+        if isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object):
             ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
         else:
             ShapeID = Shape
@@ -2413,8 +2530,8 @@ class Mesh:
     #  @return element type
     #  @ingroup l1_meshinfo
     def GetSubMeshElementType(self, Shape):
-        if ( isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object)):
-            ShapeID = Shape.GetSubShapeIndices()[0]
+        if isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object):
+            ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
         else:
             ShapeID = Shape
         return self.mesh.GetSubMeshElementType(ShapeID)
@@ -2455,24 +2572,22 @@ class Mesh:
     def GetElementPosition(self,ElemID):
         return self.mesh.GetElementPosition(ElemID)
 
-    ## If the given element is a node, returns the ID of shape
-    #  \n If there is no node for the given ID - returns -1
-    #  @return an integer value
+    ## Returns the ID of the shape, on which the given node was generated.
+    #  @return an integer value > 0 or -1 if there is no node for the given
+    #          ID or the node is not assigned to any geometry
     #  @ingroup l1_meshinfo
     def GetShapeID(self, id):
         return self.mesh.GetShapeID(id)
 
-    ## Returns the ID of the result shape after
-    #  FindShape() from SMESH_MeshEditor for the given element
-    #  \n If there is no element for the given ID - returns -1
-    #  @return an integer value
+    ## Returns the ID of the shape, on which the given element was generated.
+    #  @return an integer value > 0 or -1 if there is no element for the given
+    #          ID or the element is not assigned to any geometry
     #  @ingroup l1_meshinfo
     def GetShapeIDForElem(self,id):
         return self.mesh.GetShapeIDForElem(id)
 
-    ## Returns the number of nodes for the given element
-    #  \n If there is no element for the given ID - returns -1
-    #  @return an integer value
+    ## Returns the number of nodes of the given element
+    #  @return an integer value > 0 or -1 if there is no element for the given ID
     #  @ingroup l1_meshinfo
     def GetElemNbNodes(self, id):
         return self.mesh.GetElemNbNodes(id)
@@ -2497,8 +2612,11 @@ class Mesh:
         return self.mesh.IsMediumNode(elementID, nodeID)
 
     ## Returns true if the given node is the medium node in one of quadratic elements
+    #  @param nodeID ID of the node
+    #  @param elementType  the type of elements to check a state of the node, either of
+    #         (SMESH.ALL, SMESH.NODE, SMESH.EDGE, SMESH.FACE or SMESH.VOLUME)
     #  @ingroup l1_meshinfo
-    def IsMediumNodeOfAnyElem(self, nodeID, elementType):
+    def IsMediumNodeOfAnyElem(self, nodeID, elementType = SMESH.ALL ):
         return self.mesh.IsMediumNodeOfAnyElem(nodeID, elementType)
 
     ## Returns the number of edges for the given element
@@ -2756,6 +2874,14 @@ class Mesh:
     def AddPolygonalFace(self, IdsOfNodes):
         return self.editor.AddPolygonalFace(IdsOfNodes)
 
+    ## Adds a quadratic polygonal face to the mesh by the list of node IDs
+    #  @param IdsOfNodes the list of node IDs for creation of the element;
+    #         corner nodes follow first.
+    #  @return the Id of the new face
+    #  @ingroup l2_modif_add
+    def AddQuadPolygonalFace(self, IdsOfNodes):
+        return self.editor.AddQuadPolygonalFace(IdsOfNodes)
+
     ## Creates both simple and quadratic volume (this is determined
     #  by the number of given nodes).
     #  @param IDsOfNodes the list of node IDs for creation of the element.
@@ -2794,7 +2920,7 @@ class Mesh:
     #  @ingroup l2_modif_add
     def SetNodeOnVertex(self, NodeID, Vertex):
         if ( isinstance( Vertex, geomBuilder.GEOM._objref_GEOM_Object)):
-            VertexID = Vertex.GetSubShapeIndices()[0]
+            VertexID = self.geompyD.GetSubShapeID( self.geom, Vertex )
         else:
             VertexID = Vertex
         try:
@@ -2812,7 +2938,7 @@ class Mesh:
     #  @ingroup l2_modif_add
     def SetNodeOnEdge(self, NodeID, Edge, paramOnEdge):
         if ( isinstance( Edge, geomBuilder.GEOM._objref_GEOM_Object)):
-            EdgeID = Edge.GetSubShapeIndices()[0]
+            EdgeID = self.geompyD.GetSubShapeID( self.geom, Edge )
         else:
             EdgeID = Edge
         try:
@@ -2830,7 +2956,7 @@ class Mesh:
     #  @ingroup l2_modif_add
     def SetNodeOnFace(self, NodeID, Face, u, v):
         if ( isinstance( Face, geomBuilder.GEOM._objref_GEOM_Object)):
-            FaceID = Face.GetSubShapeIndices()[0]
+            FaceID = self.geompyD.GetSubShapeID( self.geom, Face )
         else:
             FaceID = Face
         try:
@@ -2846,7 +2972,7 @@ class Mesh:
     #  @ingroup l2_modif_add
     def SetNodeInVolume(self, NodeID, Solid):
         if ( isinstance( Solid, geomBuilder.GEOM._objref_GEOM_Object)):
-            SolidID = Solid.GetSubShapeIndices()[0]
+            SolidID = self.geompyD.GetSubShapeID( self.geom, Solid )
         else:
             SolidID = Solid
         try:
@@ -2862,7 +2988,7 @@ class Mesh:
     #  @ingroup l2_modif_add
     def SetMeshElementOnShape(self, ElementID, Shape):
         if ( isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object)):
-            ShapeID = Shape.GetSubShapeIndices()[0]
+            ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
         else:
             ShapeID = Shape
         try:
@@ -2912,8 +3038,9 @@ class Mesh:
     #  @param x  the X coordinate of a point
     #  @param y  the Y coordinate of a point
     #  @param z  the Z coordinate of a point
-    #  @param elementType type of elements to find (SMESH.ALL type
-    #         means elements of any type excluding nodes, discrete and 0D elements)
+    #  @param elementType type of elements to find; either of 
+    #         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME); SMESH.ALL type
+    #         means elements of any type excluding nodes, discrete and 0D elements.
     #  @param meshPart a part of mesh (group, sub-mesh) to search within
     #  @return list of IDs of found elements
     #  @ingroup l2_modif_throughp
@@ -2923,10 +3050,9 @@ class Mesh:
         else:
             return self.editor.FindElementsByPoint(x, y, z, elementType)
 
-    # Return point state in a closed 2D mesh in terms of TopAbs_State enumeration:
-    # 0-IN, 1-OUT, 2-ON, 3-UNKNOWN
-    # TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
-
+    ## Return point state in a closed 2D mesh in terms of TopAbs_State enumeration:
+    #  0-IN, 1-OUT, 2-ON, 3-UNKNOWN
+    #  UNKNOWN state means that either mesh is wrong or the analysis fails.
     def GetPointState(self, x, y, z):
         return self.editor.GetPointState(x, y, z)
 
@@ -3044,12 +3170,14 @@ class Mesh:
         return self.editor.Reorient2DBy3D( the2DObject, the3DObject, theOutsideNormal )
 
     ## Fuses the neighbouring triangles into quadrangles.
-    #  @param IDsOfElements The triangles to be fused,
-    #  @param theCriterion  is a numerical functor, in terms of enum SMESH.FunctorType, used to
-    #                       choose a neighbour to fuse with.
+    #  @param IDsOfElements The triangles to be fused.
+    #  @param theCriterion  a numerical functor, in terms of enum SMESH.FunctorType, used to
+    #          applied to possible quadrangles to choose a neighbour to fuse with.
+    #          Type SMESH.FunctorType._items in the Python Console to see all items.
+    #          Note that not all items correspond to numerical functors.
     #  @param MaxAngle      is the maximum angle between element normals at which the fusion
-    #                       is still performed; theMaxAngle is mesured in radians.
-    #                       Also it could be a name of variable which defines angle in degrees.
+    #          is still performed; theMaxAngle is mesured in radians.
+    #          Also it could be a name of variable which defines angle in degrees.
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_unitetri
     def TriToQuad(self, IDsOfElements, theCriterion, MaxAngle):
@@ -3062,10 +3190,12 @@ class Mesh:
 
     ## Fuses the neighbouring triangles of the object into quadrangles
     #  @param theObject is mesh, submesh or group
-    #  @param theCriterion is a numerical functor, in terms of enum SMESH.FunctorType, used to
-    #         choose a neighbour to fuse with.
+    #  @param theCriterion is a numerical functor, in terms of enum SMESH.FunctorType,
+    #          applied to possible quadrangles to choose a neighbour to fuse with.
+    #          Type SMESH.FunctorType._items in the Python Console to see all items.
+    #          Note that not all items correspond to numerical functors.
     #  @param MaxAngle   a max angle between element normals at which the fusion
-    #                   is still performed; theMaxAngle is mesured in radians.
+    #          is still performed; theMaxAngle is mesured in radians.
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_unitetri
     def TriToQuadObject (self, theObject, theCriterion, MaxAngle):
@@ -3078,9 +3208,11 @@ class Mesh:
 
     ## Splits quadrangles into triangles.
     #  @param IDsOfElements the faces to be splitted.
-    #  @param theCriterion   is a numerical functor, in terms of enum SMESH.FunctorType, used to
+    #  @param theCriterion is a numerical functor, in terms of enum SMESH.FunctorType, used to
     #         choose a diagonal for splitting. If @a theCriterion is None, which is a default
     #         value, then quadrangles will be split by the smallest diagonal.
+    #         Type SMESH.FunctorType._items in the Python Console to see all items.
+    #         Note that not all items correspond to numerical functors.
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_cutquadr
     def QuadToTri (self, IDsOfElements, theCriterion = None):
@@ -3097,6 +3229,8 @@ class Mesh:
     #  @param theCriterion is a numerical functor, in terms of enum SMESH.FunctorType, used to
     #         choose a diagonal for splitting. If @a theCriterion is None, which is a default
     #         value, then quadrangles will be split by the smallest diagonal.
+    #         Type SMESH.FunctorType._items in the Python Console to see all items.
+    #         Note that not all items correspond to numerical functors.
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_cutquadr
     def QuadToTriObject (self, theObject, theCriterion = None):
@@ -3148,6 +3282,8 @@ class Mesh:
     #  @param IDOfQuad   the ID of the quadrangle to be splitted.
     #  @param theCriterion  is a numerical functor, in terms of enum SMESH.FunctorType, used to
     #         choose a diagonal for splitting.
+    #         Type SMESH.FunctorType._items in the Python Console to see all items.
+    #         Note that not all items correspond to numerical functors.
     #  @return 1 if 1-3 diagonal is better, 2 if 2-4
     #          diagonal is better, 0 if error occurs.
     #  @ingroup l2_modif_cutquadr
@@ -3168,6 +3304,29 @@ class Mesh:
             elems = self.editor.MakeIDSource(elems, SMESH.VOLUME)
             unRegister.set( elems )
         self.editor.SplitVolumesIntoTetra(elems, method)
+        return
+
+    ## Split bi-quadratic elements into linear ones without creation of additional nodes:
+    #   - bi-quadratic triangle will be split into 3 linear quadrangles;
+    #   - bi-quadratic quadrangle will be split into 4 linear quadrangles;
+    #   - tri-quadratic hexahedron will be split into 8 linear hexahedra.
+    #   Quadratic elements of lower dimension  adjacent to the split bi-quadratic element
+    #   will be split in order to keep the mesh conformal.
+    #  @param elems - elements to split: sub-meshes, groups, filters or element IDs;
+    #         if None (default), all bi-quadratic elements will be split
+    #  @ingroup l2_modif_cutquadr
+    def SplitBiQuadraticIntoLinear(self, elems=None):
+        unRegister = genObjUnRegister()
+        if elems and isinstance( elems, list ) and isinstance( elems[0], int ):
+            elems = self.editor.MakeIDSource(elems, SMESH.ALL)
+            unRegister.set( elems )
+        if elems is None:
+            elems = [ self.GetMesh() ]
+        if isinstance( elems, Mesh ):
+            elems = [ elems.GetMesh() ]
+        if not isinstance( elems, list ):
+            elems = [elems]
+        self.editor.SplitBiQuadraticIntoLinear( elems )
 
     ## Splits hexahedra into prisms
     #  @param elems either a list of elements or a mesh or a group or a submesh or a filter
@@ -3460,15 +3619,15 @@ class Mesh:
     ## Creates 2D mesh as skin on boundary faces of a 3D mesh
     #  @return TRUE if operation has been completed successfully, FALSE otherwise
     #  @ingroup l2_modif_edit
-    def  Make2DMeshFrom3D(self):
-        return self.editor. Make2DMeshFrom3D()
+    def Make2DMeshFrom3D(self):
+        return self.editor.Make2DMeshFrom3D()
 
     ## Creates missing boundary elements
     #  @param elements - elements whose boundary is to be checked:
     #                    mesh, group, sub-mesh or list of elements
     #   if elements is mesh, it must be the mesh whose MakeBoundaryMesh() is called
-    #  @param dimension - defines type of boundary elements to create:
-    #                     SMESH.BND_2DFROM3D, SMESH.BND_1DFROM3D, SMESH.BND_1DFROM2D
+    #  @param dimension - defines type of boundary elements to create, either of
+    #                     { SMESH.BND_2DFROM3D, SMESH.BND_1DFROM3D, SMESH.BND_1DFROM2D }
     #    SMESH.BND_1DFROM3D creates mesh edges on all borders of free facets of 3D cells
     #  @param groupName - a name of group to store created boundary elements in,
     #                     "" means not to create the group
@@ -3498,7 +3657,8 @@ class Mesh:
     ##
     # @brief Creates missing boundary elements around either the whole mesh or 
     #    groups of elements
-    #  @param dimension - defines type of boundary elements to create
+    #  @param dimension - defines type of boundary elements to create, either of
+    #                     { SMESH.BND_2DFROM3D, SMESH.BND_1DFROM3D, SMESH.BND_1DFROM2D }
     #  @param groupName - a name of group to store all boundary elements in,
     #    "" means not to create the group
     #  @param meshName - a name of a new mesh, which is a copy of the initial 
@@ -3679,7 +3839,7 @@ class Mesh:
 
 
     ## Generates new elements by extrusion of the elements with given ids
-    #  @param IDsOfElements the list of elements ids for extrusion
+    #  @param IDsOfElements the list of ids of elements or nodes for extrusion
     #  @param StepVector vector or DirStruct or 3 vector components, defining
     #         the direction and value of extrusion for one step (the total extrusion
     #         length will be NbOfSteps * ||StepVector||)
@@ -3695,8 +3855,8 @@ class Mesh:
         return self.ExtrusionSweepObjects(n,e,f, StepVector, NbOfSteps, MakeGroups)
 
     ## Generates new elements by extrusion along the normal to a discretized surface or wire
-    #  @param Elements elements to extrude - a list including ids, groups, sub-meshes or a mesh
-    #         Only faces can be extruded so far. Sub-mesh should be a sub-mesh on geom faces.
+    #  @param Elements elements to extrude - a list including ids, groups, sub-meshes or a mesh.
+    #         Only faces can be extruded so far. A sub-mesh should be a sub-mesh on geom faces.
     #  @param StepSize length of one extrusion step (the total extrusion
     #         length will be \a NbOfSteps * \a StepSize ).
     #  @param NbOfSteps number of extrusion steps.
@@ -3732,15 +3892,15 @@ class Mesh:
         return self.editor.ExtrusionByNormal(Elements, StepSize, NbOfSteps,
                                              ByAverageNormal, UseInputElemsOnly, MakeGroups, Dim)
 
-    ## Generates new elements by extrusion of the elements which belong to the object
-    #  @param theObject the object which elements should be processed.
-    #                   It can be a mesh, a sub mesh or a group.
+    ## Generates new elements by extrusion of the elements or nodes which belong to the object
+    #  @param theObject the object whose elements or nodes should be processed.
+    #                   It can be a mesh, a sub-mesh or a group.
     #  @param StepVector vector or DirStruct or 3 vector components, defining
     #         the direction and value of extrusion for one step (the total extrusion
     #         length will be NbOfSteps * ||StepVector||)
     #  @param NbOfSteps the number of steps
     #  @param MakeGroups forces the generation of new groups from existing ones
-    #  @param  IsNodes is True if elements to extrude are nodes
+    #  @param IsNodes is True if elements to extrude are nodes
     #  @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
     #  @ingroup l2_modif_extrurev
     def ExtrusionSweepObject(self, theObject, StepVector, NbOfSteps, MakeGroups=False, IsNodes=False):
@@ -3749,9 +3909,9 @@ class Mesh:
         else      : e,f, = theObject,theObject
         return self.ExtrusionSweepObjects(n,e,f, StepVector, NbOfSteps, MakeGroups)
 
-    ## Generates new elements by extrusion of the elements which belong to the object
-    #  @param theObject object which elements should be processed.
-    #                   It can be a mesh, a sub mesh or a group.
+    ## Generates new elements by extrusion of edges which belong to the object
+    #  @param theObject object whose 1D elements should be processed.
+    #                   It can be a mesh, a sub-mesh or a group.
     #  @param StepVector vector or DirStruct or 3 vector components, defining
     #         the direction and value of extrusion for one step (the total extrusion
     #         length will be NbOfSteps * ||StepVector||)
@@ -3762,9 +3922,9 @@ class Mesh:
     def ExtrusionSweepObject1D(self, theObject, StepVector, NbOfSteps, MakeGroups=False):
         return self.ExtrusionSweepObjects([],theObject,[], StepVector, NbOfSteps, MakeGroups)
 
-    ## Generates new elements by extrusion of the elements which belong to the object
-    #  @param theObject object which elements should be processed.
-    #                   It can be a mesh, a sub mesh or a group.
+    ## Generates new elements by extrusion of faces which belong to the object
+    #  @param theObject object whose 2D elements should be processed.
+    #                   It can be a mesh, a sub-mesh or a group.
     #  @param StepVector vector or DirStruct or 3 vector components, defining
     #         the direction and value of extrusion for one step (the total extrusion
     #         length will be NbOfSteps * ||StepVector||)
@@ -3827,6 +3987,7 @@ class Mesh:
         if isinstance( RefPoint, geomBuilder.GEOM._objref_GEOM_Object):
             RefPoint = self.smeshpyD.GetPointStruct(RefPoint)
         if isinstance( RefPoint, list ):
+            if not RefPoint: RefPoint = [0,0,0]
             RefPoint = SMESH.PointStruct( *RefPoint )
         if isinstance( PathMesh, Mesh ):
             PathMesh = PathMesh.GetMesh()
@@ -3840,7 +4001,7 @@ class Mesh:
 
     ## Generates new elements by extrusion of the given elements
     #  The path of extrusion must be a meshed edge.
-    #  @param Base mesh or group, or submesh, or list of ids of elements for extrusion
+    #  @param Base mesh or group, or sub-mesh, or list of ids of elements for extrusion
     #  @param Path - 1D mesh or 1D sub-mesh, along which proceeds the extrusion
     #  @param NodeStart the start node from Path. Defines the direction of extrusion
     #  @param HasAngles allows the shape to be rotated around the path
@@ -3859,8 +4020,9 @@ class Mesh:
     #          only SMESH::Extrusion_Error otherwise
     #  @ingroup l2_modif_extrurev
     def ExtrusionAlongPathX(self, Base, Path, NodeStart,
-                            HasAngles, Angles, LinearVariation,
-                            HasRefPoint, RefPoint, MakeGroups, ElemType):
+                            HasAngles=False, Angles=[], LinearVariation=False,
+                            HasRefPoint=False, RefPoint=[0,0,0], MakeGroups=False,
+                            ElemType=SMESH.FACE):
         n,e,f = [],[],[]
         if ElemType == SMESH.NODE: n = Base
         if ElemType == SMESH.EDGE: e = Base
@@ -3890,7 +4052,7 @@ class Mesh:
     #          only SMESH::Extrusion_Error otherwise
     #  @ingroup l2_modif_extrurev
     def ExtrusionAlongPath(self, IDsOfElements, PathMesh, PathShape, NodeStart,
-                           HasAngles, Angles, HasRefPoint, RefPoint,
+                           HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
                            MakeGroups=False, LinearVariation=False):
         n,e,f = [],IDsOfElements,IDsOfElements
         gr,er = self.ExtrusionAlongPathObjects(n,e,f, PathMesh, PathShape,
@@ -3902,7 +4064,7 @@ class Mesh:
 
     ## Generates new elements by extrusion of the elements which belong to the object
     #  The path of extrusion must be a meshed edge.
-    #  @param theObject the object which elements should be processed.
+    #  @param theObject the object whose elements should be processed.
     #                   It can be a mesh, a sub-mesh or a group.
     #  @param PathMesh mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds
     #  @param PathShape shape(edge) defines the sub-mesh for the path
@@ -3920,7 +4082,7 @@ class Mesh:
     #          only SMESH::Extrusion_Error otherwise
     #  @ingroup l2_modif_extrurev
     def ExtrusionAlongPathObject(self, theObject, PathMesh, PathShape, NodeStart,
-                                 HasAngles, Angles, HasRefPoint, RefPoint,
+                                 HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
                                  MakeGroups=False, LinearVariation=False):
         n,e,f = [],theObject,theObject
         gr,er = self.ExtrusionAlongPathObjects(n,e,f, PathMesh, PathShape, NodeStart,
@@ -3929,10 +4091,10 @@ class Mesh:
         if MakeGroups: return gr,er
         return er
 
-    ## Generates new elements by extrusion of the elements which belong to the object
+    ## Generates new elements by extrusion of mesh segments which belong to the object
     #  The path of extrusion must be a meshed edge.
-    #  @param theObject the object which elements should be processed.
-    #                   It can be a mesh, a sub mesh or a group.
+    #  @param theObject the object whose 1D elements should be processed.
+    #                   It can be a mesh, a sub-mesh or a group.
     #  @param PathMesh mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds
     #  @param PathShape shape(edge) defines the sub-mesh for the path
     #  @param NodeStart the first or the last node on the edge. Defines the direction of extrusion
@@ -3949,7 +4111,7 @@ class Mesh:
     #          only SMESH::Extrusion_Error otherwise
     #  @ingroup l2_modif_extrurev
     def ExtrusionAlongPathObject1D(self, theObject, PathMesh, PathShape, NodeStart,
-                                   HasAngles, Angles, HasRefPoint, RefPoint,
+                                   HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
                                    MakeGroups=False, LinearVariation=False):
         n,e,f = [],theObject,[]
         gr,er = self.ExtrusionAlongPathObjects(n,e,f, PathMesh, PathShape, NodeStart,
@@ -3958,10 +4120,10 @@ class Mesh:
         if MakeGroups: return gr,er
         return er
 
-    ## Generates new elements by extrusion of the elements which belong to the object
+    ## Generates new elements by extrusion of faces which belong to the object
     #  The path of extrusion must be a meshed edge.
-    #  @param theObject the object which elements should be processed.
-    #                   It can be a mesh, a sub mesh or a group.
+    #  @param theObject the object whose 2D elements should be processed.
+    #                   It can be a mesh, a sub-mesh or a group.
     #  @param PathMesh mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds
     #  @param PathShape shape(edge) defines the sub-mesh for the path
     #  @param NodeStart the first or the last node on the edge. Defines the direction of extrusion
@@ -3978,7 +4140,7 @@ class Mesh:
     #          only SMESH::Extrusion_Error otherwise
     #  @ingroup l2_modif_extrurev
     def ExtrusionAlongPathObject2D(self, theObject, PathMesh, PathShape, NodeStart,
-                                   HasAngles, Angles, HasRefPoint, RefPoint,
+                                   HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
                                    MakeGroups=False, LinearVariation=False):
         n,e,f = [],[],theObject
         gr,er = self.ExtrusionAlongPathObjects(n,e,f, PathMesh, PathShape, NodeStart,
@@ -3990,8 +4152,8 @@ class Mesh:
     ## Creates a symmetrical copy of mesh elements
     #  @param IDsOfElements list of elements ids
     #  @param Mirror is AxisStruct or geom object(point, line, plane)
-    #  @param theMirrorType is  POINT, AXIS or PLANE
-    #  If the Mirror is a geom object this parameter is unnecessary
+    #  @param theMirrorType smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE
+    #         If the Mirror is a geom object this parameter is unnecessary
     #  @param Copy allows to copy element (Copy is 1) or to replace with its mirroring (Copy is 0)
     #  @param MakeGroups forces the generation of new groups from existing ones (if Copy)
     #  @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
@@ -4012,8 +4174,8 @@ class Mesh:
     ## Creates a new mesh by a symmetrical copy of mesh elements
     #  @param IDsOfElements the list of elements ids
     #  @param Mirror is AxisStruct or geom object (point, line, plane)
-    #  @param theMirrorType is  POINT, AXIS or PLANE
-    #  If the Mirror is a geom object this parameter is unnecessary
+    #  @param theMirrorType smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE
+    #         If the Mirror is a geom object this parameter is unnecessary
     #  @param MakeGroups to generate new groups from existing ones
     #  @param NewMeshName a name of the new mesh to create
     #  @return instance of Mesh class
@@ -4033,8 +4195,8 @@ class Mesh:
     ## Creates a symmetrical copy of the object
     #  @param theObject mesh, submesh or group
     #  @param Mirror AxisStruct or geom object (point, line, plane)
-    #  @param theMirrorType is  POINT, AXIS or PLANE
-    #  If the Mirror is a geom object this parameter is unnecessary
+    #  @param theMirrorType smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE
+    #         If the Mirror is a geom object this parameter is unnecessary
     #  @param Copy allows copying the element (Copy is 1) or replacing it with its mirror (Copy is 0)
     #  @param MakeGroups forces the generation of new groups from existing ones (if Copy)
     #  @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
@@ -4055,8 +4217,8 @@ class Mesh:
     ## Creates a new mesh by a symmetrical copy of the object
     #  @param theObject mesh, submesh or group
     #  @param Mirror AxisStruct or geom object (point, line, plane)
-    #  @param theMirrorType POINT, AXIS or PLANE
-    #  If the Mirror is a geom object this parameter is unnecessary
+    #  @param theMirrorType smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE
+    #         If the Mirror is a geom object this parameter is unnecessary
     #  @param MakeGroups forces the generation of new groups from existing ones
     #  @param NewMeshName the name of the new mesh to create
     #  @return instance of Mesh class
@@ -4293,39 +4455,51 @@ class Mesh:
 
     ## Finds groups of adjacent nodes within Tolerance.
     #  @param Tolerance the value of tolerance
-    #  @return the list of pairs of nodes IDs (e.g. [[1,12],[25,4]])
+    #  @param SeparateCornerAndMediumNodes if @c True, in quadratic mesh puts
+    #         corner and medium nodes in separate groups thus preventing
+    #         their further merge.
+    #  @return the list of groups of nodes IDs (e.g. [[1,12,13],[4,25]])
     #  @ingroup l2_modif_trsf
-    def FindCoincidentNodes (self, Tolerance):
-        return self.editor.FindCoincidentNodes(Tolerance)
+    def FindCoincidentNodes (self, Tolerance, SeparateCornerAndMediumNodes=False):
+        return self.editor.FindCoincidentNodes( Tolerance, SeparateCornerAndMediumNodes )
 
     ## Finds groups of ajacent nodes within Tolerance.
     #  @param Tolerance the value of tolerance
     #  @param SubMeshOrGroup SubMesh or Group
     #  @param exceptNodes list of either SubMeshes, Groups or node IDs to exclude from search
-    #  @return the list of pairs of nodes IDs (e.g. [[1,12],[25,4]])
+    #  @param SeparateCornerAndMediumNodes if @c True, in quadratic mesh puts
+    #         corner and medium nodes in separate groups thus preventing
+    #         their further merge.
+    #  @return the list of groups of nodes IDs (e.g. [[1,12,13],[4,25]])
     #  @ingroup l2_modif_trsf
-    def FindCoincidentNodesOnPart (self, SubMeshOrGroup, Tolerance, exceptNodes=[]):
+    def FindCoincidentNodesOnPart (self, SubMeshOrGroup, Tolerance,
+                                   exceptNodes=[], SeparateCornerAndMediumNodes=False):
         unRegister = genObjUnRegister()
         if (isinstance( SubMeshOrGroup, Mesh )):
             SubMeshOrGroup = SubMeshOrGroup.GetMesh()
-        if not isinstance( exceptNodes, list):
+        if not isinstance( exceptNodes, list ):
             exceptNodes = [ exceptNodes ]
-        if exceptNodes and isinstance( exceptNodes[0], int):
-            exceptNodes = [ self.GetIDSource( exceptNodes, SMESH.NODE)]
+        if exceptNodes and isinstance( exceptNodes[0], int ):
+            exceptNodes = [ self.GetIDSource( exceptNodes, SMESH.NODE )]
             unRegister.set( exceptNodes )
-        return self.editor.FindCoincidentNodesOnPartBut(SubMeshOrGroup, Tolerance,exceptNodes)
+        return self.editor.FindCoincidentNodesOnPartBut(SubMeshOrGroup, Tolerance,
+                                                        exceptNodes, SeparateCornerAndMediumNodes)
 
     ## Merges nodes
-    #  @param GroupsOfNodes a list of pairs of nodes IDs for merging
-    #         (e.g. [[1,12],[25,4]], then nodes 12 and 4 will be removed and replaced
+    #  @param GroupsOfNodes a list of groups of nodes IDs for merging
+    #         (e.g. [[1,12,13],[25,4]], then nodes 12, 13 and 4 will be removed and replaced
     #         by nodes 1 and 25 correspondingly in all elements and groups
+    #  @param NodesToKeep nodes to keep in the mesh: a list of groups, sub-meshes or node IDs.
+    #         If @a NodesToKeep does not include a node to keep for some group to merge,
+    #         then the first node in the group is kept.
     #  @ingroup l2_modif_trsf
-    def MergeNodes (self, GroupsOfNodes):
-        self.editor.MergeNodes(GroupsOfNodes)
+    def MergeNodes (self, GroupsOfNodes, NodesToKeep=[]):
+        # NodesToKeep are converted to SMESH_IDSource in meshEditor.MergeNodes()
+        self.editor.MergeNodes(GroupsOfNodes,NodesToKeep)
 
     ## Finds the elements built on the same nodes.
     #  @param MeshOrSubMeshOrGroup Mesh or SubMesh, or Group of elements for searching
-    #  @return the list of pairs of equal elements IDs (e.g. [[1,12],[25,4]])
+    #  @return the list of groups of equal elements IDs (e.g. [[1,12,13],[4,25]])
     #  @ingroup l2_modif_trsf
     def FindEqualElements (self, MeshOrSubMeshOrGroup=None):
         if not MeshOrSubMeshOrGroup:
@@ -4335,8 +4509,8 @@ class Mesh:
         return self.editor.FindEqualElements( MeshOrSubMeshOrGroup )
 
     ## Merges elements in each given group.
-    #  @param GroupsOfElementsID a list of pairs of elements IDs for merging
-    #        (e.g. [[1,12],[25,4]], then elements 12 and 4 will be removed and
+    #  @param GroupsOfElementsID a list of groups of elements IDs for merging
+    #        (e.g. [[1,12,13],[25,4]], then elements 12, 13 and 4 will be removed and
     #        replaced by elements 1 and 25 in all groups)
     #  @ingroup l2_modif_trsf
     def MergeElements(self, GroupsOfElementsID):
@@ -4347,6 +4521,52 @@ class Mesh:
     def MergeEqualElements(self):
         self.editor.MergeEqualElements()
 
+    ## Returns groups of FreeBorder's coincident within the given tolerance.
+    #  @param tolerance the tolerance. If the tolerance <= 0.0 then one tenth of an average
+    #         size of elements adjacent to free borders being compared is used.
+    #  @return SMESH.CoincidentFreeBorders structure
+    #  @ingroup l2_modif_trsf
+    def FindCoincidentFreeBorders (self, tolerance=0.):
+        return self.editor.FindCoincidentFreeBorders( tolerance )
+        
+    ## Sew FreeBorder's of each group
+    #  @param freeBorders either a SMESH.CoincidentFreeBorders structure or a list of lists
+    #         where each enclosed list contains node IDs of a group of coincident free
+    #         borders such that each consequent triple of IDs within a group describes
+    #         a free border in a usual way: n1, n2, nLast - i.e. 1st node, 2nd node and
+    #         last node of a border.
+    #         For example [[1, 2, 10, 20, 21, 40], [11, 12, 15, 55, 54, 41]] describes two
+    #         groups of coincident free borders, each group including two borders.
+    #  @param createPolygons if @c True faces adjacent to free borders are converted to
+    #         polygons if a node of opposite border falls on a face edge, else such
+    #         faces are split into several ones.
+    #  @param createPolyhedra if @c True volumes adjacent to free borders are converted to
+    #         polyhedra if a node of opposite border falls on a volume edge, else such
+    #         volumes, if any, remain intact and the mesh becomes non-conformal.
+    #  @return a number of successfully sewed groups
+    #  @ingroup l2_modif_trsf
+    def SewCoincidentFreeBorders (self, freeBorders, createPolygons=False, createPolyhedra=False):
+        if freeBorders and isinstance( freeBorders, list ):
+            # construct SMESH.CoincidentFreeBorders
+            if isinstance( freeBorders[0], int ):
+                freeBorders = [freeBorders]
+            borders = []
+            coincidentGroups = []
+            for nodeList in freeBorders:
+                if not nodeList or len( nodeList ) % 3:
+                    raise ValueError, "Wrong number of nodes in this group: %s" % nodeList
+                group = []
+                while nodeList:
+                    group.append  ( SMESH.FreeBorderPart( len(borders), 0, 1, 2 ))
+                    borders.append( SMESH.FreeBorder( nodeList[:3] ))
+                    nodeList = nodeList[3:]
+                    pass
+                coincidentGroups.append( group )
+                pass
+            freeBorders = SMESH.CoincidentFreeBorders( borders, coincidentGroups )
+
+        return self.editor.SewCoincidentFreeBorders( freeBorders, createPolygons, createPolyhedra )
+
     ## Sews free borders
     #  @return SMESH::Sew_Error
     #  @ingroup l2_modif_trsf
@@ -4417,11 +4637,12 @@ class Mesh:
     def ClearLastCreated(self):
         self.editor.ClearLastCreated()
 
-    ## Creates Duplicates given elements, i.e. creates new elements based on the 
+    ## Creates duplicates of given elements, i.e. creates new elements based on the 
     #  same nodes as the given ones.
     #  @param theElements - container of elements to duplicate. It can be a Mesh,
-    #         sub-mesh, group, filter or a list of element IDs.
-    # @param theGroupName - a name of group to contain the generated elements.
+    #         sub-mesh, group, filter or a list of element IDs. If \a theElements is
+    #         a Mesh, elements of highest dimension are duplicated
+    #  @param theGroupName - a name of group to contain the generated elements.
     #                    If a group with such a name already exists, the new elements
     #                    are added to the existng group, else a new group is created.
     #                    If \a theGroupName is empty, new elements are not added 
@@ -4623,6 +4844,7 @@ class Mesh:
 
     ## Returns value of a functor for a given element
     #  @param funcType an item of SMESH.FunctorType enum
+    #         Type "SMESH.FunctorType._items" in the Python Console to see all items.
     #  @param elemId element or node ID
     #  @param isElem @a elemId is ID of element or node
     #  @return the functor value or zero in case of invalid arguments
@@ -4736,6 +4958,8 @@ class Mesh:
         fun = self._getFunctor( funType )
         if fun:
             if meshPart:
+                if hasattr( meshPart, "SetMesh" ):
+                    meshPart.SetMesh( self.mesh ) # set mesh to filter
                 hist = fun.GetLocalHistogram( 1, False, meshPart )
             else:
                 hist = fun.GetHistogram( 1, False )
@@ -4745,7 +4969,25 @@ class Mesh:
 
     pass # end of Mesh class
 
-## class used to add to SMESH_MeshEditor methods removed from its CORBA API
+
+## class used to compensate change of CORBA API of SMESH_Mesh for backward compatibility
+#  with old dump scripts which call SMESH_Mesh directly and not via smeshBuilder.Mesh
+#
+class meshProxy(SMESH._objref_SMESH_Mesh):
+    def __init__(self):
+        SMESH._objref_SMESH_Mesh.__init__(self)
+    def __deepcopy__(self, memo=None):
+        new = self.__class__()
+        return new
+    def CreateDimGroup(self,*args): # 2 args added: nbCommonNodes, underlyingOnly
+        if len( args ) == 3:
+            args += SMESH.ALL_NODES, True
+        return SMESH._objref_SMESH_Mesh.CreateDimGroup( self, *args )
+    pass
+omniORB.registerObjref(SMESH._objref_SMESH_Mesh._NP_RepositoryId, meshProxy)
+
+## class used to compensate change of CORBA API of SMESH_MeshEditor for backward compatibility
+#  with old dump scripts which call SMESH_MeshEditor directly and not via smeshBuilder.Mesh
 #
 class meshEditor(SMESH._objref_SMESH_MeshEditor):
     def __init__(self):
@@ -4757,9 +4999,29 @@ class meshEditor(SMESH._objref_SMESH_MeshEditor):
         if hasattr( self.mesh, name ):
             return getattr( self.mesh, name )
         if name == "ExtrusionAlongPathObjX":
-            return getattr( self.mesh, "ExtrusionAlongPathX" )
-        print name, "NOT FOUND"
+            return getattr( self.mesh, "ExtrusionAlongPathX" ) # other method name
+        print "meshEditor: attribute '%s' NOT FOUND" % name
         return None
+    def __deepcopy__(self, memo=None):
+        new = self.__class__()
+        return new
+    def FindCoincidentNodes(self,*args): # a 2nd arg added (SeparateCornerAndMediumNodes)
+        if len( args ) == 1: args += False,
+        return SMESH._objref_SMESH_MeshEditor.FindCoincidentNodes( self, *args )
+    def FindCoincidentNodesOnPart(self,*args): # a 3d arg added (SeparateCornerAndMediumNodes)
+        if len( args ) == 2: args += False,
+        return SMESH._objref_SMESH_MeshEditor.FindCoincidentNodesOnPart( self, *args )
+    def MergeNodes(self,*args): # a 2nd arg added (NodesToKeep)
+        if len( args ) == 1:
+            return SMESH._objref_SMESH_MeshEditor.MergeNodes( self, args[0], [] )
+        NodesToKeep = args[1]
+        unRegister  = genObjUnRegister()
+        if NodesToKeep:
+            if isinstance( NodesToKeep, list ) and isinstance( NodesToKeep[0], int ):
+                NodesToKeep = self.MakeIDSource( NodesToKeep, SMESH.NODE )
+            if not isinstance( NodesToKeep, list ):
+                NodesToKeep = [ NodesToKeep ]
+        return SMESH._objref_SMESH_MeshEditor.MergeNodes( self, args[0], NodesToKeep )
     pass
 omniORB.registerObjref(SMESH._objref_SMESH_MeshEditor._NP_RepositoryId, meshEditor)
 
@@ -4767,6 +5029,13 @@ omniORB.registerObjref(SMESH._objref_SMESH_MeshEditor._NP_RepositoryId, meshEdit
 #
 class Pattern(SMESH._objref_SMESH_Pattern):
 
+    def LoadFromFile(self, patternTextOrFile ):
+        text = patternTextOrFile
+        if os.path.exists( text ):
+            text = open( patternTextOrFile ).read()
+            pass
+        return SMESH._objref_SMESH_Pattern.LoadFromFile( self, text )
+
     def ApplyToMeshFaces(self, theMesh, theFacesIDs, theNodeIndexOnKeyPoint1, theReverse):
         decrFun = lambda i: i-1
         theNodeIndexOnKeyPoint1,Parameters,hasVars = ParseParameters(theNodeIndexOnKeyPoint1, decrFun)
@@ -4779,6 +5048,11 @@ class Pattern(SMESH._objref_SMESH_Pattern):
         theMesh.SetParameters(Parameters)
         return SMESH._objref_SMESH_Pattern.ApplyToHexahedrons( self, theMesh, theVolumesIDs, theNode000Index, theNode001Index )
 
+    def MakeMesh(self, mesh, CreatePolygons=False, CreatePolyhedra=False):
+        if isinstance( mesh, Mesh ):
+            mesh = mesh.GetMesh()
+        return SMESH._objref_SMESH_Pattern.MakeMesh( self, mesh, CreatePolygons, CreatePolyhedra )
+
 # Registering the new proxy for Pattern
 omniORB.registerObjref(SMESH._objref_SMESH_Pattern._NP_RepositoryId, Pattern)
 
index ff601b47f476d27b8a3f735f716df7c3ce426559..a57b034633f9e65d9c1a8e809aece3bd0405a79f 100644 (file)
@@ -85,6 +85,7 @@ class Mesh_Algorithm:
                     attr = hypo_so_i.FindAttribute("AttributeIOR")[1]
                     if attr is not None:
                         anIOR = attr.Value()
+                        if not anIOR: continue # prevent exception in orb.string_to_object()
                         hypo_o_i = salome.orb.string_to_object(anIOR)
                         if hypo_o_i is not None:
                             # Check if this is a hypothesis
@@ -128,6 +129,7 @@ class Mesh_Algorithm:
                     attr = algo_so_i.FindAttribute("AttributeIOR")[1]
                     if attr is not None:
                         anIOR = attr.Value()
+                        if not anIOR: continue # prevent exception in orb.string_to_object()
                         algo_o_i = salome.orb.string_to_object(anIOR)
                         if algo_o_i is not None:
                             # Check if this is an algorithm
@@ -287,13 +289,11 @@ class Mesh_Algorithm:
         if not "ViscousLayers" in self.GetCompatibleHypothesis():
             raise TypeError, "ViscousLayers are not supported by %s"%self.algo.GetName()
         if faces and isinstance( faces[0], geomBuilder.GEOM._objref_GEOM_Object ):
-            import GEOM
             faceIDs = []
-            for f in faces:
-                if self.mesh.geompyD.ShapeIdToType( f.GetType() ) == "GROUP":
-                    faceIDs += f.GetSubShapeIndices()
-                else:
-                    faceIDs += [self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f)]
+            for shape in faces:
+                ff = self.mesh.geompyD.SubShapeAll( shape, self.mesh.geompyD.ShapeType["FACE"] )
+                for f in ff:
+                    faceIDs.append( self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f))
             faces = faceIDs
         hyp = self.Hypothesis("ViscousLayers",
                               [thickness, numberOfLayers, stretchFactor, faces, isFacesToIgnore],
@@ -325,7 +325,12 @@ class Mesh_Algorithm:
         if not "ViscousLayers2D" in self.GetCompatibleHypothesis():
             raise TypeError, "ViscousLayers2D are not supported by %s"%self.algo.GetName()
         if edges and isinstance( edges[0], geomBuilder.GEOM._objref_GEOM_Object ):
-            edges = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in edges ]
+            edgeIDs = []
+            for shape in edges:
+                ee = self.mesh.geompyD.SubShapeAll( shape, self.mesh.geompyD.ShapeType["EDGE"])
+                for e in ee:
+                    edgeIDs.append( self.mesh.geompyD.GetSubShapeID( self.mesh.geom, e ))
+            edges = edgeIDs
         hyp = self.Hypothesis("ViscousLayers2D",
                               [thickness, numberOfLayers, stretchFactor, edges, isEdgesToIgnore],
                               toAdd=False)
diff --git a/src/SMESH_SWIG/smesh_selection.py b/src/SMESH_SWIG/smesh_selection.py
new file mode 100644 (file)
index 0000000..a2c5257
--- /dev/null
@@ -0,0 +1,156 @@
+# Copyright (C) 2015  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
+#
+#  File   : smesh_selection.py
+#  Author : Roman NIKOLAEV, OPEN CASCADE ( roman.nikolaev@opencascade.com )
+#  Module : SMESH
+
+import salome
+salome.salome_init()
+
+import libSMESH_Swig
+sm_gui = libSMESH_Swig.SMESH_Swig()
+
+import SMESH, SALOMEDS
+from salome.smesh import smeshBuilder
+smesh =  smeshBuilder.New(salome.myStudy)
+
+import GEOM
+
+# swig -> idl
+_converter = { 
+    libSMESH_Swig.EdgeOfCell    :  None, # TODO: check how to process it
+    libSMESH_Swig.Node          :  SMESH.NODE,
+    libSMESH_Swig.Edge          :  SMESH.EDGE,
+    libSMESH_Swig.Face          :  SMESH.FACE,
+    libSMESH_Swig.Volume        :  SMESH.VOLUME,
+    libSMESH_Swig.Elem0D        :  SMESH.ELEM0D,
+    libSMESH_Swig.Ball          :  SMESH.BALL,
+    libSMESH_Swig.Cell          :  SMESH.ALL
+}
+
+# Converts swig to idl enumeration
+def _swig2idl( type ):
+    if _converter.has_key( type ) :
+        return _converter[type]
+    return None
+
+def _getEntry(mesh):
+    if isinstance( mesh, smeshBuilder.Mesh ) :
+        return salome.ObjectToID( mesh.GetMesh() )
+    else :
+        if isinstance( mesh, str ) :
+            return mesh
+    return None
+
+def _getMesh(mesh):
+    if isinstance( mesh, smeshBuilder.Mesh ) :
+        return mesh.GetMesh()
+    else :
+        if isinstance( mesh, str ) :
+            return salome.IDToObject( mesh )
+    return None
+
+def _getGeom(geom):
+    if isinstance( geom, GEOM._objref_GEOM_Object ) :
+        return geom
+    else :
+        if isinstance( geom, str ) :
+            return salome.IDToObject( geom )
+    return None
+
+
+# Selects an elements lst on the mesh
+def select( mesh, lst, append = False ) :
+    # Check mesh parameter
+    entry = _getEntry(mesh)   
+    if entry is None:
+        print "Wrong 'mesh' parameter"
+        return
+    
+    # Check lst parameter
+    tmp = []
+    if isinstance( lst, int ) :
+        tmp.append( lst )
+    else :
+        if isinstance( lst,list ) :
+            tmp = lst
+        else :
+            print "Wrong 'lst' parameter"
+            return
+    sm_gui.select( entry, tmp, append )
+
+
+def _preProcess(mesh) :
+    m = _getMesh(mesh);
+    if m is None:
+        print "Wrong 'mesh' parameter"
+        return [None, None]
+    
+    elemType = _swig2idl(sm_gui.getSelectionMode())
+    if elemType is None:
+        return [None, None]
+    return [m, elemType]
+
+
+
+# Selects an elements on the mesh inside the sphere with radius r and center (x, y, z)
+def selectInsideSphere( mesh, x, y, z, r, append = False ) :
+
+    [m, elemType] = _preProcess(mesh)
+    if m is None or elemType is None :
+        return
+    
+    l = smesh.GetInsideSphere( m, elemType, x, y, z, r )
+    if len(l) > 0:
+        select(mesh, l, append)
+
+# Selects an elements on the mesh inside the box
+def selectInsideBox( mesh, x1, y1, z1, x2, y2, z2 , append = False ) :    
+
+    [m, elemType] = _preProcess(mesh)
+    if m is None or elemType is None :
+        return
+
+    l = smesh.GetInsideBox( m, elemType, x1, y1, z1, x2, y2, z2 )
+    if len(l) > 0:
+        select(mesh, l, append)
+
+# Selects an elements on the mesh inside the cylinder
+def selectInsideCylinder( mesh, x, y, z, dx, dy, dz, h, r, append = False ) :
+
+    [m, elemType] = _preProcess(mesh)
+    if m is None or elemType is None :
+        return
+
+    l = smesh.GetInsideCylinder( m, elemType, x, y, z, dx, dy, dz, h, r )
+    if len(l) > 0:
+        select(mesh, l, append)
+
+# Selects an elements on the mesh inside the geometrical object
+def selectInside( mesh, geom, tolerance , append = False ):
+
+    [m, elemType] = _preProcess(mesh)
+    if m is None or elemType is None :
+        return    
+
+    g = _getGeom(geom)
+
+    l = smesh.GetInside( m, elemType, g ,tolerance )
+    if len(l) > 0:
+        select(mesh, l, append)
index 5bc176169602d557693edd62ad70e3d5cad21dd9..68aadb290e9778eef33c7ecc90faeb98ee6276e6 100644 (file)
@@ -35,6 +35,9 @@ INCLUDE_DIRECTORIES(
   ${Boost_INCLUDE_DIRS}
   ${CMAKE_CURRENT_SOURCE_DIR}
   ${PROJECT_SOURCE_DIR}/src/SMESHGUI
+  ${PROJECT_SOURCE_DIR}/src/OBJECT
+  ${PROJECT_SOURCE_DIR}/src/SMESHDS
+  ${PROJECT_SOURCE_DIR}/src/SMDS
   ${PROJECT_BINARY_DIR}/idl
 )
 
index 68d424c9e460a74867736be52fd8d6545c0b9b32..cb37aff4e65a958c841645a39c7490c9380ce8c8 100644 (file)
 //
 #include "libSMESH_Swig.h"
 
+
 #include <SMESHGUI.h>
 #include <SMESHGUI_Utils.h>
 #include <SMESHGUI_Displayer.h>
+#include <SMESHGUI_VTKUtils.h>
+#include <SMESH_Actor.h>
 
 // SALOME KERNEL includes
 #include <Utils_ORB_INIT.hxx>
 #include <SUIT_ViewManager.h>
 #include <SALOME_Prs.h>
 #include <SUIT_ViewWindow.h>
+#include <SVTK_ViewWindow.h>
 #include <VTKViewer_ViewModel.h>
 #include <SALOME_Event.h>
 #include <SalomeApp_Application.h>
+#include <LightApp_SelectionMgr.h>
+#include <SVTK_RenderWindowInteractor.h>
 
 // OCCT includes
 #include <TopAbs.hxx>
+#include <TColStd_MapOfInteger.hxx>
 
 // Qt includes
 #include <QApplication>
@@ -730,3 +737,112 @@ void SMESH_Swig::SetMeshIcon(const char* theMeshEntry,
                               theIsComputed,
                               isEmpty));
 }
+
+/*!
+  \brief Helper class for selection event.
+*/
+class TSelectListEvent: public SALOME_Event
+{
+  const char*       myId;
+  std::vector<int>  myIdsList;
+  bool              myIsAppend;
+
+public:
+  TSelectListEvent(const char* id, std::vector<int> ids, bool append) :
+    myId(id),
+    myIdsList(ids),
+    myIsAppend(append)
+  {}
+  virtual void Execute()
+  {
+    SMESHGUI* aSMESHGUI = SMESHGUI::GetSMESHGUI();
+    if( !aSMESHGUI ) 
+      return;
+    
+    LightApp_SelectionMgr* selMgr = SMESH::GetSelectionMgr( aSMESHGUI );
+    if( !selMgr )
+      return;
+    
+    selMgr->clearFilters();
+
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( aSMESHGUI );
+    if(!aViewWindow)
+      return;
+
+    SMESH_Actor* anActor = SMESH::FindActorByEntry( myId );
+    
+    if (!anActor || !anActor->hasIO())
+      return;
+    
+    Handle(SALOME_InteractiveObject) anIO = anActor->getIO();
+    SALOME_ListIO aList;
+    aList.Append(anIO);
+    selMgr->setSelectedObjects(aList, false);
+
+    if ( aViewWindow->SelectionMode() ==  ActorSelection ) {
+      return;
+    }
+        
+    TColStd_MapOfInteger aMap;
+    std::vector<int>::const_iterator anIter;
+    for (anIter = myIdsList.begin(); anIter != myIdsList.end(); ++anIter) {
+      aMap.Add(*anIter);
+    }
+
+    // Set new selection
+    SVTK_Selector* aSelector  = aViewWindow->GetSelector();
+    aSelector->AddOrRemoveIndex(anIO, aMap, myIsAppend);
+    aViewWindow->highlight( anIO, true, true );
+    aViewWindow->GetInteractor()->onEmitSelectionChanged();
+  }
+};
+
+/*!
+  \brief Select the elements on the mesh, sub-mesh or group.
+  \param id object entry
+  \param ids list of the element ids
+  \param mode selection mode
+*/
+void SMESH_Swig::select( const char* id, std::vector<int> ids, bool append ) {
+  ProcessVoidEvent( new TSelectListEvent( id, ids, append ) );
+}
+  
+/*!
+  \brief Select the elements on the mesh, sub-mesh or group.
+  \param id object entry
+  \param id id of the element
+  \param mode selection mode
+*/
+void SMESH_Swig::select( const char* id, int id1, bool append ) {
+  std::vector<int> ids;
+  ids.push_back( id1 );
+  ProcessVoidEvent( new TSelectListEvent( id, ids, append ) );
+}
+
+
+class TGetSelectionModeEvent : public SALOME_Event
+{
+public:
+  typedef int TResult;
+  TResult myResult;
+  TGetSelectionModeEvent() : myResult( -1 ) {}
+  virtual void Execute()
+  {
+    SMESHGUI* aSMESHGUI = SMESHGUI::GetSMESHGUI();
+    if( !aSMESHGUI ) 
+      return;
+
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( aSMESHGUI );
+    if(!aViewWindow)
+      return;
+    
+    myResult = aViewWindow->SelectionMode();
+  }
+};
+
+/*!
+  \brief Get selection mode of the active VTK View window.
+*/
+int SMESH_Swig::getSelectionMode() {
+  return ProcessEvent( new TGetSelectionModeEvent() );
+}
index 17b50f8820c442f2bbbdc10fdfcffecebb21f49a..8c30149e9def6b85b28d3f3d99989e2053e63a18 100644 (file)
 #include <SALOMEconfig.h>
 #include CORBA_SERVER_HEADER(SALOMEDS)
 
+//std includes
+#include <vector>
+
+#include <SVTK_Selection.h>
+
+#include <SVTK_Selection.h>
+
+enum
+  {
+    Node       = NodeSelection,
+    Cell       = CellSelection,
+    EdgeOfCell = EdgeOfCellSelection,
+    Edge       = EdgeSelection,
+    Face       = FaceSelection,
+    Volume     = VolumeSelection,
+    Actor      = ActorSelection,
+    Elem0D     = Elem0DSelection,
+    Ball       = BallSelection
+  };
+
 class SMESH_SWIG_EXPORT SMESH_Swig
 {
 public:
@@ -74,6 +94,11 @@ public:
    */
   void                       SetMeshIcon( const char*, const bool, const bool );
 
+  // --------------------- for the test purposes -----------------------
+  int  getSelectionMode();
+  void select( const char *id, std::vector<int> ids, bool append = false );
+  void select( const char *id, int id1, bool append = false );
+
 private:
   SALOMEDS::Study_var        myStudy;
   SALOMEDS::StudyBuilder_var myStudyBuilder;
index 8c414fc0d0b1df8b63ba4f54c545e340e82c464f..227008b3b7cc577265519a1f756ce2bb9cdfab4d 100644 (file)
 }
 
 %include "typemaps.i"
+%include "std_vector.i"
+
+namespace std {
+    %template(VectorInt) vector<int>;
+};
+
+
+/* Selection mode enumeration (corresponds to constants from the SALOME_Selection.h) */
+enum
+  {
+    Node,
+    Cell,
+    EdgeOfCell,
+    Edge,
+    Face,
+    Volume,
+    Actor,
+    Elem0D,
+    Ball
+  };
 
 class SMESH_Swig
 {
@@ -76,4 +96,10 @@ class SMESH_Swig
 
   void CreateAndDisplayActor( const char* Mesh_Entry );
   void EraseActor( const char* Mesh_Entry, const bool allViewers = false );
+
+  // --------------------- for the test purposes -----------------------
+  int  getSelectionMode();
+  void select( const char *id, std::vector<int> ids, bool append = false );
+  void select( const char *id, int id1, bool append = false );
+
 };
index 8714c1b4f5e983d8abc7340790998f364b366c8b..05af0db649eb9c848b2c21650ca2e10dcb1316be 100644 (file)
@@ -131,6 +131,7 @@ SET(StdMeshers_HEADERS
   StdMeshers_CartesianParameters3D.hxx
   StdMeshers_Cartesian_3D.hxx
   StdMeshers_QuadFromMedialAxis_1D2D.hxx
+  StdMeshers_PolygonPerFace_2D.hxx
 )
 
 IF(SALOME_SMESH_ENABLE_MEFISTO)
@@ -195,6 +196,7 @@ SET(StdMeshers_SOURCES
   StdMeshers_Cartesian_3D.cxx
   StdMeshers_Adaptive1D.cxx
   StdMeshers_QuadFromMedialAxis_1D2D.cxx
+  StdMeshers_PolygonPerFace_2D.cxx
 )
 
 IF(SALOME_SMESH_ENABLE_MEFISTO)
index 45e22ebb3fc23e654e35e05b63b96608f974025a..946c200df7c2343ba9436b324580d40fb3dba664 100644 (file)
@@ -1260,7 +1260,7 @@ bool AdaptiveAlgo::Compute(SMESH_Mesh &         theMesh,
         double maxSegSize = 0;
 
         // get points to check distance to the face
-        EdgeData::TPntIter pIt2 = eData.myPoints.begin(), pIt1 = pIt2++;
+        EdgeData::TPntIter pIt2 = eData.myPoints.begin(), pIt1 = pIt2++, pItLast;
         maxSegSize = pIt1->mySegSize = Min( pIt1->mySegSize, sizeTree.GetSize( pIt1->myP ));
         for ( ; pIt2 != eData.myPoints.end(); )
         {
@@ -1290,6 +1290,7 @@ bool AdaptiveAlgo::Compute(SMESH_Mesh &         theMesh,
         //cout << "E " << theMesh.GetMeshDS()->ShapeToIndex( eData.Edge() ) << endl;
         sizeDecreased = false;
         const gp_Pnt* avoidPnt = & eData.First().myP;
+        pItLast = --eData.myPoints.end();
         for ( pIt1 = eData.myPoints.begin(); pIt1 != eData.myPoints.end();  )
         {
           double distToFace =
@@ -1316,7 +1317,7 @@ bool AdaptiveAlgo::Compute(SMESH_Mesh &         theMesh,
             pIt1->mySegSize = allowedSize;
           }
           ++pIt1;
-          if ( & (*pIt1) == & eData.Last() )
+          if ( pIt1 == pItLast )
             avoidPnt = & eData.Last().myP;
           else
             avoidPnt = NULL;
index f6d9a2f4e7d5dc139802d481fa91f9e7be6e6dc9..7c9dca548a82d1b0f12bd63bec0590e07ca3ecf1 100644 (file)
@@ -41,6 +41,7 @@
 #include <Standard_ErrorHandler.hxx>
 #include <Standard_Failure.hxx>
 #include <TopExp_Explorer.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
 #include <TopTools_MapIteratorOfMapOfShape.hxx>
 #include <TopTools_MapOfShape.hxx>
 #include <TopTools_SequenceOfShape.hxx>
@@ -105,6 +106,7 @@ public:
   const _FaceSide* GetSide(const int i) const;
   int size() const { return myChildren.size(); }
   int NbVertices() const;
+  int NbCommonVertices( const TopTools_MapOfShape& VV ) const;
   TopoDS_Vertex FirstVertex() const;
   TopoDS_Vertex LastVertex() const;
   TopoDS_Vertex Vertex(int i) const;
@@ -145,10 +147,10 @@ public:
 public: //** Methods to find and orient faces of 6 sides of the box **//
   
   //!< initialization
-  bool Init(const TopoDS_Face& f);
+  bool Init(const TopoDS_Face& f, SMESH_Mesh& mesh );
 
   //!< try to unite self with other face
-  bool AddContinuousFace( const _QuadFaceGrid& f );
+  bool AddContinuousFace( const _QuadFaceGrid& f, const TopTools_MapOfShape& internalEdges );
 
   //!< Try to set the side as bottom hirizontal side
   bool SetBottomSide(const _FaceSide& side, int* sideIndex=0);
@@ -276,6 +278,175 @@ bool StdMeshers_CompositeHexa_3D::CheckHypothesis(SMESH_Mesh&         aMesh,
   return true;
 }
 
+namespace
+{
+
+  //================================================================================
+  /*!
+   * \brief Checks structure of a quadrangular mesh at the common VERTEX of two EDGEs.
+   *        Returns true if there are two quadrangles near the VERTEX.
+   */
+  //================================================================================
+
+  bool isContinuousMesh(TopoDS_Edge        E1,
+                        TopoDS_Edge        E2,
+                        const TopoDS_Face& F,
+                        const SMESH_Mesh&  mesh)
+  {
+    if (E1.Orientation() > TopAbs_REVERSED) // INTERNAL
+      E1.Orientation( TopAbs_FORWARD );
+    if (E2.Orientation() > TopAbs_REVERSED) // INTERNAL
+      E2.Orientation( TopAbs_FORWARD );
+
+    TopoDS_Vertex V;
+    if ( !TopExp::CommonVertex( E1, E2, V )) return false;
+
+    const SMDS_MeshNode* n = SMESH_Algo::VertexNode( V, mesh.GetMeshDS() );
+    if ( !n ) return false;
+
+    SMESHDS_SubMesh* sm = mesh.GetSubMeshContaining( F )->GetSubMeshDS();
+    if ( !sm ) return false;
+
+    int nbQuads = 0;
+    SMDS_ElemIteratorPtr fIt = n->GetInverseElementIterator(SMDSAbs_Face);
+    while ( fIt->more() )
+    {
+      const SMDS_MeshElement* f = fIt->next();
+      if ( !sm->Contains( f )) continue;
+
+      if ( f->NbCornerNodes() == 4 )
+        ++nbQuads;
+      else
+        return false;
+    }
+    return nbQuads == 2;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Finds VERTEXes located at block corners
+   */
+  //================================================================================
+
+  void getBlockCorners( SMESH_Mesh&          mesh,
+                        const TopoDS_Shape&  shape,
+                        TopTools_MapOfShape& cornerVV)
+  {
+    set<int> faceIDs; // ids of FACEs in the shape
+    TopExp_Explorer exp;
+    for ( exp.Init( shape, TopAbs_FACE ); exp.More(); exp.Next() )
+      faceIDs.insert( mesh.GetMeshDS()->ShapeToIndex( exp.Current() ));
+
+    TopTools_MapOfShape checkedVV;
+    for ( exp.Init( shape, TopAbs_VERTEX ); exp.More(); exp.Next() )
+    {
+      TopoDS_Vertex V = TopoDS::Vertex( exp.Current() );
+      if ( !checkedVV.Add( V )) continue;
+
+      const SMDS_MeshNode* n = SMESH_Algo::VertexNode( V, mesh.GetMeshDS() );
+      if ( !n ) continue;
+
+      int nbQuads = 0;
+      SMDS_ElemIteratorPtr fIt = n->GetInverseElementIterator(SMDSAbs_Face);
+      while ( fIt->more() )
+      {
+        const SMDS_MeshElement* f = fIt->next();
+        if ( !faceIDs.count( f->getshapeId() )) continue;
+
+        if ( f->NbCornerNodes() == 4 )
+          ++nbQuads;
+        else
+          nbQuads = 100;
+      }
+      if ( nbQuads == 3 )
+        cornerVV.Add( V );
+    }
+  }
+
+  //================================================================================
+  /*!
+   * \brief Return EDGEs dividing one box side
+   */
+  //================================================================================
+
+  bool getInternalEdges( SMESH_Mesh&                mesh,
+                         const TopoDS_Shape&        shape,
+                         const TopTools_MapOfShape& cornerVV,
+                         TopTools_MapOfShape&       internEE)
+  {
+    TopTools_IndexedMapOfShape subEE, subFF;
+    TopExp::MapShapes( shape, TopAbs_EDGE, subEE );
+    TopExp::MapShapes( shape, TopAbs_FACE, subFF );
+
+    TopoDS_Vertex VV[2];
+    TopTools_MapOfShape subChecked/*, ridgeEE*/;
+    TopTools_MapIteratorOfMapOfShape vIt( cornerVV );
+    for ( ; vIt.More(); vIt.Next() )
+    {
+      TopoDS_Shape V0 = vIt.Key();
+      // walk from one corner VERTEX to another along ridge EDGEs
+      PShapeIteratorPtr riIt = SMESH_MesherHelper::GetAncestors( V0, mesh, TopAbs_EDGE );
+      while ( const TopoDS_Shape* riE = riIt->next() )
+      {
+        if ( !subEE.Contains( *riE ) || !subChecked.Add( *riE ))
+          continue;
+        TopoDS_Edge ridgeE = TopoDS::Edge( *riE );
+        while ( !ridgeE.IsNull() )
+        {
+          TopExp::Vertices( ridgeE, VV[0], VV[1] );
+          TopoDS_Shape V1 = VV[ V0.IsSame( VV[0] )];
+          if ( cornerVV.Contains( V1 ) )
+            break; // ridgeE reached a corner VERTEX
+
+          // detect internal EDGEs among those sharing V1. There can be 2, 3 or 4 EDGEs and
+          // number of internal EDGEs is N-2
+          TopoDS_Shape nextRidgeE;
+          PShapeIteratorPtr eIt = SMESH_MesherHelper::GetAncestors( V1, mesh, TopAbs_EDGE );
+          while ( const TopoDS_Shape* E = eIt->next() )
+          {
+            if ( E->IsSame( ridgeE ) || !subEE.Contains( *E ) || !subChecked.Add( *E ))
+              continue;
+            // look for FACEs sharing both E and ridgeE
+            PShapeIteratorPtr fIt = SMESH_MesherHelper::GetAncestors( *E, mesh, TopAbs_FACE );
+            while ( const TopoDS_Shape* F = fIt->next() )
+            {
+              if ( !SMESH_MesherHelper::IsSubShape( ridgeE, *F ))
+                continue;
+              if ( isContinuousMesh( ridgeE, TopoDS::Edge( *E ), TopoDS::Face( *F ), mesh ))
+              {
+                nextRidgeE = *E;
+              }
+              else
+              {
+                internEE.Add( *E );
+              }
+              break;
+            }
+          }
+          // look for the next ridge EDGE ending at V1
+          if ( nextRidgeE.IsNull() )
+          {
+            eIt = SMESH_MesherHelper::GetAncestors( V1, mesh, TopAbs_EDGE );
+            while ( const TopoDS_Shape* E = eIt->next() )
+              if ( !ridgeE.IsSame( *E ) && !internEE.Contains( *E ) && subEE.Contains( *E ))
+              {
+                nextRidgeE = *E;
+                break;
+              }
+          }
+          ridgeE = TopoDS::Edge( nextRidgeE );
+          V0 = V1;
+
+          if ( ridgeE.IsNull() )
+            return false;
+        } // check EDGEs around the last VERTEX of ridgeE 
+      } // loop on ridge EDGEs around a corner VERTEX
+    } // loop on on corner VERTEXes
+
+    return true;
+  } // getInternalEdges()
+} // namespace
+
 //================================================================================
 /*!
  * \brief Tries to find 6 sides of a box
@@ -284,6 +455,7 @@ bool StdMeshers_CompositeHexa_3D::CheckHypothesis(SMESH_Mesh&         aMesh,
 
 bool StdMeshers_CompositeHexa_3D::findBoxFaces( const TopoDS_Shape&    shape,
                                                 list< _QuadFaceGrid >& boxFaces,
+                                                SMESH_Mesh&            mesh,
                                                 _QuadFaceGrid * &      fBottom,
                                                 _QuadFaceGrid * &      fTop,
                                                 _QuadFaceGrid * &      fFront,
@@ -291,27 +463,35 @@ bool StdMeshers_CompositeHexa_3D::findBoxFaces( const TopoDS_Shape&    shape,
                                                 _QuadFaceGrid * &      fLeft,
                                                 _QuadFaceGrid * &      fRight)
 {
+  TopTools_MapOfShape cornerVertices;
+  getBlockCorners( mesh, shape, cornerVertices );
+  if ( cornerVertices.Extent() != 8 )
+    return error( COMPERR_BAD_INPUT_MESH, "Can't find 8 corners of a block by 2D mesh" );
+  TopTools_MapOfShape internalEdges;
+  if ( !getInternalEdges( mesh, shape, cornerVertices, internalEdges ))
+    return error( COMPERR_BAD_INPUT_MESH, "2D mesh is not suitable for i,j,k hexa meshing" );
+
   list< _QuadFaceGrid >::iterator boxFace;
   TopExp_Explorer exp;
   int nbFaces = 0;
-  for ( exp.Init( shape, TopAbs_FACE); exp.More(); exp.Next(), ++nbFaces )
+  for ( exp.Init( shape, TopAbs_FACE ); exp.More(); exp.Next(), ++nbFaces )
   {
     _QuadFaceGrid f;
-    if ( !f.Init( TopoDS::Face( exp.Current() )))
+    if ( !f.Init( TopoDS::Face( exp.Current() ), mesh ))
       return error (COMPERR_BAD_SHAPE);
 
-    _QuadFaceGrid* prevContinuous = 0; 
+    _QuadFaceGrid* prevContinuous = 0;
     for ( boxFace = boxFaces.begin(); boxFace != boxFaces.end(); ++boxFace )
     {
       if ( prevContinuous )
       {
-        if ( prevContinuous->AddContinuousFace( *boxFace ))
+        if ( prevContinuous->AddContinuousFace( *boxFace, internalEdges ))
           boxFace = --boxFaces.erase( boxFace );
       }
-      else if ( boxFace->AddContinuousFace( f ))
+      else if ( boxFace->AddContinuousFace( f, internalEdges ))
       {
         prevContinuous = & (*boxFace);
-      }   
+      }
     }
     if ( !prevContinuous )
       boxFaces.push_back( f );
@@ -326,7 +506,7 @@ bool StdMeshers_CompositeHexa_3D::findBoxFaces( const TopoDS_Shape&    shape,
     boxFaces.resize( 6 );
     boxFace = boxFaces.begin();
     for ( exp.Init( shape, TopAbs_FACE); exp.More(); exp.Next(), ++boxFace )
-      boxFace->Init( TopoDS::Face( exp.Current() ) );
+      boxFace->Init( TopoDS::Face( exp.Current() ), mesh );
   }
   // ----------------------------------------
   // Find out position of faces within a box
@@ -396,7 +576,7 @@ bool StdMeshers_CompositeHexa_3D::Compute(SMESH_Mesh&         theMesh,
   // -------------------------
   list< _QuadFaceGrid > boxFaceContainer;
   _QuadFaceGrid *fBottom, *fTop, *fFront, *fBack, *fLeft, *fRight;
-  if ( ! findBoxFaces( theShape, boxFaceContainer,
+  if ( ! findBoxFaces( theShape, boxFaceContainer, theMesh,
                        fBottom, fTop, fFront, fBack, fLeft, fRight))
     return false;
 
@@ -559,7 +739,7 @@ bool StdMeshers_CompositeHexa_3D::Evaluate(SMESH_Mesh&         theMesh,
   // -------------------------
   list< _QuadFaceGrid > boxFaceContainer;
   _QuadFaceGrid *fBottom, *fTop, *fFront, *fBack, *fLeft, *fRight;
-  if ( ! findBoxFaces( theShape, boxFaceContainer,
+  if ( ! findBoxFaces( theShape, boxFaceContainer, theMesh,
                        fBottom, fTop, fFront, fBack, fLeft, fRight))
     return false;
 
@@ -645,7 +825,7 @@ _QuadFaceGrid::_QuadFaceGrid():
  */
 //================================================================================
 
-bool _QuadFaceGrid::Init(const TopoDS_Face& f)
+bool _QuadFaceGrid::Init(const TopoDS_Face& f, SMESH_Mesh& mesh)
 {
   myFace         = f;
   mySides        = _FaceSide();
@@ -680,6 +860,12 @@ bool _QuadFaceGrid::Init(const TopoDS_Face& f)
         else if ( SMESH_Algo::IsContinuous( sideEdges.front(), edges.back() )) {
           sideEdges.splice( sideEdges.begin(), edges, --edges.end());
         }
+        else if ( isContinuousMesh( sideEdges.back(), edges.front(), f, mesh )) {
+          sideEdges.splice( sideEdges.end(), edges, edges.begin());
+        }
+        else if ( isContinuousMesh( sideEdges.front(), edges.back(), f, mesh )) {
+          sideEdges.splice( sideEdges.begin(), edges, --edges.end());
+        }
         else {
           break;
         }
@@ -706,30 +892,17 @@ bool _QuadFaceGrid::Init(const TopoDS_Face& f)
  */
 //================================================================================
 
-bool _QuadFaceGrid::AddContinuousFace( const _QuadFaceGrid& other )
+bool _QuadFaceGrid::AddContinuousFace( const _QuadFaceGrid&       other,
+                                       const TopTools_MapOfShape& internalEdges)
 {
   for ( int i = 0; i < 4; ++i )
   {
     const _FaceSide& otherSide = other.GetSide( i );
     int iMyCommon;
-    if ( mySides.Contain( otherSide, &iMyCommon ) ) {
-      // check if normals of two faces are collinear at all vertices of an otherSide
-      const double angleTol = M_PI / 180. / 2.;
-      int iV, nbV = otherSide.NbVertices(), nbCollinear = 0;
-      for ( iV = 0; iV < nbV; ++iV )
+    if ( mySides.Contain( otherSide, &iMyCommon ) )
+    {
+      if ( internalEdges.Contains( otherSide.Edge( 0 )))
       {
-        TopoDS_Vertex v = otherSide.Vertex( iV );
-        gp_Vec n1, n2;
-        if ( !GetNormal( v, n1 ) || !other.GetNormal( v, n2 ))
-          continue;
-        if ( n1 * n2 < 0 )
-          n1.Reverse();
-        if ( n1.Angle(n2) < angleTol )
-          nbCollinear++;
-        else
-          break;
-      }
-      if ( nbCollinear > 1 ) { // this face becomes composite if not yet is
         DUMP_VERT("Cont 1", mySides.GetSide(iMyCommon)->FirstVertex());
         DUMP_VERT("Cont 2", mySides.GetSide(iMyCommon)->LastVertex());
         DUMP_VERT("Cont 3", otherSide.FirstVertex());
@@ -942,9 +1115,9 @@ bool _QuadFaceGrid::LoadGrid( SMESH_Mesh& mesh )
 
   // store the rest nodes row by row
 
-  const SMDS_MeshNode* dummy = mesh.GetMeshDS()->AddNode(0,0,0);
-  const SMDS_MeshElement* firstQuad = dummy; // most left face above the last row of found nodes
-  
+  TIDSortedElemSet emptySet, avoidSet;
+  const SMDS_MeshElement* firstQuad = 0; // most left face above the last row of found nodes
+
   int nbFoundNodes = myIndexer._xSize;
   while ( nbFoundNodes != myGrid.size() )
   {
@@ -961,8 +1134,6 @@ bool _QuadFaceGrid::LoadGrid( SMESH_Mesh& mesh )
     //     o---o  o  o  o  o
     //n1down    n2down
     //
-    TIDSortedElemSet emptySet, avoidSet;
-    avoidSet.insert( firstQuad );
     firstQuad = SMESH_MeshAlgos::FindFaceInSet( n1down, n2down, emptySet, avoidSet);
     while ( firstQuad && !faceSubMesh->Contains( firstQuad )) {
       avoidSet.insert( firstQuad );
@@ -1009,8 +1180,8 @@ bool _QuadFaceGrid::LoadGrid( SMESH_Mesh& mesh )
       n1down = myGrid[ nbFoundNodes - myIndexer._xSize - 1 ];
       n1up   = n2up;
     }
+    avoidSet.clear(); avoidSet.insert( firstQuad );
   }
-  mesh.GetMeshDS()->RemoveNode(dummy);
   DumpGrid(); // debug
 
   return true;
@@ -1471,9 +1642,24 @@ int _FaceSide::NbVertices() const
   return myNbChildren + 1;
 }
 
+//=======================================================================
+//function : NbCommonVertices
+//purpose  : Returns number of my vertices common with the given ones
+//=======================================================================
+
+int _FaceSide::NbCommonVertices( const TopTools_MapOfShape& VV ) const
+{
+  int nbCommon = 0;
+  TopTools_MapIteratorOfMapOfShape vIt ( myVertices );
+  for ( ; vIt.More(); vIt.Next() )
+    nbCommon += ( VV.Contains( vIt.Key() ));
+
+  return nbCommon;
+}
+
 //=======================================================================
 //function : FirstVertex
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 TopoDS_Vertex _FaceSide::FirstVertex() const
index 9f40c2e35628c535f2d73e986b57d54e22ee4a43..5545f781a7ff9655a4e5f882176ca84cefde6780 100644 (file)
@@ -59,6 +59,7 @@ private:
 
   bool findBoxFaces( const TopoDS_Shape&    shape,
                      list< _QuadFaceGrid >& boxFaceContainer,
+                     SMESH_Mesh&            mesh,
                      _QuadFaceGrid * &      fBottom,
                      _QuadFaceGrid * &      fTop,
                      _QuadFaceGrid * &      fFront,
index e474f5bf7f671fbbd5dcd8087bf8b6bdc2f52bff..2625b9fb1322eab64c256b743d3c76a64c076069 100644 (file)
@@ -79,8 +79,6 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&   theFace,
 //================================================================================
 /*!
  * \brief Constructor of a side of several edges
-  * \param theFace - the face
-  * \param theEdge - the edge
  */
 //================================================================================
 
@@ -101,6 +99,7 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&   theFace,
   myNormPar.resize   ( nbEdges );
   myEdgeLength.resize( nbEdges );
   myIsUniform.resize ( nbEdges, true );
+  myFace               = theFace;
   myLength             = 0;
   myNbPonits           = myNbSegments = 0;
   myProxyMesh          = theProxyMesh;
@@ -114,14 +113,13 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&   theFace,
 
   int nbDegen = 0;
   list<TopoDS_Edge>::iterator edge = theEdges.begin();
-  TopoDS_Iterator vExp;
   for ( int index = 0; edge != theEdges.end(); ++index, ++edge )
   {
     int i = theIsForward ? index : nbEdges-index-1;
     myEdgeLength[i] = SMESH_Algo::EdgeLength( *edge );
     if ( myEdgeLength[i] < DBL_MIN ) nbDegen++;
     myLength += myEdgeLength[i];
-    myEdge[i] = *edge;
+    myEdge  [i] = *edge;
     myEdgeID[i] = meshDS->ShapeToIndex( *edge );
     if ( !theIsForward ) myEdge[i].Reverse();
 
@@ -132,34 +130,16 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&   theFace,
     if ( myEdge[i].Orientation() == TopAbs_REVERSED )
       std::swap( myFirst[i], myLast[i] );
 
-    if ( const SMESHDS_SubMesh* sm = myProxyMesh->GetSubMesh( *edge )) {
-      int nbN = sm->NbNodes();
-      if ( theIgnoreMediumNodes ) {
-        SMDS_ElemIteratorPtr elemIt = sm->GetElements();
-        if ( elemIt->more() && elemIt->next()->IsQuadratic() )
-          nbN -= sm->NbElements();
-      }
-      myNbPonits += nbN;
-      myNbSegments += sm->NbElements();
-    }
-
-    // TopExp::FirstVertex() and TopExp::LastVertex() return NULL from INTERNAL edge
-    vExp.Initialize( *edge );
-    if ( vExp.Value().Orientation() == TopAbs_REVERSED ) vExp.Next();
-    if ( SMESH_Algo::VertexNode( TopoDS::Vertex( vExp.Value()), meshDS ))
-      myNbPonits += 1; // for the first end
-    else
-      myMissingVertexNodes = true;
-
     // check if the edge has a non-uniform parametrization (issue 0020705)
     if ( !myC2d[i].IsNull() )
     {
-      if ( myEdgeLength[i] > DBL_MIN)
+      if ( myEdgeLength[i] > DBL_MIN )
       {
         Geom2dAdaptor_Curve A2dC( myC2d[i],
                                   std::min( myFirst[i], myLast[i] ),
                                   std::max( myFirst[i], myLast[i] ));
-        double p2 = myFirst[i]+(myLast[i]-myFirst[i])/2., p4 = myFirst[i]+(myLast[i]-myFirst[i])/4.;
+        double p2 = myFirst[i]+(myLast[i]-myFirst[i])/2.;
+        double p4 = myFirst[i]+(myLast[i]-myFirst[i])/4.;
         double d2 = GCPnts_AbscissaPoint::Length( A2dC, myFirst[i], p2 );
         double d4 = GCPnts_AbscissaPoint::Length( A2dC, myFirst[i], p4 );
         //cout<<"len = "<<len<<"  d2 = "<<d2<<"  fabs(2*d2/len-1.0) = "<<fabs(2*d2/len-1.0)<<endl;
@@ -169,26 +149,20 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&   theFace,
       }
       else
       {
-        const TopoDS_Vertex& V = TopoDS::Vertex( vExp.Value() );
+        const TopoDS_Vertex& V = SMESH_MesherHelper::IthVertex( 0, *edge );
         Handle(Geom_Curve) C3d = new Geom_Line( BRep_Tool::Pnt( V ), gp::DX() );
         myC3dAdaptor[i].Load( C3d, 0, 0.5 * BRep_Tool::Tolerance( V ));
       }
     }
-    // reverse a proxy submesh
+    // reverse a proxy sub-mesh
     if ( !theIsForward )
       reverseProxySubmesh( myEdge[i] );
 
   } // loop on edges
 
-  vExp.Initialize( theEdges.back() );
-  if ( vExp.Value().Orientation() != TopAbs_REVERSED ) vExp.Next();
-  if ( vExp.More() )
-  {
-    if ( SMESH_Algo::VertexNode( TopoDS::Vertex( vExp.Value()), meshDS ))
-      myNbPonits++; // for the last end
-    else
-      myMissingVertexNodes = true;
-  }
+  // count nodes and segments
+  NbPoints( /*update=*/true );
+
   if ( nbEdges > 1 && myLength > DBL_MIN ) {
     const double degenNormLen = 1.e-5;
     double totLength = myLength;
@@ -209,8 +183,6 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face&   theFace,
 //================================================================================
 /*!
  * \brief Constructor of a side for vertex using data from other FaceSide
- *  \param theVertex - the vertex
- *  \param theSide - the side
  */
 //================================================================================
 
@@ -271,6 +243,7 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(UVPtStructVec&     theSideNodes,
   myMissingVertexNodes = myIgnoreMediumNodes = false;
   myDefaultPnt2d.SetCoord( 1e100, 1e100 );
 
+  myFace       = theFace;
   myPoints     = theSideNodes;
   myNbPonits   = myPoints.size();
   myNbSegments = myNbPonits + 1;
@@ -332,21 +305,29 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(UVPtStructVec&     theSideNodes,
 const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
                                                              double constValue) const
 {
-  if ( myPoints.empty() ) {
-
+  if ( myPoints.empty() )
+  {
     if ( NbEdges() == 0 ) return myPoints;
 
-    SMESHDS_Mesh* meshDS = myProxyMesh->GetMeshDS();
-    SMESH_MesherHelper helper(*myProxyMesh->GetMesh());
+    StdMeshers_FaceSide* me = const_cast< StdMeshers_FaceSide* >( this );
+    SMESHDS_Mesh*    meshDS = myProxyMesh->GetMeshDS();
+    SMESH_MesherHelper eHelper( *myProxyMesh->GetMesh() );
+    SMESH_MesherHelper fHelper( *myProxyMesh->GetMesh() );
+    fHelper.SetSubShape( myFace );
     bool paramOK;
     double eps = 1e-100;
 
     // sort nodes of all edges putting them into a map
 
-    map< double, const SMDS_MeshNode*> u2node;
-    vector< const SMESH_ProxyMesh::SubMesh* > proxySubMesh( myEdge.size());
+    map< double, const SMDS_MeshNode*>            u2node;
+    vector< pair< double, const SMDS_MeshNode*> > u2nodeVec;
+    vector<const SMDS_MeshNode*>                  nodes;
+    set<const SMDS_MeshNode*>                     vertexNodes;
+    vector< const SMESH_ProxyMesh::SubMesh* >     proxySubMesh( myEdge.size() );
     int nbProxyNodes = 0;
-    for ( size_t iE = 0; iE < myEdge.size(); ++iE )
+    size_t iE;
+
+    for ( iE = 0; iE < myEdge.size(); ++iE )
     {
       proxySubMesh[iE] = myProxyMesh->GetProxySubMesh( myEdge[iE] );
       if ( proxySubMesh[iE] )
@@ -361,74 +342,91 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
           continue;
         }
       }
-      // Put 1st vertex node of a current edge
-      TopoDS_Vertex VV[2]; // TopExp::FirstVertex() returns NULL for INTERNAL edge
-      VV[0] = SMESH_MesherHelper::IthVertex( 0, myEdge[iE]);
-      VV[1] = SMESH_MesherHelper::IthVertex( 1, myEdge[iE]);
-      const SMDS_MeshNode* node = SMESH_Algo::VertexNode( VV[0], meshDS );
-      double prevNormPar = ( iE == 0 ? 0 : myNormPar[ iE-1 ]); // normalized param
-      if ( node ) { // nodes on internal vertices may be missing
-        u2node.insert( u2node.end(), make_pair( prevNormPar, node ));
+
+      // Add 1st vertex node of a current edge
+      const SMDS_MeshNode* node = VertexNode( iE );
+      const double  prevNormPar = ( iE == 0 ? 0 : myNormPar[ iE-1 ]); // normalized param
+      if ( node ) // nodes on internal vertices may be missing
+      {
+        if ( vertexNodes.insert( node ).second ||
+             fHelper.IsRealSeam  ( node->getshapeId() ) ||
+             fHelper.IsDegenShape( node->getshapeId() ))
+          u2node.insert( u2node.end(), make_pair( prevNormPar, node ));
       }
-      else if ( iE == 0 ) {
-        MESSAGE(" NO NODE on VERTEX" );
-        return myPoints;
+      else if ( iE == 0 )
+      {
+        for ( ++iE; iE < myEdge.size(); ++iE )
+          if (( node = VertexNode( iE ))) {
+            u2node.insert( make_pair( prevNormPar, node ));
+            break;
+          }
+        --iE;
+
+        if ( !node )
+          return myPoints;
+        vertexNodes.insert( node );
       }
 
-      // Put internal nodes
-      if ( const SMESHDS_SubMesh* sm = myProxyMesh->GetSubMesh( myEdge[iE] ))
+      // Add internal nodes
+      nodes.clear();
+      if ( !GetEdgeNodes( iE, nodes, /*v0=*/false, /*v1=*/false ))
+        return myPoints;
+      if ( !nodes.empty() )
       {
-        vector< pair< double, const SMDS_MeshNode*> > u2nodeVec;
-        u2nodeVec.reserve( sm->NbNodes() );
-        SMDS_NodeIteratorPtr nItr = sm->GetNodes();
+        u2nodeVec.clear();
         double paramSize = myLast[iE] - myFirst[iE];
         double r         = myNormPar[iE] - prevNormPar;
-        helper.SetSubShape( myEdge[iE] );
-        helper.ToFixNodeParameters( true );
+        eHelper.SetSubShape( myEdge[iE] );
+        eHelper.ToFixNodeParameters( true );
         if ( !myIsUniform[iE] )
-          while ( nItr->more() )
+          for ( size_t i = 0; i < nodes.size(); ++i )
           {
-            const SMDS_MeshNode* node = nItr->next();
-            if ( myIgnoreMediumNodes && SMESH_MeshEditor::IsMedium( node, SMDSAbs_Edge ))
-              continue;
-            double u = helper.GetNodeU( myEdge[iE], node, 0, &paramOK );
-            double aLenU = GCPnts_AbscissaPoint::Length
-              ( const_cast<GeomAdaptor_Curve&>( myC3dAdaptor[iE]), myFirst[iE], u );
+            double     u = eHelper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK );
+            double aLenU = GCPnts_AbscissaPoint::Length( me->myC3dAdaptor[iE], myFirst[iE], u );
             if ( myEdgeLength[iE] < aLenU ) // nonregression test "3D_mesh_NETGEN/G6"
             {
               u2nodeVec.clear();
               break;
             }
-            double normPar = prevNormPar + r*aLenU/myEdgeLength[iE];
-            u2nodeVec.push_back( make_pair( normPar, node ));
+            double normPar = prevNormPar + r * aLenU / myEdgeLength[iE];
+            u2nodeVec.push_back( make_pair( normPar, nodes[i] ));
           }
-        nItr = sm->GetNodes();
         if ( u2nodeVec.empty() )
-          while ( nItr->more() )
+          for ( size_t i = 0; i < nodes.size(); ++i )
           {
-            const SMDS_MeshNode* node = nItr->next();
-            if ( myIgnoreMediumNodes && SMESH_MeshEditor::IsMedium( node, SMDSAbs_Edge ))
-              continue;
-            double u = helper.GetNodeU( myEdge[iE], node, 0, &paramOK );
-
+            double u = eHelper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK );
             // paramSize is signed so orientation is taken into account
             double normPar = prevNormPar + r * ( u - myFirst[iE] ) / paramSize;
-            u2nodeVec.push_back( make_pair( normPar, node ));
+            u2nodeVec.push_back( make_pair( normPar, nodes[i] ));
           }
         for ( size_t j = 0; j < u2nodeVec.size(); ++j )
           u2node.insert( u2node.end(), u2nodeVec[j] );
       }
+    } // loop on myEdge's
+
+    // Add 2nd VERTEX node for a last EDGE
+    if ( !proxySubMesh.back() )
+    {
+      if ( u2node.empty() ) return myPoints;
 
-      // Put 2nd vertex node for a last edge
-      if ( iE+1 == myEdge.size() ) {
-        node = SMESH_Algo::VertexNode( VV[1], meshDS );
-        if ( !node ) {
-          MESSAGE(" NO NODE on VERTEX" );
+      const SMDS_MeshNode* node;
+      if ( IsClosed() && !proxySubMesh[0] )
+        node = u2node.begin()->second;
+      else
+      {
+        node = VertexNode( iE );
+        while ( !node && iE > 0 )
+          node = VertexNode( --iE );
+        if ( !node )
           return myPoints;
-        }
-        u2node.insert( u2node.end(), make_pair( 1., node ));
       }
-    } // loop on myEdge's
+      if ( u2node.rbegin()->second == node &&
+           !fHelper.IsRealSeam  ( node->getshapeId() ) &&
+           !fHelper.IsDegenShape( node->getshapeId() ))
+        u2node.erase( --u2node.end() );
+
+      u2node.insert( u2node.end(), make_pair( 1., node ));
+    }
 
     if ( u2node.size() + nbProxyNodes != myNbPonits &&
          u2node.size() + nbProxyNodes != NbPoints( /*update=*/true ))
@@ -440,7 +438,7 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
 
     // fill array of UVPtStruct
 
-    UVPtStructVec& points = const_cast< UVPtStructVec& >( myPoints );
+    UVPtStructVec& points = me->myPoints;
     points.resize( myNbPonits );
 
     int iPt = 0;
@@ -487,7 +485,7 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
           // -- U ----------------------------------------------
           const SMDS_EdgePosition* epos =
             dynamic_cast<const SMDS_EdgePosition*>(uvPt.node->GetPosition());
-          if ( epos ) {
+          if ( epos && uvPt.node->getshapeId() == myEdgeID[iE] ) {
             uvPt.param = epos->GetUParameter();
           }
           else {
@@ -577,76 +575,122 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::SimulateUVPtStruct(int    nbSeg,
 //purpose  : Return nodes in the order they encounter while walking along the side
 //=======================================================================
 
-std::vector<const SMDS_MeshNode*> StdMeshers_FaceSide::GetOrderedNodes() const
+std::vector<const SMDS_MeshNode*> StdMeshers_FaceSide::GetOrderedNodes(int theEdgeInd) const
 {
   vector<const SMDS_MeshNode*> resultNodes;
-  if ( myPoints.empty() )
+  if ( myPoints.empty() || ( theEdgeInd >= 0 && NbEdges() > 0 ))
   {
     if ( NbEdges() == 0 ) return resultNodes;
 
     SMESHDS_Mesh* meshDS = myProxyMesh->GetMeshDS();
-    SMESH_MesherHelper helper(*myProxyMesh->GetMesh());
-    bool paramOK;
+    SMESH_MesherHelper eHelper( *myProxyMesh->GetMesh() );
+    SMESH_MesherHelper fHelper( *myProxyMesh->GetMesh() );
+    fHelper.SetSubShape( myFace );
+    bool paramOK = true;
 
     // Sort nodes of all edges putting them into a map
 
     map< double, const SMDS_MeshNode*> u2node;
-    for ( int i = 0; i < myEdge.size(); ++i )
+    vector<const SMDS_MeshNode*>       nodes;
+    set<const SMDS_MeshNode*>          vertexNodes;
+    int iE = 0, iEnd = myEdge.size();
+    if ( theEdgeInd >= 0 )
     {
-      // Put 1st vertex node of a current edge
-      TopoDS_Vertex VV[2]; // TopExp::FirstVertex() returns NULL for INTERNAL edge
-      VV[0] = SMESH_MesherHelper::IthVertex( 0, myEdge[i]);
-      VV[1] = SMESH_MesherHelper::IthVertex( 1, myEdge[i]);
-      const SMDS_MeshNode* node = SMESH_Algo::VertexNode( VV[0], meshDS );
-      double prevNormPar = ( i == 0 ? 0 : myNormPar[ i-1 ]); // normalized param
+      iE   = theEdgeInd % NbEdges();
+      iEnd = iE + 1;
+    }
+    for ( iE = 0; iE < iEnd; ++iE )
+    {
+      double prevNormPar = ( iE == 0 ? 0 : myNormPar[ iE-1 ]); // normalized param
+
+      const SMESH_ProxyMesh::SubMesh* proxySM = myProxyMesh->GetProxySubMesh( myEdge[iE] );
+      if ( proxySM )
+      {
+        const UVPtStructVec& points = proxySM->GetUVPtStructVec();
+        for ( size_t i = 0; i < points.size(); ++i )
+          u2node.insert( make_pair( prevNormPar + points[i].normParam, points[i].node ));
+        continue;
+      }
+
+      // Add 1st vertex node of a current EDGE
+      const SMDS_MeshNode* node = VertexNode( iE );
       if ( node ) { // nodes on internal vertices may be missing
-        u2node.insert( make_pair( prevNormPar, node ));
+        if ( vertexNodes.insert( node ).second ||
+             fHelper.IsRealSeam  ( node->getshapeId() ) ||
+             fHelper.IsDegenShape( node->getshapeId() ))
+          u2node.insert( make_pair( prevNormPar, node ));
       }
-      else if ( i == 0 ) {
-        MESSAGE(" NO NODE on VERTEX" );
-        return resultNodes;
+      else if ( iE == 0 )
+      {
+        if ( nodes.empty() ) {
+          for ( ++iE; iE < iEnd; ++iE )
+            if (( node = VertexNode( iE ))) {
+              u2node.insert( make_pair( prevNormPar, node ));
+              break;
+            }
+          --iE;
+        }
+        if ( !node )
+          return resultNodes;
+        vertexNodes.insert( node );
       }
 
-      // Put internal nodes
-      if ( SMESHDS_SubMesh* sm = meshDS->MeshElements( myEdge[i] ))
+      // Add internal nodes
+      nodes.clear();
+      if ( !GetEdgeNodes( iE, nodes, /*v0=*/false, /*v1=*/false ))
+        return resultNodes;
+      if ( !nodes.empty() )
       {
-        SMDS_NodeIteratorPtr nItr = sm->GetNodes();
-        double paramSize = myLast[i] - myFirst[i];
-        double r         = myNormPar[i] - prevNormPar;
-        helper.SetSubShape( myEdge[i] );
-        helper.ToFixNodeParameters( true );
-        while ( nItr->more() )
+        double paramSize = myLast[iE] - myFirst[iE];
+        double r         = myNormPar[iE] - prevNormPar;
+        eHelper.SetSubShape( myEdge[iE] );
+        eHelper.ToFixNodeParameters( true );
+        for ( size_t i = 0; i < nodes.size(); ++i )
         {
-          const SMDS_MeshNode* node = nItr->next();
-          if ( myIgnoreMediumNodes && SMESH_MeshEditor::IsMedium( node, SMDSAbs_Edge ))
-            continue;
-          double u = helper.GetNodeU( myEdge[i], node, 0, &paramOK );
-
+          double u = eHelper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK );
           // paramSize is signed so orientation is taken into account
-          double normPar = prevNormPar + r * ( u - myFirst[i] ) / paramSize;
-          u2node.insert( u2node.end(), make_pair( normPar, node ));
+          double normPar = prevNormPar + r * ( u - myFirst[iE] ) / paramSize;
+          u2node.insert( u2node.end(), make_pair( normPar, nodes[i] ));
         }
       }
 
-      // Put 2nd vertex node for a last edge
-      if ( i+1 == myEdge.size() ) {
-        node = SMESH_Algo::VertexNode( VV[1], meshDS );
-        if ( !node ) {
+    } // loop on myEdges
+
+    if ( u2node.empty() ) return resultNodes;
+
+    // Add 2nd vertex node for a last EDGE
+    {
+      const SMDS_MeshNode* node;
+      if ( IsClosed() && theEdgeInd < 0 )
+        node = u2node.begin()->second;
+      else
+      {
+        node = VertexNode( iE );
+        while ( !node && iE > 0 )
+          node = VertexNode( --iE );
+        if ( !node )
           return resultNodes;
-        }
-        u2node.insert( u2node.end(), make_pair( 1., node ));
       }
+      if ( u2node.rbegin()->second == node &&
+           !fHelper.IsRealSeam  ( node->getshapeId() ) &&
+           !fHelper.IsDegenShape( node->getshapeId() ))
+        u2node.erase( --u2node.end() );
+
+      u2node.insert( u2node.end(), make_pair( 1., node ));
     }
 
     // Fill the result vector
 
-    if ( u2node.size() == myNbPonits )
+    if ( theEdgeInd < 0 &&
+         u2node.size() != myNbPonits &&
+         u2node.size() != NbPoints( /*update=*/true ))
     {
-      resultNodes.reserve( u2node.size() );
-      map< double, const SMDS_MeshNode*>::iterator u2n = u2node.begin();
-      for ( ; u2n != u2node.end(); ++u2n )
-        resultNodes.push_back( u2n->second );
+      u2node.clear();
     }
+    resultNodes.reserve( u2node.size() );
+    map< double, const SMDS_MeshNode*>::iterator u2n = u2node.begin();
+    for ( ; u2n != u2node.end(); ++u2n )
+      resultNodes.push_back( u2n->second );
   }
   else
   {
@@ -658,6 +702,133 @@ std::vector<const SMDS_MeshNode*> StdMeshers_FaceSide::GetOrderedNodes() const
   return resultNodes;
 }
 
+//================================================================================
+/*!
+ * \brief Return (unsorted) nodes of the i-th EDGE.
+ *        Nodes moved to other geometry by MergeNodes() are also returned.
+ *  \retval bool - is OK
+ */
+//================================================================================
+
+bool StdMeshers_FaceSide::GetEdgeNodes(size_t                        i,
+                                       vector<const SMDS_MeshNode*>& nodes,
+                                       bool                          inlude1stVertex,
+                                       bool                          inludeLastVertex) const
+{
+  if ( i >= myEdge.size() )
+    return false;
+
+  SMESH_Mesh*     mesh = myProxyMesh->GetMesh();
+  SMESHDS_Mesh* meshDS = mesh->GetMeshDS();
+  SMESHDS_SubMesh*  sm = meshDS->MeshElements( myEdge[i] );
+
+  if ( inlude1stVertex )
+  {
+    if ( const SMDS_MeshNode* n0 = VertexNode( i ))
+      nodes.push_back( n0 );
+  }
+
+  if ( sm && ( sm->NbElements() > 0 || sm->NbNodes() > 0 ))
+  {
+    if ( mesh->HasModificationsToDiscard() ) // check nb of nodes on the EDGE sub-mesh
+    {
+      int iQuad    = sm->NbElements() ? sm->GetElements()->next()->IsQuadratic() : 0;
+      int nbExpect = sm->NbElements() - 1 + iQuad * sm->NbElements();
+      if ( nbExpect != sm->NbNodes() ) // some nodes are moved from the EDGE by MergeNodes()
+      {
+        // add nodes of all segments
+        typedef set< const SMDS_MeshNode* > TNodeSet;
+        TNodeSet sharedNodes;
+        SMDS_ElemIteratorPtr segIt = sm->GetElements();
+        while ( segIt->more() )
+        {
+          const SMDS_MeshElement* seg = segIt->next();
+          if ( seg->GetType() != SMDSAbs_Edge )
+            continue;
+          for ( int i = 0; i < 3-myIgnoreMediumNodes; ++i )
+          {
+            const SMDS_MeshNode* n = seg->GetNode( i );
+            if ( i == 2 ) // medium node
+            {
+              nodes.push_back( n );
+            }
+            else
+            {
+              pair<TNodeSet::iterator, bool> it2new = sharedNodes.insert( n );
+              if ( !it2new.second ) // n encounters twice == it's on EDGE, not on VERTEX
+              {
+                nodes.push_back( n );
+                sharedNodes.erase( it2new.first );
+              }
+            }
+          }
+        }
+      }
+    }
+    if ( nodes.size() < 2 ) // add nodes assigned to the EDGE
+    {
+      SMDS_NodeIteratorPtr nItr = sm->GetNodes();
+      while ( nItr->more() )
+      {
+        const SMDS_MeshNode* n = nItr->next();
+        if ( myIgnoreMediumNodes && SMESH_MeshEditor::IsMedium( n, SMDSAbs_Edge ))
+          continue;
+        nodes.push_back( n );
+      }
+    }
+  } // if ( sm && sm->NbElements() > 0 )
+
+  if ( inludeLastVertex )
+  {
+    if ( const SMDS_MeshNode* n1 = VertexNode( i+1 ))
+      nodes.push_back( n1 );
+  }
+  return true;
+}
+
+//================================================================================
+/*!
+ * \brief Return a node from the i-th VERTEX (count starts from zero)
+ *        Nodes moved to other geometry by MergeNodes() are also returned.
+ *  \param [in] i - the VERTEX index
+ *  \param [out] isMoved - returns \c true if the found node is moved by MergeNodes()
+ *  \return const SMDS_MeshNode* - the found node
+ */
+//================================================================================
+
+const SMDS_MeshNode* StdMeshers_FaceSide::VertexNode(std::size_t i, bool* isMoved) const
+{
+  TopoDS_Vertex V = ( i >= myEdge.size() ) ? LastVertex() : FirstVertex(i);
+
+  const SMDS_MeshNode* n = SMESH_Algo::VertexNode( V, myProxyMesh->GetMeshDS() );
+
+  if ( !n && !myEdge.empty() && myProxyMesh->GetMesh()->HasModificationsToDiscard() )
+  {
+    size_t iE = ( i < myEdge.size() ) ? i : myEdge.size()-1;
+    SMESHDS_SubMesh* sm = myProxyMesh->GetMeshDS()->MeshElements( myEdgeID[ iE ]);
+
+    n = SMESH_Algo::VertexNode( V, sm, myProxyMesh->GetMesh(), /*checkV=*/false );
+
+    if (( !n ) &&
+        (( i > 0 && i < NbEdges() ) || IsClosed() ))
+    {
+      iE = SMESH_MesherHelper::WrapIndex( int(i)-1, NbEdges() );
+      sm = myProxyMesh->GetMeshDS()->MeshElements( myEdgeID[ iE ]);
+      n  = SMESH_Algo::VertexNode( V, sm, myProxyMesh->GetMesh(), /*checkV=*/false );
+    }
+
+    if ( n && n->GetPosition()->GetDim() == 1 ) // check that n does not lie on an EDGE of myFace
+    {
+      TopoDS_Shape S = SMESH_MesherHelper::GetSubShapeByNode( n, myProxyMesh->GetMeshDS() );
+      if ( SMESH_MesherHelper::IsSubShape( S, myFace ))
+        n = 0; // VERTEX ignored by e.g. Composite Wire Discretization algo
+    }
+    if ( isMoved )
+      *isMoved = n;
+  }
+  return n;
+}
+
 //================================================================================
 /*!
  * \brief reverse order of vector elements
@@ -667,8 +838,7 @@ std::vector<const SMDS_MeshNode*> StdMeshers_FaceSide::GetOrderedNodes() const
 
 template <typename T > void reverse(vector<T> & vec)
 {
-  for ( int f=0, r=vec.size()-1; f < r; ++f, --r )
-    std::swap( vec[f], vec[r] );
+  std::reverse( vec.begin(), vec.end() );
 }
 
 //================================================================================
@@ -788,30 +958,48 @@ int StdMeshers_FaceSide::NbPoints(const bool update) const
     me->myNbSegments = 0;
     me->myMissingVertexNodes = false;
 
+    vector<const SMDS_MeshNode*> nodes;
     for ( int i = 0; i < NbEdges(); ++i )
     {
-      TopoDS_Vertex v1 = SMESH_MesherHelper::IthVertex( 0, myEdge[i] );
-      if ( SMESH_Algo::VertexNode( v1, myProxyMesh->GetMeshDS() ))
-        me->myNbPonits += 1; // for the first end
-      else
-        me->myMissingVertexNodes = true;
-    
-      if ( const SMESHDS_SubMesh* sm = myProxyMesh->GetSubMesh( Edge(i) )) {
-        int nbN = sm->NbNodes();
-        if ( myIgnoreMediumNodes ) {
-          SMDS_ElemIteratorPtr elemIt = sm->GetElements();
-          if ( elemIt->more() && elemIt->next()->IsQuadratic() )
-            nbN -= sm->NbElements();
+      if ( const SMESHDS_SubMesh* sm = myProxyMesh->GetSubMesh( Edge(i) ))
+      {
+        if ( sm->NbNodes() == sm->NbElements()-1 || sm->NbElements() == 0 )
+        {
+          me->myNbPonits += sm->NbNodes();
+          if ( myIgnoreMediumNodes && sm->IsQuadratic() )
+            me->myNbPonits -= sm->NbElements();
+        }
+        else // nodes can be moved to other shapes by MergeNodes()
+        {
+          nodes.clear();
+          GetEdgeNodes( i, nodes, /*v1=*/false, /*v2=*/false );
+          me->myNbPonits += nodes.size();
         }
-        me->myNbPonits   += nbN;
         me->myNbSegments += sm->NbElements();
       }
     }
-    TopoDS_Vertex v1 = SMESH_MesherHelper::IthVertex( 1, Edge( NbEdges()-1 ));
-    if ( SMESH_Algo::VertexNode( v1, myProxyMesh->GetMeshDS() ))
-      me->myNbPonits++; // for the last end
-    else
-      me->myMissingVertexNodes = true;
+
+    SMESH_MesherHelper helper( *myProxyMesh->GetMesh() );
+    helper.SetSubShape( myFace );
+
+    std::set< const SMDS_MeshNode* > vNodes;
+    const int nbV = NbEdges() + !IsClosed();
+    for ( int i = 0; i < nbV; ++i )
+      if ( const SMDS_MeshNode* n = VertexNode( i ))
+      {
+        if ( !vNodes.insert( n ).second &&
+             ( helper.IsRealSeam  ( n->getshapeId() ) ||
+               helper.IsDegenShape( n->getshapeId() )))
+          me->myNbPonits++;
+      }
+      else
+      {
+        me->myMissingVertexNodes = true;
+      }
+    me->myNbPonits += vNodes.size();
+
+    if ( IsClosed() )
+      me->myNbPonits++; // closing node is repeated
   }
   return myNbPonits;
 }
@@ -928,7 +1116,7 @@ BRepAdaptor_CompCurve* StdMeshers_FaceSide::GetCurve3d() const
   for ( int i=0; i<myEdge.size(); ++i )
     aBuilder.Add( aWire, myEdge[i] );
 
-  if ( myEdge.size() == 2 && FirstVertex().IsSame( LastVertex() ))
+  if ( myEdge.size() == 2 && IsClosed() )
     aWire.Closed(true); // issue 0021141
 
   return new BRepAdaptor_CompCurve( aWire );
@@ -1118,3 +1306,13 @@ TopoDS_Vertex StdMeshers_FaceSide::LastVertex(int i) const
   return v;
 }
 
+//================================================================================
+/*!
+ * \brief Return \c true if the chain of EDGEs is closed
+ */
+//================================================================================
+
+bool StdMeshers_FaceSide::IsClosed() const
+{
+  return myEdge.empty() ? false : FirstVertex().IsSame( LastVertex() );
+}
index b7d79b9929c46cabd9e59a148805c204e1c35928..485081af0e6a2aacf7c0fd217c05b0dd57d996d1 100644 (file)
@@ -191,10 +191,27 @@ public:
                                           bool   isXConst   = 0,
                                           double constValue = 0) const;
   /*!
-   * \brief Return nodes in the order they encounter while walking along the side.
+   * \brief Return nodes in the order they encounter while walking along
+   *  the while side or a specified EDGE.
     * For a closed side, the 1st point repeats at end
    */
-  std::vector<const SMDS_MeshNode*> GetOrderedNodes() const;
+  std::vector<const SMDS_MeshNode*> GetOrderedNodes(int iE=-1) const;
+
+  /*!
+   * \brief Return nodes of the i-th EDGE.
+   *        Nodes moved to other geometry by MergeNodes() are also returned.
+   * \retval bool - is OK
+   */
+  bool GetEdgeNodes(const size_t                       i,
+                    std::vector<const SMDS_MeshNode*>& nodes,
+                    bool                               inlude1stVertex=true,
+                    bool                               inludeLastVertex=true) const;
+
+  /*!
+   * \brief Return a node from the i-th VERTEX (count starts from zero)
+   *        Nodes moved to other geometry by MergeNodes() are also returned.
+   */
+  const SMDS_MeshNode* VertexNode(std::size_t i, bool* isMoved = 0) const;
 
   /*!
    * \brief Return edge and parameter on edge by normalized parameter
@@ -229,13 +246,17 @@ public:
    */
   const std::vector<TopoDS_Edge>& Edges() const { return myEdge; }
   /*!
-   * \brief Return 1st vertex of the i-the edge (count starts from zero)
+   * \brief Return 1st vertex of the i-th edge (count starts from zero)
    */
   TopoDS_Vertex FirstVertex(int i=0) const;
   /*!
-   * \brief Return last vertex of the i-the edge (count starts from zero)
+   * \brief Return last vertex of the i-th edge (count starts from zero)
    */
   TopoDS_Vertex LastVertex(int i=-1) const;
+  /*!
+   * \brief Return \c true if the chain of EDGEs is closed
+   */
+  bool IsClosed() const;
   /*!
    * \brief Return side length
    */
@@ -258,20 +279,20 @@ public:
    */
   inline Handle(Geom2d_Curve) Curve2d(int i) const;
   /*!
-   * \brief Return first normalized parameter of the i-the edge (count starts from zero)
+   * \brief Return first normalized parameter of the i-th edge (count starts from zero)
    */
   inline double FirstParameter(int i) const;
   /*!
-   * \brief Return last normalized parameter of the i-the edge (count starts from zero)
+   * \brief Return last normalized parameter of the i-th edge (count starts from zero)
    */
   inline double LastParameter(int i) const;
   /*!
-   * \brief Return first parameter of the i-the edge (count starts from zero).
+   * \brief Return first parameter of the i-th edge (count starts from zero).
    *        EDGE orientation is taken into account
    */
   inline double FirstU(int i) const;
   /*!
-   * \brief Return last parameter of the i-the edge (count starts from zero).
+   * \brief Return last parameter of the i-th edge (count starts from zero).
    *        EDGE orientation is taken into account
    */
   inline double LastU(int i) const;
@@ -289,6 +310,7 @@ protected:
   void reverseProxySubmesh( const TopoDS_Edge& E );
 
   // DON't FORGET to update Reverse() when adding one more vector!
+  TopoDS_Face                       myFace;
   std::vector<uvPtStruct>           myPoints, myFalsePoints;
   std::vector<TopoDS_Edge>          myEdge;
   std::vector<int>                  myEdgeID;
@@ -340,7 +362,7 @@ inline double StdMeshers_FaceSide::Parameter(double U, TopoDS_Edge & edge) const
 
 //================================================================================
 /*!
- * \brief Return first normalized parameter of the i-the edge
+ * \brief Return first normalized parameter of the i-th edge
  */
 //================================================================================
 
@@ -351,7 +373,7 @@ inline double StdMeshers_FaceSide::FirstParameter(int i) const
 
 //================================================================================
 /*!
- * \brief Return ast normalized parameter of the i-the edge
+ * \brief Return ast normalized parameter of the i-th edge
  */
 //================================================================================
 
@@ -362,7 +384,7 @@ inline double StdMeshers_FaceSide::LastParameter(int i) const
 
 //================================================================================
 /*!
- * \brief Return first parameter of the i-the edge
+ * \brief Return first parameter of the i-th edge
  */
 //================================================================================
 
@@ -373,7 +395,7 @@ inline double StdMeshers_FaceSide::FirstU(int i) const
 
 //================================================================================
 /*!
- * \brief Return last parameter of the i-the edge
+ * \brief Return last parameter of the i-th edge
  */
 //================================================================================
 
index b5e9a567ae93de6857d234e8ee58104bcc9737b9..083f055f206ae815ae7e4390036d253865b929c6 100644 (file)
@@ -841,6 +841,7 @@ void StdMeshers_Import_1D::importMesh(const SMESH_Mesh*          srcMesh,
 
   // 1. Copy mesh
 
+  SMESH_MeshEditor::ElemFeatures elemType;
   vector<const SMDS_MeshNode*> newNodes;
   const SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
   SMDS_ElemIteratorPtr eIt = srcMeshDS->elementsIterator();
@@ -865,7 +866,7 @@ void StdMeshers_Import_1D::importMesh(const SMESH_Mesh*          srcMesh,
       tgtMeshDS->FindElement( newNodes, elem->GetType(), /*noMedium=*/false );
     if ( !newElem )
     {
-      newElem = additor.AddElement( newNodes, elem->GetType(), elem->IsPoly());
+      newElem = additor.AddElement( newNodes, elemType.Init( elem, /*basicOnly=*/false ));
       tgtSubMesh->AddElement( newElem );
     }
     if ( toCopyGroups )
index 196814b789a73d927d0a3d711c8ca531abd95af2..60b776254489ad854f7f7dd9452386aa3491ceb2 100644 (file)
@@ -454,7 +454,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
 
         if ( geomNorm * meshNorm < 0 )
           SMDS_MeshCell::applyInterlace
-            ( SMDS_MeshCell::reverseSmdsOrder( face->GetEntityType() ), newNodes );
+            ( SMDS_MeshCell::reverseSmdsOrder( face->GetEntityType(), newNodes.size() ), newNodes );
       }
 
       // make a new face
index 20f1ff59d51a6c77758e4bbb66e03a30fc098a0c..6d99a44de3a3ef1a2e3f19bf12a2f1d08d480af7 100644 (file)
@@ -657,7 +657,7 @@ void StdMeshers_Penta_3D::MakeVolumeMesh()
   }
   //
   // 2. Make pentahedrons
-  int aID0, k , aJ[3];
+  int aID0, k , aJ[4];
   vector<const SMDS_MeshNode*> aN;
   //
   SMDS_ElemIteratorPtr itf, aItNodes;
diff --git a/src/StdMeshers/StdMeshers_PolygonPerFace_2D.cxx b/src/StdMeshers/StdMeshers_PolygonPerFace_2D.cxx
new file mode 100644 (file)
index 0000000..6b4960d
--- /dev/null
@@ -0,0 +1,158 @@
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// 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
+//
+
+// File      : StdMeshers_PolygonPerFace_2D.cxx
+// Module    : SMESH
+// Created   : Fri Oct 20 11:37:07 2006
+// Author    : Edward AGAPOV (eap)
+//
+#include "StdMeshers_PolygonPerFace_2D.hxx"
+
+#include "SMESH_Comment.hxx"
+#include "SMESH_Mesh.hxx"
+#include "SMESH_MesherHelper.hxx"
+#include "SMESH_ProxyMesh.hxx"
+#include "SMESH_subMesh.hxx"
+#include "StdMeshers_FaceSide.hxx"
+#include "StdMeshers_ViscousLayers2D.hxx"
+
+#include <TopExp_Explorer.hxx>
+#include <TopoDS_Face.hxx>
+
+#include <vector>
+#include <TopoDS.hxx>
+
+using namespace std;
+
+//=======================================================================
+//function : StdMeshers_PolygonPerFace_2D
+//purpose  : 
+//=======================================================================
+
+StdMeshers_PolygonPerFace_2D::StdMeshers_PolygonPerFace_2D(int        hypId,
+                                                           int        studyId,
+                                                           SMESH_Gen* gen)
+  :SMESH_2D_Algo(hypId, studyId, gen)
+{
+  _name = "PolygonPerFace_2D";
+}
+
+//=======================================================================
+//function : CheckHypothesis
+//purpose  : 
+//=======================================================================
+
+bool StdMeshers_PolygonPerFace_2D::CheckHypothesis(SMESH_Mesh&                          theMesh,
+                                                   const TopoDS_Shape&                  theShape,
+                                                   SMESH_Hypothesis::Hypothesis_Status& theStatus)
+{
+  theStatus = HYP_OK;
+  return true;
+}
+
+//=======================================================================
+//function : Compute
+//purpose  :
+//=======================================================================
+
+bool StdMeshers_PolygonPerFace_2D::Compute(SMESH_Mesh&         theMesh,
+                                           const TopoDS_Shape& theShape)
+{
+  const TopoDS_Face& face = TopoDS::Face( theShape );
+
+  SMESH_MesherHelper helper( theMesh );
+  helper.SetElementsOnShape( true );
+  _quadraticMesh = helper.IsQuadraticSubMesh( face );
+
+  SMESH_ProxyMesh::Ptr proxyMesh = StdMeshers_ViscousLayers2D::Compute( theMesh, face );
+  if ( !proxyMesh )
+    return false;
+
+  TError erorr;
+  TSideVector wires = StdMeshers_FaceSide::GetFaceWires(face, theMesh,
+                                                        /*skipMediumNodes=*/_quadraticMesh,
+                                                        erorr, proxyMesh,
+                                                        /*checkVertexNodes=*/false);
+  if ( wires.size() != 1 )
+    return error( COMPERR_BAD_SHAPE, SMESH_Comment("One wire required, not ") << wires.size() );
+
+  vector<const SMDS_MeshNode*> nodes = wires[0]->GetOrderedNodes();
+  int nbNodes = int( nodes.size() ) - 1; // 1st node is repeated at end
+
+  switch ( nbNodes ) {
+  case 3:
+    helper.AddFace( nodes[0], nodes[1], nodes[2] );
+    break;
+  case 4:
+    helper.AddFace( nodes[0], nodes[1], nodes[2], nodes[3] );
+    break;
+  default:
+    if ( nbNodes < 3 )
+      return error( COMPERR_BAD_INPUT_MESH, "Less that 3 nodes on the wire" );
+    nodes.resize( nodes.size() - 1 );
+    helper.AddPolygonalFace ( nodes );
+  }
+
+  return true;
+}
+
+//=======================================================================
+//function : Evaluate
+//purpose  : 
+//=======================================================================
+
+bool StdMeshers_PolygonPerFace_2D::Evaluate(SMESH_Mesh&         theMesh,
+                                            const TopoDS_Shape& theShape,
+                                            MapShapeNbElems&    theResMap)
+{
+  // count nb segments
+  int nbLinSegs = 0, nbQuadSegs = 0;
+  TopExp_Explorer edge( theShape, TopAbs_EDGE );
+  for ( ; edge.More(); edge.Next() )
+  {
+    SMESH_subMesh* sm = theMesh.GetSubMesh( edge.Current() );
+    MapShapeNbElems::iterator sm2vec = theResMap.find( sm );
+    if ( sm2vec == theResMap.end() )
+      continue;
+    nbLinSegs  += sm2vec->second.at( SMDSEntity_Edge );
+    nbQuadSegs += sm2vec->second.at( SMDSEntity_Quad_Edge );
+  }
+
+  std::vector<int> aVec( SMDSEntity_Last, 0 );
+  switch ( nbLinSegs + nbQuadSegs ) {
+  case 3:
+    aVec[ nbQuadSegs ? SMDSEntity_Quad_Triangle : SMDSEntity_Triangle ] = 1;
+    break;
+  case 4:
+    aVec[ nbQuadSegs ? SMDSEntity_Quad_Quadrangle : SMDSEntity_Quadrangle ] = 1;
+    break;
+  default:
+    if ( nbLinSegs + nbQuadSegs < 3 )
+      return error( COMPERR_BAD_INPUT_MESH, "Less that 3 nodes on the wire" );
+    aVec[ nbQuadSegs ? SMDSEntity_Quad_Polygon : SMDSEntity_Polygon ] = 1;
+  }
+
+  SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
+  theResMap.insert(std::make_pair(sm,aVec));
+
+  return true;
+}
diff --git a/src/StdMeshers/StdMeshers_PolygonPerFace_2D.hxx b/src/StdMeshers/StdMeshers_PolygonPerFace_2D.hxx
new file mode 100644 (file)
index 0000000..5a6a604
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// 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
+//
+
+//  File   : StdMeshers_PolygonPerFace_2D.hxx
+//  Module : SMESH
+//
+#ifndef _SMESH_PolygonPerFace_2D_HXX_
+#define _SMESH_PolygonPerFace_2D_HXX_
+
+#include "SMESH_StdMeshers.hxx"
+#include "SMESH_Algo.hxx"
+
+class STDMESHERS_EXPORT StdMeshers_PolygonPerFace_2D: public SMESH_2D_Algo
+{
+ public:
+  StdMeshers_PolygonPerFace_2D(int hypId, int studyId, SMESH_Gen* gen);
+
+  virtual bool CheckHypothesis(SMESH_Mesh&                          aMesh,
+                               const TopoDS_Shape&                  aShape,
+                               SMESH_Hypothesis::Hypothesis_Status& aStatus);
+
+  virtual bool Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape);
+
+  virtual bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape,
+                        MapShapeNbElems& aResMap);
+};
+
+#endif
index 44e7c115c068bfad874962ab70ca04d60b2e749e..87572c18f40434ceaa3e70cdc6b57de13e21dd5b 100644 (file)
@@ -441,32 +441,7 @@ namespace {
     tgtWires.resize( srcWires.size() );
     for ( size_t iW = 0; iW < srcWires.size(); ++iW )
     {
-      // check ori
-      //bool reverse = false;
       StdMeshers_FaceSidePtr srcWire = srcWires[iW];
-      // for ( int iE = 0; iE < srcWire->NbEdges(); ++iE )
-      // {
-      //   if ( srcHelper.IsRealSeam( srcWire->EdgeID( iE )))
-      //     continue;
-      //   TopoDS_Shape srcE = srcWire->Edge( iE );
-      //   TopoDS_Shape tgtE = shape2ShapeMap( srcE, /*isSrc=*/true);
-      //   if ( shape2ShapeMap._assocType == TShapeShapeMap::PROPAGATION ||
-      //        shape2ShapeMap._assocType == TShapeShapeMap::PROPAGATION)
-      //   {
-      //     reverse = false;
-      //   }
-      //   else if ( tgtMesh == srcMesh )
-      //   {
-      //     reverse = (( srcE.Orientation() == srcHelper.GetSubShapeOri( srcFace, srcE )) !=
-      //                ( tgtE.Orientation() == srcHelper.GetSubShapeOri( tgtFace, tgtE )));
-      //   }
-      //   else
-      //   {
-      //     TopoDS_Shape srcEbis = shape2ShapeMap( tgtE, /*isSrc=*/false );
-      //     reverse = ( srcE.Orientation() != srcEbis.Orientation() );
-      //   }
-      //   break;
-      // }
 
       list< TopoDS_Edge > tgtEdges;
       TopTools_IndexedMapOfShape edgeMap; // to detect seam edges
@@ -476,7 +451,6 @@ namespace {
         TopoDS_Edge     tgtE = TopoDS::Edge( shape2ShapeMap( srcE, /*isSrc=*/true));
         TopoDS_Shape srcEbis = shape2ShapeMap( tgtE, /*isSrc=*/false );
         if ( srcE.Orientation() != srcEbis.Orientation() )
-          //if ( reverse )
           tgtE.Reverse();
         // reverse a seam edge encountered for the second time
         const int index = edgeMap.Add( tgtE );
@@ -504,56 +478,58 @@ namespace {
             tgtE = nE.second;
         }
         tgtEdges.push_back( tgtE );
+      }
 
+      tgtWires[ iW ].reset( new StdMeshers_FaceSide( tgtFace, tgtEdges, tgtMesh,
+                                                     /*theIsForward = */ true,
+                                                     /*theIgnoreMediumNodes = */false));
+      StdMeshers_FaceSidePtr tgtWire = tgtWires[ iW ];
 
-        // Fill map of src to tgt nodes with nodes on edges
+      // Fill map of src to tgt nodes with nodes on edges
 
-        if ( srcMesh->GetSubMesh( srcE )->IsEmpty() ||
-             tgtMesh->GetSubMesh( tgtE )->IsEmpty() )
+      for ( int iE = 0; iE < srcWire->NbEdges(); ++iE )
+      {
+        if ( srcMesh->GetSubMesh( srcWire->Edge(iE) )->IsEmpty() ||
+             tgtMesh->GetSubMesh( tgtWire->Edge(iE) )->IsEmpty() )
         {
           // add nodes on VERTEXes for a case of not meshes EDGEs
-          const TopoDS_Shape&  srcV = SMESH_MesherHelper::IthVertex( 0, srcE );
-          const TopoDS_Shape&  tgtV = shape2ShapeMap( srcV, /*isSrc=*/true );
-          const SMDS_MeshNode* srcN = SMESH_Algo::VertexNode( TopoDS::Vertex( srcV ), srcMeshDS );
-          const SMDS_MeshNode* tgtN = SMESH_Algo::VertexNode( TopoDS::Vertex( tgtV ), tgtMeshDS );
+          const SMDS_MeshNode* srcN = srcWire->VertexNode( iE );
+          const SMDS_MeshNode* tgtN = tgtWire->VertexNode( iE );
           if ( srcN && tgtN )
             src2tgtNodes.insert( make_pair( srcN, tgtN ));
         }
         else
         {
-          const bool skipMediumNodes = true;
-          map< double, const SMDS_MeshNode* > srcNodes, tgtNodes;
-          if ( !SMESH_Algo::GetSortedNodesOnEdge( srcMeshDS, srcE, skipMediumNodes, srcNodes) ||
-               !SMESH_Algo::GetSortedNodesOnEdge( tgtMeshDS, tgtE, skipMediumNodes, tgtNodes ))
-            return SMESH_ComputeError::New( COMPERR_BAD_INPUT_MESH,
-                                            "Invalid node parameters on edges");
+          const bool skipMedium = true, isFwd = true;
+          StdMeshers_FaceSide srcEdge( srcFace, srcWire->Edge(iE), srcMesh, isFwd, skipMedium);
+          StdMeshers_FaceSide tgtEdge( tgtFace, tgtWire->Edge(iE), tgtMesh, isFwd, skipMedium);
+          
+          vector< const SMDS_MeshNode* > srcNodes = srcEdge.GetOrderedNodes();
+          vector< const SMDS_MeshNode* > tgtNodes = tgtEdge.GetOrderedNodes();
 
           if (( srcNodes.size() != tgtNodes.size() ) && tgtNodes.size() > 0 )
             return SMESH_ComputeError::New( COMPERR_BAD_INPUT_MESH,
                                             "Different number of nodes on edges");
           if ( !tgtNodes.empty() )
           {
-            map< double, const SMDS_MeshNode* >::iterator u_tn = tgtNodes.begin();
-            if ( srcE.Orientation() == tgtE.Orientation() )
+            vector< const SMDS_MeshNode* >::iterator tn = tgtNodes.begin();
+            //if ( srcWire->Edge(iE).Orientation() == tgtWire->Edge(iE).Orientation() )
             {
-              map< double, const SMDS_MeshNode* >::iterator u_sn = srcNodes.begin();
-              for ( ; u_tn != tgtNodes.end(); ++u_tn, ++u_sn)
-                src2tgtNodes.insert( make_pair( u_sn->second, u_tn->second ));
-            }
-            else
-            {
-              map< double, const SMDS_MeshNode* >::reverse_iterator u_sn = srcNodes.rbegin();
-              for ( ; u_tn != tgtNodes.end(); ++u_tn, ++u_sn)
-                src2tgtNodes.insert( make_pair( u_sn->second, u_tn->second ));
+              vector< const SMDS_MeshNode* >::iterator sn = srcNodes.begin();
+              for ( ; tn != tgtNodes.end(); ++tn, ++sn)
+                src2tgtNodes.insert( make_pair( *sn, *tn ));
             }
+            // else
+            // {
+            //   vector< const SMDS_MeshNode* >::reverse_iterator sn = srcNodes.rbegin();
+            //   for ( ; tn != tgtNodes.end(); ++tn, ++sn)
+            //     src2tgtNodes.insert( make_pair( *sn, *tn ));
+            // }
             is1DComputed = true;
           }
         }
       } // loop on EDGEs of a WIRE
 
-      tgtWires[ iW ].reset( new StdMeshers_FaceSide( tgtFace, tgtEdges, tgtMesh,
-                                                     /*theIsForward = */ true,
-                                                     /*theIgnoreMediumNodes = */false));
     } // loop on WIREs
 
     return TError();
@@ -670,7 +646,7 @@ namespace {
     // Make new faces
 
     // prepare the helper to adding quadratic elements if necessary
-    helper.SetSubShape( tgtFace );
+    //helper.SetSubShape( tgtFace );
     helper.IsQuadraticSubMesh( tgtFace );
 
     SMESHDS_SubMesh* srcSubDS = srcMeshDS->MeshElements( srcFace );
index 665a84efa07b94e92c450a05e5c9431460246b99..a9b924724f4a96cb424121fd43a45c17b7d0a993 100644 (file)
 #include "SMESH_Gen.hxx"
 #include "SMESH_MAT2d.hxx"
 #include "SMESH_Mesh.hxx"
+#include "SMESH_MeshEditor.hxx"
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_ProxyMesh.hxx"
 #include "SMESH_subMesh.hxx"
+#include "SMESH_subMeshEventListener.hxx"
 #include "StdMeshers_FaceSide.hxx"
+#include "StdMeshers_LayerDistribution.hxx"
+#include "StdMeshers_NumberOfLayers.hxx"
 #include "StdMeshers_Regular_1D.hxx"
 #include "StdMeshers_ViscousLayers2D.hxx"
 
+#include <BRepAdaptor_Curve.hxx>
 #include <BRepBuilderAPI_MakeEdge.hxx>
 #include <BRepTools.hxx>
 #include <BRep_Tool.hxx>
@@ -44,6 +49,7 @@
 #include <Precision.hxx>
 #include <TColgp_HArray1OfPnt.hxx>
 #include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
 #include <TopLoc_Location.hxx>
 #include <TopTools_MapOfShape.hxx>
 #include <TopoDS.hxx>
@@ -68,10 +74,72 @@ public:
   }
   void SetSegmentLength( double len )
   {
+    SMESH_Algo::_usedHypList.clear();
     _value[ BEG_LENGTH_IND ] = len;
-    _value[ PRECISION_IND ] = 1e-7;
+    _value[ PRECISION_IND  ] = 1e-7;
     _hypType = LOCAL_LENGTH;
   }
+  void SetRadialDistribution( const SMESHDS_Hypothesis* hyp )
+  {
+    SMESH_Algo::_usedHypList.clear();
+    if ( !hyp )
+      return;
+
+    if ( const StdMeshers_NumberOfLayers* nl =
+         dynamic_cast< const StdMeshers_NumberOfLayers* >( hyp ))
+    {
+      _ivalue[ NB_SEGMENTS_IND  ] = nl->GetNumberOfLayers();
+      _ivalue[ DISTR_TYPE_IND ]   = 0;
+      _hypType = NB_SEGMENTS;
+    }
+    if ( const StdMeshers_LayerDistribution* ld =
+         dynamic_cast< const StdMeshers_LayerDistribution* >( hyp ))
+    {
+      if ( SMESH_Hypothesis* h = ld->GetLayerDistribution() )
+      {
+        SMESH_Algo::_usedHypList.clear();
+        SMESH_Algo::_usedHypList.push_back( h );
+      }
+    }
+  }
+  void ComputeDistribution(SMESH_MesherHelper& theHelper,
+                           const gp_Pnt&       thePnt1,
+                           const gp_Pnt&       thePnt2,
+                           list< double >&     theParams)
+  {
+    SMESH_Mesh& mesh = *theHelper.GetMesh();
+    TopoDS_Edge edge = BRepBuilderAPI_MakeEdge( thePnt1, thePnt2 );
+
+    SMESH_Hypothesis::Hypothesis_Status aStatus;
+    CheckHypothesis( mesh, edge, aStatus );
+
+    theParams.clear();
+    BRepAdaptor_Curve C3D(edge);
+    double f = C3D.FirstParameter(), l = C3D.LastParameter(), len = thePnt1.Distance( thePnt2 );
+    if ( !StdMeshers_Regular_1D::computeInternalParameters( mesh, C3D, len, f, l, theParams, false))
+    {
+      for ( size_t i = 1; i < 15; ++i )
+        theParams.push_back( i/15 );
+    }
+    else
+    {
+      for (list<double>::iterator itU = theParams.begin(); itU != theParams.end(); ++itU )
+        *itU /= len;
+    }
+  }
+  virtual const list <const SMESHDS_Hypothesis *> &
+  GetUsedHypothesis(SMESH_Mesh &, const TopoDS_Shape &, const bool)
+  {
+    return SMESH_Algo::_usedHypList;
+  }
+  virtual bool CheckHypothesis(SMESH_Mesh&                          aMesh,
+                               const TopoDS_Shape&                  aShape,
+                               SMESH_Hypothesis::Hypothesis_Status& aStatus)
+  {
+    if ( !SMESH_Algo::_usedHypList.empty() )
+      return StdMeshers_Regular_1D::CheckHypothesis( aMesh, aShape, aStatus );
+    return true;
+  }
 };
  
 //================================================================================
@@ -94,7 +162,9 @@ StdMeshers_QuadFromMedialAxis_1D2D::StdMeshers_QuadFromMedialAxis_1D2D(int
   _neededLowerHyps[ 1 ]    = true;  // suppress warning on hiding a global 1D algo
   _neededLowerHyps[ 2 ]    = true;  // suppress warning on hiding a global 2D algo
   _compatibleHypothesis.clear();
-  //_compatibleHypothesis.push_back("ViscousLayers2D");
+  _compatibleHypothesis.push_back("ViscousLayers2D");
+  _compatibleHypothesis.push_back("LayerDistribution2D");
+  _compatibleHypothesis.push_back("NumberOfLayers2D");
 }
 
 //================================================================================
@@ -119,11 +189,47 @@ bool StdMeshers_QuadFromMedialAxis_1D2D::CheckHypothesis(SMESH_Mesh&         aMe
                                                          const TopoDS_Shape& aShape,
                                                          Hypothesis_Status&  aStatus)
 {
+  aStatus = HYP_OK;
+
+  // get one main optional hypothesis
+  const list <const SMESHDS_Hypothesis * >& hyps = GetUsedHypothesis(aMesh, aShape);
+  _hyp2D  = hyps.empty() ? 0 : hyps.front();
+
   return true; // does not require hypothesis
 }
 
 namespace
 {
+  typedef map< const SMDS_MeshNode*, list< const SMDS_MeshNode* > > TMergeMap;
+  
+  //================================================================================
+  /*!
+   * \brief Sinuous face
+   */
+  struct SinuousFace
+  {
+    FaceQuadStruct::Ptr          _quad;
+    vector< TopoDS_Edge >        _edges;
+    vector< TopoDS_Edge >        _sinuSide[2], _shortSide[2];
+    vector< TopoDS_Edge >        _sinuEdges;
+    vector< Handle(Geom_Curve) > _sinuCurves;
+    int                          _nbWires;
+    list< int >                  _nbEdgesInWire;
+    TMergeMap                    _nodesToMerge;
+
+    SinuousFace( const TopoDS_Face& f ): _quad( new FaceQuadStruct )
+    {
+      list< TopoDS_Edge > edges;
+      _nbWires = SMESH_Block::GetOrderedEdges (f, edges, _nbEdgesInWire);
+      _edges.assign( edges.begin(), edges.end() );
+
+      _quad->side.resize( 4 );
+      _quad->face = f;
+    }
+    const TopoDS_Face& Face() const { return _quad->face; }
+    bool IsRing() const { return _shortSide[0].empty() && !_sinuSide[0].empty(); }
+  };
+
   //================================================================================
   /*!
    * \brief Temporary mesh
@@ -136,6 +242,55 @@ namespace
     }
   };
 
+  //================================================================================
+  /*!
+   * \brief Event listener which removes mesh from EDGEs when 2D hyps change
+   */
+  struct EdgeCleaner : public SMESH_subMeshEventListener
+  {
+    int _prevAlgoEvent;
+    EdgeCleaner():
+      SMESH_subMeshEventListener( /*isDeletable=*/true,
+                                  "StdMeshers_QuadFromMedialAxis_1D2D::EdgeCleaner")
+    {
+      _prevAlgoEvent = -1;
+    }
+    virtual void ProcessEvent(const int                       event,
+                              const int                       eventType,
+                              SMESH_subMesh*                  faceSubMesh,
+                              SMESH_subMeshEventListenerData* data,
+                              const SMESH_Hypothesis*         hyp)
+    {
+      if ( eventType == SMESH_subMesh::ALGO_EVENT )
+      {
+        _prevAlgoEvent = event;
+        return;
+      }
+      // SMESH_subMesh::COMPUTE_EVENT
+      if ( _prevAlgoEvent == SMESH_subMesh::REMOVE_HYP ||
+           _prevAlgoEvent == SMESH_subMesh::REMOVE_ALGO ||
+           _prevAlgoEvent == SMESH_subMesh::MODIF_HYP )
+      {
+        SMESH_subMeshIteratorPtr smIt = faceSubMesh->getDependsOnIterator(/*includeSelf=*/false);
+        while ( smIt->more() )
+          smIt->next()->ComputeStateEngine( SMESH_subMesh::CLEAN );
+      }
+      _prevAlgoEvent = -1;
+    }
+  };
+
+  //================================================================================
+  /*!
+   * \brief Return a member of a std::pair
+   */
+  //================================================================================
+
+  template< typename T >
+  T& get( std::pair< T, T >& thePair, bool is2nd )
+  {
+    return is2nd ? thePair.second : thePair.first;
+  }
+
   //================================================================================
   /*!
    * \brief Select two EDGEs from a map, either mapped to least values or to max values
@@ -194,8 +349,8 @@ namespace
       algos[i] = sm->GetAlgo();
     }
 
-    const int nbSegDflt = mesh->GetGen()->GetDefaultNbSegments();
-    double minSegLen    = Precision::Infinite();
+    int nbSegDflt = mesh->GetGen() ? mesh->GetGen()->GetDefaultNbSegments() : 15;
+    double minSegLen = Precision::Infinite();
 
     for ( size_t i = 0; i < theEdges.size(); ++i )
     {
@@ -224,6 +379,7 @@ namespace
         tmpMesh.ShapeToMesh( TopoDS_Shape());
         tmpMesh.ShapeToMesh( theEdges[i] );
         try {
+          if ( !mesh->GetGen() ) continue; // tmp mesh
           mesh->GetGen()->Compute( tmpMesh, theEdges[i], true, true ); // make nodes on VERTEXes
           if ( !algo->Compute( tmpMesh, theEdges[i] ))
             continue;
@@ -331,36 +487,43 @@ namespace
   //================================================================================
   /*!
    * \brief Find EDGEs to discretize using projection from MA
-   *  \param [in] theFace - the FACE to be meshed
-   *  \param [in] theWire - ordered EDGEs of the FACE
-   *  \param [out] theSinuEdges - the EDGEs to discretize using projection from MA
-   *  \param [out] theShortEdges - other EDGEs
+   *  \param [in,out] theSinuFace - the FACE to be meshed
    *  \return bool - OK or not
    *
-   * Is separate all EDGEs into four sides of a quadrangle connected in the order:
+   * It separates all EDGEs into four sides of a quadrangle connected in the order:
    * theSinuEdges[0], theShortEdges[0], theSinuEdges[1], theShortEdges[1]
    */
   //================================================================================
 
   bool getSinuousEdges( SMESH_MesherHelper& theHelper,
-                        const TopoDS_Face&  theFace,
-                        list<TopoDS_Edge>&  theWire,
-                        vector<TopoDS_Edge> theSinuEdges[2],
-                        vector<TopoDS_Edge> theShortEdges[2])
+                        SinuousFace&        theSinuFace)
   {
+    vector<TopoDS_Edge> * theSinuEdges  = & theSinuFace._sinuSide [0];
+    vector<TopoDS_Edge> * theShortEdges = & theSinuFace._shortSide[0];
     theSinuEdges[0].clear();
     theSinuEdges[1].clear();
     theShortEdges[0].clear();
     theShortEdges[1].clear();
-
-    vector<TopoDS_Edge> allEdges( theWire.begin(), theWire.end() );
+   
+    vector<TopoDS_Edge> & allEdges = theSinuFace._edges;
     const size_t nbEdges = allEdges.size();
-    if ( nbEdges < 4 )
+    if ( nbEdges < 4 && theSinuFace._nbWires == 1 )
+      return false;
+
+    if ( theSinuFace._nbWires == 2 ) // ring
+    {
+      size_t nbOutEdges = theSinuFace._nbEdgesInWire.front();
+      theSinuEdges[0].assign ( allEdges.begin(), allEdges.begin() + nbOutEdges );
+      theSinuEdges[1].assign ( allEdges.begin() + nbOutEdges, allEdges.end() );
+      theSinuFace._sinuEdges = allEdges;
+      return true;
+    }
+    if ( theSinuFace._nbWires > 2 )
       return false;
 
     // create MedialAxis to find short edges by analyzing MA branches
     double minSegLen = getMinSegLen( theHelper, allEdges );
-    SMESH_MAT2d::MedialAxis ma( theFace, allEdges, minSegLen );
+    SMESH_MAT2d::MedialAxis ma( theSinuFace.Face(), allEdges, minSegLen * 3 );
 
     // in an initial request case, theFace represents a part of a river with almost parallel banks
     // so there should be two branch points
@@ -430,6 +593,10 @@ namespace
          !vCommon.IsSame( theHelper.IthVertex( 1, theSinuEdges[0].back() )))
       theShortEdges[0].swap( theShortEdges[1] );
 
+    theSinuFace._sinuEdges = theSinuEdges[0];
+    theSinuFace._sinuEdges.insert( theSinuFace._sinuEdges.end(),
+                                   theSinuEdges[1].begin(), theSinuEdges[1].end() );
+
     return ( theShortEdges[0].size() > 0 && theShortEdges[1].size() > 0 &&
              theSinuEdges [0].size() > 0 && theSinuEdges [1].size() > 0 );
 
@@ -437,17 +604,17 @@ namespace
     // therefor we use a complex criterion to find TWO short non-sinuous EDGEs
     // and the rest EDGEs will be treated as sinuous.
     // A short edge should have the following features:
-  // a) straight
-  // b) short
-  // c) with convex corners at ends
-  // d) far from the other short EDGE
+    // a) straight
+    // b) short
+    // c) with convex corners at ends
+    // d) far from the other short EDGE
 
-  // vector< double > isStraightEdge( nbEdges, 0 ); // criterion value
+    // vector< double > isStraightEdge( nbEdges, 0 ); // criterion value
 
-  // // a0) evaluate continuity
-  // const double contiWgt = 0.5; // weight of continuity in the criterion
-  // multimap< int, TopoDS_Edge > continuity;
-  // for ( size_t i = 0; i < nbEdges; ++I )
+    // // a0) evaluate continuity
+    // const double contiWgt = 0.5; // weight of continuity in the criterion
+    // multimap< int, TopoDS_Edge > continuity;
+    // for ( size_t i = 0; i < nbEdges; ++I )
     // {
     //   BRepAdaptor_Curve curve( allEdges[i] );
     //   GeomAbs_Shape C = GeomAbs_CN;
@@ -540,7 +707,8 @@ namespace
   //================================================================================
 
   TopoDS_Edge makeEdgeFromMA( SMESH_MesherHelper&            theHelper,
-                              const SMESH_MAT2d::MedialAxis& theMA )
+                              const SMESH_MAT2d::MedialAxis& theMA,
+                              const double                   theMinSegLen)
   {
     if ( theMA.nbBranches() != 1 )
       return TopoDS_Edge();
@@ -553,14 +721,31 @@ namespace
     TopoDS_Face face = TopoDS::Face( theHelper.GetSubShape() );
     Handle(Geom_Surface) surface = BRep_Tool::Surface( face );
 
+    vector< gp_Pnt > pnt;
+    pnt.reserve( uv.size() * 2 );
+    pnt.push_back( surface->Value( uv[0].X(), uv[0].Y() ));
+    for ( size_t i = 1; i < uv.size(); ++i )
+    {
+      gp_Pnt p = surface->Value( uv[i].X(), uv[i].Y() );
+      int nbDiv = int( p.Distance( pnt.back() ) / theMinSegLen );
+      for ( int iD = 1; iD < nbDiv; ++iD )
+      {
+        double  R = iD / double( nbDiv );
+        gp_XY uvR = uv[i-1] * (1 - R) + uv[i] * R;
+        pnt.push_back( surface->Value( uvR.X(), uvR.Y() ));
+      }
+      pnt.push_back( p );
+    }
+
     // cout << "from salome.geom import geomBuilder" << endl;
     // cout << "geompy = geomBuilder.New(salome.myStudy)" << endl;
-    Handle(TColgp_HArray1OfPnt) points = new TColgp_HArray1OfPnt(1, uv.size());
-    for ( size_t i = 0; i < uv.size(); ++i )
+    Handle(TColgp_HArray1OfPnt) points = new TColgp_HArray1OfPnt(1, pnt.size());
+    for ( size_t i = 0; i < pnt.size(); ++i )
     {
-      gp_Pnt p = surface->Value( uv[i].X(), uv[i].Y() );
+      gp_Pnt& p = pnt[i];
       points->SetValue( i+1, p );
-      //cout << "geompy.MakeVertex( "<< p.X()<<", " << p.Y()<<", " << p.Z()<<" )" << endl;
+      // cout << "geompy.MakeVertex( "<< p.X()<<", " << p.Y()<<", " << p.Z()
+      //      <<" theName = 'p_" << i << "')" << endl;
     }
 
     GeomAPI_Interpolate interpol( points, /*isClosed=*/false, gp::Resolution());
@@ -604,25 +789,47 @@ namespace
 
   bool divideMA( SMESH_MesherHelper&            theHelper,
                  const SMESH_MAT2d::MedialAxis& theMA,
-                 const vector<TopoDS_Edge>&     theSinuEdges,
-                 const size_t                   theSinuSide0Size,
+                 const SinuousFace&             theSinuFace,
                  SMESH_Algo*                    the1dAlgo,
+                 const double                   theMinSegLen,
                  vector<double>&                theMAParams )
   {
-    // check if all EDGEs of one size are meshed, then MA discretization is not needed
+    // Check if all EDGEs of one size are meshed, then MA discretization is not needed
     SMESH_Mesh* mesh = theHelper.GetMesh();
     size_t nbComputedEdges[2] = { 0, 0 };
-    for ( size_t i = 1; i < theSinuEdges.size(); ++i )
-    {
-      bool isComputed = ( ! mesh->GetSubMesh( theSinuEdges[i] )->IsEmpty() );
-      nbComputedEdges[ i < theSinuSide0Size ] += isComputed;
-    }
-    if ( nbComputedEdges[0] == theSinuSide0Size ||
-         nbComputedEdges[1] == theSinuEdges.size() - theSinuSide0Size )
+    for ( size_t iS = 0; iS < 2; ++iS )
+      for ( size_t i = 0; i < theSinuFace._sinuSide[iS].size(); ++i )
+      {
+        const TopoDS_Edge& sinuEdge = theSinuFace._sinuSide[iS][i];
+        SMESH_subMesh*           sm = mesh->GetSubMesh( sinuEdge );
+        bool             isComputed = ( !sm->IsEmpty() );
+        if ( isComputed )
+        {
+          TopAbs_ShapeEnum shape = getHypShape( mesh, sinuEdge );
+          if ( shape == TopAbs_SHAPE || shape <= TopAbs_FACE )
+          {
+            // EDGE computed using global hypothesis -> clear it
+            bool hasComputedFace = false;
+            PShapeIteratorPtr faceIt = theHelper.GetAncestors( sinuEdge, *mesh, TopAbs_FACE );
+            while ( const TopoDS_Shape* face = faceIt->next() )
+              if (( !face->IsSame( theSinuFace.Face() )) &&
+                  ( hasComputedFace = !mesh->GetSubMesh( *face )->IsEmpty() ))
+                break;
+            if ( !hasComputedFace )
+            {
+              sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
+              isComputed = false;
+            }
+          }
+        }
+        nbComputedEdges[ iS ] += isComputed;
+      }
+    if ( nbComputedEdges[0] == theSinuFace._sinuSide[0].size() ||
+         nbComputedEdges[1] == theSinuFace._sinuSide[1].size() )
       return true; // discretization is not needed
 
-
-    TopoDS_Edge branchEdge = makeEdgeFromMA( theHelper, theMA );
+    // Make MA EDGE
+    TopoDS_Edge branchEdge = makeEdgeFromMA( theHelper, theMA, theMinSegLen );
     if ( branchEdge.IsNull() )
       return false;
 
@@ -630,18 +837,24 @@ namespace
     // BRepTools::Write( branchEdge, file);
     // cout << "Write " << file << endl;
 
-    // look for a most local hyps assigned to theSinuEdges
-    TopoDS_Edge edge = theSinuEdges[0];
-    int mostSimpleShape = (int) getHypShape( mesh, edge );
-    for ( size_t i = 1; i < theSinuEdges.size(); ++i )
+
+    // Find 1D algo to mesh branchEdge
+  
+    // look for a most local 1D hyp assigned to the FACE
+    int mostSimpleShape = -1, maxShape = TopAbs_EDGE;
+    TopoDS_Edge edge;
+    for ( size_t i = 0; i < theSinuFace._sinuEdges.size(); ++i )
     {
-      int shapeType = (int) getHypShape( mesh, theSinuEdges[i] );
-      if ( shapeType > mostSimpleShape )
-        edge = theSinuEdges[i];
+      TopAbs_ShapeEnum shapeType = getHypShape( mesh, theSinuFace._sinuEdges[i] );
+      if ( mostSimpleShape < shapeType && shapeType < maxShape )
+      {
+        edge = theSinuFace._sinuEdges[i];
+        mostSimpleShape = shapeType;
+      }
     }
 
     SMESH_Algo* algo = the1dAlgo;
-    if ( mostSimpleShape != TopAbs_SHAPE )
+    if ( mostSimpleShape > -1 )
     {
       algo = mesh->GetSubMesh( edge )->GetAlgo();
       SMESH_Hypothesis::Hypothesis_Status status;
@@ -664,14 +877,13 @@ namespace
 
   //================================================================================
   /*!
-   * \brief Modifies division parameters on MA to make them coincide with projections
-   *        of VERTEXes to MA for a given pair of opposite EDGEs
+   * \brief Select division parameters on MA and make them coincide at ends with
+   *        projections of VERTEXes to MA for a given pair of opposite EDGEs
    *  \param [in] theEdgePairInd - index of the EDGE pair
    *  \param [in] theDivPoints - the BranchPoint's dividing MA into parts each
    *         corresponding to a unique pair of opposite EDGEs
-   *  \param [in,out] theMAParams - the MA division parameters to modify
-   *  \param [in,out] theParBeg - index of the 1st division point for the given EDGE pair
-   *  \param [in,out] theParEnd - index of the last division point for the given EDGE pair
+   *  \param [in] theMAParams - the MA division parameters
+   *  \param [out] theSelectedMAParams - the selected MA parameters
    *  \return bool - is OK
    */
   //================================================================================
@@ -686,11 +898,49 @@ namespace
       theSelectedMAParams = theMAParams;
       return true;
     }
-    if ( theEdgePairInd > theDivPoints.size() )
+    if ( theEdgePairInd > theDivPoints.size() || theMAParams.empty() )
       return false;
 
-    // TODO
-    return false;
+    // find a range of params to copy
+
+    double par1 = 0;
+    size_t iPar1 = 0;
+    if ( theEdgePairInd > 0 )
+    {
+      const SMESH_MAT2d::BranchPoint& bp = theDivPoints[ theEdgePairInd-1 ];
+      bp._branch->getParameter( bp, par1 );
+      while ( theMAParams[ iPar1 ] < par1 ) ++iPar1;
+      if ( par1 - theMAParams[ iPar1-1 ] < theMAParams[ iPar1 ] - par1 )
+        --iPar1;
+    }
+
+    double par2 = 1;
+    size_t iPar2 = theMAParams.size() - 1;
+    if ( theEdgePairInd < theDivPoints.size() )
+    {
+      const SMESH_MAT2d::BranchPoint& bp = theDivPoints[ theEdgePairInd ];
+      bp._branch->getParameter( bp, par2 );
+      iPar2 = iPar1;
+      while ( theMAParams[ iPar2 ] < par2 ) ++iPar2;
+      if ( par2 - theMAParams[ iPar2-1 ] < theMAParams[ iPar2 ] - par2 )
+        --iPar2;
+    }
+
+    theSelectedMAParams.assign( theMAParams.begin() + iPar1,
+                                theMAParams.begin() + iPar2 + 1 );
+
+    // adjust theSelectedMAParams to fit between par1 and par2
+
+    double d = par1 - theSelectedMAParams[0];
+    double f = ( par2 - par1 ) / ( theSelectedMAParams.back() - theSelectedMAParams[0] );
+
+    for ( size_t i = 0; i < theSelectedMAParams.size(); ++i )
+    {
+      theSelectedMAParams[i] += d;
+      theSelectedMAParams[i] = par1 + ( theSelectedMAParams[i] - par1 ) * f;
+    }
+
+    return true;
   }
 
   //--------------------------------------------------------------------------------
@@ -701,10 +951,16 @@ namespace
     double               _u;
     int                  _edgeInd; // index in theSinuEdges vector
 
-    NodePoint(const SMDS_MeshNode* n=0 ): _node(n), _u(0), _edgeInd(-1) {}
+    NodePoint(): _node(0), _u(0), _edgeInd(-1) {}
+    NodePoint(const SMDS_MeshNode* n, double u, size_t iEdge ): _node(n), _u(u), _edgeInd(iEdge) {}
     NodePoint(double u, size_t iEdge) : _node(0), _u(u), _edgeInd(iEdge) {}
     NodePoint(const SMESH_MAT2d::BoundaryPoint& p) : _node(0), _u(p._param), _edgeInd(p._edgeIndex) {}
+    gp_Pnt Point(const vector< Handle(Geom_Curve) >& curves) const
+    {
+      return _node ? SMESH_TNodeXYZ(_node) : curves[ _edgeInd ]->Value( _u );
+    }
   };
+  typedef multimap< double, pair< NodePoint, NodePoint > > TMAPar2NPoints;
 
   //================================================================================
   /*!
@@ -717,23 +973,28 @@ namespace
    */
   //================================================================================
 
-  bool findVertex( NodePoint&                  theNodePnt,
-                   const vector<TopoDS_Edge>&  theSinuEdges,
-                   SMESHDS_Mesh*               theMeshDS)
+  bool findVertexAndNode( NodePoint&                  theNodePnt,
+                          const vector<TopoDS_Edge>&  theSinuEdges,
+                          SMESHDS_Mesh*               theMeshDS = 0,
+                          size_t                      theEdgeIndPrev = 0,
+                          size_t                      theEdgeIndNext = 0)
   {
     if ( theNodePnt._edgeInd >= theSinuEdges.size() )
       return false;
 
     double f,l;
     BRep_Tool::Range( theSinuEdges[ theNodePnt._edgeInd ], f,l );
+    const double tol = 1e-3 * ( l - f );
 
     TopoDS_Vertex V;
-    if      ( Abs( f - theNodePnt._u ))
+    if      ( Abs( f - theNodePnt._u ) < tol )
       V = SMESH_MesherHelper::IthVertex( 0, theSinuEdges[ theNodePnt._edgeInd ], /*CumOri=*/false);
-    else if ( Abs( l - theNodePnt._u ))
+    else if ( Abs( l - theNodePnt._u ) < tol )
       V = SMESH_MesherHelper::IthVertex( 1, theSinuEdges[ theNodePnt._edgeInd ], /*CumOri=*/false);
+    else if ( theEdgeIndPrev != theEdgeIndNext )
+      TopExp::CommonVertex( theSinuEdges[theEdgeIndPrev], theSinuEdges[theEdgeIndNext], V );
 
-    if ( !V.IsNull() )
+    if ( !V.IsNull() && theMeshDS )
     {
       theNodePnt._node = SMESH_Algo::VertexNode( V, theMeshDS );
       if ( !theNodePnt._node )
@@ -742,9 +1003,8 @@ namespace
         theNodePnt._node = theMeshDS->AddNode( p.X(), p.Y(), p.Z() );
         theMeshDS->SetNodeOnVertex( theNodePnt._node, V );
       }
-      return true;
     }
-    return false;
+    return !V.IsNull();
   }
 
   //================================================================================
@@ -752,31 +1012,78 @@ namespace
    * \brief Add to the map of NodePoint's those on VERTEXes
    *  \param [in,out] theHelper - the helper
    *  \param [in] theMA - Medial Axis
+   *  \param [in] theMinSegLen - minimal segment length
    *  \param [in] theDivPoints - projections of VERTEXes to MA
    *  \param [in] theSinuEdges - the sinuous EDGEs
    *  \param [in] theSideEdgeIDs - indices of sinuous EDGEs per side
    *  \param [in] theIsEdgeComputed - is sinuous EGDE is meshed
    *  \param [in,out] thePointsOnE - the map to fill
+   *  \param [out] theNodes2Merge - the map of nodes to merge
    */
   //================================================================================
 
-  bool projectVertices( SMESH_MesherHelper&                           theHelper,
-                        const SMESH_MAT2d::MedialAxis&                theMA,
-                        const vector< SMESH_MAT2d::BranchPoint >&     theDivPoints,
-                        const vector<TopoDS_Edge>&                    theSinuEdges,
-                        //const vector< int >                           theSideEdgeIDs[2],
-                        const vector< bool >&                         theIsEdgeComputed,
-                        map< double, pair< NodePoint, NodePoint > > & thePointsOnE)
+  bool projectVertices( SMESH_MesherHelper&                 theHelper,
+                        const SMESH_MAT2d::MedialAxis&      theMA,
+                        vector< SMESH_MAT2d::BranchPoint >& theDivPoints,
+                        const vector< std::size_t > &       theEdgeIDs1,
+                        const vector< std::size_t > &       theEdgeIDs2,
+                        const vector< bool >&               theIsEdgeComputed,
+                        TMAPar2NPoints &                    thePointsOnE,
+                        SinuousFace&                        theSinuFace)
   {
     if ( theDivPoints.empty() )
       return true;
 
     SMESHDS_Mesh* meshDS = theHelper.GetMeshDS();
+    const vector< TopoDS_Edge >&     theSinuEdges = theSinuFace._sinuEdges;
+    const vector< Handle(Geom_Curve) >& theCurves = theSinuFace._sinuCurves;
 
     double uMA;
-    SMESH_MAT2d::BoundaryPoint bp[2];
+    SMESH_MAT2d::BoundaryPoint bp[2]; // 2 sinuous sides
     const SMESH_MAT2d::Branch& branch = *theMA.getBranch(0);
+    {
+      // add to thePointsOnE NodePoint's of ends of theSinuEdges
+      if ( !branch.getBoundaryPoints( 0., bp[0], bp[1] ) ||
+           !theMA.getBoundary().moveToClosestEdgeEnd( bp[0] )) return false;
+      if ( !theSinuFace.IsRing() &&
+           !theMA.getBoundary().moveToClosestEdgeEnd( bp[1] )) return false;
+      NodePoint np0( bp[0] ), np1( bp[1] );
+      findVertexAndNode( np0, theSinuEdges, meshDS );
+      findVertexAndNode( np1, theSinuEdges, meshDS );
+      thePointsOnE.insert( make_pair( -0.1, make_pair( np0, np1 )));
+    }
+    if ( !theSinuFace.IsRing() )
+    {
+      if ( !branch.getBoundaryPoints( 1., bp[0], bp[1] ) ||
+           !theMA.getBoundary().moveToClosestEdgeEnd( bp[0] ) ||
+           !theMA.getBoundary().moveToClosestEdgeEnd( bp[1] )) return false;
+      NodePoint np0( bp[0] ), np1( bp[1] );
+      findVertexAndNode( np0, theSinuEdges, meshDS );
+      findVertexAndNode( np1, theSinuEdges, meshDS );
+      thePointsOnE.insert( make_pair( 1.1, make_pair( np0, np1)));
+    }
+    else
+    {
+      // project a VERTEX of outer sinuous side corresponding to branch(0.)
+      // which is not included into theDivPoints
+      if ( ! ( theDivPoints[0]._iEdge     == 0 &&
+               theDivPoints[0]._edgeParam == 0. )) // recursive call
+      {
+        SMESH_MAT2d::BranchPoint brp( &branch, 0, 0 );
+        vector< SMESH_MAT2d::BranchPoint > divPoint( 1, brp );
+        vector< std::size_t > edgeIDs1(2), edgeIDs2(2);
+        edgeIDs1[0] = theEdgeIDs1.back();
+        edgeIDs1[1] = theEdgeIDs1[0];
+        edgeIDs2[0] = theEdgeIDs2.back();
+        edgeIDs2[1] = theEdgeIDs2[0];
+        projectVertices( theHelper, theMA, divPoint, edgeIDs1, edgeIDs2,
+                         theIsEdgeComputed, thePointsOnE, theSinuFace );
+      }
+    }
+
+    // project theDivPoints
 
+    TMAPar2NPoints::iterator u2NP;
     for ( size_t i = 0; i < theDivPoints.size(); ++i )
     {
       if ( !branch.getParameter( theDivPoints[i], uMA ))
@@ -784,51 +1091,449 @@ namespace
       if ( !branch.getBoundaryPoints( theDivPoints[i], bp[0], bp[1] ))
         return false;
 
-      NodePoint np[2] = { NodePoint( bp[0] ),
-                          NodePoint( bp[1] ) };
-      bool isVertex[2] = { findVertex( np[0], theSinuEdges, meshDS ),
-                           findVertex( np[1], theSinuEdges, meshDS )};
+      NodePoint  np[2] = {
+        NodePoint( bp[0] ),
+        NodePoint( bp[1] )
+      };
+      bool isVertex[2] = {
+        findVertexAndNode( np[0], theSinuEdges, meshDS, theEdgeIDs1[i], theEdgeIDs1[i+1] ),
+        findVertexAndNode( np[1], theSinuEdges, meshDS, theEdgeIDs2[i], theEdgeIDs2[i+1] )
+      };
+      const size_t iVert = isVertex[0] ? 0 : 1; // side with a VERTEX
+      const size_t iNode = 1 - iVert;           // opposite (meshed?) side
+
+      if ( isVertex[0] != isVertex[1] ) // try to find an opposite VERTEX
+      {
+        theMA.getBoundary().moveToClosestEdgeEnd( bp[iNode] ); // EDGE -> VERTEX
+        SMESH_MAT2d::BranchPoint brp;
+        theMA.getBoundary().getBranchPoint( bp[iNode], brp );  // WIRE -> MA
+        SMESH_MAT2d::BoundaryPoint bp2[2];
+        branch.getBoundaryPoints( brp, bp2[0], bp2[1] );       // MA -> WIRE
+        NodePoint np2[2] = { NodePoint( bp2[0]), NodePoint( bp2[1]) };
+        findVertexAndNode( np2[0], theSinuEdges, meshDS );
+        findVertexAndNode( np2[1], theSinuEdges, meshDS );
+        if ( np2[ iVert ]._node == np[ iVert ]._node &&
+             np2[ iNode ]._node)
+        {
+          np[ iNode ] = np2[ iNode ];
+          isVertex[ iNode ] = true;
+        }
+      }
 
-      map< double, pair< NodePoint, NodePoint > >::iterator u2NP =
-        thePointsOnE.insert( make_pair( uMA, make_pair( np[0], np[1]))).first;
+      u2NP = thePointsOnE.insert( make_pair( uMA, make_pair( np[0], np[1])));
 
+      if ( !isVertex[0] && !isVertex[1] ) return false; // error
       if ( isVertex[0] && isVertex[1] )
         continue;
 
-      bool isOppComputed = theIsEdgeComputed[ np[ isVertex[0] ]._edgeInd ];
-
+      bool isOppComputed = theIsEdgeComputed[ np[ iNode ]._edgeInd ];
       if ( !isOppComputed )
         continue;
 
       // a VERTEX is projected on a meshed EDGE; there are two options:
-      // - a projected point is joined with a closet node if a strip between this and neighbor
-      // projection is wide enough; joining is done by setting the same node to the BoundaryPoint
-      // - a neighbor projection is merged this this one if it too close; a node of deleted
+      // 1) a projected point is joined with a closet node if a strip between this and neighbor
+      // projection is WIDE enough; joining is done by creating a node coincident with the
+      //  existing node which will be merged together after all;
+      // 2) a neighbor projection is merged with this one if it is TOO CLOSE; a node of deleted
       // projection is set to the BoundaryPoint of this projection
 
+      // evaluate distance to neighbor projections
+      const double rShort = 0.33;
+      bool isShortPrev[2], isShortNext[2], isPrevCloser[2];
+      TMAPar2NPoints::iterator u2NPPrev = u2NP, u2NPNext = u2NP;
+      --u2NPPrev; ++u2NPNext;
+      // bool hasPrev = ( u2NP     != thePointsOnE.begin() );
+      // bool hasNext = ( u2NPNext != thePointsOnE.end() );
+      // if ( !hasPrev ) u2NPPrev = u2NP0;
+      // if ( !hasNext ) u2NPNext = u2NP1;
+      for ( int iS = 0; iS < 2; ++iS ) // side with Vertex and side with Nodes
+      {
+        NodePoint np     = get( u2NP->second,     iS );
+        NodePoint npPrev = get( u2NPPrev->second, iS );
+        NodePoint npNext = get( u2NPNext->second, iS );
+        gp_Pnt     p     = np    .Point( theCurves );
+        gp_Pnt     pPrev = npPrev.Point( theCurves );
+        gp_Pnt     pNext = npNext.Point( theCurves );
+        double  distPrev = p.Distance( pPrev );
+        double  distNext = p.Distance( pNext );
+        double         r = distPrev / ( distPrev + distNext );
+        isShortPrev [iS] = ( r < rShort );
+        isShortNext [iS] = (( 1 - r ) > ( 1 - rShort ));
+        isPrevCloser[iS] = (( r < 0.5 ) && ( u2NPPrev->first > 0 ));
+      }
+      // if ( !hasPrev ) isShortPrev[0] = isShortPrev[1] = false;
+      // if ( !hasNext ) isShortNext[0] = isShortNext[1] = false;
+
+      TMAPar2NPoints::iterator u2NPClose;
 
+      if (( isShortPrev[0] && isShortPrev[1] ) || // option 2) -> remove a too close projection
+          ( isShortNext[0] && isShortNext[1] ))
+      {
+        u2NPClose = isPrevCloser[0] ? u2NPPrev : u2NPNext;
+        NodePoint& npProj  = get( u2NP->second,      iNode ); // NP of VERTEX projection
+        NodePoint npCloseN = get( u2NPClose->second, iNode ); // NP close to npProj
+        NodePoint npCloseV = get( u2NPClose->second, iVert ); // NP close to VERTEX
+        if ( !npCloseV._node )
+        {
+          npProj = npCloseN;
+          thePointsOnE.erase( isPrevCloser[0] ? u2NPPrev : u2NPNext );
+          continue;
+        }
+        else
+        {
+          // can't remove the neighbor projection as it is also from VERTEX, -> option 1)
+        }
+      }
+      // else: option 1) - wide enough -> "duplicate" existing node
+      {
+        u2NPClose = isPrevCloser[ iNode ] ? u2NPPrev : u2NPNext;
+        NodePoint& npProj   = get( u2NP->second,      iNode ); // NP of VERTEX projection
+        NodePoint& npCloseN = get( u2NPClose->second, iNode ); // NP close to npProj
+        npProj = npCloseN;
+        npProj._node = 0;
+        //npProj._edgeInd = npCloseN._edgeInd;
+        // npProj._u       = npCloseN._u + 1e-3 * Abs( get( u2NPPrev->second, iNode )._u -
+        //                                             get( u2NPNext->second, iNode )._u );
+        // gp_Pnt        p = npProj.Point( theCurves );
+        // npProj._node    = meshDS->AddNode( p.X(), p.Y(), p.Z() );
+        // meshDS->SetNodeOnEdge( npProj._node, theSinuEdges[ npProj._edgeInd ], npProj._u  );
+
+        //theNodes2Merge[ npCloseN._node ].push_back( npProj._node );
+      }
     }
+
+    // remove auxiliary NodePoint's of ends of theSinuEdges
+    for ( u2NP = thePointsOnE.begin(); u2NP->first < 0; )
+      thePointsOnE.erase( u2NP++ );
+    thePointsOnE.erase( 1.1 );
+
     return true;
   }
 
+  double getUOnEdgeByPoint( const size_t     iEdge,
+                            const NodePoint* point,
+                            SinuousFace&     sinuFace )
+  {
+    if ( point->_edgeInd == iEdge )
+      return point->_u;
+
+    TopoDS_Vertex V0 = TopExp::FirstVertex( sinuFace._sinuEdges[ iEdge ]);
+    TopoDS_Vertex V1 = TopExp::LastVertex ( sinuFace._sinuEdges[ iEdge ]);
+    gp_Pnt p0 = BRep_Tool::Pnt( V0 );
+    gp_Pnt p1 = BRep_Tool::Pnt( V1 );
+    gp_Pnt  p = point->Point( sinuFace._sinuCurves );
+
+    double f,l;
+    BRep_Tool::Range( sinuFace._sinuEdges[ iEdge ], f,l );
+    return p.SquareDistance( p0 ) < p.SquareDistance( p1 ) ? f : l;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Move coincident nodes to make node params on EDGE unique
+   *  \param [in] theHelper - the helper
+   *  \param [in] thePointsOnE - nodes on two opposite river sides
+   *  \param [in] theSinuFace - the sinuous FACE
+   *  \param [out] theNodes2Merge - the map of nodes to merge
+   */
+  //================================================================================
+
+  void separateNodes( SMESH_MesherHelper&            theHelper,
+                      const SMESH_MAT2d::MedialAxis& theMA,
+                      TMAPar2NPoints &               thePointsOnE,
+                      SinuousFace&                   theSinuFace,
+                      const vector< bool >&          theIsComputedEdge)
+  {
+    if ( thePointsOnE.size() < 2 )
+      return;
+
+    SMESHDS_Mesh* meshDS = theHelper.GetMeshDS();
+    const vector<TopoDS_Edge>&    theSinuEdges = theSinuFace._sinuEdges;
+    const vector< Handle(Geom_Curve) >& curves = theSinuFace._sinuCurves;
+
+    SMESH_MAT2d::BoundaryPoint bp[2];
+    const SMESH_MAT2d::Branch& branch = *theMA.getBranch(0);
+
+    typedef TMAPar2NPoints::iterator TIterator;
+
+    for ( int iSide = 0; iSide < 2; ++iSide ) // loop on two sinuous sides
+    {
+      // get a tolerance to compare points
+      double tol = Precision::Confusion();
+      for ( size_t i = 0; i < theSinuFace._sinuSide[ iSide ].size(); ++i )
+        tol = Max( tol , BRep_Tool::Tolerance( theSinuFace._sinuSide[ iSide ][ i ]));
+
+      // find coincident points
+      TIterator u2NP = thePointsOnE.begin();
+      vector< TIterator > sameU2NP( 1, u2NP++ );
+      while ( u2NP != thePointsOnE.end() )
+      {
+        for ( ; u2NP != thePointsOnE.end(); ++u2NP )
+        {
+          NodePoint& np1 = get( sameU2NP.back()->second, iSide );
+          NodePoint& np2 = get( u2NP           ->second, iSide );
+
+          if (( !np1._node || !np2._node ) &&
+              ( np1.Point( curves ).SquareDistance( np2.Point( curves )) < tol*tol ))
+          {
+            sameU2NP.push_back( u2NP );
+          }
+          else if ( sameU2NP.size() == 1 )
+          {
+            sameU2NP[ 0 ] = u2NP;
+          }
+          else
+          {
+            break;
+          }
+        }
+
+        if ( sameU2NP.size() > 1 )
+        {
+          // find an existing node on VERTEX among sameU2NP and get underlying EDGEs
+          const SMDS_MeshNode* existingNode = 0;
+          set< int > edgeInds;
+          NodePoint* np;
+          for ( size_t i = 0; i < sameU2NP.size(); ++i )
+          {
+            np = &get( sameU2NP[i]->second, iSide );
+            if ( np->_node )
+              if ( !existingNode || np->_node->GetPosition()->GetDim() == 0 )
+                existingNode = np->_node;
+            edgeInds.insert( np->_edgeInd );
+          }
+          list< const SMDS_MeshNode* >& mergeNodes = theSinuFace._nodesToMerge[ existingNode ];
+
+          TIterator u2NPprev = sameU2NP.front();
+          TIterator u2NPnext = sameU2NP.back() ;
+          if ( u2NPprev->first < 0. ) ++u2NPprev;
+          if ( u2NPnext->first > 1. ) --u2NPnext;
+
+          set< int >::iterator edgeID = edgeInds.begin();
+          for ( ; edgeID != edgeInds.end(); ++edgeID )
+          {
+            // get U range on iEdge within which the equal points will be distributed
+            double u0, u1;
+            np = &get( u2NPprev->second, iSide );
+            u0 = getUOnEdgeByPoint( *edgeID, np, theSinuFace );
+
+            np = &get( u2NPnext->second, iSide );
+            u1 = getUOnEdgeByPoint( *edgeID, np, theSinuFace );
+
+            if ( u0 == u1 )
+            {
+              if ( u2NPprev != thePointsOnE.begin() ) --u2NPprev;
+              if ( u2NPnext != --thePointsOnE.end() ) ++u2NPnext;
+              np = &get( u2NPprev->second, iSide );
+              u0 = getUOnEdgeByPoint( *edgeID, np, theSinuFace );
+              np = &get( u2NPnext->second, iSide );
+              u1 = getUOnEdgeByPoint( *edgeID, np, theSinuFace );
+            }
+
+            // distribute points and create nodes
+            double du = ( u1 - u0 ) / ( sameU2NP.size() + 1 /*!existingNode*/ );
+            double u  = u0 + du;
+            for ( size_t i = 0; i < sameU2NP.size(); ++i )
+            {
+              np = &get( sameU2NP[i]->second, iSide );
+              if ( !np->_node && *edgeID == np->_edgeInd )
+              {
+                np->_u = u;
+                u += du;
+                gp_Pnt p = np->Point( curves );
+                np->_node = meshDS->AddNode( p.X(), p.Y(), p.Z() );
+                meshDS->SetNodeOnEdge( np->_node, theSinuEdges[ *edgeID ], np->_u  );
+
+                if ( theIsComputedEdge[ *edgeID ])
+                  mergeNodes.push_back( np->_node );
+              }
+            }
+          }
+
+          sameU2NP.resize( 1 );
+          u2NP = ++sameU2NP.back();
+          sameU2NP[ 0 ] = u2NP;
+
+        } // if ( sameU2NP.size() > 1 )
+      } // while ( u2NP != thePointsOnE.end() )
+    } // for ( int iSide = 0; iSide < 2; ++iSide )
+
+    return;
+  } // separateNodes()
+
+  //================================================================================
+  /*!
+   * \brief Setup sides of SinuousFace::_quad
+   *  \param [in] theHelper - helper
+   *  \param [in] thePointsOnEdges - NodePoint's on sinuous sides
+   *  \param [in,out] theSinuFace - the FACE
+   *  \param [in] the1dAlgo - algorithm to use for radial discretization of a ring FACE
+   *  \return bool - is OK
+   */
+  //================================================================================
+
+  bool setQuadSides(SMESH_MesherHelper&   theHelper,
+                    const TMAPar2NPoints& thePointsOnEdges,
+                    SinuousFace&          theFace,
+                    SMESH_Algo*           the1dAlgo)
+  {
+    SMESH_Mesh*               mesh = theHelper.GetMesh();
+    const TopoDS_Face&        face = theFace._quad->face;
+    SMESH_ProxyMesh::Ptr proxyMesh = StdMeshers_ViscousLayers2D::Compute( *mesh, face );
+    if ( !proxyMesh )
+      return false;
+
+    list< TopoDS_Edge > side[4];
+    side[0].insert( side[0].end(), theFace._shortSide[0].begin(), theFace._shortSide[0].end() );
+    side[1].insert( side[1].end(), theFace._sinuSide[1].begin(),  theFace._sinuSide[1].end() );
+    side[2].insert( side[2].end(), theFace._shortSide[1].begin(), theFace._shortSide[1].end() );
+    side[3].insert( side[3].end(), theFace._sinuSide[0].begin(),  theFace._sinuSide[0].end() );
+
+    for ( int i = 0; i < 4; ++i )
+    {
+      theFace._quad->side[i] = StdMeshers_FaceSide::New( face, side[i], mesh, i < QUAD_TOP_SIDE,
+                                                         /*skipMediumNodes=*/true, proxyMesh );
+    }
+
+    if ( theFace.IsRing() )
+    {
+      // --------------------------------------
+      // Discretize a ring in radial direction
+      // --------------------------------------
+
+      if ( thePointsOnEdges.size() < 4 )
+        return false;
+
+      // find most distant opposite nodes
+      double maxDist = 0, dist;
+      TMAPar2NPoints::const_iterator u2NPdist, u2NP = thePointsOnEdges.begin();
+      for ( ; u2NP != thePointsOnEdges.end(); ++u2NP )
+      {
+        SMESH_TNodeXYZ        xyz( u2NP->second.first._node ); // node out
+        dist = xyz.SquareDistance( u2NP->second.second._node );// node in
+        if ( dist > maxDist )
+        {
+          u2NPdist = u2NP;
+          maxDist = dist;
+        }
+      }
+      // compute distribution of radial nodes
+      list< double > params; // normalized params
+      static_cast< StdMeshers_QuadFromMedialAxis_1D2D::Algo1D* >
+        ( the1dAlgo )->ComputeDistribution( theHelper,
+                                            SMESH_TNodeXYZ( u2NPdist->second.first._node ),
+                                            SMESH_TNodeXYZ( u2NPdist->second.second._node ),
+                                            params );
+
+      // add a radial quad side
+      u2NP = thePointsOnEdges.begin();
+      const SMDS_MeshNode* nOut = u2NP->second.first._node;
+      const SMDS_MeshNode*  nIn = u2NP->second.second._node;
+      nOut = proxyMesh->GetProxyNode( nOut );
+      nIn  = proxyMesh->GetProxyNode( nIn );
+      gp_XY uvOut = theHelper.GetNodeUV( face, nOut );
+      gp_XY uvIn  = theHelper.GetNodeUV( face, nIn );
+      Handle(Geom_Surface) surface = BRep_Tool::Surface( face );
+      UVPtStructVec uvsNew; UVPtStruct uvPt;
+      uvPt.node = nOut;
+      uvPt.u    = uvOut.X();
+      uvPt.v    = uvOut.Y();
+      uvsNew.push_back( uvPt );
+      for (list<double>::iterator itU = params.begin(); itU != params.end(); ++itU )
+      {
+        gp_XY uv  = ( 1 - *itU ) * uvOut + *itU * uvIn;
+        gp_Pnt p  = surface->Value( uv.X(), uv.Y() );
+        uvPt.node = theHelper.AddNode( p.X(), p.Y(), p.Z(), /*id=*/0, uv.X(), uv.Y() );
+        uvPt.u    = uv.X();
+        uvPt.v    = uv.Y();
+        uvsNew.push_back( uvPt );
+      }
+      uvPt.node = nIn;
+      uvPt.u    = uvIn.X();
+      uvPt.v    = uvIn.Y();
+      uvsNew.push_back( uvPt );
+
+      theFace._quad->side[ 0 ] = StdMeshers_FaceSide::New( uvsNew );
+      theFace._quad->side[ 2 ] = theFace._quad->side[ 0 ];
+
+      if ( theFace._quad->side[ 1 ].GetUVPtStruct().empty() ||
+           theFace._quad->side[ 3 ].GetUVPtStruct().empty() )
+        return false;
+
+      // assure that the outer sinuous side starts at nOut
+      if ( theFace._sinuSide[0].size() > 1 )
+      {
+        const UVPtStructVec& uvsOut = theFace._quad->side[ 3 ].GetUVPtStruct(); // _sinuSide[0]
+        size_t i; // find UVPtStruct holding nOut
+        for ( i = 0; i < uvsOut.size(); ++i )
+          if ( nOut == uvsOut[i].node )
+            break;
+        if ( i == uvsOut.size() )
+          return false;
+
+        if ( i != 0  &&  i != uvsOut.size()-1 )
+        {
+          // create a new OUT quad side
+          uvsNew.clear();
+          uvsNew.reserve( uvsOut.size() );
+          uvsNew.insert( uvsNew.end(), uvsOut.begin() + i, uvsOut.end() );
+          uvsNew.insert( uvsNew.end(), uvsOut.begin() + 1, uvsOut.begin() + i + 1);
+          theFace._quad->side[ 3 ] = StdMeshers_FaceSide::New( uvsNew );
+        }
+      }
+
+      // rotate the IN side if opposite nodes of IN and OUT sides don't match
+      const SMDS_MeshNode * nIn0 = theFace._quad->side[ 1 ].First().node;
+      if ( nIn0 != nIn )
+      {
+        nIn  = proxyMesh->GetProxyNode( nIn );
+        const UVPtStructVec& uvsIn = theFace._quad->side[ 1 ].GetUVPtStruct(); // _sinuSide[1]
+        size_t i; // find UVPtStruct holding nIn
+        for ( i = 0; i < uvsIn.size(); ++i )
+          if ( nIn == uvsIn[i].node )
+            break;
+        if ( i == uvsIn.size() )
+          return false;
+
+        // create a new IN quad side
+        uvsNew.clear();
+        uvsNew.reserve( uvsIn.size() );
+        uvsNew.insert( uvsNew.end(), uvsIn.begin() + i, uvsIn.end() );
+        uvsNew.insert( uvsNew.end(), uvsIn.begin() + 1, uvsIn.begin() + i + 1);
+        theFace._quad->side[ 1 ] = StdMeshers_FaceSide::New( uvsNew );
+      }
+
+      if ( theFace._quad->side[ 1 ].GetUVPtStruct().empty() ||
+           theFace._quad->side[ 3 ].GetUVPtStruct().empty() )
+        return false;
+
+    } // if ( theFace.IsRing() )
+
+    return true;
+
+  } // setQuadSides()
+
   //================================================================================
   /*!
    * \brief Divide the sinuous EDGEs by projecting the division point of Medial
    *        Axis to the EGDEs
    *  \param [in] theHelper - the helper
+   *  \param [in] theMinSegLen - minimal segment length
    *  \param [in] theMA - the Medial Axis
    *  \param [in] theMAParams - parameters of division points of \a theMA
    *  \param [in] theSinuEdges - the EDGEs to make nodes on
    *  \param [in] theSinuSide0Size - the number of EDGEs in the 1st sinuous side
+   *  \param [in] the1dAlgo - algorithm to use for radial discretization of a ring FACE
    *  \return bool - is OK or not
    */
   //================================================================================
 
   bool computeSinuEdges( SMESH_MesherHelper&        theHelper,
+                         double                     /*theMinSegLen*/,
                          SMESH_MAT2d::MedialAxis&   theMA,
                          vector<double>&            theMAParams,
-                         const vector<TopoDS_Edge>& theSinuEdges,
-                         const size_t               theSinuSide0Size)
+                         SinuousFace&               theSinuFace,
+                         SMESH_Algo*                the1dAlgo)
   {
     if ( theMA.nbBranches() != 1 )
       return false;
@@ -842,10 +1547,13 @@ namespace
     SMESHDS_Mesh* meshDS = theHelper.GetMeshDS();
     double f,l;
 
-    vector< Handle(Geom_Curve) > curves ( theSinuEdges.size() );
-    vector< int >                edgeIDs( theSinuEdges.size() );
-    vector< bool >            isComputed( theSinuEdges.size() );
-    //bool hasComputed = false;
+    // get data of sinuous EDGEs and remove unnecessary nodes
+    const vector< TopoDS_Edge >& theSinuEdges = theSinuFace._sinuEdges;
+    vector< Handle(Geom_Curve) >& curves      = theSinuFace._sinuCurves;
+    vector< int >                edgeIDs   ( theSinuEdges.size() ); // IDs in the main shape
+    vector< bool >               isComputed( theSinuEdges.size() );
+    curves.resize( theSinuEdges.size(), 0 );
+    bool                         allComputed = true;
     for ( size_t i = 0; i < theSinuEdges.size(); ++i )
     {
       curves[i] = BRep_Tool::Curve( theSinuEdges[i], f,l );
@@ -854,32 +1562,52 @@ namespace
       SMESH_subMesh* sm = mesh->GetSubMesh( theSinuEdges[i] );
       edgeIDs   [i] = sm->GetId();
       isComputed[i] = ( !sm->IsEmpty() );
-      // if ( isComputed[i] )
-      //   hasComputed = true;
+      if ( !isComputed[i] )
+        allComputed = false;
     }
 
     const SMESH_MAT2d::Branch& branch = *theMA.getBranch(0);
     SMESH_MAT2d::BoundaryPoint bp[2];
 
-    vector< std::size_t > edgeIDs1, edgeIDs2;
+    vector< std::size_t > edgeIDs1, edgeIDs2; // indices in theSinuEdges
     vector< SMESH_MAT2d::BranchPoint > divPoints;
-    branch.getOppositeGeomEdges( edgeIDs1, edgeIDs2, divPoints );
+    if ( !allComputed )
+      branch.getOppositeGeomEdges( edgeIDs1, edgeIDs2, divPoints );
+
     for ( size_t i = 0; i < edgeIDs1.size(); ++i )
       if ( isComputed[ edgeIDs1[i]] &&
-           isComputed[ edgeIDs2[i]])
-        return false;
+           isComputed[ edgeIDs2[i]] )
+      {
+        int nbNodes1 = meshDS->MeshElements(edgeIDs[ edgeIDs1[i]] )->NbNodes();
+        int nbNodes2 = meshDS->MeshElements(edgeIDs[ edgeIDs2[i]] )->NbNodes();
+        if ( nbNodes1 != nbNodes2 )
+          return false;
+        if (( i-1 >= 0 ) &&
+            ( edgeIDs1[i-1] == edgeIDs1[i] ||
+              edgeIDs2[i-1] == edgeIDs2[i] ))
+          return false;
+        if (( i+1 < edgeIDs1.size() ) &&
+            ( edgeIDs1[i+1] == edgeIDs1[i] ||
+              edgeIDs2[i+1] == edgeIDs2[i] ))
+          return false;
+      }
 
-    // map param on MA to parameters of nodes on a pair of theSinuEdges
-    typedef map< double, pair< NodePoint, NodePoint > > TMAPar2NPoints;
+    // map (param on MA) to (parameters of nodes on a pair of theSinuEdges)
     TMAPar2NPoints pointsOnE;
     vector<double> maParams;
+    set<int>       projectedEdges; // treated EDGEs which 'isComputed'
 
     // compute params of nodes on EDGEs by projecting division points from MA
-    //const double tol = 1e-5 * theMAParams.back();
-    size_t iEdgePair = 0;
-    while ( iEdgePair < edgeIDs1.size() )
+
+    for ( size_t iEdgePair = 0; iEdgePair < edgeIDs1.size(); ++iEdgePair )
+      // loop on pairs of opposite EDGEs
     {
-      if ( isComputed[ edgeIDs1[ iEdgePair ]] ||
+      if ( projectedEdges.count( edgeIDs1[ iEdgePair ]) ||
+           projectedEdges.count( edgeIDs2[ iEdgePair ]) )
+        continue;
+
+      // --------------------------------------------------------------------------------
+      if ( isComputed[ edgeIDs1[ iEdgePair ]] !=                    // one EDGE is meshed
            isComputed[ edgeIDs2[ iEdgePair ]])
       {
         // "projection" from one side to the other
@@ -892,48 +1620,45 @@ namespace
         if ( !SMESH_Algo::GetSortedNodesOnEdge( meshDS, theSinuEdges[ iEdgeComputed ], /*skipMedium=*/true, nodeParams ))
           return false;
 
+        projectedEdges.insert( iEdgeComputed );
+
         SMESH_MAT2d::BoundaryPoint& bndPnt = bp[ 1-iSideComputed ];
         SMESH_MAT2d::BranchPoint brp;
-        NodePoint npN, npB;
+        NodePoint npN, npB; // NodePoint's initialized by node and BoundaryPoint
         NodePoint& np0 = iSideComputed ? npB : npN;
         NodePoint& np1 = iSideComputed ? npN : npB;
 
         double maParam1st, maParamLast, maParam;
         if ( !theMA.getBoundary().getBranchPoint( iEdgeComputed, nodeParams.begin()->first, brp ))
-            return false;
+          return false;
         branch.getParameter( brp, maParam1st );
         if ( !theMA.getBoundary().getBranchPoint( iEdgeComputed, nodeParams.rbegin()->first, brp ))
-            return false;
+          return false;
         branch.getParameter( brp, maParamLast );
 
-        map< double, const SMDS_MeshNode* >::iterator u2n = nodeParams.begin(), u2nEnd = --nodeParams.end();
-        TMAPar2NPoints::iterator pos, end = pointsOnE.end();
+        map< double, const SMDS_MeshNode* >::iterator u2n = nodeParams.begin(), u2nEnd = nodeParams.end();
+        TMAPar2NPoints::iterator end = pointsOnE.end(), pos = end;
         TMAPar2NPoints::iterator & hint = (maParamLast > maParam1st) ? end : pos;
-        for ( ++u2n; u2n != u2nEnd; ++u2n )
+        for ( ++u2n, --u2nEnd; u2n != u2nEnd; ++u2n )
         {
+          // point on EDGE (u2n) --> MA point (brp)
           if ( !theMA.getBoundary().getBranchPoint( iEdgeComputed, u2n->first, brp ))
             return false;
-          if ( !branch.getBoundaryPoints( brp, bp[0], bp[1] ))
-            return false;
-          if ( !branch.getParameter( brp, maParam ))
+          // MA point --> points on 2 EDGEs (bp)
+          if ( !branch.getBoundaryPoints( brp, bp[0], bp[1] ) ||
+               !branch.getParameter( brp, maParam ))
             return false;
 
-          npN = NodePoint( u2n->second );
+          npN = NodePoint( u2n->second, u2n->first, iEdgeComputed );
           npB = NodePoint( bndPnt );
           pos = pointsOnE.insert( hint, make_pair( maParam, make_pair( np0, np1 )));
         }
-
-        // move iEdgePair forward
-        while ( iEdgePair < edgeIDs1.size() )
-          if ( edgeIDs1[ iEdgePair ] == bp[0]._edgeIndex &&
-               edgeIDs2[ iEdgePair ] == bp[1]._edgeIndex )
-            break;
-          else
-            ++iEdgePair;
       }
-      else
+      // --------------------------------------------------------------------------------
+      else if ( !isComputed[ edgeIDs1[ iEdgePair ]] &&         // none of EDGEs is meshed
+                !isComputed[ edgeIDs2[ iEdgePair ]])
       {
-        // projection from MA
+        // "projection" from MA
         maParams.clear();
         if ( !getParamsForEdgePair( iEdgePair, divPoints, theMAParams, maParams ))
           return false;
@@ -947,12 +1672,63 @@ namespace
                                                                                 NodePoint(bp[1]))));
         }
       }
-      ++iEdgePair;
-    }
+      // --------------------------------------------------------------------------------
+      else if ( isComputed[ edgeIDs1[ iEdgePair ]] &&             // equally meshed EDGES
+                isComputed[ edgeIDs2[ iEdgePair ]])
+      {
+        // add existing nodes
+
+        size_t iE0 = edgeIDs1[ iEdgePair ];
+        size_t iE1 = edgeIDs2[ iEdgePair ];
+        map< double, const SMDS_MeshNode* > nodeParams[2]; // params of existing nodes
+        if ( !SMESH_Algo::GetSortedNodesOnEdge( meshDS, theSinuEdges[ iE0 ],
+                                                /*skipMedium=*/false, nodeParams[0] ) ||
+             !SMESH_Algo::GetSortedNodesOnEdge( meshDS, theSinuEdges[ iE1 ],
+                                                /*skipMedium=*/false, nodeParams[1] ) ||
+             nodeParams[0].size() != nodeParams[1].size() )
+          return false;
+
+        if ( nodeParams[0].size() <= 2 )
+          continue; // nodes on VERTEXes only
 
-    if ( !projectVertices( theHelper, theMA, divPoints, theSinuEdges, isComputed, pointsOnE ))
+        bool reverse = ( theSinuEdges[0].Orientation() == theSinuEdges[1].Orientation() );
+        double maParam;
+        SMESH_MAT2d::BranchPoint brp;
+        std::pair< NodePoint, NodePoint > npPair;
+
+        map< double, const SMDS_MeshNode* >::iterator
+          u2n0F = ++nodeParams[0].begin(),
+          u2n1F = ++nodeParams[1].begin();
+        map< double, const SMDS_MeshNode* >::reverse_iterator
+          u2n1R = ++nodeParams[1].rbegin();
+        for ( ; u2n0F != nodeParams[0].end(); ++u2n0F )
+        {
+          if ( !theMA.getBoundary().getBranchPoint( iE0, u2n0F->first, brp ) ||
+               !branch.getParameter( brp, maParam ))
+            return false;
+
+          npPair.first = NodePoint( u2n0F->second, u2n0F->first, iE0 );
+          if ( reverse )
+          {
+            npPair.second = NodePoint( u2n1R->second, u2n1R->first, iE1 );
+            ++u2n1R;
+          }
+          else
+          {
+            npPair.second = NodePoint( u2n1F->second, u2n1F->first, iE1 );
+            ++u2n1F;
+          }
+          pointsOnE.insert( make_pair( maParam, npPair ));
+        }
+      }
+    }  // loop on pairs of opposite EDGEs
+
+    if ( !projectVertices( theHelper, theMA, divPoints, edgeIDs1, edgeIDs2,
+                           isComputed, pointsOnE, theSinuFace ))
       return false;
 
+    separateNodes( theHelper, theMA, pointsOnE, theSinuFace, isComputed );
+
     // create nodes
     TMAPar2NPoints::iterator u2np = pointsOnE.begin();
     for ( ; u2np != pointsOnE.end(); ++u2np )
@@ -997,6 +1773,10 @@ namespace
         ->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
     }
 
+    // Setup sides of a quadrangle
+    if ( !setQuadSides( theHelper, pointsOnE, theSinuFace, the1dAlgo ))
+      return false;
+
     return true;
   }
 
@@ -1008,16 +1788,29 @@ namespace
 
   bool computeShortEdges( SMESH_MesherHelper&        theHelper,
                           const vector<TopoDS_Edge>& theShortEdges,
-                          SMESH_Algo*                the1dAlgo )
+                          SMESH_Algo*                the1dAlgo,
+                          const bool                 theHasRadialHyp,
+                          const bool                 theIs2nd)
   {
+    SMESH_Hypothesis::Hypothesis_Status aStatus;
     for ( size_t i = 0; i < theShortEdges.size(); ++i )
     {
-      theHelper.GetGen()->Compute( *theHelper.GetMesh(), theShortEdges[i], true, true );
+      if ( !theHasRadialHyp )
+        // use global hyps
+        theHelper.GetGen()->Compute( *theHelper.GetMesh(), theShortEdges[i], true, true );
 
       SMESH_subMesh* sm = theHelper.GetMesh()->GetSubMesh(theShortEdges[i] );
       if ( sm->IsEmpty() )
       {
+        // use 2D hyp or minSegLen
         try {
+          // compute VERTEXes
+          SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/false);
+          while ( smIt->more() )
+            smIt->next()->ComputeStateEngine( SMESH_subMesh::COMPUTE );
+
+          // compute EDGE
+          the1dAlgo->CheckHypothesis( *theHelper.GetMesh(), theShortEdges[i], aStatus );
           if ( !the1dAlgo->Compute( *theHelper.GetMesh(), theShortEdges[i] ))
             return false;
         }
@@ -1115,9 +1908,44 @@ namespace
     return true;
   }
 
+  //================================================================================
+  /*!
+   * \brief Remove temporary node
+   */
+  //================================================================================
+
+  void mergeNodes( SMESH_MesherHelper& theHelper,
+                   SinuousFace&        theSinuFace )
+  {
+    SMESH_MeshEditor editor( theHelper.GetMesh() );
+    SMESH_MeshEditor::TListOfListOfNodes nodesGroups;
+
+    TMergeMap::iterator n2nn = theSinuFace._nodesToMerge.begin();
+    for ( ; n2nn != theSinuFace._nodesToMerge.end(); ++n2nn )
+    {
+      if ( !n2nn->first ) continue;
+      nodesGroups.push_back( list< const SMDS_MeshNode* >() );
+      list< const SMDS_MeshNode* > & group = nodesGroups.back();
+
+      group.push_back( n2nn->first );
+      group.splice( group.end(), n2nn->second );
+    }
+    editor.MergeNodes( nodesGroups );
+  }
 
 } // namespace
 
+//================================================================================
+/*!
+ * \brief Sets event listener which removes mesh from EDGEs when 2D hyps change
+ */
+//================================================================================
+
+void StdMeshers_QuadFromMedialAxis_1D2D::SetEventListener(SMESH_subMesh* faceSubMesh)
+{
+  faceSubMesh->SetEventListener( new EdgeCleaner, 0, faceSubMesh );
+}
+
 //================================================================================
 /*!
  * \brief Create quadrangle elements
@@ -1129,59 +1957,39 @@ namespace
  */
 //================================================================================
 
-bool StdMeshers_QuadFromMedialAxis_1D2D::computeQuads( SMESH_MesherHelper&       theHelper,
-                                                       const TopoDS_Face&        theFace,
-                                                       const vector<TopoDS_Edge> theSinuEdges[2],
-                                                       const vector<TopoDS_Edge> theShortEdges[2])
+bool StdMeshers_QuadFromMedialAxis_1D2D::computeQuads( SMESH_MesherHelper& theHelper,
+                                                       FaceQuadStruct::Ptr theQuad)
 {
-  SMESH_Mesh* mesh = theHelper.GetMesh();
-  SMESH_ProxyMesh::Ptr proxyMesh = StdMeshers_ViscousLayers2D::Compute( *mesh, theFace );
-  if ( !proxyMesh )
-    return false;
-
-  StdMeshers_Quadrangle_2D::myProxyMesh  = proxyMesh;
   StdMeshers_Quadrangle_2D::myHelper     = &theHelper;
   StdMeshers_Quadrangle_2D::myNeedSmooth = false;
   StdMeshers_Quadrangle_2D::myCheckOri   = false;
   StdMeshers_Quadrangle_2D::myQuadList.clear();
 
-  // fill FaceQuadStruct
-
-  list< TopoDS_Edge > side[4];
-  side[0].insert( side[0].end(), theShortEdges[0].begin(), theShortEdges[0].end() );
-  side[1].insert( side[1].end(), theSinuEdges[1].begin(),  theSinuEdges[1].end() );
-  side[2].insert( side[2].end(), theShortEdges[1].begin(), theShortEdges[1].end() );
-  side[3].insert( side[3].end(), theSinuEdges[0].begin(),  theSinuEdges[0].end() );
-
-  FaceQuadStruct::Ptr quad( new FaceQuadStruct );
-  quad->side.resize( 4 );
-  quad->face = theFace;
-  for ( int i = 0; i < 4; ++i )
-  {
-    quad->side[i] = StdMeshers_FaceSide::New( theFace, side[i], mesh, i < QUAD_TOP_SIDE,
-                                              /*skipMediumNodes=*/true, proxyMesh );
-  }
-  int nbNodesShort0 = quad->side[0].NbPoints();
-  int nbNodesShort1 = quad->side[2].NbPoints();
+  int nbNodesShort0 = theQuad->side[0].NbPoints();
+  int nbNodesShort1 = theQuad->side[2].NbPoints();
 
   // compute UV of internal points
-  myQuadList.push_back( quad );
-  if ( !StdMeshers_Quadrangle_2D::setNormalizedGrid( quad ))
+  myQuadList.push_back( theQuad );
+  if ( !StdMeshers_Quadrangle_2D::setNormalizedGrid( theQuad ))
     return false;
 
   // elliptic smooth of internal points to get boundary cell normal to the boundary
-  ellipticSmooth( quad, 1 );
+  bool isRing = theQuad->side[0].grid->Edge(0).IsNull();
+  if ( !isRing )
+    ellipticSmooth( theQuad, 1 );
 
   // create quadrangles
   bool ok;
+  theHelper.SetElementsOnShape( true );
   if ( nbNodesShort0 == nbNodesShort1 )
-    ok = StdMeshers_Quadrangle_2D::computeQuadDominant( *mesh, theFace, quad );
+    ok = StdMeshers_Quadrangle_2D::computeQuadDominant( *theHelper.GetMesh(),
+                                                        theQuad->face, theQuad );
   else
-    ok = StdMeshers_Quadrangle_2D::computeTriangles( *mesh, theFace, quad );
+    ok = StdMeshers_Quadrangle_2D::computeTriangles( *theHelper.GetMesh(),
+                                                     theQuad->face, theQuad );
 
-  StdMeshers_Quadrangle_2D::myProxyMesh.reset();
   StdMeshers_Quadrangle_2D::myHelper = 0;
-  
+
   return ok;
 }
 
@@ -1200,37 +2008,48 @@ bool StdMeshers_QuadFromMedialAxis_1D2D::Compute(SMESH_Mesh&         theMesh,
   TopoDS_Face F = TopoDS::Face( theShape );
   if ( F.Orientation() >= TopAbs_INTERNAL ) F.Orientation( TopAbs_FORWARD );
 
-  list< TopoDS_Edge > edges;
-  list< int > nbEdgesInWire;
-  int nbWire = SMESH_Block::GetOrderedEdges (F, edges, nbEdgesInWire);
+  SinuousFace sinuFace( F );
+
+  _progress = 0.01;
 
-  vector< TopoDS_Edge > sinuSide[2], shortSide[2];
-  if ( nbWire == 1 && getSinuousEdges( helper, F, edges, sinuSide, shortSide ))
+  if ( getSinuousEdges( helper, sinuFace ))
   {
-    vector< TopoDS_Edge > sinuEdges  = sinuSide[0];
-    sinuEdges.insert( sinuEdges.end(), sinuSide[1].begin(), sinuSide[1].end() );
-    if ( sinuEdges.size() > 2 )
-      return error(COMPERR_BAD_SHAPE, "Not yet supported case" );
+    _progress = 0.4;
 
-    double minSegLen = getMinSegLen( helper, sinuEdges );
-    SMESH_MAT2d::MedialAxis ma( F, sinuEdges, minSegLen, /*ignoreCorners=*/true );
+    double minSegLen = getMinSegLen( helper, sinuFace._sinuEdges );
+    SMESH_MAT2d::MedialAxis ma( F, sinuFace._sinuEdges, minSegLen, /*ignoreCorners=*/true );
 
     if ( !_regular1D )
       _regular1D = new Algo1D( _studyId, _gen );
     _regular1D->SetSegmentLength( minSegLen );
 
     vector<double> maParams;
-    if ( ! divideMA( helper, ma, sinuEdges, sinuSide[0].size(), _regular1D, maParams ))
+    if ( ! divideMA( helper, ma, sinuFace, _regular1D, minSegLen, maParams ))
       return error(COMPERR_BAD_SHAPE);
 
-    if ( !computeShortEdges( helper, shortSide[0], _regular1D ) ||
-         !computeShortEdges( helper, shortSide[1], _regular1D ))
+    _progress = 0.8;
+    if ( _hyp2D )
+      _regular1D->SetRadialDistribution( _hyp2D );
+
+    if ( !computeShortEdges( helper, sinuFace._shortSide[0], _regular1D, _hyp2D, 0 ) ||
+         !computeShortEdges( helper, sinuFace._shortSide[1], _regular1D, _hyp2D, 1 ))
       return error("Failed to mesh short edges");
 
-    if ( !computeSinuEdges( helper, ma, maParams, sinuEdges, sinuSide[0].size() ))
+    _progress = 0.85;
+
+    if ( !computeSinuEdges( helper, minSegLen, ma, maParams, sinuFace, _regular1D ))
       return error("Failed to mesh sinuous edges");
 
-    return computeQuads( helper, F, sinuSide, shortSide );
+    _progress = 0.9;
+
+    bool ok = computeQuads( helper, sinuFace._quad );
+
+    if ( ok )
+      mergeNodes( helper, sinuFace );
+
+    _progress = 1.;
+
+    return ok;
   }
 
   return error(COMPERR_BAD_SHAPE, "Not implemented so far");
@@ -1248,3 +2067,32 @@ bool StdMeshers_QuadFromMedialAxis_1D2D::Evaluate(SMESH_Mesh &         theMesh,
 {
   return StdMeshers_Quadrangle_2D::Evaluate(theMesh,theShape,theResMap);
 }
+
+//================================================================================
+/*!
+ * \brief Return true if the algorithm can mesh this shape
+ *  \param [in] aShape - shape to check
+ *  \param [in] toCheckAll - if true, this check returns OK if all shapes are OK,
+ *              else, returns OK if at least one shape is OK
+ */
+//================================================================================
+
+bool StdMeshers_QuadFromMedialAxis_1D2D::IsApplicable( const TopoDS_Shape & aShape,
+                                                       bool                 toCheckAll )
+{
+  TmpMesh tmpMesh;
+  SMESH_MesherHelper helper( tmpMesh );
+
+  int nbFoundFaces = 0;
+  for (TopExp_Explorer exp( aShape, TopAbs_FACE ); exp.More(); exp.Next(), ++nbFoundFaces )
+  {
+    const TopoDS_Face& face = TopoDS::Face( exp.Current() );
+    SinuousFace sinuFace( face );
+    bool isApplicable = getSinuousEdges( helper, sinuFace );
+
+    if ( toCheckAll  && !isApplicable ) return false;
+    if ( !toCheckAll &&  isApplicable ) return true;
+  }
+  return ( toCheckAll && nbFoundFaces != 0 );
+}
+
index df8a84a4c484c02f13ca4ec18894d44d2ae506f6..aec59a2d724705107b0d632832cc9cd7bd64a98b 100644 (file)
@@ -51,15 +51,19 @@ class STDMESHERS_EXPORT StdMeshers_QuadFromMedialAxis_1D2D: public StdMeshers_Qu
                         const TopoDS_Shape & aShape,
                         MapShapeNbElems&     aResMap);
 
- private:
+  virtual void SetEventListener(SMESH_subMesh* subMesh);
 
-  bool computeQuads( SMESH_MesherHelper&            theHelper,
-                     const TopoDS_Face&             theFace,
-                     const std::vector<TopoDS_Edge> theSinuEdges[2],
-                     const std::vector<TopoDS_Edge> theShortEdges[2]);
+  static bool IsApplicable(const TopoDS_Shape & aShape, bool toCheckAll);
 
   class Algo1D;
-  Algo1D* _regular1D;
+
+ private:
+
+  bool computeQuads( SMESH_MesherHelper& theHelper,
+                     FaceQuadStruct::Ptr theQuad);
+
+  Algo1D*                   _regular1D;
+  const SMESHDS_Hypothesis* _hyp2D;
 };
 
 #endif
index 0e35c560e03db2ac17e557c4998aeb468924fd4b..f7ac411d9a55673e25cf2f6eccb77454b0248f49 100644 (file)
@@ -228,6 +228,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh&         aMesh,
   myHelper = &helper;
 
   _quadraticMesh = myHelper->IsQuadraticSubMesh(aShape);
+  myHelper->SetElementsOnShape( true );
   myNeedSmooth = false;
   myCheckOri   = false;
 
@@ -249,7 +250,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh&         aMesh,
 
   enum { NOT_COMPUTED = -1, COMPUTE_FAILED = 0, COMPUTE_OK = 1 };
   int res = NOT_COMPUTED;
-  if (myQuadranglePreference)
+  if ( myQuadranglePreference )
   {
     int nfull = n1+n2+n3+n4;
     if ((nfull % 2) == 0 && ((n1 != n3) || (n2 != n4)))
@@ -258,7 +259,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh&         aMesh,
       res = computeQuadPref( aMesh, F, quad );
     }
   }
-  else if (myQuadType == QUAD_REDUCED)
+  else if ( myQuadType == QUAD_REDUCED )
   {
     int n13    = n1 - n3;
     int n24    = n2 - n4;
@@ -471,10 +472,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
       b = quad->uv_grid[ j      * nbhoriz + i + 1].node;
       c = quad->uv_grid[(j + 1) * nbhoriz + i + 1].node;
       d = quad->uv_grid[(j + 1) * nbhoriz + i    ].node;
-      SMDS_MeshFace* face = myHelper->AddFace(a, b, c, d);
-      if (face) {
-        meshDS->SetMeshElementOnShape(face, geomFaceID);
-      }
+      myHelper->AddFace(a, b, c, d);
     }
   }
 
@@ -558,8 +556,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
       }
 
       if (near == g) { // make triangle
-        SMDS_MeshFace* face = myHelper->AddFace(a, b, c);
-        if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+        myHelper->AddFace(a, b, c);
       }
       else { // make quadrangle
         if (near - 1 < ilow)
@@ -569,8 +566,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
         //SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
         
         if (!myTrianglePreference){
-          SMDS_MeshFace* face = myHelper->AddFace(a, b, c, d);
-          if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+          myHelper->AddFace(a, b, c, d);
         }
         else {
           splitQuadFace(meshDS, geomFaceID, a, b, c, d);
@@ -584,8 +580,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
               d = uv_e3[1].node;
             else
               d = quad->uv_grid[nbhoriz + k - 1].node;
-            SMDS_MeshFace* face = myHelper->AddFace(a, c, d);
-            if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+            myHelper->AddFace(a, c, d);
           }
         }
         g = near;
@@ -609,7 +604,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
       int g = nbhoriz - 1; // last processed node in the regular grid
 
       ilow = 0;
-      iup = nbhoriz - 1;
+      iup  = nbhoriz - 1;
 
       int stop = 0;
       if ( quad->side[3].grid->Edge(0).IsNull() ) // left side is simulated one
@@ -642,14 +637,12 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
           d = quad->UVPt( g, nbvertic-2 ).node;
           if ( myTrianglePreference )
           {
-            if ( SMDS_MeshFace* face = myHelper->AddFace(a, d, c))
-              meshDS->SetMeshElementOnShape(face, geomFaceID);
+            myHelper->AddFace(a, d, c);
           }
           else
           {
             if ( SMDS_MeshFace* face = myHelper->AddFace(a, b, d, c))
             {
-              meshDS->SetMeshElementOnShape(face, geomFaceID);
               SMESH_ComputeErrorPtr& err = aMesh.GetSubMesh( aFace )->GetComputeError();
               if ( !err || err->IsOK() || err->myName < COMPERR_WARNING )
               {
@@ -667,7 +660,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
       for ( ; i > stop; i--) {
         a = uv_e2[i].node;
         b = uv_e2[i - 1].node;
-        gp_Pnt pb (b->X(), b->Y(), b->Z());
+        gp_Pnt pb = SMESH_TNodeXYZ( b );
 
         // find node c in the grid, which will be linked with node b
         int near = g;
@@ -683,7 +676,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
               nk = uv_e1[nbright - 2].node;
             else
               nk = quad->uv_grid[nbhoriz*(nbvertic - 2) + k].node;
-            gp_Pnt pnk (nk->X(), nk->Y(), nk->Z());
+            gp_Pnt pnk = SMESH_TNodeXYZ( nk );
             double dist = pb.Distance(pnk);
             if (dist < mind - eps) {
               c = nk;
@@ -696,8 +689,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
         }
 
         if (near == g) { // make triangle
-          SMDS_MeshFace* face = myHelper->AddFace(a, b, c);
-          if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+          myHelper->AddFace(a, b, c);
         }
         else { // make quadrangle
           if (near + 1 > iup)
@@ -706,8 +698,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
             d = quad->uv_grid[nbhoriz*(nbvertic - 2) + near + 1].node;
           //SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
           if (!myTrianglePreference){
-            SMDS_MeshFace* face = myHelper->AddFace(a, b, c, d);
-            if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+            myHelper->AddFace(a, b, c, d);
           }
           else {
             splitQuadFace(meshDS, geomFaceID, a, b, c, d);
@@ -720,8 +711,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
                 d = uv_e1[nbright - 2].node;
               else
                 d = quad->uv_grid[nbhoriz*(nbvertic - 2) + k + 1].node;
-              SMDS_MeshFace* face = myHelper->AddFace(a, c, d);
-              if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+              myHelper->AddFace(a, c, d);
             }
           }
           g = near;
@@ -770,8 +760,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
       }
 
       if (near == g) { // make triangle
-        SMDS_MeshFace* face = myHelper->AddFace(a, b, c);
-        if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+        myHelper->AddFace(a, b, c);
       }
       else { // make quadrangle
         if (near - 1 < jlow)
@@ -781,8 +770,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
         //SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
 
         if (!myTrianglePreference){
-          SMDS_MeshFace* face = myHelper->AddFace(a, b, c, d);
-          if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+          myHelper->AddFace(a, b, c, d);
         }
         else {
           splitQuadFace(meshDS, geomFaceID, a, b, c, d);
@@ -795,8 +783,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
               d = uv_e0[nbdown - 2].node;
             else
               d = quad->uv_grid[nbhoriz*k - 2].node;
-            SMDS_MeshFace* face = myHelper->AddFace(a, c, d);
-            if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+            myHelper->AddFace(a, c, d);
           }
         }
         g = near;
@@ -823,14 +810,12 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
           d = quad->UVPt( 1, g ).node;
           if ( myTrianglePreference )
           {
-            if ( SMDS_MeshFace* face = myHelper->AddFace(a, d, c))
-              meshDS->SetMeshElementOnShape(face, geomFaceID);
+            myHelper->AddFace(a, d, c);
           }
           else
           {
             if ( SMDS_MeshFace* face = myHelper->AddFace(a, b, d, c))
             {
-              meshDS->SetMeshElementOnShape(face, geomFaceID);
               SMESH_ComputeErrorPtr& err = aMesh.GetSubMesh( aFace )->GetComputeError();
               if ( !err || err->IsOK() || err->myName < COMPERR_WARNING )
               {
@@ -876,8 +861,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
         }
 
         if (near == g) { // make triangle
-          SMDS_MeshFace* face = myHelper->AddFace(a, b, c);
-          if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+          myHelper->AddFace(a, b, c);
         }
         else { // make quadrangle
           if (near + 1 > jup)
@@ -885,8 +869,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
           else
             d = quad->uv_grid[nbhoriz*(near + 1) + 1].node;
           if (!myTrianglePreference) {
-            SMDS_MeshFace* face = myHelper->AddFace(a, b, c, d);
-            if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+            myHelper->AddFace(a, b, c, d);
           }
           else {
             splitQuadFace(meshDS, geomFaceID, a, b, c, d);
@@ -899,8 +882,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
                 d = quad->uv_grid[nbhoriz*jup + 1].node; //uv_e2[1].node;
               else
                 d = quad->uv_grid[nbhoriz*(k + 1) + 1].node;
-              SMDS_MeshFace* face = myHelper->AddFace(a, c, d);
-              if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+              myHelper->AddFace(a, c, d);
             }
           }
           g = near;
@@ -1453,6 +1435,8 @@ bool StdMeshers_Quadrangle_2D::setNormalizedGrid (FaceQuadStruct::Ptr quad)
 
   int nbhoriz  = Min( bSide.NbPoints(), tSide.NbPoints() );
   int nbvertic = Min( rSide.NbPoints(), lSide.NbPoints() );
+  if ( nbhoriz < 1 || nbvertic < 1 )
+    return error("Algo error: empty quad");
 
   if ( myQuadList.size() == 1 )
   {
@@ -1853,6 +1837,10 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
         }
         sideLCb = StdMeshers_FaceSide::New( pointsLCb, aFace );
         p3dom   = pointsLCb.back();
+
+        gp_Pnt xyz = S->Value( p3dom.u, p3dom.v );
+        p3dom.node = myHelper->AddNode( xyz.X(), xyz.Y(), xyz.Z(), 0, p3dom.u, p3dom.v );
+        pointsLCb.back() = p3dom;
       }
       // Make a side separating domains L and Ct
       StdMeshers_FaceSidePtr sideLCt;
@@ -2004,6 +1992,16 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
       sideRCb = StdMeshers_FaceSide::New( pointsRCb, aFace );
       pTBL    = pointsLCb.back();
       pTBR    = pointsRCb.back();
+      {
+        gp_Pnt xyz = S->Value( pTBL.u, pTBL.v );
+        pTBL.node = myHelper->AddNode( xyz.X(), xyz.Y(), xyz.Z(), 0, pTBL.u, pTBL.v );
+        pointsLCb.back() = pTBL;
+      }
+      {
+        gp_Pnt xyz = S->Value( pTBR.u, pTBR.v );
+        pTBR.node = myHelper->AddNode( xyz.X(), xyz.Y(), xyz.Z(), 0, pTBR.u, pTBR.v );
+        pointsRCb.back() = pTBR;
+      }
     }
     // Make sides separating domains Ct and L and R
     StdMeshers_FaceSidePtr sideLCt, sideRCt;
@@ -2207,10 +2205,8 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
       for (i=1; i<=dl; i++) {
         for (j=1; j<nl; j++) {
           if (WisF) {
-            SMDS_MeshFace* F =
-              myHelper->AddFace(NodesL.Value(i,j), NodesL.Value(i+1,j),
-                                NodesL.Value(i+1,j+1), NodesL.Value(i,j+1));
-            if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+            myHelper->AddFace(NodesL.Value(i,j), NodesL.Value(i+1,j),
+                              NodesL.Value(i+1,j+1), NodesL.Value(i,j+1));
           }
         }
       }
@@ -2264,10 +2260,8 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
       for (i=1; i<=dr; i++) {
         for (j=1; j<nr; j++) {
           if (WisF) {
-            SMDS_MeshFace* F =
-              myHelper->AddFace(NodesR.Value(i,j), NodesR.Value(i+1,j),
-                                NodesR.Value(i+1,j+1), NodesR.Value(i,j+1));
-            if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+            myHelper->AddFace(NodesR.Value(i,j), NodesR.Value(i+1,j),
+                              NodesR.Value(i+1,j+1), NodesR.Value(i,j+1));
           }
         }
       }
@@ -2337,10 +2331,8 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
     for (i=1; i<nb; i++) {
       for (j=1; j<nbv; j++) {
         if (WisF) {
-          SMDS_MeshFace* F =
-            myHelper->AddFace(NodesC.Value(i,j), NodesC.Value(i+1,j),
-                              NodesC.Value(i+1,j+1), NodesC.Value(i,j+1));
-          if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+          myHelper->AddFace(NodesC.Value(i,j), NodesC.Value(i+1,j),
+                            NodesC.Value(i+1,j+1), NodesC.Value(i,j+1));
         }
       }
     }
@@ -2369,10 +2361,8 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
     for (j=1; j<nnn-1; j++) {
       for (i=1; i<nb; i++) {
         if (WisF) {
-          SMDS_MeshFace* F =
-            myHelper->AddFace(NodesBRD.Value(i,j), NodesBRD.Value(i+1,j),
-                              NodesBRD.Value(i+1,j+1), NodesBRD.Value(i,j+1));
-          if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+          myHelper->AddFace(NodesBRD.Value(i,j), NodesBRD.Value(i+1,j),
+                            NodesBRD.Value(i+1,j+1), NodesBRD.Value(i,j+1));
         }
       }
     }
@@ -2475,10 +2465,8 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
       for (j=1; j<=drl+addv; j++) {
         for (i=1; i<nb; i++) {
           if (WisF) {
-            SMDS_MeshFace* F =
-              myHelper->AddFace(NodesC.Value(i,j), NodesC.Value(i+1,j),
-                                NodesC.Value(i+1,j+1), NodesC.Value(i,j+1));
-            if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+            myHelper->AddFace(NodesC.Value(i,j), NodesC.Value(i+1,j),
+                              NodesC.Value(i+1,j+1), NodesC.Value(i,j+1));
           }
         }
       } // end nr<nl
@@ -2502,10 +2490,8 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
       }
       for (i=1; i<nt; i++) {
         if (WisF) {
-          SMDS_MeshFace* F =
-            myHelper->AddFace(NodesLast.Value(i,1), NodesLast.Value(i+1,1),
-                              NodesLast.Value(i+1,2), NodesLast.Value(i,2));
-          if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+          myHelper->AddFace(NodesLast.Value(i,1), NodesLast.Value(i+1,1),
+                            NodesLast.Value(i+1,2), NodesLast.Value(i,2));
         }
       }
     } // if ((drl+addv) > 0)
@@ -2664,21 +2650,16 @@ void StdMeshers_Quadrangle_2D::splitQuadFace(SMESHDS_Mesh *       theMeshDS,
                                              const SMDS_MeshNode* theNode3,
                                              const SMDS_MeshNode* theNode4)
 {
-  SMDS_MeshFace* face;
   if ( SMESH_TNodeXYZ( theNode1 ).SquareDistance( theNode3 ) >
        SMESH_TNodeXYZ( theNode2 ).SquareDistance( theNode4 ) )
   {
-    face = myHelper->AddFace(theNode2, theNode4 , theNode1);
-    if (face) theMeshDS->SetMeshElementOnShape(face, theFaceID);
-    face = myHelper->AddFace(theNode2, theNode3, theNode4);
-    if (face) theMeshDS->SetMeshElementOnShape(face, theFaceID);
+    myHelper->AddFace(theNode2, theNode4 , theNode1);
+    myHelper->AddFace(theNode2, theNode3, theNode4);
   }
   else
   {
-    face = myHelper->AddFace(theNode1, theNode2 ,theNode3);
-    if (face) theMeshDS->SetMeshElementOnShape(face, theFaceID);
-    face = myHelper->AddFace(theNode1, theNode3, theNode4);
-    if (face) theMeshDS->SetMeshElementOnShape(face, theFaceID);
+    myHelper->AddFace(theNode1, theNode2 ,theNode3);
+    myHelper->AddFace(theNode1, theNode3, theNode4);
   }
 }
 
@@ -3090,10 +3071,8 @@ bool StdMeshers_Quadrangle_2D::computeReduced (SMESH_Mesh &        aMesh,
       // create faces
       for (i=1; i<=dl; i++) {
         for (j=1; j<nl; j++) {
-            SMDS_MeshFace* F =
-              myHelper->AddFace(NodesL.Value(i,j), NodesL.Value(i+1,j),
-                                NodesL.Value(i+1,j+1), NodesL.Value(i,j+1));
-            if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+          myHelper->AddFace(NodesL.Value(i,j), NodesL.Value(i+1,j),
+                            NodesL.Value(i+1,j+1), NodesL.Value(i,j+1));
         }
       }
     }
@@ -3145,10 +3124,8 @@ bool StdMeshers_Quadrangle_2D::computeReduced (SMESH_Mesh &        aMesh,
       // create faces
       for (i=1; i<=dr; i++) {
         for (j=1; j<nr; j++) {
-            SMDS_MeshFace* F =
-              myHelper->AddFace(NodesR.Value(i,j), NodesR.Value(i+1,j),
-                                NodesR.Value(i+1,j+1), NodesR.Value(i,j+1));
-            if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+          myHelper->AddFace(NodesR.Value(i,j), NodesR.Value(i+1,j),
+                            NodesR.Value(i+1,j+1), NodesR.Value(i,j+1));
         }
       }
     }
@@ -3209,10 +3186,8 @@ bool StdMeshers_Quadrangle_2D::computeReduced (SMESH_Mesh &        aMesh,
     // create faces
     for (i=1; i<nb; i++) {
       for (j=1; j<nbv; j++) {
-        SMDS_MeshFace* F =
-          myHelper->AddFace(NodesC.Value(i,j), NodesC.Value(i+1,j),
-                            NodesC.Value(i+1,j+1), NodesC.Value(i,j+1));
-        if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+        myHelper->AddFace(NodesC.Value(i,j), NodesC.Value(i+1,j),
+                          NodesC.Value(i+1,j+1), NodesC.Value(i,j+1));
       }
     }
   } // end Multiple Reduce implementation
@@ -3312,8 +3287,6 @@ bool StdMeshers_Quadrangle_2D::computeReduced (SMESH_Mesh &        aMesh,
     if (uv_eb.size() != nb || uv_er.size() != nr || uv_et.size() != nt || uv_el.size() != nl)
       return error(COMPERR_BAD_INPUT_MESH);
 
-    myHelper->SetElementsOnShape( true );
-
     gp_UV uv[ UV_SIZE ];
     uv[ UV_A0 ].SetCoord( uv_eb.front().u, uv_eb.front().v);
     uv[ UV_A1 ].SetCoord( uv_eb.back().u,  uv_eb.back().v );
@@ -3875,7 +3848,7 @@ void StdMeshers_Quadrangle_2D::updateDegenUV(FaceQuadStruct::Ptr quad)
 
     // Set number of nodes on a degenerated side to be same as on an opposite side
     // ----------------------------------------------------------------------------
-    for ( unsigned i = 0; i < quad->side.size(); ++i )
+    for ( size_t i = 0; i < quad->side.size(); ++i )
     {
       StdMeshers_FaceSidePtr degSide = quad->side[i];
       if ( !myHelper->IsDegenShape( degSide->EdgeID(0) ))
@@ -3906,29 +3879,72 @@ void StdMeshers_Quadrangle_2D::smooth (FaceQuadStruct::Ptr quad)
 {
   if ( !myNeedSmooth ) return;
 
-  // Get nodes to smooth
+  SMESHDS_Mesh* meshDS = myHelper->GetMeshDS();
+  const double     tol = BRep_Tool::Tolerance( quad->face );
+  Handle(ShapeAnalysis_Surface) surface = myHelper->GetSurface( quad->face );
+
+  if ( myHelper->HasDegeneratedEdges() && myForcedPnts.empty() )
+  {
+    // "smooth" by computing node positions using 3D TFI and further projection
+
+    int nbhoriz  = quad->iSize;
+    int nbvertic = quad->jSize;
 
-  // TODO: do not smooth fixed nodes
+    SMESH_TNodeXYZ a0( quad->UVPt( 0,         0          ).node );
+    SMESH_TNodeXYZ a1( quad->UVPt( nbhoriz-1, 0          ).node );
+    SMESH_TNodeXYZ a2( quad->UVPt( nbhoriz-1, nbvertic-1 ).node );
+    SMESH_TNodeXYZ a3( quad->UVPt( 0,         nbvertic-1 ).node );
+
+    for (int i = 1; i < nbhoriz-1; i++)
+    {
+      SMESH_TNodeXYZ p0( quad->UVPt( i, 0          ).node );
+      SMESH_TNodeXYZ p2( quad->UVPt( i, nbvertic-1 ).node );
+      for (int j = 1; j < nbvertic-1; j++)
+      {
+        SMESH_TNodeXYZ p1( quad->UVPt( nbhoriz-1, j ).node );
+        SMESH_TNodeXYZ p3( quad->UVPt( 0,         j ).node );
+
+        UVPtStruct& uvp = quad->UVPt( i, j );
+
+        gp_Pnt    p = myHelper->calcTFI(uvp.x,uvp.y, a0,a1,a2,a3, p0,p1,p2,p3);
+        gp_Pnt2d uv = surface->NextValueOfUV( uvp.UV(), p, 10*tol );
+        gp_Pnt pnew = surface->Value( uv );
+
+        meshDS->MoveNode( uvp.node, pnew.X(), pnew.Y(), pnew.Z() );
+        uvp.u = uv.X();
+        uvp.v = uv.Y();
+      }
+    }
+    return;
+  }
+
+  // Get nodes to smooth
 
   typedef map< const SMDS_MeshNode*, TSmoothNode, TIDCompare > TNo2SmooNoMap;
   TNo2SmooNoMap smooNoMap;
 
-  const TopoDS_Face&  geomFace = TopoDS::Face( myHelper->GetSubShape() );
-  Handle(Geom_Surface) surface = BRep_Tool::Surface( geomFace );
-  double U1, U2, V1, V2;
-  surface->Bounds(U1, U2, V1, V2);
-  GeomAPI_ProjectPointOnSurf proj;
-  proj.Init( surface, U1, U2, V1, V2, BRep_Tool::Tolerance( geomFace ) );
-
-  SMESHDS_Mesh*        meshDS = myHelper->GetMeshDS();
-  SMESHDS_SubMesh*   fSubMesh = meshDS->MeshElements( geomFace );
-  SMDS_NodeIteratorPtr    nIt = fSubMesh->GetNodes();
+  // fixed nodes
+  set< const SMDS_MeshNode* > fixedNodes;
+  for ( size_t i = 0; i < myForcedPnts.size(); ++i )
+  {
+    fixedNodes.insert( myForcedPnts[i].node );
+    if ( myForcedPnts[i].node->getshapeId() != myHelper->GetSubShapeID() )
+    {
+      TSmoothNode & sNode = smooNoMap[ myForcedPnts[i].node ];
+      sNode._uv  = myForcedPnts[i].uv;
+      sNode._xyz = SMESH_TNodeXYZ( myForcedPnts[i].node );
+    }
+  }
+  SMESHDS_SubMesh* fSubMesh = meshDS->MeshElements( quad->face );
+  SMDS_NodeIteratorPtr  nIt = fSubMesh->GetNodes();
   while ( nIt->more() ) // loop on nodes bound to a FACE
   {
     const SMDS_MeshNode* node = nIt->next();
     TSmoothNode & sNode = smooNoMap[ node ];
-    sNode._uv  = myHelper->GetNodeUV( geomFace, node );
+    sNode._uv  = myHelper->GetNodeUV( quad->face, node );
     sNode._xyz = SMESH_TNodeXYZ( node );
+    if ( fixedNodes.count( node ))
+      continue; // fixed - no triangles
 
     // set sNode._triangles
     SMDS_ElemIteratorPtr fIt = node->GetInverseElementIterator( SMDSAbs_Face );
@@ -3946,16 +3962,22 @@ void StdMeshers_Quadrangle_2D::smooth (FaceQuadStruct::Ptr quad)
     }
   }
   // set _uv of smooth nodes on FACE boundary
-  for ( unsigned i = 0; i < quad->side.size(); ++i )
-  {
-    const vector<UVPtStruct>& uvVec = quad->side[i].GetUVPtStruct();
-    for ( unsigned j = 0; j < uvVec.size(); ++j )
-    {
-      TSmoothNode & sNode = smooNoMap[ uvVec[j].node ];
-      sNode._uv  = uvVec[j].UV();
-      sNode._xyz = SMESH_TNodeXYZ( uvVec[j].node );
-    }
-  }
+  set< StdMeshers_FaceSide* > sidesOnEdge;
+  list< FaceQuadStruct::Ptr >::iterator q = myQuadList.begin();
+  for ( ; q != myQuadList.end() ; ++q )
+    for ( size_t i = 0; i < (*q)->side.size(); ++i )
+      if ( ! (*q)->side[i].grid->Edge(0).IsNull() &&
+           //(*q)->nbNodeOut( i ) == 0 &&
+           sidesOnEdge.insert( (*q)->side[i].grid.get() ).second )
+      {
+        const vector<UVPtStruct>& uvVec = (*q)->side[i].grid->GetUVPtStruct();
+        for ( unsigned j = 0; j < uvVec.size(); ++j )
+        {
+          TSmoothNode & sNode = smooNoMap[ uvVec[j].node ];
+          sNode._uv  = uvVec[j].UV();
+          sNode._xyz = SMESH_TNodeXYZ( uvVec[j].node );
+        }
+      }
 
   // define refernce orientation in 2D
   TNo2SmooNoMap::iterator n2sn = smooNoMap.begin();
@@ -3984,22 +4006,16 @@ void StdMeshers_Quadrangle_2D::smooth (FaceQuadStruct::Ptr quad)
       {
         // compute a new XYZ
         gp_XYZ newXYZ (0,0,0);
-        for ( unsigned i = 0; i < sNode._triangles.size(); ++i )
+        for ( size_t i = 0; i < sNode._triangles.size(); ++i )
           newXYZ += sNode._triangles[i]._n1->_xyz;
         newXYZ /= sNode._triangles.size();
 
         // compute a new UV by projection
-        proj.Perform( newXYZ );
-        isValid = ( proj.IsDone() && proj.NbPoints() > 0 );
-        if ( isValid )
-        {
-          // check validity of the newUV
-          Quantity_Parameter u,v;
-          proj.LowerDistanceParameters( u, v );
-          newUV.SetCoord( u, v );
-          for ( unsigned i = 0; i < sNode._triangles.size() && isValid; ++i )
-            isValid = ( sNode._triangles[i].IsForward( newUV ) == refForward );
-        }
+        newUV = surface->NextValueOfUV( sNode._uv, newXYZ, 10*tol ).XY();
+
+        // check validity of the newUV
+        for ( size_t i = 0; i < sNode._triangles.size() && isValid; ++i )
+          isValid = ( sNode._triangles[i].IsForward( newUV ) == refForward );
       }
       if ( !isValid )
       {
@@ -4017,7 +4033,7 @@ void StdMeshers_Quadrangle_2D::smooth (FaceQuadStruct::Ptr quad)
       if ( isValid )
       {
         sNode._uv = newUV;
-        sNode._xyz = surface->Value( newUV.X(), newUV.Y() ).XYZ();
+        sNode._xyz = surface->Value( newUV ).XYZ();
       }
     }
   }
@@ -4031,7 +4047,7 @@ void StdMeshers_Quadrangle_2D::smooth (FaceQuadStruct::Ptr quad)
       continue; // not movable node
 
     SMDS_MeshNode* node = const_cast< SMDS_MeshNode*>( n2sn->first );
-    gp_Pnt xyz = surface->Value( sNode._uv.X(), sNode._uv.Y() );
+    gp_Pnt xyz = surface->Value( sNode._uv );
     meshDS->MoveNode( node, xyz.X(), xyz.Y(), xyz.Z() );
 
     // store the new UV
@@ -4051,13 +4067,13 @@ void StdMeshers_Quadrangle_2D::smooth (FaceQuadStruct::Ptr quad)
       if ( node->getshapeId() != myHelper->GetSubShapeID() )
         continue; // medium node is on EDGE or VERTEX
 
-      gp_XY uv1 = myHelper->GetNodeUV( geomFace, link.node1(), node );
-      gp_XY uv2 = myHelper->GetNodeUV( geomFace, link.node2(), node );
+      gp_XYZ pm = 0.5 * ( SMESH_TNodeXYZ( link.node1() ) + SMESH_TNodeXYZ( link.node2() ));
+      gp_XY uvm = myHelper->GetNodeUV( quad->face, node );
+
+      gp_Pnt2d uv = surface->NextValueOfUV( uvm, pm, 10*tol );
+      gp_Pnt  xyz = surface->Value( uv );
 
-      gp_XY uv  = myHelper->GetMiddleUV( surface, uv1, uv2 );
       node->SetPosition( SMDS_PositionPtr( new SMDS_FacePosition( uv.X(), uv.Y() )));
-      
-      gp_Pnt xyz = surface->Value( uv.X(), uv.Y() );
       meshDS->MoveNode( node, xyz.X(), xyz.Y(), xyz.Z() );
     }
   }
@@ -4158,6 +4174,7 @@ bool StdMeshers_Quadrangle_2D::check()
         if ( !myHelper->IsSeamShape( nn[i]->getshapeId() ))
           nInFace = nn[i];
 
+    toCheckUV = true;
     for ( int i = 0; i < nbN; ++i )
       uv[ i ] = myHelper->GetNodeUV( geomFace, nn[i], nInFace, &toCheckUV );
 
@@ -4227,10 +4244,11 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face&          theFace,
   theNbDegenEdges = 0;
 
   SMESH_MesherHelper helper( theMesh );
+  StdMeshers_FaceSide faceSide( theFace, theWire, &theMesh, /*isFwd=*/true, /*skipMedium=*/true);
 
   // sort theVertices by angle
   multimap<double, TopoDS_Vertex> vertexByAngle;
-  TopTools_DataMapOfShapeReal angleByVertex;
+  TopTools_DataMapOfShapeReal     angleByVertex;
   TopoDS_Edge prevE = theWire.back();
   if ( SMESH_Algo::isDegenerated( prevE ))
   {
@@ -4242,17 +4260,17 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face&          theFace,
     prevE = *edge;
   }
   list<TopoDS_Edge>::iterator edge = theWire.begin();
-  for ( ; edge != theWire.end(); ++edge )
+  for ( int iE = 0; edge != theWire.end(); ++edge, ++iE )
   {
     if ( SMESH_Algo::isDegenerated( *edge ))
     {
       ++theNbDegenEdges;
       continue;
     }
-    TopoDS_Vertex v = helper.IthVertex( 0, *edge );
-    if ( !theConsiderMesh || SMESH_Algo::VertexNode( v, helper.GetMeshDS() ))
+    if ( !theConsiderMesh || faceSide.VertexNode( iE ))
     {
-      double angle = SMESH_MesherHelper::GetAngle( prevE, *edge, theFace, v );
+      TopoDS_Vertex v = helper.IthVertex( 0, *edge );
+      double    angle = helper.GetAngle( prevE, *edge, theFace, v );
       vertexByAngle.insert( make_pair( angle, v ));
       angleByVertex.Bind( v, angle );
     }
@@ -4271,6 +4289,17 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face&          theFace,
     triaVertex.Nullify();
 
   // check nb of available corners
+  if ( faceSide.NbEdges() < nbCorners )
+    return error(COMPERR_BAD_SHAPE,
+                 TComm("Face must have 4 sides but not ") << faceSide.NbEdges() );
+
+  if ( theConsiderMesh )
+  {
+    const int nbSegments = Max( faceSide.NbPoints()-1, faceSide.NbSegments() );
+    if ( nbSegments < nbCorners )
+      return error(COMPERR_BAD_INPUT_MESH, TComm("Too few boundary nodes: ") << nbSegments);
+  }
+
   if ( nbCorners == 3 )
   {
     if ( vertexByAngle.size() < 3 )
@@ -4633,49 +4662,66 @@ bool StdMeshers_Quadrangle_2D::getEnforcedUV()
   Standard_Real u1,u2,v1,v2;
   const TopoDS_Face&   face = TopoDS::Face( myHelper->GetSubShape() );
   const double          tol = BRep_Tool::Tolerance( face );
-  Handle(Geom_Surface) surf = BRep_Tool::Surface( face );
-  surf->Bounds( u1,u2,v1,v2 );
-  GeomAPI_ProjectPointOnSurf project;
-  project.Init(surf, u1,u2, v1,v2, tol );
+  Handle(ShapeAnalysis_Surface) project = myHelper->GetSurface( face );
+  project->Bounds( u1,u2,v1,v2 );
   Bnd_Box bbox;
   BRepBndLib::Add( face, bbox );
   double farTol = 0.01 * sqrt( bbox.SquareExtent() );
 
+  // get internal VERTEXes of the FACE to use them instead of equal points
+  typedef map< pair< double, double >, TopoDS_Vertex > TUV2VMap;
+  TUV2VMap uv2intV;
+  for ( TopExp_Explorer vExp( face, TopAbs_VERTEX, TopAbs_EDGE ); vExp.More(); vExp.Next() )
+  {
+    TopoDS_Vertex v = TopoDS::Vertex( vExp.Current() );
+    gp_Pnt2d     uv = project->ValueOfUV( BRep_Tool::Pnt( v ), tol );
+    uv2intV.insert( make_pair( make_pair( uv.X(), uv.Y() ), v ));
+  }
+
   for ( size_t iP = 0; iP < points.size(); ++iP )
   {
-    project.Perform( points[ iP ]);
-    if ( !project.IsDone() )
-    {
-      if ( isStrictCheck && iP < nbPoints )
-        return error
-          (TComm("Projection of an enforced point to the face failed - (")
-           << points[ iP ].X() << ", "<< points[ iP ].Y() << ", "<< points[ iP ].Z() << " )");
-      continue;
-    }
-    if ( project.LowerDistance() > farTol )
+    gp_Pnt2d uv = project->ValueOfUV( points[ iP ], tol );
+    if ( project->Gap() > farTol )
     {
       if ( isStrictCheck && iP < nbPoints )
         return error
           (COMPERR_BAD_PARMETERS, TComm("An enforced point is too far from the face, dist = ")
-           << project.LowerDistance() << " - ("
+           << points[ iP ].Distance( project->Value( uv )) << " - ("
            << points[ iP ].X() << ", "<< points[ iP ].Y() << ", "<< points[ iP ].Z() << " )");
       continue;
     }
-    Quantity_Parameter u, v;
-    project.LowerDistanceParameters(u, v);
-    gp_Pnt2d uv( u, v );
     BRepClass_FaceClassifier clsf ( face, uv, tol );
     switch ( clsf.State() ) {
     case TopAbs_IN:
     {
-      double edgeDist =  ( Min( Abs( u - u1 ), Abs( u - u2 )) +
-                           Min( Abs( v - v1 ), Abs( v - v2 )));
+      double edgeDist = ( Min( Abs( uv.X() - u1 ), Abs( uv.X() - u2 )) +
+                          Min( Abs( uv.Y() - v1 ), Abs( uv.Y() - v2 )));
       ForcedPoint fp;
       fp.uv  = uv.XY();
       fp.xyz = points[ iP ].XYZ();
       if ( iP >= nbPoints )
         fp.vertex = TopoDS::Vertex( vMap( iP - nbPoints + 1 ));
 
+      TUV2VMap::iterator uv2v = uv2intV.lower_bound( make_pair( uv.X()-tol, uv.Y()-tol ));
+      for ( ; uv2v != uv2intV.end() && uv2v->first.first <= uv.X()+tol;  ++uv2v )
+        if ( uv.SquareDistance( gp_Pnt2d( uv2v->first.first, uv2v->first.second )) < tol*tol )
+        {
+          fp.vertex = uv2v->second;
+          break;
+        }
+
+      fp.node = 0;
+      if ( myHelper->IsSubShape( fp.vertex, myHelper->GetMesh() ))
+      {
+        SMESH_subMesh* sm = myHelper->GetMesh()->GetSubMesh( fp.vertex );
+        sm->ComputeStateEngine( SMESH_subMesh::COMPUTE );
+        fp.node = SMESH_Algo::VertexNode( fp.vertex, myHelper->GetMeshDS() );
+      }
+      else
+      {
+        fp.node = myHelper->AddNode( fp.xyz.X(), fp.xyz.Y(), fp.xyz.Z(),
+                                     0, fp.uv.X(), fp.uv.Y() );
+      }
       sortedFP.insert( make_pair( edgeDist, fp ));
       break;
     }
@@ -4744,7 +4790,7 @@ bool StdMeshers_Quadrangle_2D::addEnforcedNodes()
   {
     bool isNodeEnforced = false;
 
-    // look for a quad enclosing a enforced point
+    // look for a quad enclosing an enforced point
     for ( quadIt = myQuadList.begin(); quadIt != myQuadList.end(); ++quadIt )
     {
       FaceQuadStruct::Ptr quad = *quadIt;
@@ -4799,8 +4845,9 @@ bool StdMeshers_Quadrangle_2D::addEnforcedNodes()
           }
           // make a node of a side forced
           vector<UVPtStruct>& points = (vector<UVPtStruct>&) side.GetUVPtStruct();
-          points[ sideNodeIndex ].u = myForcedPnts[ iFP ].U();
-          points[ sideNodeIndex ].v = myForcedPnts[ iFP ].V();
+          points[ sideNodeIndex ].u    = myForcedPnts[ iFP ].U();
+          points[ sideNodeIndex ].v    = myForcedPnts[ iFP ].V();
+          points[ sideNodeIndex ].node = myForcedPnts[ iFP ].node;
 
           updateSideUV( side, sideNodeIndex, quadsBySide );
 
@@ -4847,6 +4894,9 @@ bool StdMeshers_Quadrangle_2D::addEnforcedNodes()
           FaceQuadStruct::Ptr   newQuad = myQuadList.back();
           FaceQuadStruct::Side& newSide = newQuad->side[ iNewSide ];
 
+          vector<UVPtStruct>& points = (vector<UVPtStruct>&) newSide.GetUVPtStruct();
+          points[ indForced ].node = myForcedPnts[ iFP ].node;
+
           newSide.forced_nodes.insert( indForced );
           quad->side[( iNewSide+2 ) % 4 ].forced_nodes.insert( indForced );
 
@@ -4883,6 +4933,7 @@ bool StdMeshers_Quadrangle_2D::addEnforcedNodes()
                      << myForcedPnts[iFP].xyz.Y() << ", "
                      << myForcedPnts[iFP].xyz.Z() << " )");
     }
+    myNeedSmooth = true;
 
   } // loop on enforced points
 
@@ -4900,25 +4951,31 @@ bool StdMeshers_Quadrangle_2D::addEnforcedNodes()
       if ( quadVec.size() <= 1 )
         continue; // outer side
 
-      bool missedNodesOnSide = false;
       const vector<UVPtStruct>& points = side.grid->GetUVPtStruct();
       for ( size_t iC = 0; iC < side.contacts.size(); ++iC )
       {
+        if ( side.contacts[iC].point <  side.from ||
+             side.contacts[iC].point >= side.to )
+          continue;
+        if ( side.contacts[iC].other_point <  side.contacts[iC].other_side->from ||
+             side.contacts[iC].other_point >= side.contacts[iC].other_side->to )
+          continue;
         const vector<UVPtStruct>& oGrid = side.contacts[iC].other_side->grid->GetUVPtStruct();
         const UVPtStruct&         uvPt  = points[ side.contacts[iC].point ];
-        if ( side.contacts[iC].other_point >= oGrid.size()      ||
+        if ( side.contacts[iC].other_point >= oGrid .size() ||
              side.contacts[iC].point       >= points.size() )
           throw SALOME_Exception( "StdMeshers_Quadrangle_2D::addEnforcedNodes(): wrong contact" );
         if ( oGrid[ side.contacts[iC].other_point ].node )
           (( UVPtStruct& ) uvPt).node = oGrid[ side.contacts[iC].other_point ].node;
       }
+
+      bool missedNodesOnSide = false;
       for ( size_t iP = 0; iP < points.size(); ++iP )
         if ( !points[ iP ].node )
         {
           UVPtStruct& uvPnt = ( UVPtStruct& ) points[ iP ];
-          gp_Pnt P = surf->Value( uvPnt.u, uvPnt.v );
-          uvPnt.node = meshDS->AddNode(P.X(), P.Y(), P.Z());
-          meshDS->SetNodeOnFace( uvPnt.node, myHelper->GetSubShapeID(), uvPnt.u, uvPnt.v );
+          gp_Pnt          P = surf->Value( uvPnt.u, uvPnt.v );
+          uvPnt.node = myHelper->AddNode(P.X(), P.Y(), P.Z(), 0, uvPnt.u, uvPnt.v );
           missedNodesOnSide = true;
         }
       if ( missedNodesOnSide )
@@ -4978,8 +5035,10 @@ int StdMeshers_Quadrangle_2D::splitQuad(FaceQuadStruct::Ptr quad, int I, int J)
     newQuad->side[ QUAD_TOP_SIDE    ].from = iTop;
     newQuad->name = ( TComm("Right of I=") << I );
 
-    quad->side[ QUAD_BOTTOM_SIDE ].to = iBot + 1;
-    quad->side[ QUAD_TOP_SIDE    ].to = iTop + 1;
+    bool bRev = quad->side[ QUAD_BOTTOM_SIDE ].IsReversed();
+    bool tRev = quad->side[ QUAD_TOP_SIDE    ].IsReversed();
+    quad->side[ QUAD_BOTTOM_SIDE ].to = iBot + ( bRev ? -1 : +1 );
+    quad->side[ QUAD_TOP_SIDE    ].to = iTop + ( tRev ? -1 : +1 );
     quad->uv_grid.clear();
 
     return QUAD_LEFT_SIDE;
@@ -5013,8 +5072,10 @@ int StdMeshers_Quadrangle_2D::splitQuad(FaceQuadStruct::Ptr quad, int I, int J)
     //      << " L " << &quad->side[ QUAD_LEFT_SIDE ] << " "<< quad->side[ QUAD_LEFT_SIDE].NbPoints()
     //      << " R " << &quad->side[ QUAD_RIGHT_SIDE ]  << " "<< quad->side[ QUAD_RIGHT_SIDE].NbPoints()<< endl;
 
-    newQuad->side[ QUAD_RIGHT_SIDE ].to = iRgt+1;
-    newQuad->side[ QUAD_LEFT_SIDE  ].to = iLft+1;
+    bool rRev = newQuad->side[ QUAD_RIGHT_SIDE ].IsReversed();
+    bool lRev = newQuad->side[ QUAD_LEFT_SIDE  ].IsReversed();
+    newQuad->side[ QUAD_RIGHT_SIDE ].to = iRgt + ( rRev ? -1 : +1 );
+    newQuad->side[ QUAD_LEFT_SIDE  ].to = iLft + ( lRev ? -1 : +1 );
     newQuad->name = ( TComm("Below J=") << J );
 
     quad->side[ QUAD_RIGHT_SIDE ].from = iRgt;
@@ -5567,6 +5628,8 @@ void FaceQuadStruct::Side::AddContact( int ip, Side* side, int iop )
   if ( ip  >= GetUVPtStruct().size()      ||
        iop >= side->GetUVPtStruct().size() )
     throw SALOME_Exception( "FaceQuadStruct::Side::AddContact(): wrong point" );
+  if ( ip < from || ip >= to )
+    return;
   {
     contacts.resize( contacts.size() + 1 );
     Contact&    c = contacts.back();
index 6a06c9a46af65cccf7d52a7d132a2585e8784cb6..460a5e4ab7fbbd948b0f064face9a77f1f42be1b 100644 (file)
@@ -244,9 +244,10 @@ class STDMESHERS_EXPORT StdMeshers_Quadrangle_2D: public SMESH_2D_Algo
 
   struct ForcedPoint
   {
-    gp_XY         uv;
-    gp_XYZ        xyz;
-    TopoDS_Vertex vertex;
+    gp_XY                uv;
+    gp_XYZ               xyz;
+    TopoDS_Vertex        vertex;
+    const SMDS_MeshNode* node;
 
     double U() const { return uv.X(); }
     double V() const { return uv.Y(); }
index 6a2f5df176f4de0b41e981dfa1ab80bc5cf5c70a..03395bd108806aa396c50e9fd5909e31afeefa6b 100644 (file)
@@ -75,10 +75,12 @@ StdMeshers_RadialQuadrangle_1D2D::StdMeshers_RadialQuadrangle_1D2D(int hypId,
 
   _compatibleHypothesis.push_back("LayerDistribution2D");
   _compatibleHypothesis.push_back("NumberOfLayers2D");
-  myNbLayerHypo = 0;
-  myDistributionHypo = 0;
   _requireDiscreteBoundary = false;
   _supportSubmeshes = true;
+  _neededLowerHyps[ 1 ] = true;  // suppress warning on hiding a global 1D algo
+
+  myNbLayerHypo      = 0;
+  myDistributionHypo = 0;
 }
 
 
@@ -278,6 +280,38 @@ namespace
     }
     return nbe;
   }
+  //================================================================================
+  /*!
+   * \brief Checks if the common vertex between LinEdge's lies inside the circle
+   *  and not outside
+   *  \param [in] CircEdge - 
+   *  \param [in] LinEdge1 - 
+   *  \param [in] LinEdge2 - 
+   *  \return bool - false if there are 3 EDGEs and the corner is outside
+   */
+  //================================================================================
+
+  bool isCornerInsideCircle(const TopoDS_Edge& CircEdge,
+                            const TopoDS_Edge& LinEdge1,
+                            const TopoDS_Edge& LinEdge2)
+  {
+    if ( !CircEdge.IsNull() &&
+         !LinEdge1.IsNull() &&
+         !LinEdge2.IsNull() )
+    {
+      Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
+      TopoDS_Vertex aCommonV;
+      if ( !aCirc.IsNull() &&
+           TopExp::CommonVertex( LinEdge1, LinEdge2, aCommonV ))
+      {
+        gp_Pnt aCommonP = BRep_Tool::Pnt( aCommonV );
+        gp_Pnt  aCenter = aCirc->Location();
+        double     dist = aCenter.Distance( aCommonP );
+        return dist < 0.1 * aCirc->Radius();
+      }
+    }
+    return true;
+  }
 
 //================================================================================
 //================================================================================
@@ -436,7 +470,7 @@ bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh&         aMesh,
   TopoDS_Edge CircEdge, LinEdge1, LinEdge2;
   int nbe = analyseFace( aShape, CircEdge, LinEdge1, LinEdge2 );
   Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
-  if( nbe>3 || nbe < 1 || aCirc.IsNull() )
+  if( nbe > 3 || nbe < 1 || aCirc.IsNull() )
     return error("The face must be a full circle or a part of circle (i.e. the number "
                  "of edges is less or equal to 3 and one of them is a circle curve)");
 
@@ -669,15 +703,17 @@ bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh&         aMesh,
     // segments of line
     double fp, lp;
     Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
-    Handle(Geom_Line)  aLine1 = Handle(Geom_Line)::DownCast( getCurve( LinEdge1 ));
-    Handle(Geom_Line)  aLine2 = Handle(Geom_Line)::DownCast( getCurve( LinEdge2 ));
-    if( aCirc.IsNull() || aLine1.IsNull() || aLine2.IsNull() )
+    Handle(Geom_Line)  aLine1 = Handle(Geom_Line  )::DownCast( getCurve( LinEdge1 ));
+    Handle(Geom_Line)  aLine2 = Handle(Geom_Line  )::DownCast( getCurve( LinEdge2 ));
+    if ( aCirc.IsNull() || aLine1.IsNull() || aLine2.IsNull() )
+      return error(COMPERR_BAD_SHAPE);
+    if ( !isCornerInsideCircle( CircEdge, LinEdge1, LinEdge2 ))
       return error(COMPERR_BAD_SHAPE);
 
     if ( !algo1d->ComputeCircularEdge( aMesh, CircEdge ))
       return error( algo1d->GetComputeError() );
     map< double, const SMDS_MeshNode* > theNodes;
-    if ( !GetSortedNodesOnEdge(aMesh.GetMeshDS(),CircEdge,true,theNodes))
+    if ( !GetSortedNodesOnEdge( aMesh.GetMeshDS(), CircEdge, true, theNodes ))
       return error("Circular edge is incorrectly meshed");
 
     myHelper->IsQuadraticSubMesh( aShape );
@@ -894,8 +930,7 @@ bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh&         aMesh,
   //cout<<"Angles.Length() = "<<Angles.Length()<<"   Points.Length() = "<<Points.Length()<<endl;
   //cout<<"Nodes1.size() = "<<Nodes1.size()<<"   Pnts2d1.Length() = "<<Pnts2d1.Length()<<endl;
   for(; i<Angles.Length(); i++) {
-    vector< const SMDS_MeshNode* > tmpNodes;
-    tmpNodes.reserve(Nodes1.size());
+    vector< const SMDS_MeshNode* > tmpNodes(Nodes1.size());
     gp_Trsf aTrsf;
     gp_Ax1 theAxis(P0,gp_Dir(Axis));
     aTrsf.SetRotation( theAxis, Angles.Value(i) );
@@ -1290,18 +1325,20 @@ bool StdMeshers_RadialQuadrangle_1D2D::Evaluate(SMESH_Mesh& aMesh,
 
 //================================================================================
 /*!
- * \brief Return true if applied compute mesh on this shape
+ * \brief Return true if the algorithm can compute mesh on this shape
  */
 //================================================================================
 
 bool StdMeshers_RadialQuadrangle_1D2D::IsApplicable( const TopoDS_Shape & aShape, bool toCheckAll )
 {
   int nbFoundFaces = 0;
-  for (TopExp_Explorer exp( aShape, TopAbs_FACE ); exp.More(); exp.Next(), ++nbFoundFaces ){
+  for (TopExp_Explorer exp( aShape, TopAbs_FACE ); exp.More(); exp.Next(), ++nbFoundFaces )
+  {
     TopoDS_Edge CircEdge, LinEdge1, LinEdge2;
     int nbe = analyseFace( exp.Current(), CircEdge, LinEdge1, LinEdge2 );
     Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
-    bool ok = ( nbe <= 3 && nbe >= 1 && !aCirc.IsNull() );
+    bool ok = ( nbe <= 3 && nbe >= 1 && !aCirc.IsNull() &&
+                isCornerInsideCircle( CircEdge, LinEdge1, LinEdge2 ));
     if( toCheckAll  && !ok ) return false;
     if( !toCheckAll && ok  ) return true;
   }
index be0c2a4dd6698d69992eb2173f4678febe78be9d..9db3c64c0ba7b09d86e71192f9c52c9a2c769ce7 100644 (file)
@@ -72,7 +72,6 @@ SET(_link_LIBRARIES
 # header files / to be processed by moc
 SET(_moc_HEADERS
   StdMeshersGUI_StdHypothesisCreator.h
-  StdMeshersGUI_DistrPreview.h
   StdMeshersGUI_DistrTable.h
   StdMeshersGUI_NbSegmentsCreator.h
   StdMeshersGUI_ObjectReferenceParamWdg.h
@@ -85,6 +84,12 @@ SET(_moc_HEADERS
   StdMeshersGUI_PropagationHelperWdg.h
 )
 
+IF(SALOME_USE_PLOT2DVIEWER)
+  LIST(APPEND _moc_HEADERS
+    StdMeshersGUI_DistrPreview.h
+    )
+ENDIF()
+
 # header files / no moc processing
 SET(_other_HEADERS
   SMESH_StdMeshersGUI.hxx
@@ -102,7 +107,6 @@ QT4_WRAP_CPP(_moc_SOURCES ${_moc_HEADERS})
 SET(_other_SOURCES
   StdMeshersGUI.cxx
   StdMeshersGUI_StdHypothesisCreator.cxx
-  StdMeshersGUI_DistrPreview.cxx
   StdMeshersGUI_DistrTable.cxx
   StdMeshersGUI_NbSegmentsCreator.cxx
   StdMeshersGUI_ObjectReferenceParamWdg.cxx
@@ -115,6 +119,12 @@ SET(_other_SOURCES
   StdMeshersGUI_PropagationHelperWdg.cxx
 )
 
+IF(SALOME_USE_PLOT2DVIEWER)
+  LIST(APPEND _other_SOURCES
+    StdMeshersGUI_DistrPreview.cxx
+    )
+ENDIF()
+
 # sources / to compile
 SET(StdMeshersGUI_SOURCES ${_other_SOURCES} ${_moc_SOURCES})
 
index 90005331aaa3d103a287dfc221d4bfe7b9e7a18e..0d567e4fb232d2e74af3458a136ca8d5cd6547f5 100644 (file)
@@ -106,7 +106,7 @@ StdMeshersGUI_DistrPreview::StdMeshersGUI_DistrPreview( QWidget* p, StdMeshers::
   myDistr->attach( this );
   QPen distrPen = QPen( Qt::blue, 1 );
   QwtSymbol* distrSymbol = new QwtSymbol( QwtSymbol::XCross, QBrush( Qt::blue ),
-                                                 QPen( Qt::blue ), QSize( 5, 5 ) );
+                                                  QPen( Qt::blue ), QSize( 5, 5 ) );
   myDistr->setPen( distrPen );
   myDistr->setSymbol( distrSymbol );
   if( Plot2d_QwtLegendLabel* anItem = getLegendLabel( myDistr ) ) {
index b67942897ae89c93f83006f968fee15c3dece2a6..82d2e437d8726a5a743e365d02278b3e1f5ebf3c 100644 (file)
@@ -111,9 +111,11 @@ void StdMeshersGUI_LayerDistributionParamWdg::init()
 
   myCreateButton = new QPushButton( this );
   myCreateButton->setObjectName( "createBut" );
+  myCreateButton->setMinimumWidth(100);
 
   myEditButton   = new QPushButton( tr("EDIT"), this );
   myEditButton->setObjectName( "editBut" );
+  myEditButton->setMinimumWidth(100);
 
   myHypTypePopup = new QMenu( this );
 
@@ -130,8 +132,8 @@ void StdMeshersGUI_LayerDistributionParamWdg::init()
   }
 
   aHBox->addWidget( myCreateButton );
+  aHBox->addStretch(5);
   aHBox->addWidget( myEditButton );
-  aHBox->addStretch();
 
   connect( myCreateButton, SIGNAL(clicked()), SLOT(onCreate()));
   connect( myEditButton,   SIGNAL(clicked()), SLOT(onEdit()));
index 0d86a141a936f791c0bd747c00e84fe178d4e626..fa4eb1dcc19f93aba7715d911075fc99ce650bb5 100644 (file)
@@ -25,7 +25,9 @@
 // SMESH includes
 //
 #include "StdMeshersGUI_NbSegmentsCreator.h"
-#include "StdMeshersGUI_DistrPreview.h"
+#ifndef DISABLE_PLOT2DVIEWER
+  #include "StdMeshersGUI_DistrPreview.h"
+#endif
 #include "StdMeshersGUI_DistrTable.h"
 #include "StdMeshersGUI_PropagationHelperWdg.h"
 #include "StdMeshersGUI_SubShapeSelectorWdg.h"
@@ -64,7 +66,9 @@ StdMeshersGUI_NbSegmentsCreator::StdMeshersGUI_NbSegmentsCreator()
   myDistr( 0 ),
   myScale( 0 ),
   myTable( 0 ),
+#ifndef DISABLE_PLOT2DVIEWER
   myPreview( 0 ),
+#endif
   myExpr( 0 ),
   myConvBox( 0 ),
   myConv( 0 ),
@@ -179,12 +183,14 @@ QFrame* StdMeshersGUI_NbSegmentsCreator::buildFrame()
   
        // c)  table
   myTable = new StdMeshersGUI_DistrTableFrame( GroupC1 );
+  myTable->setMinimumHeight(220);
   myDistLayout->addWidget( myTable, 1, 0, 2, 1 );
 
+#ifndef DISABLE_PLOT2DVIEWER
        // d) preview
   myPreview = new StdMeshersGUI_DistrPreview( GroupC1, h.in() );  
-  myPreview->setMinimumHeight(220);
   myDistLayout->addWidget( myPreview, 1, 1, 2, 1 );
+#endif
   
   // 5)  conversion (radiogroup)
   myConvBox = new QGroupBox( tr( "SMESH_CONV_MODE" ), GroupC1 );
@@ -449,7 +455,9 @@ void StdMeshersGUI_NbSegmentsCreator::onValueChanged()
   myDirectionWidget->ShowPreview( distr!=0 );
 
   bool isFunc = distr==2 || distr==3;
+#ifndef DISABLE_PLOT2DVIEWER
   myPreview->setShown( isFunc );
+#endif
   myConvBox->setShown( isFunc );
   
   myTable->setShown( distr==2 );
@@ -457,6 +465,7 @@ void StdMeshersGUI_NbSegmentsCreator::onValueChanged()
   myLExpr->setShown( distr==3 );
   myInfo->setShown( distr==3);
 
+#ifndef DISABLE_PLOT2DVIEWER
   //change of preview
   int nbSeg = myNbSeg->value();
   if( distr==2 ) //preview for table-described function
@@ -470,6 +479,7 @@ void StdMeshersGUI_NbSegmentsCreator::onValueChanged()
 
   if( isFunc )
     myPreview->setConversion( StdMeshersGUI_DistrPreview::Conversion( myConv->checkedId() ) );
+#endif
 
   if ( (QtxComboBox*)sender() == myDistr && dlg() ) {
     QApplication::instance()->processEvents();
index f39b2feb9c2089939249f22eba6eb2deb2a7be74..99c235e4ac6067782a411b9c3ccea78de9478188 100644 (file)
@@ -39,7 +39,9 @@ class SalomeApp_IntSpinBox;
 class QtxComboBox;
 class SMESHGUI_SpinBox;
 class StdMeshersGUI_DistrTableFrame;
-class StdMeshersGUI_DistrPreview;
+#ifndef DISABLE_PLOT2DVIEWER
+  class StdMeshersGUI_DistrPreview;
+#endif
 class QLineEdit;
 class QButtonGroup;
 class QGroupBox;
@@ -86,7 +88,9 @@ private:
   QtxComboBox*     myDistr;
   SMESHGUI_SpinBox*   myScale;
   StdMeshersGUI_DistrTableFrame*  myTable;
+#ifndef DISABLE_PLOT2DVIEWER
   StdMeshersGUI_DistrPreview* myPreview;
+#endif
   QLineEdit       *myName, *myExpr;
   QGroupBox*       myConvBox;
   QButtonGroup*    myConv;
index 63eb5de65f055e3a65d806d0bf367d6952fb65cd..03706a8fe392b5c65c59cc8d2a217d65a4d9131b 100644 (file)
@@ -57,7 +57,7 @@ public:
   StdMeshersGUI_ObjectReferenceParamWdg( SUIT_SelectionFilter* filter, 
                                          QWidget*              parent,
                                          bool                  multiSelection=false
-                                        /* ,bool                  stretch=true*/);
+                                         /* ,bool                  stretch=true*/);
   StdMeshersGUI_ObjectReferenceParamWdg( SMESH::MeshObjectType objType,
                                          QWidget*       parent,
                                          bool           multiSelection=false);
index 5f38e7f6c97dc7ef0e720d134f50371934b1ae9a..ea722142c8ebfff0881eb20bb03730226c3b14f9 100644 (file)
@@ -1349,6 +1349,7 @@ void StdMeshersGUI_StdHypothesisCreator::attuneStdWidget (QWidget* w, const int)
     {
       sb->RangeStepAndValidator( VALUE_SMALL, VALUE_MAX, 1.0, "length_precision" );
       sb->setEnabled( !widget< QCheckBox >( 1 )->isChecked() );
+      sb->setMinimumWidth( 150 );
     }
     else if( hypType()=="MaxElementArea" )
     {
@@ -1617,9 +1618,10 @@ void StdMeshersGUI_StdHypothesisCreator::valueChanged( QWidget* paramWidget)
   }
   else if ( hypType().startsWith( "ViscousLayers" ) && paramWidget->inherits("QButtonGroup"))
   {
-    if ( QLabel* label = getLabel(4) )
+    int widgetNumber = hypType() == "ViscousLayers2D" ? 3 : 4;
+    if ( QLabel* label = getLabel( widgetNumber + 1 ) )
     {
-      bool toIgnore = widget< StdMeshersGUI_RadioButtonsGrpWdg >( 3 )->checkedId();
+      bool toIgnore = widget< StdMeshersGUI_RadioButtonsGrpWdg >( widgetNumber )->checkedId();
       if ( hypType() == "ViscousLayers2D" )
         label->setText( tr( toIgnore ? "SMESH_EDGES_WO_LAYERS" : "SMESH_EDGES_WITH_LAYERS" ));
       else
index 7b605972d31ea7d74f53b88e1e5028463df794b3..66da7722e2d71ca00fd84f78368e5d70b5420925 100644 (file)
@@ -255,24 +255,27 @@ void StdMeshersGUI_SubShapeSelectorWdg::selectionIntoArgument()
 
       GEOM::GEOM_Object_var aGeomObj = GetGeomObjectByEntry( IO->getEntry() );
       if ( !CORBA::is_nil( aGeomObj ) ) { // Selected Object From Study
-        GEOM::GEOM_Object_var aGeomFatherObj = aGeomObj->GetMainShape();
-        QString aFatherEntry = "";
-        QString aMainFatherEntry = "";
-        TopoDS_Shape shape;
-        if ( !CORBA::is_nil( aGeomFatherObj ) ) {
-          // Get Main Shape
-          GEOM::GEOM_Object_var aGeomMain = GetGeomObjectByEntry( myEntry.c_str() );
-          if ( !CORBA::is_nil( aGeomMain ) && aGeomMain->GetType() == 37 ) {  // Main Shape is a Group
-            GEOM::GEOM_Object_var aMainFatherObj = aGeomMain->GetMainShape();
-            if ( !CORBA::is_nil( aMainFatherObj ) )
-              aMainFatherEntry = aMainFatherObj->GetStudyEntry();
-          }
-          aFatherEntry = aGeomFatherObj->GetStudyEntry();
-        }
-
-        if (( ! aFatherEntry.isEmpty() ) &&
-            ( aFatherEntry == myEntry.c_str() || aFatherEntry == aMainFatherEntry ) )
+        // commented for IPAL52836
+        //
+        // GEOM::GEOM_Object_var aGeomFatherObj = aGeomObj->GetMainShape();
+        // QString aFatherEntry = "";
+        // QString aMainFatherEntry = "";
+        // TopoDS_Shape shape;
+        // if ( !CORBA::is_nil( aGeomFatherObj ) ) {
+        //   // Get Main Shape
+        //   GEOM::GEOM_Object_var aGeomMain = GetGeomObjectByEntry( myEntry.c_str() );
+        //   if ( !CORBA::is_nil( aGeomMain ) && aGeomMain->GetType() == 37 ) {  // Main Shape is a Group
+        //     GEOM::GEOM_Object_var aMainFatherObj = aGeomMain->GetMainShape();
+        //     if ( !CORBA::is_nil( aMainFatherObj ) )
+        //       aMainFatherEntry = aMainFatherObj->GetStudyEntry();
+        //   }
+        //   aFatherEntry = aGeomFatherObj->GetStudyEntry();
+        // }
+
+        // if (( ! aFatherEntry.isEmpty() ) &&
+        //     ( aFatherEntry == myEntry.c_str() || aFatherEntry == aMainFatherEntry ) )
         {
+          TopoDS_Shape shape;
           if ( aGeomObj->GetType() == 37 /*GEOM_GROUP*/ ) { // Selected Group that belongs the main object
             GEOMBase::GetShape(aGeomObj, shape);
             if ( !shape.IsNull() ) {
@@ -285,7 +288,9 @@ void StdMeshersGUI_SubShapeSelectorWdg::selectionIntoArgument()
                 }
               }
             }
-          } else if ( aGeomObj->GetType() == 28 /*GEOM_SUBSHAPE*/  ) {
+          } else if ( aGeomObj->GetType() == 28 /*GEOM_SUBSHAPE*/ ||
+                      myEntry == IO->getEntry() )
+          {
             GEOMBase::GetShape(aGeomObj, shape); 
             if ( !shape.IsNull() && shape.ShapeType() == mySubShType ) {
               int index = myPreviewActor->GetIndexByShape( shape );
@@ -412,7 +417,7 @@ void StdMeshersGUI_SubShapeSelectorWdg::onListSelectionChanged()
   if ( !myPreviewActor )
     return;
 
-  mySelectionMgr->clearSelected();
+  //mySelectionMgr->clearSelected();
   TColStd_MapOfInteger aIndexes;
   QList<QListWidgetItem*> selItems = myListWidget->selectedItems();
   QListWidgetItem* anItem;
@@ -421,6 +426,8 @@ void StdMeshersGUI_SubShapeSelectorWdg::onListSelectionChanged()
 
   // update remove button
   myRemoveButton->setEnabled( selItems.size() > 0 );
+
+  emit selectionChanged();
 }
 
 //=================================================================================
@@ -525,9 +532,6 @@ SMESH::long_array_var StdMeshersGUI_SubShapeSelectorWdg::GetListOfIDs()
 {
   SMESH::long_array_var anArray = new SMESH::long_array;
 
-  // if ( myMainEntry != "" && myIsNotCorrected )
-  //   myListOfIDs = GetCorrectedListOfIDs( true );
-
   int size = myListOfIDs.size();
   anArray->length( size );
   for (int i = 0; i < size; i++)
@@ -570,17 +574,6 @@ bool StdMeshersGUI_SubShapeSelectorWdg::SetListOfIDs( SMESH::long_array_var theI
   return isOk;
 }
 
-//=================================================================================
-// function : SetMainShapeEntry
-// purpose  : Called to set the Entry of main shape of the mesh
-//=================================================================================
-// void StdMeshersGUI_SubShapeSelectorWdg::SetMainShapeEntry( const QString& theEntry )
-// {
-//   myMainEntry = theEntry;
-//   myMainShape = GetTopoDSByEntry( theEntry );
-//   myIsNotCorrected = true;
-// }
-
 //=================================================================================
 // function : GetMainShapeEntry
 // purpose  : Called to get the Main Object Entry
@@ -591,82 +584,6 @@ const char* StdMeshersGUI_SubShapeSelectorWdg::GetMainShapeEntry()
   return myMainEntry.c_str();
 }
 
-//=================================================================================
-// function : GetCorrectedListOfIds
-// purpose  : Called to convert the list of IDs from sub-shape IDs to main shape IDs
-//=================================================================================
-// QList<int>
-// StdMeshersGUI_SubShapeSelectorWdg::GetCorrectedListOfIDs( bool fromSubshapeToMainshape,
-//                                                           bool* isOK )
-// {
-//   if (( myMainShape.IsNull() || myGeomShape.IsNull() ) &&  fromSubshapeToMainshape )
-//     return myListOfIDs;
-//   else if (( myMainShape.IsNull() /*||*/&& myGeomShape.IsNull() ) &&  !fromSubshapeToMainshape )
-//     return mySelectedIDs;
-
-//   if ( !fromSubshapeToMainshape ) // called from SetListOfIDs
-//   {
-//     if ( myMainShape.IsNull() )
-//       std::swap( myMainShape, myGeomShape );
-//   }
-
-//   QList<int> aList;
-//   TopTools_IndexedMapOfShape aGeomMap, aMainMap;
-//   TopExp::MapShapes(myMainShape, aMainMap);
-//   if ( !myGeomShape.IsNull() )
-//     TopExp::MapShapes(myGeomShape, aGeomMap);
-
-//   bool ok = true;
-//   if ( fromSubshapeToMainshape ) // convert indexes from sub-shape to mainshape
-//   {
-//     int size = myListOfIDs.size();
-//     for (int i = 0; i < size; i++) {
-//       int index = myListOfIDs.at(i);
-//       if ( aGeomMap.Extent() < index )
-//       {
-//         ok = false;
-//       }
-//       else
-//       {
-//         TopoDS_Shape aSubShape = aGeomMap.FindKey( index );
-//         if ( mySubShType != aSubShape.ShapeType() )
-//           ok = false;
-//         if ( !aMainMap.Contains( aSubShape ))
-//           ok = false;
-//         else
-//           index = aMainMap.FindIndex( aSubShape );
-//       }
-//       aList.append( index );
-//     }
-//     myIsNotCorrected = false;
-//   }
-//   else // convert indexes from main shape to sub-shape, or just check indices
-//   {
-//     int size = mySelectedIDs.size();
-//     for (int i = 0; i < size; i++) {
-//       int index = mySelectedIDs.at(i);
-//       if ( aMainMap.Extent() < index )
-//       {
-//         ok = false;
-//       }
-//       else
-//       {
-//         TopoDS_Shape aSubShape = aMainMap.FindKey( index );
-//         if ( mySubShType != aSubShape.ShapeType() )
-//           ok = false;
-//         if ( !aGeomMap.Contains( aSubShape ) && !aGeomMap.IsEmpty() )
-//           ok = false;
-//         else
-//           index = aGeomMap.FindIndex( aSubShape );
-//       }
-//       aList.append( index );
-//     }
-//   }
-//   if ( isOK ) *isOK = ok;
-
-//   return aList;
-// }
-
 void StdMeshersGUI_SubShapeSelectorWdg::updateButtons()
 {
   if ( myPreviewActor ) {
index 7d0a5bd1ddd8c248d0bec24458a73dbea7629a21..1b40658d95d11c4340fefa14924962f7f0bae927 100644 (file)
@@ -85,6 +85,9 @@ public:
   SMESH_PreviewActorsCollection* GetActorCollection() { return myPreviewActor; }
   void                           ClearSelected();
 
+signals:
+  void                           selectionChanged();
+
 private:
   void                           updateState();
   void                           setFilter();
index e744cf34e978f01454fc6490f9ddde683a34fee4..0f56903ef2b147f423333fdf675f5f97c8c54168 100644 (file)
             <source>ICON_SMESH_TREE_ALGO_MEFISTO_2D</source>
             <translation>mesh_tree_algo_mefisto.png</translation>
         </message>
+        <message>
+            <source>ICON_SMESH_TREE_ALGO_PolygonPerFace_2D</source>
+            <translation>mesh_tree_algo_polygon.png</translation>
+        </message>
         <message>
             <source>ICON_SMESH_TREE_ALGO_Projection_1D</source>
             <translation>mesh_tree_algo_regular.png</translation>
index a2394892579ff10d4271f60b5fd4bf451addf7c4..5b6fe40c30f13be00185adebc70f77b5b4926ca5 100644 (file)
@@ -322,11 +322,11 @@ this one for this mesh/sub-mesh.</translation>
     </message>
     <message>
         <source>SMESH_NUMBER_OF_LAYERS_HYPOTHESIS</source>
-        <translation>Radial Prism Parameter</translation>
+        <translation>Radial Discretization</translation>
     </message>
     <message>
         <source>SMESH_NUMBER_OF_LAYERS_2D_HYPOTHESIS</source>
-        <translation>Radial Quadrangle Parameter</translation>
+        <translation>Radial Discretization</translation>
     </message>
     <message>
         <source>SMESH_NUMBER_OF_LAYERS_TITLE</source>
index ca25b3ee0ee2c0ee590888f69b8b3bc2e143d39e..3e07638091be8cfcc6dec9cb623f27bc81b6db68 100644 (file)
       <source>ENF_NODES</source>
       <translation>強化された節点</translation>
     </message>
-    <message>
-      <source/>
-      <translation type="unfinished"/>
-    </message>
   </context>
   <context>
     <name>StdMeshersGUI_LayerDistributionParamWdg</name>
index 7e1ab27e81fdcfa3ba7f3a1fb165baa05559bc58..57b2d058a1862d2769e634af47bf0c08443a1c55 100644 (file)
@@ -119,6 +119,7 @@ SET(StdMeshersEngine_HEADERS
   StdMeshers_ViscousLayers2D_i.hxx
   StdMeshers_CartesianParameters3D_i.hxx
   StdMeshers_Cartesian_3D_i.hxx
+  StdMeshers_PolygonPerFace_2D_i.hxx
 )
 IF(SALOME_SMESH_ENABLE_MEFISTO)
   SET(StdMeshersEngine_HEADERS ${StdMeshersEngine_HEADERS} StdMeshers_MEFISTO_2D_i.hxx)
@@ -173,6 +174,7 @@ SET(StdMeshersEngine_SOURCES
   StdMeshers_CartesianParameters3D_i.cxx
   StdMeshers_Cartesian_3D_i.cxx
   StdMeshers_Adaptive1D_i.cxx 
+  StdMeshers_PolygonPerFace_2D_i.cxx
 )
 
 IF(SALOME_SMESH_ENABLE_MEFISTO)
diff --git a/src/StdMeshers_I/StdMeshers_PolygonPerFace_2D_i.cxx b/src/StdMeshers_I/StdMeshers_PolygonPerFace_2D_i.cxx
new file mode 100644 (file)
index 0000000..d41e343
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// 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
+//
+
+//  File   : StdMeshers_PolygonPerFace_2D_i.cxx
+//  Module : SMESH
+//
+
+#include "StdMeshers_PolygonPerFace_2D_i.hxx"
+
+#include "SMESH_Gen.hxx"
+#include "StdMeshers_PolygonPerFace_2D.hxx"
+
+//=============================================================================
+/*!
+ *  Constructor
+ */
+//=============================================================================
+
+StdMeshers_PolygonPerFace_2D_i::StdMeshers_PolygonPerFace_2D_i( PortableServer::POA_ptr thePOA,
+                                                                int                     theStudyId,
+                                                                ::SMESH_Gen*            theGenImpl )
+  : SALOME::GenericObj_i( thePOA ),
+    SMESH_Hypothesis_i( thePOA ),
+    SMESH_Algo_i( thePOA ),
+    SMESH_2D_Algo_i( thePOA )
+{
+  //MESSAGE( "StdMeshers_PolygonPerFace_2D_i::StdMeshers_PolygonPerFace_2D_i" );
+  myBaseImpl = new ::StdMeshers_PolygonPerFace_2D( theGenImpl->GetANewId(),
+                                                   theStudyId,
+                                                   theGenImpl );
+}
+
+//=============================================================================
+/*!
+ *  Destructor
+ */
+//=============================================================================
+
+StdMeshers_PolygonPerFace_2D_i::~StdMeshers_PolygonPerFace_2D_i()
+{
+  //MESSAGE( "StdMeshers_PolygonPerFace_2D_i::~StdMeshers_PolygonPerFace_2D_i" );
+}
diff --git a/src/StdMeshers_I/StdMeshers_PolygonPerFace_2D_i.hxx b/src/StdMeshers_I/StdMeshers_PolygonPerFace_2D_i.hxx
new file mode 100644 (file)
index 0000000..3718010
--- /dev/null
@@ -0,0 +1,54 @@
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// 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
+//
+
+//  File   : StdMeshers_PolygonPerFace_2D_i.hxx
+//  Module : SMESH
+//
+#ifndef _SMESH_PolygonPerFace_2D_I_HXX_
+#define _SMESH_PolygonPerFace_2D_I_HXX_
+
+#include "SMESH_StdMeshers_I.hxx"
+
+#include <SALOMEconfig.h>
+#include CORBA_SERVER_HEADER(SMESH_BasicHypothesis)
+
+#include "SMESH_2D_Algo_i.hxx"
+
+class SMESH_Gen;
+
+// ======================================================
+// Polygon Per Face 2d algorithm
+// ======================================================
+class STDMESHERS_I_EXPORT StdMeshers_PolygonPerFace_2D_i:
+  public virtual POA_StdMeshers::StdMeshers_PolygonPerFace_2D,
+  public virtual SMESH_2D_Algo_i
+{
+ public:
+  // Constructor
+  StdMeshers_PolygonPerFace_2D_i( PortableServer::POA_ptr thePOA,
+                                  int                     theStudyId,
+                                  ::SMESH_Gen*            theGenImpl );
+  // Destructor
+  virtual ~StdMeshers_PolygonPerFace_2D_i();
+};
+
+#endif
index cf497681c33af745a46d390489cc3a9c3f3c763c..c9a1ef050ca198bae48d31ed92a058f0163d4430 100644 (file)
@@ -136,3 +136,15 @@ StdMeshers_QuadFromMedialAxis_1D2D_i::~StdMeshers_QuadFromMedialAxis_1D2D_i()
 {
   MESSAGE( "StdMeshers_QuadFromMedialAxis_1D2D_i::~StdMeshers_QuadFromMedialAxis_1D2D_i" );
 }
+
+//================================================================================
+/*!
+ * \brief Return true if the algorithm is applicable to a shape
+ */
+//================================================================================
+
+CORBA::Boolean StdMeshers_QuadFromMedialAxis_1D2D_i::IsApplicable( const TopoDS_Shape &S,
+                                                                   CORBA::Boolean toCheckAll )
+{
+  return ::StdMeshers_QuadFromMedialAxis_1D2D::IsApplicable( S, toCheckAll );
+}
index 145d31e3c0374aeac6092c5d9778ac81d04e09c0..c8c2cf1157f6983e01c7d7554f6678c147d8cab3 100644 (file)
@@ -78,11 +78,8 @@ class STDMESHERS_I_EXPORT StdMeshers_QuadFromMedialAxis_1D2D_i:
   // Destructor
   virtual ~StdMeshers_QuadFromMedialAxis_1D2D_i();
 
-  // Get implementation
-  //::StdMeshers_Quadrangle_2D* GetImpl();
-
   // Return true if the algorithm is applicable to a shape
-  //static CORBA::Boolean IsApplicable(const TopoDS_Shape &S, CORBA::Boolean toCheckAll);
+  static CORBA::Boolean IsApplicable(const TopoDS_Shape &S, CORBA::Boolean toCheckAll);
 };
 
 #endif
index 3e9eb70b7ea4304ef1e64af3d9f34c5ab0e0caaa..2346e1cf80ceb9deca68fdcd033149e045d2e30e 100644 (file)
 
 #include "utilities.h"
 
-#include "StdMeshers_LocalLength_i.hxx"
-#include "StdMeshers_AutomaticLength_i.hxx"
-#include "StdMeshers_StartEndLength_i.hxx"
+#include "StdMeshers_Adaptive1D_i.hxx"
 #include "StdMeshers_Arithmetic1D_i.hxx"
-#include "StdMeshers_Geometric1D_i.hxx"
-#include "StdMeshers_FixedPoints1D_i.hxx"
-#include "StdMeshers_NumberOfSegments_i.hxx"
+#include "StdMeshers_AutomaticLength_i.hxx"
+#include "StdMeshers_CartesianParameters3D_i.hxx"
+#include "StdMeshers_Cartesian_3D_i.hxx"
+#include "StdMeshers_CompositeSegment_1D_i.hxx"
 #include "StdMeshers_Deflection1D_i.hxx"
-#include "StdMeshers_Adaptive1D_i.hxx"
-#include "StdMeshers_Propagation_i.hxx"
+#include "StdMeshers_FixedPoints1D_i.hxx"
+#include "StdMeshers_Geometric1D_i.hxx"
+#include "StdMeshers_Hexa_3D_i.hxx"
+#include "StdMeshers_ImportSource1D_i.hxx"
+#include "StdMeshers_ImportSource2D_i.hxx"
+#include "StdMeshers_Import_1D2D_i.hxx"
+#include "StdMeshers_Import_1D_i.hxx"
+#include "StdMeshers_LayerDistribution2D_i.hxx"
+#include "StdMeshers_LayerDistribution_i.hxx"
 #include "StdMeshers_LengthFromEdges_i.hxx"
-#include "StdMeshers_QuadranglePreference_i.hxx"
-//#include "StdMeshers_TrianglePreference_i.hxx"
-#include "StdMeshers_QuadraticMesh_i.hxx"
+#include "StdMeshers_LocalLength_i.hxx"
 #include "StdMeshers_MaxElementArea_i.hxx"
 #include "StdMeshers_MaxElementVolume_i.hxx"
+#include "StdMeshers_MaxLength_i.hxx"
 #include "StdMeshers_NotConformAllowed_i.hxx"
-#include "StdMeshers_ProjectionSource3D_i.hxx"
-#include "StdMeshers_ProjectionSource2D_i.hxx"
-#include "StdMeshers_ProjectionSource1D_i.hxx"
-#include "StdMeshers_NumberOfLayers_i.hxx"
-#include "StdMeshers_LayerDistribution_i.hxx"
 #include "StdMeshers_NumberOfLayers2D_i.hxx"
-#include "StdMeshers_LayerDistribution2D_i.hxx"
-#include "StdMeshers_SegmentLengthAroundVertex_i.hxx"
-#include "StdMeshers_MaxLength_i.hxx"
+#include "StdMeshers_NumberOfLayers_i.hxx"
+#include "StdMeshers_NumberOfSegments_i.hxx"
+#include "StdMeshers_PolygonPerFace_2D_i.hxx"
+#include "StdMeshers_Prism_3D_i.hxx"
+#include "StdMeshers_ProjectionSource1D_i.hxx"
+#include "StdMeshers_ProjectionSource2D_i.hxx"
+#include "StdMeshers_ProjectionSource3D_i.hxx"
+#include "StdMeshers_Projection_1D_2D_3D_i.hxx"
+#include "StdMeshers_Propagation_i.hxx"
 #include "StdMeshers_QuadrangleParams_i.hxx"
-#include "StdMeshers_ImportSource1D_i.hxx"
-#include "StdMeshers_ImportSource2D_i.hxx"
-#include "StdMeshers_Cartesian_3D_i.hxx"
-
-#include "StdMeshers_Regular_1D_i.hxx"
-#ifdef ENABLE_MEFISTO
- #include "StdMeshers_MEFISTO_2D_i.hxx"
-#endif
+#include "StdMeshers_QuadranglePreference_i.hxx"
 #include "StdMeshers_Quadrangle_2D_i.hxx"
-#include "StdMeshers_Hexa_3D_i.hxx"
-#include "StdMeshers_Projection_1D_2D_3D_i.hxx"
-#include "StdMeshers_Prism_3D_i.hxx"
+#include "StdMeshers_QuadraticMesh_i.hxx"
+#include "StdMeshers_RadialQuadrangle_1D2D_i.hxx"
+#include "StdMeshers_Regular_1D_i.hxx"
 #include "StdMeshers_SegmentAroundVertex_0D_i.hxx"
-#include "StdMeshers_CompositeSegment_1D_i.hxx"
+#include "StdMeshers_SegmentLengthAroundVertex_i.hxx"
+#include "StdMeshers_StartEndLength_i.hxx"
 #include "StdMeshers_UseExisting_1D2D_i.hxx"
-#include "StdMeshers_RadialQuadrangle_1D2D_i.hxx"
-#include "StdMeshers_Import_1D_i.hxx"
-#include "StdMeshers_Import_1D2D_i.hxx"
-#include "StdMeshers_ViscousLayers_i.hxx"
 #include "StdMeshers_ViscousLayers2D_i.hxx"
-#include "StdMeshers_CartesianParameters3D_i.hxx"
+#include "StdMeshers_ViscousLayers_i.hxx"
+#ifdef ENABLE_MEFISTO
+ #include "StdMeshers_MEFISTO_2D_i.hxx"
+#endif
 
 namespace SMESH {
   class ApplicableToAny
   {
   public:
-    static CORBA::Boolean IsApplicable( const TopoDS_Shape &S, CORBA::Boolean toCheckAll ) {
+    static CORBA::Boolean IsApplicable( const TopoDS_Shape &S, CORBA::Boolean toCheckAll )
+    {
       return true;
     }
   };
 };
-template <class T, class TIsApplicable = SMESH::ApplicableToAny> class StdHypothesisCreator_i:public HypothesisCreator_i<T>
+template <class T, class TIsApplicable = SMESH::ApplicableToAny>
+class StdHypothesisCreator_i : public HypothesisCreator_i< T >
 {
 public:
   // as we have 'module StdMeshers' in SMESH_BasicHypothesis.idl
   virtual std::string GetModuleName() { return "StdMeshers"; }
-  virtual CORBA::Boolean IsApplicable( const TopoDS_Shape & S, CORBA::Boolean toCheckAll ) {
+  virtual CORBA::Boolean IsApplicable( const TopoDS_Shape & S, CORBA::Boolean toCheckAll )
+  {
     return TIsApplicable::IsApplicable( S, toCheckAll );
   }
 };
@@ -217,7 +219,7 @@ STDMESHERS_I_EXPORT
     else if (strcmp(aHypName, "Quadrangle_2D") == 0)
       aCreator = new StdHypothesisCreator_i<StdMeshers_Quadrangle_2D_i, StdMeshers_Quadrangle_2D_i>;
     else if (strcmp(aHypName, "QuadFromMedialAxis_1D2D") == 0)
-      aCreator = new StdHypothesisCreator_i<StdMeshers_QuadFromMedialAxis_1D2D_i, StdMeshers_Quadrangle_2D_i>;
+      aCreator = new StdHypothesisCreator_i<StdMeshers_QuadFromMedialAxis_1D2D_i, StdMeshers_QuadFromMedialAxis_1D2D_i>;
     else if (strcmp(aHypName, "Hexa_3D") == 0)
       aCreator = new StdHypothesisCreator_i<StdMeshers_Hexa_3D_i, StdMeshers_Hexa_3D_i>;
     else if (strcmp(aHypName, "Projection_1D") == 0)
@@ -248,6 +250,8 @@ STDMESHERS_I_EXPORT
       aCreator = new StdHypothesisCreator_i<StdMeshers_Import_1D2D_i>;
     else if (strcmp(aHypName, "Cartesian_3D") == 0)
       aCreator = new StdHypothesisCreator_i<StdMeshers_Cartesian_3D_i>;
+    else if (strcmp(aHypName, "PolygonPerFace_2D") == 0)
+      aCreator = new StdHypothesisCreator_i<StdMeshers_PolygonPerFace_2D_i>;
     else ;
 
     return aCreator;
index b5a4e088e0fb342a08c7455b4854789d1f11b096..379e593d5a892dc2976b8eee896afaf9b292ff28 100644 (file)
@@ -415,7 +415,7 @@ CORBA::Long MeshJobManager_i::initialize(const MESHJOB::MeshJobParameterList & m
   jobParameters->out_files[0] = CORBA::string_dup(outputfile_name.c_str());
 
   // CAUTION: the maximum duration has to be set with a format like "hh:mm"
-  jobParameters->maximum_duration = CORBA::string_dup("01:00");
+  //jobParameters->maximum_duration = CORBA::string_dup("01:00");
   jobParameters->queue = CORBA::string_dup("");
 
   // Setting resource and additionnal properties (if needed)
index 8ed4d5a5951827eef114d43a3c613e2639f56d98..180dfe3cc2a27f661b55e5e92802184546e0a68e 100644 (file)
@@ -50,7 +50,7 @@ all_states = run_states+end_states;
 # The SALOME launcher resource is specified by its name as defined in
 # the file CatalogResources.xml (see root directory of the
 # application). We could have a check box in the dialog to specify
-# wether we want a local execution or a remote one.
+# whether we want a local execution or a remote one.
 resource_name = "localhost"
 from salome.smesh.spadder.configreader import ConfigReader