Salome HOME
Merge remote branch 'origin/V7_4_BR'
authorvsr <vsr@opencascade.com>
Thu, 28 Aug 2014 09:21:01 +0000 (13:21 +0400)
committervsr <vsr@opencascade.com>
Thu, 28 Aug 2014 09:21:01 +0000 (13:21 +0400)
127 files changed:
doc/salome/examples/transforming_meshes_ex13.py
doc/salome/gui/SMESH/images/analyticdensity.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/createmesh-inv.png
doc/salome/gui/SMESH/images/createmesh-inv2.png [changed mode: 0755->0644]
doc/salome/gui/SMESH/images/createmesh-inv3.png [changed mode: 0755->0644]
doc/salome/gui/SMESH/images/distributionwithanalyticdensity.png [changed mode: 0755->0644]
doc/salome/gui/SMESH/images/distributionwithtabledensity.png [changed mode: 0755->0644]
doc/salome/gui/SMESH/images/duplicate04.png
doc/salome/gui/SMESH/images/image10.jpg [changed mode: 0755->0644]
doc/salome/gui/SMESH/images/reorient_2d_face.png
doc/salome/gui/SMESH/images/reorient_2d_point.png
doc/salome/gui/SMESH/images/reorient_2d_volume.png [new file with mode: 0644]
doc/salome/gui/SMESH/input/1d_meshing_hypo.doc
doc/salome/gui/SMESH/input/additional_hypo.doc
doc/salome/gui/SMESH/input/constructing_meshes.doc
doc/salome/gui/SMESH/input/constructing_submeshes.doc
doc/salome/gui/SMESH/input/creating_groups.doc
doc/salome/gui/SMESH/input/double_nodes_page.doc
doc/salome/gui/SMESH/input/editing_meshes.doc
doc/salome/gui/SMESH/input/modifying_meshes.doc
doc/salome/gui/SMESH/input/reorient_faces.doc
doc/salome/gui/SMESH/input/tui_transforming_meshes.doc
idl/SMESH_Gen.idl
idl/SMESH_Mesh.idl
idl/SMESH_MeshEditor.idl
resources/CMakeLists.txt
resources/SalomeApp.xml.in
resources/mesh_minus.png [new file with mode: 0644]
resources/mesh_plus.png [new file with mode: 0644]
resources/reorient_faces_volume.png [new file with mode: 0644]
src/Driver/CMakeLists.txt
src/DriverCGNS/DriverCGNS_Read.cxx
src/DriverMED/DriverMED_Family.cxx
src/DriverMED/DriverMED_Family.h
src/DriverMED/DriverMED_W_SMESHDS_Mesh.cxx
src/DriverMED/DriverMED_W_SMESHDS_Mesh.h
src/DriverUNV/UNV2411_Structure.cxx
src/SMDS/SMDS_Mesh.cxx
src/SMDS/SMDS_Mesh.hxx
src/SMESH/SMESH_Algo.cxx
src/SMESH/SMESH_Algo.hxx
src/SMESH/SMESH_Gen.cxx
src/SMESH/SMESH_Gen.hxx
src/SMESH/SMESH_HypoFilter.cxx
src/SMESH/SMESH_HypoFilter.hxx
src/SMESH/SMESH_Hypothesis.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_Pattern.hxx
src/SMESH/SMESH_subMesh.cxx
src/SMESH/SMESH_subMesh.hxx
src/SMESHDS/SMESHDS_Hypothesis.cxx
src/SMESHDS/SMESHDS_Hypothesis.hxx
src/SMESHDS/SMESHDS_Mesh.cxx
src/SMESHDS/SMESHDS_Mesh.hxx
src/SMESHDS/SMESHDS_TSubMeshHolder.hxx [new file with mode: 0644]
src/SMESHGUI/CMakeLists.txt
src/SMESHGUI/SMESHGUI.cxx
src/SMESHGUI/SMESHGUI_ComputeDlg.cxx
src/SMESHGUI/SMESHGUI_DuplicateNodesDlg.cxx
src/SMESHGUI/SMESHGUI_FilterDlg.cxx
src/SMESHGUI/SMESHGUI_FilterDlg.h
src/SMESHGUI/SMESHGUI_GEOMGenUtils.cxx
src/SMESHGUI/SMESHGUI_GEOMGenUtils.h
src/SMESHGUI/SMESHGUI_GroupDlg.cxx
src/SMESHGUI/SMESHGUI_GroupUtils.cxx
src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx
src/SMESHGUI/SMESHGUI_MeshDlg.cxx
src/SMESHGUI/SMESHGUI_MeshDlg.h
src/SMESHGUI/SMESHGUI_MeshOp.cxx
src/SMESHGUI/SMESHGUI_MeshOp.h
src/SMESHGUI/SMESHGUI_Operations.h [new file with mode: 0644]
src/SMESHGUI/SMESHGUI_ReorientFacesDlg.cxx
src/SMESHGUI/SMESHGUI_ReorientFacesDlg.h
src/SMESHGUI/SMESHGUI_Utils.h
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/SMESH_Block.cxx
src/SMESHUtils/SMESH_ComputeError.hxx
src/SMESHUtils/SMESH_TryCatch.cxx
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_Gen_i.cxx
src/SMESH_I/SMESH_Gen_i.hxx
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_SWIG/StdMeshersBuilder.py
src/SMESH_SWIG/smeshBuilder.py
src/SMESH_SWIG/smesh_algorithm.py
src/StdMeshers/StdMeshers_Adaptive1D.cxx
src/StdMeshers/StdMeshers_Cartesian_3D.cxx
src/StdMeshers/StdMeshers_FaceSide.cxx
src/StdMeshers/StdMeshers_FaceSide.hxx
src/StdMeshers/StdMeshers_Hexa_3D.cxx
src/StdMeshers/StdMeshers_Import_1D.cxx
src/StdMeshers/StdMeshers_MEFISTO_2D.cxx
src/StdMeshers/StdMeshers_Prism_3D.cxx
src/StdMeshers/StdMeshers_ProjectionUtils.cxx
src/StdMeshers/StdMeshers_Projection_2D.cxx
src/StdMeshers/StdMeshers_Propagation.cxx
src/StdMeshers/StdMeshers_Propagation.hxx
src/StdMeshers/StdMeshers_QuadToTriaAdaptor.cxx
src/StdMeshers/StdMeshers_Quadrangle_2D.cxx
src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.cxx
src/StdMeshers/StdMeshers_Regular_1D.cxx
src/StdMeshers/StdMeshers_ViscousLayers.cxx
src/StdMeshers/StdMeshers_ViscousLayers.hxx
src/StdMeshers/StdMeshers_ViscousLayers2D.cxx
src/StdMeshers/StdMeshers_ViscousLayers2D.hxx
src/StdMeshersGUI/StdMeshersGUI_CartesianParamCreator.cxx
src/StdMeshersGUI/StdMeshersGUI_ObjectReferenceParamWdg.cxx
src/StdMeshersGUI/StdMeshersGUI_StdHypothesisCreator.cxx
src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.cxx
src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.h
src/StdMeshersGUI/StdMeshers_msg_en.ts

index fb56273bafecde0ab53efc1490c172c801868849..37a3f5eed20b01b3dbb18da1b46a60dc3fc56a83 100644 (file)
@@ -1,4 +1,4 @@
-# Reorient faces by vector
+# Reorient faces
 
 
 import salome
@@ -52,3 +52,20 @@ mesh.Reorient2D( group, smesh.MakeDirStruct( -10, 1, 10 ), [0,0,0])
 #
 # FaceOrPoint - a SMESH.PointStruct structure
 mesh.Reorient2D( localAlgo.GetSubMesh().GetIDs(), [10,1,0], SMESH.PointStruct(0,0,0))
+
+
+# Use Reorient2DBy3D() to orient faces of 2 geom faces to have their normal pointing inside volumes
+
+mesh3D = smesh.Mesh( box, '3D mesh')
+mesh3D.AutomaticHexahedralization(0.5)
+group0 = mesh3D.Group( faces[0] )
+group1 = mesh3D.Group( faces[1] )
+
+# pass group0 and ids of faces of group1 to inverse
+nbRev = mesh3D.Reorient2DBy3D([ group0, group1.GetIDs() ], mesh3D, theOutsideNormal=False)
+print "Nb reoriented faces:", nbRev
+
+# orient the reversed faces back
+nbRev = mesh3D.Reorient2DBy3D( mesh3D, mesh3D, theOutsideNormal=True)
+print "Nb re-reoriented faces:", nbRev
+
diff --git a/doc/salome/gui/SMESH/images/analyticdensity.png b/doc/salome/gui/SMESH/images/analyticdensity.png
new file mode 100644 (file)
index 0000000..b1c9972
Binary files /dev/null and b/doc/salome/gui/SMESH/images/analyticdensity.png differ
index 2180d416a6d84a76954fcfe8b660b3990f4fc2de..d17ce5373d7e1cd6664f189baee5e975de700a0d 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/createmesh-inv.png and b/doc/salome/gui/SMESH/images/createmesh-inv.png differ
old mode 100755 (executable)
new mode 100644 (file)
index 2b6bede..30e6248
Binary files a/doc/salome/gui/SMESH/images/createmesh-inv2.png and b/doc/salome/gui/SMESH/images/createmesh-inv2.png differ
old mode 100755 (executable)
new mode 100644 (file)
index 96fed7d..f53ab0a
Binary files a/doc/salome/gui/SMESH/images/createmesh-inv3.png and b/doc/salome/gui/SMESH/images/createmesh-inv3.png differ
old mode 100755 (executable)
new mode 100644 (file)
index 83c086b..170428d
Binary files a/doc/salome/gui/SMESH/images/distributionwithanalyticdensity.png and b/doc/salome/gui/SMESH/images/distributionwithanalyticdensity.png differ
old mode 100755 (executable)
new mode 100644 (file)
index 60847cd..5fa982c
Binary files a/doc/salome/gui/SMESH/images/distributionwithtabledensity.png and b/doc/salome/gui/SMESH/images/distributionwithtabledensity.png differ
index 70cb4adfba7946199525fd6dc653770f74bdaefa..eab51a1fb8c3e03a8e82a9428e9433552a93bb52 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/duplicate04.png and b/doc/salome/gui/SMESH/images/duplicate04.png differ
old mode 100755 (executable)
new mode 100644 (file)
index a53ea0b..c52d80c
Binary files a/doc/salome/gui/SMESH/images/image10.jpg and b/doc/salome/gui/SMESH/images/image10.jpg differ
index b143ac4ebad635b8cf76bca63c524afa7a0b8cd9..0407fafed71f8a89b63d6fa2f20add9b8c6b435c 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/reorient_2d_face.png and b/doc/salome/gui/SMESH/images/reorient_2d_face.png differ
index 844ac09ef384e2f13fd71cf4acc5c6f207ae7b8f..8440c9137db18c979f581b97606e7f27e26b62aa 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/reorient_2d_point.png and b/doc/salome/gui/SMESH/images/reorient_2d_point.png differ
diff --git a/doc/salome/gui/SMESH/images/reorient_2d_volume.png b/doc/salome/gui/SMESH/images/reorient_2d_volume.png
new file mode 100644 (file)
index 0000000..1d04de0
Binary files /dev/null and b/doc/salome/gui/SMESH/images/reorient_2d_volume.png differ
index 1228865f7a643638333442e018cd0ee2646eeba1..7a9228b68497eb5bfd97e9677b94ce5d68387799 100644 (file)
@@ -183,28 +183,48 @@ You can set the type of distribution for this hypothesis in the
 <br><b>Equidistant Distribution</b> - all segments will have the same
 length, you define only the <b>Number of Segments</b>.
 
-<br><b>Scale Distribution</b> - length of segments gradually changes depending on the <b>Scale Factor</b>, which is a ratio of the first segment length to the last segment length.
+<br><b>Scale Distribution</b> - length of segments gradually changes
+depending on the <b>Scale Factor</b>, which is a ratio of the first
+segment length to the last segment length.<br>
+Length of segments changes in geometric progression with the common
+ratio (A) depending on the <b>Scale Factor</b> (S) and <b>Number of
+Segments</b> (N) as follows: <code> A = S**(1/(N-1))</code>. For an
+edge of length L, length of the first segment is 
+<code>L * (1 - A)/(1 - A**N)</code>.
 
-\image html a-nbsegments2.png
-
-<br><b>Distribution with Table Density</b> - you input a number of
-pairs <b>t - F(t)</b>, where \b t ranges from 0 to 1,  and the module computes the
-formula, which will rule the change of length of segments and shows
-the curve in the plot. You can select the <b>Conversion mode</b> from
-\b Exponent and <b>Cut negative</b>.
 
-\image html distributionwithtabledensity.png
+\image html a-nbsegments2.png
 
 <br><b>Distribution with Analytic Density</b> - you input the formula,
 which will rule the change of length of segments and the module shows
-the curve in the plot.
+in the plot the density function curve in red and the node
+distribution as blue crosses.
 
 \image html distributionwithanalyticdensity.png
 
+<br>
+\anchor analyticdensity_anchor
+The node distribution is computed so that to have the density function
+integral on the range between two nodes equal for all segments.
+\image html analyticdensity.png
+
+<br><b>Distribution with Table Density</b> - you input a number of
+pairs <b>t - F(t)</b>, where \b t ranges from 0 to 1, and the module computes the
+formula, which will rule the change of length of segments and shows
+in the plot the density function curve in red and the node
+distribution as blue crosses. The node distribution is computed the
+same way as for 
+\ref analyticdensity_anchor "Distribution with Analytic Density". You
+can select the <b>Conversion mode</b> from\b Exponent and <b>Cut
+negative</b>. 
+
+\image html distributionwithtabledensity.png
+
 <b>See Also</b> a sample TUI Script of a 
 \ref tui_deflection_1d "Defining Number of Segments" hypothesis
 operation.
 
+
 <br>
 \anchor start_and_end_length_anchor
 <h2>Start and End Length hypothesis</h2>
index adccc49aadb51367b2a0bf94d3e4e0c797045cd1..5c5c204eff554dfaa4fffab44bf22c2c308a53fa 100644 (file)
@@ -93,7 +93,7 @@ computations.
   and edges, just hide the mesh to avoid this. 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
-  preview chunk size" preference (in Preferences/Mesh/General tab).<br>
+  preview chunk size" preference (in Preferences/Mesh/General tab).
 
   If faces/edges without layers are specified, the element layers are
   not constructed on geometrical faces shared by several solids in 3D
@@ -106,6 +106,15 @@ computations.
   possibly being internal faces/edges within the whole model.
   \image html viscous_layers_on_submesh.png 2D viscous layers constructed on boundary edges of a sub-mesh on a disk face.
 
+  If you use \b several hypotheses to define viscous layers on faces of
+  one solid, keep in mind the following. Each hypothesis defines a set
+  of faces with viscous layers (even if you specify faces without
+  layers). The sets of faces with viscous layers defined by several
+  hypotheses should not intersect, else the module won't add an
+  hypothesis that is incompatible with another one. <br>
+  Also you can't define different number of layers on adjacent faces
+  of a solid.<br>
+  This logic is also valid for the 2D hypothesis.
 </li>
 </ul>
 
index b4aa75ecb02e1b8f60a07d4e1e92d894763d4a45..232d4f524b006770d80f347e7900bf98699d3e74 100644 (file)
     \image html createmesh-inv.png
     <br>
   </li>
-  <li>Select <b>Mesh Type</b> in the corresponding list from <b>Any, Hexahedral, Tetrahedral, Triangular </b> and \b Quadrilateral (there can be less items for lower dimensions). 
-  
-  Selection of a mesh type hides any algorithms that are not able to create elements of this type.</li>
-  
+  <li> To filter off irrelevant meshing algorithms, you can
+    select <b>Mesh Type</b> in the corresponding list from <b>Any,
+      Hexahedral, Tetrahedral, Triangular </b> and \b Quadrilateral (there
+    can be less items for the geometry of lower dimensions).
+
+    Selection of a mesh type hides all meshing algorithms that can not
+    generate elements of this type.</li>
+
   <li>Apply \subpage basic_meshing_algos_page "meshing algorithms" and
     \subpage about_hypo_page "hypotheses" which will be used to compute
     this mesh.
@@ -42,7 +46,8 @@
     dimension of the CAD model (geometry) the algorithms listed on
     this page affect and the maximal dimension of elements the algorithms
     generate. For example, \b 3D page lists the algorithms that affect
-    3D geometrical objects (solids).
+    3D geometrical objects (solids) and generate 3D mesh elements
+    (tetrahedra, hexahedra etc.)
 
     \note
     - Some page(s) can be disabled if the source geometrical
@@ -65,7 +70,6 @@
     it is "Mesh_1". Then select the geometrical object you wish to
     mesh in the Object Browser and click "Select" button near \b Geometry
     field (if the name of the object has not yet appeared in \b Geometry field).
-
     <center>
     \image html image120.png
     <em>"Select" button</em>
     Now you can define 3D Algorithm and 3D Hypotheses, which will be
     applied to the solids of your geometrical object. Click the <em>"Add
       Hypothesis"</em>  button to add a hypothesis.
-
     <center>
     \image html image121.png
     <em>"Add Hypothesis" button</em>
     </center>
+    Click the <em>"Plus"</em> button to enable adding more additional hypotheses.
 
     Click the <em>"Edit Hypothesis"</em> button to change the values for the
     current hypothesis.
-
     <center>
     \image html image122.png
     <em>"Edit Hypothesis" button</em>
     </center>
 
-    Most 2D and 3D algorithms can work without hypotheses using default meshing parameters. Some algorithms do not require any hypotheses. After selection of an algorithm "Hypothesis" field of
+    Most 2D and 3D algorithms can work without hypotheses using
+    default meshing parameters. Some algorithms do not require any
+    hypotheses. After selection of an algorithm "Hypothesis" field of
     the dialog can contain:
     <ul>
       <li> <em>\<Default\></em> if the algorithm can work using default
     that any object has edges, even if their existence is not
     apparent, for example, a sphere has 4 edges). Note that the
     choice of hypotheses and lower dimension algorithms depends on
-    the higher dimension algorithm. 
+    the higher dimension algorithm.
+
+    If you wish you can select different algorithms and/or hypotheses
+    for meshing some parts of your CAD model by \ref constructing_submeshes_page.
 
     Some algorithms generate mesh of several dimensions, while others
     produce mesh of only one dimension. In the latter case there must
 
     It contains: 
     <ul>
+      <li>a mesh name (<em>Mesh_mechanic</em>);
       <li>a reference to the geometrical object on the basis of
-        which the mesh has been constructed;</li> 
+        which the mesh has been constructed (\a mechanic);</li> 
       <li><b>Applied hypotheses</b> folder containing the references
         to the hypotheses applied at the construction of the mesh;</li>
       <li><b>Applied algorithms</b> folder containing the references
index 917fd5f65e434515d46350c874b401e55705569d..230903449a5119b44b678cb47e447181b7ac8e37 100644 (file)
@@ -2,7 +2,7 @@
 
 \page constructing_submeshes_page Constructing sub-meshes
 
-Sub-mesh is a mesh on a geometrical sub-object created with algorithms
+Sub-mesh is a mesh on a geometrical sub-object created with meshing algorithms
 and/or hypotheses other than the algorithms and hypotheses assigned to
 the parent mesh on the parent geometrical object.
 
@@ -52,7 +52,7 @@ The following dialog box will appear:
 \par
 It allows to define the \b Name, the parent \b Mesh and the \b
 Geometry (e.g. a face if the parent mesh has been built on box) of the
-sub-mesh. You can define algorithms and hypotheses in the same way as
+sub-mesh. You can select meshing algorithms and hypotheses in the same way as
 in \ref constructing_meshes_page "Create mesh" menu.
 
 \par
@@ -93,11 +93,13 @@ displayed as follows:
 \par
 It contains:
 <ul>
-<li>a reference to the geometrical object on the basis of which the sub-mesh has been constructed;</li>
+<li>a sub-mesh name (\a SubMeshFace1)
+<li>a reference to the geometrical object on the basis of which the
+  sub-mesh has been constructed (<em>Cylindrical Face_1</em>);</li>
 <li><b>Applied hypotheses</b> folder containing the references to the
-hypotheses applied to the construction of the sub-mesh;</li>
+hypotheses selected at the construction of the sub-mesh;</li>
 <li><b>Applied algorithms</b> folder containing the references to the
-algorithms applied to the construction of the sub-mesh.</li>
+algorithms selected at the construction of the sub-mesh.</li>
 </ul>
 
 <br><b>See Also</b> a sample TUI Script of a 
index 95adb865585d0c07851f94fb19298d08bb290682..5dda220d1e343f2bbbe8492bfe96d8eb8db0c256 100644 (file)
@@ -40,31 +40,26 @@ the following ways:
   mesh. For this, turn on the <b>Select All</b> check box. In this mode
   all controls, which allow selecting the entities in other ways, are
   disabled.</li>
-<li>By applying the Filter. The <b>Set filter</b> button allows to
-  define the filter for selection of the elements for your group. See more
-  about filters on the 
-  \ref selection_filter_library_page "Selection filter library" page.<br>
-  If the <b>Enable manual edition</b> check box is turned off, the 
-  filter entirely defines the group contents. In this mode, the filter is
-  applied to all elements of the mesh. If there are no entities
-  corresponding to the filter, the \b Apply button is disabled.<br>
-  If the <b>Enable manual edition</b> check box is turned on, the defined
-  filter can be used to for selection of entities for the group.</li>
 <li>By choosing entities manually with the mouse in the 3D Viewer. For
   this, turn on the <b>Enable manual edition</b> check box. You can
   click on an element in the 3D viewer and it will be highlighted. After
   that click the \b Add button and the ID of this element will be
-  added to the list.</li>
-<li>By adding entities from either a submesh or an existing
+  added to the list.<br>
+  The <b>Set filter</b> button allows to define the filter for
+  selection of the elements for your group. See more about filters on
+  the \ref selection_filter_library_page "Selection filter library"
+  page.</li> 
+<li>By adding entities from either a sub-mesh or an existing
   group.  For this, turn on the <b>Enable manual edition</b> check
-  box. <b>Select from</b> set of fields allows to select a submesh or
+  box. <b>Select from</b> set of fields allows to select a sub-mesh or
   a group of the appropriate type.</li>
 </ul>
 In the <b>manual edition</b> mode you can
 <ul>
-<li>click the \b Remove button to remove the selected elements from the list</li>
+<li>click the \b Remove button to remove the selected list items from
+  the list.</li>
 <li>click the <b>Sort List</b> button to sort the list of IDs of 
-mesh elements.</li>
+  mesh elements.</li>
 </ul>
 
 \image html creategroup.png
index ce643d32680cab3d465471b0b66aa2dc9f717913..dcdc6f491833d20c7816db4c08607ab095d53770 100644 (file)
@@ -130,25 +130,27 @@ This mode duplicates nodes located on boundaries between given groups of volumes
 
 Parameters to be defined in this mode:
 <ul>
-  <li><b>Groups of volumes</b> (<em>mandatory</em>): list of volume
+  <li><b>Groups (faces or volumes) </b> (<em>mandatory</em>): list of mesh
     groups. These groups should be disjoint, i.e. should not have shared
-    volumes.</li>
+    elements.</li>
   <li> If <b>Create joint elements</b> option is activated, flat
     elements are created on the duplicated nodes: a triangular facet
     shared by two volumes of two groups generates a flat prism, a
-    quadrangular facet generates a flat hexahedron.
+    quadrangular facet generates a flat hexahedron. 
+    Correspondingly 2D joint elements (null area faces) are generated
+    where edges are shared by two faces.
     <br>
-    The created flat volumes are stored in groups. These groups are named
+    The created flat volumes (or faces) are stored in groups. These groups are named
     according to the position of the group in the list of groups: group
     "j_n_p" is a group of flat elements that are built between the group \#n
     and the group \#p in the group list. All the flat elements are gathered
-    into the group named "joints3D". The flat element of the multiple
+    into the group named "joints3D" (correspondingly "joints2D"). The flat element of the multiple
     junctions between the simple junction are stored in a group named
     "jointsMultiples".</li>
-  <li> If <b>On all boundaries</b> option is activated, the volumes,
-    which are not included into <b>Groups of volumes</b>, are considered
+  <li> If <b>On all boundaries</b> option is activated, the volumes (or faces),
+    which are not included into <b>Groups</b> input, are considered
     as another group and thus the nodes on the boundary
-    between <b>Groups of volumes</b> and the remaining mesh are also
+    between <b>Groups</b> and the remaining mesh are also
     duplicated.</li>
 </ul>
 
index 62685e557199f1d49fd4d44cbfc7d2181949dde1..4cc70553fe34336561b80b37fd85f2a9704e67e3 100644 (file)
@@ -2,11 +2,11 @@
 
 \page editing_meshes_page Editing Meshes
 
-\n After you have created a mesh or submesh with definite applied
-hypotheses and algorithms you can edit your mesh by \b assigning new
-hypotheses and algorithms or \b unassigning the applied hypotheses and
-algorithms. The editing proceeds in the same way as <b>Mesh
-Creation</b>.
+\n After you have created a mesh or sub-mesh with definite applied
+meshing algorithms and hypotheses you can edit your mesh by \b assigning other
+algorithms and/or hypotheses or \b unassigning the applied hypotheses and
+algorithms. The editing proceeds in the same way as 
+\ref create_mesh_anchor "Mesh Creation".
 
 \image html createmesh-inv3.png
 
@@ -26,4 +26,4 @@ changes if we apply different algorithms to it.
 <br><b>See Also</b> a sample TUI Script of an 
 \ref tui_editing_mesh "Edit Mesh" operation.  
 
-*/
\ No newline at end of file
+*/
index 8a4f0e5ba2072f50e565f6cb1ab61ceeb43b112a..9006ddcd0415495135211859ce5f41bc773472eb 100755 (executable)
@@ -36,7 +36,7 @@ with consequent transformation of all adjacent elements and edges.</li>
 <li>\subpage uniting_set_of_triangles_page "Unite several adjacent triangles".</li>
 <li>\subpage changing_orientation_of_elements_page "Change orientation"
  of the selected elements.</li>
-<li>\subpage reorient_faces_page "Reorient faces by vector".</li>
+<li>\subpage reorient_faces_page "Reorient faces".</li>
 <li>\subpage cutting_quadrangles_page "Cut a quadrangle" into two triangles.</li>
 <li>\subpage split_to_tetra_page "Split" volumic elements into tetrahedra or prisms.</li>
 <li>\subpage smoothing_page "Smooth" elements, reducung distortions in
index db408ef0878332e3ef8a470def7e36eb49f443a6..519da7ef11e5a7160fd1effb8cb59f26bf2cfc0a 100644 (file)
@@ -1,49 +1,66 @@
 /*!
 
-\page reorient_faces_page Reorient faces by vector
+\page reorient_faces_page Reorient faces
 
-\n This operation allows changing orientation of a set of neighboring
-faces. The desired orientation is defined by a vector. Since the direction
-of face normals in the set can be even opposite, it is necessary to
-specify a control face whose normal will be compared with the vector. This
-face can be either specified explicitly or found by proximity to
-a given point.
+\n This operation allows changing orientation of faces two ways.
+<ol>
+<li> To reorient a set of neighboring faces by defining the desired
+  orientation by a vector. <br> Since the direction of face normals in
+  the set can be even opposite, it is necessary to specify a control
+  face whose normal will be compared with the vector. This face can be
+  either <ul>
+    <li> found by proximity to a given point or </li> 
+    <li> specified explicitly. </li> 
+</ul> </li>
+<li> To reorient faces with relation to adjacent volumes. </li>
+</ol>
 
 Orientation of a face is changed by reverting the order of its nodes.
 
 <em>To change orientation of faces:</em>
 <ol>
-<li>In the \b Modification menu select <b>Reorient faces by
-    vector</b> item or click <em>Reorient faces by
-    vector</em> button in the toolbar.
+<li>In the \b Modification menu select <b>Reorient faces</b>
+  item or click <em>Reorient faces</em> button in the toolbar.
 
 <center>
 \image html reorient_faces_face.png
-<em>"Reorient faces by vector" button</em>
+<em>"Reorient faces" button</em>
 </center>
 
 The following dialog box will appear:
 
 <center>
-\image html reorient_2d_point.png
-\image html reorient_2d_face.png
+\image html reorient_2d_point.png "First mode: to reorient adjacent faces according to a vector. The control face is found by point."
+<br>
+\image html reorient_2d_face.png "Second mode: to reorient adjacent faces according to a vector. The control face is explicitly given."
+<br>
+\image html reorient_2d_volume.png "Third mode: to reorient faces with relation to adjacent volumes."
 </center>
 
 <li>In this dialog
 <ul>
-<li>Specify the way of selection of the control face: by point or
-  explicitly.</li>
-<li>Select the \b Object (mesh, sub-mesh or a group of faces) containing faces to reorient in the Object Browser or in the 3D Viewer.</li>
-<li>Specify the coordinates of the \b Point by which the control face
-  will be found or of the control \b Face itself. You can easy specify the \b
-  Point by either picking a node in the 3D Viewer or selecting a vertex
-  in the Object Browser. It is possible to pick the  \b Face by mouse in
-  the 3D Viewer or enter its ID.</li>
-<li>Set up the \b Direction vector to be compared with the normal of the
-  control face. If you pick a node in the 3D Viewer then the \b Direction
-  vector will go from the coordinate system origin to the selected node.
-  If you pick two nodes (holding Shift button) then the \b Direction vector
-  will go from the first to the second node.</li>
+<li>Specify either of the tree operation modes.</li>
+<li>Select the \b Object (mesh, sub-mesh or group)
+  containing faces to reorient, in the Object Browser or in the 3D
+  Viewer.</li>
+<li>To reorient according to vector: <ul>
+    <li>Specify the coordinates of the \b Point by which the control face
+      will be found or the control \b Face itself. You can easy specify the \b
+      Point by either picking a node in the 3D Viewer or selecting a vertex
+      in the Object Browser. It is possible to pick the \b Face by mouse in
+      the 3D Viewer or enter its ID.</li>
+    <li>Set up the \b Direction vector to be compared with the normal of the
+      control face. If you pick a node in the 3D Viewer then the \b Direction
+      vector will go from the coordinate system origin to the selected node.
+      If you pick two nodes (holding Shift button) then the \b Direction vector
+      will go from the first to the second node.</li> </ul> </li>
+<li>To reorient according to volumes: <ul>
+    <li>Select an object (mesh, sub-mesh or group) containing
+      reference \b Volumes, in the Object Browser or in the 3D
+      Viewer.</li>
+    <li>Specify whether face normals should point outside or inside
+      the reference volumes using <b>Face normal outside volume</b>
+      check-box.</li></ul> </li>
 </ul>
 </li>
 
@@ -51,6 +68,6 @@ The following dialog box will appear:
 </ol>
 
 <br><b>See Also</b> a sample TUI Script of a
-\ref tui_reorient_faces "Reorient faces by vector" operation. 
+\ref tui_reorient_faces "Reorient faces" operation. 
 
 */
index d3ad4de47db317e10870302aeb4220b943532fdf..86ce3dca0b9ca759794874332e655494097893c8 100644 (file)
@@ -68,7 +68,7 @@
 
 <br>
 \anchor tui_reorient_faces
-<h3>Reorient faces by vector</h3>
+<h3>Reorient faces</h3>
 \tui_script{transforming_meshes_ex13.py}
 
 */
index 052423ae1acc143206847c8987ea59c3e2adbd0a..cb625d0b9da1fce14b190787a89b2e940f1404d0 100644 (file)
@@ -173,6 +173,17 @@ module SMESH
                                                    in boolean           byMesh)
       raises ( SALOME::SALOME_Exception );
 
+    /*!
+     * Returns \c True if a hypothesis is assigned to a sole sub-mesh in a current Study
+     *  \param [in] theHyp - the hypothesis of interest
+     *  \param [out] theMesh - the sole mesh using \a theHyp
+     *  \param [out] theShape - the sole geometry \a theHyp is assigned to
+     *  \return boolean - \c True if \a theMesh and \a theShape are sole using \a theHyp
+     */
+    boolean GetSoleSubMeshUsingHyp( in SMESH_Hypothesis   theHyp,
+                                    out SMESH_Mesh        theMesh,
+                                    out GEOM::GEOM_Object theShape);
+
     /*!
      * Sets number of segments per diagonal of boundary box of geometry by which
      * default segment length of appropriate 1D hypotheses is defined
@@ -363,7 +374,7 @@ module SMESH
       raises ( SALOME::SALOME_Exception );
 
     /*!
-     * Return indeces of faces, edges and vertices of given sub-shapes
+     * Return indices of faces, edges and vertices of given sub-shapes
      * within theMainObject
      */
     long_array GetSubShapesId( in GEOM::GEOM_Object theMainObject,
@@ -407,18 +418,22 @@ module SMESH
 
     /*!
      * \brief Moves objects to the specified position
+     *  \param what objects being moved
+     *  \param where parent object where objects are moved to
+     *  \param row position in the parent object's children list at which objects are moved
      *
      * This function is used in the drag-n-drop functionality.
-     *
-     * \param what objects being moved
-     * \param where parent object where objects are moved to
-     * \param row position in the parent object's children list at which objects are moved
      */
-    void Move( in sobject_list what, 
-              in SALOMEDS::SObject where, 
+    void Move( in sobject_list what,
+              in SALOMEDS::SObject where,
               in long row );
     /*!
-     * Return true if algorithm can be applied
+     * Returns true if algorithm can be used to mesh a given geometry
+     *  \param theAlgoType - the algorithm type
+     *  \param theLibName - a name of the Plug-in library implementing the algorithm
+     *  \param theShapeObject - the geometry to mesh
+     *  \param toCheckAll - if \c True, returns \c True if all shapes are meshable,
+     *         else, returns \c True if at least one shape is meshable
      */
     boolean IsApplicable( in string             theAlgoType,
                           in string             theLibName,
index 059170dcb2864ac2ee8f23daa6bdeaa358755b77..593272ab041154ef960366d3ce0ec1811e91858a 100644 (file)
@@ -88,19 +88,19 @@ module SMESH
   typedef sequence<log_block> log_array;
 
   struct PointStruct { double x;
-                      double y;
-                      double z; } ;
+                       double y;
+                       double z; } ;
 
   typedef sequence<PointStruct> nodes_array;
 
   struct DirStruct   { PointStruct PS ; } ;          // analog to OCCT gp_Vec
 
   struct AxisStruct  { double x;
-                      double y;
-                      double z;
-                      double vx;
-                      double vy;
-                      double vz; } ;
+                       double y;
+                       double z;
+                       double vx;
+                       double vy;
+                       double vz; } ;
   /*!
    * Node location on a shape
    */
@@ -215,7 +215,8 @@ module SMESH
     HYP_BAD_DIM,      // bad dimension
     HYP_BAD_SUBSHAPE, // shape is neither the main one, nor its sub-shape, nor a group
     HYP_BAD_GEOMETRY, // geometry mismatches algorithm's expectation
-    HYP_NEED_SHAPE    // algorithm can work on shape only
+    HYP_NEED_SHAPE,   // algorithm can work on shape only
+    HYP_INCOMPAT_HYPS // several additional hypotheses are incompatible one with other
   };
 
   /*!
@@ -389,7 +390,7 @@ module SMESH
      * Create a group
      */
     SMESH_Group CreateGroup( in ElementType elem_type,
-                            in string      name )
+                             in string      name )
       raises (SALOME::SALOME_Exception);
 
     /*!
@@ -508,31 +509,29 @@ module SMESH
       raises (SALOME::SALOME_Exception);
 
     /*!
-     * Add hypothesis to the mesh, under a particular Sub-shape
+     * Add hypothesis to the mesh, under a particular sub-shape
      * (or the main shape itself)
-     * The Add method is only used to prepare the build of the mesh and store
+     * This method is only used to prepare the build of the mesh and store
      * the algorithms and associated parameters.
-     * Actual job of mesh the shape is done by MESH_Gen.
+     * Actual job of meshing the shape is done by SMESH_Gen::Compute()
      * @params
-     * - aSubShape : sub-shape obtained by a shape explode in GEOM
+     * - aSubObject : sub-shape obtained by a shape explode in GEOM
      *   (or main shape)
-     * - anHyp : hypothesis object
+     * - anHyp : an hypothesis object
      * @return
-     * - OK if the hypothesis is compatible with the sub-shape
-     *   (and all previous hypothesis on the sub-shape)
-     * - NOK if the hypothesis is not compatible with the sub-shape
-     *   (or one previous hypothesis on the sub-shape)
-     * raises exception if hypothesis has not been created
+     * - An enum item explaining what's up
+     * - anErrorText: an optional textual description of a problem (if any)
      */
     Hypothesis_Status AddHypothesis(in GEOM::GEOM_Object aSubObject,
-                                   in SMESH_Hypothesis anHyp)
+                                    in SMESH_Hypothesis  anHyp,
+                                    out string           anErrorText)
       raises (SALOME::SALOME_Exception);
 
     /*!
      * Remove an hypothesis previouly added with AddHypothesis.
      */
     Hypothesis_Status RemoveHypothesis(in GEOM::GEOM_Object aSubObject,
-                                      in SMESH_Hypothesis anHyp)
+                                       in SMESH_Hypothesis anHyp)
       raises (SALOME::SALOME_Exception);
 
     /*!
index 397efff4484f7a82b0ed83409978a0639fb31e3e..293c8c8de10205af43ea45e8139b45cca64cb022 100644 (file)
@@ -238,12 +238,23 @@ module SMESH
      * \param theFace - ID of face whose orientation is checked.
      *        It can be < 1 then \a thePoint is used to find a face.
      * \param thePoint - is used to find a face if \a theFace < 1.
-     * \return number of reoriented elements.
+     * \return number of reoriented faces.
      */
     long Reorient2D(in SMESH_IDSource the2Dgroup,
                     in DirStruct      theDirection,
                     in long           theFace,
                     in PointStruct    thePoint) raises (SALOME::SALOME_Exception);
+    /*!
+     * \brief Reorient faces basing on orientation of adjacent volumes.
+     * \param faces - a list of objects containing face to reorient
+     * \param volumes - an object containing volumes.
+     * \param outsideNormal - to orient faces to have their normal 
+     *        pointing either \a outside or \a inside the adjacent volumes.
+     * \return number of reoriented faces.
+     */
+    long Reorient2DBy3D(in ListOfIDSources faces,
+                        in SMESH_IDSource  volumes,
+                        in boolean         outsideNormal) raises (SALOME::SALOME_Exception);
 
     /*!
      * \brief Fuse neighbour triangles into quadrangles.
index f55e54a70b6170f73d2f2ed1ccd5f345c77b6c7f..4ffa049b7ea6c3b5b6c9e3c95fb710ac0535a3ef 100755 (executable)
@@ -44,6 +44,8 @@ SET(SMESH_RESOURCES_FILES
   mesh_hypo_segment.png
   mesh_hypo_volume.png
   mesh_hypo_edit.png
+  mesh_plus.png
+  mesh_minus.png
   mesh_info.png
   advanced_mesh_info.png
   standard_mesh_info.png
@@ -205,6 +207,7 @@ SET(SMESH_RESOURCES_FILES
   mesh_min_dist.png
   reorient_faces_point.png
   reorient_faces_face.png
+  reorient_faces_volume.png
   mesh_ball.png
   mesh_measure_basic_props.png
   mesh_measure_length.png
index b482b89f698d8107293af54e307eb4adad4158b2..c49059d3a984ab6728550c093a4d3406a033cc03 100644 (file)
   </section>
 
  <section name="windows_geometry">
-  <parameter value="#00 #00 #00 #FF #00 #00 #00 #00 #FD #00 #00 #00 #02 #00 #00 #00 #00 #00 #00 #01 #00 #00 #00 #02 #44 #FC #02 #00 #00 #00 #01 #FC #00 #00 #00 #7B #00 #00 #02 #44 #00 #00 #00 #97 #01 #00 #00 #14 #FA #00 #00 #00 #00 #01 #00 #00 #00 #02 #FB #00 #00 #00 #10 #00 #77 #00 #69 #00 #6E #00 #64 #00 #6F #00 #77 #00 #5F #00 #30 #01 #00 #00 #00 #00 #FF #FF #FF #FF #00 #00 #00 #46 #00 #FF #FF #FF #FB #00 #00 #00 #10 #00 #77 #00 #69 #00 #6E #00 #64 #00 #6F #00 #77 #00 #5F #00 #33 #01 #00 #00 #00 #00 #00 #00 #01 #00 #00 #00 #00 #C0 #00 #FF #FF #FF #00 #00 #00 #03 #00 #00 #05 #40 #00 #00 #00 #53 #FC #01 #00 #00 #00 #01 #FB #00 #00 #00 #10 #00 #77 #00 #69 #00 #6E #00 #64 #00 #6F #00 #77 #00 #5F #00 #31 #01 #00 #00 #00 #00 #00 #00 #05 #40 #00 #00 #00 #46 #00 #FF #FF #FF #00 #00 #04 #38 #00 #00 #02 #44 #00 #00 #00 #04 #00 #00 #00 #04 #00 #00 #00 #08 #00 #00 #00 #08 #FC #00 #00 #00 #05 #00 #00 #00 #02 #00 #00 #00 #02 #00 #00 #00 #10 #00 #53 #00 #74 #00 #61 #00 #6E #00 #64 #00 #61 #00 #72 #00 #64 #01 #00 #00 #00 #00 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #0E #00 #4D #00 #6F #00 #64 #00 #75 #00 #6C #00 #65 #00 #73 #01 #00 #00 #00 #CE #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #02 #00 #00 #00 #07 #00 #00 #00 #2A #00 #4E #00 #6F #00 #64 #00 #65 #00 #20 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #02 #01 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #2A #00 #45 #00 #64 #00 #67 #00 #65 #00 #20 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #02 #4D #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #2A #00 #46 #00 #61 #00 #63 #00 #65 #00 #20 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #02 #F6 #00 #00 #02 #4A #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #18 #00 #4D #00 #65 #00 #73 #00 #68 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #00 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #26 #00 #41 #00 #64 #00 #64 #00 #20 #00 #45 #00 #6C #00 #65 #00 #6D #00 #65 #00 #6E #00 #74 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #01 #2B #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #3C #00 #41 #00 #64 #00 #64 #00 #20 #00 #4E #00 #6F #00 #6E #00 #20 #00 #4C #00 #69 #00 #6E #00 #65 #00 #61 #00 #72 #00 #20 #00 #45 #00 #6C #00 #65 #00 #6D #00 #65 #00 #6E #00 #74 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #02 #EB #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #1A #00 #47 #00 #72 #00 #6F #00 #75 #00 #70 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #04 #2F #00 #00 #01 #3E #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #02 #00 #00 #00 #01 #00 #00 #00 #2E #00 #56 #00 #6F #00 #6C #00 #75 #00 #6D #00 #65 #00 #20 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #00 #00 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #02 #00 #00 #00 #00 #00 #00 #00 #02 #00 #00 #00 #07 #00 #00 #00 #1C #00 #52 #00 #65 #00 #6D #00 #6F #00 #76 #00 #65 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #00 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #2C #00 #54 #00 #72 #00 #61 #00 #6E #00 #73 #00 #66 #00 #6F #00 #72 #00 #6D #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #8A #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #28 #00 #4D #00 #6F #00 #64 #00 #69 #00 #66 #00 #69 #00 #63 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #01 #90 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #26 #00 #49 #00 #6E #00 #66 #00 #6F #00 #72 #00 #6D #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #03 #6F #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #26 #00 #52 #00 #65 #00 #6E #00 #75 #00 #6D #00 #62 #00 #65 #00 #72 #00 #69 #00 #6E #00 #67 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #03 #BB #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #28 #00 #4D #00 #65 #00 #61 #00 #73 #00 #75 #00 #72 #00 #65 #00 #6D #00 #65 #00 #6E #00 #74 #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #04 #07 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #28 #00 #44 #00 #69 #00 #73 #00 #70 #00 #6C #00 #61 #00 #79 #00 #20 #00 #4D #00 #6F #00 #64 #00 #65 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #04 #34 #00 #00 #01 #0C #00 #00 #00 #00 #00 #00 #00 #00" name="SMESH"/>
+  <parameter name="SMESH" value="#00 #00 #00 #FF #00 #00 #00 #00 #FD #00 #00 #00 #02 #00 #00 #00 #00 #00 #00 #01 #00 #00 #00 #02 #49 #FC #02 #00 #00 #00 #02 #FC #00 #00 #00 #7B #00 #00 #02 #49 #00 #00 #00 #97 #01 #00 #00 #14 #FA #00 #00 #00 #00 #01 #00 #00 #00 #02 #FB #00 #00 #00 #22 #00 #6F #00 #62 #00 #6A #00 #65 #00 #63 #00 #74 #00 #42 #00 #72 #00 #6F #00 #77 #00 #73 #00 #65 #00 #72 #00 #44 #00 #6F #00 #63 #00 #6B #01 #00 #00 #00 #00 #FF #FF #FF #FF #00 #00 #00 #46 #00 #FF #FF #FF #FB #00 #00 #00 #18 #00 #6E #00 #6F #00 #74 #00 #65 #00 #42 #00 #6F #00 #6F #00 #6B #00 #44 #00 #6F #00 #63 #00 #6B #01 #00 #00 #00 #00 #00 #00 #01 #00 #00 #00 #00 #C0 #00 #FF #FF #FF #FB #00 #00 #00 #36 #00 #67 #00 #65 #00 #6F #00 #6D #00 #43 #00 #72 #00 #65 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #49 #00 #6E #00 #66 #00 #6F #00 #72 #00 #6D #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #44 #00 #6F #00 #63 #00 #6B #00 #00 #00 #02 #1F #00 #00 #00 #A5 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #03 #00 #00 #05 #40 #00 #00 #00 #53 #FC #01 #00 #00 #00 #01 #FB #00 #00 #00 #22 #00 #70 #00 #79 #00 #74 #00 #68 #00 #6F #00 #6E #00 #43 #00 #6F #00 #6E #00 #73 #00 #6F #00 #6C #00 #65 #00 #44 #00 #6F #00 #63 #00 #6B #01 #00 #00 #00 #00 #00 #00 #05 #40 #00 #00 #00 #46 #00 #FF #FF #FF #00 #00 #04 #38 #00 #00 #02 #49 #00 #00 #00 #04 #00 #00 #00 #04 #00 #00 #00 #08 #00 #00 #00 #08 #FC #00 #00 #00 #06 #00 #00 #00 #02 #00 #00 #00 #02 #00 #00 #00 #1C #00 #53 #00 #61 #00 #6C #00 #6F #00 #6D #00 #65 #00 #53 #00 #74 #00 #61 #00 #6E #00 #64 #00 #61 #00 #72 #00 #64 #01 #00 #00 #00 #00 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #1A #00 #53 #00 #61 #00 #6C #00 #6F #00 #6D #00 #65 #00 #4D #00 #6F #00 #64 #00 #75 #00 #6C #00 #65 #00 #73 #01 #00 #00 #00 #CE #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #02 #00 #00 #00 #07 #00 #00 #00 #12 #00 #47 #00 #45 #00 #4F #00 #4D #00 #42 #00 #61 #00 #73 #00 #69 #00 #63 #00 #00 #00 #00 #00 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #1C #00 #47 #00 #45 #00 #4F #00 #4D #00 #50 #00 #72 #00 #69 #00 #6D #00 #69 #00 #74 #00 #69 #00 #76 #00 #65 #00 #73 #00 #00 #00 #00 #0E #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #2A #00 #47 #00 #45 #00 #4F #00 #4D #00 #42 #00 #6F #00 #6F #00 #6C #00 #65 #00 #61 #00 #6E #00 #4F #00 #70 #00 #65 #00 #72 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #73 #00 #00 #00 #00 #1C #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #16 #00 #54 #00 #4F #00 #4F #00 #4C #00 #5F #00 #42 #00 #4C #00 #4F #00 #43 #00 #4B #00 #53 #00 #00 #00 #00 #2A #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #18 #00 #47 #00 #45 #00 #4F #00 #4D #00 #50 #00 #69 #00 #63 #00 #74 #00 #75 #00 #72 #00 #65 #00 #73 #00 #00 #00 #00 #38 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #1A #00 #54 #00 #4F #00 #4F #00 #4C #00 #5F #00 #41 #00 #44 #00 #56 #00 #41 #00 #4E #00 #43 #00 #45 #00 #44 #00 #00 #00 #00 #46 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #26 #00 #47 #00 #45 #00 #4F #00 #4D #00 #49 #00 #6D #00 #70 #00 #6F #00 #72 #00 #74 #00 #45 #00 #78 #00 #70 #00 #6F #00 #72 #00 #74 #00 #58 #00 #41 #00 #4F #00 #00 #00 #00 #54 #00 #00 #01 #69 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #02 #00 #00 #00 #05 #00 #00 #00 #24 #00 #47 #00 #45 #00 #4F #00 #4D #00 #54 #00 #72 #00 #61 #00 #6E #00 #73 #00 #66 #00 #6F #00 #72 #00 #6D #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #00 #00 #00 #00 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #1C #00 #47 #00 #45 #00 #4F #00 #4D #00 #4F #00 #70 #00 #65 #00 #72 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #73 #00 #00 #00 #00 #0E #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #1C #00 #47 #00 #45 #00 #4F #00 #4D #00 #47 #00 #65 #00 #6E #00 #65 #00 #72 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #00 #00 #00 #1C #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #12 #00 #47 #00 #45 #00 #4F #00 #4D #00 #42 #00 #75 #00 #69 #00 #6C #00 #64 #00 #00 #00 #00 #2A #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #20 #00 #47 #00 #45 #00 #4F #00 #4D #00 #4D #00 #6F #00 #64 #00 #69 #00 #66 #00 #69 #00 #63 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #00 #00 #00 #38 #00 #00 #01 #FB #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #02 #00 #00 #00 #05 #00 #00 #00 #18 #00 #47 #00 #45 #00 #4F #00 #4D #00 #4D #00 #65 #00 #61 #00 #73 #00 #75 #00 #72 #00 #65 #00 #73 #00 #00 #00 #00 #00 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #20 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #4D #00 #65 #00 #73 #00 #68 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #00 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #2C #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #41 #00 #64 #00 #64 #00 #45 #00 #6C #00 #65 #00 #6D #00 #65 #00 #6E #00 #74 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #01 #2B #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #2C #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #41 #00 #64 #00 #64 #00 #45 #00 #6C #00 #65 #00 #6D #00 #65 #00 #6E #00 #74 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #02 #EB #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #24 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #52 #00 #65 #00 #6D #00 #6F #00 #76 #00 #65 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #04 #2F #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #02 #00 #00 #00 #07 #00 #00 #00 #2E #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #49 #00 #6E #00 #66 #00 #6F #00 #72 #00 #6D #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #00 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #22 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #47 #00 #72 #00 #6F #00 #75 #00 #70 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #4C #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #34 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #54 #00 #72 #00 #61 #00 #6E #00 #73 #00 #66 #00 #6F #00 #72 #00 #6D #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #D6 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #30 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #4D #00 #6F #00 #64 #00 #69 #00 #66 #00 #69 #00 #63 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #01 #DC #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #2E #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #52 #00 #65 #00 #6E #00 #75 #00 #6D #00 #62 #00 #65 #00 #72 #00 #69 #00 #6E #00 #67 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #03 #BB #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #30 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #4D #00 #65 #00 #61 #00 #73 #00 #75 #00 #72 #00 #65 #00 #6D #00 #65 #00 #6E #00 #74 #00 #73 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #04 #07 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #2E #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #44 #00 #69 #00 #73 #00 #70 #00 #6C #00 #61 #00 #79 #00 #4D #00 #6F #00 #64 #00 #65 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #04 #34 #00 #00 #01 #58 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #02 #00 #00 #00 #04 #00 #00 #00 #30 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #4E #00 #6F #00 #64 #00 #65 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #00 #00 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #30 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #45 #00 #64 #00 #67 #00 #65 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #00 #00 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #30 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #46 #00 #61 #00 #63 #00 #65 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #00 #00 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #34 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #56 #00 #6F #00 #6C #00 #75 #00 #6D #00 #65 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #00 #00 #00 #00 #02 #AA #00 #00 #00 #00 #00 #00 #00 #00"/>
  </section>
  <section name="windows_visibility">
-  <parameter value="#00 #00 #00 #00 #15 #FF #FF #FF #FF #00 #00 #00 #02 #00 #00 #00 #00 #00 #00 #01 #00 #00 #00 #02 #44 #FC #02 #00 #00 #00 #01 #FC #00 #00 #00 #7B #00 #00 #02 #44 #00 #00 #00 #97 #01 #00 #00 #14 #FA #00 #00 #00 #00 #01 #00 #00 #00 #02 #FB #00 #00 #00 #10 #00 #77 #00 #69 #00 #6E #00 #64 #00 #6F #00 #77 #00 #5F #00 #30 #01 #00 #00 #00 #00 #FF #FF #FF #FF #00 #00 #00 #46 #00 #FF #FF #FF #FB #00 #00 #00 #10 #00 #77 #00 #69 #00 #6E #00 #64 #00 #6F #00 #77 #00 #5F #00 #33 #01 #00 #00 #00 #00 #00 #00 #01 #00 #00 #00 #00 #C0 #00 #FF #FF #FF #00 #00 #00 #03 #00 #00 #05 #40 #00 #00 #00 #53 #FC #01 #00 #00 #00 #01 #FB #00 #00 #00 #10 #00 #77 #00 #69 #00 #6E #00 #64 #00 #6F #00 #77 #00 #5F #00 #31 #01 #00 #00 #00 #00 #00 #00 #05 #40 #00 #00 #00 #46 #00 #FF #FF #FF #00 #00 #04 #38 #00 #00 #02 #44 #00 #00 #00 #04 #00 #00 #00 #04 #00 #00 #00 #08 #00 #00 #00 #08 #FC #00 #00 #00 #05 #00 #00 #00 #02 #00 #00 #00 #02 #00 #00 #00 #10 #00 #53 #00 #74 #00 #61 #00 #6E #00 #64 #00 #61 #00 #72 #00 #64 #01 #00 #00 #00 #00 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #0E #00 #4D #00 #6F #00 #64 #00 #75 #00 #6C #00 #65 #00 #73 #01 #00 #00 #00 #CE #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #02 #00 #00 #00 #07 #00 #00 #00 #2A #00 #4E #00 #6F #00 #64 #00 #65 #00 #20 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #02 #01 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #2A #00 #45 #00 #64 #00 #67 #00 #65 #00 #20 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #02 #4D #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #2A #00 #46 #00 #61 #00 #63 #00 #65 #00 #20 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #02 #F6 #00 #00 #02 #4A #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #18 #00 #4D #00 #65 #00 #73 #00 #68 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #00 #00 #26 #00 #41 #00 #64 #00 #64 #00 #20 #00 #45 #00 #6C #00 #65 #00 #6D #00 #65 #00 #6E #00 #74 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #3C #00 #41 #00 #64 #00 #64 #00 #20 #00 #4E #00 #6F #00 #6E #00 #20 #00 #4C #00 #69 #00 #6E #00 #65 #00 #61 #00 #72 #00 #20 #00 #45 #00 #6C #00 #65 #00 #6D #00 #65 #00 #6E #00 #74 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #28 #00 #44 #00 #69 #00 #73 #00 #70 #00 #6C #00 #61 #00 #79 #00 #20 #00 #4D #00 #6F #00 #64 #00 #65 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #2A #00 #45 #00 #64 #00 #67 #00 #65 #00 #20 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #00 #2A #00 #46 #00 #61 #00 #63 #00 #65 #00 #20 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #00 #1A #00 #47 #00 #72 #00 #6F #00 #75 #00 #70 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #26 #00 #49 #00 #6E #00 #66 #00 #6F #00 #72 #00 #6D #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #28 #00 #4D #00 #65 #00 #61 #00 #73 #00 #75 #00 #72 #00 #65 #00 #6D #00 #65 #00 #6E #00 #74 #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #18 #00 #4D #00 #65 #00 #73 #00 #68 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #28 #00 #4D #00 #6F #00 #64 #00 #69 #00 #66 #00 #69 #00 #63 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #0E #00 #4D #00 #6F #00 #64 #00 #75 #00 #6C #00 #65 #00 #73 #01 #00 #00 #00 #2A #00 #4E #00 #6F #00 #64 #00 #65 #00 #20 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #00 #28 #00 #52 #00 #65 #00 #63 #00 #6F #00 #72 #00 #64 #00 #69 #00 #6E #00 #67 #00 #20 #00 #4F #00 #70 #00 #65 #00 #72 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #73 #01 #00 #00 #00 #1C #00 #52 #00 #65 #00 #6D #00 #6F #00 #76 #00 #65 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #26 #00 #52 #00 #65 #00 #6E #00 #75 #00 #6D #00 #62 #00 #65 #00 #72 #00 #69 #00 #6E #00 #67 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #10 #00 #53 #00 #74 #00 #61 #00 #6E #00 #64 #00 #61 #00 #72 #00 #64 #01 #00 #00 #00 #2C #00 #54 #00 #72 #00 #61 #00 #6E #00 #73 #00 #66 #00 #6F #00 #72 #00 #6D #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #1E #00 #56 #00 #69 #00 #65 #00 #77 #00 #20 #00 #4F #00 #70 #00 #65 #00 #72 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #73 #01 #00 #00 #00 #2E #00 #56 #00 #6F #00 #6C #00 #75 #00 #6D #00 #65 #00 #20 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #01 #00 #00 #00 #03 #00 #00 #00 #10 #00 #77 #00 #69 #00 #6E #00 #64 #00 #6F #00 #77 #00 #5F #00 #30 #01 #00 #00 #00 #10 #00 #77 #00 #69 #00 #6E #00 #64 #00 #6F #00 #77 #00 #5F #00 #31 #01 #00 #00 #00 #10 #00 #77 #00 #69 #00 #6E #00 #64 #00 #6F #00 #77 #00 #5F #00 #33 #01" name="SMESH"/>
+  <parameter name="SMESH" value="#00 #00 #00 #00 #35 #FF #FF #FF #FF #00 #00 #00 #02 #00 #00 #00 #00 #00 #00 #01 #00 #00 #00 #02 #44 #FC #02 #00 #00 #00 #01 #FC #00 #00 #00 #7B #00 #00 #02 #44 #00 #00 #00 #97 #01 #00 #00 #14 #FA #00 #00 #00 #00 #01 #00 #00 #00 #02 #FB #00 #00 #00 #10 #00 #77 #00 #69 #00 #6E #00 #64 #00 #6F #00 #77 #00 #5F #00 #30 #01 #00 #00 #00 #00 #FF #FF #FF #FF #00 #00 #00 #46 #00 #FF #FF #FF #FB #00 #00 #00 #10 #00 #77 #00 #69 #00 #6E #00 #64 #00 #6F #00 #77 #00 #5F #00 #33 #01 #00 #00 #00 #00 #00 #00 #01 #00 #00 #00 #00 #C0 #00 #FF #FF #FF #00 #00 #00 #03 #00 #00 #05 #40 #00 #00 #00 #53 #FC #01 #00 #00 #00 #01 #FB #00 #00 #00 #10 #00 #77 #00 #69 #00 #6E #00 #64 #00 #6F #00 #77 #00 #5F #00 #31 #01 #00 #00 #00 #00 #00 #00 #05 #40 #00 #00 #00 #46 #00 #FF #FF #FF #00 #00 #04 #38 #00 #00 #02 #44 #00 #00 #00 #04 #00 #00 #00 #04 #00 #00 #00 #08 #00 #00 #00 #08 #FC #00 #00 #00 #05 #00 #00 #00 #02 #00 #00 #00 #02 #00 #00 #00 #10 #00 #53 #00 #74 #00 #61 #00 #6E #00 #64 #00 #61 #00 #72 #00 #64 #01 #00 #00 #00 #00 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #0E #00 #4D #00 #6F #00 #64 #00 #75 #00 #6C #00 #65 #00 #73 #01 #00 #00 #00 #CE #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #02 #00 #00 #00 #07 #00 #00 #00 #2A #00 #4E #00 #6F #00 #64 #00 #65 #00 #20 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #02 #01 #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #2A #00 #45 #00 #64 #00 #67 #00 #65 #00 #20 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #02 #4D #FF #FF #FF #FF #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #2A #00 #46 #00 #61 #00 #63 #00 #65 #00 #20 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #02 #F6 #00 #00 #02 #4A #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #00 #18 #00 #4D #00 #65 #00 #73 #00 #68 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #00 #00 #26 #00 #41 #00 #64 #00 #64 #00 #20 #00 #45 #00 #6C #00 #65 #00 #6D #00 #65 #00 #6E #00 #74 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #3C #00 #41 #00 #64 #00 #64 #00 #20 #00 #4E #00 #6F #00 #6E #00 #20 #00 #4C #00 #69 #00 #6E #00 #65 #00 #61 #00 #72 #00 #20 #00 #45 #00 #6C #00 #65 #00 #6D #00 #65 #00 #6E #00 #74 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #28 #00 #44 #00 #69 #00 #73 #00 #70 #00 #6C #00 #61 #00 #79 #00 #20 #00 #4D #00 #6F #00 #64 #00 #65 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #2A #00 #45 #00 #64 #00 #67 #00 #65 #00 #20 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #00 #2A #00 #46 #00 #61 #00 #63 #00 #65 #00 #20 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #00 #12 #00 #47 #00 #45 #00 #4F #00 #4D #00 #42 #00 #61 #00 #73 #00 #69 #00 #63 #01 #00 #00 #00 #2A #00 #47 #00 #45 #00 #4F #00 #4D #00 #42 #00 #6F #00 #6F #00 #6C #00 #65 #00 #61 #00 #6E #00 #4F #00 #70 #00 #65 #00 #72 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #73 #01 #00 #00 #00 #12 #00 #47 #00 #45 #00 #4F #00 #4D #00 #42 #00 #75 #00 #69 #00 #6C #00 #64 #01 #00 #00 #00 #1C #00 #47 #00 #45 #00 #4F #00 #4D #00 #47 #00 #65 #00 #6E #00 #65 #00 #72 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #01 #00 #00 #00 #26 #00 #47 #00 #45 #00 #4F #00 #4D #00 #49 #00 #6D #00 #70 #00 #6F #00 #72 #00 #74 #00 #45 #00 #78 #00 #70 #00 #6F #00 #72 #00 #74 #00 #58 #00 #41 #00 #4F #01 #00 #00 #00 #18 #00 #47 #00 #45 #00 #4F #00 #4D #00 #4D #00 #65 #00 #61 #00 #73 #00 #75 #00 #72 #00 #65 #00 #73 #00 #00 #00 #00 #20 #00 #47 #00 #45 #00 #4F #00 #4D #00 #4D #00 #6F #00 #64 #00 #69 #00 #66 #00 #69 #00 #63 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #01 #00 #00 #00 #1C #00 #47 #00 #45 #00 #4F #00 #4D #00 #4F #00 #70 #00 #65 #00 #72 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #73 #01 #00 #00 #00 #18 #00 #47 #00 #45 #00 #4F #00 #4D #00 #50 #00 #69 #00 #63 #00 #74 #00 #75 #00 #72 #00 #65 #00 #73 #01 #00 #00 #00 #1C #00 #47 #00 #45 #00 #4F #00 #4D #00 #50 #00 #72 #00 #69 #00 #6D #00 #69 #00 #74 #00 #69 #00 #76 #00 #65 #00 #73 #01 #00 #00 #00 #24 #00 #47 #00 #45 #00 #4F #00 #4D #00 #54 #00 #72 #00 #61 #00 #6E #00 #73 #00 #66 #00 #6F #00 #72 #00 #6D #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #01 #00 #00 #00 #1A #00 #47 #00 #72 #00 #6F #00 #75 #00 #70 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #26 #00 #49 #00 #6E #00 #66 #00 #6F #00 #72 #00 #6D #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #28 #00 #4D #00 #65 #00 #61 #00 #73 #00 #75 #00 #72 #00 #65 #00 #6D #00 #65 #00 #6E #00 #74 #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #18 #00 #4D #00 #65 #00 #73 #00 #68 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #28 #00 #4D #00 #6F #00 #64 #00 #69 #00 #66 #00 #69 #00 #63 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #0E #00 #4D #00 #6F #00 #64 #00 #75 #00 #6C #00 #65 #00 #73 #01 #00 #00 #00 #2A #00 #4E #00 #6F #00 #64 #00 #65 #00 #20 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #00 #32 #00 #4F #00 #43 #00 #43 #00 #56 #00 #69 #00 #65 #00 #77 #00 #65 #00 #72 #00 #33 #00 #44 #00 #56 #00 #69 #00 #65 #00 #77 #00 #4F #00 #70 #00 #65 #00 #72 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #73 #01 #00 #00 #00 #28 #00 #52 #00 #65 #00 #63 #00 #6F #00 #72 #00 #64 #00 #69 #00 #6E #00 #67 #00 #20 #00 #4F #00 #70 #00 #65 #00 #72 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #73 #01 #00 #00 #00 #1C #00 #52 #00 #65 #00 #6D #00 #6F #00 #76 #00 #65 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #26 #00 #52 #00 #65 #00 #6E #00 #75 #00 #6D #00 #62 #00 #65 #00 #72 #00 #69 #00 #6E #00 #67 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #2C #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #41 #00 #64 #00 #64 #00 #45 #00 #6C #00 #65 #00 #6D #00 #65 #00 #6E #00 #74 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #2E #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #44 #00 #69 #00 #73 #00 #70 #00 #6C #00 #61 #00 #79 #00 #4D #00 #6F #00 #64 #00 #65 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #30 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #45 #00 #64 #00 #67 #00 #65 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #00 #30 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #46 #00 #61 #00 #63 #00 #65 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #00 #22 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #47 #00 #72 #00 #6F #00 #75 #00 #70 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #2E #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #49 #00 #6E #00 #66 #00 #6F #00 #72 #00 #6D #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #30 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #4D #00 #65 #00 #61 #00 #73 #00 #75 #00 #72 #00 #65 #00 #6D #00 #65 #00 #6E #00 #74 #00 #73 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #20 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #4D #00 #65 #00 #73 #00 #68 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #30 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #4D #00 #6F #00 #64 #00 #69 #00 #66 #00 #69 #00 #63 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #30 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #4E #00 #6F #00 #64 #00 #65 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #00 #24 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #52 #00 #65 #00 #6D #00 #6F #00 #76 #00 #65 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #2E #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #52 #00 #65 #00 #6E #00 #75 #00 #6D #00 #62 #00 #65 #00 #72 #00 #69 #00 #6E #00 #67 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #34 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #54 #00 #72 #00 #61 #00 #6E #00 #73 #00 #66 #00 #6F #00 #72 #00 #6D #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #34 #00 #53 #00 #4D #00 #45 #00 #53 #00 #48 #00 #56 #00 #6F #00 #6C #00 #75 #00 #6D #00 #65 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #00 #00 #00 #1A #00 #53 #00 #61 #00 #6C #00 #6F #00 #6D #00 #65 #00 #4D #00 #6F #00 #64 #00 #75 #00 #6C #00 #65 #00 #73 #01 #00 #00 #00 #1C #00 #53 #00 #61 #00 #6C #00 #6F #00 #6D #00 #65 #00 #53 #00 #74 #00 #61 #00 #6E #00 #64 #00 #61 #00 #72 #00 #64 #01 #00 #00 #00 #10 #00 #53 #00 #74 #00 #61 #00 #6E #00 #64 #00 #61 #00 #72 #00 #64 #01 #00 #00 #00 #1A #00 #54 #00 #4F #00 #4F #00 #4C #00 #5F #00 #41 #00 #44 #00 #56 #00 #41 #00 #4E #00 #43 #00 #45 #00 #44 #01 #00 #00 #00 #16 #00 #54 #00 #4F #00 #4F #00 #4C #00 #5F #00 #42 #00 #4C #00 #4F #00 #43 #00 #4B #00 #53 #01 #00 #00 #00 #2C #00 #54 #00 #72 #00 #61 #00 #6E #00 #73 #00 #66 #00 #6F #00 #72 #00 #6D #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #01 #00 #00 #00 #2C #00 #56 #00 #54 #00 #4B #00 #52 #00 #65 #00 #63 #00 #6F #00 #72 #00 #64 #00 #69 #00 #6E #00 #67 #00 #4F #00 #70 #00 #65 #00 #72 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #73 #01 #00 #00 #00 #2E #00 #56 #00 #54 #00 #4B #00 #56 #00 #69 #00 #65 #00 #77 #00 #65 #00 #72 #00 #56 #00 #69 #00 #65 #00 #77 #00 #4F #00 #70 #00 #65 #00 #72 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #73 #01 #00 #00 #00 #1E #00 #56 #00 #69 #00 #65 #00 #77 #00 #20 #00 #4F #00 #70 #00 #65 #00 #72 #00 #61 #00 #74 #00 #69 #00 #6F #00 #6E #00 #73 #01 #00 #00 #00 #2E #00 #56 #00 #6F #00 #6C #00 #75 #00 #6D #00 #65 #00 #20 #00 #43 #00 #6F #00 #6E #00 #74 #00 #72 #00 #6F #00 #6C #00 #73 #00 #20 #00 #54 #00 #6F #00 #6F #00 #6C #00 #62 #00 #61 #00 #72 #00 #01 #00 #00 #00 #06 #00 #00 #00 #18 #00 #6E #00 #6F #00 #74 #00 #65 #00 #42 #00 #6F #00 #6F #00 #6B #00 #44 #00 #6F #00 #63 #00 #6B #01 #00 #00 #00 #22 #00 #6F #00 #62 #00 #6A #00 #65 #00 #63 #00 #74 #00 #42 #00 #72 #00 #6F #00 #77 #00 #73 #00 #65 #00 #72 #00 #44 #00 #6F #00 #63 #00 #6B #01 #00 #00 #00 #22 #00 #70 #00 #79 #00 #74 #00 #68 #00 #6F #00 #6E #00 #43 #00 #6F #00 #6E #00 #73 #00 #6F #00 #6C #00 #65 #00 #44 #00 #6F #00 #63 #00 #6B #01 #00 #00 #00 #10 #00 #77 #00 #69 #00 #6E #00 #64 #00 #6F #00 #77 #00 #5F #00 #30 #01 #00 #00 #00 #10 #00 #77 #00 #69 #00 #6E #00 #64 #00 #6F #00 #77 #00 #5F #00 #31 #01 #00 #00 #00 #10 #00 #77 #00 #69 #00 #6E #00 #64 #00 #6F #00 #77 #00 #5F #00 #33 #01"/>
  </section>
 </document>
diff --git a/resources/mesh_minus.png b/resources/mesh_minus.png
new file mode 100644 (file)
index 0000000..884e6b4
Binary files /dev/null and b/resources/mesh_minus.png differ
diff --git a/resources/mesh_plus.png b/resources/mesh_plus.png
new file mode 100644 (file)
index 0000000..3d4eda9
Binary files /dev/null and b/resources/mesh_plus.png differ
diff --git a/resources/reorient_faces_volume.png b/resources/reorient_faces_volume.png
new file mode 100644 (file)
index 0000000..e58bdb6
Binary files /dev/null and b/resources/reorient_faces_volume.png differ
index b69a98952928b8bd6967d886c35550d217eb1897..8eccaefcdd7094355a079cf7150ea99cd8ee968c 100644 (file)
@@ -39,6 +39,7 @@ SET(_link_LIBRARIES
   ${CAS_TKernel}
   ${CAS_TKTopAlgo}
   SMESHDS
+  SMESHUtils
 )
 
 # --- headers ---
index b47f9bbb7447b2474493fe7434ddc3d50252c6b2..4d3d1e4459aa993f2ca8549cb2162c1ccbaf969a 100644 (file)
@@ -29,6 +29,7 @@
 #include "SMESHDS_Group.hxx"
 #include "SMESHDS_Mesh.hxx"
 #include "SMESH_Comment.hxx"
+#include "SMESH_TypeDefs.hxx"
 
 #include <gp_XYZ.hxx>
 
@@ -76,7 +77,9 @@ namespace
     }
     bool IsStructured() const { return ( _type == CGNS_ENUMV( Structured )); }
     int IndexSize() const { return IsStructured() ? _meshDim : 1; }
-    string ReadZonesConnection(int file, int base, const map< string, TZoneData >& zonesByName);
+    string ReadZonesConnection(int file, int base,
+                               const map< string, TZoneData >& zonesByName,
+                               SMESHDS_Mesh*                   mesh);
     void ReplaceNodes( cgsize_t* ids, int nbIds, int idShift = 0 ) const;
 
     // Methods for a structured zone
@@ -205,6 +208,37 @@ namespace
     //gp_XYZ End() const { return gp_XYZ( _end[0]-1, _end[1]-1, _end[2]-1 ); }
   };
 
+  //================================================================================
+  /*!
+   * \brief Checks if the two arrays of node IDs describe nodes with equal coordinates
+   */
+  //================================================================================
+
+  bool isEqualNodes( const int* nIds1, const int* nIds2, int nbNodes, SMESHDS_Mesh* mesh )
+  {
+    if ( nbNodes > 0 )
+    {
+      SMESH_TNodeXYZ nn1[2], nn2[2];
+      nn1[0] = mesh->FindNode( nIds1[0] );
+      nn2[0] = mesh->FindNode( nIds2[0] );
+      if ( !nn1[0]._node || !nn2[0]._node )
+        return false;
+      double dist1 = ( nn1[0] - nn2[0] ).Modulus();
+      double dist2 = 0, tol = 1e-7;
+      if ( nbNodes > 1 )
+      {
+        nn1[1] = mesh->FindNode( nIds1[1] );
+        nn2[1] = mesh->FindNode( nIds2[1] );
+        if ( !nn1[1]._node || !nn2[1]._node )
+          return false;
+        dist2 = ( nn1[1] - nn2[1] ).Modulus();
+        tol   = 1e-5 * ( nn1[0] - nn1[1] ).Modulus();
+      }
+      return ( dist1 < tol & dist2 < tol );
+    }
+    return false;
+  }
+
   //================================================================================
   /*!
    * \brief Reads zone interface connectivity
@@ -220,7 +254,8 @@ namespace
 
   string TZoneData::ReadZonesConnection( int                             file,
                                          int                             base,
-                                         const map< string, TZoneData >& zonesByName)
+                                         const map< string, TZoneData >& zonesByName,
+                                         SMESHDS_Mesh*                   mesh)
   {
     string error;
 
@@ -277,6 +312,26 @@ namespace
                   continue; // this interface already read
               }
             }
+            // check if range and donorRange describe the same nodes
+            {
+              int ids1[2], ids2[2], nbN = 0;
+              TPointRangeIterator rangeIt1bis( range, _meshDim );
+              index1 = rangeIt1bis.Next();
+              index2 = T * ( index1 - begin1 ) + begin2;
+              ids1[0] = NodeID( index1 );
+              ids2[0] = zone2.NodeID( index2 );
+              ++nbN;
+              if ( rangeIt1bis.More() )
+              {
+                index1 = rangeIt1bis.Next();
+                index2 = T * ( index1 - begin1 ) + begin2;
+                ids1[1] = NodeID( index1 );
+                ids2[1] = zone2.NodeID( index2 );
+                ++nbN;
+              }
+              if ( !isEqualNodes( &ids1[0], &ids2[0], nbN, mesh ))
+                continue;
+            }
             while ( rangeIt1.More() )
             {
               index1 = rangeIt1.Next();
@@ -338,7 +393,7 @@ namespace
           {
             for ( int isThisZone = 0; isThisZone < 2; ++isThisZone )
             {
-              const TZoneData&            zone = isThisZone ? *this : zone2;
+              const TZoneData&           zone = isThisZone ? *this : zone2;
               CGNS_ENUMT(PointSetType_t) type = isThisZone ? ptype : donorPtype;
               vector< cgsize_t >&      points = isThisZone ? ids : donorIds;
               if ( type == CGNS_ENUMV( PointRange ))
@@ -361,8 +416,10 @@ namespace
                   points[i] += zone._nodeIdShift;
               }
             }
-            for ( size_t i = 0; i < ids.size() && i < donorIds.size(); ++i )
-              _nodeReplacementMap.insert( make_pair( ids[i], donorIds[i] ));
+            size_t nbN = std::min( ids.size(), donorIds.size());
+            if ( isEqualNodes( &ids[0], &donorIds[0], nbN, mesh ))
+              for ( size_t i = 0; i < nbN; ++i )
+                _nodeReplacementMap.insert( make_pair( ids[i], donorIds[i] ));
           }
           else
           {
@@ -710,7 +767,7 @@ Driver_Mesh::Status DriverCGNS_Read::Perform()
 
     // Read connectivity between zones. Nodes of the zone interface will be
     // replaced withing the zones read later
-    string err = zone.ReadZonesConnection( _fn, cgnsBase, zonesByName );
+    string err = zone.ReadZonesConnection( _fn, cgnsBase, zonesByName, myMesh );
     if ( !err.empty() )
       addMessage( err );
 
index 42f2f6aa3b148427484d0d853b562ecfd1a9bb41..2f9aceb467012d1a9705c823fb6ab2c2ceb102b1 100644 (file)
@@ -145,7 +145,7 @@ DriverMED_Family
 //=============================================================================
 DriverMED_FamilyPtrList 
 DriverMED_Family
-::MakeFamilies(const SMESHDS_SubMeshPtrMap& theSubMeshes,
+::MakeFamilies(SMESHDS_SubMeshIteratorPtr      theSubMeshes,
                const SMESHDS_GroupBasePtrList& theGroups,
                const bool doGroupOfNodes,
                const bool doGroupOfEdges,
@@ -170,11 +170,10 @@ DriverMED_Family
   int aElemFamId = FIRST_ELEM_FAMILY;
 
   // Process sub-meshes
-  SMESHDS_SubMeshPtrMap::const_iterator aSMIter = theSubMeshes.begin();
-  for (; aSMIter != theSubMeshes.end(); aSMIter++)
+  while ( theSubMeshes->more() )
   {
-    const int anId = aSMIter->first;
-    SMESHDS_SubMesh* aSubMesh = aSMIter->second;
+    SMESHDS_SubMesh* aSubMesh = const_cast< SMESHDS_SubMesh* >( theSubMeshes->next() );
+    const int anId = aSubMesh->GetID();
     if ( aSubMesh->IsComplexSubmesh() )
       continue; // submesh containing other submeshs
     DriverMED_FamilyPtrList aSMFams = SplitByType(aSubMesh,anId);
index d774603da613dca1459906d952e24fd31b467135..5a1c4d66cdd2397988e763a47e9d0880c71cef41 100644 (file)
@@ -69,7 +69,7 @@ class MESHDRIVERMED_EXPORT DriverMED_Family
   */
   static 
   DriverMED_FamilyPtrList
-  MakeFamilies (const SMESHDS_SubMeshPtrMap& theSubMeshes,
+  MakeFamilies (SMESHDS_SubMeshIteratorPtr      theSubMeshes,
                 const SMESHDS_GroupBasePtrList& theGroups,
                 const bool doGroupOfNodes,
                 const bool doGroupOfEdges,
index 47fa68b5d35e9bb2f258ce007489ef72eb4bf1ad..aec74adc9d00b70e7c3a62ffdc8ceae7ed079313 100644 (file)
@@ -101,7 +101,7 @@ void DriverMED_W_SMESHDS_Mesh::AddAllSubMeshes()
 
 void DriverMED_W_SMESHDS_Mesh::AddSubMesh(SMESHDS_SubMesh* theSubMesh, int theID)
 {
-  mySubMeshes[theID] = theSubMesh;
+  mySubMeshes.push_back( theSubMesh );
 }
 
 void DriverMED_W_SMESHDS_Mesh::AddGroupOfNodes()
@@ -292,6 +292,20 @@ namespace
 //       return elem_famNum->second;
     return aDefaultFamilyId;
   }
+
+  //================================================================================
+  /*!
+   * \brief Returns iterator on sub-meshes
+   */
+  //================================================================================
+
+  SMESHDS_SubMeshIteratorPtr getIterator( std::vector<SMESHDS_SubMesh*>& mySubMeshes )
+  {
+    return SMESHDS_SubMeshIteratorPtr
+      ( new SMDS_SetIterator
+        < const SMESHDS_SubMesh*, std::vector< SMESHDS_SubMesh* >::iterator >( mySubMeshes.begin(),
+                                                                               mySubMeshes.end() ));
+  }
 }
 
 Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform()
@@ -435,7 +449,7 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform()
          myDoGroupOfBalls   && nbBalls);
     } else {
       aFamilies = DriverMED_Family::MakeFamilies
-        (mySubMeshes, myGroups,
+        (getIterator( mySubMeshes ), myGroups,
          myDoGroupOfNodes   && nbNodes,
          myDoGroupOfEdges   && nbEdges,
          myDoGroupOfFaces   && nbFaces,
index d817c3f276ad14a6da1c0b42fa80facf4a0c9fdb..4342d5dd233ec277b428b225654deff769e507d2 100644 (file)
@@ -79,7 +79,7 @@ class MESHDRIVERMED_EXPORT DriverMED_W_SMESHDS_Mesh: public Driver_SMESHDS_Mesh
   MED::EVersion myMedVersion;
   std::list<SMESHDS_GroupBase*> myGroups;
   bool myAllSubMeshes;
-  std::map<int,SMESHDS_SubMesh*> mySubMeshes;
+  std::vector<SMESHDS_SubMesh*> mySubMeshes;
   bool myDoGroupOfNodes;
   bool myDoGroupOfEdges;
   bool myDoGroupOfFaces;
index 24ee333f72b92eddced40abad4b3b2a7378213de..182e9d7e8d723ccfb1a97344ee10707c29c4f4ab 100644 (file)
@@ -20,8 +20,8 @@
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-#include <fstream>      
-#include <stdio.h>      
+#include <fstream>
+#include <cstdio>
 
 #include "UNV2411_Structure.hxx"
 #include "UNV_Utilities.hxx"
@@ -36,7 +36,9 @@ UNV2411::TRecord::TRecord():
   exp_coord_sys_num(1),
   disp_coord_sys_num(1),
   color(11)//(0) -  0019936: EDF 794 SMESH : Export UNV : Node color and group id
-{}
+{
+  coord[1] = coord[2] = 0.0; // prepare to e.g. 2D mesh
+}
 
 void UNV2411::Read(std::ifstream& in_stream, TDataSet& theDataSet)
 {
@@ -54,7 +56,40 @@ void UNV2411::Read(std::ifstream& in_stream, TDataSet& theDataSet)
    * always 3 coordinates in the UNV file, no matter
    * which dimensionality libMesh is in
    */
+  int dim = 3;
   std::string num_buf;
+
+  // Issue 22638. Find out space dimension to read a 2D mesh from a file
+  // generated by SIMAIL from Simulog
+  if ( !in_stream.eof() )
+  {
+    int where  = in_stream.tellg();
+
+    TRecord aRec;
+    in_stream >> aRec.label ;
+    if ( aRec.label == -1 ) return; // dataset end 
+
+    dim = 0;
+    num_buf = read_line( in_stream );
+    for ( size_t i = 0; i < num_buf.size(); )
+    {
+      // skip spaces
+      while ( i < num_buf.size() && num_buf[i] == ' ' )
+        ++i;
+
+      dim += ( i < num_buf.size() );
+
+      // skip non-spaces
+      while ( i < num_buf.size() && num_buf[i] != ' ' )
+        ++i;
+    }
+    if ( dim == 0 )
+      return;
+
+    in_stream.seekg( where, in_stream.beg );
+  }
+
+  // read the rest records
   while ( !in_stream.eof() )
   {
     TRecord aRec;
@@ -72,7 +107,7 @@ void UNV2411::Read(std::ifstream& in_stream, TDataSet& theDataSet)
      * take care of the
      * floating-point data
      */
-    for(int d = 0; d < 3; d++){
+    for(int d = 0; d < dim; d++){
       in_stream>>num_buf;
       aRec.coord[d] = D_to_e(num_buf);
     }
index 29f119e5089058bf8615f3d2e30fec1750409581..930b1b9b738ad56f74265ea1c9d2aff1d1b241a2 100644 (file)
@@ -637,7 +637,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                                             const SMDS_MeshNode * n4,
                                             int ID)
 {
-    //MESSAGE("AddVolumeWithID " << ID);
+  //MESSAGE("AddVolumeWithID " << ID);
   SMDS_MeshVolume* volume = 0;
   if ( !n1 || !n2 || !n3 || !n4) return volume;
   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
@@ -657,31 +657,30 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
   }
   else {
     // --- retrieve nodes ID
-    vector<vtkIdType> nodeIds;
-    nodeIds.clear();
-    nodeIds.push_back(n1->getVtkId());
-    nodeIds.push_back(n3->getVtkId()); // order SMDS-->VTK
-    nodeIds.push_back(n2->getVtkId());
-    nodeIds.push_back(n4->getVtkId());
+    myNodeIds.resize(4);
+    myNodeIds[0] = n1->getVtkId();
+    myNodeIds[1] = n3->getVtkId(); // order SMDS-->VTK
+    myNodeIds[2] = n2->getVtkId();
+    myNodeIds[3] = n4->getVtkId();
 
     SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-    volvtk->init(nodeIds, this);
+    volvtk->init(myNodeIds, this);
     if (!this->registerElement(ID,volvtk))
-      {
-        this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-        myVolumePool->destroy(volvtk);
-        return 0;
-      }
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+      myVolumePool->destroy(volvtk);
+      return 0;
+    }
     volume = volvtk;
     adjustmyCellsCapacity(ID);
     myCells[ID] = volume;
     myInfo.myNbTetras++;
   }
 
-//  if (!registerElement(ID, volume)) {
-//    RemoveElement(volume, false);
-//    volume = NULL;
-//  }
+  //  if (!registerElement(ID, volume)) {
+  //    RemoveElement(volume, false);
+  //    volume = NULL;
+  //  }
   return volume;
 }
 
@@ -744,7 +743,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                                             const SMDS_MeshNode * n5,
                                             int ID)
 {
-    //MESSAGE("AddVolumeWithID " << ID);
+  //MESSAGE("AddVolumeWithID " << ID);
   SMDS_MeshVolume* volume = 0;
   if ( !n1 || !n2 || !n3 || !n4 || !n5) return volume;
   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
@@ -764,32 +763,31 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
   }
   else {
     // --- retrieve nodes ID
-    vector<vtkIdType> nodeIds;
-    nodeIds.clear();
-    nodeIds.push_back(n1->getVtkId());
-    nodeIds.push_back(n4->getVtkId());
-    nodeIds.push_back(n3->getVtkId());
-    nodeIds.push_back(n2->getVtkId());
-    nodeIds.push_back(n5->getVtkId());
+    myNodeIds.resize(5);
+    myNodeIds[0] = n1->getVtkId();
+    myNodeIds[1] = n4->getVtkId();
+    myNodeIds[2] = n3->getVtkId();
+    myNodeIds[3] = n2->getVtkId();
+    myNodeIds[4] = n5->getVtkId();
 
     SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-    volvtk->init(nodeIds, this);
+    volvtk->init(myNodeIds, this);
     if (!this->registerElement(ID,volvtk))
-      {
-        this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-        myVolumePool->destroy(volvtk);
-        return 0;
-      }
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+      myVolumePool->destroy(volvtk);
+      return 0;
+    }
     volume = volvtk;
     adjustmyCellsCapacity(ID);
     myCells[ID] = volume;
     myInfo.myNbPyramids++;
   }
 
-//  if (!registerElement(ID, volume)) {
-//    RemoveElement(volume, false);
-//    volume = NULL;
-//  }
+  //  if (!registerElement(ID, volume)) {
+  //    RemoveElement(volume, false);
+  //    volume = NULL;
+  //  }
   return volume;
 }
 
@@ -856,7 +854,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                                             const SMDS_MeshNode * n6,
                                             int ID)
 {
-    //MESSAGE("AddVolumeWithID " << ID);
+  //MESSAGE("AddVolumeWithID " << ID);
   SMDS_MeshVolume* volume = 0;
   if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6) return volume;
   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
@@ -877,33 +875,32 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
   }
   else {
     // --- retrieve nodes ID
-    vector<vtkIdType> nodeIds;
-    nodeIds.clear();
-    nodeIds.push_back(n1->getVtkId());
-    nodeIds.push_back(n2->getVtkId());
-    nodeIds.push_back(n3->getVtkId());
-    nodeIds.push_back(n4->getVtkId());
-    nodeIds.push_back(n5->getVtkId());
-    nodeIds.push_back(n6->getVtkId());
+    myNodeIds.resize(6);
+    myNodeIds[0] = n1->getVtkId();
+    myNodeIds[1] = n2->getVtkId();
+    myNodeIds[2] = n3->getVtkId();
+    myNodeIds[3] = n4->getVtkId();
+    myNodeIds[4] = n5->getVtkId();
+    myNodeIds[5] = n6->getVtkId();
 
     SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-    volvtk->init(nodeIds, this);
+    volvtk->init(myNodeIds, this);
     if (!this->registerElement(ID,volvtk))
-      {
-        this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-        myVolumePool->destroy(volvtk);
-        return 0;
-      }
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+      myVolumePool->destroy(volvtk);
+      return 0;
+    }
     volume = volvtk;
     adjustmyCellsCapacity(ID);
     myCells[ID] = volume;
     myInfo.myNbPrisms++;
   }
 
-//  if (!registerElement(ID, volume)) {
-//    RemoveElement(volume, false);
-//    volume = NULL;
-//  }
+  //  if (!registerElement(ID, volume)) {
+  //    RemoveElement(volume, false);
+  //    volume = NULL;
+  //  }
   return volume;
 }
 
@@ -1006,29 +1003,29 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
   }
   else {
     // --- retrieve nodes ID
-    vector<vtkIdType> nodeIds;
-    nodeIds.push_back(n1->getVtkId());
-    nodeIds.push_back(n6->getVtkId());
-    nodeIds.push_back(n5->getVtkId());
-    nodeIds.push_back(n4->getVtkId());
-    nodeIds.push_back(n3->getVtkId());
-    nodeIds.push_back(n2->getVtkId());
-
-    nodeIds.push_back(n7->getVtkId());
-    nodeIds.push_back(n12->getVtkId());
-    nodeIds.push_back(n11->getVtkId());
-    nodeIds.push_back(n10->getVtkId());
-    nodeIds.push_back(n9->getVtkId());
-    nodeIds.push_back(n8->getVtkId());
+    myNodeIds.resize(12);
+    myNodeIds[0] = n1->getVtkId();
+    myNodeIds[1] = n6->getVtkId();
+    myNodeIds[2] = n5->getVtkId();
+    myNodeIds[3] = n4->getVtkId();
+    myNodeIds[4] = n3->getVtkId();
+    myNodeIds[5] = n2->getVtkId();
+
+    myNodeIds[6] = n7->getVtkId();
+    myNodeIds[7] = n12->getVtkId();
+    myNodeIds[8] = n11->getVtkId();
+    myNodeIds[9] = n10->getVtkId();
+    myNodeIds[10] = n9->getVtkId();
+    myNodeIds[11] = n8->getVtkId();
 
     SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-    volvtk->init(nodeIds, this);
+    volvtk->init(myNodeIds, this);
     if (!this->registerElement(ID,volvtk))
-      {
-        this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-        myVolumePool->destroy(volvtk);
-        return 0;
-      }
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+      myVolumePool->destroy(volvtk);
+      return 0;
+    }
     volume = volvtk;
     adjustmyCellsCapacity(ID);
     myCells[ID] = volume;
@@ -1133,35 +1130,34 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
   }
   else {
     // --- retrieve nodes ID
-    vector<vtkIdType> nodeIds;
-    nodeIds.clear();
-    nodeIds.push_back(n1->getVtkId());
-    nodeIds.push_back(n4->getVtkId());
-    nodeIds.push_back(n3->getVtkId());
-    nodeIds.push_back(n2->getVtkId());
-    nodeIds.push_back(n5->getVtkId());
-    nodeIds.push_back(n8->getVtkId());
-    nodeIds.push_back(n7->getVtkId());
-    nodeIds.push_back(n6->getVtkId());
+    myNodeIds.resize(8);
+    myNodeIds[0] = n1->getVtkId();
+    myNodeIds[1] = n4->getVtkId();
+    myNodeIds[2] = n3->getVtkId();
+    myNodeIds[3] = n2->getVtkId();
+    myNodeIds[4] = n5->getVtkId();
+    myNodeIds[5] = n8->getVtkId();
+    myNodeIds[6] = n7->getVtkId();
+    myNodeIds[7] = n6->getVtkId();
 
     SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-    volvtk->init(nodeIds, this);
+    volvtk->init(myNodeIds, this);
     if (!this->registerElement(ID,volvtk))
-      {
-        this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-        myVolumePool->destroy(volvtk);
-        return 0;
-      }
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+      myVolumePool->destroy(volvtk);
+      return 0;
+    }
     volume = volvtk;
     adjustmyCellsCapacity(ID);
     myCells[ID] = volume;
     myInfo.myNbHexas++;
   }
-//  if (!registerElement(ID, volume)) {
-//    RemoveElement(volume, false);
-//    volume = NULL;
-//  }
+
+  //  if (!registerElement(ID, volume)) {
+  //    RemoveElement(volume, false);
+  //    volume = NULL;
+  //  }
   return volume;
 }
 
@@ -1329,57 +1325,55 @@ SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID (const vector<int> & nodes_ids,
 /// Add a polygon defined by its nodes
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID
-                          (const vector<const SMDS_MeshNode*> & nodes,
-                           const int                            ID)
+SMDS_MeshFace*
+SMDS_Mesh::AddPolygonalFaceWithID (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;
-    }
+  {
+    MESSAGE("Error : Not implemented");
+    return NULL;
+  }
   else
-    {
-//#ifdef VTK_HAVE_POLYHEDRON
+  {
+    //#ifdef VTK_HAVE_POLYHEDRON
     //MESSAGE("AddPolygonalFaceWithID vtk " << ID);
-    vector<vtkIdType> nodeIds;
-    nodeIds.clear();
-    vector<const SMDS_MeshNode*>::const_iterator it = nodes.begin();
-    for ( ; it != nodes.end(); ++it)
-      nodeIds.push_back((*it)->getVtkId());
+    myNodeIds.resize( nodes.size() );
+    for ( size_t i = 0; i < nodes.size(); ++i )
+      myNodeIds[i] = nodes[i]->getVtkId();
 
     SMDS_VtkFace *facevtk = myFacePool->getNew();
-    facevtk->initPoly(nodeIds, this);
+    facevtk->initPoly(myNodeIds, this);
     if (!this->registerElement(ID,facevtk))
-      {
-        this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
-        myFacePool->destroy(facevtk);
-        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++;
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+      myFacePool->destroy(facevtk);
+      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;
+  //#ifndef VTK_HAVE_POLYHEDRON
+  //  if (!registerElement(ID, face))
+  //    {
+  //      registerElement(myElementIDFactory->GetFreeID(), face);
+  //      //RemoveElement(face, false);
+  //      //face = NULL;
+  //    }
+  //#endif
 return face;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1419,63 +1413,61 @@ SMDS_MeshVolume * SMDS_Mesh::AddPolyhedralVolumeWithID
 /// @return The created  volume
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolumeWithID
-                            (const vector<const SMDS_MeshNode*>& nodes,
-                             const vector<int>                 & quantities,
-                             const int                           ID)
+SMDS_MeshVolume*
+SMDS_Mesh::AddPolyhedralVolumeWithID (const vector<const SMDS_MeshNode*>& nodes,
+                                      const vector<int>                 & quantities,
+                                      const int                           ID)
 {
   SMDS_MeshVolume* volume = 0;
   if ( nodes.empty() || quantities.empty() )
     return NULL;
   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   if (hasConstructionFaces())
-    {
-      MESSAGE("Error : Not implemented");
-      return NULL;
-    }
+  {
+    MESSAGE("Error : Not implemented");
+    return NULL;
+  }
   else if (hasConstructionEdges())
-    {
-      MESSAGE("Error : Not implemented");
-      return NULL;
-    }
+  {
+    MESSAGE("Error : Not implemented");
+    return NULL;
+  }
   else
+  {
+    //#ifdef VTK_HAVE_POLYHEDRON
+    //MESSAGE("AddPolyhedralVolumeWithID vtk " << ID);
+    myNodeIds.resize( nodes.size() );
+    for ( size_t i = 0; i < nodes.size(); ++i )
+      myNodeIds[i] = nodes[i]->getVtkId();
+
+    SMDS_VtkVolume *volvtk = myVolumePool->getNew();
+    volvtk->initPoly(myNodeIds, quantities, this);
+    if (!this->registerElement(ID, volvtk))
     {
-//#ifdef VTK_HAVE_POLYHEDRON
-      //MESSAGE("AddPolyhedralVolumeWithID vtk " << ID);
-      vector<vtkIdType> nodeIds;
-      nodeIds.clear();
-      vector<const SMDS_MeshNode*>::const_iterator it = nodes.begin();
-      for (; it != nodes.end(); ++it)
-        nodeIds.push_back((*it)->getVtkId());
-
-      SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-      volvtk->initPoly(nodeIds, quantities, this);
-      if (!this->registerElement(ID, volvtk))
-        {
-          this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-          myVolumePool->destroy(volvtk);
-          return 0;
-        }
-      volume = volvtk;
-//#else
-//      MESSAGE("AddPolyhedralVolumeWithID smds " << ID);
-//      for ( int i = 0; i < nodes.size(); ++i )
-//      if ( !nodes[ i ] ) return 0;
-//      volume = new SMDS_PolyhedralVolumeOfNodes(nodes, quantities);
-//#endif
-      adjustmyCellsCapacity(ID);
-      myCells[ID] = volume;
-      myInfo.myNbPolyhedrons++;
+      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+      myVolumePool->destroy(volvtk);
+      return 0;
     }
+    volume = volvtk;
+    //#else
+    //      MESSAGE("AddPolyhedralVolumeWithID smds " << ID);
+    //      for ( int i = 0; i < nodes.size(); ++i )
+    //      if ( !nodes[ i ] ) return 0;
+    //      volume = new SMDS_PolyhedralVolumeOfNodes(nodes, quantities);
+    //#endif
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = volume;
+    myInfo.myNbPolyhedrons++;
+  }
 
-//#ifndef VTK_HAVE_POLYHEDRON
-//  if (!registerElement(ID, volume))
-//    {
-//      registerElement(myElementIDFactory->GetFreeID(), volume);
-//      //RemoveElement(volume, false);
-//      //volume = NULL;
-//    }
-//#endif
+  //#ifndef VTK_HAVE_POLYHEDRON
+  //  if (!registerElement(ID, volume))
+  //    {
+  //      registerElement(myElementIDFactory->GetFreeID(), volume);
+  //      //RemoveElement(volume, false);
+  //      //volume = NULL;
+  //    }
+  //#endif
   return volume;
 }
 
@@ -1705,21 +1697,20 @@ SMDS_MeshFace * SMDS_Mesh::createTriangle(const SMDS_MeshNode * node1,
   else
   {
     // --- retrieve nodes ID
-    vector<vtkIdType> nodeIds;
-    nodeIds.clear();
-    nodeIds.push_back(node1->getVtkId());
-    nodeIds.push_back(node2->getVtkId());
-    nodeIds.push_back(node3->getVtkId());
+    myNodeIds.resize(3);
+    myNodeIds[0] = node1->getVtkId();
+    myNodeIds[1] = node2->getVtkId();
+    myNodeIds[2] = node3->getVtkId();
 
     SMDS_MeshFace * face = 0;
     SMDS_VtkFace *facevtk = myFacePool->getNew();
-    facevtk->init(nodeIds, this); // put in vtkUnstructuredGrid
+    facevtk->init(myNodeIds, this); // put in vtkUnstructuredGrid
     if (!this->registerElement(ID,facevtk))
-      {
-        this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
-        myFacePool->destroy(facevtk);
-        return 0;
-      }
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+      myFacePool->destroy(facevtk);
+      return 0;
+    }
     face = facevtk;
     adjustmyCellsCapacity(ID);
     myCells[ID] = face;
@@ -1743,7 +1734,7 @@ SMDS_MeshFace * SMDS_Mesh::createQuadrangle(const SMDS_MeshNode * node1,
   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   if(hasConstructionEdges())
   {
-      //MESSAGE("createQuadrangle hasConstructionEdges "<< ID);
+    //MESSAGE("createQuadrangle hasConstructionEdges "<< ID);
     SMDS_MeshEdge *edge1, *edge2, *edge3, *edge4;
     edge1=FindEdgeOrCreate(node1,node2);
     edge2=FindEdgeOrCreate(node2,node3);
@@ -1759,22 +1750,21 @@ SMDS_MeshFace * SMDS_Mesh::createQuadrangle(const SMDS_MeshNode * node1,
   else
   {
     // --- retrieve nodes ID
-    vector<vtkIdType> nodeIds;
-    nodeIds.clear();
-    nodeIds.push_back(node1->getVtkId());
-    nodeIds.push_back(node2->getVtkId());
-    nodeIds.push_back(node3->getVtkId());
-    nodeIds.push_back(node4->getVtkId());
+    myNodeIds.resize(4);
+    myNodeIds[0] = node1->getVtkId();
+    myNodeIds[1] = node2->getVtkId();
+    myNodeIds[2] = node3->getVtkId();
+    myNodeIds[3] = node4->getVtkId();
 
     SMDS_MeshFace * face = 0;
     SMDS_VtkFace *facevtk = myFacePool->getNew();
-    facevtk->init(nodeIds, this);
+    facevtk->init(myNodeIds, this);
     if (!this->registerElement(ID,facevtk))
-      {
-        this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
-        myFacePool->destroy(facevtk);
-        return 0;
-      }
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+      myFacePool->destroy(facevtk);
+      return 0;
+    }
     face = facevtk;
     adjustmyCellsCapacity(ID);
     myCells[ID] = face;
@@ -2094,19 +2084,18 @@ SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1,
     if ( NbEdges() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
     int ID = myElementIDFactory->GetFreeID(); // -PR- voir si on range cet element
     adjustmyCellsCapacity(ID);
-    vector<vtkIdType> nodeIds;
-    nodeIds.clear();
-    nodeIds.push_back(node1->getVtkId());
-    nodeIds.push_back(node2->getVtkId());
+    myNodeIds.resize(2);
+    myNodeIds[0] = node1->getVtkId();
+    myNodeIds[1] = node2->getVtkId();
 
     SMDS_VtkEdge *edgevtk = myEdgePool->getNew();
-    edgevtk->init(nodeIds, this);
+    edgevtk->init(myNodeIds, this);
     if (!this->registerElement(ID,edgevtk))
-      {
-        this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
-        myEdgePool->destroy(edgevtk);
-        return 0;
-      }
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
+      myEdgePool->destroy(edgevtk);
+      return 0;
+    }
     toReturn = edgevtk;
     myCells[ID] = toReturn;
     myInfo.myNbEdges++;
@@ -3591,30 +3580,29 @@ SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
   if ( !n1 || !n2 || !n12 ) return 0;
 
   // --- retrieve nodes ID
-  vector<vtkIdType> nodeIds;
-  nodeIds.clear();
-  nodeIds.push_back(n1->getVtkId());
-  nodeIds.push_back(n2->getVtkId());
-  nodeIds.push_back(n12->getVtkId());
+  myNodeIds.resize(3);
+  myNodeIds[0] = n1->getVtkId();
+  myNodeIds[1] = n2->getVtkId();
+  myNodeIds[2] = n12->getVtkId();
 
   SMDS_MeshEdge * edge = 0;
   SMDS_VtkEdge *edgevtk = myEdgePool->getNew();
-  edgevtk->init(nodeIds, this);
+  edgevtk->init(myNodeIds, this);
   if (!this->registerElement(ID,edgevtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
-      myEdgePool->destroy(edgevtk);
-      return 0;
-    }
+  {
+    this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
+    myEdgePool->destroy(edgevtk);
+    return 0;
+  }
   edge = edgevtk;
   adjustmyCellsCapacity(ID);
   myCells[ID] = edge;
   myInfo.myNbQuadEdges++;
 
-//  if (!registerElement(ID, edge)) {
-//        RemoveElement(edge, false);
-//        edge = NULL;
-//  }
+  //  if (!registerElement(ID, edge)) {
+  //        RemoveElement(edge, false);
+  //        edge = NULL;
+  //  }
   return edge;
 
 }
@@ -3672,33 +3660,32 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
   else
   {
     // --- retrieve nodes ID
-    vector<vtkIdType> nodeIds;
-    nodeIds.clear();
-    nodeIds.push_back(n1->getVtkId());
-    nodeIds.push_back(n2->getVtkId());
-    nodeIds.push_back(n3->getVtkId());
-    nodeIds.push_back(n12->getVtkId());
-    nodeIds.push_back(n23->getVtkId());
-    nodeIds.push_back(n31->getVtkId());
+    myNodeIds.resize(6);
+    myNodeIds[0] = n1->getVtkId();
+    myNodeIds[1] = n2->getVtkId();
+    myNodeIds[2] = n3->getVtkId();
+    myNodeIds[3] = n12->getVtkId();
+    myNodeIds[4] = n23->getVtkId();
+    myNodeIds[5] = n31->getVtkId();
 
     SMDS_MeshFace * face = 0;
     SMDS_VtkFace *facevtk = myFacePool->getNew();
-    facevtk->init(nodeIds, this);
+    facevtk->init(myNodeIds, this);
     if (!this->registerElement(ID,facevtk))
-      {
-        this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
-        myFacePool->destroy(facevtk);
-        return 0;
-      }
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+      myFacePool->destroy(facevtk);
+      return 0;
+    }
     face = facevtk;
     adjustmyCellsCapacity(ID);
     myCells[ID] = face;
     myInfo.myNbQuadTriangles++;
 
-//    if (!registerElement(ID, face)) {
-//      RemoveElement(face, false);
-//      face = NULL;
-//    }
+    //    if (!registerElement(ID, face)) {
+    //      RemoveElement(face, false);
+    //      face = NULL;
+    //    }
     return face;
   }
 }
@@ -3759,34 +3746,33 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
   else
   {
     // --- retrieve nodes ID
-    vector<vtkIdType> nodeIds;
-    nodeIds.clear();
-    nodeIds.push_back(n1->getVtkId());
-    nodeIds.push_back(n2->getVtkId());
-    nodeIds.push_back(n3->getVtkId());
-    nodeIds.push_back(n12->getVtkId());
-    nodeIds.push_back(n23->getVtkId());
-    nodeIds.push_back(n31->getVtkId());
-    nodeIds.push_back(nCenter->getVtkId());
+    myNodeIds.resize(7);
+    myNodeIds[0] = n1->getVtkId();
+    myNodeIds[1] = n2->getVtkId();
+    myNodeIds[2] = n3->getVtkId();
+    myNodeIds[3] = n12->getVtkId();
+    myNodeIds[4] = n23->getVtkId();
+    myNodeIds[5] = n31->getVtkId();
+    myNodeIds[6] = nCenter->getVtkId();
 
     SMDS_MeshFace * face = 0;
     SMDS_VtkFace *facevtk = myFacePool->getNew();
-    facevtk->init(nodeIds, this);
+    facevtk->init(myNodeIds, this);
     if (!this->registerElement(ID,facevtk))
-      {
-        this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
-        myFacePool->destroy(facevtk);
-        return 0;
-      }
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+      myFacePool->destroy(facevtk);
+      return 0;
+    }
     face = facevtk;
     adjustmyCellsCapacity(ID);
     myCells[ID] = face;
     myInfo.myNbBiQuadTriangles++;
 
-//    if (!registerElement(ID, face)) {
-//      RemoveElement(face, false);
-//      face = NULL;
-//    }
+    //    if (!registerElement(ID, face)) {
+    //      RemoveElement(face, false);
+    //      face = NULL;
+    //    }
     return face;
   }
 }
@@ -3845,40 +3831,39 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41) return 0;
   if(hasConstructionEdges()) {
     // creation quadratic edges - not implemented
-        return 0;
+    return 0;
   }
   else
   {
     // --- retrieve nodes ID
-    vector<vtkIdType> nodeIds;
-    nodeIds.clear();
-    nodeIds.push_back(n1->getVtkId());
-    nodeIds.push_back(n2->getVtkId());
-    nodeIds.push_back(n3->getVtkId());
-    nodeIds.push_back(n4->getVtkId());
-    nodeIds.push_back(n12->getVtkId());
-    nodeIds.push_back(n23->getVtkId());
-    nodeIds.push_back(n34->getVtkId());
-    nodeIds.push_back(n41->getVtkId());
+    myNodeIds.resize(8);
+    myNodeIds[0] = n1->getVtkId();
+    myNodeIds[1] = n2->getVtkId();
+    myNodeIds[2] = n3->getVtkId();
+    myNodeIds[3] = n4->getVtkId();
+    myNodeIds[4] = n12->getVtkId();
+    myNodeIds[5] = n23->getVtkId();
+    myNodeIds[6] = n34->getVtkId();
+    myNodeIds[7] = n41->getVtkId();
 
     SMDS_MeshFace * face = 0;
     SMDS_VtkFace *facevtk = myFacePool->getNew();
-    facevtk->init(nodeIds, this);
+    facevtk->init(myNodeIds, this);
     if (!this->registerElement(ID,facevtk))
-      {
-        this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
-        myFacePool->destroy(facevtk);
-        return 0;
-      }
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+      myFacePool->destroy(facevtk);
+      return 0;
+    }
     face = facevtk;
     adjustmyCellsCapacity(ID);
     myCells[ID] = face;
     myInfo.myNbQuadQuadrangles++;
 
-//    if (!registerElement(ID, face)) {
-//      RemoveElement(face, false);
-//      face = NULL;
-//    }
+    //    if (!registerElement(ID, face)) {
+    //      RemoveElement(face, false);
+    //      face = NULL;
+    //    }
     return face;
   }
 }
@@ -3939,41 +3924,40 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41 || !nCenter) return 0;
   if(hasConstructionEdges()) {
     // creation quadratic edges - not implemented
-        return 0;
+    return 0;
   }
   else
   {
     // --- retrieve nodes ID
-    vector<vtkIdType> nodeIds;
-    nodeIds.clear();
-    nodeIds.push_back(n1->getVtkId());
-    nodeIds.push_back(n2->getVtkId());
-    nodeIds.push_back(n3->getVtkId());
-    nodeIds.push_back(n4->getVtkId());
-    nodeIds.push_back(n12->getVtkId());
-    nodeIds.push_back(n23->getVtkId());
-    nodeIds.push_back(n34->getVtkId());
-    nodeIds.push_back(n41->getVtkId());
-    nodeIds.push_back(nCenter->getVtkId());
+    myNodeIds.resize(9);
+    myNodeIds[0] = n1->getVtkId();
+    myNodeIds[1] = n2->getVtkId();
+    myNodeIds[2] = n3->getVtkId();
+    myNodeIds[3] = n4->getVtkId();
+    myNodeIds[4] = n12->getVtkId();
+    myNodeIds[5] = n23->getVtkId();
+    myNodeIds[6] = n34->getVtkId();
+    myNodeIds[7] = n41->getVtkId();
+    myNodeIds[8] = nCenter->getVtkId();
 
     SMDS_MeshFace * face = 0;
     SMDS_VtkFace *facevtk = myFacePool->getNew();
-    facevtk->init(nodeIds, this);
+    facevtk->init(myNodeIds, this);
     if (!this->registerElement(ID,facevtk))
-      {
-        this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
-        myFacePool->destroy(facevtk);
-        return 0;
-      }
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+      myFacePool->destroy(facevtk);
+      return 0;
+    }
     face = facevtk;
     adjustmyCellsCapacity(ID);
     myCells[ID] = face;
     myInfo.myNbBiQuadQuadrangles++;
 
-//    if (!registerElement(ID, face)) {
-//      RemoveElement(face, false);
-//      face = NULL;
-//    }
+    //    if (!registerElement(ID, face)) {
+    //      RemoveElement(face, false);
+    //      face = NULL;
+    //    }
     return face;
   }
 }
@@ -4046,37 +4030,36 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
     return 0;
   }
   // --- retrieve nodes ID
-  vector<vtkIdType> nodeIds;
-  nodeIds.clear();
-  nodeIds.push_back(n1->getVtkId());
-  nodeIds.push_back(n3->getVtkId());
-  nodeIds.push_back(n2->getVtkId());
-  nodeIds.push_back(n4->getVtkId());
+  myNodeIds.resize(10);
+  myNodeIds[0] = n1->getVtkId();
+  myNodeIds[1] = n3->getVtkId();
+  myNodeIds[2] = n2->getVtkId();
+  myNodeIds[3] = n4->getVtkId();
 
-  nodeIds.push_back(n31->getVtkId());
-  nodeIds.push_back(n23->getVtkId());
-  nodeIds.push_back(n12->getVtkId());
+  myNodeIds[4] = n31->getVtkId();
+  myNodeIds[5] = n23->getVtkId();
+  myNodeIds[6] = n12->getVtkId();
 
-  nodeIds.push_back(n14->getVtkId());
-  nodeIds.push_back(n34->getVtkId());
-  nodeIds.push_back(n24->getVtkId());
+  myNodeIds[7] = n14->getVtkId();
+  myNodeIds[8] = n34->getVtkId();
+  myNodeIds[9] = n24->getVtkId();
 
   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-  volvtk->init(nodeIds, this);
+  volvtk->init(myNodeIds, this);
   if (!this->registerElement(ID,volvtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-      myVolumePool->destroy(volvtk);
-      return 0;
-    }
+  {
+    this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+    myVolumePool->destroy(volvtk);
+    return 0;
+  }
   adjustmyCellsCapacity(ID);
   myCells[ID] = volvtk;
   myInfo.myNbQuadTetras++;
 
-//  if (!registerElement(ID, volvtk)) {
-//    RemoveElement(volvtk, false);
-//    volvtk = NULL;
-//  }
+  //  if (!registerElement(ID, volvtk)) {
+  //    RemoveElement(volvtk, false);
+  //    volvtk = NULL;
+  //  }
   return volvtk;
 }
 
@@ -4159,40 +4142,39 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
     return 0;
   }
   // --- retrieve nodes ID
-  vector<vtkIdType> nodeIds;
-  nodeIds.clear();
-  nodeIds.push_back(n1->getVtkId());
-  nodeIds.push_back(n4->getVtkId());
-  nodeIds.push_back(n3->getVtkId());
-  nodeIds.push_back(n2->getVtkId());
-  nodeIds.push_back(n5->getVtkId());
-
-  nodeIds.push_back(n41->getVtkId());
-  nodeIds.push_back(n34->getVtkId());
-  nodeIds.push_back(n23->getVtkId());
-  nodeIds.push_back(n12->getVtkId());
-
-  nodeIds.push_back(n15->getVtkId());
-  nodeIds.push_back(n45->getVtkId());
-  nodeIds.push_back(n35->getVtkId());
-  nodeIds.push_back(n25->getVtkId());
+  myNodeIds.resize(13);
+  myNodeIds[0] = n1->getVtkId();
+  myNodeIds[1] = n4->getVtkId();
+  myNodeIds[2] = n3->getVtkId();
+  myNodeIds[3] = n2->getVtkId();
+  myNodeIds[4] = n5->getVtkId();
+
+  myNodeIds[5] = n41->getVtkId();
+  myNodeIds[6] = n34->getVtkId();
+  myNodeIds[7] = n23->getVtkId();
+  myNodeIds[8] = n12->getVtkId();
+
+  myNodeIds[9] = n15->getVtkId();
+  myNodeIds[10] = n45->getVtkId();
+  myNodeIds[11] = n35->getVtkId();
+  myNodeIds[12] = n25->getVtkId();
 
   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-  volvtk->init(nodeIds, this);
+  volvtk->init(myNodeIds, this);
   if (!this->registerElement(ID,volvtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-      myVolumePool->destroy(volvtk);
-      return 0;
-    }
+  {
+    this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+    myVolumePool->destroy(volvtk);
+    return 0;
+  }
   adjustmyCellsCapacity(ID);
   myCells[ID] = volvtk;
   myInfo.myNbQuadPyramids++;
 
-//  if (!registerElement(ID, volvtk)) {
-//    RemoveElement(volvtk, false);
-//    volvtk = NULL;
-//  }
+  //  if (!registerElement(ID, volvtk)) {
+  //    RemoveElement(volvtk, false);
+  //    volvtk = NULL;
+  //  }
   return volvtk;
 }
 
@@ -4283,44 +4265,43 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
     return 0;
   }
   // --- retrieve nodes ID
-  vector<vtkIdType> nodeIds;
-  nodeIds.clear();
-  nodeIds.push_back(n1->getVtkId());
-  nodeIds.push_back(n2->getVtkId());
-  nodeIds.push_back(n3->getVtkId());
+  myNodeIds.resize(15);
+  myNodeIds[0] = n1->getVtkId();
+  myNodeIds[1] = n2->getVtkId();
+  myNodeIds[2] = n3->getVtkId();
 
-  nodeIds.push_back(n4->getVtkId());
-  nodeIds.push_back(n5->getVtkId());
-  nodeIds.push_back(n6->getVtkId());
+  myNodeIds[3] = n4->getVtkId();
+  myNodeIds[4] = n5->getVtkId();
+  myNodeIds[5] = n6->getVtkId();
 
-  nodeIds.push_back(n12->getVtkId());
-  nodeIds.push_back(n23->getVtkId());
-  nodeIds.push_back(n31->getVtkId());
+  myNodeIds[6] = n12->getVtkId();
+  myNodeIds[7] = n23->getVtkId();
+  myNodeIds[8] = n31->getVtkId();
 
-  nodeIds.push_back(n45->getVtkId());
-  nodeIds.push_back(n56->getVtkId());
-  nodeIds.push_back(n64->getVtkId());
+  myNodeIds[9] = n45->getVtkId();
+  myNodeIds[10] = n56->getVtkId();
+  myNodeIds[11] = n64->getVtkId();
 
-  nodeIds.push_back(n14->getVtkId());
-  nodeIds.push_back(n25->getVtkId());
-  nodeIds.push_back(n36->getVtkId());
+  myNodeIds[12] = n14->getVtkId();
+  myNodeIds[13] = n25->getVtkId();
+  myNodeIds[14] = n36->getVtkId();
 
   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-  volvtk->init(nodeIds, this);
+  volvtk->init(myNodeIds, this);
   if (!this->registerElement(ID,volvtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-      myVolumePool->destroy(volvtk);
-      return 0;
-    }
+  {
+    this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+    myVolumePool->destroy(volvtk);
+    return 0;
+  }
   adjustmyCellsCapacity(ID);
   myCells[ID] = volvtk;
   myInfo.myNbQuadPrisms++;
 
-//  if (!registerElement(ID, volvtk)) {
-//    RemoveElement(volvtk, false);
-//    volvtk = NULL;
-//  }
+  //  if (!registerElement(ID, volvtk)) {
+  //    RemoveElement(volvtk, false);
+  //    volvtk = NULL;
+  //  }
   return volvtk;
 }
 
@@ -4426,49 +4407,48 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
     // creation quadratic faces - not implemented
   }
   // --- retrieve nodes ID
-  vector<vtkIdType> nodeIds;
-  nodeIds.clear();
-  nodeIds.push_back(n1->getVtkId());
-  nodeIds.push_back(n4->getVtkId());
-  nodeIds.push_back(n3->getVtkId());
-  nodeIds.push_back(n2->getVtkId());
-
-  nodeIds.push_back(n5->getVtkId());
-  nodeIds.push_back(n8->getVtkId());
-  nodeIds.push_back(n7->getVtkId());
-  nodeIds.push_back(n6->getVtkId());
-
-  nodeIds.push_back(n41->getVtkId());
-  nodeIds.push_back(n34->getVtkId());
-  nodeIds.push_back(n23->getVtkId());
-  nodeIds.push_back(n12->getVtkId());
-
-  nodeIds.push_back(n85->getVtkId());
-  nodeIds.push_back(n78->getVtkId());
-  nodeIds.push_back(n67->getVtkId());
-  nodeIds.push_back(n56->getVtkId());
-
-  nodeIds.push_back(n15->getVtkId());
-  nodeIds.push_back(n48->getVtkId());
-  nodeIds.push_back(n37->getVtkId());
-  nodeIds.push_back(n26->getVtkId());
+  myNodeIds.resize(20);
+  myNodeIds[0] = n1->getVtkId();
+  myNodeIds[1] = n4->getVtkId();
+  myNodeIds[2] = n3->getVtkId();
+  myNodeIds[3] = n2->getVtkId();
+
+  myNodeIds[4] = n5->getVtkId();
+  myNodeIds[5] = n8->getVtkId();
+  myNodeIds[6] = n7->getVtkId();
+  myNodeIds[7] = n6->getVtkId();
+
+  myNodeIds[8] = n41->getVtkId();
+  myNodeIds[9] = n34->getVtkId();
+  myNodeIds[10] = n23->getVtkId();
+  myNodeIds[11] = n12->getVtkId();
+
+  myNodeIds[12] = n85->getVtkId();
+  myNodeIds[13] = n78->getVtkId();
+  myNodeIds[14] = n67->getVtkId();
+  myNodeIds[15] = n56->getVtkId();
+
+  myNodeIds[16] = n15->getVtkId();
+  myNodeIds[17] = n48->getVtkId();
+  myNodeIds[18] = n37->getVtkId();
+  myNodeIds[19] = n26->getVtkId();
 
   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-  volvtk->init(nodeIds, this);
+  volvtk->init(myNodeIds, this);
   if (!this->registerElement(ID,volvtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-      myVolumePool->destroy(volvtk);
-      return 0;
-    }
+  {
+    this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+    myVolumePool->destroy(volvtk);
+    return 0;
+  }
   adjustmyCellsCapacity(ID);
   myCells[ID] = volvtk;
   myInfo.myNbQuadHexas++;
 
-//  if (!registerElement(ID, volvtk)) {
-//    RemoveElement(volvtk, false);
-//    volvtk = NULL;
-//  }
+  //  if (!registerElement(ID, volvtk)) {
+  //    RemoveElement(volvtk, false);
+  //    volvtk = NULL;
+  //  }
   return volvtk;
 }
 
@@ -4599,49 +4579,48 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
     // creation quadratic faces - not implemented
   }
   // --- retrieve nodes ID
-  vector<vtkIdType> nodeIds;
-  nodeIds.clear();
-  nodeIds.push_back(n1->getVtkId());
-  nodeIds.push_back(n4->getVtkId());
-  nodeIds.push_back(n3->getVtkId());
-  nodeIds.push_back(n2->getVtkId());
-
-  nodeIds.push_back(n5->getVtkId());
-  nodeIds.push_back(n8->getVtkId());
-  nodeIds.push_back(n7->getVtkId());
-  nodeIds.push_back(n6->getVtkId());
-
-  nodeIds.push_back(n41->getVtkId());
-  nodeIds.push_back(n34->getVtkId());
-  nodeIds.push_back(n23->getVtkId());
-  nodeIds.push_back(n12->getVtkId());
-
-  nodeIds.push_back(n85->getVtkId());
-  nodeIds.push_back(n78->getVtkId());
-  nodeIds.push_back(n67->getVtkId());
-  nodeIds.push_back(n56->getVtkId());
-
-  nodeIds.push_back(n15->getVtkId());
-  nodeIds.push_back(n48->getVtkId());
-  nodeIds.push_back(n37->getVtkId());
-  nodeIds.push_back(n26->getVtkId());
-
-  nodeIds.push_back(n1256->getVtkId());
-  nodeIds.push_back(n3478->getVtkId());
-  nodeIds.push_back(n1458->getVtkId());
-  nodeIds.push_back(n2367->getVtkId());
-  nodeIds.push_back(n1234->getVtkId());
-  nodeIds.push_back(n5678->getVtkId());
-  nodeIds.push_back(nCenter->getVtkId());
+  myNodeIds.resize(27);
+  myNodeIds[0] = n1->getVtkId();
+  myNodeIds[1] = n4->getVtkId();
+  myNodeIds[2] = n3->getVtkId();
+  myNodeIds[3] = n2->getVtkId();
+
+  myNodeIds[4] = n5->getVtkId();
+  myNodeIds[5] = n8->getVtkId();
+  myNodeIds[6] = n7->getVtkId();
+  myNodeIds[7] = n6->getVtkId();
+
+  myNodeIds[8] = n41->getVtkId();
+  myNodeIds[9] = n34->getVtkId();
+  myNodeIds[10] = n23->getVtkId();
+  myNodeIds[11] = n12->getVtkId();
+
+  myNodeIds[12] = n85->getVtkId();
+  myNodeIds[13] = n78->getVtkId();
+  myNodeIds[14] = n67->getVtkId();
+  myNodeIds[15] = n56->getVtkId();
+
+  myNodeIds[16] = n15->getVtkId();
+  myNodeIds[17] = n48->getVtkId();
+  myNodeIds[18] = n37->getVtkId();
+  myNodeIds[19] = n26->getVtkId();
+
+  myNodeIds[20] = n1256->getVtkId();
+  myNodeIds[21] = n3478->getVtkId();
+  myNodeIds[22] = n1458->getVtkId();
+  myNodeIds[23] = n2367->getVtkId();
+  myNodeIds[24] = n1234->getVtkId();
+  myNodeIds[25] = n5678->getVtkId();
+  myNodeIds[26] = nCenter->getVtkId();
 
   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-  volvtk->init(nodeIds, this);
+  volvtk->init(myNodeIds, this);
   if (!this->registerElement(ID,volvtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-      myVolumePool->destroy(volvtk);
-      return 0;
-    }
+  {
+    this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+    myVolumePool->destroy(volvtk);
+    return 0;
+  }
   adjustmyCellsCapacity(ID);
   myCells[ID] = volvtk;
   myInfo.myNbTriQuadHexas++;
@@ -4655,8 +4634,8 @@ void SMDS_Mesh::updateNodeMinMax()
   myNodeMin = 0;
   if (myNodes.size() == 0)
   {
-        myNodeMax=0;
-        return;
+    myNodeMax=0;
+    return;
   }
   while (!myNodes[myNodeMin] && (myNodeMin<myNodes.size()))
     myNodeMin++;
index e447d059b471077d6ede8edd7904664cf81ea5d5..6b3402d0b3628bd0a43346c768133adfe9e9ed69 100644 (file)
@@ -774,7 +774,7 @@ protected:
   bool registerElement(int ID, SMDS_MeshElement * element);
 
   void addChildrenWithNodes(std::set<const SMDS_MeshElement*>& setOfChildren,
-                            const SMDS_MeshElement * element,
+                            const SMDS_MeshElement *           element,
                             std::set<const SMDS_MeshElement*>& nodes);
 
   inline void adjustmyCellsCapacity(int ID)
@@ -818,8 +818,8 @@ protected:
   //! SMDS_MeshCells refer to vtk cells (vtk id != index in myCells),store reference to this mesh, and sub-shape
   SetOfCells             myCells;
 
-  //! for cells only: index = ID for SMDS users, value = ID in vtkUnstructuredGrid
-  //std::vector<int>       myCellIdSmdsToVtk;
+  //! a buffer to speed up elements addition by excluding some memory allocation
+  std::vector<vtkIdType> myNodeIds;
 
   //! for cells only: index = ID in vtkUnstructuredGrid, value = ID for SMDS users
   std::vector<int>       myCellIdVtkToSmds;
index 8f071e7838dca925a575c8739e0986300fc63547..732c3e64ae2a9a96bf00ddd29c7e37fdfe5d77cf 100644 (file)
@@ -178,6 +178,7 @@ const SMESH_Algo::Features& SMESH_Algo::GetFeatures( const std::string& algoType
 SMESH_Algo::SMESH_Algo (int hypId, int studyId, SMESH_Gen * gen)
   : SMESH_Hypothesis(hypId, studyId, gen)
 {
+  _compatibleAllHypFilter = _compatibleNoAuxHypFilter = NULL;
   _onlyUnaryInput = _requireDiscreteBoundary = _requireShape = true;
   _quadraticMesh = _supportSubmeshes = false;
   _error = COMPERR_OK;
@@ -193,6 +194,8 @@ SMESH_Algo::SMESH_Algo (int hypId, int studyId, SMESH_Gen * gen)
 
 SMESH_Algo::~SMESH_Algo()
 {
+  delete _compatibleNoAuxHypFilter;
+  // delete _compatibleAllHypFilter; -- _compatibleNoAuxHypFilter does it!!!
 }
 
 //=============================================================================
@@ -263,10 +266,9 @@ SMESH_Algo::GetUsedHypothesis(SMESH_Mesh &         aMesh,
 {
   SMESH_Algo* me = const_cast< SMESH_Algo* >( this );
   me->_usedHypList.clear();
-  SMESH_HypoFilter filter;
-  if ( InitCompatibleHypoFilter( filter, ignoreAuxiliary ))
+  if ( const SMESH_HypoFilter* filter = GetCompatibleHypoFilter( ignoreAuxiliary ))
   {
-    aMesh.GetHypotheses( aShape, filter, me->_usedHypList, true );
+    aMesh.GetHypotheses( aShape, *filter, me->_usedHypList, true );
     if ( ignoreAuxiliary && _usedHypList.size() > 1 )
       me->_usedHypList.clear(); //only one compatible hypothesis allowed
   }
@@ -288,9 +290,8 @@ SMESH_Algo::GetAppliedHypothesis(SMESH_Mesh &         aMesh,
 {
   SMESH_Algo* me = const_cast< SMESH_Algo* >( this );
   me->_appliedHypList.clear();
-  SMESH_HypoFilter filter;
-  if ( InitCompatibleHypoFilter( filter, ignoreAuxiliary ))
-    aMesh.GetHypotheses( aShape, filter, me->_appliedHypList, false );
+  if ( const SMESH_HypoFilter* filter = GetCompatibleHypoFilter( ignoreAuxiliary ))
+    aMesh.GetHypotheses( aShape, *filter, me->_appliedHypList, false );
 
   return _appliedHypList;
 }
@@ -410,7 +411,7 @@ bool SMESH_Algo::GetSortedNodesOnEdge(const SMESHDS_Mesh*                   theM
     return false;
 
   SMESHDS_SubMesh * eSubMesh = theMesh->MeshElements( theEdge );
-  if ( !eSubMesh || ( eSubMesh->NbElements()==0 && eSubMesh->NbNodes() == 0))
+  if ( !eSubMesh || ( eSubMesh->NbElements()==0 &&  eSubMesh->NbNodes() == 0))
     return false; // edge is not meshed
 
   int nbNodes = 0;
@@ -457,27 +458,35 @@ bool SMESH_Algo::GetSortedNodesOnEdge(const SMESHDS_Mesh*                   theM
 
 //================================================================================
 /*!
- * \brief Make filter recognize only compatible hypotheses
- * \param theFilter - the filter to initialize
- * \param ignoreAuxiliary - make filter ignore compatible auxiliary hypotheses
+ * \brief Returns the filter recognizing only compatible hypotheses
+ *  \param ignoreAuxiliary - make filter ignore auxiliary hypotheses
+ *  \retval SMESH_HypoFilter* - the filter that can be NULL
  */
 //================================================================================
 
-bool SMESH_Algo::InitCompatibleHypoFilter( SMESH_HypoFilter & theFilter,
-                                           const bool         ignoreAuxiliary) const
+const SMESH_HypoFilter*
+SMESH_Algo::GetCompatibleHypoFilter(const bool ignoreAuxiliary) const
 {
   if ( !_compatibleHypothesis.empty() )
   {
-    theFilter.Init( theFilter.HasName( _compatibleHypothesis[0] ));
-    for ( int i = 1; i < _compatibleHypothesis.size(); ++i )
-      theFilter.Or( theFilter.HasName( _compatibleHypothesis[ i ] ));
-
-    if ( ignoreAuxiliary )
-      theFilter.AndNot( theFilter.IsAuxiliary() );
-
-    return true;
+    if ( !_compatibleAllHypFilter )
+    {
+      SMESH_HypoFilter* filter = new SMESH_HypoFilter();
+      filter->Init( filter->HasName( _compatibleHypothesis[0] ));
+      for ( int i = 1; i < _compatibleHypothesis.size(); ++i )
+        filter->Or( filter->HasName( _compatibleHypothesis[ i ] ));
+
+      SMESH_HypoFilter* filterNoAux = new SMESH_HypoFilter( filter );
+      filterNoAux->AndNot( filterNoAux->IsAuxiliary() );
+
+      // _compatibleNoAuxHypFilter will detele _compatibleAllHypFilter!!!
+      SMESH_Algo* me = const_cast< SMESH_Algo* >( this );
+      me->_compatibleAllHypFilter   = filter;
+      me->_compatibleNoAuxHypFilter = filterNoAux;
+    }
+    return ignoreAuxiliary ? _compatibleNoAuxHypFilter : _compatibleAllHypFilter;
   }
-  return false;
+  return 0;
 }
 
 //================================================================================
@@ -594,6 +603,7 @@ bool SMESH_Algo::isDegenerated( const TopoDS_Edge & E )
  * \param V - the vertex
  * \param meshDS - mesh
  * \retval const SMDS_MeshNode* - found node or NULL
+ * \sa SMESH_MesherHelper::GetSubShapeByNode( const SMDS_MeshNode*, SMESHDS_Mesh* )
  */
 //================================================================================
 
index 8aeaf7bb67636f791f51f7a2ac0ab62f5aef2aeb..4e5dc4afcbe137f27e5510248c4910c4e4290c8b 100644 (file)
@@ -138,6 +138,8 @@ class SMESH_EXPORT SMESH_Algo : public SMESH_Hypothesis
     * \param aShape - the shape
     * \param aStatus - check result
     * \retval bool - true if hypothesis is well defined
+    *
+    * Textual description of a problem can be stored in _comment field.
    */
   virtual bool CheckHypothesis(SMESH_Mesh&                          aMesh,
                                const TopoDS_Shape&                  aShape,
@@ -218,13 +220,12 @@ class SMESH_EXPORT SMESH_Algo : public SMESH_Hypothesis
                        const TopoDS_Shape & aShape,
                        const bool           ignoreAuxiliary=true) const;
   /*!
-   * \brief Make the filter recognize only compatible hypotheses
-   * \param theFilter - the filter to initialize
-   * \param ignoreAuxiliary - make filter ignore compatible auxiliary hypotheses
-   * \retval bool - true if the algo has compatible hypotheses
+   * \brief Returns the filter recognizing only compatible hypotheses
+   *  \param ignoreAuxiliary - make filter ignore compatible auxiliary hypotheses
+   *  \retval SMESH_HypoFilter* - the filter that can be NULL
    */
-  bool InitCompatibleHypoFilter( SMESH_HypoFilter & theFilter,
-                                 const bool         ignoreAuxiliary) const;
+  const SMESH_HypoFilter* GetCompatibleHypoFilter(const bool ignoreAuxiliary) const;
+
   /*!
    * \brief Just return false as the algorithm does not hold parameters values
    */
@@ -408,9 +409,12 @@ public:
 
 protected:
 
+  const SMESH_HypoFilter *              _compatibleAllHypFilter;
+  const SMESH_HypoFilter *              _compatibleNoAuxHypFilter;
   std::vector<std::string>              _compatibleHypothesis;
   std::list<const SMESHDS_Hypothesis *> _appliedHypList;
   std::list<const SMESHDS_Hypothesis *> _usedHypList;
+  
 
   // Algo features influencing which Compute() and how is called:
   // in what turn and with what input shape.
index c8ba34bc33dc1d07aa213dab65459e05aeb88408..864f50c21449346cb49b5ccccdfd2e718d5b4af9 100644 (file)
@@ -232,7 +232,7 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
       if ( aShapesId && aShapeDim > (int)aDim )
         continue;
 
-      SMESH_Algo* algo = GetAlgo( aMesh, aSubShape, &algoShape );
+      SMESH_Algo* algo = GetAlgo( smToCompute, &algoShape );
       if ( algo && !algo->NeedDiscreteBoundary() )
       {
         if ( algo->SupportSubmeshes() )
@@ -288,27 +288,27 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
     // Apply all-dimensional algorithms supporing sub-meshes
     // ======================================================
 
+    std::vector< SMESH_subMesh* > smVec;
     for ( aShapeDim = 0; aShapeDim < 4; ++aShapeDim )
     {
       // ------------------------------------------------
       // sort list of sub-meshes according to mesh order
       // ------------------------------------------------
-      aMesh.SortByMeshOrder( smWithAlgoSupportingSubmeshes[ aShapeDim ] );
+      smVec.assign( smWithAlgoSupportingSubmeshes[ aShapeDim ].begin(),
+                    smWithAlgoSupportingSubmeshes[ aShapeDim ].end() );
+      aMesh.SortByMeshOrder( smVec );
 
       // ------------------------------------------------------------
       // compute sub-meshes with local uni-dimensional algos under
       // sub-meshes with all-dimensional algos
       // ------------------------------------------------------------
-      list< SMESH_subMesh* >::iterator subIt, subEnd;
-      subIt  = smWithAlgoSupportingSubmeshes[ aShapeDim ].begin();
-      subEnd = smWithAlgoSupportingSubmeshes[ aShapeDim ].end();
       // start from lower shapes
-      for ( ; subIt != subEnd; ++subIt )
+      for ( size_t i = 0; i < smVec.size(); ++i )
       {
-        sm = *subIt;
+        sm = smVec[i];
 
         // get a shape the algo is assigned to
-        if ( !GetAlgo( aMesh, sm->GetSubShape(), & algoShape ))
+        if ( !GetAlgo( sm, & algoShape ))
           continue; // strange...
 
         // look for more local algos
@@ -331,7 +331,8 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
             .And( SMESH_HypoFilter::IsApplicableTo( aSubShape ))
             .And( SMESH_HypoFilter::IsMoreLocalThan( algoShape, aMesh ));
 
-          if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( aSubShape, filter, true )) {
+          if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( smToCompute, filter, true))
+          {
             if ( ! subAlgo->NeedDiscreteBoundary() ) continue;
             SMESH_Hypothesis::Hypothesis_Status status;
             if ( subAlgo->CheckHypothesis( aMesh, aSubShape, status ))
@@ -343,10 +344,9 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
       // --------------------------------
       // apply the all-dimensional algos
       // --------------------------------
-      subIt  = smWithAlgoSupportingSubmeshes[ aShapeDim ].begin();
-      for ( ; subIt != subEnd; ++subIt )
+      for ( size_t i = 0; i < smVec.size(); ++i )
       {
-        sm = *subIt;
+        sm = smVec[i];
         if ( sm->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE)
         {
           const TopAbs_ShapeEnum shapeType = sm->GetSubShape().ShapeType();
@@ -478,7 +478,7 @@ bool SMESH_Gen::Evaluate(SMESH_Mesh &          aMesh,
       const int aShapeDim = GetShapeDim( aSubShape );
       if ( aShapeDim < 1 ) break;
       
-      SMESH_Algo* algo = GetAlgo( aMesh, aSubShape );
+      SMESH_Algo* algo = GetAlgo( smToCompute );
       if ( algo && !algo->NeedDiscreteBoundary() ) {
         if ( algo->SupportSubmeshes() ) {
           smWithAlgoSupportingSubmeshes.push_front( smToCompute );
@@ -494,22 +494,22 @@ bool SMESH_Gen::Evaluate(SMESH_Mesh &          aMesh,
     // ------------------------------------------------------------
     // sort list of meshes according to mesh order
     // ------------------------------------------------------------
-    aMesh.SortByMeshOrder( smWithAlgoSupportingSubmeshes );
+    std::vector< SMESH_subMesh* > smVec( smWithAlgoSupportingSubmeshes.begin(),
+                                         smWithAlgoSupportingSubmeshes.end() );
+    aMesh.SortByMeshOrder( smVec );
 
     // ------------------------------------------------------------
     // compute sub-meshes under shapes with algos that DO NOT require
     // Discreteized boundaries and DO support sub-meshes
     // ------------------------------------------------------------
-    list< SMESH_subMesh* >::iterator subIt, subEnd;
-    subIt  = smWithAlgoSupportingSubmeshes.begin();
-    subEnd = smWithAlgoSupportingSubmeshes.end();
     // start from lower shapes
-    for ( ; subIt != subEnd; ++subIt ) {
-      sm = *subIt;
+    for ( size_t i = 0; i < smVec.size(); ++i )
+    {
+      sm = smVec[i];
 
       // get a shape the algo is assigned to
       TopoDS_Shape algoShape;
-      if ( !GetAlgo( aMesh, sm->GetSubShape(), & algoShape ))
+      if ( !GetAlgo( sm, & algoShape ))
         continue; // strange...
 
       // look for more local algos
@@ -526,7 +526,8 @@ bool SMESH_Gen::Evaluate(SMESH_Mesh &          aMesh,
           .And( SMESH_HypoFilter::IsApplicableTo( aSubShape ))
           .And( SMESH_HypoFilter::IsMoreLocalThan( algoShape, aMesh ));
 
-        if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( aSubShape, filter, true )) {
+        if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( smToCompute, filter, true ))
+        {
           if ( ! subAlgo->NeedDiscreteBoundary() ) continue;
           SMESH_Hypothesis::Hypothesis_Status status;
           if ( subAlgo->CheckHypothesis( aMesh, aSubShape, status ))
@@ -538,9 +539,9 @@ bool SMESH_Gen::Evaluate(SMESH_Mesh &          aMesh,
     // ----------------------------------------------------------
     // apply the algos that do not require Discreteized boundaries
     // ----------------------------------------------------------
-    for ( subIt = smWithAlgoSupportingSubmeshes.begin(); subIt != subEnd; ++subIt )
+    for ( size_t i = 0; i < smVec.size(); ++i )
     {
-      sm = *subIt;
+      sm = smVec[i];
       sm->Evaluate(aResMap);
       if ( aShapesId )
         aShapesId->insert( sm->GetId() );
@@ -1014,6 +1015,23 @@ SMESH_Algo *SMESH_Gen::GetAlgo(SMESH_Mesh &         aMesh,
                                const TopoDS_Shape & aShape,
                                TopoDS_Shape*        assignedTo)
 {
+  return GetAlgo( aMesh.GetSubMesh( aShape ), assignedTo );
+}
+
+//=============================================================================
+/*!
+ * Finds algo to mesh a sub-mesh. Optionally returns a shape the found algo is bound to
+ */
+//=============================================================================
+
+SMESH_Algo *SMESH_Gen::GetAlgo(SMESH_subMesh * aSubMesh,
+                               TopoDS_Shape*   assignedTo)
+{
+  if ( !aSubMesh ) return 0;
+
+  const TopoDS_Shape & aShape = aSubMesh->GetSubShape();
+  SMESH_Mesh&          aMesh  = *aSubMesh->GetFather();
+
   SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() );
   filter.And( filter.IsApplicableTo( aShape ));
 
@@ -1021,7 +1039,7 @@ SMESH_Algo *SMESH_Gen::GetAlgo(SMESH_Mesh &         aMesh,
 
   TopoDS_Shape assignedToShape;
   SMESH_Algo* algo =
-    (SMESH_Algo*) aMesh.GetHypothesis( aShape, filter, true, &assignedToShape );
+    (SMESH_Algo*) aMesh.GetHypothesis( aSubMesh, filter, true, &assignedToShape );
 
   if ( algo &&
        aShape.ShapeType() == TopAbs_FACE &&
@@ -1036,7 +1054,7 @@ SMESH_Algo *SMESH_Gen::GetAlgo(SMESH_Mesh &         aMesh,
     filter.AndNot( filter.Is( algo ));
     TopoDS_Shape assignedToShape2;
     SMESH_Algo* algo2 =
-      (SMESH_Algo*) aMesh.GetHypothesis( aShape, filter, true, &assignedToShape2 );
+      (SMESH_Algo*) aMesh.GetHypothesis( aSubMesh, filter, true, &assignedToShape2 );
     if ( algo2 &&                                                  // algo found
          !assignedToShape2.IsSame( aMesh.GetShapeToMesh() ) &&     // algo is local
          ( SMESH_MesherHelper::GetGroupType( assignedToShape2 ) == // algo of the same level
index 5462eacab103d169f65f131890a996a258b58df7..4dac76d43965d1ddab2d68b995d92cba5d233094 100644 (file)
@@ -147,6 +147,7 @@ public:
   { return GetShapeDim( aShape.ShapeType() ); }
 
   SMESH_Algo* GetAlgo(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, TopoDS_Shape* assignedTo=0);
+  SMESH_Algo* GetAlgo(SMESH_subMesh * aSubMesh, TopoDS_Shape* assignedTo=0);
 
   static bool IsGlobalHypothesis(const SMESH_Hypothesis* theHyp, SMESH_Mesh& aMesh);
 
index e19fd11a6b4da5a8c443b373c48fb664947b697c..e5d1670641db19c8d03d0099796eb79772ae1ed0 100644 (file)
@@ -185,6 +185,7 @@ bool SMESH_HypoFilter::IsMoreLocalThanPredicate::IsOk(const SMESH_Hypothesis* aH
 //=======================================================================
 
 SMESH_HypoFilter::SMESH_HypoFilter()
+  : myNbPredicates(0)
 {
 }
 
@@ -194,6 +195,7 @@ SMESH_HypoFilter::SMESH_HypoFilter()
 //=======================================================================
 
 SMESH_HypoFilter::SMESH_HypoFilter( SMESH_HypoPredicate* aPredicate, bool notNegate )
+  : myNbPredicates(0)
 {
   add( notNegate ? AND : AND_NOT, aPredicate );
 }
@@ -352,15 +354,14 @@ SMESH_HypoPredicate* SMESH_HypoFilter::HasType(const int theHypType)
 bool SMESH_HypoFilter::IsOk (const SMESH_Hypothesis* aHyp,
                              const TopoDS_Shape&     aShape) const
 {
-  if ( myPredicates.empty() )
+  if ( IsEmpty() )
     return true;
 
-  bool ok = ( myPredicates.front()->_logical_op <= AND_NOT );
-  list<SMESH_HypoPredicate*>::const_iterator pred = myPredicates.begin();
-  for ( ; pred != myPredicates.end(); ++pred )
+  bool ok = ( myPredicates[0]->_logical_op <= AND_NOT );
+  for ( int i = 0; i < myNbPredicates; ++i )
   {
-    bool ok2 = (*pred)->IsOk( aHyp, aShape );
-    switch ( (*pred)->_logical_op ) {
+    bool ok2 = myPredicates[i]->IsOk( aHyp, aShape );
+    switch ( myPredicates[i]->_logical_op ) {
     case AND:     ok = ok && ok2; break;
     case AND_NOT: ok = ok && !ok2; break;
     case OR:      ok = ok || ok2; break;
@@ -378,10 +379,11 @@ bool SMESH_HypoFilter::IsOk (const SMESH_Hypothesis* aHyp,
 
 SMESH_HypoFilter & SMESH_HypoFilter::Init  ( SMESH_HypoPredicate* aPredicate, bool notNegate )
 {
-  list<SMESH_HypoPredicate*>::const_iterator pred = myPredicates.begin();
-  for ( ; pred != myPredicates.end(); ++pred )
+  SMESH_HypoPredicate** pred = &myPredicates[0];
+  SMESH_HypoPredicate** end  = &myPredicates[myNbPredicates];
+  for ( ; pred != end; ++pred )
     delete *pred;
-  myPredicates.clear();
+  myNbPredicates = 0;
 
   add( notNegate ? AND : AND_NOT, aPredicate );
   return *this;
@@ -395,7 +397,11 @@ SMESH_HypoFilter & SMESH_HypoFilter::Init  ( SMESH_HypoPredicate* aPredicate, bo
 
 SMESH_HypoFilter::~SMESH_HypoFilter()
 {
-  Init(0);
+  SMESH_HypoPredicate** pred = &myPredicates[0];
+  SMESH_HypoPredicate** end  = &myPredicates[myNbPredicates];
+  for ( ; pred != end; ++pred )
+    delete *pred;
+  myNbPredicates = 0;
 }
 
 
index 6ac97e62ddb355f0c7ea2148c27955ba3cfcce6c..7a9c47d7734aa3c3ae48c0d1b962dfbc8f533a11 100644 (file)
@@ -59,7 +59,7 @@ class SMESH_EXPORT SMESH_HypoFilter: public SMESH_HypoPredicate
   // Create and add predicates.
   // Added predicates will be destroyed by filter when it dies
   SMESH_HypoFilter();
-  SMESH_HypoFilter( SMESH_HypoPredicate* aPredicate, bool notNegate = true );
+  explicit SMESH_HypoFilter( SMESH_HypoPredicate* aPredicate, bool notNegate = true );
   // notNegate==false means !aPredicate->IsOk()
   SMESH_HypoFilter & Init  ( SMESH_HypoPredicate* aPredicate, bool notNegate = true );
   SMESH_HypoFilter & And   ( SMESH_HypoPredicate* aPredicate );
@@ -80,7 +80,7 @@ class SMESH_EXPORT SMESH_HypoFilter: public SMESH_HypoPredicate
   static SMESH_HypoPredicate* HasDim(const int theDim);
   static SMESH_HypoPredicate* HasType(const int theHypType);
 
-  bool IsEmpty() const { return myPredicates.empty(); }
+  bool IsEmpty() const { return myNbPredicates == 0; }
 
   /*!
    * \brief check aHyp or/and aShape it is assigned to
@@ -90,7 +90,7 @@ class SMESH_EXPORT SMESH_HypoFilter: public SMESH_HypoPredicate
   /*!
    * \brief return true if contains no predicates
    */
-  bool IsAny() const { return myPredicates.empty(); }
+  bool IsAny() const { return myNbPredicates > 0; }
 
   ~SMESH_HypoFilter();
 
@@ -98,7 +98,9 @@ class SMESH_EXPORT SMESH_HypoFilter: public SMESH_HypoPredicate
  protected:
   // fields
 
-  std::list<SMESH_HypoPredicate*> myPredicates;
+  //std::list<SMESH_HypoPredicate*> myPredicates;
+  SMESH_HypoPredicate* myPredicates[100];
+  int                  myNbPredicates;
 
   // private methods
 
@@ -111,7 +113,7 @@ class SMESH_EXPORT SMESH_HypoFilter: public SMESH_HypoPredicate
   {
     if ( pred ) {
       pred->_logical_op = bool_op;
-      myPredicates.push_back( pred );
+      myPredicates[ myNbPredicates++ ] = pred;
     }
   }
 
index 215f11471d577b845b736de8359c9f450b2e4e60..4454410c4885cea358857e1edca69926d1ffc8bf 100644 (file)
@@ -63,7 +63,8 @@ public:
     HYP_BAD_DIM,      // bad dimension
     HYP_BAD_SUBSHAPE, // shape is neither the main one, nor its sub-shape, nor a group
     HYP_BAD_GEOMETRY, // shape geometry mismatches algorithm's expectation
-    HYP_NEED_SHAPE    // algorithm can work on shape only
+    HYP_NEED_SHAPE,   // algorithm can work on shape only
+    HYP_INCOMPAT_HYPS // several additional hypotheses are incompatible one with other
   };
   static bool IsStatusFatal(Hypothesis_Status theStatus)
   { return theStatus >= HYP_UNKNOWN_FATAL; }
index b3cf4dfda3677f04b029546ba3874aa1095e5d98..7692f9f0e1ff690412fddde109d55e491ada1165 100644 (file)
 //
 #include "SMESH_Mesh.hxx"
 #include "SMESH_MesherHelper.hxx"
-#include "SMESH_subMesh.hxx"
+#include "SMDS_MeshVolume.hxx"
+#include "SMDS_SetIterator.hxx"
+#include "SMESHDS_Document.hxx"
+#include "SMESHDS_Group.hxx"
+#include "SMESHDS_GroupOnGeom.hxx"
+#include "SMESHDS_Script.hxx"
+#include "SMESHDS_TSubMeshHolder.hxx"
 #include "SMESH_Gen.hxx"
-#include "SMESH_Hypothesis.hxx"
 #include "SMESH_Group.hxx"
 #include "SMESH_HypoFilter.hxx"
-#include "SMESHDS_Group.hxx"
-#include "SMESHDS_Script.hxx"
-#include "SMESHDS_GroupOnGeom.hxx"
-#include "SMESHDS_Document.hxx"
-#include "SMDS_MeshVolume.hxx"
-#include "SMDS_SetIterator.hxx"
+#include "SMESH_Hypothesis.hxx"
+#include "SMESH_subMesh.hxx"
 
 #include "utilities.h"
 
@@ -91,6 +92,10 @@ static int MYDEBUG = 0;
 
 typedef SMESH_HypoFilter THypType;
 
+class SMESH_Mesh::SubMeshHolder : public SMESHDS_TSubMeshHolder< SMESH_subMesh >
+{
+};
+
 //=============================================================================
 /*!
  * 
@@ -116,6 +121,7 @@ SMESH_Mesh::SMESH_Mesh(int               theLocalId,
   _shapeDiagonal = 0.0;
   _callUp        = NULL;
   _myMeshDS->ShapeToMesh( PseudoShape() );
+  _subMeshHolder = new SubMeshHolder;
 }
 
 //================================================================================
@@ -138,6 +144,7 @@ SMESH_Mesh::SMESH_Mesh():
   _shapeDiagonal( 0.0 ),
   _callUp( 0 )
 {
+  _subMeshHolder = new SubMeshHolder;
 }
 
 namespace
@@ -185,13 +192,7 @@ SMESH_Mesh::~SMESH_Mesh()
   _mapGroup.clear();
 
   // delete sub-meshes
-  map <int, SMESH_subMesh*>::iterator sm = _mapSubMesh.begin();
-  for ( ; sm != _mapSubMesh.end(); ++sm )
-  {
-    delete sm->second;
-    sm->second = 0;
-  }
-  _mapSubMesh.clear();
+  delete _subMeshHolder;
 
   if ( _callUp) delete _callUp;
   _callUp = 0;
@@ -248,10 +249,7 @@ void SMESH_Mesh::ShapeToMesh(const TopoDS_Shape & aShape)
   {
     // removal of a shape to mesh, delete objects referring to sub-shapes:
     // - sub-meshes
-    map <int, SMESH_subMesh *>::iterator i_sm = _mapSubMesh.begin();
-    for ( ; i_sm != _mapSubMesh.end(); ++i_sm )
-      delete i_sm->second;
-    _mapSubMesh.clear();
+    _subMeshHolder->DeleteAll();
     //  - groups on geometry
     map <int, SMESH_Group *>::iterator i_gr = _mapGroup.begin();
     while ( i_gr != _mapGroup.end() ) {
@@ -603,12 +601,16 @@ SMESH_ComputeErrorPtr SMESH_Mesh::GMFToMesh(const char* theFileName,
 //=============================================================================
 
 SMESH_Hypothesis::Hypothesis_Status
-  SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape,
-                            int                  anHypId  ) throw(SALOME_Exception)
+SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape,
+                          int                  anHypId,
+                          std::string*         anError  ) throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
   if(MYDEBUG) MESSAGE("SMESH_Mesh::AddHypothesis");
 
+  if ( anError )
+    anError->clear();
+
   SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
   if ( !subMesh || !subMesh->GetId())
     return SMESH_Hypothesis::HYP_BAD_SUBSHAPE;
@@ -633,23 +635,36 @@ SMESH_Hypothesis::Hypothesis_Status
     }
   }
 
-  // shape 
+  // shape
 
-  bool isAlgo = ( !anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO );
-  int event = isAlgo ? SMESH_subMesh::ADD_ALGO : SMESH_subMesh::ADD_HYP;
+  bool isAlgo = ( anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO );
+  int   event = isAlgo ? SMESH_subMesh::ADD_ALGO : SMESH_subMesh::ADD_HYP;
 
   SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp);
 
+  if ( anError && SMESH_Hypothesis::IsStatusFatal(ret) && subMesh->GetComputeError() )
+    *anError = subMesh->GetComputeError()->myComment;
+
   // sub-shapes
-  if (!SMESH_Hypothesis::IsStatusFatal(ret) &&
-      anHyp->GetDim() <= SMESH_Gen::GetShapeDim(aSubShape)) // is added on father
+  if ( !SMESH_Hypothesis::IsStatusFatal(ret) &&
+       anHyp->GetDim() <= SMESH_Gen::GetShapeDim(aSubShape)) // is added on father
   {
     event = isAlgo ? SMESH_subMesh::ADD_FATHER_ALGO : SMESH_subMesh::ADD_FATHER_HYP;
 
     SMESH_Hypothesis::Hypothesis_Status ret2 =
-      subMesh->SubMeshesAlgoStateEngine(event, anHyp);
+      subMesh->SubMeshesAlgoStateEngine(event, anHyp, /*exitOnFatal=*/true);
     if (ret2 > ret)
+    {
       ret = ret2;
+      if ( SMESH_Hypothesis::IsStatusFatal( ret ))
+      {
+        if ( anError && subMesh->GetComputeError() )
+          *anError = subMesh->GetComputeError()->myComment;
+        // remove anHyp
+        event = isAlgo ? SMESH_subMesh::REMOVE_ALGO : SMESH_subMesh::REMOVE_HYP;
+        subMesh->AlgoStateEngine(event, anHyp);
+      }
+    }
 
     // check concurent hypotheses on ancestors
     if (ret < SMESH_Hypothesis::HYP_CONCURENT && !isGlobalHyp )
@@ -756,7 +771,6 @@ const list<const SMESHDS_Hypothesis*>&
 SMESH_Mesh::GetHypothesisList(const TopoDS_Shape & aSubShape) const
   throw(SALOME_Exception)
 {
-  Unexpect aCatch(SalomeException);
   return _myMeshDS->GetHypothesis(aSubShape);
 }
 
@@ -776,7 +790,30 @@ const SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const TopoDS_Shape &    aSubS
                                                    const bool              andAncestors,
                                                    TopoDS_Shape*           assignedTo) const
 {
+  return GetHypothesis( const_cast< SMESH_Mesh* >(this)->GetSubMesh( aSubShape ),
+                        aFilter, andAncestors, assignedTo );
+}
+
+//=======================================================================
+/*!
+ * \brief Return the hypothesis assigned to the shape of a sub-mesh
+ *  \param aSubMesh     - the sub-mesh to check
+ *  \param aFilter      - the hypothesis filter
+ *  \param andAncestors - flag to check hypos assigned to ancestors of the shape
+ *  \param assignedTo   - to return the shape the found hypo is assigned to
+ *  \retval SMESH_Hypothesis* - the first hypo passed through aFilter
+ */
+//=======================================================================
+
+const SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const SMESH_subMesh *   aSubMesh,
+                                                   const SMESH_HypoFilter& aFilter,
+                                                   const bool              andAncestors,
+                                                   TopoDS_Shape*           assignedTo) const
+{
+  if ( !aSubMesh ) return 0;
+
   {
+    const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
     const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(aSubShape);
     list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
     for ( ; hyp != hypList.end(); hyp++ ) {
@@ -790,9 +827,12 @@ const SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const TopoDS_Shape &    aSubS
   if ( andAncestors )
   {
     // user sorted submeshes of ancestors, according to stored submesh priority
-    const list<SMESH_subMesh*> smList = getAncestorsSubMeshes( aSubShape );
-    list<SMESH_subMesh*>::const_iterator smIt = smList.begin(); 
-    for ( ; smIt != smList.end(); smIt++ )
+    std::vector< SMESH_subMesh * > & ancestors =
+      const_cast< std::vector< SMESH_subMesh * > & > ( aSubMesh->GetAncestors() );
+    SortByMeshOrder( ancestors );
+
+    vector<SMESH_subMesh*>::const_iterator smIt = ancestors.begin(); 
+    for ( ; smIt != ancestors.end(); smIt++ )
     {
       const TopoDS_Shape& curSh = (*smIt)->GetSubShape();
       const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(curSh);
@@ -811,7 +851,7 @@ const SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const TopoDS_Shape &    aSubS
 
 //================================================================================
 /*!
- * \brief Return hypothesis assigned to the shape
+ * \brief Return hypotheses assigned to the shape
   * \param aSubShape - the shape to check
   * \param aFilter - the hypothesis filter
   * \param aHypList - the list of the found hypotheses
@@ -826,6 +866,29 @@ int SMESH_Mesh::GetHypotheses(const TopoDS_Shape &                aSubShape,
                               const bool                          andAncestors,
                               list< TopoDS_Shape > *              assignedTo/*=0*/) const
 {
+  return GetHypotheses( const_cast< SMESH_Mesh* >(this)->GetSubMesh( aSubShape ),
+                        aFilter, aHypList, andAncestors, assignedTo );
+}
+
+//================================================================================
+/*!
+ * \brief Return hypotheses assigned to the shape of a sub-mesh
+  * \param aSubShape - the sub-mesh to check
+  * \param aFilter - the hypothesis filter
+  * \param aHypList - the list of the found hypotheses
+  * \param andAncestors - flag to check hypos assigned to ancestors of the shape
+  * \retval int - number of unique hypos in aHypList
+ */
+//================================================================================
+
+int SMESH_Mesh::GetHypotheses(const SMESH_subMesh *               aSubMesh,
+                              const SMESH_HypoFilter&             aFilter,
+                              list <const SMESHDS_Hypothesis * >& aHypList,
+                              const bool                          andAncestors,
+                              list< TopoDS_Shape > *              assignedTo/*=0*/) const
+{
+  if ( !aSubMesh ) return 0;
+
   set<string> hypTypes; // to exclude same type hypos from the result list
   int nbHyps = 0;
 
@@ -843,45 +906,51 @@ int SMESH_Mesh::GetHypotheses(const TopoDS_Shape &                aSubShape,
 
   // get hypos from aSubShape
   {
+    const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
     const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(aSubShape);
     for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ )
-      if ( aFilter.IsOk (cSMESH_Hyp( *hyp ), aSubShape) &&
-           ( cSMESH_Hyp(*hyp)->IsAuxiliary() || !mainHypFound ) &&
-           hypTypes.insert( (*hyp)->GetName() ).second )
+    {
+      const SMESH_Hypothesis* h = cSMESH_Hyp( *hyp );
+      if (( aFilter.IsOk( h, aSubShape )) &&
+          ( h->IsAuxiliary() || !mainHypFound ) &&
+          ( h->IsAuxiliary() || hypTypes.insert( h->GetName() ).second ))
       {
         aHypList.push_back( *hyp );
         nbHyps++;
-        if ( !cSMESH_Hyp(*hyp)->IsAuxiliary() )
+        if ( !h->IsAuxiliary() )
           mainHypFound = true;
         if ( assignedTo ) assignedTo->push_back( aSubShape );
       }
+    }
   }
 
   // get hypos from ancestors of aSubShape
   if ( andAncestors )
   {
-    TopTools_MapOfShape map;
-
     // user sorted submeshes of ancestors, according to stored submesh priority
-    const list<SMESH_subMesh*> smList = getAncestorsSubMeshes( aSubShape );
-    list<SMESH_subMesh*>::const_iterator smIt = smList.begin(); 
-    for ( ; smIt != smList.end(); smIt++ )
+    std::vector< SMESH_subMesh * > & ancestors =
+      const_cast< std::vector< SMESH_subMesh * > & > ( aSubMesh->GetAncestors() );
+    SortByMeshOrder( ancestors );
+
+    vector<SMESH_subMesh*>::const_iterator smIt = ancestors.begin();
+    for ( ; smIt != ancestors.end(); smIt++ )
     {
       const TopoDS_Shape& curSh = (*smIt)->GetSubShape();
-     if ( !map.Add( curSh ))
-        continue;
       const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(curSh);
       for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ )
-        if (aFilter.IsOk( cSMESH_Hyp( *hyp ), curSh ) &&
-            ( cSMESH_Hyp(*hyp)->IsAuxiliary() || !mainHypFound ) &&
-            hypTypes.insert( (*hyp)->GetName() ).second )
+      {
+        const SMESH_Hypothesis* h = cSMESH_Hyp( *hyp );
+        if (( aFilter.IsOk( h, curSh )) &&
+            ( h->IsAuxiliary() || !mainHypFound ) &&
+            ( h->IsAuxiliary() || hypTypes.insert( h->GetName() ).second ))
         {
           aHypList.push_back( *hyp );
           nbHyps++;
-          if ( !cSMESH_Hyp(*hyp)->IsAuxiliary() )
+          if ( !h->IsAuxiliary() )
             mainHypFound = true;
           if ( assignedTo ) assignedTo->push_back( curSh );
         }
+      }
     }
   }
   return nbHyps;
@@ -937,9 +1006,9 @@ void SMESH_Mesh::ClearLog() throw(SALOME_Exception)
 SMESH_subMesh *SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape)
   throw(SALOME_Exception)
 {
-  Unexpect aCatch(SalomeException);
-  SMESH_subMesh *aSubMesh;
   int index = _myMeshDS->ShapeToIndex(aSubShape);
+  if ( !index && aSubShape.IsNull() )
+    return 0;
 
   // for submeshes on GEOM Group
   if (( !index || index > _nbSubShapes ) && aSubShape.ShapeType() == TopAbs_COMPOUND ) {
@@ -952,18 +1021,29 @@ SMESH_subMesh *SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape)
         fillAncestorsMap( _myMeshDS->IndexToShape( ++_nbSubShapes ));
     }
   }
-//   if ( !index )
-//     return NULL; // neither sub-shape nor a group
+  // if ( !index )
+  //   return NULL; // neither sub-shape nor a group
 
-  map <int, SMESH_subMesh *>::iterator i_sm = _mapSubMesh.find(index);
-  if ( i_sm != _mapSubMesh.end())
-  {
-    aSubMesh = i_sm->second;
-  }
-  else
+  SMESH_subMesh* aSubMesh = _subMeshHolder->Get( index );
+  if ( !aSubMesh )
   {
     aSubMesh = new SMESH_subMesh(index, this, _myMeshDS, aSubShape);
-    _mapSubMesh[index] = aSubMesh;
+    _subMeshHolder->Add( index, aSubMesh );
+
+    // include non-computable sub-meshes in SMESH_subMesh::_ancestors of sub-submeshes
+    switch ( aSubShape.ShapeType() ) {
+    case TopAbs_COMPOUND:
+    case TopAbs_WIRE:
+    case TopAbs_SHELL:
+      for ( TopoDS_Iterator subIt( aSubShape ); subIt.More(); subIt.Next() )
+      {
+        SMESH_subMesh* sm = GetSubMesh( subIt.Value() );
+        SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*inclideSelf=*/true);
+        while ( smIt->more() )
+          smIt->next()->ClearAncestors();
+      }
+    default:;
+    }
   }
   return aSubMesh;
 }
@@ -978,17 +1058,10 @@ SMESH_subMesh *SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape)
 SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const TopoDS_Shape & aSubShape) const
   throw(SALOME_Exception)
 {
-  Unexpect aCatch(SalomeException);
-  SMESH_subMesh *aSubMesh = NULL;
-  
   int index = _myMeshDS->ShapeToIndex(aSubShape);
-
-  map <int, SMESH_subMesh *>::const_iterator i_sm = _mapSubMesh.find(index);
-  if ( i_sm != _mapSubMesh.end())
-    aSubMesh = i_sm->second;
-
-  return aSubMesh;
+  return GetSubMeshContaining( index );
 }
+
 //=============================================================================
 /*!
  * Get the SMESH_subMesh object implementation. Dont create it, return null
@@ -999,13 +1072,11 @@ SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const TopoDS_Shape & aSubShape)
 SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const int aShapeID) const
 throw(SALOME_Exception)
 {
-  Unexpect aCatch(SalomeException);
-  
-  map <int, SMESH_subMesh *>::const_iterator i_sm = _mapSubMesh.find(aShapeID);
-  if (i_sm == _mapSubMesh.end())
-    return NULL;
-  return i_sm->second;
+  SMESH_subMesh *aSubMesh = _subMeshHolder->Get( aShapeID );
+
+  return aSubMesh;
 }
+
 //================================================================================
 /*!
  * \brief Return submeshes of groups containing the given sub-shape
@@ -1016,7 +1087,6 @@ list<SMESH_subMesh*>
 SMESH_Mesh::GetGroupSubMeshesContaining(const TopoDS_Shape & aSubShape) const
   throw(SALOME_Exception)
 {
-  Unexpect aCatch(SalomeException);
   list<SMESH_subMesh*> found;
 
   SMESH_subMesh * subMesh = GetSubMeshContaining(aSubShape);
@@ -1024,13 +1094,14 @@ SMESH_Mesh::GetGroupSubMeshesContaining(const TopoDS_Shape & aSubShape) const
     return found;
 
   // submeshes of groups have max IDs, so search from the map end
-  map<int, SMESH_subMesh *>::const_reverse_iterator i_sm;
-  for ( i_sm = _mapSubMesh.rbegin(); i_sm != _mapSubMesh.rend(); ++i_sm) {
-    SMESHDS_SubMesh * ds = i_sm->second->GetSubMeshDS();
+SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator( /*reverse=*/true ) );
+  while ( smIt->more() ) {
+    SMESH_subMesh*    sm = smIt->next();
+    SMESHDS_SubMesh * ds = sm->GetSubMeshDS();
     if ( ds && ds->IsComplexSubmesh() ) {
-      if ( SMESH_MesherHelper::IsSubShape( aSubShape, i_sm->second->GetSubShape() ))
+      if ( SMESH_MesherHelper::IsSubShape( aSubShape, sm->GetSubShape() ))
       {
-        found.push_back( i_sm->second );
+        found.push_back( sm );
         //break;
       }
     } else {
@@ -1040,7 +1111,7 @@ SMESH_Mesh::GetGroupSubMeshesContaining(const TopoDS_Shape & aSubShape) const
 
   if ( found.empty() ) // maybe the main shape is a COMPOUND (issue 0021530)
   {
-    if ( SMESH_subMesh * mainSM = GetSubMeshContaining(1))
+    if ( SMESH_subMesh * mainSM = GetSubMeshContaining(1) )
       if ( mainSM->GetSubShape().ShapeType() == TopAbs_COMPOUND )
       {
         TopoDS_Iterator it( mainSM->GetSubShape() );
@@ -1065,9 +1136,7 @@ bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp,
   if ( !aSubMesh || !aSubMesh->IsApplicableHypotesis( hyp ))
     return false;
 
-  const TopoDS_Shape & aSubShape = const_cast<SMESH_subMesh*>( aSubMesh )->GetSubShape();
-
-  SMESH_Algo *algo = _gen->GetAlgo(*this, aSubShape );
+  SMESH_Algo *algo = aSubMesh->GetAlgo();
 
   // algorithm
   if (anHyp->GetType() > SMESHDS_Hypothesis::PARAM_ALGO)
@@ -1077,17 +1146,15 @@ bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp,
   if (algo)
   {
     // look trough hypotheses used by algo
-    SMESH_HypoFilter hypoKind;
-    if ( algo->InitCompatibleHypoFilter( hypoKind, !hyp->IsAuxiliary() )) {
+    const SMESH_HypoFilter* hypoKind;
+    if (( hypoKind = algo->GetCompatibleHypoFilter( !hyp->IsAuxiliary() ))) {
       list <const SMESHDS_Hypothesis * > usedHyps;
-      if ( GetHypotheses( aSubShape, hypoKind, usedHyps, true ))
+      if ( GetHypotheses( aSubMesh, *hypoKind, usedHyps, true ))
         return ( find( usedHyps.begin(), usedHyps.end(), anHyp ) != usedHyps.end() );
     }
   }
 
-  // look through all assigned hypotheses
-  //SMESH_HypoFilter filter( SMESH_HypoFilter::Is( hyp ));
-  return false; //GetHypothesis( aSubShape, filter, true );
+  return false;
 }
 
 //=============================================================================
@@ -1096,22 +1163,20 @@ bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp,
  */
 //=============================================================================
 
-const list < SMESH_subMesh * >&
-SMESH_Mesh::GetSubMeshUsingHypothesis(SMESHDS_Hypothesis * anHyp)
-  throw(SALOME_Exception)
-{
-  Unexpect aCatch(SalomeException);
-  if(MYDEBUG) MESSAGE("SMESH_Mesh::GetSubMeshUsingHypothesis");
-  map < int, SMESH_subMesh * >::iterator itsm;
-  _subMeshesUsingHypothesisList.clear();
-  for (itsm = _mapSubMesh.begin(); itsm != _mapSubMesh.end(); itsm++)
-  {
-    SMESH_subMesh *aSubMesh = (*itsm).second;
-    if ( IsUsedHypothesis ( anHyp, aSubMesh ))
-      _subMeshesUsingHypothesisList.push_back(aSubMesh);
-  }
-  return _subMeshesUsingHypothesisList;
-}
+// const list < SMESH_subMesh * >&
+// SMESH_Mesh::GetSubMeshUsingHypothesis(SMESHDS_Hypothesis * anHyp)
+//   throw(SALOME_Exception)
+// {
+//   _subMeshesUsingHypothesisList.clear();
+//   SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() );
+//   while ( smIt->more() )
+//   {
+//     SMESH_subMesh* aSubMesh = smIt->next();
+//     if ( IsUsedHypothesis ( anHyp, aSubMesh ))
+//       _subMeshesUsingHypothesisList.push_back( aSubMesh );
+//   }
+//   return _subMeshesUsingHypothesisList;
+// }
 
 //=======================================================================
 //function : NotifySubMeshesHypothesisModification
@@ -1128,48 +1193,51 @@ void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* h
   if (_callUp)
     _callUp->HypothesisModified();
 
-  const SMESH_Algo *foundAlgo = 0;
-  SMESH_HypoFilter algoKind, compatibleHypoKind;
+  SMESH_Algo *algo;
+  const SMESH_HypoFilter* compatibleHypoKind;
   list <const SMESHDS_Hypothesis * > usedHyps;
 
+  // keep sub-meshes not to miss ones whose state can change due to notifying others
+  vector< SMESH_subMesh* > smToNotify;
 
-  map < int, SMESH_subMesh * >::iterator itsm;
-  for (itsm = _mapSubMesh.begin(); itsm != _mapSubMesh.end(); itsm++)
+  SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() );
+  while ( smIt->more() )
   {
-    SMESH_subMesh *aSubMesh = (*itsm).second;
-    if ( aSubMesh->IsApplicableHypotesis( hyp ))
+    SMESH_subMesh* aSubMesh = smIt->next();
+
+    // if aSubMesh meshing depends on hyp,
+    // we call aSubMesh->AlgoStateEngine( MODIF_HYP, hyp ) that causes either
+    // 1) clearing of already computed aSubMesh or
+    // 2) changing algo_state from MISSING_HYP to HYP_OK when parameters of hyp becomes valid,
+    // other possible changes are not interesting. (IPAL0052457 - assigning hyp performance pb)
+    if ( aSubMesh->GetComputeState() != SMESH_subMesh::COMPUTE_OK &&
+         aSubMesh->GetComputeState() != SMESH_subMesh::FAILED_TO_COMPUTE &&
+         aSubMesh->GetAlgoState()    != SMESH_subMesh::MISSING_HYP )
+      continue;
+
+    const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
+
+    if (( aSubMesh->IsApplicableHypotesis( hyp )) &&
+        ( algo = aSubMesh->GetAlgo() )            &&
+        ( compatibleHypoKind = algo->GetCompatibleHypoFilter( !hyp->IsAuxiliary() )) &&
+        ( compatibleHypoKind->IsOk( hyp, aSubShape )))
     {
-      const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
-
-      if ( !foundAlgo ) // init filter for algo search
-        algoKind.Init( THypType::IsAlgo() ).And( THypType::IsApplicableTo( aSubShape ));
-      
-      const SMESH_Algo *algo = static_cast<const SMESH_Algo*>
-        ( GetHypothesis( aSubShape, algoKind, true ));
-
-      if ( algo )
+      // check if hyp is used by algo
+      usedHyps.clear();
+      if ( GetHypotheses( aSubMesh, *compatibleHypoKind, usedHyps, true ) &&
+           find( usedHyps.begin(), usedHyps.end(), hyp ) != usedHyps.end() )
       {
-        bool sameAlgo = ( algo == foundAlgo );
-        if ( !sameAlgo && foundAlgo )
-          sameAlgo = ( strcmp( algo->GetName(), foundAlgo->GetName() ) == 0);
-
-        if ( !sameAlgo ) { // init filter for used hypos search
-          if ( !algo->InitCompatibleHypoFilter( compatibleHypoKind, !hyp->IsAuxiliary() ))
-            continue; // algo does not use any hypothesis
-          foundAlgo = algo;
-        }
-
-        // check if hyp is used by algo
-        usedHyps.clear();
-        if ( GetHypotheses( aSubShape, compatibleHypoKind, usedHyps, true ) &&
-             find( usedHyps.begin(), usedHyps.end(), hyp ) != usedHyps.end() )
-        {
-          aSubMesh->AlgoStateEngine(SMESH_subMesh::MODIF_HYP,
-                                    const_cast< SMESH_Hypothesis*>( hyp ));
-        }
+        smToNotify.push_back( aSubMesh );
       }
     }
   }
+
+  for ( size_t i = 0; i < smToNotify.size(); ++i )
+  {
+    smToNotify[i]->AlgoStateEngine(SMESH_subMesh::MODIF_HYP,
+                                   const_cast< SMESH_Hypothesis*>( hyp ));
+  }
+
   HasModificationsToDiscard(); // to reset _isModified flag if mesh becomes empty
   GetMeshDS()->Modified();
 }
@@ -1221,21 +1289,23 @@ 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;
-  map <int, SMESH_subMesh*>::const_iterator i_sm = _mapSubMesh.begin();
-  for ( ; i_sm != _mapSubMesh.end() ; ++i_sm )
-    switch ( i_sm->second->GetSubShape().ShapeType() )
+SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() );
+  while ( smIt->more() )
+  {
+    const SMESH_subMesh* aSubMesh = smIt->next();
+    switch ( aSubMesh->GetSubShape().ShapeType() )
     {
     case TopAbs_EDGE:
     case TopAbs_FACE:
     case TopAbs_SOLID:
-      if ( i_sm->second->IsMeshComputed() )
+      if ( aSubMesh->IsMeshComputed() )
         hasComputed = true;
       else
         hasNotComputed = true;
       if ( hasComputed && hasNotComputed)
         return true;
     }
-
+  }
   if ( NbNodes() < 1 )
     const_cast<SMESH_Mesh*>(this)->_isModified = false;
 
@@ -2147,7 +2217,6 @@ const TListOfListOfInt& SMESH_Mesh::GetMeshOrder() const
 
 void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape)
 {
-
   int desType, ancType;
   if ( !theShape.IsSame( GetShapeToMesh()) && theShape.ShapeType() == TopAbs_COMPOUND )
   {
@@ -2168,6 +2237,7 @@ void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape)
           ancList.InsertBefore( theShape, ancIt );
       }
   }
+  else // else added for 52457: Addition of hypotheses is 8 time longer than meshing
   {
     for ( desType = TopAbs_VERTEX; desType > TopAbs_COMPOUND; desType-- )
       for ( ancType = desType - 1; ancType >= TopAbs_COMPOUND; ancType-- )
@@ -2179,9 +2249,11 @@ void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape)
   // visit COMPOUNDs inside a COMPOUND that are not reachable by TopExp_Explorer
   if ( theShape.ShapeType() == TopAbs_COMPOUND )
   {
-    for ( TopoDS_Iterator sIt(theShape); sIt.More(); sIt.Next() )
-      if ( sIt.Value().ShapeType() == TopAbs_COMPOUND )
-        fillAncestorsMap( sIt.Value() );
+    TopoDS_Iterator sIt(theShape);
+    if ( sIt.More() && sIt.Value().ShapeType() == TopAbs_COMPOUND )
+      for ( ; sIt.More(); sIt.Next() )
+        if ( sIt.Value().ShapeType() == TopAbs_COMPOUND )
+          fillAncestorsMap( sIt.Value() );
   }
 }
 
@@ -2193,38 +2265,59 @@ void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape)
  */
 //=============================================================================
 
-bool SMESH_Mesh::SortByMeshOrder(list<SMESH_subMesh*>& theListToSort) const
+ bool SMESH_Mesh::SortByMeshOrder(std::vector<SMESH_subMesh*>& theListToSort) const
 {
   if ( !_mySubMeshOrder.size() || theListToSort.size() < 2)
     return true;
   
   bool res = false;
-  list<SMESH_subMesh*> onlyOrderedList;
+  vector<SMESH_subMesh*> onlyOrderedList;
   // collect all ordered submeshes in one list as pointers
   // and get their positions within theListToSort
-  typedef list<SMESH_subMesh*>::iterator TPosInList;
+  typedef vector<SMESH_subMesh*>::iterator TPosInList;
   map< int, TPosInList > sortedPos;
   TPosInList smBeg = theListToSort.begin(), smEnd = theListToSort.end();
   TListOfListOfInt::const_iterator listIdsIt = _mySubMeshOrder.begin();
-  for( ; listIdsIt != _mySubMeshOrder.end(); listIdsIt++) {
+  for( ; listIdsIt != _mySubMeshOrder.end(); listIdsIt++)
+  {
     const TListOfInt& listOfId = *listIdsIt;
+    // convert sm ids to sm's
+    vector<SMESH_subMesh*> smVec;
     TListOfInt::const_iterator idIt = listOfId.begin();
     for ( ; idIt != listOfId.end(); idIt++ ) {
       if ( SMESH_subMesh * sm = GetSubMeshContaining( *idIt )) {
-        TPosInList smPos = find( smBeg, smEnd, sm );
-        if ( smPos != smEnd ) {
-          onlyOrderedList.push_back( sm );
-          sortedPos[ distance( smBeg, smPos )] = smPos;
+        if ( sm->GetSubMeshDS() && sm->GetSubMeshDS()->IsComplexSubmesh() )
+        {
+          SMESHDS_SubMeshIteratorPtr smdsIt = sm->GetSubMeshDS()->GetSubMeshIterator();
+          while ( smdsIt->more() )
+          {
+            const SMESHDS_SubMesh* smDS = smdsIt->next();
+            if (( sm = GetSubMeshContaining( smDS->GetID() )))
+              smVec.push_back( sm );
+          }
+        }
+        else
+        {
+          smVec.push_back( sm );
         }
       }
     }
+    // find smVec items in theListToSort
+    for ( size_t i = 0; i < smVec.size(); ++i )
+    {
+      TPosInList smPos = find( smBeg, smEnd, smVec[i] );
+      if ( smPos != smEnd ) {
+        onlyOrderedList.push_back( smVec[i] );
+        sortedPos[ distance( smBeg, smPos )] = smPos;
+      }
+    }
   }
   if (onlyOrderedList.size() < 2)
     return res;
   res = true;
 
-  list<SMESH_subMesh*>::iterator onlyBIt = onlyOrderedList.begin();
-  list<SMESH_subMesh*>::iterator onlyEIt = onlyOrderedList.end();
+  vector<SMESH_subMesh*>::iterator onlyBIt = onlyOrderedList.begin();
+  vector<SMESH_subMesh*>::iterator onlyEIt = onlyOrderedList.end();
 
   // iterate on ordered submeshes and insert them in detected positions
   map< int, TPosInList >::iterator i_pos = sortedPos.begin();
@@ -2266,17 +2359,15 @@ bool SMESH_Mesh::IsOrderOK( const SMESH_subMesh* smBefore,
  */
 //=============================================================================
 
-list<SMESH_subMesh*>
-SMESH_Mesh::getAncestorsSubMeshes (const TopoDS_Shape& theSubShape) const
+void SMESH_Mesh::getAncestorsSubMeshes (const TopoDS_Shape&            theSubShape,
+                                        std::vector< SMESH_subMesh* >& theSubMeshes) const
 {
-  list<SMESH_subMesh*> listOfSubMesh;
+  theSubMeshes.clear();
   TopTools_ListIteratorOfListOfShape it( GetAncestors( theSubShape ));
   for (; it.More(); it.Next() )
     if ( SMESH_subMesh* sm = GetSubMeshContaining( it.Value() ))
-      listOfSubMesh.push_back(sm);
+      theSubMeshes.push_back(sm);
 
   // sort submeshes according to stored mesh order
-  SortByMeshOrder( listOfSubMesh );
-
-  return listOfSubMesh;
+  SortByMeshOrder( theSubMeshes );
 }
index 19818878e248be311e0806510d47e17caba43ccd..0cf3e0949f34410fb09f32f085c7dae772a0a9f9 100644 (file)
@@ -126,7 +126,7 @@ public:
                                   bool        theMakeRequiredGroups = true );
 
   SMESH_Hypothesis::Hypothesis_Status
-  AddHypothesis(const TopoDS_Shape & aSubShape, int anHypId)
+  AddHypothesis(const TopoDS_Shape & aSubShape, int anHypId, std::string* error=0)
     throw(SALOME_Exception);
   
   SMESH_Hypothesis::Hypothesis_Status
@@ -148,6 +148,17 @@ public:
                     const bool                               andAncestors,
                     std::list< TopoDS_Shape > *              assignedTo=0) const;
 
+  const SMESH_Hypothesis * GetHypothesis(const SMESH_subMesh *   aSubMesh,
+                                         const SMESH_HypoFilter& aFilter,
+                                         const bool              andAncestors,
+                                         TopoDS_Shape*           assignedTo=0) const;
+  
+  int GetHypotheses(const SMESH_subMesh *                    aSubMesh,
+                    const SMESH_HypoFilter&                  aFilter,
+                    std::list< const SMESHDS_Hypothesis * >& aHypList,
+                    const bool                               andAncestors,
+                    std::list< TopoDS_Shape > *              assignedTo=0) const;
+
   SMESH_Hypothesis * GetHypothesis(const int aHypID) const;
 
   const std::list<SMESHDS_Command*> & GetLog() throw(SALOME_Exception);
@@ -182,8 +193,8 @@ public:
    */
   void NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* theChangedHyp);
 
-  const std::list < SMESH_subMesh * >&
-  GetSubMeshUsingHypothesis(SMESHDS_Hypothesis * anHyp) throw(SALOME_Exception);
+  // const std::list < SMESH_subMesh * >&
+  // GetSubMeshUsingHypothesis(SMESHDS_Hypothesis * anHyp) throw(SALOME_Exception);
   /*!
    * \brief Return True if anHyp is used to mesh aSubShape
    */
@@ -322,7 +333,7 @@ public:
   const TListOfListOfInt& GetMeshOrder() const;
 
   // sort submeshes according to stored mesh order
-  bool SortByMeshOrder(std::list<SMESH_subMesh*>& theListToSort) const;
+  bool SortByMeshOrder(std::vector<SMESH_subMesh*>& theListToSort) const;
 
   // return true if given order of sub-meshes is OK
   bool IsOrderOK( const SMESH_subMesh* smBefore,
@@ -333,8 +344,8 @@ public:
 private:
 
   void fillAncestorsMap(const TopoDS_Shape& theShape);
-  std::list<SMESH_subMesh*> getAncestorsSubMeshes
-    (const TopoDS_Shape& theSubShape) const;
+  void getAncestorsSubMeshes(const TopoDS_Shape&            theSubShape,
+                             std::vector< SMESH_subMesh* >& theSubMeshes) const;
   
 protected:
   int                        _id;           // id given by creator (unique within the creator instance)
@@ -342,12 +353,14 @@ protected:
   int                        _groupId;      // id generator for group objects
   int                        _nbSubShapes;  // initial nb of subshapes in the shape to mesh
   bool                       _isShapeToMesh;// set to true when a shape is given (only once)
-  std::list <SMESH_subMesh*> _subMeshesUsingHypothesisList;
+  //std::list <SMESH_subMesh*> _subMeshesUsingHypothesisList;
   SMESHDS_Document *         _myDocument;
   SMESHDS_Mesh *             _myMeshDS;
   SMESH_Gen *                _gen;
-  std::map <int, SMESH_subMesh*> _mapSubMesh;
-  std::map <int, SMESH_Group*>   _mapGroup;
+  std::map <int, SMESH_Group*> _mapGroup;
+
+  class SubMeshHolder;
+  SubMeshHolder*             _subMeshHolder;
   
   bool                       _isAutoColor;
   bool                       _isModified; //!< modified since last total re-compute, issue 0020693
@@ -356,11 +369,13 @@ protected:
   
   TopTools_IndexedDataMapOfShapeListOfShape _mapAncestors;
 
+  mutable std::vector<SMESH_subMesh*> _ancestorSubMeshes; // to speed up GetHypothes[ei]s()
+
   TListOfListOfInt           _mySubMeshOrder;
 
   // Struct calling methods at CORBA API implementation level, used to
-  // 1) make an upper level be consistent with a lower one when group removal
-  // is invoked by hyp modification (issue 0020918)
+  // 1) make an upper level (SMESH_I) be consistent with a lower one (SMESH)
+  // when group removal is invoked by hyp modification (issue 0020918)
   // 2) to forget not loaded mesh data at hyp modification
   TCallUp*                    _callUp;
 
index 8b6afbfe54c6d0cdb047e6f68223cdcca501a548..e216b2e7448f86b80edb40a310c0fba76caab60f 100644 (file)
@@ -518,14 +518,12 @@ int SMESH_MeshEditor::FindShape (const SMDS_MeshElement * theElem)
   }
   else
   {
-    const map<int,SMESHDS_SubMesh*>& id2sm = GetMeshDS()->SubMeshes();
-    map<int,SMESHDS_SubMesh*>::const_iterator id_sm = id2sm.begin();
-    for ( ; id_sm != id2sm.end(); ++id_sm )
-      if ( id_sm->second->Contains( theElem ))
-        return id_sm->first;
+    SMESHDS_SubMeshIteratorPtr smIt = GetMeshDS()->SubMeshes();
+    while ( const SMESHDS_SubMesh* sm = smIt->next() )
+      if ( sm->Contains( theElem ))
+        return sm->GetID();
   }
 
-  //MESSAGE ("::FindShape() - SHAPE NOT FOUND")
   return 0;
 }
 
@@ -1245,6 +1243,92 @@ int SMESH_MeshEditor::Reorient2D (TIDSortedElemSet &       theFaces,
   return nbReori;
 }
 
+//================================================================================
+/*!
+ * \brief Reorient faces basing on orientation of adjacent volumes.
+ * \param theFaces - faces to reorient. If empty, all mesh faces are treated.
+ * \param theVolumes - reference volumes.
+ * \param theOutsideNormal - to orient faces to have their normal
+ *        pointing either \a outside or \a inside the adjacent volumes.
+ * \return number of reoriented faces.
+ */
+//================================================================================
+
+int SMESH_MeshEditor::Reorient2DBy3D (TIDSortedElemSet & theFaces,
+                                      TIDSortedElemSet & theVolumes,
+                                      const bool         theOutsideNormal)
+{
+  int nbReori = 0;
+
+  SMDS_ElemIteratorPtr faceIt;
+  if ( theFaces.empty() )
+    faceIt = GetMeshDS()->elementsIterator( SMDSAbs_Face );
+  else
+    faceIt = elemSetIterator( theFaces );
+
+  vector< const SMDS_MeshNode* > faceNodes;
+  TIDSortedElemSet checkedVolumes;
+  set< const SMDS_MeshNode* > faceNodesSet;
+  SMDS_VolumeTool volumeTool;
+
+  while ( faceIt->more() ) // loop on given faces
+  {
+    const SMDS_MeshElement* face = faceIt->next();
+    if ( face->GetType() != SMDSAbs_Face )
+      continue;
+
+    const int nbCornersNodes = face->NbCornerNodes();
+    faceNodes.assign( face->begin_nodes(), face->end_nodes() );
+
+    checkedVolumes.clear();
+    SMDS_ElemIteratorPtr vIt = faceNodes[ 0 ]->GetInverseElementIterator( SMDSAbs_Volume );
+    while ( vIt->more() )
+    {
+      const SMDS_MeshElement* volume = vIt->next();
+
+      if ( !checkedVolumes.insert( volume ).second )
+        continue;
+      if ( !theVolumes.empty() && !theVolumes.count( volume ))
+        continue;
+
+      // is volume adjacent?
+      bool allNodesCommon = true;
+      for ( int iN = 1; iN < nbCornersNodes && allNodesCommon; ++iN )
+        allNodesCommon = ( volume->GetNodeIndex( faceNodes[ iN ]) > -1 );
+      if ( !allNodesCommon )
+        continue;
+
+      // get nodes of a corresponding volume facet
+      faceNodesSet.clear();
+      faceNodesSet.insert( faceNodes.begin(), faceNodes.end() );
+      volumeTool.Set( volume );
+      int facetID = volumeTool.GetFaceIndex( faceNodesSet );
+      if ( facetID < 0 ) continue;
+      volumeTool.SetExternalNormal();
+      const SMDS_MeshNode** facetNodes = volumeTool.GetFaceNodes( facetID );
+
+      // compare order of faceNodes and facetNodes
+      const int iQ = 1 + ( nbCornersNodes < faceNodes.size() );
+      int iNN[2];
+      for ( int i = 0; i < 2; ++i )
+      {
+        const SMDS_MeshNode* n = facetNodes[ i*iQ ];
+        for ( int iN = 0; iN < nbCornersNodes; ++iN )
+          if ( faceNodes[ iN ] == n )
+          {
+            iNN[ i ] = iN;
+            break;
+          }
+      }
+      bool isOutside = Abs( iNN[0]-iNN[1] ) == 1 ? iNN[0] < iNN[1] : iNN[0] > iNN[1];
+      if ( isOutside != theOutsideNormal )
+        nbReori += Reorient( face );
+    }
+  }  // loop on given faces
+
+  return nbReori;
+}
+
 //=======================================================================
 //function : getBadRate
 //purpose  :
@@ -6428,7 +6512,7 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
 
   if ( ( theMakeGroups && theCopy ) ||
        ( theMakeGroups && theTargetMesh ) )
-    newGroupIDs = generateGroups( srcNodes, srcElems, groupPostfix, theTargetMesh );
+    newGroupIDs = generateGroups( srcNodes, srcElems, groupPostfix, theTargetMesh, false );
 
   return newGroupIDs;
 }
@@ -6436,9 +6520,11 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
 //=======================================================================
 /*!
  * \brief Create groups of elements made during transformation
- * \param nodeGens - nodes making corresponding myLastCreatedNodes
- * \param elemGens - elements making corresponding myLastCreatedElems
- * \param postfix - to append to names of new groups
+ *  \param nodeGens - nodes making corresponding myLastCreatedNodes
+ *  \param elemGens - elements making corresponding myLastCreatedElems
+ *  \param postfix - to append to names of new groups
+ *  \param targetMesh - mesh to create groups in
+ *  \param topPresent - is there "top" elements that are created by sweeping
  */
 //=======================================================================
 
@@ -6446,14 +6532,17 @@ SMESH_MeshEditor::PGroupIDs
 SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens,
                                  const SMESH_SequenceOfElemPtr& elemGens,
                                  const std::string&             postfix,
-                                 SMESH_Mesh*                    targetMesh)
+                                 SMESH_Mesh*                    targetMesh,
+                                 const bool                     topPresent)
 {
   PGroupIDs newGroupIDs( new list<int> );
   SMESH_Mesh* mesh = targetMesh ? targetMesh : GetMesh();
 
   // Sort existing groups by types and collect their names
 
-  // to store an old group and a generated new ones
+  // containers to store an old group and generated new ones;
+  // 1st new group is for result elems of different type than a source one;
+  // 2nd new group is for same type result elems ("top" group at extrusion)
   using boost::tuple;
   using boost::make_tuple;
   typedef tuple< SMESHDS_GroupBase*, SMESHDS_Group*, SMESHDS_Group* > TOldNewGroup;
@@ -6483,6 +6572,7 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens,
 
   // Loop on nodes and elements to add them in new groups
 
+  vector< const SMDS_MeshElement* > resultElems;
   for ( int isNodes = 0; isNodes < 2; ++isNodes )
   {
     const SMESH_SequenceOfElemPtr& gens  = isNodes ? nodeGens : elemGens;
@@ -6505,7 +6595,7 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens,
         continue;
       }
       // collect all elements made by the iElem-th sourceElem
-      list< const SMDS_MeshElement* > resultElems;
+      resultElems.clear();
       if ( const SMDS_MeshElement* resElem = elems( iElem ))
         if ( resElem != sourceElem )
           resultElems.push_back( resElem );
@@ -6514,25 +6604,23 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens,
           if ( resElem != sourceElem )
             resultElems.push_back( resElem );
 
-      // there must be a top element
       const SMDS_MeshElement* topElem = 0;
-      if ( isNodes )
+      if ( isNodes ) // there must be a top element
       {
         topElem = resultElems.back();
         resultElems.pop_back();
       }
       else
       {
-        list< const SMDS_MeshElement* >::reverse_iterator resElemIt = resultElems.rbegin();
+        vector< const SMDS_MeshElement* >::reverse_iterator resElemIt = resultElems.rbegin();
         for ( ; resElemIt != resultElems.rend() ; ++resElemIt )
           if ( (*resElemIt)->GetType() == sourceElem->GetType() )
           {
             topElem = *resElemIt;
-            resultElems.erase( --(resElemIt.base()) ); // erase *resElemIt
+            *resElemIt = 0; // erase *resElemIt
             break;
           }
       }
-
       // add resultElems to groups originted from ones the sourceElem belongs to
       list< TOldNewGroup >::iterator gOldNew, gLast = groupsOldNew.end();
       for ( gOldNew = groupsOldNew.begin(); gOldNew != gLast; ++gOldNew )
@@ -6542,16 +6630,17 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens,
         {
           // fill in a new group
           SMDS_MeshGroup & newGroup = gOldNew->get<1>()->SMDSGroup();
-          list< const SMDS_MeshElement* >::iterator resLast = resultElems.end(), resElemIt;
+          vector< const SMDS_MeshElement* >::iterator resLast = resultElems.end(), resElemIt;
           for ( resElemIt = resultElems.begin(); resElemIt != resLast; ++resElemIt )
-            newGroup.Add( *resElemIt );
+            if ( *resElemIt )
+              newGroup.Add( *resElemIt );
 
           // fill a "top" group
           if ( topElem )
           {
             SMDS_MeshGroup & newTopGroup = gOldNew->get<2>()->SMDSGroup();
             newTopGroup.Add( topElem );
-          }
+         }
         }
       }
     } // loop on created elements
@@ -6565,7 +6654,6 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens,
     SMESHDS_GroupBase* oldGroupDS =   orderedOldNewGroups[i]->get<0>();
     SMESHDS_Group*   newGroups[2] = { orderedOldNewGroups[i]->get<1>(),
                                       orderedOldNewGroups[i]->get<2>() };
-    const int nbNewGroups = !newGroups[0]->IsEmpty() + !newGroups[1]->IsEmpty();
     for ( int is2nd = 0; is2nd < 2; ++is2nd )
     {
       SMESHDS_Group* newGroupDS = newGroups[ is2nd ];
@@ -6579,11 +6667,21 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens,
         newGroupDS->SetType( newGroupDS->GetElements()->next()->GetType() );
 
         // make a name
-        const bool isTop = ( nbNewGroups == 2 &&
+        const bool isTop = ( topPresent &&
                              newGroupDS->GetType() == oldGroupDS->GetType() &&
                              is2nd );
 
         string name = oldGroupDS->GetStoreName();
+        { // remove trailing whitespaces (issue 22599)
+          size_t size = name.size();
+          while ( size > 1 && isspace( name[ size-1 ]))
+            --size;
+          if ( size != name.size() )
+          {
+            name.resize( size );
+            oldGroupDS->SetStoreName( name.c_str() );
+          }
+        }
         if ( !targetMesh ) {
           string suffix = ( isTop ? "top": postfix.c_str() );
           name += "_";
index 865a395c96c2884f1d246553eaa53dc08d451d9d..5adb43a4132c2fef50e9d3b54adf2c07b0ab8a19 100644 (file)
@@ -126,6 +126,12 @@ public:
   // Reverse theFaces whose orientation to be same as that of theFace
   // oriented according to theDirection. Return nb of reoriented faces
 
+  int Reorient2DBy3D (TIDSortedElemSet & theFaces,
+                      TIDSortedElemSet & theVolumes,
+                      const bool         theOutsideNormal);
+  // Reorient faces basing on orientation of adjacent volumes.
+  // Return nb of reoriented faces
+
   /*!
    * \brief Fuse neighbour triangles into quadrangles.
    * \param theElems     - The triangles to be fused.
@@ -605,11 +611,14 @@ public:
    * \param nodeGens - nodes making corresponding myLastCreatedNodes
    * \param elemGens - elements making corresponding myLastCreatedElems
    * \param postfix - to append to names of new groups
+   * \param targetMesh - mesh to create groups in
+   * \param topPresent - is there "top" elements that are created by sweeping
    */
   PGroupIDs generateGroups(const SMESH_SequenceOfElemPtr& nodeGens,
                            const SMESH_SequenceOfElemPtr& elemGens,
                            const std::string&             postfix,
-                           SMESH_Mesh*                    targetMesh=0);
+                           SMESH_Mesh*                    targetMesh=0,
+                           const bool                     topPresent=true);
   /*!
    * \brief Create elements by sweeping an element
    * \param elem - element to sweep
index d41ff05787741281e1ecb822fb3b89566b6aed2d..31f2d88b7b98a25c5d8339de5f334be10b009709 100644 (file)
@@ -380,10 +380,13 @@ void SMESH_MesherHelper::AddTLinkNode(const SMDS_MeshNode* n1,
  */
 //================================================================================
 
-void SMESH_MesherHelper::AddTLinks(const SMDS_MeshEdge* edge)
+bool SMESH_MesherHelper::AddTLinks(const SMDS_MeshEdge* edge)
 {
-  if ( edge->IsQuadratic() )
+  if ( edge && edge->IsQuadratic() )
     AddTLinkNode(edge->GetNode(0), edge->GetNode(1), edge->GetNode(2));
+  else
+    return false;
+  return true;
 }
 
 //================================================================================
@@ -392,8 +395,9 @@ void SMESH_MesherHelper::AddTLinks(const SMDS_MeshEdge* edge)
  */
 //================================================================================
 
-void SMESH_MesherHelper::AddTLinks(const SMDS_MeshFace* f)
+bool SMESH_MesherHelper::AddTLinks(const SMDS_MeshFace* f)
 {
+  bool isQuad = true;
   if ( !f->IsPoly() )
     switch ( f->NbNodes() ) {
     case 7:
@@ -417,7 +421,9 @@ void SMESH_MesherHelper::AddTLinks(const SMDS_MeshFace* f)
       AddTLinkNode(f->GetNode(2),f->GetNode(3),f->GetNode(6));
       AddTLinkNode(f->GetNode(3),f->GetNode(0),f->GetNode(7)); break;
     default:;
+      isQuad = false;
     }
+  return isQuad;
 }
 
 //================================================================================
@@ -426,7 +432,7 @@ void SMESH_MesherHelper::AddTLinks(const SMDS_MeshFace* f)
  */
 //================================================================================
 
-void SMESH_MesherHelper::AddTLinks(const SMDS_MeshVolume* volume)
+bool SMESH_MesherHelper::AddTLinks(const SMDS_MeshVolume* volume)
 {
   if ( volume->IsQuadratic() )
   {
@@ -460,7 +466,9 @@ void SMESH_MesherHelper::AddTLinks(const SMDS_MeshVolume* volume)
                          nFCenter ));
       }
     }
+    return true;
   }
+  return false;
 }
 
 //================================================================================
@@ -2328,11 +2336,12 @@ bool SMESH_MesherHelper::LoadNodeColumns(TParam2ColumnMap &            theParam2
           while ( ++u_n != sortedBaseNN.end() && !isNodeInSubMesh( u_n->second, faceSubMesh ));
           sortedBaseNN.erase( sortedBaseNN.begin(), u_n );
         }
-        if ( u_n = --sortedBaseNN.end(), !isNodeInSubMesh( u_n->second, faceSubMesh ))
-        {
-          while ( u_n != sortedBaseNN.begin() && !isNodeInSubMesh( (--u_n)->second, faceSubMesh ));
-          sortedBaseNN.erase( ++u_n, sortedBaseNN.end() );
-        }
+        if ( !sortedBaseNN.empty() )
+          if ( u_n = --sortedBaseNN.end(), !isNodeInSubMesh( u_n->second, faceSubMesh ))
+          {
+            while ( u_n != sortedBaseNN.begin() && !isNodeInSubMesh( (--u_n)->second, faceSubMesh ));
+            sortedBaseNN.erase( ++u_n, sortedBaseNN.end() );
+          }
         if ( sortedBaseNN.empty() ) continue;
       }
 
@@ -2349,7 +2358,7 @@ bool SMESH_MesherHelper::LoadNodeColumns(TParam2ColumnMap &            theParam2
         u2nn->second.push_back( u_n->second );
       }
     }
-    if ( theParam2ColumnMap.empty() )
+    if ( theParam2ColumnMap.size() < 2 )
       return false;
   }
 
@@ -2732,24 +2741,22 @@ double SMESH_MesherHelper::MaxTolerance( const TopoDS_Shape& shape )
  */
 //================================================================================
 
-double SMESH_MesherHelper::GetAngle( const TopoDS_Edge & theE1,
-                                     const TopoDS_Edge & theE2,
-                                     const TopoDS_Face & theFace,
-                                     gp_Vec*             theFaceNormal)
+double SMESH_MesherHelper::GetAngle( const TopoDS_Edge &   theE1,
+                                     const TopoDS_Edge &   theE2,
+                                     const TopoDS_Face &   theFace,
+                                     const TopoDS_Vertex & theCommonV,
+                                     gp_Vec*               theFaceNormal)
 {
   double angle = 1e100;
   try
   {
-    TopoDS_Vertex vCommon;
-    if ( !TopExp::CommonVertex( theE1, theE2, vCommon ))
-      return angle;
     double f,l;
     Handle(Geom_Curve)     c1 = BRep_Tool::Curve( theE1, f,l );
     Handle(Geom_Curve)     c2 = BRep_Tool::Curve( theE2, f,l );
     Handle(Geom2d_Curve) c2d1 = BRep_Tool::CurveOnSurface( theE1, theFace, f,l );
     Handle(Geom_Surface) surf = BRep_Tool::Surface( theFace );
-    double                 p1 = BRep_Tool::Parameter( vCommon, theE1 );
-    double                 p2 = BRep_Tool::Parameter( vCommon, theE2 );
+    double                 p1 = BRep_Tool::Parameter( theCommonV, theE1 );
+    double                 p2 = BRep_Tool::Parameter( theCommonV, theE2 );
     if ( c1.IsNull() || c2.IsNull() )
       return angle;
     gp_XY uv = c2d1->Value( p1 ).XY();
@@ -2758,10 +2765,10 @@ double SMESH_MesherHelper::GetAngle( const TopoDS_Edge & theE1,
     gp_Vec vec1, vec2, vecRef = du ^ dv;
     int  nbLoops = 0;
     double p1tmp = p1;
-    while ( vecRef.SquareMagnitude() < std::numeric_limits<double>::min() )
+    while ( vecRef.SquareMagnitude() < 1e-25 )
     {
       double dp = ( l - f ) / 1000.;
-      p1tmp += dp * (( Abs( p1 - f ) > Abs( p1 - l )) ? +1. : -1.);
+      p1tmp += dp * (( Abs( p1 - f ) > Abs( p1 - l )) ? -1. : +1.);
       uv = c2d1->Value( p1tmp ).XY();
       surf->D1( uv.X(), uv.Y(), p, du, dv );
       vecRef = du ^ dv;
index 0c05c442510383894820d45b656dfaaf8971b892..1540751f58e80980b55b10d3258ee67ca602670b 100644 (file)
@@ -130,6 +130,7 @@ class SMESH_EXPORT SMESH_MesherHelper
    * \param node - the node
    * \param meshDS - mesh DS
    * \retval TopoDS_Shape - found support shape
+   * \sa SMESH_Algo::VertexNode( const TopoDS_Vertex&, SMESHDS_Mesh* )
    */
   static TopoDS_Shape GetSubShapeByNode(const SMDS_MeshNode* node,
                                         const SMESHDS_Mesh*  meshDS);
@@ -218,7 +219,8 @@ class SMESH_EXPORT SMESH_MesherHelper
   static double MaxTolerance( const TopoDS_Shape& shape );
 
   static double GetAngle( const TopoDS_Edge & E1, const TopoDS_Edge & E2,
-                          const TopoDS_Face & F, gp_Vec* faceNormal=0);
+                          const TopoDS_Face & F,  const TopoDS_Vertex & V,
+                          gp_Vec* faceNormal=0);
 
   static bool IsClosedEdge( const TopoDS_Edge& anEdge );
 
@@ -559,13 +561,20 @@ public:
   { return IsRealSeam( GetMeshDS()->ShapeToIndex( subShape)); }
   /*!
    * \brief Check if the shape set through IsQuadraticSubMesh() or SetSubShape()
-   *        has a seam edge
-    * \retval bool - true if it has
+   *        has a seam edge, i.e. an edge that has two parametric representations
+   *        on a surface
+   *  \retval bool - true if it has
    */
   bool HasSeam() const { return !mySeamShapeIds.empty(); }
+  /*!
+   * \brief Check if the shape set through IsQuadraticSubMesh() or SetSubShape()
+   *        has a seam edge that encounters twice in a wire
+   *  \retval bool - true if it has
+   */
+  bool HasRealSeam() const { return HasSeam() && ( *mySeamShapeIds.begin() < 0 ); }
   /*!
    * \brief Return index of periodic parametric direction of a closed face
-    * \retval int - 1 for U, 2 for V direction
+    \retval int - 1 for U, 2 for V direction
    */
   int GetPeriodicIndex() const { return myParIndex; }
   /*!
@@ -628,9 +637,9 @@ public:
   void AddTLinkNodeMap(const TLinkNodeMap& aMap)
     { myTLinkNodeMap.insert(aMap.begin(), aMap.end()); }
 
-  void AddTLinks(const SMDS_MeshEdge*   edge);
-  void AddTLinks(const SMDS_MeshFace*   face);
-  void AddTLinks(const SMDS_MeshVolume* vol);
+  bool AddTLinks(const SMDS_MeshEdge*   edge);
+  bool AddTLinks(const SMDS_MeshFace*   face);
+  bool AddTLinks(const SMDS_MeshVolume* vol);
 
   /**
    * Returns myTLinkNodeMap
index af13d4548c7fed9612a140ae4ccaa5081c251e63..75d26244d4b88a7ca74356cbad42cb0f85be903f 100644 (file)
@@ -86,20 +86,15 @@ typedef map< const SMDS_MeshElement*, int > TNodePointIDMap;
 
 #define smdsNode( elem ) static_cast<const SMDS_MeshNode*>( elem )
 
-//=======================================================================
-//function : SMESH_Pattern
-//purpose  : 
-//=======================================================================
-
-SMESH_Pattern::SMESH_Pattern ()
+namespace
 {
-}
+  
 //=======================================================================
 //function : getInt
 //purpose  : 
 //=======================================================================
 
-static inline int getInt( const char * theSring )
+inline int getInt( const char * theSring )
 {
   if ( *theSring < '0' || *theSring > '9' )
     return -1;
@@ -119,7 +114,7 @@ static inline int getInt( const char * theSring )
 //purpose  : 
 //=======================================================================
 
-static inline double getDouble( const char * theSring )
+inline double getDouble( const char * theSring )
 {
   char *ptr;
   return strtod( theSring, &ptr );
@@ -131,9 +126,9 @@ static inline double getDouble( const char * theSring )
 //           Return the number of the found tokens
 //=======================================================================
 
-static int readLine (list <const char*> & theFields,
-                     const char*        & theLineBeg,
-                     const bool           theClearFields )
+int readLine (list <const char*> & theFields,
+              const char*        & theLineBeg,
+              const bool           theClearFields )
 {
   if ( theClearFields )
     theFields.clear();
@@ -206,6 +201,65 @@ static int readLine (list <const char*> & theFields,
   return nbRead;
 }
 
+//=======================================================================
+//function : isRealSeam
+//purpose  : return true if an EDGE encounters twice in a FACE
+//=======================================================================
+
+// bool isRealSeam( const TopoDS_Edge& e, const TopoDS_Face& f )
+// {
+//   if ( BRep_Tool::IsClosed( e, f ))
+//   {
+//     int nb = 0;
+//     for (TopExp_Explorer exp( f, TopAbs_EDGE ); exp.More(); exp.Next())
+//       if ( exp.Current().IsSame( e ))
+//         if ( ++nb == 2 )
+//           return true;
+//   }
+//   return false;
+// }
+
+//=======================================================================
+//function : loadVE
+//purpose  : load VERTEXes and EDGEs in a map. Return nb loaded VERTEXes
+//=======================================================================
+
+int loadVE( const list< TopoDS_Edge > &          eList,
+            TopTools_IndexedMapOfOrientedShape & map )
+{
+  list< TopoDS_Edge >::const_iterator eIt = eList.begin();
+  // vertices
+  int nbV;
+  for ( eIt = eList.begin(); eIt != eList.end(); eIt++ )
+  {
+    nbV = map.Extent();
+    map.Add( TopExp::FirstVertex( *eIt, true ));
+    bool added = ( nbV < map.Extent() );
+    if ( !added ) { // vertex encountered twice
+      // a seam vertex have two corresponding key points
+      map.Add( TopExp::FirstVertex( *eIt, true ).Reversed());
+    }
+  }
+  nbV = map.Extent();
+
+  // edges
+  for ( eIt = eList.begin(); eIt != eList.end(); eIt++ )
+    map.Add( *eIt );
+
+  return nbV;
+}
+
+} // namespace
+
+//=======================================================================
+//function : SMESH_Pattern
+//purpose  :
+//=======================================================================
+
+SMESH_Pattern::SMESH_Pattern ()
+{
+}
+
 //=======================================================================
 //function : Load
 //purpose  : Load a pattern from <theFile>
@@ -647,31 +701,34 @@ bool SMESH_Pattern::Load (SMESH_Mesh*        theMesh,
 
     // Load shapes in the consequent order and count nb of points
 
-    // vertices
-    for ( elIt = eList.begin(); elIt != eList.end(); elIt++ ) {
-      int nbV = myShapeIDMap.Extent();
-      myShapeIDMap.Add( TopExp::FirstVertex( *elIt, true ));
-      bool added = ( nbV < myShapeIDMap.Extent() );
-      if ( !added ) { // vertex encountered twice
-        // a seam vertex have two corresponding key points
-        myShapeIDMap.Add( TopExp::FirstVertex( *elIt, true ).Reversed());
-        ++nbNodes;
-      }
+    loadVE( eList, myShapeIDMap );
+    myShapeIDMap.Add( face );
+
+    nbNodes += myShapeIDMap.Extent() - 1;
+
+    for ( elIt = eList.begin(); elIt != eList.end(); elIt++ )
       if ( SMESHDS_SubMesh * eSubMesh = aMeshDS->MeshElements( *elIt ))
         nbNodes += eSubMesh->NbNodes() + 1;
-    }
-    // edges
-    for ( elIt = eList.begin(); elIt != eList.end(); elIt++ )
-      myShapeIDMap.Add( *elIt );
-    // the face
-    myShapeIDMap.Add( face );
 
     myPoints.resize( nbNodes );
 
     // Load U of points on edges
 
-    for ( elIt = eList.begin(); elIt != eList.end(); elIt++ )
+    list<int>::iterator nbEinW = myNbKeyPntInBoundary.begin();
+    int iE = 0;
+    vector< TopoDS_Edge > eVec;
+    for ( elIt = eList.begin(); elIt != eList.end(); elIt++, iE++ )
     {
+      if ( isClosed && ( iE == 0 || iE == *nbEinW ))
+      {
+        // new wire begins; put EDGEs in eVec
+        list<TopoDS_Edge>::iterator eEnd = elIt;
+        std::advance( eEnd, *nbEinW );
+        eVec.assign( elIt, eEnd );
+        if ( iE > 0 )
+          ++nbEinW;
+        iE = 0;
+      }
       TopoDS_Edge & edge = *elIt;
       list< TPoint* > & ePoints = getShapePoints( edge );
       double f, l;
@@ -698,13 +755,8 @@ bool SMESH_Pattern::Load (SMESH_Mesh*        theMesh,
             TopoDS_Shape & v = is2 ? v2 : v1;
             if ( helper.IsRealSeam( v ) ) {
               // reverse or not depending on orientation of adjacent seam
-              TopoDS_Edge seam;
-              list<TopoDS_Edge>::iterator eIt2 = elIt;
-              if ( is2 )
-                seam = ( ++eIt2 == eList.end() ? eList.front() : *eIt2 );
-              else
-                seam = ( eIt2 == eList.begin() ? eList.back() : *(--eIt2) );
-              if ( seam.Orientation() == TopAbs_REVERSED )
+              int iSeam = helper.WrapIndex( iE + ( is2 ? +1 : -1 ), eVec.size() );
+              if ( eVec[ iSeam ].Orientation() == TopAbs_REVERSED )
                 v.Reverse();
             }
           }
@@ -999,6 +1051,7 @@ void SMESH_Pattern::computeUVOnEdge (const TopoDS_Edge&      theEdge,
     BRep_Tool::CurveOnSurface( theEdge, TopoDS::Face( myShape ), f, l );
 
   ePoints.back()->myInitU = 1.0;
+  //ePoints.front()->myInitU = 0.0; //myUV = C2d->Value( isForward ? f : l ).XY();
   list< TPoint* >::const_iterator pIt = ePoints.begin();
   for ( pIt++; pIt != ePoints.end(); pIt++ )
   {
@@ -2387,33 +2440,7 @@ bool SMESH_Pattern::Apply (const TopoDS_Face&   theFace,
   }
 
   // here shapes get IDs, for the outer wire IDs are OK
-  list<TopoDS_Edge>::iterator elIt = eList.begin();
-  for ( ; elIt != eList.end(); elIt++ ) {
-    myShapeIDMap.Add( TopExp::FirstVertex( *elIt, true ));
-    bool isClosed1 = BRep_Tool::IsClosed( *elIt, theFace );
-    // BEGIN: jfa for bug 0019943
-    if (isClosed1) {
-      isClosed1 = false;
-      for (TopExp_Explorer expw (theFace, TopAbs_WIRE); expw.More() && !isClosed1; expw.Next()) {
-        const TopoDS_Wire& wire = TopoDS::Wire(expw.Current());
-        int nbe = 0;
-        for (BRepTools_WireExplorer we (wire, theFace); we.More() && !isClosed1; we.Next()) {
-          if (we.Current().IsSame(*elIt)) {
-            nbe++;
-            if (nbe == 2) isClosed1 = true;
-          }
-        }
-      }
-    }
-    // END: jfa for bug 0019943
-    if (isClosed1)
-      myShapeIDMap.Add( TopExp::LastVertex( *elIt, true ));// vertex orienation is REVERSED
-  }
-  int nbVertices = myShapeIDMap.Extent();
-
-  for ( elIt = eList.begin(); elIt != eList.end(); elIt++ )
-    myShapeIDMap.Add( *elIt );
-
+  int nbVertices = loadVE( eList, myShapeIDMap );
   myShapeIDMap.Add( face );
 
   if ( myShapeIDToPointsMap.size() != myShapeIDMap.Extent() ) {
@@ -2425,10 +2452,11 @@ bool SMESH_Pattern::Apply (const TopoDS_Face&   theFace,
   list< list< TPoint* > > edgesPointsList;
   edgesPointsList.push_back( list< TPoint* >() );
   list< TPoint* > * edgesPoints = & edgesPointsList.back();
-  list< TPoint* >::iterator pIt;
+  list< TPoint* >::iterator pIt, pEnd;
 
   // compute UV of points on the outer wire
   int iE, nbEdgesInOuterWire = nbVertexInWires.front();
+  list< TopoDS_Edge >::iterator elIt;
   for (iE = 0, elIt = eList.begin();
        iE < nbEdgesInOuterWire && elIt != eList.end();
        iE++, elIt++ )
@@ -2543,14 +2571,24 @@ bool SMESH_Pattern::Apply (const TopoDS_Face&   theFace,
     // re-fill myShapeIDMap - all shapes get good IDs
 
     myShapeIDMap.Clear();
-    for ( elIt = eList.begin(); elIt != eList.end(); elIt++ )
-      myShapeIDMap.Add( TopExp::FirstVertex( *elIt, true ));
-    for ( elIt = eList.begin(); elIt != eList.end(); elIt++ )
-      myShapeIDMap.Add( *elIt );
+    nbVertices = loadVE( eList, myShapeIDMap );
     myShapeIDMap.Add( face );
 
   } // there are inner wires
 
+  // Set XYZ of on-vertex points
+
+  // for ( int iV = 1; iV <= nbVertices; ++iV )
+  // {
+  //   const TopoDS_Vertex&    V = TopoDS::Vertex( myShapeIDMap( iV ));
+  //   list< TPoint* > & vPoints = getShapePoints( iV );
+  //   if ( !vPoints.empty() )
+  //   {
+  //     //vPoints.front()->myUV  = BRep_Tool::Parameters( V, theFace ).XY();
+  //     vPoints.front()->myXYZ = BRep_Tool::Pnt( V );
+  //   }
+  // }
+
   // Compute XYZ of on-edge points
 
   TopLoc_Location loc;
@@ -2558,8 +2596,7 @@ bool SMESH_Pattern::Apply (const TopoDS_Face&   theFace,
   {
     BRepAdaptor_Curve C3d( *elIt );
     list< TPoint* > & ePoints = getShapePoints( iE++ );
-    pIt = ePoints.begin();
-    for ( pIt++; pIt != ePoints.end(); pIt++ )
+    for ( pIt = ++ePoints.begin(), pEnd = ePoints.end(); pIt != pEnd; pIt++ )
     {
       TPoint* point = *pIt;
       point->myXYZ = C3d.Value( point->myU );
@@ -3881,13 +3918,97 @@ void SMESH_Pattern::clearMesh(SMESH_Mesh* theMesh) const
   }
 }
 
+//=======================================================================
+//function : findExistingNodes
+//purpose  : fills nodes vector with nodes existing on a given shape (IMP 22368)
+//           Returns true if all nodes for all points on S are found
+//=======================================================================
+
+bool SMESH_Pattern::findExistingNodes( SMESH_Mesh*                      mesh,
+                                       const TopoDS_Shape&              S,
+                                       const std::list< TPoint* > &     points,
+                                       vector< const SMDS_MeshNode* > & nodesVector)
+{
+  if ( S.IsNull() || points.empty() )
+    return false;
+
+  SMESHDS_Mesh* aMeshDS = mesh->GetMeshDS();
+
+  switch ( S.ShapeType() )
+  {
+  case TopAbs_VERTEX:
+  {
+    int pIndex = points.back() - &myPoints[0];
+    if ( !nodesVector[ pIndex ] )
+      nodesVector[ pIndex ] = SMESH_Algo::VertexNode( TopoDS::Vertex( S ), aMeshDS );
+    return nodesVector[ pIndex ];
+  }
+  case TopAbs_EDGE:
+  {
+    const TopoDS_Edge& edge = TopoDS::Edge( S );
+    map< double, const SMDS_MeshNode* > paramsOfNodes;
+    if ( !SMESH_Algo::GetSortedNodesOnEdge( aMeshDS, edge,
+                                            /*ignoreMediumNodes=*/false,
+                                            paramsOfNodes )
+         || paramsOfNodes.size() < 3 )
+      break;
+    // points on VERTEXes are included with wrong myU
+    list< TPoint* >::const_reverse_iterator pItR = ++points.rbegin();
+    list< TPoint* >::const_iterator         pItF = ++points.begin();
+    const bool isForward = ( (*pItF)->myU < (*pItR)->myU );
+    map< double, const SMDS_MeshNode* >::iterator u2n    = ++paramsOfNodes.begin();
+    map< double, const SMDS_MeshNode* >::iterator u2nEnd = --paramsOfNodes.end();
+    TPoint* p;
+    if ( paramsOfNodes.size() == points.size() )
+    {
+      for ( ; u2n != u2nEnd; ++u2n )
+      {
+        p = ( isForward ? *pItF : *pItR );
+        int pIndex = p - &myPoints[0];
+        if ( !nodesVector [ pIndex ] )
+          nodesVector [ pIndex ] = u2n->second;
+        ++pItF;
+        ++pItR;
+      }
+      return true;
+    }
+    else
+    {
+      const double tolFact = 0.05;
+      while ( u2n != u2nEnd && pItF != points.end() )
+      {
+        const double         u = u2n->first;
+        const SMDS_MeshNode* n = u2n->second;
+        const double       tol = ( (++u2n)->first - u ) * tolFact;
+        do
+        {
+          p = ( isForward ? *pItF : *pItR );
+          if ( Abs( u - p->myU ) < tol )
+          {
+            int pIndex = p - &myPoints[0];
+            if ( !nodesVector [ pIndex ] )
+              nodesVector [ pIndex ] = n;
+            ++pItF;
+            ++pItR;
+            break;
+          }
+        }
+        while ( p->myU < u && ( ++pItF, ++pItR != points.rend() ));
+      }
+    }
+    break;
+  } // case TopAbs_EDGE:
+
+  default:;
+  } // switch ( S.ShapeType() )
+
+  return false;
+}
+
 //=======================================================================
 //function : MakeMesh
 //purpose  : Create nodes and elements in <theMesh> using nodes
 //           coordinates computed by either of Apply...() methods
-// WARNING : StdMeshers_Projection_... relies on MakeMesh() behavior: that
-//           it does not care of nodes and elements already existing on
-//           sub-shapes. DO NOT MERGE them or modify also StdMeshers_Projection_..
 //=======================================================================
 
 bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh,
@@ -3982,83 +4103,23 @@ bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh,
   {
     nodesVector.resize( myPoints.size(), 0 );
 
-    // find existing nodes on EDGEs and VERTEXes (IMP 22368)
-    map< int, list< TPoint* > >::iterator idPointIt = myShapeIDToPointsMap.begin();
-    if ( !myShapeIDMap.IsEmpty() && aMeshDS->NbNodes() > 0 )
-
-      for ( ; idPointIt != myShapeIDToPointsMap.end(); idPointIt++ )
-      {
-        const TopoDS_Shape&    S = myShapeIDMap( idPointIt->first );
-        list< TPoint* > & points = idPointIt->second;
-        if ( points.empty() )
-          continue;
-
-        switch ( S.ShapeType() )
-        {
-        case TopAbs_VERTEX:
-        {
-          int pIndex = points.back() - &myPoints[0];
-          if ( !nodesVector[ pIndex ] )
-            nodesVector[ pIndex ] = SMESH_Algo::VertexNode( TopoDS::Vertex( S ), aMeshDS );
-          break;
-        }
-        case TopAbs_EDGE:
-        {
-          const TopoDS_Edge& edge = TopoDS::Edge( S );
-          map< double, const SMDS_MeshNode* > paramsOfNodes;
-          if ( !SMESH_Algo::GetSortedNodesOnEdge( aMeshDS, edge,
-                                                  /*ignoreMediumNodes=*/false,
-                                                  paramsOfNodes )
-               || paramsOfNodes.size() < 3 )
-            break;
-          // points on VERTEXes are included with wrong myU
-          list< TPoint* >::reverse_iterator pItR = ++points.rbegin();
-          list< TPoint* >::iterator         pItF = ++points.begin();
-          const bool isForward = ( (*pItF)->myU < (*pItR)->myU );
-          map< double, const SMDS_MeshNode* >::iterator u2n    = ++paramsOfNodes.begin();
-          map< double, const SMDS_MeshNode* >::iterator u2nEnd = --paramsOfNodes.end();
-          TPoint* p;
-          const double tolFact = ( paramsOfNodes.size() == points.size() ) ? 0.3 : 0.05;
-          while ( u2n != u2nEnd && pItF != points.end() )
-          {
-            const double         u = u2n->first;
-            const SMDS_MeshNode* n = u2n->second;
-            const double       tol = ( (++u2n)->first - u ) * tolFact;
-            do
-            {
-              p = ( isForward ? *pItF : *pItR );
-              if ( Abs( u - p->myU ) < tol )
-              {
-                int pIndex = p - &myPoints[0];
-                if ( !nodesVector [ pIndex ] )
-                  nodesVector [ pIndex ] = n;
-                ++pItF;
-                ++pItR;
-                break;
-              }
-            }
-            while ( p->myU < u && ( ++pItF, ++pItR != points.rend() ));
-          }
-          break;
-        }
-        default:;
-        }
-      } // end of "find existing nodes on EDGEs and VERTEXes"
-
     // loop on sub-shapes of myShape: create nodes
-    idPointIt = myShapeIDToPointsMap.begin();
+    map< int, list< TPoint* > >::iterator idPointIt = myShapeIDToPointsMap.begin();
     for ( ; idPointIt != myShapeIDToPointsMap.end(); idPointIt++ )
     {
+      list< TPoint* > & points = idPointIt->second;
       TopoDS_Shape S;
-      if ( !myShapeIDMap.IsEmpty() ) {
+      if ( !myShapeIDMap.IsEmpty() )
         S = myShapeIDMap( idPointIt->first );
-      }
-      list< TPoint* > & points = idPointIt->second;
+
+      // find existing nodes on EDGEs and VERTEXes
+      if ( findExistingNodes( theMesh, S, points, nodesVector ))
+        continue;
+
       list< TPoint* >::iterator pIt = points.begin();
       for ( ; pIt != points.end(); pIt++ )
       {
         TPoint* point = *pIt;
-        //int pIndex = pointIndex[ point ];
         int pIndex = point - &myPoints[0];
         if ( nodesVector [ pIndex ] )
           continue;
@@ -4067,8 +4128,8 @@ bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh,
                                                 point->myXYZ.Z());
         nodesVector [ pIndex ] = node;
 
-        if ( !S.IsNull() /*subMeshDS*/ ) {
-          // !!!!! do not merge new nodes with ones existing on submeshes (see method comment)
+        if ( !S.IsNull() ) {
+
           switch ( S.ShapeType() ) {
           case TopAbs_VERTEX: {
             aMeshDS->SetNodeOnVertex( node, TopoDS::Vertex( S )); break;
@@ -4740,7 +4801,7 @@ bool SMESH_Pattern::setShapeToMesh(const TopoDS_Shape& theShape)
     TopTools_MapOfShape seamVertices;
     TopoDS_Face face = TopoDS::Face( theShape );
     TopExp_Explorer eExp( theShape, TopAbs_EDGE );
-    for ( ; eExp.More() && nbNodeOnSeamEdge == 0; eExp.Next() ) {
+    for ( ; eExp.More() /*&& nbNodeOnSeamEdge == 0*/; eExp.Next() ) {
       const TopoDS_Edge& ee = TopoDS::Edge(eExp.Current());
       if ( BRep_Tool::IsClosed(ee, face) ) {
         // seam edge and vertices encounter twice in theFace
index cbe6774933a86e0689cfa559b5f77fc7ecb7c21a..225e5abaa27b534c7557bde1e7bdaa479fb7e6fb 100644 (file)
@@ -334,6 +334,12 @@ private:
   void clearMesh(SMESH_Mesh* theMesh) const;
   // clear mesh elements existing on myShape in theMesh
 
+  bool findExistingNodes( SMESH_Mesh*                           mesh,
+                          const TopoDS_Shape&                   S,
+                          const std::list< TPoint* > &          points,
+                          std::vector< const SMDS_MeshNode* > & nodes);
+  // fills nodes vector with nodes existing on a given shape
+
   static SMESHDS_SubMesh * getSubmeshWithElements(SMESH_Mesh*         theMesh,
                                                   const TopoDS_Shape& theShape);
   // return submesh containing elements bound to theShape in theMesh
index 77a53769b83d297e06c4d5dfabaeb757faf8dcdf..59294a54c8f608fbd6fd4d8791e8c98d209e4262 100644 (file)
 #include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
 #include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
 #include <TopTools_IndexedMapOfShape.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Compound.hxx>
-#include <gp_Pnt.hxx>
-#include <TopExp_Explorer.hxx>
 #include <TopoDS_Iterator.hxx>
+#include <gp_Pnt.hxx>
 
 #include <Standard_OutOfMemory.hxx>
 #include <Standard_ErrorHandler.hxx>
@@ -195,7 +196,10 @@ SMESH_subMesh *SMESH_subMesh::GetFirstToCompute()
 SMESH_Algo* SMESH_subMesh::GetAlgo() const
 {
   if ( !_algo )
-    ((SMESH_subMesh*)this)->_algo = _father->GetGen()->GetAlgo(*_father, _subShape);
+  {
+    SMESH_subMesh* me = const_cast< SMESH_subMesh* >( this );
+    me->_algo = _father->GetGen()->GetAlgo( me );
+  }
   return _algo;
 }
 
@@ -666,11 +670,17 @@ bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis,
   return false;
 }
 
-//=============================================================================
+//================================================================================
 /*!
- *
+ * \brief Treats modification of hypotheses definition
+ *  \param [in] event - what happens
+ *  \param [in] anHyp - a hypothesis
+ *  \return SMESH_Hypothesis::Hypothesis_Status - a treatment result.
+ * 
+ * Optional description of a problematic situation (if any) can be retrieved
+ * via GetComputeError().
  */
-//=============================================================================
+//================================================================================
 
 SMESH_Hypothesis::Hypothesis_Status
   SMESH_subMesh::AlgoStateEngine(int event, SMESH_Hypothesis * anHyp)
@@ -735,7 +745,7 @@ SMESH_Hypothesis::Hypothesis_Status
       SMESH_HypoFilter filter( SMESH_HypoFilter::HasType( algo->GetType() ));
       filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+1 ));
       filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+2 ));
-      if ( SMESH_Algo * curAlgo = (SMESH_Algo*)_father->GetHypothesis(_subShape, filter, true ))
+      if ( SMESH_Algo * curAlgo = (SMESH_Algo*)_father->GetHypothesis( this, filter, true ))
         if ( !curAlgo->NeedDiscreteBoundary() )
           algoRequiringCleaning = curAlgo;
     }
@@ -749,7 +759,7 @@ SMESH_Hypothesis::Hypothesis_Status
     if ( ! CanAddHypothesis( anHyp )) // check dimension
       return SMESH_Hypothesis::HYP_BAD_DIM;
 
-    if ( /*!anHyp->IsAuxiliary() &&*/ getSimilarAttached( _subShape, anHyp ) )
+    if ( !anHyp->IsAuxiliary() && getSimilarAttached( _subShape, anHyp ) )
       return SMESH_Hypothesis::HYP_ALREADY_EXIST;
 
     if ( !meshDS->AddHypothesis(_subShape, anHyp))
@@ -778,6 +788,9 @@ SMESH_Hypothesis::Hypothesis_Status
   if (!isApplicableHyp)
     return ret; // not applicable hypotheses do not change algo state
 
+  if (( algo = GetAlgo()))
+    algo->InitComputeError();
+
   switch (_algoState)
   {
 
@@ -942,7 +955,7 @@ SMESH_Hypothesis::Hypothesis_Status
           // ret should be fatal: anHyp was not added
           ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
       }
-      else if (!_father->IsUsedHypothesis(  anHyp, this ))
+      else if (!_father->IsUsedHypothesis( anHyp, this ))
         ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
 
       if (SMESH_Hypothesis::IsStatusFatal( ret ))
@@ -964,7 +977,7 @@ SMESH_Hypothesis::Hypothesis_Status
         f.Init(   SMESH_HypoFilter::IsAlgo() );
         f.And(    SMESH_HypoFilter::IsApplicableTo( _subShape ));
         f.AndNot( SMESH_HypoFilter::Is( algo ));
-        const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( _subShape, f, true );
+        const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( this, f, true );
         if (prevAlgo &&
             string(algo->GetName()) != string(prevAlgo->GetName()) )
           modifiedHyp = true;
@@ -1023,7 +1036,7 @@ SMESH_Hypothesis::Hypothesis_Status
           f.Init(   SMESH_HypoFilter::IsAlgo() );
           f.And(    SMESH_HypoFilter::IsApplicableTo( _subShape ));
           f.AndNot( SMESH_HypoFilter::Is( algo ));
-          const SMESH_Hypothesis* prevAlgo = _father->GetHypothesis( _subShape, f, true );
+          const SMESH_Hypothesis* prevAlgo = _father->GetHypothesis( this, f, true );
           if (prevAlgo &&
               string(algo->GetName()) != string(prevAlgo->GetName()) )
             modifiedHyp = true;
@@ -1089,26 +1102,32 @@ SMESH_Hypothesis::Hypothesis_Status
   {
     // is algo hidden?
     SMESH_Gen* gen = _father->GetGen();
-    TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
-    for ( ; ( ret == SMESH_Hypothesis::HYP_OK && it.More()); it.Next() ) {
-      if ( SMESH_Algo* upperAlgo = gen->GetAlgo( *_father, it.Value() ))
+    const std::vector< SMESH_subMesh * > & ancestors = GetAncestors();
+    for ( size_t iA = 0; ( ret == SMESH_Hypothesis::HYP_OK && iA < ancestors.size()); ++iA ) {
+      if ( SMESH_Algo* upperAlgo = ancestors[ iA ]->GetAlgo() )
         if ( !upperAlgo->NeedDiscreteBoundary() && !upperAlgo->SupportSubmeshes())
           ret = SMESH_Hypothesis::HYP_HIDDEN_ALGO;
     }
     // is algo hiding?
     if ( ret == SMESH_Hypothesis::HYP_OK &&
          !algo->NeedDiscreteBoundary()    &&
-         !algo->SupportSubmeshes()) {
+         !algo->SupportSubmeshes())
+    {
       TopoDS_Shape algoAssignedTo, otherAssignedTo;
-      gen->GetAlgo( *_father, _subShape, &algoAssignedTo );
+      gen->GetAlgo( this, &algoAssignedTo );
       map<int, SMESH_subMesh*>::reverse_iterator i_sm = _mapDepend.rbegin();
       for ( ; ( ret == SMESH_Hypothesis::HYP_OK && i_sm != _mapDepend.rend()) ; ++i_sm )
-        if ( gen->GetAlgo( *_father, i_sm->second->_subShape, &otherAssignedTo ) &&
+        if ( gen->GetAlgo( i_sm->second, &otherAssignedTo ) &&
              SMESH_MesherHelper::IsSubShape( /*sub=*/otherAssignedTo, /*main=*/algoAssignedTo ))
           ret = SMESH_Hypothesis::HYP_HIDING_ALGO;
     }
   }
 
+  if ( _algo ) { // get an error description set by _algo->CheckHypothesis()
+    _computeError = _algo->GetComputeError();
+    _algo->InitComputeError();
+  }
+
   bool stateChange = ( _algoState != oldAlgoState );
 
   if ( stateChange && _algoState == HYP_OK ) // hyp becomes OK
@@ -1136,8 +1155,8 @@ SMESH_Hypothesis::Hypothesis_Status
     ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
   }
 
-  if (stateChange || modifiedHyp)
-    ComputeStateEngine(MODIF_ALGO_STATE);
+  if ( stateChange || modifiedHyp )
+    ComputeStateEngine( MODIF_ALGO_STATE );
 
   _realComputeCost = ( _algoState == HYP_OK ) ? computeCost() : 0;
 
@@ -1177,16 +1196,16 @@ bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo)
   for (; itsub.More(); itsub.Next())
   {
     // loop on adjacent subShapes
-    TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( itsub.Value() ));
-    for (; it.More(); it.Next())
+    const std::vector< SMESH_subMesh * > & ancestors = GetAncestors();
+    for ( size_t iA = 0; iA < ancestors.size(); ++iA )
     {
-      const TopoDS_Shape& adjacent = it.Value();
+      const TopoDS_Shape& adjacent = ancestors[ iA ]->GetSubShape();
       if ( _subShape.IsSame( adjacent )) continue;
       if ( adjacent.ShapeType() != _subShape.ShapeType())
         break;
 
       // check algo attached to smAdjacent
-      SMESH_Algo * algo = gen->GetAlgo((*_father), adjacent);
+      SMESH_Algo * algo = ancestors[ iA ]->GetAlgo();
       if (algo &&
           !algo->NeedDiscreteBoundary() &&
           algo->OnlyUnaryInput())
@@ -1208,14 +1227,24 @@ void SMESH_subMesh::setAlgoState(algo_state state)
   _algoState = state;
 }
 
-//=============================================================================
+//================================================================================
 /*!
+ * \brief Send an event to sub-meshes
+ *  \param [in] event - the event
+ *  \param [in] anHyp - an hypothesis
+ *  \param [in] exitOnFatal - to stop iteration on sub-meshes if a sub-mesh
+ *              reports a fatal result
+ *  \return SMESH_Hypothesis::Hypothesis_Status - the worst result
  *
+ * Optional description of a problematic situation (if any) can be retrieved
+ * via GetComputeError().
  */
-//=============================================================================
+//================================================================================
+
 SMESH_Hypothesis::Hypothesis_Status
-  SMESH_subMesh::SubMeshesAlgoStateEngine(int event,
-                                          SMESH_Hypothesis * anHyp)
+  SMESH_subMesh::SubMeshesAlgoStateEngine(int                event,
+                                          SMESH_Hypothesis * anHyp,
+                                          bool               exitOnFatal)
 {
   SMESH_Hypothesis::Hypothesis_Status ret = SMESH_Hypothesis::HYP_OK;
   //EAP: a wire (dim==1) should notify edges (dim==1)
@@ -1224,10 +1253,16 @@ SMESH_Hypothesis::Hypothesis_Status
   {
     SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
     while ( smIt->more() ) {
-      SMESH_Hypothesis::Hypothesis_Status ret2 =
-        smIt->next()->AlgoStateEngine(event, anHyp);
+      SMESH_subMesh* sm = smIt->next();
+      SMESH_Hypothesis::Hypothesis_Status ret2 = sm->AlgoStateEngine(event, anHyp);
       if ( ret2 > ret )
+      {
         ret = ret2;
+        _computeError = sm->_computeError;
+        sm->_computeError.reset();
+        if ( exitOnFatal && SMESH_Hypothesis::IsStatusFatal( ret ))
+          break;
+      }
     }
   }
   return ret;
@@ -1553,7 +1588,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
             if ( !algo->NeedDiscreteBoundary() && !subFailed )
               _computeError =
                 SMESH_ComputeError::New(COMPERR_BAD_INPUT_MESH,
-                                        "Unexpected computed submesh",algo);
+                                        "Unexpected computed sub-mesh",algo);
             break; // goto exit
           }
         }
@@ -1587,8 +1622,8 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           {
             ret = algo->Compute((*_father), shape);
           }
-          if ( !_computeError || (/* !ret && */_computeError->IsOK() ) ) // algo can set _computeError of submesh
-            _computeError = algo->GetComputeError();
+          // algo can set _computeError of submesh
+          _computeError = SMESH_ComputeError::Worst( _computeError, algo->GetComputeError() );
         }
         catch ( ::SMESH_ComputeError& comperr ) {
           cout << " SMESH_ComputeError caught" << endl;
@@ -1735,6 +1770,8 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
     case CHECK_COMPUTE_STATE:
       if ( IsMeshComputed() )
         _computeState = COMPUTE_OK;
+      else if ( _computeError && _computeError->IsKO() )
+        _computeState = FAILED_TO_COMPUTE;
       break;
     default:
       ASSERT(0);
@@ -2033,12 +2070,10 @@ void SMESH_subMesh::ComputeSubMeshStateEngine(int event, const bool includeSelf)
 
 void SMESH_subMesh::updateDependantsState(const compute_event theEvent)
 {
-  TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
-  for (; it.More(); it.Next())
+  const std::vector< SMESH_subMesh * > & ancestors = GetAncestors();
+  for ( size_t iA = 0; iA < ancestors.size(); ++iA )
   {
-    const TopoDS_Shape& ancestor = it.Value();
-    if ( SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor))
-      aSubMesh->ComputeStateEngine( theEvent );
+    ancestors[ iA ]->ComputeStateEngine( theEvent );
   }
 }
 
@@ -2052,19 +2087,17 @@ void SMESH_subMesh::cleanDependants()
 {
   int dimToClean = SMESH_Gen::GetShapeDim( _subShape ) + 1;
 
-  TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
-  for (; it.More(); it.Next())
+  const std::vector< SMESH_subMesh * > & ancestors = GetAncestors();
+  for ( size_t iA = 0; iA < ancestors.size(); ++iA )
   {
-    const TopoDS_Shape& ancestor = it.Value();
-    if ( SMESH_Gen::GetShapeDim( ancestor ) == dimToClean ) {
+    const TopoDS_Shape& ancestor = ancestors[ iA ]->GetSubShape();
+    if ( SMESH_Gen::GetShapeDim( ancestor ) == dimToClean )
+    {
       // PAL8021. do not go upper than SOLID, else ComputeStateEngine(CLEAN)
       // will erase mesh on other shapes in a compound
-      if ( ancestor.ShapeType() >= TopAbs_SOLID ) {
-        SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor);
-        if (aSubMesh &&
-            !aSubMesh->IsEmpty() ) // prevent infinite CLEAN via event lesteners
-          aSubMesh->ComputeStateEngine(CLEAN);
-      }
+      if ( ancestor.ShapeType() >= TopAbs_SOLID &&
+           !ancestors[ iA ]->IsEmpty() )  // prevent infinite CLEAN via event lesteners
+        ancestors[ iA ]->ComputeStateEngine(CLEAN);
     }
   }
 }
@@ -2140,7 +2173,7 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen,
     }
     else if ( subMesh->GetComputeState() == READY_TO_COMPUTE )
     {
-      SMESH_Algo* anAlgo = theGen->GetAlgo( *_father, S );
+      SMESH_Algo* anAlgo = theGen->GetAlgo( subMesh );
       if (strcmp( anAlgo->GetName(), theAlgo->GetName()) == 0 && // same algo
           anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp) // same hyps
         aBuilder.Add( aCompound, S );
@@ -2299,16 +2332,31 @@ void SMESH_subMesh::setEventListener(EventListener*     listener,
 /*!
  * \brief Return an event listener data
  * \param listener - the listener whose data is
+ * \param myOwn - if \c true, returns a listener set by this sub-mesh,
+ *        else returns a listener listening to events of this sub-mesh
  * \retval EventListenerData* - found data, maybe NULL
  */
 //================================================================================
 
-EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener) const
+EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener,
+                                                       const bool     myOwn) const
 {
-  map< EventListener*, EventListenerData* >::const_iterator l_d =
-    _eventListeners.find( listener );
-  if ( l_d != _eventListeners.end() )
-    return l_d->second;
+  if ( myOwn )
+  {
+    list< OwnListenerData >::const_iterator d;
+    for ( d = _ownListeners.begin(); d != _ownListeners.end(); ++d )
+    {
+      if ( d->myListener == listener && _father->MeshExists( d->myMeshID ))
+        return d->mySubMesh->GetEventListenerData( listener, !myOwn );
+    }
+  }
+  else
+  {
+    map< EventListener*, EventListenerData* >::const_iterator l_d =
+      _eventListeners.find( listener );
+    if ( l_d != _eventListeners.end() )
+      return l_d->second;
+  }
   return 0;
 }
 
@@ -2316,16 +2364,31 @@ EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener)
 /*!
  * \brief Return an event listener data
  * \param listenerName - the listener name
+ * \param myOwn - if \c true, returns a listener set by this sub-mesh,
+ *        else returns a listener listening to events of this sub-mesh
  * \retval EventListenerData* - found data, maybe NULL
  */
 //================================================================================
 
-EventListenerData* SMESH_subMesh::GetEventListenerData(const string& listenerName) const
+EventListenerData* SMESH_subMesh::GetEventListenerData(const string& listenerName,
+                                                       const bool    myOwn) const
 {
-  map< EventListener*, EventListenerData* >::const_iterator l_d = _eventListeners.begin();
-  for ( ; l_d != _eventListeners.end(); ++l_d )
-    if ( listenerName == l_d->first->GetName() )
-      return l_d->second;
+  if ( myOwn )
+  {
+    list< OwnListenerData >::const_iterator d;
+    for ( d = _ownListeners.begin(); d != _ownListeners.end(); ++d )
+    {
+      if ( _father->MeshExists( d->myMeshID ) && listenerName == d->myListener->GetName())
+        return d->mySubMesh->GetEventListenerData( listenerName, !myOwn );
+    }
+  }
+  else
+  {
+    map< EventListener*, EventListenerData* >::const_iterator l_d = _eventListeners.begin();
+    for ( ; l_d != _eventListeners.end(); ++l_d )
+      if ( listenerName == l_d->first->GetName() )
+        return l_d->second;
+  }
   return 0;
 }
 
@@ -2544,6 +2607,44 @@ SMESH_subMeshIteratorPtr SMESH_subMesh::getDependsOnIterator(const bool includeS
   }
 }
 
+//================================================================================
+/*!
+ * \brief Returns ancestor sub-meshes. Finds them if not yet found.
+ */
+//================================================================================
+
+const std::vector< SMESH_subMesh * > & SMESH_subMesh::GetAncestors() const
+{
+  if ( _ancestors.empty() &&
+       !_subShape.IsSame( _father->GetShapeToMesh() ))
+  {
+    const TopTools_ListOfShape& ancShapes = _father->GetAncestors( _subShape );
+
+    SMESH_subMesh* me = const_cast< SMESH_subMesh* >( this );
+    me->_ancestors.reserve( ancShapes.Extent() );
+
+    TopTools_MapOfShape map;
+   
+    for ( TopTools_ListIteratorOfListOfShape it( ancShapes ); it.More(); it.Next() )
+      if ( SMESH_subMesh* sm = _father->GetSubMeshContaining( it.Value() ))
+        if ( map.Add( it.Value() ))
+          me->_ancestors.push_back( sm );
+  }
+
+  return _ancestors;
+}
+
+//================================================================================
+/*!
+ * \brief Clears the vector of ancestor sub-meshes
+ */
+//================================================================================
+
+void SMESH_subMesh::ClearAncestors()
+{
+  _ancestors.clear();
+}
+
 //================================================================================
 /*!
  * \brief  Find common submeshes (based on shared sub-shapes with other
index f38d6367a53d925f21715f565c88e8010c9651a4..6d38841e0c7b71ba81b0c06daec33dd06fccee1b 100644 (file)
@@ -88,6 +88,9 @@ class SMESH_EXPORT SMESH_subMesh
   SMESH_subMeshIteratorPtr getDependsOnIterator(const bool includeSelf,
                                                 const bool complexShapeFirst=false) const;
 
+  const std::vector< SMESH_subMesh * > & GetAncestors() const;
+  void ClearAncestors();
+
   const TopoDS_Shape & GetSubShape() const;
 
   enum compute_state
@@ -139,16 +142,22 @@ class SMESH_EXPORT SMESH_subMesh
   /*!
    * \brief Return an event listener data
     * \param listener - the listener whose data is
+    * \param myOwn - if \c true, returns a listener set by this sub-mesh,
+    *        else returns a listener listening to events of this sub-mesh
     * \retval EventListenerData* - found data, maybe NULL
    */
-  EventListenerData* GetEventListenerData(EventListener* listener) const;
+  EventListenerData* GetEventListenerData(EventListener* listener,
+                                          const bool     myOwn=false) const;
 
   /*!
    * \brief Return an event listener data
     * \param listenerName - the listener name
+    * \param myOwn - if \c true, returns a listener set by this sub-mesh,
+    *        else returns a listener listening to events of this sub-mesh
     * \retval EventListenerData* - found data, maybe NULL
    */
-  EventListenerData* GetEventListenerData(const std::string& listenerName) const;
+  EventListenerData* GetEventListenerData(const std::string& listenerName,
+                                          const bool         myOwn=false) const;
 
   /*!
    * \brief Unregister the listener and delete it and it's data
@@ -209,10 +218,10 @@ public:
     AlgoStateEngine(int event, SMESH_Hypothesis * anHyp);
 
   SMESH_Hypothesis::Hypothesis_Status
-    SubMeshesAlgoStateEngine(int event, SMESH_Hypothesis * anHyp);
+    SubMeshesAlgoStateEngine(int event, SMESH_Hypothesis * anHyp, bool exitOnFatal=false);
 
   algo_state             GetAlgoState() const    { return _algoState; }
-  compute_state          GetComputeState() const { return _computeState; };
+  compute_state          GetComputeState() const { return _computeState; }
   SMESH_ComputeErrorPtr& GetComputeError()       { return _computeError; }
 
   void DumpAlgoState(bool isMain);
@@ -319,6 +328,7 @@ protected:
 
   std::map < int, SMESH_subMesh * >_mapDepend;
   bool                  _dependenceAnalysed;
+  std::vector< SMESH_subMesh * >   _ancestors;
 
   SMESH_Algo *          _algo; // the algorithm found by last *StateEngine() call
   algo_state            _algoState;
index a5851a204dabd96da12107c3a2570305363e8942..6e43761420178a48e273f7dfc0497630bcce3a51 100644 (file)
@@ -103,3 +103,14 @@ bool SMESHDS_Hypothesis::operator==(const SMESHDS_Hypothesis& other) const
   ((SMESHDS_Hypothesis*)&other)->SaveTo(otherSave);
   return mySave.str() == otherSave.str();
 }
+
+//================================================================================
+/*!
+ * \brief Compare types of hypotheses
+ */
+//================================================================================
+
+bool SMESHDS_Hypothesis::IsSameName( const SMESHDS_Hypothesis& other) const
+{
+  return _name == other._name;
+}
index ea01d617a6279b978558ad16bdfcb65db5b9e709..5e416504834d9582264fc45adfbd2bfa7422362a 100644 (file)
@@ -48,6 +48,7 @@ class SMESHDS_EXPORT SMESHDS_Hypothesis
   virtual std::ostream & SaveTo(std::ostream & save)=0;
   virtual std::istream & LoadFrom(std::istream & load)=0;
 
+  bool IsSameName( const SMESHDS_Hypothesis& other) const;
   virtual bool operator==(const SMESHDS_Hypothesis& other) const;
   bool operator!=(const SMESHDS_Hypothesis& other) const { return !(*this==other); }
 
index 6766fbda76a822021b0426e748ef5dd874b84b67..ff1da64b0e784bb9bcca13e5743caedd89ff4b3a 100644 (file)
 //
 #include "SMESHDS_Mesh.hxx"
 
-#include "SMESHDS_Group.hxx"
-#include "SMDS_VertexPosition.hxx"
+#include "SMDS_Downward.hxx"
 #include "SMDS_EdgePosition.hxx"
 #include "SMDS_FacePosition.hxx"
 #include "SMDS_SpacePosition.hxx"
-#include "SMDS_Downward.hxx"
+#include "SMDS_VertexPosition.hxx"
+#include "SMESHDS_Group.hxx"
 #include "SMESHDS_GroupOnGeom.hxx"
 #include "SMESHDS_Script.hxx"
+#include "SMESHDS_TSubMeshHolder.hxx"
 
 #include <Standard_ErrorHandler.hxx>
 #include <Standard_OutOfRange.hxx>
 
 using namespace std;
 
+class SMESHDS_Mesh::SubMeshHolder : public SMESHDS_TSubMeshHolder< const SMESHDS_SubMesh >
+{
+};
+
 //=======================================================================
 //function : Create
 //purpose  : 
 //=======================================================================
 SMESHDS_Mesh::SMESHDS_Mesh(int theMeshID, bool theIsEmbeddedMode):
   myMeshID(theMeshID),
-  myIsEmbeddedMode(theIsEmbeddedMode),
-  myCurSubID(-1)
+  mySubMeshHolder( new SubMeshHolder ),
+  myIsEmbeddedMode(theIsEmbeddedMode)
 {
   myScript = new SMESHDS_Script(theIsEmbeddedMode);
-  myCurSubMesh = 0;
   SetPersistentId(theMeshID);
 }
 
@@ -107,19 +111,17 @@ void SMESHDS_Mesh::ShapeToMesh(const TopoDS_Shape & S)
     // - hypotheses
     myShapeToHypothesis.Clear();
     // - shape indices in SMDS_Position of nodes
-    map<int,SMESHDS_SubMesh*>::iterator i_sub = myShapeIndexToSubMesh.begin();
-    for ( ; i_sub != myShapeIndexToSubMesh.end(); i_sub++ ) {
-      if ( !i_sub->second->IsComplexSubmesh() ) {
-        SMDS_NodeIteratorPtr nIt = i_sub->second->GetNodes();
+    SMESHDS_SubMeshIteratorPtr smIt = SubMeshes();
+    while ( SMESHDS_SubMesh* sm = const_cast< SMESHDS_SubMesh* >( smIt->next() )) {
+      if ( !sm->IsComplexSubmesh() ) {
+        SMDS_NodeIteratorPtr nIt = sm->GetNodes();
         while ( nIt->more() )
-          i_sub->second->RemoveNode(nIt->next(), false);
+          sm->RemoveNode(nIt->next(), false);
       }
     }
     // - sub-meshes
-    TShapeIndexToSubMesh::iterator i_sm = myShapeIndexToSubMesh.begin();
-    for ( ; i_sm != myShapeIndexToSubMesh.end(); ++i_sm )
-      delete i_sm->second;
-    myShapeIndexToSubMesh.clear();
+    mySubMeshHolder->DeleteAll();
+
     myIndexToShape.Clear();
     // - groups on geometry
     set<SMESHDS_GroupBase*>::iterator gr = myGroups.begin();
@@ -145,12 +147,12 @@ void SMESHDS_Mesh::ShapeToMesh(const TopoDS_Shape & S)
 bool SMESHDS_Mesh::AddHypothesis(const TopoDS_Shape & SS,
                                  const SMESHDS_Hypothesis * H)
 {
-  if (!myShapeToHypothesis.IsBound(SS.Oriented(TopAbs_FORWARD))) {
+  if (!myShapeToHypothesis.IsBound(SS/*.Oriented(TopAbs_FORWARD)*/)) {
     list<const SMESHDS_Hypothesis *> aList;
-    myShapeToHypothesis.Bind(SS.Oriented(TopAbs_FORWARD), aList);
+    myShapeToHypothesis.Bind(SS/*.Oriented(TopAbs_FORWARD)*/, aList);
   }
   list<const SMESHDS_Hypothesis *>& alist =
-    myShapeToHypothesis(SS.Oriented(TopAbs_FORWARD)); // ignore orientation of SS
+    myShapeToHypothesis(SS/*.Oriented(TopAbs_FORWARD)*/); // ignore orientation of SS
 
   //Check if the Hypothesis is still present
   list<const SMESHDS_Hypothesis*>::iterator ith = find(alist.begin(),alist.end(), H );
@@ -169,9 +171,9 @@ bool SMESHDS_Mesh::AddHypothesis(const TopoDS_Shape & SS,
 bool SMESHDS_Mesh::RemoveHypothesis(const TopoDS_Shape &       S,
                                     const SMESHDS_Hypothesis * H)
 {
-  if( myShapeToHypothesis.IsBound( S.Oriented(TopAbs_FORWARD) ) )
+  if( myShapeToHypothesis.IsBound( S/*.Oriented(TopAbs_FORWARD)*/ ) )
   {
-    list<const SMESHDS_Hypothesis *>& alist=myShapeToHypothesis.ChangeFind( S.Oriented(TopAbs_FORWARD) );
+    list<const SMESHDS_Hypothesis *>& alist=myShapeToHypothesis.ChangeFind( S/*.Oriented(TopAbs_FORWARD)*/ );
     list<const SMESHDS_Hypothesis*>::iterator ith=find(alist.begin(),alist.end(), H );
     if (ith != alist.end())
     {
@@ -790,7 +792,7 @@ SMDS_MeshVolume* SMESHDS_Mesh::AddPolyhedralVolume
 //purpose  : 
 //=======================================================================
 
-static void removeFromContainers (map<int,SMESHDS_SubMesh*>&     theSubMeshes,
+static void removeFromContainers (SMESHDS_Mesh*                  theMesh,
                                   set<SMESHDS_GroupBase*>&       theGroups,
                                   list<const SMDS_MeshElement*>& theElems,
                                   const bool                     isNode)
@@ -821,18 +823,17 @@ static void removeFromContainers (map<int,SMESHDS_SubMesh*>&     theSubMeshes,
 
   // Rm from sub-meshes
   // Element should belong to only one sub-mesh
-  if ( !theSubMeshes.empty() )
+  if ( theMesh->SubMeshes()->more() )
   {
-    SMESHDS_Mesh* mesh = theSubMeshes.begin()->second->GetParent();
     list<const SMDS_MeshElement *>::iterator elIt = theElems.begin();
     if ( isNode ) {
       for ( ; elIt != theElems.end(); ++elIt )
-        if ( SMESHDS_SubMesh* sm = mesh->MeshElements( (*elIt)->getshapeId() ))
+        if ( SMESHDS_SubMesh* sm = theMesh->MeshElements( (*elIt)->getshapeId() ))
           sm->RemoveNode( static_cast<const SMDS_MeshNode*> (*elIt), deleted );
     }
     else {
       for ( ; elIt != theElems.end(); ++elIt )
-        if ( SMESHDS_SubMesh* sm = mesh->MeshElements( (*elIt)->getshapeId() ))
+        if ( SMESHDS_SubMesh* sm = theMesh->MeshElements( (*elIt)->getshapeId() ))
           sm->RemoveElement( *elIt, deleted );
     }
   }
@@ -840,36 +841,34 @@ static void removeFromContainers (map<int,SMESHDS_SubMesh*>&     theSubMeshes,
 
 //=======================================================================
 //function : RemoveNode
-//purpose  : 
+//purpose  :
 //=======================================================================
 void SMESHDS_Mesh::RemoveNode(const SMDS_MeshNode * n)
 {
   if ( n->NbInverseElements() == 0 && !(hasConstructionEdges() || hasConstructionFaces()))
   {
-    SMESHDS_SubMesh* subMesh=0;
-    map<int,SMESHDS_SubMesh*>::iterator SubIt =
-      myShapeIndexToSubMesh.find( n->getshapeId() );
-    if ( SubIt != myShapeIndexToSubMesh.end() )
-      subMesh = SubIt->second;
-    else
-      SubIt = myShapeIndexToSubMesh.begin();
-    for ( ; !subMesh && SubIt != myShapeIndexToSubMesh.end(); SubIt++ )
-      if (!SubIt->second->IsComplexSubmesh() && SubIt->second->Contains( n ))
-        subMesh = SubIt->second;
-
+    SMESHDS_SubMesh* subMesh = MeshElements( n->getshapeId() );
+    SMESHDS_SubMeshIteratorPtr subIt;
+    if ( !subMesh )
+      subIt = SubMeshes();
+    for ( ; !subMesh && subIt->more(); ) {
+      subMesh = const_cast< SMESHDS_SubMesh* >( subIt->next() );
+      if ( subMesh->IsComplexSubmesh() || !subMesh->Contains( n ))
+        subMesh = 0;
+    }
     RemoveFreeNode( n, subMesh, true);
     return;
   }
-    
+
   myScript->RemoveNode(n->GetID());
-  
+
   list<const SMDS_MeshElement *> removedElems;
   list<const SMDS_MeshElement *> removedNodes;
 
   SMDS_Mesh::RemoveElement( n, removedElems, removedNodes, true );
 
-  removeFromContainers( myShapeIndexToSubMesh, myGroups, removedElems, false );
-  removeFromContainers( myShapeIndexToSubMesh, myGroups, removedNodes, true );
+  removeFromContainers( this, myGroups, removedElems, false );
+  removeFromContainers( this, myGroups, removedNodes, true );
 }
 
 //=======================================================================
@@ -917,11 +916,8 @@ void SMESHDS_Mesh::RemoveElement(const SMDS_MeshElement * elt)
   {
     SMESHDS_SubMesh* subMesh=0;
     if ( elt->getshapeId() > 0 )
-    {
-      map<int,SMESHDS_SubMesh*>::iterator SubIt = myShapeIndexToSubMesh.find( elt->getshapeId() );
-      if ( SubIt != myShapeIndexToSubMesh.end() )
-        subMesh = SubIt->second;
-    }
+      subMesh = MeshElements( elt->getshapeId() );
+
     RemoveFreeElement( elt, subMesh, true);
     return;
   }
@@ -933,7 +929,7 @@ void SMESHDS_Mesh::RemoveElement(const SMDS_MeshElement * elt)
 
   SMDS_Mesh::RemoveElement(elt, removedElems, removedNodes, false);
   
-  removeFromContainers( myShapeIndexToSubMesh, myGroups, removedElems, false );
+  removeFromContainers( this, myGroups, removedElems, false );
 }
 
 //=======================================================================
@@ -987,9 +983,9 @@ void SMESHDS_Mesh::ClearMesh()
   SMDS_Mesh::Clear();
 
   // clear submeshes
-  map<int,SMESHDS_SubMesh*>::iterator sub, subEnd = myShapeIndexToSubMesh.end();
-  for ( sub = myShapeIndexToSubMesh.begin(); sub != subEnd; ++sub )
-    sub->second->Clear();
+  SMESHDS_SubMeshIteratorPtr smIt = SubMeshes();
+  while ( SMESHDS_SubMesh* sm = const_cast< SMESHDS_SubMesh* >( smIt->next() ))
+    sm->Clear();
 
   // clear groups
   TGroups::iterator group, groupEnd = myGroups.end();
@@ -1011,8 +1007,6 @@ void SMESHDS_Mesh::ClearMesh()
  * \brief return submesh by shape
   * \param shape - the sub-shape
   * \retval SMESHDS_SubMesh* - the found submesh
-  *
- * search of submeshes is optimized
  */
 //================================================================================
 
@@ -1021,35 +1015,7 @@ SMESHDS_SubMesh* SMESHDS_Mesh::getSubmesh( const TopoDS_Shape & shape )
   if ( shape.IsNull() )
     return 0;
 
-  if ( !myCurSubShape.IsNull() && shape.IsSame( myCurSubShape ))
-    return myCurSubMesh;
-
-  getSubmesh( ShapeToIndex( shape ));
-  myCurSubShape = shape;
-  return myCurSubMesh;
-}
-
-//================================================================================
-/*!
- * \brief return submesh by sub-shape index
-  * \param Index - the sub-shape index
-  * \retval SMESHDS_SubMesh* - the found submesh
- * search of submeshes is optimized
- */
-//================================================================================
-
-SMESHDS_SubMesh* SMESHDS_Mesh::getSubmesh( const int Index )
-{
-  //Update or build submesh
-  if ( Index != myCurSubID ) {
-    map<int,SMESHDS_SubMesh*>::iterator it = myShapeIndexToSubMesh.find( Index );
-    if ( it == myShapeIndexToSubMesh.end() )
-      it = myShapeIndexToSubMesh.insert( make_pair(Index, new SMESHDS_SubMesh(this, Index) )).first;
-    myCurSubMesh = it->second;
-    myCurSubID = Index;
-    myCurSubShape.Nullify(); // myCurSubShape no more corresponds to submesh
-  }
-  return myCurSubMesh;
+  return NewSubMesh( ShapeToIndex( shape ));
 }
 
 //================================================================================
@@ -1142,12 +1108,9 @@ void SMESHDS_Mesh::SetNodeOnVertex(const SMDS_MeshNode *       aNode,
 void SMESHDS_Mesh::UnSetNodeOnShape(const SMDS_MeshNode* aNode)
 {
   int shapeId = aNode->getshapeId();
-  if (shapeId >= 0)
-    {
-      map<int, SMESHDS_SubMesh*>::iterator it = myShapeIndexToSubMesh.find(shapeId);
-      if (it != myShapeIndexToSubMesh.end())
-        it->second->RemoveNode(aNode, /*deleted=*/false);
-    }
+  if (shapeId > 0)
+    if ( SMESHDS_SubMesh* sm = MeshElements( shapeId ))
+      sm->RemoveNode(aNode, /*deleted=*/false);
 }
 
 //=======================================================================
@@ -1167,16 +1130,13 @@ void SMESHDS_Mesh::SetMeshElementOnShape(const SMDS_MeshElement * anElement,
 void SMESHDS_Mesh::UnSetMeshElementOnShape(const SMDS_MeshElement * elem,
                                            const TopoDS_Shape &     S)
 {
-  int Index = myIndexToShape.FindIndex(S);
-
-  map<int,SMESHDS_SubMesh*>::iterator it = myShapeIndexToSubMesh.find( Index );
-  if ( it != myShapeIndexToSubMesh.end() )
-    {
-      if (elem->GetType() == SMDSAbs_Node)
-        it->second->RemoveNode(static_cast<const SMDS_MeshNode*> (elem), /*deleted=*/false);
-      else
-        it->second->RemoveElement(elem, /*deleted=*/false);
-    }
+  if ( SMESHDS_SubMesh* sm = MeshElements( S ))
+  {
+    if (elem->GetType() == SMDSAbs_Node)
+      sm->RemoveNode(static_cast<const SMDS_MeshNode*> (elem), /*deleted=*/false);
+    else
+      sm->RemoveElement(elem, /*deleted=*/false);
+  }
 }
 
 //=======================================================================
@@ -1185,7 +1145,7 @@ void SMESHDS_Mesh::UnSetMeshElementOnShape(const SMDS_MeshElement * elem,
 //=======================================================================
 TopoDS_Shape SMESHDS_Mesh::ShapeToMesh() const
 {
-        return myShape;
+  return myShape;
 }
 
 //=======================================================================
@@ -1213,11 +1173,7 @@ bool SMESHDS_Mesh::IsGroupOfSubShapes (const TopoDS_Shape& theShape) const
 SMESHDS_SubMesh * SMESHDS_Mesh::MeshElements(const TopoDS_Shape & S) const
 {
   int Index = ShapeToIndex(S);
-  TShapeIndexToSubMesh::const_iterator anIter = myShapeIndexToSubMesh.find(Index);
-  if (anIter != myShapeIndexToSubMesh.end())
-    return anIter->second;
-  else
-    return NULL;
+  return (SMESHDS_SubMesh *) ( Index ? mySubMeshHolder->Get( Index ) : 0 );
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1225,11 +1181,7 @@ SMESHDS_SubMesh * SMESHDS_Mesh::MeshElements(const TopoDS_Shape & S) const
 ///////////////////////////////////////////////////////////////////////////////
 SMESHDS_SubMesh * SMESHDS_Mesh::MeshElements(const int Index) const
 {
-  TShapeIndexToSubMesh::const_iterator anIter = myShapeIndexToSubMesh.find(Index);
-  if (anIter != myShapeIndexToSubMesh.end())
-    return anIter->second;
-  else
-    return NULL;
+  return const_cast< SMESHDS_SubMesh* >( mySubMeshHolder->Get( Index ));
 }
 
 //=======================================================================
@@ -1239,13 +1191,23 @@ SMESHDS_SubMesh * SMESHDS_Mesh::MeshElements(const int Index) const
 list<int> SMESHDS_Mesh::SubMeshIndices() const
 {
   list<int> anIndices;
-  std::map<int,SMESHDS_SubMesh*>::const_iterator anIter = myShapeIndexToSubMesh.begin();
-  for (; anIter != myShapeIndexToSubMesh.end(); anIter++) {
-    anIndices.push_back((*anIter).first);
-  }
+  SMESHDS_SubMeshIteratorPtr smIt = SubMeshes();
+  while ( const SMESHDS_SubMesh* sm = smIt->next() )
+    anIndices.push_back( sm->GetID() );
+
   return anIndices;
 }
 
+//=======================================================================
+//function : SubMeshes
+//purpose  : 
+//=======================================================================
+
+SMESHDS_SubMeshIteratorPtr SMESHDS_Mesh::SubMeshes() const
+{
+  return SMESHDS_SubMeshIteratorPtr( mySubMeshHolder->GetIterator() );
+}
+
 //=======================================================================
 //function : GetHypothesis
 //purpose  : 
@@ -1254,8 +1216,8 @@ list<int> SMESHDS_Mesh::SubMeshIndices() const
 const list<const SMESHDS_Hypothesis*>&
 SMESHDS_Mesh::GetHypothesis(const TopoDS_Shape & S) const
 {
-  if ( myShapeToHypothesis.IsBound( S.Oriented(TopAbs_FORWARD) ) ) // ignore orientation of S
-     return myShapeToHypothesis.Find( S.Oriented(TopAbs_FORWARD) );
+  if ( myShapeToHypothesis.IsBound( S/*.Oriented(TopAbs_FORWARD)*/ ) ) // ignore orientation of S
+     return myShapeToHypothesis.Find( S/*.Oriented(TopAbs_FORWARD)*/ );
 
   static list<const SMESHDS_Hypothesis*> empty;
   return empty;
@@ -1300,9 +1262,8 @@ void SMESHDS_Mesh::ClearScript()
 //=======================================================================
 bool SMESHDS_Mesh::HasMeshElements(const TopoDS_Shape & S) const
 {
-        if (myShape.IsNull()) MESSAGE("myShape is NULL");
-        int Index = myIndexToShape.FindIndex(S);
-        return myShapeIndexToSubMesh.find(Index)!=myShapeIndexToSubMesh.end();
+  int Index = myIndexToShape.FindIndex(S);
+  return mySubMeshHolder->Get( Index );
 }
 
 //=======================================================================
@@ -1311,7 +1272,7 @@ bool SMESHDS_Mesh::HasMeshElements(const TopoDS_Shape & S) const
 //=======================================================================
 bool SMESHDS_Mesh::HasHypothesis(const TopoDS_Shape & S)
 {
-  return myShapeToHypothesis.IsBound(S.Oriented(TopAbs_FORWARD));
+  return myShapeToHypothesis.IsBound(S/*.Oriented(TopAbs_FORWARD)*/);
 }
 
 //=======================================================================
@@ -1320,15 +1281,12 @@ bool SMESHDS_Mesh::HasHypothesis(const TopoDS_Shape & S)
 //=======================================================================
 SMESHDS_SubMesh * SMESHDS_Mesh::NewSubMesh(int Index)
 {
-  SMESHDS_SubMesh* SM = 0;
-  TShapeIndexToSubMesh::iterator anIter = myShapeIndexToSubMesh.find(Index);
-  if (anIter == myShapeIndexToSubMesh.end())
+  SMESHDS_SubMesh* SM = MeshElements( Index );
+  if ( !SM )
   {
     SM = new SMESHDS_SubMesh(this, Index);
-    myShapeIndexToSubMesh[Index]=SM;
+    mySubMeshHolder->Add( Index, SM );
   }
-  else
-    SM = anIter->second;
   return SM;
 }
 
@@ -1394,7 +1352,7 @@ const TopoDS_Shape& SMESHDS_Mesh::IndexToShape(int ShapeIndex) const
 
 int SMESHDS_Mesh::MaxSubMeshIndex() const
 {
-  return myShapeIndexToSubMesh.empty() ? 0 : myShapeIndexToSubMesh.rbegin()->first;
+  return mySubMeshHolder->GetMaxID();
 }
 
 //=======================================================================
@@ -1417,8 +1375,7 @@ int SMESHDS_Mesh::ShapeToIndex(const TopoDS_Shape & S) const
 //=======================================================================
 void SMESHDS_Mesh::SetNodeInVolume(const SMDS_MeshNode* aNode, int Index)
 {
-  //add(aNode, getSubmesh(Index));
-  if ( add( aNode, getSubmesh( Index )))
+  if ( add( aNode, NewSubMesh( Index )))
     ((SMDS_MeshNode*) aNode)->SetPosition( SMDS_SpacePosition::originSpacePosition());
 }
 
@@ -1429,7 +1386,7 @@ void SMESHDS_Mesh::SetNodeInVolume(const SMDS_MeshNode* aNode, int Index)
 void SMESHDS_Mesh::SetNodeOnFace(const SMDS_MeshNode* aNode, int Index, double u, double v)
 {
   //Set Position on Node
-  if ( add( aNode, getSubmesh( Index )))
+  if ( add( aNode, NewSubMesh( Index )))
     const_cast< SMDS_MeshNode* >
       ( aNode )->SetPosition(SMDS_PositionPtr(new SMDS_FacePosition( u, v)));
 }
@@ -1443,7 +1400,7 @@ void SMESHDS_Mesh::SetNodeOnEdge(const SMDS_MeshNode* aNode,
                                  double               u)
 {
   //Set Position on Node
-  if ( add( aNode, getSubmesh( Index )))
+  if ( add( aNode, NewSubMesh( Index )))
     const_cast< SMDS_MeshNode* >
       ( aNode )->SetPosition(SMDS_PositionPtr(new SMDS_EdgePosition(u)));
 }
@@ -1455,7 +1412,7 @@ void SMESHDS_Mesh::SetNodeOnEdge(const SMDS_MeshNode* aNode,
 void SMESHDS_Mesh::SetNodeOnVertex(const SMDS_MeshNode* aNode, int Index)
 {
   //Set Position on Node
-  if ( add( aNode, getSubmesh( Index )))
+  if ( add( aNode, NewSubMesh( Index )))
     const_cast< SMDS_MeshNode* >
       ( aNode )->SetPosition(SMDS_PositionPtr(new SMDS_VertexPosition()));
 }
@@ -1467,7 +1424,7 @@ void SMESHDS_Mesh::SetNodeOnVertex(const SMDS_MeshNode* aNode, int Index)
 void SMESHDS_Mesh::SetMeshElementOnShape(const SMDS_MeshElement* anElement,
                                          int                     Index)
 {
-  add( anElement, getSubmesh( Index ));
+  add( anElement, NewSubMesh( Index ));
 }
 
 //=======================================================================
@@ -1479,9 +1436,7 @@ SMESHDS_Mesh::~SMESHDS_Mesh()
   // myScript
   delete myScript;
   // submeshes
-  TShapeIndexToSubMesh::iterator i_sm = myShapeIndexToSubMesh.begin();
-  for ( ; i_sm != myShapeIndexToSubMesh.end(); ++i_sm )
-    delete i_sm->second;
+  delete mySubMeshHolder;
 }
 
 
@@ -2279,20 +2234,20 @@ void SMESHDS_Mesh::compactMesh()
   int myCellsSize = myCells.size();
   int newSmdsId = 0;
   for (int i = 0; i < myCellsSize; i++)
+  {
+    if (myCells[i])
     {
-      if (myCells[i])
-        {
-          newSmdsId++; // SMDS id start to 1
-          assert(newSmdsId <= newCellSize);
-          newCells[newSmdsId] = myCells[i];
-          newCells[newSmdsId]->setId(newSmdsId);
-          //MESSAGE("myCells["<< i << "] --> newCells[" << newSmdsId << "]");
-          int idvtk = myCells[i]->getVtkId();
-          //newSmdsToVtk[newSmdsId] = idvtk;
-          assert(idvtk < newCellSize);
-          newVtkToSmds[idvtk] = newSmdsId;
-        }
+      newSmdsId++; // SMDS id start to 1
+      assert(newSmdsId <= newCellSize);
+      newCells[newSmdsId] = myCells[i];
+      newCells[newSmdsId]->setId(newSmdsId);
+      //MESSAGE("myCells["<< i << "] --> newCells[" << newSmdsId << "]");
+      int idvtk = myCells[i]->getVtkId();
+      //newSmdsToVtk[newSmdsId] = idvtk;
+      assert(idvtk < newCellSize);
+      newVtkToSmds[idvtk] = newSmdsId;
     }
+  }
 
   myCells.swap(newCells);
   //myCellIdSmdsToVtk.swap(newSmdsToVtk);
@@ -2305,12 +2260,9 @@ void SMESHDS_Mesh::compactMesh()
 
   // --- compact list myNodes and myElements in submeshes
 
-  map<int,SMESHDS_SubMesh*>::iterator it = myShapeIndexToSubMesh.begin();
-  for(; it != myShapeIndexToSubMesh.end(); ++it)
-    {
-      (*it).second->compactList();
-    }
-
+  SMESHDS_SubMeshIteratorPtr smIt = SubMeshes();
+  while ( SMESHDS_SubMesh* sm = const_cast< SMESHDS_SubMesh* >( smIt->next() ))
+    sm->compactList();
 }
 
 void SMESHDS_Mesh::CleanDownWardConnectivity()
index 8b8fc0a55b0ef5f9d4f93240732a14c802ed22a4..e51df85d098d56f7c31578fc02615d4ed4b2f9a0 100644 (file)
@@ -35,6 +35,8 @@
 #include <TopTools_IndexedMapOfShape.hxx>
 #include <TopoDS_Shape.hxx>
 
+#include <map>
+
 class TopoDS_Solid ;
 class TopoDS_Shell ;
 class TopoDS_Face  ;
@@ -50,8 +52,6 @@ class SMDS_MeshVolume   ;
 class SMDS_Mesh0DElement;
 class SMDS_BallElement;
 
-#include <map>
-
 /*
  * Using of native hash_map isn't portable and don't work on WIN32 platform.
  * So this functionality implement on new NCollection_DataMap technology
@@ -566,9 +566,7 @@ public:
   SMESHDS_SubMesh * MeshElements(const TopoDS_Shape & S) const;
   SMESHDS_SubMesh * MeshElements(const int Index) const;
   std::list<int> SubMeshIndices() const;
-  const std::map<int,SMESHDS_SubMesh*>& SubMeshes() const
-  { return myShapeIndexToSubMesh; }
-  const TopoDS_Shape& GetCurrentSubShape() const { return myCurSubShape; }
+  SMESHDS_SubMeshIteratorPtr SubMeshes() const;
 
   bool HasHypothesis(const TopoDS_Shape & S);
   const std::list<const SMESHDS_Hypothesis*>& GetHypothesis(const TopoDS_Shape & S) const;
@@ -601,22 +599,14 @@ public:
   ~SMESHDS_Mesh();
   
 private:
-  void addNodeToSubmesh( const SMDS_MeshNode* aNode, int Index )
-  {
-    //Update or build submesh
-    std::map<int,SMESHDS_SubMesh*>::iterator it = myShapeIndexToSubMesh.find( Index );
-    if ( it == myShapeIndexToSubMesh.end() )
-      it = myShapeIndexToSubMesh.insert( std::make_pair(Index, new SMESHDS_SubMesh(this, Index) )).first;
-    it->second->AddNode( aNode ); // add aNode to submesh
-  }
-  
+
   ShapeToHypothesis          myShapeToHypothesis;
 
   int                        myMeshID, myPersistentID;
   TopoDS_Shape               myShape;
 
-  typedef std::map<int,SMESHDS_SubMesh*> TShapeIndexToSubMesh;
-  TShapeIndexToSubMesh myShapeIndexToSubMesh;
+  class SubMeshHolder;
+  SubMeshHolder*             mySubMeshHolder;
 
   TopTools_IndexedMapOfShape myIndexToShape;
 
@@ -626,14 +616,8 @@ private:
   SMESHDS_Script*            myScript;
   bool                       myIsEmbeddedMode;
 
-  // optimize addition of nodes/elements to submeshes by, SetNodeInVolume() etc:
-  // avoid search of submeshes in maps
   bool add( const SMDS_MeshElement* elem, SMESHDS_SubMesh* subMesh );
   SMESHDS_SubMesh* getSubmesh( const TopoDS_Shape & shape);
-  SMESHDS_SubMesh* getSubmesh( const int            Index );
-  int                        myCurSubID;
-  TopoDS_Shape               myCurSubShape;
-  SMESHDS_SubMesh*           myCurSubMesh;
 };
 
 
diff --git a/src/SMESHDS/SMESHDS_TSubMeshHolder.hxx b/src/SMESHDS/SMESHDS_TSubMeshHolder.hxx
new file mode 100644 (file)
index 0000000..52c9eb2
--- /dev/null
@@ -0,0 +1,151 @@
+// Copyright (C) 2007-2014  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 __SMESHDS_SubMeshHolder_HXX__
+#define __SMESHDS_SubMeshHolder_HXX__
+
+#include <vector>
+#include <map>
+
+//=======================================================================
+/*!
+ * \brief A binder of a sub-mesh to its ID which can be negative. Provides fast
+ *        access to a sub-mesh by its ID.
+ *
+ * Issue 52457: Addition of hypotheses is 8 time longer than meshing.
+ */
+//=======================================================================
+
+template <class SUBMESH>
+class SMESHDS_TSubMeshHolder
+{
+  std::vector< SUBMESH* >   myVec; // for ID >= 0
+  std::map< int, SUBMESH* > myMap; // for ID < 0
+
+public:
+
+  ~SMESHDS_TSubMeshHolder()
+  {
+    DeleteAll();
+  }
+  void Add( int id, SUBMESH* sm )
+  {
+    if ( id < 0 )
+    {
+      myMap[ id ] = sm;
+    }
+    else
+    {
+      if ( myVec.size() <= id )
+        myVec.resize( id+1, (SUBMESH*) NULL );
+      myVec[ id ] = sm;
+    }
+  }
+  SUBMESH* Get( int id ) const
+  {
+    if ( id < 0 )
+    {
+      typename std::map< int, SUBMESH* >::const_iterator i2sm = myMap.find( id );
+      return (SUBMESH*) ( i2sm == myMap.end() ? NULL : i2sm->second );
+    }
+    else
+    {
+      return (SUBMESH*) ( id >= myVec.size() ? NULL : myVec[ id ]);
+    }
+  }
+  void DeleteAll()
+  {
+    for ( size_t i = 0; i < myVec.size(); ++i )
+      if ( SUBMESH* sm = myVec[i] )
+      {
+        myVec[i] = 0; // avoid access via Get(i)
+        delete sm;
+      }
+    myVec.clear();
+
+    typename std::map< int, SUBMESH* >::iterator i2sm = myMap.begin();
+    for ( ; i2sm != myMap.end(); ++i2sm )
+      if ( SUBMESH* sm = i2sm->second )
+      {
+        i2sm->second = 0; // avoid access via Get(i)
+        delete sm;
+      }
+    myMap.clear();
+  }
+  int GetMinID() const
+  {
+    return myMap.empty() ? 0 : myMap.begin()->first;
+  }
+  int GetMaxID() const
+  {
+    return myVec.empty() ? ( myMap.empty() ? 0 : myMap.rbegin()->first ) : myVec.size();
+  }
+
+  //-----------------------------------------------------------------------
+  struct Iterator : public SMDS_Iterator< SUBMESH* >
+  {
+    const SMESHDS_TSubMeshHolder<SUBMESH>* myHolder;
+    SUBMESH* myNext;
+    int myCurID, myEndID, myIDDelta;
+
+    void init( const SMESHDS_TSubMeshHolder<SUBMESH>* holder,
+               int firstID, int endID, int delta )
+    {
+      myHolder  = holder;
+      myNext    = 0;
+      myCurID   = firstID;
+      myEndID   = endID;
+      myIDDelta = delta;
+
+      next();
+    }
+
+    bool more()
+    {
+      return myNext;
+    }
+
+    SUBMESH* next()
+    {
+      SUBMESH* res = myNext;
+      myNext = 0;
+      while ( !myNext && myCurID != myEndID )
+      {
+        myNext = myHolder->Get( myCurID );
+        myCurID += myIDDelta;
+      }
+      return res;
+    }
+    virtual ~Iterator() {}
+  };
+  //-----------------------------------------------------------------------
+
+  SMDS_Iterator< SUBMESH* >* GetIterator(const bool reverse=false) const
+  {
+    Iterator* iter = new Iterator;
+    if ( reverse ) iter->init( this, GetMaxID(), GetMinID()-1, -1 );
+    else           iter->init( this, GetMinID(), GetMaxID()+1, +1 );
+    return iter;
+  }
+};
+
+
+#endif
index 39f74475706b955df8a2a1b79cf69f97313339bf..d92818942747496b2d24ef0ba22587c8458025e9 100644 (file)
@@ -146,6 +146,7 @@ SET(_moc_HEADERS
 
 # header files / no moc processing
 SET(_other_HEADERS
+  SMESHGUI_Operations.h
   SMESHGUI_Utils.h
   SMESHGUI_HypothesesUtils.h
   SMESHGUI_Selection.h
index 9e70d965de2d25a6fcccdaef81f27152f7935771..8723415cda627dd5cbdc57350b073a769c3644ce 100644 (file)
@@ -64,6 +64,7 @@
 #include "SMESHGUI_MeshPatternDlg.h"
 #include "SMESHGUI_MultiEditDlg.h"
 #include "SMESHGUI_NodesDlg.h"
+#include "SMESHGUI_Operations.h"
 #include "SMESHGUI_Preferences_ScalarBarDlg.h"
 #include "SMESHGUI_PropertiesDlg.h"
 #include "SMESHGUI_RemoveElementsDlg.h"
@@ -82,6 +83,7 @@
 #include "SMESHGUI_TransparencyDlg.h"
 
 #include "SMESHGUI_FilterUtils.h"
+#include "SMESHGUI_GEOMGenUtils.h"
 #include "SMESHGUI_GroupUtils.h"
 #include "SMESHGUI_HypothesesUtils.h"
 #include "SMESHGUI_MeshUtils.h"
@@ -210,27 +212,29 @@ namespace
     QStringList filter;
     std::string myExtension;
 
-    if ( theCommandID == 113 ) {
+    if ( theCommandID == SMESHOp::OpImportMED ) {
       filter.append( QObject::tr( "MED_FILES_FILTER" ) + " (*.*med)" );
       filter.append( QObject::tr( "ALL_FILES_FILTER" ) + " (*)" );
     }
-    else if ( theCommandID == 112 ) {
+    else if ( theCommandID == SMESHOp::OpImportUNV ) {
       filter.append( QObject::tr( "IDEAS_FILES_FILTER" ) + " (*.unv)" );
     }
-    else if ( theCommandID == 111 ) {
+    else if ( theCommandID == SMESHOp::OpImportDAT ) {
       filter.append( QObject::tr( "DAT_FILES_FILTER" ) + " (*.dat)" );
     }
-    else if ( theCommandID == 115 ) {
+    else if ( theCommandID == SMESHOp::OpImportSTL ) {
       filter.append( QObject::tr( "STL_FILES_FILTER" ) + " (*.stl)" );
     }
-    else if ( theCommandID == 116 ) {
+  #ifdef WITH_CGNS
+    else if ( theCommandID == SMESHOp::OpImportCGNS ) {
       filter.append( QObject::tr( "CGNS_FILES_FILTER" ) + " (*.cgns)" );
     }
-    else if ( theCommandID == 117 ) {
+  #endif
+    else if ( theCommandID == SMESHOp::OpImportSAUV ) {
       filter.append( QObject::tr( "SAUV files (*.sauv*)" ) );
       filter.append( QObject::tr( "All files (*)" ) );
     }
-    else if ( theCommandID == 118 ) {
+    else if ( theCommandID == SMESHOp::OpImportGMF ) {
       filter.append( QObject::tr( "GMF_ASCII_FILES_FILTER" ) + " (*.mesh)"  );
       filter.append( QObject::tr( "GMF_BINARY_FILES_FILTER") + " (*.meshb)" );
     }
@@ -242,7 +246,7 @@ namespace
     QStringList filenames;
     bool toCreateGroups = true;
 
-    // if ( theCommandID == 118 ) { // GMF
+    // if ( theCommandID == SMESHOp::OpImportGMF ) { // GMF
     //   SalomeApp_CheckFileDlg* fd = new SalomeApp_CheckFileDlg
     //     ( SMESHGUI::desktop(), true, QObject::tr("SMESH_REQUIRED_GROUPS"), true, true );
     //   fd->setWindowTitle( QObject::tr( "SMESH_IMPORT_MESH" ) );
@@ -273,14 +277,14 @@ namespace
         SMESH::mesh_array_var aMeshes = new SMESH::mesh_array;
         try {
           switch ( theCommandID ) {
-          case 111:
+          case SMESHOp::OpImportDAT:
             {
               // DAT format (currently unsupported)
               errors.append( QString( "%1 :\n\t%2" ).arg( filename ).
                              arg( QObject::tr( "SMESH_ERR_NOT_SUPPORTED_FORMAT" ) ) );
               break;
             }
-          case 112:
+          case SMESHOp::OpImportUNV:
             {
               // UNV format
               aMeshes->length( 1 );
@@ -290,7 +294,7 @@ namespace
                                arg( QObject::tr( "SMESH_ERR_UNKNOWN_IMPORT_ERROR" ) ) );
               break;
             }
-          case 113:
+          case SMESHOp::OpImportMED:
             {
               // MED format
               SMESH::DriverMED_ReadStatus res;
@@ -301,7 +305,7 @@ namespace
               }
               break;
             }
-          case 115:
+          case SMESHOp::OpImportSTL:
             {
               // STL format
               aMeshes->length( 1 );
@@ -312,7 +316,8 @@ namespace
               }
               break;
             }
-          case 116:
+        #ifdef WITH_CGNS
+          case SMESHOp::OpImportCGNS:
             {
               // CGNS format
               SMESH::DriverMED_ReadStatus res;
@@ -323,7 +328,8 @@ namespace
               }
               break;
             }
-          case 117:
+        #endif
+          case SMESHOp::OpImportSAUV:
             {
               // SAUV format
               SMESH::DriverMED_ReadStatus res;
@@ -334,7 +340,7 @@ namespace
               }
               break;
             }
-          case 118:
+          case SMESHOp::OpImportGMF:
             {
               // GMF format
               SMESH::ComputeError_var res;
@@ -365,7 +371,7 @@ namespace
             _PTR(StudyBuilder) aBuilder = aStudy->NewBuilder();
             _PTR(AttributePixMap) aPixmap = aBuilder->FindOrCreateAttribute( aMeshSO, "AttributePixMap" );
             aPixmap->SetPixMap( "ICON_SMESH_TREE_MESH_IMPORTED" );
-            if ( theCommandID == 112 ) // mesh names aren't taken from the file for UNV import
+            if ( theCommandID == SMESHOp::OpImportUNV ) // mesh names aren't taken from the file for UNV import
               SMESH::SetName( aMeshSO, QFileInfo(filename).fileName() );
 
             anEntryList.append( aMeshSO->GetID().c_str() );
@@ -413,13 +419,17 @@ namespace
     if( aSel )
       aSel->selectedObjects( selected );
 
-    const bool isMED = ( theCommandID == 122 || theCommandID == 125 );
-    const bool isDAT = ( theCommandID == 121 || theCommandID == 124 );
-    const bool isUNV = ( theCommandID == 123 || theCommandID == 126 );
-    const bool isSTL = ( theCommandID == 140 || theCommandID == 141 );
-    const bool isCGNS= ( theCommandID == 142 || theCommandID == 143 );
-    const bool isSAUV= ( theCommandID == 144 || theCommandID == 145 );
-    const bool isGMF = ( theCommandID == 146 || theCommandID == 147 );
+    const bool isDAT = ( theCommandID == SMESHOp::OpExportDAT || theCommandID == SMESHOp::OpPopupExportDAT );
+    const bool isMED = ( theCommandID == SMESHOp::OpExportMED || theCommandID == SMESHOp::OpPopupExportMED );
+    const bool isUNV = ( theCommandID == SMESHOp::OpExportUNV || theCommandID == SMESHOp::OpPopupExportUNV );
+    const bool isSTL = ( theCommandID == SMESHOp::OpExportSTL || theCommandID == SMESHOp::OpPopupExportSTL );
+  #ifdef WITH_CGNS
+    const bool isCGNS= ( theCommandID == SMESHOp::OpExportCGNS || theCommandID == SMESHOp::OpPopupExportCGNS );
+  #else
+    const bool isCGNS= false;
+  #endif
+    const bool isSAUV= ( theCommandID == SMESHOp::OpExportSAUV || theCommandID == SMESHOp::OpPopupExportSAUV );
+    const bool isGMF = ( theCommandID == SMESHOp::OpExportGMF || theCommandID == SMESHOp::OpPopupExportGMF );
 
     // actually, the following condition can't be met (added for insurance)
     if( selected.Extent() == 0 ||
@@ -918,22 +928,22 @@ namespace
           if(SMESH_Actor *anActor = SMESH::FindActorByEntry(IObject->getEntry())){
             unsigned int aMode = anActor->GetEntityMode();
             switch(theCommandID){
-            case 222:
-              InverseEntityMode(aMode,SMESH_Actor::eBallElem);
-              break;
-            case 216:
+            case SMESHOp::OpDE0DElements:
               InverseEntityMode(aMode,SMESH_Actor::e0DElements);
               break;
-            case 217:
+            case SMESHOp::OpDEEdges:
               InverseEntityMode(aMode,SMESH_Actor::eEdges);
               break;
-            case 218:
+            case SMESHOp::OpDEFaces:
               InverseEntityMode(aMode,SMESH_Actor::eFaces);
               break;
-            case 219:
+            case SMESHOp::OpDEVolumes:
               InverseEntityMode(aMode,SMESH_Actor::eVolumes);
               break;
-            case 220:
+            case SMESHOp::OpDEBalls:
+              InverseEntityMode(aMode,SMESH_Actor::eBallElem);
+              break;
+            case SMESHOp::OpDEAllEntity:
               aMode = SMESH_Actor::eAllEntity;
               break;
             }
@@ -1274,7 +1284,7 @@ namespace
     if( !aSel || !appStudy )
       return;
 
-    if( theCommandID == 1134 ) { // Clipping dialog can be activated without selection
+    if( theCommandID == SMESHOp::OpClipping ) { // Clipping dialog can be activated without selection
       if( SMESHGUI* aModule = SMESHGUI::GetSMESHGUI() ) {
         aModule->EmitSignalDeactivateDialog();
         if( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( aModule ) )
@@ -1289,12 +1299,12 @@ namespace
 
     if(selected.Extent() >= 1){
       switch(theCommandID){
-      case 1133:{
+      case SMESHOp::OpTransparency:{
         SMESHGUI::GetSMESHGUI()->EmitSignalDeactivateDialog();
         (new SMESHGUI_TransparencyDlg( SMESHGUI::GetSMESHGUI() ))->show();
         return;
       }
-      case 1132: {
+      case SMESHOp::OpProperties: {
         double color[3];
         QColor faceColor, edgeColor, nodeColor, elem0dColor, ballColor;
         QColor orientationColor, outlineColor, volumeColor;
@@ -1515,7 +1525,7 @@ namespace
           SMESH::RepaintCurrentView();
         } // if ( dlg.exec() )
         return;
-      } // case 1132:
+      } // case SMESHOp::OpProperties:
       } // switch(theCommandID)
       SALOME_ListIteratorOfListIO It( selected );
       for( ; It.More(); It.Next()){
@@ -1523,26 +1533,26 @@ namespace
         if(IObject->hasEntry()){
           if(SMESH_Actor *anActor = SMESH::FindActorByEntry(IObject->getEntry())){
             switch(theCommandID){
-            case 211:
+            case SMESHOp::OpDMWireframe:
               anActor->SetRepresentation(SMESH_Actor::eEdge);
               break;
-            case 212:
+            case SMESHOp::OpDMShading:
               anActor->SetRepresentation(SMESH_Actor::eSurface);
               break;
-            case 213:
+            case SMESHOp::OpDMShrink:
               if(anActor->IsShrunk())
                 anActor->UnShrink();
               else
                 anActor->SetShrink();
               break;
-            case 215:
+            case SMESHOp::OpDMNodes:
               anActor->SetRepresentation(SMESH_Actor::ePoint);
               break;
-            case 231:
+            case SMESHOp::OpRepresentationLines:
               if(anActor->GetQuadratic2DRepresentation() != SMESH_Actor::eLines)
                 anActor->SetQuadratic2DRepresentation(SMESH_Actor::eLines);
               break;
-            case 232:
+            case SMESHOp::OpRepresentationArcs:
               if(anActor->GetQuadratic2DRepresentation() != SMESH_Actor::eArcs)
                 anActor->SetQuadratic2DRepresentation(SMESH_Actor::eArcs);
               break;
@@ -1567,82 +1577,82 @@ namespace
         SMESH_Actor::eControl aControl = SMESH_Actor::eNone;
         if(SMESH_Actor *anActor = SMESH::FindActorByEntry(anIO->getEntry())) {
           switch ( theCommandID ){
-          case 6001:
-            aControl = SMESH_Actor::eLength;
+          case SMESHOp::OpFreeNode:
+            aControl = SMESH_Actor::eFreeNodes;
             break;
-          case 6018:
-            aControl = SMESH_Actor::eLength2D;
+          case SMESHOp::OpEqualNode:
+            aControl = SMESH_Actor::eCoincidentNodes;
             break;
-          case 6002:
+          case SMESHOp::OpFreeEdge:
             aControl = SMESH_Actor::eFreeEdges;
             break;
-          case 6003:
+          case SMESHOp::OpFreeBorder:
             aControl = SMESH_Actor::eFreeBorders;
             break;
-          case 6004:
+          case SMESHOp::OpLength:
+            aControl = SMESH_Actor::eLength;
+            break;
+          case SMESHOp::OpConnection:
             aControl = SMESH_Actor::eMultiConnection;
             break;
-          case 6005:
-            aControl = SMESH_Actor::eFreeNodes;
+          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 6019:
+          case SMESHOp::OpConnection2D:
             aControl = SMESH_Actor::eMultiConnection2D;
             break;
-          case 6011:
+          case SMESHOp::OpArea:
             aControl = SMESH_Actor::eArea;
             break;
-          case 6012:
+          case SMESHOp::OpTaper:
             aControl = SMESH_Actor::eTaper;
             break;
-          case 6013:
+          case SMESHOp::OpAspectRatio:
             aControl = SMESH_Actor::eAspectRatio;
             break;
-          case 6017:
-            aControl = SMESH_Actor::eAspectRatio3D;
-            break;
-          case 6014:
+          case SMESHOp::OpMinimumAngle:
             aControl = SMESH_Actor::eMinimumAngle;
             break;
-          case 6015:
+          case SMESHOp::OpWarpingAngle:
             aControl = SMESH_Actor::eWarping;
             break;
-          case 6016:
+          case SMESHOp::OpSkew:
             aControl = SMESH_Actor::eSkew;
             break;
-          case 6009:
-            aControl = SMESH_Actor::eVolume3D;
+          case SMESHOp::OpMaxElementLength2D:
+            aControl = SMESH_Actor::eMaxElementLength2D;
             break;
-          case 6021:
-            aControl = SMESH_Actor::eFreeFaces;
+          case SMESHOp::OpEqualFace:
+            aControl = SMESH_Actor:: eCoincidentElems2D;
             break;
-          case 6022:
-            aControl = SMESH_Actor::eMaxElementLength2D;
+          case SMESHOp::OpAspectRatio3D:
+            aControl = SMESH_Actor::eAspectRatio3D;
+            break;
+          case SMESHOp::OpVolume:
+            aControl = SMESH_Actor::eVolume3D;
             break;
-          case 6023:
+          case SMESHOp::OpMaxElementLength3D:
             aControl = SMESH_Actor::eMaxElementLength3D;
             break;
-          case 6024:
+          case SMESHOp::OpBareBorderVolume:
             aControl = SMESH_Actor::eBareBorderVolume;
             break;
-          case 6025:
-            aControl = SMESH_Actor::eBareBorderFace;
-            break;
-          case 6026:
+          case SMESHOp::OpOverConstrainedVolume:
             aControl = SMESH_Actor::eOverConstrainedVolume;
             break;
-          case 6027:
-            aControl = SMESH_Actor::eOverConstrainedFace;
-            break;
-          case 6028:
-            aControl = SMESH_Actor::eCoincidentNodes;
-            break;
-          case 6029:
-            aControl = SMESH_Actor::eCoincidentElems1D;
-            break;
-          case 6030:
-            aControl = SMESH_Actor:: eCoincidentElems2D;
-            break;
-          case 6031:
+          case SMESHOp::OpEqualVolume:
             aControl = SMESH_Actor::eCoincidentElems3D;
             break;
           }
@@ -2348,25 +2358,26 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   //QAction* act = action( theCommandID );
 
   switch (theCommandID) {
-  case 33:                                      // DELETE
+  case SMESHOp::OpDelete:
     if(checkLock(aStudy)) break;
     OnEditDelete();
     break;
-
-  case 116:
-  case 115:
-  case 117:
-  case 118:
-  case 113:
-  case 112:
-  case 111:                                     // IMPORT
+  case SMESHOp::OpImportDAT:
+  case SMESHOp::OpImportUNV:
+  case SMESHOp::OpImportMED:
+  case SMESHOp::OpImportSTL:
+#ifdef WITH_CGNS
+  case SMESHOp::OpImportCGNS:
+#endif
+  case SMESHOp::OpImportSAUV:
+  case SMESHOp::OpImportGMF:
     {
       if(checkLock(aStudy)) break;
       ::ImportMeshesFromFile(GetSMESHGen(),theCommandID);
       break;
     }
 
-  case 150:    //MED FILE INFORMATION
+  case SMESHOp::OpFileInformation:
     {
       SALOME_ListIO selected;
       LightApp_SelectionMgr *aSel = SMESHGUI::selectionMgr();
@@ -2384,27 +2395,30 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
-
-  case 122:                                     // EXPORT MED
-  case 121:
-  case 123:
-  case 124:
-  case 125:
-  case 126:
-  case 140:
-  case 141:
-  case 142:
-  case 143:
-  case 144:
-  case 145:
-  case 146:
-  case 147:
+  case SMESHOp::OpExportDAT:
+  case SMESHOp::OpExportMED:
+  case SMESHOp::OpExportUNV:
+  case SMESHOp::OpExportSTL:
+#ifdef WITH_CGNS
+  case SMESHOp::OpExportCGNS:
+#endif
+  case SMESHOp::OpExportSAUV:
+  case SMESHOp::OpExportGMF:
+  case SMESHOp::OpPopupExportDAT:
+  case SMESHOp::OpPopupExportMED:
+  case SMESHOp::OpPopupExportUNV:
+  case SMESHOp::OpPopupExportSTL:
+#ifdef WITH_CGNS
+  case SMESHOp::OpPopupExportCGNS:
+#endif
+  case SMESHOp::OpPopupExportSAUV:
+  case SMESHOp::OpPopupExportGMF:
     {
       ::ExportMeshToFile(theCommandID);
       break;
     }
 
-  case 200:                                     // SCALAR BAR
+  case SMESHOp::OpReset:                      // SCALAR BAR
     {
       LightApp_SelectionMgr *aSel = SMESHGUI::selectionMgr();
       SALOME_ListIO selected;
@@ -2424,19 +2438,19 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
-  case 201:
+  case SMESHOp::OpScalarBarProperties:
     {
       SMESHGUI_Preferences_ScalarBarDlg::ScalarBarProperties( this );
       break;
     }
-  case 2021:
+  case SMESHOp::OpSaveDistribution:
     {
       // dump control distribution data to the text file
       ::SaveDistribution();
       break;
     }
 
-  case 2022:
+  case SMESHOp::OpShowDistribution:
     {
       // show/ distribution
       ::ShowDistribution();
@@ -2444,7 +2458,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
     }
 
 #ifndef DISABLE_PLOT2DVIEWER
-  case 2023:
+  case SMESHOp::OpPlotDistribution:
     {
       // plot distribution
       ::PlotDistribution();
@@ -2453,43 +2467,43 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
 #endif
 
     // Auto-color
-  case 1136:
+  case SMESHOp::OpAutoColor:
     ::AutoColor();
   break;
 
-  case 1137:
+  case SMESHOp::OpDisableAutoColor:
     ::DisableAutoColor();
   break;
 
-  case 1134: // Clipping
-  case 1133: // Tranparency
-  case 1132: // Display preferences (colors, shrink size, line width, ...)
+  case SMESHOp::OpClipping:
+  case SMESHOp::OpTransparency:
+  case SMESHOp::OpProperties: // Display preferences (colors, shrink size, line width, ...)
 
     // Display Mode
-  case 215: // Nodes
-  case 213: // Nodes
-  case 212: // Nodes
-  case 211: // Nodes
+  case SMESHOp::OpDMWireframe:
+  case SMESHOp::OpDMShading:
+  case SMESHOp::OpDMNodes:
+  case SMESHOp::OpDMShrink:
     ::SetDisplayMode(theCommandID, myMarkerMap);
   break;
 
   //2D quadratic representation
-  case 231:
-  case 232:
+  case SMESHOp::OpRepresentationLines:
+  case SMESHOp::OpRepresentationArcs:
     ::SetDisplayMode(theCommandID, myMarkerMap);
   break;
 
   // Display Entity
-  case 216: // 0D elements
-  case 217: // Edges
-  case 218: // Faces
-  case 219: // Volumes
-  case 220: // All Entity
-  case 222: // Balls
+  case SMESHOp::OpDE0DElements:
+  case SMESHOp::OpDEEdges:
+  case SMESHOp::OpDEFaces:
+  case SMESHOp::OpDEVolumes:
+  case SMESHOp::OpDEBalls:
+  case SMESHOp::OpDEAllEntity:
     ::SetDisplayEntity(theCommandID);
   break;
 
-  case 221: // Orientation of faces
+  case SMESHOp::OpOrientationOnFaces:
     {
       LightApp_SelectionMgr* mgr = selectionMgr();
       SALOME_ListIO selected; mgr->selectedObjects( selected );
@@ -2506,7 +2520,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       break;
     }
 
-  case 214:                                     // UPDATE
+  case SMESHOp::OpUpdate:
     {
       if(checkLock(aStudy)) break;
       SUIT_OverrideCursor wc;
@@ -2530,15 +2544,15 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       break;
     }
 
-  case 300:                                     // ERASE
-  case 301:                                     // DISPLAY
-  case 302:                                     // DISPLAY ONLY
+  case SMESHOp::OpHide:
+  case SMESHOp::OpShow:
+  case SMESHOp::OpShowOnly:
     {
       SMESH::EDisplaing anAction;
       switch (theCommandID) {
-      case 300: anAction = SMESH::eErase; break;
-      case 301: anAction = SMESH::eDisplay; break;
-      case 302: anAction = SMESH::eDisplayOnly; break;
+      case SMESHOp::OpHide: anAction = SMESH::eErase; break;
+      case SMESHOp::OpShow: anAction = SMESH::eDisplay; break;
+      case SMESHOp::OpShowOnly: anAction = SMESH::eDisplayOnly; break;
       }
 
       LightApp_SelectionMgr *aSel = SMESHGUI::selectionMgr();
@@ -2546,7 +2560,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       if (aSel)
         aSel->selectedObjects( sel_objects );
 
-      if( theCommandID==302 )
+      if( theCommandID==SMESHOp::OpShowOnly )
       {
         MESSAGE("anAction = SMESH::eDisplayOnly");
         startOperation( myEraseAll );
@@ -2579,7 +2593,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
         }
 
         // PAL13338 + PAL15161 -->
-        if ( ( theCommandID==301 || theCommandID==302 ) && !checkLock(aStudy)) {
+        if ( ( theCommandID==SMESHOp::OpShow || theCommandID==SMESHOp::OpShowOnly ) && !checkLock(aStudy)) {
           MESSAGE("anAction = SMESH::eDisplayOnly");
           SMESH::UpdateView();
           SMESHGUI::GetSMESHGUI()->EmitSignalVisibilityChanged();
@@ -2601,7 +2615,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       break;
     }
 
-  case 4000:                                    // NODES
+  case SMESHOp::OpNode:
     {
       if(checkLock(aStudy)) break;
 
@@ -2618,33 +2632,23 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       break;
     }
 
-  case 2151:  // FILTER
-  {
-    if ( vtkwnd )
-    {
-      EmitSignalDeactivateDialog();
-      ( new SMESHGUI_FilterDlg( this, SMESH::EDGE ) )->show();
-    }
-    break;
-  }
-
-  case 701: // COMPUTE MESH
-  case 711: // PRECOMPUTE MESH
-  case 712: // EVALUATE MESH
-  case 713: // MESH ORDER
-  case 702: // Create mesh
-  case 703: // Create sub-mesh
-  case 704: // Edit mesh/sub-mesh
+  case SMESHOp::OpCreateMesh:
+  case SMESHOp::OpCreateSubMesh:
+  case SMESHOp::OpEditMeshOrSubMesh:
+  case SMESHOp::OpCompute:
+  case SMESHOp::OpPreCompute:
+  case SMESHOp::OpEvaluate:
+  case SMESHOp::OpMeshOrder:
     startOperation( theCommandID );
     break;
-  case 705: // copy mesh
+  case SMESHOp::OpCopyMesh:
     {
       if (checkLock(aStudy)) break;
       EmitSignalDeactivateDialog();
       ( new SMESHGUI_CopyMeshDlg( this ) )->show();
     }
     break;
-  case 710: // Build compound mesh
+  case SMESHOp::OpBuildCompoundMesh:
     {
       if (checkLock(aStudy)) break;
       EmitSignalDeactivateDialog();
@@ -2652,8 +2656,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
     }
     break;
 
-  case 407: // DIAGONAL INVERSION
-  case 408: // Delete diagonal
+  case SMESHOp::OpDiagonalInversion:
+  case SMESHOp::OpUnionOfTwoTriangle:
     {
       if ( !vtkwnd )
       {
@@ -2675,16 +2679,16 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       */
       EmitSignalDeactivateDialog();
-      if ( theCommandID == 407 )
+      if ( theCommandID == SMESHOp::OpDiagonalInversion )
         ( new SMESHGUI_TrianglesInversionDlg( this ) )->show();
       else
         ( new SMESHGUI_UnionOfTwoTrianglesDlg( this ) )->show();
       break;
     }
-  case 409: // Change orientation
-  case 410: // Union of triangles
-  case 411: // Cutting of quadrangles
-  case 419: // Splitting volumes into tetrahedra
+  case SMESHOp::OpOrientation:
+  case SMESHOp::OpUnionOfTriangles:
+  case SMESHOp::OpCuttingOfQuadrangles:
+  case SMESHOp::OpSplitVolumes:
     {
       if ( !vtkwnd )
       {
@@ -2698,11 +2702,11 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
 
       EmitSignalDeactivateDialog();
       SMESHGUI_MultiEditDlg* aDlg = NULL;
-      if ( theCommandID == 409 )
+      if ( theCommandID == SMESHOp::OpOrientation )
         aDlg = new SMESHGUI_ChangeOrientationDlg(this);
-      else if ( theCommandID == 410 )
+      else if ( theCommandID == SMESHOp::OpUnionOfTriangles )
         aDlg = new SMESHGUI_UnionOfTrianglesDlg(this);
-      else if ( theCommandID == 419 )
+      else if ( theCommandID == SMESHOp::OpSplitVolumes )
         aDlg = new SMESHGUI_SplitVolumesDlg(this);
       else
         aDlg = new SMESHGUI_CuttingOfQuadsDlg(this);
@@ -2710,7 +2714,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       aDlg->show();
       break;
     }
-  case 412: // Smoothing
+  case SMESHOp::OpSmoothing:
     {
       if(checkLock(aStudy)) break;
       if( vtkwnd ) {
@@ -2723,7 +2727,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
-  case 413: // Extrusion
+  case SMESHOp::OpExtrusion:
     {
       if (checkLock(aStudy)) break;
       if (vtkwnd) {
@@ -2735,7 +2739,19 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
-  case 414: // Revolution
+  case SMESHOp::OpExtrusionAlongAPath:
+    {
+      if (checkLock(aStudy)) break;
+      if (vtkwnd) {
+        EmitSignalDeactivateDialog();
+        ( new SMESHGUI_ExtrusionAlongPathDlg( this ) )->show();
+      } else {
+        SUIT_MessageBox::warning(desktop(),
+                                 tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK"));
+      }
+      break;
+    }
+  case SMESHOp::OpRevolution:
     {
       if(checkLock(aStudy)) break;
       if( vtkwnd ) {
@@ -2748,7 +2764,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
-  case 415: // Pattern mapping
+  case SMESHOp::OpPatternMapping:
     {
       if ( checkLock( aStudy ) )
         break;
@@ -2763,27 +2779,15 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
-  case 416: // Extrusion along a path
-    {
-      if (checkLock(aStudy)) break;
-      if (vtkwnd) {
-        EmitSignalDeactivateDialog();
-        ( new SMESHGUI_ExtrusionAlongPathDlg( this ) )->show();
-      } else {
-        SUIT_MessageBox::warning(desktop(),
-                                 tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK"));
-      }
-      break;
-    }
-  case 417: // Convert mesh to quadratic
-  case 418: // create 2D mesh from 3D
-  case 420: // Reorient faces
-  case 806: // CREATE GEO GROUP
+  case SMESHOp::OpConvertMeshToQuadratic:
+  case SMESHOp::OpCreateBoundaryElements: // create 2D mesh from 3D
+  case SMESHOp::OpReorientFaces:
+  case SMESHOp::OpCreateGeometryGroup:
     {
       startOperation( theCommandID );
       break;
     }
-  case 801:                                     // CREATE GROUP
+  case SMESHOp::OpCreateGroup:
     {
       if ( !vtkwnd )
       {
@@ -2811,7 +2815,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       break;
     }
 
-  case 802:                                     // CONSTRUCT GROUP
+  case SMESHOp::OpConstructGroup:
     {
       if ( !vtkwnd )
       {
@@ -2889,7 +2893,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       break;
     }
 
-  case 803:                                     // EDIT GROUP
+  case SMESHOp::OpEditGroup:
     {
       if ( !vtkwnd )
       {
@@ -2926,7 +2930,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       break;
     }
 
-  case 804:                                     // Add elements to group
+  case SMESHOp::OpAddElemGroupPopup:     // Add elements to group
     {
       if(checkLock(aStudy)) break;
       if (myState == 800) {
@@ -2936,7 +2940,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       break;
     }
 
-  case 805:                                     // Remove elements from group
+  case SMESHOp::OpRemoveElemGroupPopup:  // Remove elements from group
     {
       if(checkLock(aStudy)) break;
       if (myState == 800) {
@@ -2946,7 +2950,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       break;
     }
 
-  case 815:                                     // Edit GEOM GROUP as standalone
+  case SMESHOp::OpEditGeomGroupAsGroup:
     {
       if ( !vtkwnd )
       {
@@ -2985,9 +2989,9 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       break;
     }
 
-    case 810: // Union Groups
-    case 811: // Intersect groups
-    case 812: // Cut groups
+    case SMESHOp::OpUnionGroups:
+    case SMESHOp::OpIntersectGroups:
+    case SMESHOp::OpCutGroups:
     {
       if ( !vtkwnd )
       {
@@ -3002,9 +3006,9 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       EmitSignalDeactivateDialog();
 
       SMESHGUI_GroupOpDlg* aDlg = 0;
-      if ( theCommandID == 810 )
+      if ( theCommandID == SMESHOp::OpUnionGroups )
         aDlg = new SMESHGUI_UnionGroupsDlg( this );
-      else if ( theCommandID == 811 )
+      else if ( theCommandID == SMESHOp::OpIntersectGroups )
         aDlg = new SMESHGUI_IntersectGroupsDlg( this );
       else
         aDlg = new SMESHGUI_CutGroupsDlg( this );
@@ -3014,7 +3018,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       break;
     }
 
-    case 814: // Create groups of entities from existing groups of superior dimensions
+    case SMESHOp::OpGroupUnderlyingElem: // Create groups of entities from existing groups of superior dimensions
     {
       if ( checkLock( aStudy ) )
         break;
@@ -3026,7 +3030,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       break;
     }
 
-    case 813: // Delete groups with their contents
+    case SMESHOp::OpDeleteGroup: // Delete groups with their contents
     {
       if ( !vtkwnd )
       {
@@ -3044,10 +3048,10 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       break;
     }
 
-  case 900:                                     // MESH INFOS
-  case 903:                                     // WHAT IS
+  case SMESHOp::OpMeshInformation:
+  case SMESHOp::OpWhatIs:
     {
-      int page = theCommandID == 900 ? SMESHGUI_MeshInfoDlg::BaseInfo : SMESHGUI_MeshInfoDlg::ElemInfo;
+      int page = theCommandID == SMESHOp::OpMeshInformation ? SMESHGUI_MeshInfoDlg::BaseInfo : SMESHGUI_MeshInfoDlg::ElemInfo;
       EmitSignalDeactivateDialog();
       LightApp_SelectionMgr *aSel = SMESHGUI::selectionMgr();
       SALOME_ListIO selected;
@@ -3069,13 +3073,13 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       break;
     }
 
-  case 904:                                     // FIND ELEM
+  case SMESHOp::OpFindElementByPoint:
     {
       startOperation( theCommandID );
       break;
     }
 
-  case 1100:                                    // EDIT HYPOTHESIS
+  case SMESHOp::OpEditHypothesis:
     {
       if(checkLock(aStudy)) break;
 
@@ -3090,15 +3094,26 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
         Handle(SALOME_InteractiveObject) anIObject = selected.First();
         SMESH::SMESH_Hypothesis_var aHypothesis = SMESH::IObjectToInterface<SMESH::SMESH_Hypothesis>(anIObject);
 
-        /* Look for all mesh objects that have this hypothesis affected in order to flag as ModifiedMesh */
-        /* At end below '...->updateObjBrowser(true)' will change icon of mesh objects                   */
-        /* Warning : however by internal mechanism all subMeshes icons are changed !                     */
         if ( !aHypothesis->_is_nil() )
         {
-          // BUG 0020378
-          //SMESHGUI_GenericHypothesisCreator* aCreator = SMESH::GetHypothesisCreator(aHypothesis->GetName());
-          SMESHGUI_GenericHypothesisCreator* aCreator = SMESH::GetHypothesisCreator(aHypothesis->GetName());
-          if (aCreator) {
+          SMESHGUI_GenericHypothesisCreator* aCreator =
+            SMESH::GetHypothesisCreator( SMESH::toQStr( aHypothesis->GetName() ));
+          if (aCreator)
+          {
+            // set geometry of mesh and sub-mesh to aCreator
+            aSel->selectedObjects( selected, "",  /*convertReferences=*/false);
+            if ( selected.Extent() == 1 )
+            {
+              QString subGeomID, meshGeomID;
+              Handle(SALOME_InteractiveObject) hypIO = selected.First();
+              if ( SMESH::GetGeomEntries( hypIO, subGeomID, meshGeomID ))
+              {
+                if ( subGeomID.isEmpty() ) subGeomID = meshGeomID;
+                aCreator->setShapeEntry( subGeomID );
+                aCreator->setMainShapeEntry( meshGeomID );
+              }
+            }
+
             aCreator->edit( aHypothesis.in(), anIObject->getName(), desktop(), this, SLOT( onHypothesisEdit( int ) ) );
           }
           else
@@ -3109,7 +3124,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
-  case 1102:                                    // REMOVE HYPOTHESIS / ALGORITHMS
+  case SMESHOp::OpUnassign:                      // REMOVE HYPOTHESIS / ALGORITHMS
     {
       if(checkLock(aStudy)) break;
       SUIT_OverrideCursor wc;
@@ -3130,33 +3145,33 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       break;
     }
 
-  case 4008:                                    // BALL
-  case 4009:                                    // ELEM0D
-  case 4010:                                    // EDGE
-  case 4021:                                    // TRIANGLE
-  case 4022:                                    // QUAD
-  case 4023:                                    // POLYGON
-  case 4031:                                    // TETRA
-  case 4032:                                    // HEXA
-  case 4133:                                    // PENTA
-  case 4134:                                    // PYRAMID
-  case 4135:                                    // OCTA12
+  case SMESHOp::OpElem0D:
+  case SMESHOp::OpBall:
+  case SMESHOp::OpEdge:
+  case SMESHOp::OpTriangle:
+  case SMESHOp::OpQuadrangle:
+  case SMESHOp::OpPolygon:
+  case SMESHOp::OpTetrahedron:
+  case SMESHOp::OpHexahedron:
+  case SMESHOp::OpPentahedron:
+  case SMESHOp::OpPyramid:
+  case SMESHOp::OpHexagonalPrism:
     {
       if(checkLock(aStudy)) break;
       if ( vtkwnd ) {
         EmitSignalDeactivateDialog();
         SMDSAbs_EntityType type = SMDSEntity_Edge;
         switch (theCommandID) {
-        case 4008: type = SMDSEntity_Ball;            break;
-        case 4009: type = SMDSEntity_0D;              break;
-        case 4021: type = SMDSEntity_Triangle;        break;
-        case 4022: type = SMDSEntity_Quadrangle;      break;
-        case 4031: type = SMDSEntity_Tetra;           break;
-        case 4023: type = SMDSEntity_Polygon;         break;
-        case 4032: type = SMDSEntity_Hexa;            break;
-        case 4133: type = SMDSEntity_Penta;           break;
-        case 4134: type = SMDSEntity_Pyramid;         break;
-        case 4135: type = SMDSEntity_Hexagonal_Prism; break;
+        case SMESHOp::OpElem0D: type = SMDSEntity_0D;                      break;
+        case SMESHOp::OpBall: type = SMDSEntity_Ball;                      break;
+        case SMESHOp::OpTriangle: type = SMDSEntity_Triangle;              break;
+        case SMESHOp::OpQuadrangle: type = SMDSEntity_Quadrangle;          break;
+        case SMESHOp::OpTetrahedron: type = SMDSEntity_Tetra;              break;
+        case SMESHOp::OpPolygon: type = SMDSEntity_Polygon;                break;
+        case SMESHOp::OpHexahedron: type = SMDSEntity_Hexa;                break;
+        case SMESHOp::OpPentahedron: type = SMDSEntity_Penta;              break;
+        case SMESHOp::OpPyramid: type = SMDSEntity_Pyramid;                break;
+        case SMESHOp::OpHexagonalPrism: type = SMDSEntity_Hexagonal_Prism; break;
         default:;
         }
         ( new SMESHGUI_AddMeshElementDlg( this, type ) )->show();
@@ -3167,7 +3182,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
-  case 4033:                                    // POLYHEDRON
+  case SMESHOp::OpPolyhedron:
     {
       if(checkLock(aStudy)) break;
       if ( vtkwnd ) {
@@ -3180,16 +3195,16 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
-  case 4034:     // QUADRATIC EDGE
-  case 4035:     // QUADRATIC TRIANGLE
-  case 4036:     // QUADRATIC QUADRANGLE
-  case 4136:     // BIQUADRATIC QUADRANGLE
-  case 4137:     // BIQUADRATIC TRIANGLE
-  case 4037:     // QUADRATIC TETRAHEDRON
-  case 4038:     // QUADRATIC PYRAMID
-  case 4039:     // QUADRATIC PENTAHEDRON
-  case 4040:     // QUADRATIC HEXAHEDRON
-  case 4140:     // TRIQUADRATIC HEXAHEDRON
+  case SMESHOp::OpQuadraticEdge:
+  case SMESHOp::OpQuadraticTriangle:
+  case SMESHOp::OpBiQuadraticTriangle:
+  case SMESHOp::OpQuadraticQuadrangle:
+  case SMESHOp::OpBiQuadraticQuadrangle:
+  case SMESHOp::OpQuadraticTetrahedron:
+  case SMESHOp::OpQuadraticPyramid:
+  case SMESHOp::OpQuadraticPentahedron:
+  case SMESHOp::OpQuadraticHexahedron:
+  case SMESHOp::OpTriQuadraticHexahedron:
     {
       if(checkLock(aStudy)) break;
       if ( vtkwnd ) {
@@ -3197,16 +3212,16 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
         SMDSAbs_EntityType type = SMDSEntity_Last;
 
         switch (theCommandID) {
-        case 4034: type = SMDSEntity_Quad_Edge; break;
-        case 4035: type = SMDSEntity_Quad_Triangle; break;
-        case 4036: type = SMDSEntity_Quad_Quadrangle; break;
-        case 4136: type = SMDSEntity_BiQuad_Quadrangle; break;
-        case 4137: type = SMDSEntity_BiQuad_Triangle; break;
-        case 4037: type = SMDSEntity_Quad_Tetra; break;
-        case 4038: type = SMDSEntity_Quad_Pyramid; break;
-        case 4039: type = SMDSEntity_Quad_Penta; break;
-        case 4040: type = SMDSEntity_Quad_Hexa; break;
-        case 4140: type = SMDSEntity_TriQuad_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::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;
         }
         if ( type != SMDSEntity_Last )
@@ -3218,7 +3233,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
-  case 4041:                                    // REMOVES NODES
+  case SMESHOp::OpRemoveNodes:
     {
       if(checkLock(aStudy)) break;
       if ( vtkwnd ) {
@@ -3231,7 +3246,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
-  case 4042:                                    // REMOVES ELEMENTS
+  case SMESHOp::OpRemoveElements:                                    // REMOVES ELEMENTS
     {
       if(checkLock(aStudy)) break;
       if( vtkwnd ) {
@@ -3245,7 +3260,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
         }
       break;
     }
-  case 4043: {                                // CLEAR_MESH
+  case SMESHOp::OpClearMesh: {
 
     if(checkLock(aStudy)) break;
 
@@ -3285,7 +3300,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
     updateObjBrowser();
     break;
   }
-  case 4044:                                     // REMOVE ORPHAN NODES
+  case SMESHOp::OpRemoveOrphanNodes:
     {
       if(checkLock(aStudy)) break;
       SALOME_ListIO selected;
@@ -3324,7 +3339,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
-  case 4051:                                    // RENUMBERING NODES
+  case SMESHOp::OpRenumberingNodes:
     {
       if(checkLock(aStudy)) break;
       if( vtkwnd ) {
@@ -3338,7 +3353,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
         }
       break;
     }
-  case 4052:                                    // RENUMBERING ELEMENTS
+  case SMESHOp::OpRenumberingElements:
     {
       if(checkLock(aStudy)) break;
       if ( vtkwnd ) {
@@ -3352,7 +3367,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
         }
       break;
     }
-  case 4061:                                   // TRANSLATION
+  case SMESHOp::OpTranslation:
     {
       if(checkLock(aStudy)) break;
       if ( vtkwnd ) {
@@ -3365,7 +3380,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
-  case 4062:                                   // ROTATION
+  case SMESHOp::OpRotation:
     {
       if(checkLock(aStudy)) break;
       if( vtkwnd ) {
@@ -3378,7 +3393,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
-  case 4063:                                   // SYMMETRY
+  case SMESHOp::OpSymmetry:
     {
       if(checkLock(aStudy)) break;
       if(vtkwnd) {
@@ -3391,7 +3406,21 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
-  case 4064:                                   // SEWING
+  case SMESHOp::OpScale:
+    {
+      if(checkLock(aStudy)) break;
+      if ( vtkwnd ) {
+        EmitSignalDeactivateDialog();
+        ( new SMESHGUI_ScaleDlg( this ) )->show();
+      }
+      else {
+        SUIT_MessageBox::warning(SMESHGUI::desktop(),
+                                 tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK"));
+      }
+      break;
+    }
+
+  case SMESHOp::OpSewing:
     {
       if(checkLock(aStudy)) break;
       if(vtkwnd) {
@@ -3404,7 +3433,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
-  case 4065:                                   // MERGE NODES
+  case SMESHOp::OpMergeNodes:
     {
       if(checkLock(aStudy)) break;
       if(vtkwnd) {
@@ -3417,7 +3446,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
-  case 4066:                                   // MERGE EQUAL ELEMENTS
+  case SMESHOp::OpMergeElements:
     {
       if (checkLock(aStudy)) break;
       if (vtkwnd) {
@@ -3430,25 +3459,11 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       break;
     }
 
-  case 4067: // MAKE MESH PASS THROUGH POINT
-    startOperation( 4067 );
+  case SMESHOp::OpMoveNode: // MAKE MESH PASS THROUGH POINT
+    startOperation( SMESHOp::OpMoveNode );
     break;
 
-  case 4068: // SCALE
-    {
-      if(checkLock(aStudy)) break;
-      if ( vtkwnd ) {
-        EmitSignalDeactivateDialog();
-        ( new SMESHGUI_ScaleDlg( this ) )->show();
-      }
-      else {
-        SUIT_MessageBox::warning(SMESHGUI::desktop(),
-                                 tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK"));
-      }
-      break;
-    }
-
-  case 4069: // DUPLICATE NODES
+  case SMESHOp::OpDuplicateNodes:
     {
       if(checkLock(aStudy)) break;
       if ( vtkwnd ) {
@@ -3462,11 +3477,11 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       break;
     }
 
-  case 4070: // 0D_ON_ALL_NODES
-    startOperation( 4070 );
+  case SMESHOp::OpElem0DOnElemNodes: // 0D_ON_ALL_NODES
+    startOperation( SMESHOp::OpElem0DOnElemNodes );
     break;
 
-  case 5105: // Library of selection filters
+  case SMESHOp::OpSelectFiltersLibrary: // Library of selection filters
   {
     static QList<int> aTypes;
     if ( aTypes.isEmpty() )
@@ -3483,33 +3498,33 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
     myFilterLibraryDlg->raise();
   }
   break;
-
-  case 6017:                                    // CONTROLS
-  case 6016:
-  case 6015:
-  case 6014:
-  case 6013:
-  case 6012:
-  case 6011:
-  case 6001:
-  case 6018:
-  case 6019:
-  case 6002:
-  case 6003:
-  case 6004:
-  case 6005:
-  case 6009:
-  case 6021:
-  case 6022:
-  case 6023:
-  case 6024:
-  case 6025:
-  case 6026:
-  case 6027:
-  case 6028:
-  case 6029:
-  case 6030:
-  case 6031:
+  // CONTROLS
+  case SMESHOp::OpFreeNode:
+  case SMESHOp::OpEqualNode:
+  case SMESHOp::OpFreeEdge:
+  case SMESHOp::OpFreeBorder:
+  case SMESHOp::OpLength:
+  case SMESHOp::OpConnection:
+  case SMESHOp::OpEqualEdge:
+  case SMESHOp::OpFreeFace:
+  case SMESHOp::OpBareBorderFace:
+  case SMESHOp::OpOverConstrainedFace:
+  case SMESHOp::OpLength2D:
+  case SMESHOp::OpConnection2D:
+  case SMESHOp::OpArea:
+  case SMESHOp::OpTaper:
+  case SMESHOp::OpAspectRatio:
+  case SMESHOp::OpMinimumAngle:
+  case SMESHOp::OpWarpingAngle:
+  case SMESHOp::OpSkew:
+  case SMESHOp::OpMaxElementLength2D:
+  case SMESHOp::OpEqualFace:
+  case SMESHOp::OpAspectRatio3D:
+  case SMESHOp::OpVolume:
+  case SMESHOp::OpMaxElementLength3D:
+  case SMESHOp::OpBareBorderVolume:
+  case SMESHOp::OpOverConstrainedVolume:
+  case SMESHOp::OpEqualVolume:
     if ( vtkwnd ) {
 
       LightApp_SelectionMgr* mgr = selectionMgr();
@@ -3540,10 +3555,10 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
                                tr( "NOT_A_VTK_VIEWER" ) );
     }
     break;
-  case 6032:
+  case SMESHOp::OpOverallMeshQuality:
     OverallMeshQuality();
     break;
-  case 9010:
+  case SMESHOp::OpNumberingNodes:
     {
       SUIT_OverrideCursor wc;
       LightApp_SelectionMgr* mgr = selectionMgr();
@@ -3560,7 +3575,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
-  case 9011:
+  case SMESHOp::OpNumberingElements:
     {
       SUIT_OverrideCursor wc;
       LightApp_SelectionMgr* mgr = selectionMgr();
@@ -3576,20 +3591,20 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
       break;
     }
-  case 501:
-  case 502:
-  case 503:
-  case 504:
-  case 505:
+  case SMESHOp::OpPropertiesLength:
+  case SMESHOp::OpPropertiesArea:
+  case SMESHOp::OpPropertiesVolume:
+  case SMESHOp::OpMinimumDistance:
+  case SMESHOp::OpBoundingBox:
     {
       int page = SMESHGUI_MeasureDlg::MinDistance;
-      if ( theCommandID == 502 )
+      if ( theCommandID == SMESHOp::OpBoundingBox )
         page = SMESHGUI_MeasureDlg::BoundingBox;
-      else if ( theCommandID == 503 )
+      else if ( theCommandID == SMESHOp::OpPropertiesLength )
         page = SMESHGUI_MeasureDlg::Length;
-      else if ( theCommandID == 504 )
+      else if ( theCommandID == SMESHOp::OpPropertiesArea )
         page = SMESHGUI_MeasureDlg::Area;
-      else if ( theCommandID == 505 )
+      else if ( theCommandID == SMESHOp::OpPropertiesVolume )
         page = SMESHGUI_MeasureDlg::Volume;
 
       EmitSignalDeactivateDialog();
@@ -3597,7 +3612,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       dlg->show();
       break;
     }
-  case 41:
+  case SMESHOp::OpSortChild:
     ::sortChildren();
     break;
 
@@ -3725,183 +3740,192 @@ void SMESHGUI::initialize( CAM_Application* app )
 
   // ----- create actions --------------
 
-  //createSMESHAction(  111, "IMPORT_DAT", "", (Qt::CTRL+Qt::Key_B) );
-  createSMESHAction(  112, "IMPORT_UNV", "", (Qt::CTRL+Qt::Key_U) );
-  createSMESHAction(  113, "IMPORT_MED", "", (Qt::CTRL+Qt::Key_M) );
-  createSMESHAction(  114, "NUM" );
-  createSMESHAction(  115, "IMPORT_STL"  );
-  createSMESHAction(  116, "IMPORT_CGNS" );
-  createSMESHAction(  117, "IMPORT_SAUV" );
-  createSMESHAction(  118, "IMPORT_GMF"  );
-  createSMESHAction(  121, "DAT" );
-  createSMESHAction(  122, "MED" );
-  createSMESHAction(  123, "UNV" );
-  createSMESHAction(  140, "STL" );
-  createSMESHAction(  142, "CGNS");
-  createSMESHAction(  144, "SAUV");
-  createSMESHAction(  146, "GMF" );
-  createSMESHAction(  124, "DAT" );
-  createSMESHAction(  125, "MED" );
-  createSMESHAction(  126, "UNV" );
-  createSMESHAction(  141, "STL" );
-  createSMESHAction(  143, "CGNS");
-  createSMESHAction(  145, "SAUV");
-  createSMESHAction(  147, "GMF" );
-  createSMESHAction(  150, "FILE_INFO" );
-  createSMESHAction(   33, "DELETE",          "ICON_DELETE", Qt::Key_Delete );
-  createSMESHAction( 5105, "SEL_FILTER_LIB" );
-  createSMESHAction(  701, "COMPUTE",         "ICON_COMPUTE" );
-  createSMESHAction(  702, "CREATE_MESH",     "ICON_DLG_INIT_MESH" );
-  createSMESHAction(  703, "CREATE_SUBMESH",  "ICON_DLG_ADD_SUBMESH" );
-  createSMESHAction(  704, "EDIT_MESHSUBMESH","ICON_DLG_EDIT_MESH" );
-  createSMESHAction(  705, "COPY_MESH",       "ICON_COPY_MESH" );
-  createSMESHAction(  710, "BUILD_COMPOUND",  "ICON_BUILD_COMPOUND" );
-  createSMESHAction(  711, "PRECOMPUTE",      "ICON_PRECOMPUTE" );
-  createSMESHAction(  712, "EVALUATE",        "ICON_COMPUTE" );
-  createSMESHAction(  713, "MESH_ORDER",      "ICON_COMPUTE" );
-  createSMESHAction(  806, "CREATE_GEO_GROUP","ICON_CREATE_GEO_GROUP" );
-  createSMESHAction(  801, "CREATE_GROUP",    "ICON_CREATE_GROUP" );
-  createSMESHAction(  802, "CONSTRUCT_GROUP", "ICON_CONSTRUCT_GROUP" );
-  createSMESHAction(  803, "EDIT_GROUP",      "ICON_EDIT_GROUP" );
-  createSMESHAction(  815, "EDIT_GEOMGROUP_AS_GROUP", "ICON_EDIT_GROUP" );
-  createSMESHAction(  804, "ADD" );
-  createSMESHAction(  805, "REMOVE" );
-  createSMESHAction(  810, "UN_GROUP",        "ICON_UNION" );
-  createSMESHAction(  811, "INT_GROUP",       "ICON_INTERSECT" );
-  createSMESHAction(  812, "CUT_GROUP",       "ICON_CUT" );
-  createSMESHAction(  814, "UNDERLYING_ELEMS","ICON_UNDERLYING_ELEMS" );
-  createSMESHAction(  813, "DEL_GROUP",       "ICON_DEL_GROUP" );
-  createSMESHAction(  900, "ADV_INFO",        "ICON_ADV_INFO" );
-  //createSMESHAction(  902, "STD_INFO",        "ICON_STD_INFO" );
-  //createSMESHAction(  903, "WHAT_IS",         "ICON_WHAT_IS" ); // VSR: issue #0021242 (eliminate "Mesh Element Information" command)
-  createSMESHAction(  904, "FIND_ELEM",       "ICON_FIND_ELEM" );
-  createSMESHAction( 6001, "LENGTH",          "ICON_LENGTH",        0, true );
-  createSMESHAction( 6002, "FREE_EDGE",       "ICON_FREE_EDGE",     0, true );
-  createSMESHAction( 6021, "FREE_FACES",      "ICON_FREE_FACES",    0, true );
-  createSMESHAction( 6022, "MAX_ELEMENT_LENGTH_2D",  "ICON_MAX_ELEMENT_LENGTH_2D",   0, true );
-  createSMESHAction( 6023, "MAX_ELEMENT_LENGTH_3D",  "ICON_MAX_ELEMENT_LENGTH_3D",   0, true );
-  createSMESHAction( 6024, "BARE_BORDER_VOLUME",     "ICON_BARE_BORDER_VOLUME",      0, true );
-  createSMESHAction( 6025, "BARE_BORDER_FACE",       "ICON_BARE_BORDER_FACE",        0, true );
-  createSMESHAction( 6026, "OVER_CONSTRAINED_VOLUME","ICON_OVER_CONSTRAINED_VOLUME", 0, true );
-  createSMESHAction( 6027, "OVER_CONSTRAINED_FACE",  "ICON_OVER_CONSTRAINED_FACE",   0, true );
-  createSMESHAction( 6028, "EQUAL_NODE",      "ICON_EQUAL_NODE",    0, true );
-  createSMESHAction( 6029, "EQUAL_EDGE",      "ICON_EQUAL_EDGE",    0, true );
-  createSMESHAction( 6030, "EQUAL_FACE",      "ICON_EQUAL_FACE",    0, true );
-  createSMESHAction( 6031, "EQUAL_VOLUME",    "ICON_EQUAL_VOLUME",  0, true );
-  createSMESHAction( 6032, "OVERALL_MESH_QUALITY" );
-  createSMESHAction( 6003, "FREE_BORDER",     "ICON_FREE_EDGE_2D",  0, true );
-  createSMESHAction( 6004, "CONNECTION",      "ICON_CONNECTION",    0, true );
-  createSMESHAction( 6005, "FREE_NODE",       "ICON_FREE_NODE",     0, true );
-  createSMESHAction( 6011, "AREA",            "ICON_AREA",          0, true );
-  createSMESHAction( 6012, "TAPER",           "ICON_TAPER",         0, true );
-  createSMESHAction( 6013, "ASPECT",          "ICON_ASPECT",        0, true );
-  createSMESHAction( 6014, "MIN_ANG",         "ICON_ANGLE",         0, true );
-  createSMESHAction( 6015, "WARP",            "ICON_WARP",          0, true );
-  createSMESHAction( 6016, "SKEW",            "ICON_SKEW",          0, true );
-  createSMESHAction( 6017, "ASPECT_3D",       "ICON_ASPECT_3D",     0, true );
-  createSMESHAction( 6018, "LENGTH_2D",       "ICON_LENGTH_2D",     0, true );
-  createSMESHAction( 6019, "CONNECTION_2D",   "ICON_CONNECTION_2D", 0, true );
-  createSMESHAction( 6009, "VOLUME_3D",       "ICON_VOLUME_3D",     0, true );
-  createSMESHAction( 4000, "NODE",            "ICON_DLG_NODE" );
-  createSMESHAction( 4009, "ELEM0D",          "ICON_DLG_ELEM0D" );
-  createSMESHAction( 4008, "BALL",            "ICON_DLG_BALL" );
-  createSMESHAction( 4010, "EDGE",            "ICON_DLG_EDGE" );
-  createSMESHAction( 4021, "TRIANGLE",        "ICON_DLG_TRIANGLE" );
-  createSMESHAction( 4022, "QUAD",            "ICON_DLG_QUADRANGLE" );
-  createSMESHAction( 4023, "POLYGON",         "ICON_DLG_POLYGON" );
-  createSMESHAction( 4031, "TETRA",           "ICON_DLG_TETRAS" );
-  createSMESHAction( 4032, "HEXA",            "ICON_DLG_HEXAS" );
-  createSMESHAction( 4133, "PENTA",           "ICON_DLG_PENTA" );
-  createSMESHAction( 4134, "PYRAMID",         "ICON_DLG_PYRAMID" );
-  createSMESHAction( 4135, "OCTA",            "ICON_DLG_OCTA" );
-  createSMESHAction( 4033, "POLYHEDRON",              "ICON_DLG_POLYHEDRON" );
-  createSMESHAction( 4034, "QUADRATIC_EDGE",          "ICON_DLG_QUADRATIC_EDGE" );
-  createSMESHAction( 4035, "QUADRATIC_TRIANGLE",      "ICON_DLG_QUADRATIC_TRIANGLE" );
-  createSMESHAction( 4036, "QUADRATIC_QUADRANGLE",    "ICON_DLG_QUADRATIC_QUADRANGLE" );
-  createSMESHAction( 4136, "BIQUADRATIC_QUADRANGLE",  "ICON_DLG_BIQUADRATIC_QUADRANGLE" );
-  createSMESHAction( 4137, "BIQUADRATIC_TRIANGLE",    "ICON_DLG_BIQUADRATIC_TRIANGLE" );
-  createSMESHAction( 4037, "QUADRATIC_TETRAHEDRON",   "ICON_DLG_QUADRATIC_TETRAHEDRON" );
-  createSMESHAction( 4038, "QUADRATIC_PYRAMID",       "ICON_DLG_QUADRATIC_PYRAMID" );
-  createSMESHAction( 4039, "QUADRATIC_PENTAHEDRON",   "ICON_DLG_QUADRATIC_PENTAHEDRON" );
-  createSMESHAction( 4040, "QUADRATIC_HEXAHEDRON",    "ICON_DLG_QUADRATIC_HEXAHEDRON" );
-  createSMESHAction( 4140, "TRIQUADRATIC_HEXAHEDRON", "ICON_DLG_TRIQUADRATIC_HEXAHEDRON" );
-  createSMESHAction( 4041, "REMOVE_NODES",          "ICON_DLG_REM_NODE" );
-  createSMESHAction( 4042, "REMOVE_ELEMENTS",       "ICON_DLG_REM_ELEMENT" );
-  createSMESHAction( 4044, "REMOVE_ORPHAN_NODES",   "ICON_DLG_REM_ORPHAN_NODES" );
-  createSMESHAction( 4043, "CLEAR_MESH"    ,  "ICON_CLEAR_MESH" );
-  createSMESHAction( 4051, "RENUM_NODES",     "ICON_DLG_RENUMBERING_NODES" );
-  createSMESHAction( 4052, "RENUM_ELEMENTS",  "ICON_DLG_RENUMBERING_ELEMENTS" );
-  createSMESHAction( 4061, "TRANS",           "ICON_SMESH_TRANSLATION_VECTOR" );
-  createSMESHAction( 4062, "ROT",             "ICON_DLG_MESH_ROTATION" );
-  createSMESHAction( 4063, "SYM",             "ICON_SMESH_SYMMETRY_PLANE" );
-  createSMESHAction( 4064, "SEW",             "ICON_SMESH_SEWING_FREEBORDERS" );
-  createSMESHAction( 4065, "MERGE",           "ICON_SMESH_MERGE_NODES" );
-  createSMESHAction( 4066, "MERGE_ELEMENTS",  "ICON_DLG_MERGE_ELEMENTS" );
-  createSMESHAction( 4067, "MESH_THROU_POINT","ICON_DLG_MOVE_NODE" );
-  createSMESHAction( 4068, "SCALE",           "ICON_DLG_MESH_SCALE" );
-  createSMESHAction( 4069, "DUPLICATE_NODES", "ICON_SMESH_DUPLICATE_NODES" );
-  createSMESHAction( 4070, "0D_ON_ALL_NODES", "ICON_0D_ON_ALL_NODES" );
-  createSMESHAction(  407, "INV",             "ICON_DLG_MESH_DIAGONAL" );
-  createSMESHAction(  408, "UNION2",          "ICON_UNION2TRI" );
-  createSMESHAction(  409, "ORIENT",          "ICON_DLG_MESH_ORIENTATION" );
-  createSMESHAction(  410, "UNION",           "ICON_UNIONTRI" );
-  createSMESHAction(  411, "CUT",             "ICON_CUTQUAD" );
-  createSMESHAction(  412, "SMOOTH",          "ICON_DLG_SMOOTHING" );
-  createSMESHAction(  413, "EXTRUSION",       "ICON_EXTRUSION" );
-  createSMESHAction(  414, "REVOLUTION",      "ICON_REVOLUTION" );
-  createSMESHAction(  415, "MAP",             "ICON_MAP" );
-  createSMESHAction(  416, "EXTRUSION_ALONG", "ICON_EXTRUSION_ALONG" );
-  createSMESHAction(  417, "CONV_TO_QUAD",    "ICON_CONV_TO_QUAD" );
-  createSMESHAction(  418, "2D_FROM_3D",      "ICON_2D_FROM_3D" );
-  createSMESHAction(  419, "SPLIT_TO_TETRA",  "ICON_SPLIT_TO_TETRA" );
-  createSMESHAction(  420, "REORIENT_2D",     "ICON_REORIENT_2D" );
-  createSMESHAction(  200, "RESET" );
-  createSMESHAction(  201, "SCALAR_BAR_PROP" );
-  createSMESHAction(  2021, "SAVE_DISTRIBUTION" );
-  createSMESHAction(  2022, "SHOW_DISTRIBUTION","",0, true );
+  //createSMESHAction(  SMESHOp::OpImportDAT, "IMPORT_DAT", "", (Qt::CTRL+Qt::Key_B) );
+  createSMESHAction( SMESHOp::OpImportUNV, "IMPORT_UNV", "", (Qt::CTRL+Qt::Key_U) );
+  createSMESHAction( SMESHOp::OpImportMED, "IMPORT_MED", "", (Qt::CTRL+Qt::Key_M) );
+  //createSMESHAction(  114, "NUM" );
+  createSMESHAction( SMESHOp::OpImportSTL, "IMPORT_STL"  );
+#ifdef WITH_CGNS
+  createSMESHAction( SMESHOp::OpImportCGNS, "IMPORT_CGNS" );
+#endif
+  createSMESHAction( SMESHOp::OpImportSAUV, "IMPORT_SAUV" );
+  createSMESHAction( SMESHOp::OpImportGMF,  "IMPORT_GMF"  );
+  createSMESHAction( SMESHOp::OpExportDAT,  "DAT" );
+  createSMESHAction( SMESHOp::OpExportMED,  "MED" );
+  createSMESHAction( SMESHOp::OpExportUNV,  "UNV" );
+  createSMESHAction( SMESHOp::OpExportSTL,  "STL" );
+#ifdef WITH_CGNS
+  createSMESHAction( SMESHOp::OpExportCGNS, "CGNS");
+#endif
+  createSMESHAction( SMESHOp::OpExportSAUV,     "SAUV");
+  createSMESHAction( SMESHOp::OpExportGMF,      "GMF" );
+  createSMESHAction( SMESHOp::OpPopupExportDAT, "DAT" );
+  createSMESHAction( SMESHOp::OpPopupExportMED, "MED" );
+  createSMESHAction( SMESHOp::OpPopupExportUNV, "UNV" );
+  createSMESHAction( SMESHOp::OpPopupExportSTL, "STL" );
+#ifdef WITH_CGNS
+  createSMESHAction( SMESHOp::OpPopupExportCGNS, "CGNS");
+#endif
+  createSMESHAction( SMESHOp::OpPopupExportSAUV, "SAUV");
+  createSMESHAction( SMESHOp::OpPopupExportGMF,  "GMF" );
+  createSMESHAction( SMESHOp::OpFileInformation, "FILE_INFO" );
+  createSMESHAction( SMESHOp::OpDelete,          "DELETE", "ICON_DELETE", Qt::Key_Delete );
+  createSMESHAction( SMESHOp::OpSelectFiltersLibrary, "SEL_FILTER_LIB" );
+  createSMESHAction( SMESHOp::OpCreateMesh,           "CREATE_MESH",             "ICON_DLG_INIT_MESH" );
+  createSMESHAction( SMESHOp::OpCreateSubMesh,        "CREATE_SUBMESH",          "ICON_DLG_ADD_SUBMESH" );
+  createSMESHAction( SMESHOp::OpEditMeshOrSubMesh,    "EDIT_MESHSUBMESH",        "ICON_DLG_EDIT_MESH" );
+  createSMESHAction( SMESHOp::OpBuildCompoundMesh,    "BUILD_COMPOUND",          "ICON_BUILD_COMPOUND" );
+  createSMESHAction( SMESHOp::OpCopyMesh,             "COPY_MESH",               "ICON_COPY_MESH" );
+  createSMESHAction( SMESHOp::OpCompute,              "COMPUTE",                 "ICON_COMPUTE" );
+  createSMESHAction( SMESHOp::OpPreCompute,           "PRECOMPUTE",              "ICON_PRECOMPUTE" );
+  createSMESHAction( SMESHOp::OpEvaluate,             "EVALUATE",                "ICON_COMPUTE" );
+  createSMESHAction( SMESHOp::OpMeshOrder,            "MESH_ORDER",              "ICON_COMPUTE" );
+  createSMESHAction( SMESHOp::OpCreateGroup,          "CREATE_GROUP",            "ICON_CREATE_GROUP" );
+  createSMESHAction( SMESHOp::OpCreateGeometryGroup,  "CREATE_GEO_GROUP",        "ICON_CREATE_GEO_GROUP" );
+  createSMESHAction( SMESHOp::OpConstructGroup,       "CONSTRUCT_GROUP",         "ICON_CONSTRUCT_GROUP" );
+  createSMESHAction( SMESHOp::OpEditGroup,            "EDIT_GROUP",              "ICON_EDIT_GROUP" );
+  createSMESHAction( SMESHOp::OpEditGeomGroupAsGroup, "EDIT_GEOMGROUP_AS_GROUP", "ICON_EDIT_GROUP" );
+  createSMESHAction( SMESHOp::OpUnionGroups,          "UN_GROUP",                "ICON_UNION" );
+  createSMESHAction( SMESHOp::OpIntersectGroups,      "INT_GROUP",               "ICON_INTERSECT" );
+  createSMESHAction( SMESHOp::OpCutGroups,            "CUT_GROUP",               "ICON_CUT" );
+  createSMESHAction( SMESHOp::OpGroupUnderlyingElem,  "UNDERLYING_ELEMS",        "ICON_UNDERLYING_ELEMS" );
+  createSMESHAction( SMESHOp::OpAddElemGroupPopup,    "ADD" );
+  createSMESHAction( SMESHOp::OpRemoveElemGroupPopup, "REMOVE" );
+  createSMESHAction( SMESHOp::OpDeleteGroup,          "DEL_GROUP",               "ICON_DEL_GROUP" );
+  createSMESHAction( SMESHOp::OpMeshInformation ,     "ADV_INFO",                "ICON_ADV_INFO" );
+  //createSMESHAction( SMESHOp::OpStdInfo, "STD_INFO",        "ICON_STD_INFO" );
+  //createSMESHAction( SMESHOp::OpWhatIs, "WHAT_IS",         "ICON_WHAT_IS" ); // VSR: issue #0021242 (eliminate "Mesh Element Information" command)
+  createSMESHAction( SMESHOp::OpFindElementByPoint,   "FIND_ELEM",               "ICON_FIND_ELEM" );
+  //update
+  createSMESHAction( SMESHOp::OpFreeNode,              "FREE_NODE",               "ICON_FREE_NODE",     0, true );
+  createSMESHAction( SMESHOp::OpEqualNode,             "EQUAL_NODE",              "ICON_EQUAL_NODE",    0, true );
+  createSMESHAction( SMESHOp::OpFreeEdge,              "FREE_EDGE",               "ICON_FREE_EDGE",     0, true );
+  createSMESHAction( SMESHOp::OpFreeBorder,            "FREE_BORDER",             "ICON_FREE_EDGE_2D",  0, true );
+  createSMESHAction( SMESHOp::OpLength,                "LENGTH",                  "ICON_LENGTH",        0, true );
+  createSMESHAction( SMESHOp::OpConnection,            "CONNECTION",              "ICON_CONNECTION",    0, true );
+  createSMESHAction( SMESHOp::OpEqualEdge,             "EQUAL_EDGE",              "ICON_EQUAL_EDGE",    0, true );
+  createSMESHAction( SMESHOp::OpFreeFace,              "FREE_FACES",              "ICON_FREE_FACES",    0, true );
+  createSMESHAction( SMESHOp::OpBareBorderFace,        "BARE_BORDER_FACE",        "ICON_BARE_BORDER_FACE",        0, true );
+  createSMESHAction( SMESHOp::OpOverConstrainedFace,   "OVER_CONSTRAINED_FACE",   "ICON_OVER_CONSTRAINED_FACE",   0, true );
+  createSMESHAction( SMESHOp::OpLength2D,              "LENGTH_2D",               "ICON_LENGTH_2D",     0, true );
+  createSMESHAction( SMESHOp::OpConnection2D,          "CONNECTION_2D",           "ICON_CONNECTION_2D", 0, true );
+  createSMESHAction( SMESHOp::OpArea,                  "AREA",                    "ICON_AREA",          0, true );
+  createSMESHAction( SMESHOp::OpTaper,                 "TAPER",                   "ICON_TAPER",         0, true );
+  createSMESHAction( SMESHOp::OpAspectRatio,           "ASPECT",                  "ICON_ASPECT",        0, true );
+  createSMESHAction( SMESHOp::OpMinimumAngle,          "MIN_ANG",                 "ICON_ANGLE",         0, true );
+  createSMESHAction( SMESHOp::OpWarpingAngle,          "WARP",                    "ICON_WARP",          0, true );
+  createSMESHAction( SMESHOp::OpSkew,                  "SKEW",                    "ICON_SKEW",          0, true );
+  createSMESHAction( SMESHOp::OpMaxElementLength2D,    "MAX_ELEMENT_LENGTH_2D",   "ICON_MAX_ELEMENT_LENGTH_2D",   0, true );
+  createSMESHAction( SMESHOp::OpEqualFace,             "EQUAL_FACE",              "ICON_EQUAL_FACE",    0, true );
+  createSMESHAction( SMESHOp::OpAspectRatio3D,         "ASPECT_3D",               "ICON_ASPECT_3D",     0, true );
+  createSMESHAction( SMESHOp::OpVolume,                "VOLUME_3D",               "ICON_VOLUME_3D",     0, true );
+  createSMESHAction( SMESHOp::OpMaxElementLength3D,    "MAX_ELEMENT_LENGTH_3D",   "ICON_MAX_ELEMENT_LENGTH_3D",   0, true );
+  createSMESHAction( SMESHOp::OpBareBorderVolume,      "BARE_BORDER_VOLUME",      "ICON_BARE_BORDER_VOLUME",      0, true );
+  createSMESHAction( SMESHOp::OpOverConstrainedVolume, "OVER_CONSTRAINED_VOLUME", "ICON_OVER_CONSTRAINED_VOLUME", 0, true );
+  createSMESHAction( SMESHOp::OpEqualVolume,           "EQUAL_VOLUME",            "ICON_EQUAL_VOLUME",  0, true );
+  createSMESHAction( SMESHOp::OpOverallMeshQuality,    "OVERALL_MESH_QUALITY" );
+
+  createSMESHAction( SMESHOp::OpNode,                   "NODE",            "ICON_DLG_NODE" );
+  createSMESHAction( SMESHOp::OpElem0D,                 "ELEM0D",          "ICON_DLG_ELEM0D" );
+  createSMESHAction( SMESHOp::OpElem0DOnElemNodes,      "0D_ON_ALL_NODES", "ICON_0D_ON_ALL_NODES" );
+  createSMESHAction( SMESHOp::OpBall,                   "BALL",            "ICON_DLG_BALL" );
+  createSMESHAction( SMESHOp::OpEdge,                   "EDGE",            "ICON_DLG_EDGE" );
+  createSMESHAction( SMESHOp::OpTriangle,               "TRIANGLE",        "ICON_DLG_TRIANGLE" );
+  createSMESHAction( SMESHOp::OpQuadrangle,             "QUAD",            "ICON_DLG_QUADRANGLE" );
+  createSMESHAction( SMESHOp::OpPolygon,                "POLYGON",         "ICON_DLG_POLYGON" );
+  createSMESHAction( SMESHOp::OpTetrahedron,            "TETRA",           "ICON_DLG_TETRAS" );
+  createSMESHAction( SMESHOp::OpHexahedron,             "HEXA",            "ICON_DLG_HEXAS" );
+  createSMESHAction( SMESHOp::OpPentahedron,            "PENTA",           "ICON_DLG_PENTA" );
+  createSMESHAction( SMESHOp::OpPyramid ,               "PYRAMID",         "ICON_DLG_PYRAMID" );
+  createSMESHAction( SMESHOp::OpHexagonalPrism,         "OCTA",            "ICON_DLG_OCTA" );
+  createSMESHAction( SMESHOp::OpPolyhedron,             "POLYHEDRON",      "ICON_DLG_POLYHEDRON" );
+  createSMESHAction( SMESHOp::OpQuadraticEdge,          "QUADRATIC_EDGE",          "ICON_DLG_QUADRATIC_EDGE" );
+  createSMESHAction( SMESHOp::OpQuadraticTriangle,      "QUADRATIC_TRIANGLE",      "ICON_DLG_QUADRATIC_TRIANGLE" );
+  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::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" );
+  createSMESHAction( SMESHOp::OpQuadraticHexahedron,    "QUADRATIC_HEXAHEDRON",    "ICON_DLG_QUADRATIC_HEXAHEDRON" );
+  createSMESHAction( SMESHOp::OpTriQuadraticHexahedron, "TRIQUADRATIC_HEXAHEDRON", "ICON_DLG_TRIQUADRATIC_HEXAHEDRON" );
+
+  createSMESHAction( SMESHOp::OpRemoveNodes,       "REMOVE_NODES",          "ICON_DLG_REM_NODE" );
+  createSMESHAction( SMESHOp::OpRemoveElements,    "REMOVE_ELEMENTS",       "ICON_DLG_REM_ELEMENT" );
+  createSMESHAction( SMESHOp::OpRemoveOrphanNodes, "REMOVE_ORPHAN_NODES",   "ICON_DLG_REM_ORPHAN_NODES" );
+  createSMESHAction( SMESHOp::OpClearMesh,         "CLEAR_MESH",            "ICON_CLEAR_MESH" );
+
+  createSMESHAction( SMESHOp::OpRenumberingNodes,    "RENUM_NODES",     "ICON_DLG_RENUMBERING_NODES" );
+  createSMESHAction( SMESHOp::OpRenumberingElements, "RENUM_ELEMENTS",  "ICON_DLG_RENUMBERING_ELEMENTS" );
+
+  createSMESHAction( SMESHOp::OpTranslation,            "TRANS",           "ICON_SMESH_TRANSLATION_VECTOR" );
+  createSMESHAction( SMESHOp::OpRotation,               "ROT",             "ICON_DLG_MESH_ROTATION" );
+  createSMESHAction( SMESHOp::OpSymmetry,               "SYM",             "ICON_SMESH_SYMMETRY_PLANE" );
+  createSMESHAction( SMESHOp::OpScale,                  "SCALE",           "ICON_DLG_MESH_SCALE" );
+  createSMESHAction( SMESHOp::OpSewing,                 "SEW",             "ICON_SMESH_SEWING_FREEBORDERS" );
+  createSMESHAction( SMESHOp::OpMergeNodes,             "MERGE",           "ICON_SMESH_MERGE_NODES" );
+  createSMESHAction( SMESHOp::OpMergeElements,          "MERGE_ELEMENTS",  "ICON_DLG_MERGE_ELEMENTS" );
+  createSMESHAction( SMESHOp::OpMoveNode,               "MESH_THROU_POINT","ICON_DLG_MOVE_NODE" );
+  createSMESHAction( SMESHOp::OpDuplicateNodes,         "DUPLICATE_NODES", "ICON_SMESH_DUPLICATE_NODES" );
+  createSMESHAction( SMESHOp::OpDiagonalInversion,      "INV",             "ICON_DLG_MESH_DIAGONAL" );
+  createSMESHAction( SMESHOp::OpUnionOfTwoTriangle,     "UNION2",          "ICON_UNION2TRI" );
+  createSMESHAction( SMESHOp::OpOrientation,            "ORIENT",          "ICON_DLG_MESH_ORIENTATION" );
+  createSMESHAction( SMESHOp::OpReorientFaces,          "REORIENT_2D",     "ICON_REORIENT_2D" );
+  createSMESHAction( SMESHOp::OpUnionOfTriangles,       "UNION",           "ICON_UNIONTRI" );
+  createSMESHAction( SMESHOp::OpCuttingOfQuadrangles,   "CUT",             "ICON_CUTQUAD" );
+  createSMESHAction( SMESHOp::OpSplitVolumes,           "SPLIT_TO_TETRA",  "ICON_SPLIT_TO_TETRA" );
+  createSMESHAction( SMESHOp::OpSmoothing,              "SMOOTH",          "ICON_DLG_SMOOTHING" );
+  createSMESHAction( SMESHOp::OpExtrusion,              "EXTRUSION",       "ICON_EXTRUSION" );
+  createSMESHAction( SMESHOp::OpExtrusionAlongAPath,    "EXTRUSION_ALONG", "ICON_EXTRUSION_ALONG" );
+  createSMESHAction( SMESHOp::OpRevolution,             "REVOLUTION",      "ICON_REVOLUTION" );
+  createSMESHAction( SMESHOp::OpPatternMapping,         "MAP",             "ICON_MAP" );
+  createSMESHAction( SMESHOp::OpConvertMeshToQuadratic, "CONV_TO_QUAD",    "ICON_CONV_TO_QUAD" );
+  createSMESHAction( SMESHOp::OpCreateBoundaryElements, "2D_FROM_3D",      "ICON_2D_FROM_3D" );
+
+  createSMESHAction( SMESHOp::OpReset,               "RESET" );
+  createSMESHAction( SMESHOp::OpScalarBarProperties, "SCALAR_BAR_PROP" );
+  createSMESHAction( SMESHOp::OpSaveDistribution,    "SAVE_DISTRIBUTION" );
+  createSMESHAction( SMESHOp::OpShowDistribution,    "SHOW_DISTRIBUTION","",0, true );
 #ifndef DISABLE_PLOT2DVIEWER
-  createSMESHAction(  2023, "PLOT_DISTRIBUTION" );
+  createSMESHAction( SMESHOp::OpPlotDistribution, "PLOT_DISTRIBUTION" );
 #endif
-  createSMESHAction(  211, "WIRE",           "ICON_WIRE", 0, true );
-  createSMESHAction(  212, "SHADE",          "ICON_SHADE", 0, true );
-  createSMESHAction(  213, "SHRINK",         "ICON_SHRINK", 0, true );
-  createSMESHAction(  214, "UPDATE",         "ICON_UPDATE" );
-  createSMESHAction(  215, "NODES",          "ICON_POINTS", 0, true );
-  createSMESHAction(  222, "BALLS",          "ICON_DLG_BALL", 0, true );
-  createSMESHAction(  216, "ELEMS0D",        "ICON_DLG_ELEM0D", 0, true );
-  createSMESHAction(  217, "EDGES",          "ICON_DLG_EDGE", 0, true );
-  createSMESHAction(  218, "FACES",          "ICON_DLG_TRIANGLE", 0, true );
-  createSMESHAction(  219, "VOLUMES",        "ICON_DLG_TETRAS", 0, true );
-  createSMESHAction(  220, "ALL" );
-  createSMESHAction(  221, "FACE_ORIENTATION", "", 0, true );
-
-  createSMESHAction(  231, "LINE_REPRESENTATION", "", 0, true );
-  createSMESHAction(  232, "ARC_REPRESENTATION", "", 0, true );
-
-  createSMESHAction( 1100, "EDIT_HYPO" );
-  createSMESHAction( 1102, "UNASSIGN" );
-  createSMESHAction( 9010, "NUM_NODES", "", 0, true );
-  createSMESHAction( 9011, "NUM_ELEMENTS", "", 0, true );
-  createSMESHAction( 1131, "DISPMODE" );
-  createSMESHAction( 1132, "COLORS" );
-  createSMESHAction( 1133, "TRANSP" );
-  createSMESHAction( 1134, "CLIP" );
-  createSMESHAction( 1135, "DISP_ENT" );
-  createSMESHAction( 1136, "AUTO_COLOR" );
-  createSMESHAction( 1137, "DISABLE_AUTO_COLOR" );
-  createSMESHAction( 2000, "CTRL" );
-
-  createSMESHAction( 501, "MEASURE_MIN_DIST", "ICON_MEASURE_MIN_DIST" );
-  createSMESHAction( 502, "MEASURE_BND_BOX",  "ICON_MEASURE_BND_BOX" );
-  createSMESHAction( 503, "MEASURE_LENGTH",   "ICON_MEASURE_LENGTH" );
-  createSMESHAction( 504, "MEASURE_AREA",     "ICON_MEASURE_AREA" );
-  createSMESHAction( 505, "MEASURE_VOLUME",   "ICON_MEASURE_VOLUME" );
-
-  createSMESHAction( 300, "HIDE" );
-  createSMESHAction( 301, "SHOW" );
-  createSMESHAction( 302, "DISPLAY_ONLY" );
-
-  createSMESHAction( 41, "SORT_CHILD_ITEMS" );
+  createSMESHAction( SMESHOp::OpDMWireframe,  "WIRE",    "ICON_WIRE", 0, true );
+  createSMESHAction( SMESHOp::OpDMShading,    "SHADE",   "ICON_SHADE", 0, true );
+  createSMESHAction( SMESHOp::OpDMNodes,      "NODES",   "ICON_POINTS", 0, true );
+  createSMESHAction( SMESHOp::OpDMShrink,     "SHRINK",  "ICON_SHRINK", 0, true );
+  createSMESHAction( SMESHOp::OpUpdate,       "UPDATE",  "ICON_UPDATE" );
+  createSMESHAction( SMESHOp::OpDE0DElements, "ELEMS0D", "ICON_DLG_ELEM0D", 0, true );
+  createSMESHAction( SMESHOp::OpDEEdges,      "EDGES",   "ICON_DLG_EDGE", 0, true );
+  createSMESHAction( SMESHOp::OpDEFaces,      "FACES",   "ICON_DLG_TRIANGLE", 0, true );
+  createSMESHAction( SMESHOp::OpDEVolumes,    "VOLUMES", "ICON_DLG_TETRAS", 0, true );
+  createSMESHAction( SMESHOp::OpDEBalls,      "BALLS",   "ICON_DLG_BALL", 0, true );
+  createSMESHAction( SMESHOp::OpDEAllEntity,  "ALL" );
+  createSMESHAction( SMESHOp::OpOrientationOnFaces, "FACE_ORIENTATION", "", 0, true );
+
+  createSMESHAction( SMESHOp::OpRepresentationLines, "LINE_REPRESENTATION", "", 0, true );
+  createSMESHAction( SMESHOp::OpRepresentationArcs,  "ARC_REPRESENTATION", "", 0, true );
+
+  createSMESHAction( SMESHOp::OpEditHypothesis,    "EDIT_HYPO" );
+  createSMESHAction( SMESHOp::OpUnassign,          "UNASSIGN" );
+  createSMESHAction( SMESHOp::OpNumberingNodes,    "NUM_NODES", "", 0, true );
+  createSMESHAction( SMESHOp::OpNumberingElements, "NUM_ELEMENTS", "", 0, true );
+  createSMESHAction( SMESHOp::OpProperties,   "COLORS" );
+  createSMESHAction( SMESHOp::OpTransparency, "TRANSP" );
+  createSMESHAction( SMESHOp::OpClipping,     "CLIP" );
+  createSMESHAction( SMESHOp::OpAutoColor,        "AUTO_COLOR" );
+  createSMESHAction( SMESHOp::OpDisableAutoColor, "DISABLE_AUTO_COLOR" );
+
+  createSMESHAction( SMESHOp::OpMinimumDistance,  "MEASURE_MIN_DIST", "ICON_MEASURE_MIN_DIST" );
+  createSMESHAction( SMESHOp::OpBoundingBox,      "MEASURE_BND_BOX",  "ICON_MEASURE_BND_BOX" );
+  createSMESHAction( SMESHOp::OpPropertiesLength, "MEASURE_LENGTH",   "ICON_MEASURE_LENGTH" );
+  createSMESHAction( SMESHOp::OpPropertiesArea,   "MEASURE_AREA",     "ICON_MEASURE_AREA" );
+  createSMESHAction( SMESHOp::OpPropertiesVolume, "MEASURE_VOLUME",   "ICON_MEASURE_VOLUME" );
+
+  createSMESHAction( SMESHOp::OpHide,     "HIDE" );
+  createSMESHAction( SMESHOp::OpShow,     "SHOW" );
+  createSMESHAction( SMESHOp::OpShowOnly, "DISPLAY_ONLY" );
+
+  createSMESHAction( SMESHOp::OpSortChild, "SORT_CHILD_ITEMS" );
 
   // ----- create menu --------------
   int fileId    = createMenu( tr( "MEN_FILE" ),    -1,  1 ),
@@ -3927,288 +3951,287 @@ void SMESHGUI::initialize( CAM_Application* app )
       transfId = createMenu( tr( "MEN_TRANSF" ), modifyId, 405 ),
       basicPropId = createMenu( tr( "MEN_BASIC_PROPERTIES" ), measureId, -1, 10 );
 
-  //createMenu( 111, importId, -1 );
-  createMenu( 112, importId, -1 );
-  createMenu( 113, importId, -1 );
-  createMenu( 115, importId, -1 );
+  //createMenu( SMESHOp::OpImportDAT, importId, -1 );
+  createMenu( SMESHOp::OpImportUNV,  importId, -1 );
+  createMenu( SMESHOp::OpImportMED,  importId, -1 );
+  createMenu( SMESHOp::OpImportSTL,  importId, -1 );
 #ifdef WITH_CGNS
-  createMenu( 116, importId, -1 );
+  createMenu( SMESHOp::OpImportCGNS, importId, -1 );
 #endif
-  createMenu( 117, importId, -1 );
-  createMenu( 118, importId, -1 );
-  createMenu( 121, exportId, -1 );
-  createMenu( 122, exportId, -1 );
-  createMenu( 123, exportId, -1 );
-  createMenu( 140, exportId, -1 ); // export to STL
+  createMenu( SMESHOp::OpImportSAUV, importId, -1 );
+  createMenu( SMESHOp::OpImportGMF,  importId, -1 );
+  createMenu( SMESHOp::OpExportDAT,  exportId, -1 );
+  createMenu( SMESHOp::OpExportMED,  exportId, -1 );
+  createMenu( SMESHOp::OpExportUNV,  exportId, -1 );
+  createMenu( SMESHOp::OpExportSTL,  exportId, -1 );
 #ifdef WITH_CGNS
-  createMenu( 142, exportId, -1 ); // export to CGNS
+  createMenu( SMESHOp::OpExportCGNS, exportId, -1 );
 #endif
-  createMenu( 144, exportId, -1 ); // export to SAUV
-  createMenu( 146, exportId, -1 ); // export to GMF
+  createMenu( SMESHOp::OpExportSAUV, exportId, -1 );
+  createMenu( SMESHOp::OpExportGMF,  exportId, -1 );
   createMenu( separator(), fileId, 10 );
 
-  createMenu( 33, editId, -1 );
-
-  createMenu( 5105, toolsId, -1 );
-
-  createMenu( 702, meshId, -1 ); // "Mesh" menu
-  createMenu( 703, meshId, -1 );
-  createMenu( 704, meshId, -1 );
-  createMenu( 710, meshId, -1 );
-  createMenu( 705, meshId, -1 );
-  createMenu( separator(), meshId, -1 );
-  createMenu( 701, meshId, -1 );
-  createMenu( 711, meshId, -1 );
-  createMenu( 712, meshId, -1 );
-  createMenu( 713, meshId, -1 );
-  createMenu( separator(), meshId, -1 );
-  createMenu( 801, meshId, -1 );
-  createMenu( 806, meshId, -1 );
-  createMenu( 802, meshId, -1 );
-  createMenu( 803, meshId, -1 );
-  createMenu( 815, meshId, -1 );
-  createMenu( separator(), meshId, -1 );
-  createMenu( 810, meshId, -1 );
-  createMenu( 811, meshId, -1 );
-  createMenu( 812, meshId, -1 );
-  createMenu( separator(), meshId, -1 );
-  createMenu( 814, meshId, -1 );
-  createMenu( separator(), meshId, -1 );
-  createMenu( 900, meshId, -1 );
-  //createMenu( 902, meshId, -1 );
-  //createMenu( 903, meshId, -1 ); // VSR: issue #0021242 (eliminate "Mesh Element Information" command)
-  createMenu( 904, meshId, -1 );
-  createMenu( separator(), meshId, -1 );
-
-  createMenu( 6005, nodeId, -1 );
-  createMenu( 6028, nodeId, -1 );
-  createMenu( 6002, edgeId, -1 );
-  createMenu( 6003, edgeId, -1 );
-  createMenu( 6001, edgeId, -1 );
-  createMenu( 6004, edgeId, -1 );
-  createMenu( 6029, edgeId, -1 );
-  createMenu( 6021, faceId, -1 );
-  createMenu( 6025, faceId, -1 );
-  createMenu( 6027, faceId, -1 );
-  createMenu( 6018, faceId, -1 );
-  createMenu( 6019, faceId, -1 );
-  createMenu( 6011, faceId, -1 );
-  createMenu( 6012, faceId, -1 );
-  createMenu( 6013, faceId, -1 );
-  createMenu( 6014, faceId, -1 );
-  createMenu( 6015, faceId, -1 );
-  createMenu( 6016, faceId, -1 );
-  createMenu( 6022, faceId, -1 );
-  createMenu( 6030, faceId, -1 );
-  createMenu( 6017, volumeId, -1 );
-  createMenu( 6009, volumeId, -1 );
-  createMenu( 6023, volumeId, -1 );
-  createMenu( 6024, volumeId, -1 );
-  createMenu( 6026, volumeId, -1 );
-  createMenu( 6031, volumeId, -1 );
-  createMenu( separator(), ctrlId, -1 );
-  createMenu( 6032, ctrlId, -1 );
-
-  createMenu( 4000, addId, -1 );
-  createMenu( 4009, addId, -1 );
-  createMenu( 4070, addId, -1 );
-  createMenu( 4008, addId, -1 );
-  createMenu( 4010, addId, -1 );
-  createMenu( 4021, addId, -1 );
-  createMenu( 4022, addId, -1 );
-  createMenu( 4023, addId, -1 );
-  createMenu( 4031, addId, -1 );
-  createMenu( 4032, addId, -1 );
-  createMenu( 4133, addId, -1 );
-  createMenu( 4134, addId, -1 );
-  createMenu( 4135, addId, -1 );
-  createMenu( 4033, addId, -1 );
-  createMenu( separator(), addId, -1 );
-  createMenu( 4034, addId, -1 );
-  createMenu( 4035, addId, -1 );
-  createMenu( 4137, addId, -1 );
-  createMenu( 4036, addId, -1 );
-  createMenu( 4136, addId, -1 );
-  createMenu( 4037, addId, -1 );
-  createMenu( 4038, addId, -1 );
-  createMenu( 4039, addId, -1 );
-  createMenu( 4040, addId, -1 );
-  createMenu( 4140, addId, -1 );
-
-  createMenu( 4041, removeId, -1 );
-  createMenu( 4042, removeId, -1 );
-  createMenu( 4044, removeId, -1 );
-  createMenu( separator(), removeId, -1 );
-  createMenu( 813, removeId, -1 );
-  createMenu( separator(), removeId, -1 );
-  createMenu( 4043, removeId, -1 );
-
-  createMenu( 4051, renumId, -1 );
-  createMenu( 4052, renumId, -1 );
-
-  createMenu( 4061, transfId, -1 );
-  createMenu( 4062, transfId, -1 );
-  createMenu( 4063, transfId, -1 );
-  createMenu( 4068, transfId, -1 );
-  createMenu( 4064, transfId, -1 );
-  createMenu( 4065, transfId, -1 );
-  createMenu( 4066, transfId, -1 );
-  createMenu( 4069, transfId, -1 );
-
-  createMenu( 4067,modifyId, -1 );
-  createMenu( 407, modifyId, -1 );
-  createMenu( 408, modifyId, -1 );
-  createMenu( 409, modifyId, -1 );
-  createMenu( 420, modifyId, -1 );
-  createMenu( 410, modifyId, -1 );
-  createMenu( 411, modifyId, -1 );
-  createMenu( 419, modifyId, -1 );
-  createMenu( 412, modifyId, -1 );
-  createMenu( 413, modifyId, -1 );
-  createMenu( 416, modifyId, -1 );
-  createMenu( 414, modifyId, -1 );
-  createMenu( 415, modifyId, -1 );
-  createMenu( 417, modifyId, -1 );
-  createMenu( 418, modifyId, -1 );
-
-  createMenu( 501, measureId, -1 );
-  createMenu( 502, measureId, -1 );
-  createMenu( 503, basicPropId, -1 );
-  createMenu( 504, basicPropId, -1 );
-  createMenu( 505, basicPropId, -1 );
-  createMenu( 214, viewId, -1 );
+  createMenu( SMESHOp::OpDelete, editId, -1 );
+
+  createMenu( SMESHOp::OpSelectFiltersLibrary, toolsId, -1 );
+
+  createMenu( SMESHOp::OpCreateMesh,           meshId, -1 ); // "Mesh" menu
+  createMenu( SMESHOp::OpCreateSubMesh,        meshId, -1 );
+  createMenu( SMESHOp::OpEditMeshOrSubMesh,    meshId, -1 );
+  createMenu( SMESHOp::OpBuildCompoundMesh,    meshId, -1 );
+  createMenu( SMESHOp::OpCopyMesh,             meshId, -1 );
+  createMenu( separator(),                     meshId, -1 );
+  createMenu( SMESHOp::OpCompute,              meshId, -1 );
+  createMenu( SMESHOp::OpPreCompute,           meshId, -1 );
+  createMenu( SMESHOp::OpEvaluate,             meshId, -1 );
+  createMenu( SMESHOp::OpMeshOrder,            meshId, -1 );
+  createMenu( separator(),                     meshId, -1 );
+  createMenu( SMESHOp::OpCreateGroup,          meshId, -1 );
+  createMenu( SMESHOp::OpCreateGeometryGroup,  meshId, -1 );
+  createMenu( SMESHOp::OpConstructGroup,       meshId, -1 );
+  createMenu( SMESHOp::OpEditGroup,            meshId, -1 );
+  createMenu( SMESHOp::OpEditGeomGroupAsGroup, meshId, -1 );
+  createMenu( separator(),                     meshId, -1 );
+  createMenu( SMESHOp::OpUnionGroups,          meshId, -1 );
+  createMenu( SMESHOp::OpIntersectGroups,      meshId, -1 );
+  createMenu( SMESHOp::OpCutGroups,            meshId, -1 );
+  createMenu( separator(),                     meshId, -1 );
+  createMenu( SMESHOp::OpGroupUnderlyingElem,  meshId, -1 );
+  createMenu( separator(),                     meshId, -1 );
+  createMenu( SMESHOp::OpMeshInformation,      meshId, -1 );
+  //createMenu( SMESHOp::OpStdInfo, meshId, -1 );
+  //createMenu( SMESHOp::OpWhatIs, meshId, -1 ); // VSR: issue #0021242 (eliminate "Mesh Element Information" command)
+  createMenu( SMESHOp::OpFindElementByPoint,   meshId, -1 );
+  createMenu( separator(),                     meshId, -1 );
+
+  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::OpFreeFace,              faceId,   -1 );
+  createMenu( SMESHOp::OpBareBorderFace,        faceId,   -1 );
+  createMenu( SMESHOp::OpOverConstrainedFace,   faceId,   -1 );
+  createMenu( SMESHOp::OpLength2D,              faceId,   -1 );
+  createMenu( SMESHOp::OpConnection2D,          faceId,   -1 );
+  createMenu( SMESHOp::OpArea,                  faceId,   -1 );
+  createMenu( SMESHOp::OpTaper,                 faceId,   -1 );
+  createMenu( SMESHOp::OpAspectRatio,           faceId,   -1 );
+  createMenu( SMESHOp::OpMinimumAngle,          faceId,   -1 );
+  createMenu( SMESHOp::OpWarpingAngle,          faceId,   -1 );
+  createMenu( SMESHOp::OpSkew,                  faceId,   -1 );
+  createMenu( SMESHOp::OpMaxElementLength2D,    faceId,   -1 );
+  createMenu( SMESHOp::OpEqualFace,             faceId,   -1 );
+  createMenu( SMESHOp::OpAspectRatio3D,         volumeId, -1 );
+  createMenu( SMESHOp::OpVolume,                volumeId, -1 );
+  createMenu( SMESHOp::OpMaxElementLength3D,    volumeId, -1 );
+  createMenu( SMESHOp::OpBareBorderVolume,      volumeId, -1 );
+  createMenu( SMESHOp::OpOverConstrainedVolume, volumeId, -1 );
+  createMenu( SMESHOp::OpEqualVolume,           volumeId, -1 );
+  createMenu( separator(),                      ctrlId,   -1 );
+  createMenu( SMESHOp::OpOverallMeshQuality,    ctrlId,   -1 );
+
+  createMenu( SMESHOp::OpNode,                   addId, -1 );
+  createMenu( SMESHOp::OpElem0D,                 addId, -1 );
+  createMenu( SMESHOp::OpElem0DOnElemNodes,      addId, -1 );
+  createMenu( SMESHOp::OpBall,                   addId, -1 );
+  createMenu( SMESHOp::OpEdge,                   addId, -1 );
+  createMenu( SMESHOp::OpTriangle,               addId, -1 );
+  createMenu( SMESHOp::OpQuadrangle,             addId, -1 );
+  createMenu( SMESHOp::OpPolygon,                addId, -1 );
+  createMenu( SMESHOp::OpTetrahedron,            addId, -1 );
+  createMenu( SMESHOp::OpHexahedron,             addId, -1 );
+  createMenu( SMESHOp::OpPentahedron,            addId, -1 );
+  createMenu( SMESHOp::OpPyramid,                addId, -1 );
+  createMenu( SMESHOp::OpHexagonalPrism,         addId, -1 );
+  createMenu( SMESHOp::OpPolyhedron,             addId, -1 );
+  createMenu( separator(),                       addId, -1 );
+  createMenu( SMESHOp::OpQuadraticEdge,          addId, -1 );
+  createMenu( SMESHOp::OpQuadraticTriangle,      addId, -1 );
+  createMenu( SMESHOp::OpBiQuadraticTriangle ,   addId, -1 );
+  createMenu( SMESHOp::OpQuadraticQuadrangle,    addId, -1 );
+  createMenu( SMESHOp::OpBiQuadraticQuadrangle,  addId, -1 );
+  createMenu( SMESHOp::OpQuadraticTetrahedron,   addId, -1 );
+  createMenu( SMESHOp::OpQuadraticPyramid,       addId, -1 );
+  createMenu( SMESHOp::OpQuadraticPentahedron,   addId, -1 );
+  createMenu( SMESHOp::OpQuadraticHexahedron,    addId, -1 );
+  createMenu( SMESHOp::OpTriQuadraticHexahedron, addId, -1 );
+
+  createMenu( SMESHOp::OpRemoveNodes,       removeId, -1 );
+  createMenu( SMESHOp::OpRemoveElements,    removeId, -1 );
+  createMenu( SMESHOp::OpRemoveOrphanNodes, removeId, -1 );
+  createMenu( separator(),                  removeId, -1 );
+  createMenu( SMESHOp::OpDeleteGroup,       removeId, -1 );
+  createMenu( separator(),                  removeId, -1 );
+  createMenu( SMESHOp::OpClearMesh,         removeId, -1 );
+
+  createMenu( SMESHOp::OpRenumberingNodes,    renumId, -1 );
+  createMenu( SMESHOp::OpRenumberingElements, renumId, -1 );
+
+  createMenu( SMESHOp::OpTranslation,    transfId, -1 );
+  createMenu( SMESHOp::OpRotation,       transfId, -1 );
+  createMenu( SMESHOp::OpSymmetry,       transfId, -1 );
+  createMenu( SMESHOp::OpScale,          transfId, -1 );
+  createMenu( SMESHOp::OpSewing,         transfId, -1 );
+  createMenu( SMESHOp::OpMergeNodes,     transfId, -1 );
+  createMenu( SMESHOp::OpMergeElements,  transfId, -1 );
+  createMenu( SMESHOp::OpDuplicateNodes, transfId, -1 );
+
+  createMenu( SMESHOp::OpMoveNode,               modifyId, -1 );
+  createMenu( SMESHOp::OpDiagonalInversion,      modifyId, -1 );
+  createMenu( SMESHOp::OpUnionOfTwoTriangle,     modifyId, -1 );
+  createMenu( SMESHOp::OpOrientation,            modifyId, -1 );
+  createMenu( SMESHOp::OpReorientFaces,          modifyId, -1 );
+  createMenu( SMESHOp::OpUnionOfTriangles,       modifyId, -1 );
+  createMenu( SMESHOp::OpCuttingOfQuadrangles,   modifyId, -1 );
+  createMenu( SMESHOp::OpSplitVolumes,           modifyId, -1 );
+  createMenu( SMESHOp::OpSmoothing,              modifyId, -1 );
+  createMenu( SMESHOp::OpExtrusion,              modifyId, -1 );
+  createMenu( SMESHOp::OpExtrusionAlongAPath ,   modifyId, -1 );
+  createMenu( SMESHOp::OpRevolution,             modifyId, -1 );
+  createMenu( SMESHOp::OpPatternMapping,         modifyId, -1 );
+  createMenu( SMESHOp::OpConvertMeshToQuadratic, modifyId, -1 );
+  createMenu( SMESHOp::OpCreateBoundaryElements, modifyId, -1 );
+
+  createMenu( SMESHOp::OpMinimumDistance,  measureId,   -1 );
+  createMenu( SMESHOp::OpBoundingBox,      measureId,   -1 );
+  createMenu( SMESHOp::OpPropertiesLength, basicPropId, -1 );
+  createMenu( SMESHOp::OpPropertiesArea,   basicPropId, -1 );
+  createMenu( SMESHOp::OpPropertiesVolume, basicPropId, -1 );
+  createMenu( SMESHOp::OpUpdate,           viewId,      -1 );
 
   // ----- create toolbars --------------
-  int meshTb       = createTool( tr( "TB_MESH" ) ),
-      info         = createTool( tr( "TB_INFO" ) ),
-      groupTb      = createTool( tr( "TB_GROUP" ) ),
-      ctrl0dTb     = createTool( tr( "TB_CTRL0D" ) ),
-      ctrl1dTb     = createTool( tr( "TB_CTRL1D" ) ),
-      ctrl2dTb     = createTool( tr( "TB_CTRL2D" ) ),
-      ctrl3dTb     = createTool( tr( "TB_CTRL3D" ) ),
-      addElemTb    = createTool( tr( "TB_ADD" ) ),
-      addNonElemTb = createTool( tr( "TB_ADDNON" ) ),
-      remTb        = createTool( tr( "TB_REM" ) ),
-      renumbTb     = createTool( tr( "TB_RENUMBER" ) ),  
-      transformTb  = createTool( tr( "TB_TRANSFORM" ) ),  
-      modifyTb     = createTool( tr( "TB_MODIFY" ) ),
-      measuremTb     = createTool( tr( "TB_MEASUREM" ) ),
-      dispModeTb   = createTool( tr( "TB_DISP_MODE" ) );
-
-  createTool( 702, meshTb );
-  createTool( 703, meshTb );
-  createTool( 704, meshTb );
-  createTool( 710, meshTb );
-  createTool( 705, meshTb );
-  createTool( separator(), meshTb );
-  createTool( 701, meshTb );
-  createTool( 711, meshTb );
-  createTool( 712, meshTb );
-  createTool( 713, meshTb );
-
-  createTool( 801, groupTb );
-  createTool( 806, groupTb );
-  createTool( 802, groupTb );
-  createTool( 803, groupTb );
-
-  createTool( 900, info );
-  //createTool( 902, meshTb );
-  //createTool( 903, meshTb ); // VSR: issue #0021242 (eliminate "Mesh Element Information" command)
-  createTool( 904, info );
-
-  createTool( 6005, ctrl0dTb );
-  createTool( 6028, ctrl0dTb );
-
-  createTool( 6002, ctrl1dTb );
-  createTool( 6003, ctrl1dTb );
-  createTool( 6001, ctrl1dTb );
-  createTool( 6004, ctrl1dTb );
-  createTool( 6029, ctrl1dTb );
-
-  createTool( 6021, ctrl2dTb );
-  createTool( 6025, ctrl2dTb );
-  createTool( 6027, ctrl2dTb );
-  createTool( 6018, ctrl2dTb );
-  createTool( 6019, ctrl2dTb );
-  createTool( 6011, ctrl2dTb );
-  createTool( 6012, ctrl2dTb );
-  createTool( 6013, ctrl2dTb );
-  createTool( 6014, ctrl2dTb );
-  createTool( 6015, ctrl2dTb );
-  createTool( 6016, ctrl2dTb );
-  createTool( 6022, ctrl2dTb );
-  createTool( 6030, ctrl2dTb );
-
-  createTool( 6017, ctrl3dTb );
-  createTool( 6009, ctrl3dTb );
-  createTool( 6023, ctrl3dTb );
-  createTool( 6024, ctrl3dTb );
-  createTool( 6026, ctrl3dTb );
-  createTool( 6031, ctrl3dTb );
-
-  createTool( 4000, addElemTb );
-  createTool( 4009, addElemTb );
-  createTool( 4070, addElemTb );
-  createTool( 4008, addElemTb );
-  createTool( 4010, addElemTb );
-  createTool( 4021, addElemTb );
-  createTool( 4022, addElemTb );
-  createTool( 4023, addElemTb );
-  createTool( 4031, addElemTb );
-  createTool( 4032, addElemTb );
-  createTool( 4133, addElemTb );
-  createTool( 4134, addElemTb );
-  createTool( 4135, addElemTb );
-  createTool( 4033, addElemTb );
-
-  createTool( 4034, addNonElemTb );
-  createTool( 4035, addNonElemTb );
-  createTool( 4137, addNonElemTb );
-  createTool( 4036, addNonElemTb );
-  createTool( 4136, addNonElemTb );
-  createTool( 4037, addNonElemTb );
-  createTool( 4038, addNonElemTb );
-  createTool( 4039, addNonElemTb );
-  createTool( 4040, addNonElemTb );
-  createTool( 4140, addNonElemTb );
-
-  createTool( 4041, remTb );
-  createTool( 4042, remTb );
-  createTool( 4044, remTb );
-  createTool( 4043, remTb );
-
-  createTool( 4051, renumbTb );
-  createTool( 4052, renumbTb );
-
-
-  createTool( 4061, transformTb );
-  createTool( 4062, transformTb );
-  createTool( 4063, transformTb );
-  createTool( 4068, transformTb );
-  createTool( 4064, transformTb );
-  createTool( 4065, transformTb );
-  createTool( 4066, transformTb );
-  createTool( 4069, transformTb );
-
-  createTool( 4067,modifyTb );
-  createTool( 407, modifyTb );
-  createTool( 408, modifyTb );
-  createTool( 409, modifyTb );
-  createTool( 420, modifyTb );
-  createTool( 410, modifyTb );
-  createTool( 411, modifyTb );
-  createTool( 419, modifyTb );
-  createTool( 412, modifyTb );
-  createTool( 413, modifyTb );
-  createTool( 416, modifyTb );
-  createTool( 414, modifyTb );
-  createTool( 415, modifyTb );
-  createTool( 417, modifyTb );
-  createTool( 418, modifyTb );
-
-  createTool( 501, measuremTb );  
-
-  createTool( 214, dispModeTb );
+  int meshTb       = createTool( tr( "TB_MESH" ),      QString( "SMESHMeshToolbar" ) ),
+      info         = createTool( tr( "TB_INFO" ),      QString( "SMESHInformationToolbar" ) ),
+      groupTb      = createTool( tr( "TB_GROUP" ),     QString( "SMESHGroupToolbar" ) ),
+      ctrl0dTb     = createTool( tr( "TB_CTRL0D" ),    QString( "SMESHNodeControlsToolbar" ) ),
+      ctrl1dTb     = createTool( tr( "TB_CTRL1D" ),    QString( "SMESHEdgeControlsToolbar" ) ),
+      ctrl2dTb     = createTool( tr( "TB_CTRL2D" ),    QString( "SMESHFaceControlsToolbar" ) ),
+      ctrl3dTb     = createTool( tr( "TB_CTRL3D" ),    QString( "SMESHVolumeControlsToolbar" ) ),
+      addElemTb    = createTool( tr( "TB_ADD" ),       QString( "SMESHAddElementToolbar" ) ),
+      addNonElemTb = createTool( tr( "TB_ADDNON" ),    QString( "SMESHAddElementToolbar" ) ),
+      remTb        = createTool( tr( "TB_REM" ),       QString( "SMESHRemoveToolbar" ) ),
+      renumbTb     = createTool( tr( "TB_RENUMBER" ),  QString( "SMESHRenumberingToolbar" ) ),  
+      transformTb  = createTool( tr( "TB_TRANSFORM" ), QString( "SMESHTransformationToolbar" ) ),  
+      modifyTb     = createTool( tr( "TB_MODIFY" ),    QString( "SMESHModificationToolbar" ) ),
+      measuremTb   = createTool( tr( "TB_MEASUREM" ),  QString( "SMESHMeasurementsToolbar" ) ),
+      dispModeTb   = createTool( tr( "TB_DISP_MODE" ), QString( "SMESHDisplayModeToolbar" ) );
+
+  createTool( SMESHOp::OpCreateMesh,        meshTb );
+  createTool( SMESHOp::OpCreateSubMesh,     meshTb );
+  createTool( SMESHOp::OpEditMeshOrSubMesh, meshTb );
+  createTool( SMESHOp::OpBuildCompoundMesh, meshTb );
+  createTool( SMESHOp::OpCopyMesh,          meshTb );
+  createTool( separator(),                  meshTb );
+  createTool( SMESHOp::OpCompute,           meshTb );
+  createTool( SMESHOp::OpPreCompute,        meshTb );
+  createTool( SMESHOp::OpEvaluate,          meshTb );
+  createTool( SMESHOp::OpMeshOrder,         meshTb );
+
+  createTool( SMESHOp::OpCreateGroup,         groupTb );
+  createTool( SMESHOp::OpCreateGeometryGroup, groupTb );
+  createTool( SMESHOp::OpConstructGroup,      groupTb );
+  createTool( SMESHOp::OpEditGroup,           groupTb );
+
+  createTool( SMESHOp::OpMeshInformation,    info );
+  //createTool( SMESHOp::OpStdInfo, meshTb );
+  //createTool( SMESHOp::OpWhatIs, meshTb ); // VSR: issue #0021242 (eliminate "Mesh Element Information" command)
+  createTool( SMESHOp::OpFindElementByPoint, info );
+
+  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::OpFreeFace,            ctrl2dTb );
+  createTool( SMESHOp::OpBareBorderFace,      ctrl2dTb );
+  createTool( SMESHOp::OpOverConstrainedFace, ctrl2dTb );
+  createTool( SMESHOp::OpLength2D,            ctrl2dTb );
+  createTool( SMESHOp::OpConnection2D,        ctrl2dTb );
+  createTool( SMESHOp::OpArea,                ctrl2dTb );
+  createTool( SMESHOp::OpTaper,               ctrl2dTb );
+  createTool( SMESHOp::OpAspectRatio,         ctrl2dTb );
+  createTool( SMESHOp::OpMinimumAngle,        ctrl2dTb );
+  createTool( SMESHOp::OpWarpingAngle,        ctrl2dTb );
+  createTool( SMESHOp::OpSkew,                ctrl2dTb );
+  createTool( SMESHOp::OpMaxElementLength2D,  ctrl2dTb );
+  createTool( SMESHOp::OpEqualFace,           ctrl2dTb );
+
+  createTool( SMESHOp::OpAspectRatio3D,         ctrl3dTb );
+  createTool( SMESHOp::OpVolume,                ctrl3dTb );
+  createTool( SMESHOp::OpMaxElementLength3D,    ctrl3dTb );
+  createTool( SMESHOp::OpBareBorderVolume,      ctrl3dTb );
+  createTool( SMESHOp::OpOverConstrainedVolume, ctrl3dTb );
+  createTool( SMESHOp::OpEqualVolume,           ctrl3dTb );
+
+  createTool( SMESHOp::OpNode,              addElemTb );
+  createTool( SMESHOp::OpElem0D,            addElemTb );
+  createTool( SMESHOp::OpElem0DOnElemNodes, addElemTb );
+  createTool( SMESHOp::OpBall,              addElemTb );
+  createTool( SMESHOp::OpEdge,              addElemTb );
+  createTool( SMESHOp::OpTriangle,          addElemTb );
+  createTool( SMESHOp::OpQuadrangle,        addElemTb );
+  createTool( SMESHOp::OpPolygon,           addElemTb );
+  createTool( SMESHOp::OpTetrahedron,       addElemTb );
+  createTool( SMESHOp::OpHexahedron,        addElemTb );
+  createTool( SMESHOp::OpPentahedron,       addElemTb );
+  createTool( SMESHOp::OpPyramid,           addElemTb );
+  createTool( SMESHOp::OpHexagonalPrism,    addElemTb );
+  createTool( SMESHOp::OpPolyhedron,        addElemTb );
+
+  createTool( SMESHOp::OpQuadraticEdge,          addNonElemTb );
+  createTool( SMESHOp::OpQuadraticTriangle,      addNonElemTb );
+  createTool( SMESHOp::OpBiQuadraticTriangle,    addNonElemTb );
+  createTool( SMESHOp::OpQuadraticQuadrangle,    addNonElemTb );
+  createTool( SMESHOp::OpBiQuadraticQuadrangle,  addNonElemTb );
+  createTool( SMESHOp::OpQuadraticTetrahedron,   addNonElemTb );
+  createTool( SMESHOp::OpQuadraticPyramid,       addNonElemTb );
+  createTool( SMESHOp::OpQuadraticPentahedron,   addNonElemTb );
+  createTool( SMESHOp::OpQuadraticHexahedron,    addNonElemTb );
+  createTool( SMESHOp::OpTriQuadraticHexahedron, addNonElemTb );
+
+  createTool( SMESHOp::OpRemoveNodes,       remTb );
+  createTool( SMESHOp::OpRemoveElements,    remTb );
+  createTool( SMESHOp::OpRemoveOrphanNodes, remTb );
+  createTool( SMESHOp::OpClearMesh,         remTb );
+
+  createTool( SMESHOp::OpRenumberingNodes,    renumbTb );
+  createTool( SMESHOp::OpRenumberingElements, renumbTb );
+
+  createTool( SMESHOp::OpTranslation,    transformTb );
+  createTool( SMESHOp::OpRotation,       transformTb );
+  createTool( SMESHOp::OpSymmetry,       transformTb );
+  createTool( SMESHOp::OpScale,          transformTb );
+  createTool( SMESHOp::OpSewing,         transformTb );
+  createTool( SMESHOp::OpMergeNodes,     transformTb );
+  createTool( SMESHOp::OpMergeElements,  transformTb );
+  createTool( SMESHOp::OpDuplicateNodes, transformTb );
+
+  createTool( SMESHOp::OpMoveNode,               modifyTb );
+  createTool( SMESHOp::OpDiagonalInversion,      modifyTb );
+  createTool( SMESHOp::OpUnionOfTwoTriangle,     modifyTb );
+  createTool( SMESHOp::OpOrientation,            modifyTb );
+  createTool( SMESHOp::OpReorientFaces,          modifyTb );
+  createTool( SMESHOp::OpUnionOfTriangles,       modifyTb );
+  createTool( SMESHOp::OpCuttingOfQuadrangles,   modifyTb );
+  createTool( SMESHOp::OpSplitVolumes,           modifyTb );
+  createTool( SMESHOp::OpSmoothing,              modifyTb );
+  createTool( SMESHOp::OpExtrusion,              modifyTb );
+  createTool( SMESHOp::OpExtrusionAlongAPath,    modifyTb );
+  createTool( SMESHOp::OpRevolution,             modifyTb );
+  createTool( SMESHOp::OpPatternMapping,         modifyTb );
+  createTool( SMESHOp::OpConvertMeshToQuadratic, modifyTb );
+  createTool( SMESHOp::OpCreateBoundaryElements, modifyTb );
+
+  createTool( SMESHOp::OpMinimumDistance, measuremTb );
+
+  createTool( SMESHOp::OpUpdate, dispModeTb );
 
   QString lc = "$";        // VSR : instead of QtxPopupSelection::defEquality();
   QString dc = "selcount"; // VSR : instead of QtxPopupSelection::defSelCountParam()
@@ -4249,34 +4272,34 @@ void SMESHGUI::initialize( CAM_Application* app )
     hasFaces("({'Face'} in elemTypes)"),
     hasVolumes("({'Volume'} in elemTypes)");
 
-  createPopupItem( 150, OB, mesh, "&& selcount=1 && isImported" );      // FILE INFORMATION
-  createPopupItem( 703, OB, mesh, "&& isComputable");      // CREATE_SUBMESH
-  createPopupItem( 704, OB, mesh, "&& isComputable");      // EDIT_MESHSUBMESH
-  createPopupItem( 704, OB, subMesh, "&& isComputable" );  // EDIT_MESHSUBMESH
-  createPopupItem( 803, OB, group );                       // EDIT_GROUP
-  createPopupItem( 815, OB, group, "&& groupType != 'Group'" ); // EDIT AS STANDALONE
+  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::OpEditGroup,            OB, group );
+  createPopupItem( SMESHOp::OpEditGeomGroupAsGroup, OB, group, "&& groupType != 'Group'" );
 
   popupMgr()->insert( separator(), -1, 0 );
-  createPopupItem( 701, OB, mesh, "&& isComputable" );     // COMPUTE
-  createPopupItem( 711, OB, mesh, "&& isComputable && isPreComputable" ); // PRECOMPUTE
-  createPopupItem( 712, OB, mesh, "&& isComputable" );     // EVALUATE
-  createPopupItem( 713, OB, mesh, "&& isComputable" );     // MESH ORDER
-  createPopupItem( 214, OB, mesh_part );                   // UPDATE
-  createPopupItem( 900, OB, mesh_part );                   // ADV_INFO
-  createPopupItem( 904, OB, mesh_group );                  // FIND_ELEM
-  createPopupItem( 6032, OB, mesh_part );                  // CTRL_INFO
+  createPopupItem( SMESHOp::OpCompute,                OB, mesh, "&& isComputable" );
+  createPopupItem( SMESHOp::OpPreCompute,             OB, mesh, "&& isComputable && isPreComputable" );
+  createPopupItem( SMESHOp::OpEvaluate,               OB, mesh, "&& isComputable" );
+  createPopupItem( SMESHOp::OpMeshOrder,              OB, mesh, "&& isComputable" );
+  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( 801, OB, mesh );                        // CREATE_GROUP
-  createPopupItem( 806, OB, mesh );                        // CREATE_GEO_GROUP
-  createPopupItem( 802, OB, subMesh );                     // CONSTRUCT_GROUP
+  createPopupItem( SMESHOp::OpCreateGroup,            OB, mesh );
+  createPopupItem( SMESHOp::OpCreateGeometryGroup,    OB, mesh );
+  createPopupItem( SMESHOp::OpConstructGroup,         OB, subMesh );
   popupMgr()->insert( separator(), -1, 0 );
-  createPopupItem( 1100, OB, hypo);                        // EDIT HYPOTHESIS
-  createPopupItem( 1102, OB, hyp_alg );                    // REMOVE HYPOTHESIS / ALGORITHMS
+  createPopupItem( SMESHOp::OpEditHypothesis,         OB, hypo);
+  createPopupItem( SMESHOp::OpUnassign,               OB, hyp_alg );     // REMOVE HYPOTHESIS / ALGORITHMS
   popupMgr()->insert( separator(), -1, 0 );
-  createPopupItem( 4043, OB, mesh );                       // CLEAR_MESH
+  createPopupItem( SMESHOp::OpClearMesh,              OB, mesh );
   popupMgr()->insert( separator(), -1, 0 );
-  createPopupItem( 417, OB, mesh + " " + subMesh );        // convert to quadratic
-  createPopupItem( 418, OB, mesh + " " + group,            // create 2D mesh from 3D
+  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 );
 
@@ -4285,33 +4308,33 @@ void SMESHGUI::initialize( CAM_Application* app )
   QString only_one_2D        = only_one_non_empty + " && dim>1";
 
   int anId = popupMgr()->insert( tr( "MEN_EXPORT" ), -1, -1 );        // EXPORT submenu
-  createPopupItem( 125, OB, mesh_group, multiple_non_empty, anId );   // EXPORT_MED
-  createPopupItem( 126, OB, mesh_group, only_one_non_empty, anId );   // EXPORT_UNV
-  createPopupItem( 141, OB, mesh_group, only_one_2D, anId );          // EXPORT_STL
+  createPopupItem( SMESHOp::OpPopupExportMED,  OB, mesh_group, multiple_non_empty, anId );
+  createPopupItem( SMESHOp::OpPopupExportUNV,  OB, mesh_group, only_one_non_empty, anId );
+  createPopupItem( SMESHOp::OpPopupExportSTL,  OB, mesh_group, only_one_2D, anId );
 #ifdef WITH_CGNS
-  createPopupItem( 143, OB, mesh_group, multiple_non_empty, anId );   // EXPORT_CGNS
+  createPopupItem( SMESHOp::OpPopupExportCGNS, OB, mesh_group, multiple_non_empty, anId );
 #endif
-  createPopupItem( 145, OB, mesh_group, multiple_non_empty, anId );   // EXPORT_SAUV
-  createPopupItem( 147, OB, mesh_group, multiple_non_empty, anId );   // EXPORT_GMF
-  createPopupItem( 124, OB, mesh_group, multiple_non_empty, anId );   // EXPORT_DAT
-  createPopupItem(  33, OB, mesh_part + " " + hyp_alg );        // DELETE
-  createPopupItem( 813, OB, group );                            // DEL_GROUP with contents
+  createPopupItem( SMESHOp::OpPopupExportSAUV, OB, mesh_group, multiple_non_empty, anId );
+  createPopupItem( SMESHOp::OpPopupExportGMF,  OB, mesh_group, multiple_non_empty, anId );
+  createPopupItem( SMESHOp::OpPopupExportDAT,  OB, mesh_group, multiple_non_empty, anId );
+  createPopupItem( SMESHOp::OpDelete,          OB, mesh_part + " " + hyp_alg );
+  createPopupItem( SMESHOp::OpDeleteGroup,     OB, group );
   popupMgr()->insert( separator(), -1, 0 );
 
   // popup for viewer
-  createPopupItem( 803, View, group ); // EDIT_GROUP
-  createPopupItem( 804, View, elems ); // ADD
-  createPopupItem( 805, View, elems ); // REMOVE
+  createPopupItem( SMESHOp::OpEditGroup,            View, group );
+  createPopupItem( SMESHOp::OpAddElemGroupPopup,    View, elems );
+  createPopupItem( SMESHOp::OpRemoveElemGroupPopup, View, elems );
 
   popupMgr()->insert( separator(), -1, 0 );
-  createPopupItem( 214, View, mesh_part );  // UPDATE
-  createPopupItem( 900, View, mesh_part );  // ADV_INFO
-  createPopupItem( 6032,View, mesh_part );  // CTRL_INFO
-  createPopupItem( 904, View, mesh );       // FIND_ELEM
+  createPopupItem( SMESHOp::OpUpdate,             View, mesh_part );
+  createPopupItem( SMESHOp::OpMeshInformation,    View, mesh_part );
+  createPopupItem( SMESHOp::OpOverallMeshQuality, View, mesh_part );
+  createPopupItem( SMESHOp::OpFindElementByPoint, View, mesh );
   popupMgr()->insert( separator(), -1, 0 );
 
-  createPopupItem( 1136, OB + " " + View, mesh, "&& (not isAutoColor)" ); // AUTO_COLOR
-  createPopupItem( 1137, OB + " " + View, mesh, "&& isAutoColor" );       // DISABLE_AUTO_COLOR
+  createPopupItem( SMESHOp::OpAutoColor,        OB + " " + View, mesh, "&& (not isAutoColor)" );
+  createPopupItem( SMESHOp::OpDisableAutoColor, OB + " " + View, mesh, "&& isAutoColor" );
   popupMgr()->insert( separator(), -1, 0 );
 
   QString aClient = QString( "%1client in {%2}" ).arg( lc ).arg( "'VTKViewer'" );
@@ -4328,13 +4351,13 @@ void SMESHGUI::initialize( CAM_Application* app )
   //-------------------------------------------------
   anId = popupMgr()->insert( tr( "MEN_NUM" ), -1, -1 );
 
-  popupMgr()->insert( action( 9010 ), anId, -1 );
-  popupMgr()->setRule( action( 9010 ), aMeshInVTK + "&& isVisible &&" + hasNodes, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 9010 ), "{'Point'} in labeledTypes", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert( action( SMESHOp::OpNumberingNodes ), anId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpNumberingNodes ), aMeshInVTK + "&& isVisible &&" + hasNodes, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpNumberingNodes ), "{'Point'} in labeledTypes", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert( action( 9011 ), anId, -1 );
-  popupMgr()->setRule( action( 9011 ), aMeshInVTK + "&& isVisible &&" + hasElems, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 9011 ), "{'Cell'} in labeledTypes", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert( action( SMESHOp::OpNumberingElements ), anId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpNumberingElements ), aMeshInVTK + "&& isVisible &&" + hasElems, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpNumberingElements ), "{'Cell'} in labeledTypes", QtxPopupMgr::ToggleRule );
 
   popupMgr()->insert( separator(), -1, -1 );
 
@@ -4343,23 +4366,23 @@ void SMESHGUI::initialize( CAM_Application* app )
   //-------------------------------------------------
   anId = popupMgr()->insert( tr( "MEN_DISPMODE" ), -1, -1 );
 
-  popupMgr()->insert( action( 211 ), anId, -1 ); // WIRE
-  popupMgr()->setRule( action( 211 ), aMeshInVTK + "&&" + hasElems, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 211 ), "displayMode = 'eEdge'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert( action( SMESHOp::OpDMWireframe ), anId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpDMWireframe ), aMeshInVTK + "&&" + hasElems, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpDMWireframe ), "displayMode = 'eEdge'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert( action( 212 ), anId, -1 ); // SHADE
-  popupMgr()->setRule( action( 212 ),aMeshInVTK+ "&& (" + hasFaces + "||" + hasVolumes + ")", QtxPopupMgr::VisibleRule);
-  popupMgr()->setRule( action( 212 ), "displayMode = 'eSurface'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert( action( SMESHOp::OpDMShading ), anId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpDMShading ),aMeshInVTK+ "&& (" + hasFaces + "||" + hasVolumes + ")", QtxPopupMgr::VisibleRule);
+  popupMgr()->setRule( action( SMESHOp::OpDMShading ), "displayMode = 'eSurface'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert( action( 215 ), anId, -1 ); // POINTS
-  popupMgr()->setRule( action( 215 ), aMeshInVTK + "&&" + hasNodes, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 215 ), "displayMode = 'ePoint'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert( action( SMESHOp::OpDMNodes ), anId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpDMNodes ), aMeshInVTK + "&&" + hasNodes, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpDMNodes ), "displayMode = 'ePoint'", QtxPopupMgr::ToggleRule );
 
   popupMgr()->insert( separator(), anId, -1 );
 
-  popupMgr()->insert( action( 213 ), anId, -1 ); // SHRINK
-  popupMgr()->setRule( action( 213 ), aMeshInVTK + "&& shrinkMode <> 'IsNotShrinkable' && displayMode <> 'ePoint'", QtxPopupMgr::VisibleRule);
-  popupMgr()->setRule( action( 213 ), "shrinkMode = 'IsShrunk'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert( action( SMESHOp::OpDMShrink ), anId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpDMShrink ), aMeshInVTK + "&& shrinkMode <> 'IsNotShrinkable' && displayMode <> 'ePoint'", QtxPopupMgr::VisibleRule);
+  popupMgr()->setRule( action( SMESHOp::OpDMShrink ), "shrinkMode = 'IsShrunk'", QtxPopupMgr::ToggleRule );
 
   //-------------------------------------------------
   // Display Entity
@@ -4368,62 +4391,62 @@ void SMESHGUI::initialize( CAM_Application* app )
 
   anId = popupMgr()->insert( tr( "MEN_DISP_ENT" ), -1, -1 );
 
-  popupMgr()->insert( action(216), anId, -1 ); // ELEMS 0D
-  popupMgr()->setRule(action(216), aDiffElemsInVTK + "&& isVisible &&" + hasElems0d, QtxPopupMgr::VisibleRule);
-  popupMgr()->setRule(action(216), "{'Elem0d'} in entityMode", QtxPopupMgr::ToggleRule);
+  popupMgr()->insert( action( SMESHOp::OpDE0DElements ), anId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpDE0DElements ), aDiffElemsInVTK + "&& isVisible &&" + hasElems0d, QtxPopupMgr::VisibleRule);
+  popupMgr()->setRule( action( SMESHOp::OpDE0DElements ), "{'Elem0d'} in entityMode", QtxPopupMgr::ToggleRule);
 
-  popupMgr()->insert( action( 217 ), anId, -1 ); // EDGES
-  popupMgr()->setRule( action( 217 ), aDiffElemsInVTK + "&& isVisible &&" + hasEdges, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 217 ), "{'Edge'} in entityMode", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert( action( SMESHOp::OpDEEdges ), anId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpDEEdges ), aDiffElemsInVTK + "&& isVisible &&" + hasEdges, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpDEEdges ), "{'Edge'} in entityMode", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert( action( 218 ), anId, -1 ); // FACES
-  popupMgr()->setRule( action( 218 ), aDiffElemsInVTK + "&& isVisible &&" + hasFaces, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 218 ), "{'Face'} in entityMode", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert( action( SMESHOp::OpDEFaces ), anId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpDEFaces ), aDiffElemsInVTK + "&& isVisible &&" + hasFaces, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpDEFaces ), "{'Face'} in entityMode", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert( action( 219 ), anId, -1 ); // VOLUMES
-  popupMgr()->setRule( action( 219 ), aDiffElemsInVTK + "&& isVisible &&" + hasVolumes, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 219 ), "{'Volume'} in entityMode", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert( action( SMESHOp::OpDEVolumes ), anId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpDEVolumes ), aDiffElemsInVTK + "&& isVisible &&" + hasVolumes, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpDEVolumes ), "{'Volume'} in entityMode", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert( action( 222 ), anId, -1 ); // BALLS
-  popupMgr()->setRule( action( 222 ), aDiffElemsInVTK + "&& isVisible &&" + hasBalls, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 222 ), "{'BallElem'} in entityMode", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert( action( SMESHOp::OpDEBalls ), anId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpDEBalls ), aDiffElemsInVTK + "&& isVisible &&" + hasBalls, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpDEBalls ), "{'BallElem'} in entityMode", QtxPopupMgr::ToggleRule );
 
   popupMgr()->insert( separator(), anId, -1 );
 
-  popupMgr()->insert( action( 220 ), anId, -1 ); // ALL
-  popupMgr()->setRule( action( 220 ), aDiffElemsInVTK + "&& isVisible && not( elemTypes in entityMode )", QtxPopupMgr::VisibleRule );
+  popupMgr()->insert( action( SMESHOp::OpDEAllEntity ), anId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpDEAllEntity ), aDiffElemsInVTK + "&& isVisible && not( elemTypes in entityMode )", QtxPopupMgr::VisibleRule );
 
 
   //-------------------------------------------------
   // Representation of the 2D Quadratic elements
   //-------------------------------------------------
   anId = popupMgr()->insert( tr( "MEN_QUADRATIC_REPRESENT" ), -1, -1 );
-  popupMgr()->insert( action( 231 ), anId, -1 ); // LINE REPRESENTATION
-  popupMgr()->setRule( action( 231 ), aMeshInVTK + "and isVisible",QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 231 ), "quadratic2DMode = 'eLines'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert( action( SMESHOp::OpRepresentationLines ), anId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpRepresentationLines ), aMeshInVTK + "and isVisible",QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpRepresentationLines ), "quadratic2DMode = 'eLines'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert( action( 232 ), anId, -1 ); // ARC REPRESENTATION
-  popupMgr()->setRule( action( 232 ), aMeshInVTK + "and isVisible", QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 232 ), "quadratic2DMode = 'eArcs'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert( action( SMESHOp::OpRepresentationArcs ), anId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpRepresentationArcs ), aMeshInVTK + "and isVisible", QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpRepresentationArcs ), "quadratic2DMode = 'eArcs'", QtxPopupMgr::ToggleRule );
 
   //-------------------------------------------------
   // Orientation of faces
   //-------------------------------------------------
-  popupMgr()->insert( action( 221 ), -1, -1 );
-  popupMgr()->setRule( action( 221 ), aMeshInVTK + "&& isVisible", QtxPopupMgr::VisibleRule);
-  popupMgr()->setRule( action( 221 ), "facesOrientationMode = 'IsOriented'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert( action( SMESHOp::OpOrientationOnFaces ), -1, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpOrientationOnFaces ), aMeshInVTK + "&& isVisible", QtxPopupMgr::VisibleRule);
+  popupMgr()->setRule( action( SMESHOp::OpOrientationOnFaces ), "facesOrientationMode = 'IsOriented'", QtxPopupMgr::ToggleRule );
 
   //-------------------------------------------------
   // Color / Size
   //-------------------------------------------------
-  popupMgr()->insert( action( 1132 ), -1, -1 );
-  popupMgr()->setRule( action( 1132 ), aMeshInVTK + "&& isVisible", QtxPopupMgr::VisibleRule );
+  popupMgr()->insert( action( SMESHOp::OpProperties ), -1, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpProperties ), aMeshInVTK + "&& isVisible", QtxPopupMgr::VisibleRule );
 
   //-------------------------------------------------
   // Transparency
   //-------------------------------------------------
-  popupMgr()->insert( action( 1133 ), -1, -1 );
-  popupMgr()->setRule( action( 1133 ), aMeshInVTK + "&& isVisible", QtxPopupMgr::VisibleRule );
+  popupMgr()->insert( action( SMESHOp::OpTransparency ), -1, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpTransparency ), aMeshInVTK + "&& isVisible", QtxPopupMgr::VisibleRule );
 
   //-------------------------------------------------
   // Controls
@@ -4436,170 +4459,170 @@ void SMESHGUI::initialize( CAM_Application* app )
 
   anId = popupMgr()->insert( tr( "MEN_CTRL" ), -1, -1 );
 
-  popupMgr()->insert( action( 200 ), anId, -1 ); // RESET
-  popupMgr()->setRule( action( 200 ), aMeshInVTK + "&& controlMode <> 'eNone'", QtxPopupMgr::VisibleRule );
+  popupMgr()->insert( action( SMESHOp::OpReset ), anId, -1 ); // RESET
+  popupMgr()->setRule( action( SMESHOp::OpReset ), aMeshInVTK + "&& controlMode <> 'eNone'", QtxPopupMgr::VisibleRule );
 
   popupMgr()->insert( separator(), anId, -1 );
 
   int aSubId = popupMgr()->insert( tr( "MEN_NODE_CTRL" ), anId, -1 ); // NODE CONTROLS
 
-  popupMgr()->insert( action( 6005 ), aSubId, -1 ); // FREE_NODE
-  popupMgr()->setRule( action( 6005 ), aMeshInVtkHasNodes, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6005 ), "controlMode = 'eFreeNodes'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert( action( SMESHOp::OpFreeNode ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpFreeNode ), aMeshInVtkHasNodes, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpFreeNode ), "controlMode = 'eFreeNodes'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert ( action( 6028 ), aSubId, -1 ); // EQUAL_NODE
-  popupMgr()->setRule( action( 6028 ), aMeshInVtkHasNodes, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6028 ), "controlMode = 'eCoincidentNodes'", QtxPopupMgr::ToggleRule);
+  popupMgr()->insert ( action( SMESHOp::OpEqualNode ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpEqualNode ), aMeshInVtkHasNodes, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpEqualNode ), "controlMode = 'eCoincidentNodes'", QtxPopupMgr::ToggleRule);
 
   aSubId = popupMgr()->insert( tr( "MEN_EDGE_CTRL" ), anId, -1 ); // EDGE CONTROLS
 
-  popupMgr()->insert( action( 6002 ), aSubId, -1 ); // FREE_EDGE
-  popupMgr()->setRule( action( 6002 ), aMeshInVtkHasEdges, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6002 ), "controlMode = 'eFreeEdges'", QtxPopupMgr::ToggleRule );
+  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( 6003 ), aSubId, -1 ); // FREE_BORDER
-  popupMgr()->setRule( action( 6003 ), aMeshInVtkHasEdges, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6003 ), "controlMode = 'eFreeBorders'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert( action( SMESHOp::OpFreeBorder ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpFreeBorder ), aMeshInVtkHasEdges, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpFreeBorder ), "controlMode = 'eFreeBorders'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert( action( 6001 ), aSubId, -1 ); // LENGTH
-  popupMgr()->setRule( action( 6001 ), aMeshInVtkHasEdges, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6001 ), "controlMode = 'eLength'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert( action( SMESHOp::OpLength ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpLength ), aMeshInVtkHasEdges, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpLength ), "controlMode = 'eLength'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert( action( 6004 ), aSubId, -1 ); // CONNECTION
-  popupMgr()->setRule( action( 6004 ), aMeshInVtkHasEdges, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6004 ), "controlMode = 'eMultiConnection'", QtxPopupMgr::ToggleRule );
-  popupMgr()->insert ( action( 6029 ), aSubId, -1 ); // EQUAL_EDGE
-  popupMgr()->setRule( action( 6029 ), aMeshInVtkHasEdges, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6029 ), "controlMode = 'eCoincidentElems1D'", QtxPopupMgr::ToggleRule);
+  popupMgr()->insert( action( SMESHOp::OpConnection ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpConnection ), aMeshInVtkHasEdges, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpConnection ), "controlMode = 'eMultiConnection'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert ( action( SMESHOp::OpEqualEdge ), aSubId, -1 ); // EQUAL_EDGE
+  popupMgr()->setRule( action( SMESHOp::OpEqualEdge ), aMeshInVtkHasEdges, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpEqualEdge ), "controlMode = 'eCoincidentElems1D'", QtxPopupMgr::ToggleRule);
 
   aSubId = popupMgr()->insert( tr( "MEN_FACE_CTRL" ), anId, -1 ); // FACE CONTROLS
 
-  popupMgr()->insert ( action( 6021 ), aSubId, -1 ); // FREE_FACE
-  popupMgr()->setRule( action( 6021 ), aMeshInVtkHasFaces /*aMeshInVtkHasVolumes*/,
+  popupMgr()->insert ( action( SMESHOp::OpFreeFace ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpFreeFace ), aMeshInVtkHasFaces /*aMeshInVtkHasVolumes*/,
                                        QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6021 ), "controlMode = 'eFreeFaces'", QtxPopupMgr::ToggleRule );
+  popupMgr()->setRule( action( SMESHOp::OpFreeFace ), "controlMode = 'eFreeFaces'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert ( action( 6018 ), aSubId, -1 ); // LENGTH_2D
-  popupMgr()->setRule( action( 6018 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6018 ), "controlMode = 'eLength2D'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert ( action( SMESHOp::OpLength2D ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpLength2D ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpLength2D ), "controlMode = 'eLength2D'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert ( action( 6019 ), aSubId, -1 ); // CONNECTION_2D
-  popupMgr()->setRule( action( 6019 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6019 ), "controlMode = 'eMultiConnection2D'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert ( action( SMESHOp::OpConnection2D ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpConnection2D ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpConnection2D ), "controlMode = 'eMultiConnection2D'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert ( action( 6011 ), aSubId, -1 ); // AREA
-  popupMgr()->setRule( action( 6011 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6011 ), "controlMode = 'eArea'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert ( action( SMESHOp::OpArea ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpArea ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpArea ), "controlMode = 'eArea'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert ( action( 6012 ), aSubId, -1 ); // TAPER
-  popupMgr()->setRule( action( 6012 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6012 ), "controlMode = 'eTaper'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert ( action( SMESHOp::OpTaper ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpTaper ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpTaper ), "controlMode = 'eTaper'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert ( action( 6013 ), aSubId, -1 ); // ASPECT
-  popupMgr()->setRule( action( 6013 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6013 ), "controlMode = 'eAspectRatio'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert ( action( SMESHOp::OpAspectRatio ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpAspectRatio ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpAspectRatio ), "controlMode = 'eAspectRatio'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert ( action( 6014 ), aSubId, -1 ); // MIN_ANG
-  popupMgr()->setRule( action( 6014 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6014 ), "controlMode = 'eMinimumAngle'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert ( action( SMESHOp::OpMinimumAngle ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpMinimumAngle ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpMinimumAngle ), "controlMode = 'eMinimumAngle'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert ( action( 6015 ), aSubId, -1 ); // WARP
-  popupMgr()->setRule( action( 6015 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6015 ), "controlMode = 'eWarping'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert ( action( SMESHOp::OpWarpingAngle ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpWarpingAngle ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpWarpingAngle ), "controlMode = 'eWarping'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert ( action( 6016 ), aSubId, -1 ); // SKEW
-  popupMgr()->setRule( action( 6016 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6016 ), "controlMode = 'eSkew'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert ( action( SMESHOp::OpSkew ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpSkew ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpSkew ), "controlMode = 'eSkew'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert ( action( 6022 ), aSubId, -1 ); // MAX_ELEMENT_LENGTH_2D
-  popupMgr()->setRule( action( 6022 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6022 ), "controlMode = 'eMaxElementLength2D'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert ( action( SMESHOp::OpMaxElementLength2D ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpMaxElementLength2D ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpMaxElementLength2D ), "controlMode = 'eMaxElementLength2D'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert ( action( 6025 ), aSubId, -1 ); // BARE_BORDER_FACE
-  popupMgr()->setRule( action( 6025 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6025 ), "controlMode = 'eBareBorderFace'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert ( action( SMESHOp::OpBareBorderFace ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpBareBorderFace ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpBareBorderFace ), "controlMode = 'eBareBorderFace'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert ( action( 6027 ), aSubId, -1 ); // OVER_CONSTRAINED_FACE
-  popupMgr()->setRule( action( 6027 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6027 ), "controlMode = 'eOverConstrainedFace'", QtxPopupMgr::ToggleRule );
-  popupMgr()->insert ( action( 6030 ), aSubId, -1 ); // EQUAL_FACE
-  popupMgr()->setRule( action( 6030 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6030 ), "controlMode = 'eCoincidentElems2D'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert ( action( SMESHOp::OpOverConstrainedFace ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpOverConstrainedFace ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpOverConstrainedFace ), "controlMode = 'eOverConstrainedFace'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert ( action( SMESHOp::OpEqualFace ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpEqualFace ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpEqualFace ), "controlMode = 'eCoincidentElems2D'", QtxPopupMgr::ToggleRule );
 
   aSubId = popupMgr()->insert( tr( "MEN_VOLUME_CTRL" ), anId, -1 ); // VOLUME CONTROLS
 
-  popupMgr()->insert ( action( 6017 ), aSubId, -1 ); // ASPECT_3D
-  popupMgr()->setRule( action( 6017 ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6017 ), "controlMode = 'eAspectRatio3D'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert ( action( SMESHOp::OpAspectRatio3D  ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpAspectRatio3D ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpAspectRatio3D ), "controlMode = 'eAspectRatio3D'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert ( action( 6009 ), aSubId, -1 ); // VOLUME_3D
-  popupMgr()->setRule( action( 6009 ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6009 ), "controlMode = 'eVolume3D'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert ( action( SMESHOp::OpVolume ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpVolume ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpVolume ), "controlMode = 'eVolume3D'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert ( action( 6023 ), aSubId, -1 ); // MAX_ELEMENT_LENGTH_3D
-  popupMgr()->setRule( action( 6023 ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6023 ), "controlMode = 'eMaxElementLength3D'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert ( action( SMESHOp::OpMaxElementLength3D ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpMaxElementLength3D ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpMaxElementLength3D ), "controlMode = 'eMaxElementLength3D'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert ( action( 6024 ), aSubId, -1 ); // BARE_BORDER_VOLUME
-  popupMgr()->setRule( action( 6024 ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6024 ), "controlMode = 'eBareBorderVolume'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert ( action( SMESHOp::OpBareBorderVolume ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpBareBorderVolume ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpBareBorderVolume ), "controlMode = 'eBareBorderVolume'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert ( action( 6026 ), aSubId, -1 ); // OVER_CONSTRAINED_VOLUME
-  popupMgr()->setRule( action( 6026 ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6026 ), "controlMode = 'eOverConstrainedVolume'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert ( action( SMESHOp::OpOverConstrainedVolume ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpOverConstrainedVolume ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpOverConstrainedVolume ), "controlMode = 'eOverConstrainedVolume'", QtxPopupMgr::ToggleRule );
 
-  popupMgr()->insert ( action( 6031 ), aSubId, -1 ); // EQUAL_VOLUME
-  popupMgr()->setRule( action( 6031 ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 6031 ), "controlMode = 'eCoincidentElems3D'", QtxPopupMgr::ToggleRule );
+  popupMgr()->insert ( action( SMESHOp::OpEqualVolume  ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpEqualVolume ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpEqualVolume ), "controlMode = 'eCoincidentElems3D'", QtxPopupMgr::ToggleRule );
 
   popupMgr()->insert( separator(), anId, -1 );
 
-  popupMgr()->insert( action( 201 ), anId, -1 ); // SCALAR_BAR_PROP
-  popupMgr()->setRule( action( 201 ), aMeshInVTK + "&& controlMode <> 'eNone'", QtxPopupMgr::VisibleRule );
+  popupMgr()->insert( action( SMESHOp::OpScalarBarProperties ), anId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpScalarBarProperties ), aMeshInVTK + "&& controlMode <> 'eNone'", QtxPopupMgr::VisibleRule );
 
   popupMgr()->insert( separator(), anId, -1 );
 
   aSubId = popupMgr()->insert( tr( "MEN_DISTRIBUTION_CTRL" ), anId, -1 ); // NODE CONTROLS
 
-  popupMgr()->insert( action( 2021 ), aSubId, -1 ); // SAVE_DISTRIBUTION
-  popupMgr()->setRule( action( 2021 ), aMeshInVTK + "&& isNumFunctor", QtxPopupMgr::VisibleRule );
+  popupMgr()->insert( action( SMESHOp::OpSaveDistribution ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpSaveDistribution ), aMeshInVTK + "&& isNumFunctor", QtxPopupMgr::VisibleRule );
 
-  popupMgr()->insert( action( 2022 ), aSubId, -1 ); // SHOW_DISTRIBUTION
-  popupMgr()->setRule( action( 2022 ), aMeshInVTK + "&& isNumFunctor", QtxPopupMgr::VisibleRule );
-  popupMgr()->setRule( action( 2022 ), aMeshInVTK + "&& isNumFunctor && isDistributionVisible", QtxPopupMgr::ToggleRule);
+  popupMgr()->insert( action( SMESHOp::OpShowDistribution ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpShowDistribution ), aMeshInVTK + "&& isNumFunctor", QtxPopupMgr::VisibleRule );
+  popupMgr()->setRule( action( SMESHOp::OpShowDistribution ), aMeshInVTK + "&& isNumFunctor && isDistributionVisible", QtxPopupMgr::ToggleRule);
 
 #ifndef DISABLE_PLOT2DVIEWER
-  popupMgr()->insert( action( 2023 ), aSubId, -1 ); // PLOT_DISTRIBUTION
-  popupMgr()->setRule( action( 2023 ), aMeshInVTK + "&& isNumFunctor", QtxPopupMgr::VisibleRule );
+  popupMgr()->insert( action( SMESHOp::OpPlotDistribution ), aSubId, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpPlotDistribution ), aMeshInVTK + "&& isNumFunctor", QtxPopupMgr::VisibleRule );
 #endif
 
   //-------------------------------------------------
-  // Display / Erase
+  // Show / Hide
   //-------------------------------------------------
   popupMgr()->insert( separator(), -1, -1 );
   QString aRule = "$component={'SMESH'} and ( type='Component' or (" + aClient + " and " +
     aType + " and " + aSelCount + " and " + anActiveVTK + " and " + isNotEmpty + " %1 ) )";
-  popupMgr()->insert( action( 301 ), -1, -1 ); // DISPLAY
-  popupMgr()->setRule( action( 301 ), aRule.arg( "and (not isVisible)" ), QtxPopupMgr::VisibleRule );
+  popupMgr()->insert( action( SMESHOp::OpShow ), -1, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpShow ), aRule.arg( "and (not isVisible)" ), QtxPopupMgr::VisibleRule );
 
-  popupMgr()->insert( action( 300 ), -1, -1 ); // ERASE
-  popupMgr()->setRule( action( 300 ), aRule.arg( "and isVisible" ), QtxPopupMgr::VisibleRule );
+  popupMgr()->insert( action( SMESHOp::OpHide ), -1, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpHide ), aRule.arg( "and isVisible" ), QtxPopupMgr::VisibleRule );
 
-  popupMgr()->insert( action( 302 ), -1, -1 ); // DISPLAY_ONLY
-  popupMgr()->setRule( action( 302 ), aRule.arg( "" ), QtxPopupMgr::VisibleRule );
+  popupMgr()->insert( action( SMESHOp::OpShowOnly ), -1, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpShowOnly ), aRule.arg( "" ), QtxPopupMgr::VisibleRule );
 
   popupMgr()->insert( separator(), -1, -1 );
 
   //-------------------------------------------------
   // Clipping
   //-------------------------------------------------
-  popupMgr()->insert( action( 1134 ), -1, -1 );
-  popupMgr()->setRule( action( 1134 ), "client='VTKViewer'", QtxPopupMgr::VisibleRule );
+  popupMgr()->insert( action( SMESHOp::OpClipping ), -1, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpClipping ), "client='VTKViewer'", QtxPopupMgr::VisibleRule );
 
   popupMgr()->insert( separator(), -1, -1 );
 
-  popupMgr()->insert( action( 41 ), -1, -1 );
-  popupMgr()->setRule( action( 41 ), "$component={'SMESH'} and client='ObjectBrowser' and isContainer and nbChildren>1", QtxPopupMgr::VisibleRule );
+  popupMgr()->insert( action( SMESHOp::OpSortChild ), -1, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpSortChild ), "$component={'SMESH'} and client='ObjectBrowser' and isContainer and nbChildren>1", QtxPopupMgr::VisibleRule );
   popupMgr()->insert( separator(), -1, -1 );
 
   connect( application(), SIGNAL( viewManagerActivated( SUIT_ViewManager* ) ),
@@ -4637,7 +4660,7 @@ bool SMESHGUI::isSelectionCompatible()
 bool SMESHGUI::reusableOperation( const int id )
 {
   // compute, evaluate and precompute are not reusable operations
-  return ( id == 701 || id == 711 || id == 712 ) ? false : SalomeApp_Module::reusableOperation( id );
+  return ( id == SMESHOp::OpCompute || id == SMESHOp::OpPreCompute || id == SMESHOp::OpEvaluate ) ? false : SalomeApp_Module::reusableOperation( id );
 }
 
 bool SMESHGUI::activateModule( SUIT_Study* study )
@@ -4662,11 +4685,11 @@ bool SMESHGUI::activateModule( SUIT_Study* study )
   // end of SMESH plugins loading
 
   // Reset actions accelerator keys
-  //action(111)->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_B)); // Import DAT
-  action(112)->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_U)); // Import UNV
-  action(113)->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M)); // Import MED
+  //action(SMESHOp::OpImportDAT)->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_B));
+  action(SMESHOp::OpImportUNV)->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_U));
+  action(SMESHOp::OpImportMED)->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M));
 
-  action(  33)->setEnabled(true); // Delete: Key_Delete
+  action(SMESHOp::OpDelete)->setEnabled(true); // Delete: Key_Delete
 
   //  0020210. Make SMESH_Gen update meshes at switching GEOM->SMESH
   GetSMESHGen()->SetCurrentStudy(SALOMEDS::Study::_nil());
@@ -4697,11 +4720,11 @@ bool SMESHGUI::deactivateModule( SUIT_Study* study )
   EmitSignalCloseAllDialogs();
 
   // Unset actions accelerator keys
-  //action(111)->setShortcut(QKeySequence()); // Import DAT
-  action(112)->setShortcut(QKeySequence()); // Import UNV
-  action(113)->setShortcut(QKeySequence()); // Import MED
+  //action(SMESHOp::OpImportDAT)->setShortcut(QKeySequence());
+  action(SMESHOp::OpImportUNV)->setShortcut(QKeySequence());
+  action(SMESHOp::OpImportMED)->setShortcut(QKeySequence());
 
-  action(  33)->setEnabled(false); // Delete: Key_Delete
+  action(SMESHOp::OpDelete)->setEnabled(false); // Delete: Key_Delete
 
   return SalomeApp_Module::deactivateModule( study );
 }
@@ -4755,7 +4778,7 @@ void SMESHGUI::contextMenuPopup( const QString& client, QMenu* menu, QString& ti
     _PTR(Study) study = appStudy->studyDS();
     _PTR(SObject) obj = study->FindObjectID( io->getEntry() );
     if ( obj ) {
-      QString aName = QString( obj->GetName().c_str() );
+      QString aName = QString( QString::fromUtf8(obj->GetName().c_str()) );
       while ( aName.at( aName.length() - 1 ) == ' ' ) // Remove extraspaces in Name of Popup
           aName.remove( (aName.length() - 1), 1 );
       title = aName;
@@ -5354,46 +5377,46 @@ LightApp_Operation* SMESHGUI::createOperation( const int id ) const
   // to do : create operation here
   switch( id )
   {
-    case 417: //convert to quadratic
+    case SMESHOp::OpConvertMeshToQuadratic:
       op = new SMESHGUI_ConvToQuadOp();
     break;
-    case 418: // create 2D mesh as boundary on 3D
+    case SMESHOp::OpCreateBoundaryElements: // create 2D mesh as boundary on 3D
       op = new SMESHGUI_Make2DFrom3DOp();
     break;
-    case 420: // Reorient faces
+    case SMESHOp::OpReorientFaces:
       op = new SMESHGUI_ReorientFacesOp();
       break;
-    case 701: // Compute mesh
-      op = new SMESHGUI_ComputeOp();
-    break;
-    case 702: // Create mesh
+    case SMESHOp::OpCreateMesh:
       op = new SMESHGUI_MeshOp( true, true );
     break;
-    case 703: // Create sub-mesh
+    case SMESHOp::OpCreateSubMesh:
       op = new SMESHGUI_MeshOp( true, false );
     break;
-    case 704: // Edit mesh/sub-mesh
+    case SMESHOp::OpEditMeshOrSubMesh:
       op = new SMESHGUI_MeshOp( false );
     break;
-    case 711: // Precompute mesh
+    case SMESHOp::OpCompute:
+      op = new SMESHGUI_ComputeOp();
+    break;
+    case SMESHOp::OpPreCompute:
       op = new SMESHGUI_PrecomputeOp();
     break;
-    case 712: // Evaluate mesh
+    case SMESHOp::OpEvaluate:
       op = new SMESHGUI_EvaluateOp();
     break;
-    case 713: // Evaluate mesh
+    case SMESHOp::OpMeshOrder:
       op = new SMESHGUI_MeshOrderOp();
     break;
-    case 806: // Create group on geom
+    case SMESHOp::OpCreateGeometryGroup:
       op = new SMESHGUI_GroupOnShapeOp();
       break;
-    case 904: // Find element
+    case SMESHOp::OpFindElementByPoint:
       op = new SMESHGUI_FindElemByPointOp();
       break;
-    case 4067: // Make mesh pass through point
+    case SMESHOp::OpMoveNode: // Make mesh pass through point
       op = new SMESHGUI_MakeNodeAtPointOp();
       break;
-    case 4070: // Create 0D elements on all nodes
+    case SMESHOp::OpElem0DOnElemNodes: // Create 0D elements on all nodes
       op = new SMESHGUI_Add0DElemsOnAllNodesOp();
       break;
     default:
@@ -6735,7 +6758,7 @@ void SMESHGUI::message( const QString& msg )
       _PTR(SObject) obj = study->FindObjectID( entry.toLatin1().constData() );
       QString name;
       if ( obj )
-        name = obj->GetName().c_str();
+        name = QString::fromUtf8(obj->GetName().c_str());
       if ( name.isEmpty() )
         return;
       
index 15b9487bcafaa3dbc9fc31d026a8e6777da298c7..1bf5e5c8b975283865894de8afd4f48782407be9 100644 (file)
@@ -916,7 +916,7 @@ void SMESHGUI_BaseComputeOp::computeMesh()
       long nbElements = 0;
       if ( !memoryLack )
       {
-       // List of objects that will be updated automatically
+        // List of objects that will be updated automatically
         QList< QPair< SMESH::SMESH_IDSource_var, _PTR(SObject) > > aListToUpdate;
         SMESH::SMESH_IDSource_var aMeshObj = SMESH::SObjectToInterface<SMESH::SMESH_IDSource>( aMeshSObj );
         // put Mesh into list
@@ -949,60 +949,60 @@ void SMESHGUI_BaseComputeOp::computeMesh()
         // update mesh, sub-mesh and groups, if it's possible
         QList< QPair< SMESH::SMESH_IDSource_var, _PTR(SObject) > >::iterator anIter;
         for( anIter = aListToUpdate.begin(); anIter != aListToUpdate.end(); anIter++ ) {
-         SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow( SMESH::SObjectToObject( (*anIter).second ));
-         if ( getSMESHGUI()->automaticUpdate( (*anIter).first, &entities, &limitExceeded, &hidden, &nbElements ) )
-         {
-           try {
+          SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow( SMESH::SObjectToObject( (*anIter).second ));
+          if ( getSMESHGUI()->automaticUpdate( (*anIter).first, &entities, &limitExceeded, &hidden, &nbElements ) )
+          {
+            try {
 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
-             OCC_CATCH_SIGNALS;
+              OCC_CATCH_SIGNALS;
 #endif
-             bool toDisplay = false;
-
-             if ( !aMesh->_is_nil() ) { // display a mesh only
-               toDisplay = true;
-               SMESH_Actor *anActor = SMESH::FindActorByObject( aMesh );
-               if ( !anActor ) anActor = SMESH::CreateActor( (*anIter).second->GetStudy(), (*anIter).second->GetID().c_str(), true );    
-               if ( anActor ) // actor is not created for an empty mesh
-               {
-                 anActor->SetEntityMode( entities );
-                 SMESH::DisplayActor( SMESH::GetActiveWindow(), anActor );
-               }
-             }
-             Handle(SALOME_InteractiveObject) anIO = new SALOME_InteractiveObject
-               ( (*anIter).second->GetID().c_str(), "SMESH", (*anIter).second->GetName().c_str() );
-             SMESH::Update(anIO, toDisplay);
-
-             if ( limitExceeded && !aMesh->_is_nil() )
-             {
-               QStringList hiddenMsg;
-               if ( hidden & SMESH_Actor::e0DElements ) hiddenMsg << tr( "SMESH_ELEMS0D" );
-               if ( hidden & SMESH_Actor::eEdges )      hiddenMsg << tr( "SMESH_EDGES" );
-               if ( hidden & SMESH_Actor::eFaces )      hiddenMsg << tr( "SMESH_FACES" );
-               if ( hidden & SMESH_Actor::eVolumes )    hiddenMsg << tr( "SMESH_VOLUMES" );
-               if ( hidden & SMESH_Actor::eBallElem )   hiddenMsg << tr( "SMESH_BALLS" );
-               SUIT_MessageBox::warning( desktop(),
-                                         tr( "SMESH_WRN_WARNING" ),
-                                         tr( "SMESH_WRN_SIZE_INC_LIMIT_EXCEEDED" ).arg( nbElements ).arg( limitSize ).arg( hiddenMsg.join(", ") ) );
-             }
-           }
-           catch (...) {
+              bool toDisplay = false;
+
+              if ( !aMesh->_is_nil() ) { // display a mesh only
+                toDisplay = true;
+                SMESH_Actor *anActor = SMESH::FindActorByObject( aMesh );
+                if ( !anActor ) anActor = SMESH::CreateActor( (*anIter).second->GetStudy(), (*anIter).second->GetID().c_str(), true );    
+                if ( anActor ) // actor is not created for an empty mesh
+                {
+                  anActor->SetEntityMode( entities );
+                  SMESH::DisplayActor( SMESH::GetActiveWindow(), anActor );
+                }
+              }
+              Handle(SALOME_InteractiveObject) anIO = new SALOME_InteractiveObject
+                ( (*anIter).second->GetID().c_str(), "SMESH", (*anIter).second->GetName().c_str() );
+              SMESH::Update(anIO, toDisplay);
+
+              if ( limitExceeded && !aMesh->_is_nil() )
+              {
+                QStringList hiddenMsg;
+                if ( hidden & SMESH_Actor::e0DElements ) hiddenMsg << tr( "SMESH_ELEMS0D" );
+                if ( hidden & SMESH_Actor::eEdges )      hiddenMsg << tr( "SMESH_EDGES" );
+                if ( hidden & SMESH_Actor::eFaces )      hiddenMsg << tr( "SMESH_FACES" );
+                if ( hidden & SMESH_Actor::eVolumes )    hiddenMsg << tr( "SMESH_VOLUMES" );
+                if ( hidden & SMESH_Actor::eBallElem )   hiddenMsg << tr( "SMESH_BALLS" );
+                SUIT_MessageBox::warning( desktop(),
+                                          tr( "SMESH_WRN_WARNING" ),
+                                          tr( "SMESH_WRN_SIZE_INC_LIMIT_EXCEEDED" ).arg( nbElements ).arg( limitSize ).arg( hiddenMsg.join(", ") ) );
+              }
+            }
+            catch (...) {
 #ifdef _DEBUG_
-             MESSAGE ( "Exception thrown during mesh visualization" );
+              MESSAGE ( "Exception thrown during mesh visualization" );
 #endif
-             if ( SMDS_Mesh::CheckMemory(true) ) { // has memory to show warning?
-               SMESH::OnVisuException();
-             }
-             else {
-               memoryLack = true;
-             }
-           }
-         }
-         else if ( limitExceeded && !aMesh->_is_nil() )
-         {
-           SUIT_MessageBox::warning( desktop(),
-                                     tr( "SMESH_WRN_WARNING" ),
-                                     tr( "SMESH_WRN_SIZE_LIMIT_EXCEEDED" ).arg( nbElements ).arg( limitSize ) );
-         }
+              if ( SMDS_Mesh::CheckMemory(true) ) { // has memory to show warning?
+                SMESH::OnVisuException();
+              }
+              else {
+                memoryLack = true;
+              }
+            }
+          }
+          else if ( limitExceeded && !aMesh->_is_nil() )
+          {
+            SUIT_MessageBox::warning( desktop(),
+                                      tr( "SMESH_WRN_WARNING" ),
+                                      tr( "SMESH_WRN_SIZE_LIMIT_EXCEEDED" ).arg( nbElements ).arg( limitSize ) );
+          }
         }
       }
       LightApp_SelectionMgr *Sel = selectionMgr();
index 368aa77ca6624905b542afd43c2ca2571e31d680..ad4997644dd4f5be795d78a3dc9b578ee8e67dfd 100644 (file)
@@ -602,7 +602,8 @@ void SMESHGUI_DuplicateNodesDlg::onSelectionChanged()
         ok = ( aGroupType != SMESH::NODE );
         break;
       case 3:
-        ok = ( aGroupType == SMESH::VOLUME );
+        ok = ( aGroupType == SMESH::VOLUME || 
+              aGroupType == SMESH::FACE );
         break;
       }
     }
index 4211d08bffaa52994ee96cba3463069744b36e4c..8409afa4a0f54b61bce997949ef38269d7e850d2 100755 (executable)
@@ -2654,7 +2654,9 @@ SMESHGUI_FilterDlg::SMESHGUI_FilterDlg( SMESHGUI*         theModule,
 : QDialog( SMESH::GetDesktop( theModule ) ),
   mySMESHGUI( theModule ),
   mySelectionMgr( SMESH::GetSelectionMgr( theModule ) ),
-  myInitSourceWgOnApply( true )
+  myInitSourceWgOnApply( true ),
+  myInsertEnabled( true ),
+  myDiffSourcesEnabled( true )
 {
   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
     mySelector = aViewWindow->GetSelector();
@@ -2671,7 +2673,9 @@ SMESHGUI_FilterDlg::SMESHGUI_FilterDlg( SMESHGUI*   theModule,
 : QDialog( SMESH::GetDesktop( theModule ) ),
   mySMESHGUI( theModule ),
   mySelectionMgr( SMESH::GetSelectionMgr( theModule ) ),
-  myInitSourceWgOnApply( true )
+  myInitSourceWgOnApply( true ),
+  myInsertEnabled( true ),
+  myDiffSourcesEnabled( true )
 {
   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
     mySelector = aViewWindow->GetSelector();
@@ -2730,6 +2734,7 @@ QWidget* SMESHGUI_FilterDlg::createMainFrame (QWidget* theParent)
   int rows = aLay->rowCount();
   int cols = aLay->columnCount();
 
+  // This line looks strange when all additional parameters and mySetInViewer are hidden
   QFrame* aLine = new QFrame(aGrp);
   aLine->setFrameStyle(QFrame::HLine | QFrame::Sunken);
   aLay->addWidget(aLine, rows++, 0, 1, cols);
@@ -3215,6 +3220,21 @@ void SMESHGUI_FilterDlg::SetSourceWg (QWidget* theWg,
   myInitSourceWgOnApply = initOnApply;
 }
 
+//=======================================================================
+//function : EnableFiltering
+//purpose  : Enables "Insert filter in the viewer"
+//           and different "Source"s (Mesh, Initial Selection, Current Group)
+//=======================================================================
+
+void SMESHGUI_FilterDlg::SetEnabled( bool setInViewer, bool diffSources )
+{
+  myInsertEnabled = setInViewer;
+  myDiffSourcesEnabled = diffSources;
+
+  mySetInViewer->setVisible( myInsertEnabled );
+  mySourceGrp->button(0)->parentWidget()->setVisible( myDiffSourcesEnabled );
+}
+
 //=======================================================================
 // name    : SMESHGUI_FilterDlg::SetMesh
 // Purpose : Set mesh
@@ -3397,8 +3417,10 @@ void SMESHGUI_FilterDlg::insertFilterInViewer()
     SMESH::ElementType anEntType = (SMESH::ElementType)myTable->GetType();
 
     if (myFilter[ myTable->GetType() ]->_is_nil() ||
-         myFilter[ myTable->GetType() ]->GetPredicate()->_is_nil() ||
-         !mySetInViewer->isChecked()) {
+        myFilter[ myTable->GetType() ]->GetPredicate()->_is_nil() ||
+        !mySetInViewer->isChecked() ||
+        !myInsertEnabled )
+    {
       SMESH::RemoveFilter(getFilterId(anEntType), aSelector);
     }
     else {
@@ -3423,7 +3445,7 @@ void SMESHGUI_FilterDlg::filterSource (const int theType,
 
   int aSourceId = mySourceGrp->checkedId();
 
-  if (aSourceId == Mesh)
+  if (aSourceId == Mesh || !myDiffSourcesEnabled )
   {
     if (myMesh->_is_nil())
       return;
index e00941329b5a1479e7e3f28bea65bb8a66f49f29..da3358a8a88053192a93671e9f648bf725780325 100755 (executable)
@@ -229,6 +229,7 @@ public:
   void                      SetSelection();
   void                      SetMesh (SMESH::SMESH_Mesh_var);
   void                      SetSourceWg( QWidget*, const bool initOnApply = true );
+  void                      SetEnabled( bool setInViewer, bool diffSources );
 
   static SMESH::Filter::Criterion createCriterion();
 
@@ -297,6 +298,8 @@ private:
   SVTK_Selector*            mySelector;
   SMESH::SMESH_Mesh_var     myMesh;
   bool                      myInitSourceWgOnApply;
+  bool                      myInsertEnabled;
+  bool                      myDiffSourcesEnabled;
   QWidget*                  mySourceWg;
 
   SALOME_DataMapOfIOMapOfInteger myIObjects;
index 8c2fa06ef3f0f5044388135b5b6f2375c5cc3110..88b1819445cb5ace027fd75faba4cb4bead9bcc2 100644 (file)
@@ -27,6 +27,7 @@
 //
 #include "SMESHGUI_GEOMGenUtils.h"
 #include "SMESHGUI_Utils.h"
+#include "SMESHGUI.h"
 
 // SALOME GEOM includes
 #include <GeometryGUI.h>
@@ -39,6 +40,8 @@
 #include <SALOMEconfig.h>
 #include CORBA_CLIENT_HEADER(SMESH_Mesh)
 
+#include <QString>
+
 namespace SMESH
 {
   GEOM::GEOM_Gen_var GetGEOMGen()
@@ -156,4 +159,86 @@ namespace SMESH
     GEOM::GEOM_Object_wrap subShape = aShapesOp->GetSubShape (theMainShape,theID);
     return subShape._retn();
   }
+
+  //================================================================================
+  /*!
+   * \brief Return entries of sub-mesh geometry and mesh geometry by an IO of assigned
+   *        hypothesis
+   *  \param [in] hypIO - IO of hyp which is a reference SO to a hyp SO
+   *  \param [out] subGeom - found entry of a sub-mesh if any
+   *  \param [out] meshGeom - found entry of a mesh
+   *  \return bool - \c true if any geometry has been found
+   */
+  //================================================================================
+
+  bool GetGeomEntries( Handle(SALOME_InteractiveObject)& hypIO,
+                       QString&                          subGeom,
+                       QString&                          meshGeom )
+  {
+    subGeom.clear();
+    meshGeom.clear();
+    if ( hypIO.IsNull() ) return false;
+
+    _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
+    if ( !aStudy ) return false;
+
+    _PTR(SObject) hypSO = aStudy->FindObjectID( hypIO->getEntry() );
+    if ( !hypSO ) return false;
+
+    // Depth() is a number of fathers
+    if ( hypSO->Depth() == 4 ) // hypSO is not a reference to a hyp but a hyp it-self
+    {
+      SMESH::SMESH_Hypothesis_var hyp =
+        SMESH::SObjectToInterface< SMESH::SMESH_Hypothesis >( hypSO );
+      SMESH::SMESH_Mesh_var mesh;
+      GEOM::GEOM_Object_var geom;
+      SMESH::SMESH_Gen_var  gen = SMESHGUI::GetSMESHGUI()->GetSMESHGen();
+      if ( !gen || !gen->GetSoleSubMeshUsingHyp( hyp, mesh.out(), geom.out() ))
+        return false;
+
+      subGeom = toQStr( geom->GetStudyEntry() );
+
+      geom  = mesh->GetShapeToMesh();
+      if ( geom->_is_nil() )
+        return false;
+      meshGeom = toQStr( geom->GetStudyEntry() );
+    }
+    else
+    {
+      _PTR(SObject) appliedSO = hypSO->GetFather(); // "Applied hypotheses" folder
+      if ( !appliedSO ) return false;
+
+      _PTR(SObject) subOrMeshSO = appliedSO->GetFather(); // mesh or sub-mesh SO
+      if ( !subOrMeshSO ) return false;
+
+      bool isMesh;
+      GEOM::GEOM_Object_var geom = GetShapeOnMeshOrSubMesh( subOrMeshSO, &isMesh );
+      if ( geom->_is_nil() )
+        return false;
+
+      if ( isMesh )
+      {
+        meshGeom = toQStr( geom->GetStudyEntry() );
+        return !meshGeom.isEmpty();
+      }
+
+      subGeom = toQStr( geom->GetStudyEntry() );
+
+      _PTR(SObject) subFolderSO = subOrMeshSO->GetFather(); // "SubMeshes on ..." folder
+      if ( !subFolderSO ) return false;
+
+      _PTR(SObject) meshSO = subFolderSO->GetFather(); // mesh SO
+      if ( !meshSO ) return false;
+
+      geom = GetShapeOnMeshOrSubMesh( meshSO );
+      if ( geom->_is_nil() )
+        return false;
+
+      meshGeom = toQStr( geom->GetStudyEntry() );
+    }
+
+    return !meshGeom.isEmpty() && !subGeom.isEmpty();
+  }
+
+
 } // end of namespace SMESH
index 72fa9e6d34568c99bc3d140f1376941e1eb9708c..f9cdeafd40acc430f0a58f0b3cc8d5d48ee8492c 100644 (file)
@@ -38,6 +38,8 @@
 #include CORBA_SERVER_HEADER(GEOM_Gen)
 
 class SALOMEDSClient_SObject;
+class Handle_SALOME_InteractiveObject;
+class QString;
 
 namespace SMESH
 {
@@ -50,6 +52,9 @@ namespace SMESH
   SMESHGUI_EXPORT char* GetGeomName( _PTR(SObject) smeshSO );
 
   SMESHGUI_EXPORT GEOM::GEOM_Object_ptr GetSubShape( GEOM::GEOM_Object_ptr, long );
+
+  SMESHGUI_EXPORT bool GetGeomEntries( Handle_SALOME_InteractiveObject& hypIO,
+                                       QString& subGeom, QString& meshGeom);
 }
 
 #endif // SMESHGUI_GEOMGENUTILS_H
index 54a1a5c700770693bcfc528ca14a3b566080f644..60095ebe2a7651a7ec543801ba34316e50278c05 100644 (file)
@@ -53,6 +53,7 @@
 #include <SUIT_ResourceMgr.h>
 #include <SUIT_Session.h>
 #include <SUIT_MessageBox.h>
+#include <SUIT_OverrideCursor.h>
 
 #include <SalomeApp_Tools.h>
 #include <SalomeApp_Application.h>
@@ -446,16 +447,17 @@ void SMESHGUI_GroupDlg::initDialog( bool create)
   mySMESHGUI->SetActiveDialogBox(this);
   mySMESHGUI->SetState(800);
 
+  SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( mySMESHGUI->application()->activeStudy() );
   mySelectionMode = grpNoSelection;
-  myMeshFilter = new SMESH_TypeFilter(SMESH::MESH);
+
+  myMeshFilter    = new SMESH_TypeFilter(SMESH::MESH);
   mySubMeshFilter = new SMESH_LogicalFilter(QList<SUIT_SelectionFilter*>(),
                                             SMESH_LogicalFilter::LO_OR,
                                             /*takeOwnership=*/true);
-  myGroupFilter = new SMESH_LogicalFilter(QList<SUIT_SelectionFilter*>(),
-                                          SMESH_LogicalFilter::LO_OR,
-                                          /*takeOwnership=*/true);
-  SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( mySMESHGUI->application()->activeStudy() );
-  myGeomFilter = new GEOM_SelectionFilter( aStudy, true );
+  myGroupFilter   = new SMESH_LogicalFilter(QList<SUIT_SelectionFilter*>(),
+                                            SMESH_LogicalFilter::LO_OR,
+                                            /*takeOwnership=*/true);
+  myGeomFilter    = new GEOM_SelectionFilter( aStudy, true );
 
   connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), this, SLOT(onDeactivate()));
   connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()),        this, SLOT(reject()));
@@ -518,7 +520,7 @@ QString SMESHGUI_GroupDlg::GetDefaultName(const QString& theOperation)
   bool isUnique = false;
   while (!isUnique) {
     aName = theOperation + "_" + QString::number(++aNumber);
-    isUnique = (aSet.count(aName.toLatin1().data()) == 0);
+    isUnique = (aSet.count(aName.toUtf8().data()) == 0);
   }
 
   return aName;
@@ -534,7 +536,7 @@ void  SMESHGUI_GroupDlg::setDefaultName() const
   do
   {
     aResName = aPrefix + QString::number( i++ );
-    anObj = aStudy->FindObject( aResName.toLatin1().data() );
+    anObj = aStudy->FindObject( aResName.toUtf8().data() );
   }
   while ( anObj );
   myName->setText(aResName); 
@@ -570,7 +572,7 @@ void SMESHGUI_GroupDlg::init (SMESH::SMESH_Mesh_ptr theMesh)
   if( !aList.IsEmpty() )
   {
     QString aName = aList.First()->getName();
-    myMeshGroupLine->setText(aName);
+    myMeshGroupLine->setText(aName);//??????
     myMeshGroupLine->home( false );
   }
 
@@ -593,14 +595,14 @@ void SMESHGUI_GroupDlg::init (SMESH::SMESH_GroupBase_ptr theGroup,
 
   myNameChanged = true;
   myName->blockSignals(true);
-  myName->setText(theGroup->GetName());
+  myName->setText(QString::fromUtf8(theGroup->GetName()));
   myName->blockSignals(false);
   myName->home(false);
 
   SALOMEDS::Color aColor = theGroup->GetColor();
   setGroupColor( aColor );
 
-  myMeshGroupLine->setText(theGroup->GetName());
+  myMeshGroupLine->setText(QString::fromUtf8(theGroup->GetName()));
 
   int aType = 0;
   switch(theGroup->GetType()) {
@@ -685,7 +687,7 @@ void SMESHGUI_GroupDlg::init (SMESH::SMESH_GroupBase_ptr theGroup,
   {
     myNameChanged = true;
     myName->blockSignals(true);
-    myName->setText(theGroup->GetName());
+    myName->setText(QString::fromUtf8(theGroup->GetName()));
     myName->blockSignals(false);
   }
 
@@ -923,6 +925,8 @@ bool SMESHGUI_GroupDlg::onApply()
   SMESH::SMESH_GroupBase_var resultGroup;
   bool isCreation, isConversion = false;
     
+  SUIT_OverrideCursor wc;
+
   if (myGrpTypeId == 0)  // standalone
   {
     if (!mySelectAll->isChecked() && !myElements->count() && myAllowElemsModif->isChecked())
@@ -1038,7 +1042,7 @@ bool SMESHGUI_GroupDlg::onApply()
 
       if (myGeomObjects->length() == 1) {
         myGroupOnGeom = myMesh->CreateGroupFromGEOM(aType,
-                                                    myName->text().toLatin1().data(),
+                                                    myName->text().toUtf8().data(),
                                                     myGeomObjects[0]);
       }
       else {
@@ -1080,11 +1084,11 @@ bool SMESHGUI_GroupDlg::onApply()
           aNewGeomGroupName += myName->text();
           SALOMEDS::SObject_var aNewGroupSO =
             geomGen->AddInStudy(aSMESHGen->GetCurrentStudy(), aGroupVar,
-                                aNewGeomGroupName.toLatin1().data(), aMeshShape);
+                                aNewGeomGroupName.toUtf8().data(), aMeshShape);
         }
 
         myGroupOnGeom = myMesh->CreateGroupFromGEOM(aType,
-                                                    myName->text().toLatin1().data(),
+                                                    myName->text().toUtf8().data(),
                                                     aGroupVar);
       }
       resultGroup = SMESH::SMESH_GroupBase::_narrow( myGroupOnGeom );
@@ -1107,7 +1111,7 @@ bool SMESHGUI_GroupDlg::onApply()
         return false;
 
       myGroupOnFilter = myMesh->CreateGroupFromFilter(aType,
-                                                      myName->text().toLatin1().data(),
+                                                      myName->text().toUtf8().data(),
                                                       myFilter);
 
       resultGroup = SMESH::SMESH_GroupBase::_narrow( myGroupOnFilter );
@@ -1148,13 +1152,14 @@ bool SMESHGUI_GroupDlg::onApply()
     }
     else
     {
-      resultGroup->SetName(myName->text().toLatin1().data());
+      resultGroup->SetName(myName->text().toUtf8().data());
 
       if ( aMeshGroupSO )
       {
-        if(SMESH_Actor *anActor = SMESH::FindActorByEntry(aMeshGroupSO->GetID().c_str())) {
+        if ( SMESH_Actor *anActor = SMESH::FindActorByEntry(aMeshGroupSO->GetID().c_str()))
+        {
+          Handle(SALOME_InteractiveObject) anIO = anActor->getIO();
           if ( isConversion ) { // need to reset TVisualObj and actor
-            Handle(SALOME_InteractiveObject) anIO = anActor->getIO();
             SMESH::RemoveVisualObjectWithActors( anIO->getEntry(), true );
             SMESH::Update( anIO,true);
             myActorsList.clear();
@@ -1162,7 +1167,7 @@ bool SMESHGUI_GroupDlg::onApply()
             if ( !anActor ) return false;
             myActorsList.append( anActor );
           }
-          anActor->setName(myName->text().toLatin1().data());
+          anActor->setName(myName->text().toUtf8().data());
           QColor c;
           int delta;
           switch ( myTypeId ) {
@@ -1180,12 +1185,14 @@ bool SMESHGUI_GroupDlg::onApply()
             anActor->SetSufaceColor( aColor.R, aColor.G, aColor.B, delta ); break;          
             break;
           }
+          // update a visible group accoding to a changed contents
+          if ( !isConversion && anActor->GetVisibility() )
+            SMESH::Update( anIO, true );
         }
       }
     }
     SMESHGUI::Modified();
     mySMESHGUI->updateObjBrowser(true);
-    SMESH::UpdateView(); // asv: fix of BUG PAL5515
     mySelectionMgr->clearSelected();
 
     if( LightApp_Application* anApp =
@@ -1642,7 +1649,7 @@ void SMESHGUI_GroupDlg::onSelectGroup(bool on)
 
 //=================================================================================
 // function : (onSelectGeomGroup)
-// purpose  : Called when group type changed. on == "on group" or "on filter"
+// purpose  : Called when group type changed. on == "on geometry" or "on filter"
 //=================================================================================
 void SMESHGUI_GroupDlg::onSelectGeomGroup(bool on)
 {
@@ -1653,7 +1660,7 @@ void SMESHGUI_GroupDlg::onSelectGeomGroup(bool on)
     else if (mySelectGroup->isChecked()) {
       mySelectGroup->setChecked(false);
     }
-    if ( myGrpTypeId == 1 ) { // on group
+    if ( myGrpTypeId == 1 ) { // on geometry
       myCurrentLineEdit = myGeomGroupLine;
       updateGeomPopup();
     }
@@ -1741,10 +1748,14 @@ void SMESHGUI_GroupDlg::setFilters()
     myFilterDlg->Init( aType );
   }
 
+  bool isStandalone = ( sender() == myFilterBtn );
+  myFilterDlg->SetEnabled( /*setInViewer=*/isStandalone,
+                           /*diffSources=*/isStandalone );
   myFilterDlg->SetMesh( myMesh );
   myFilterDlg->SetSelection();
   myFilterDlg->SetSourceWg( myElements, false );
 
+
   myFilterDlg->show();
 }
 
index 2584d2b4f9929c30365d769045be7c894d55c2d4..ec8fa4ad8d02be3b981d23080475307079650a89 100644 (file)
@@ -42,7 +42,7 @@ namespace SMESH
     SMESH::SMESH_Group_var aGroup;
     try {
       if ( !theMesh->_is_nil() )
-        aGroup = theMesh->CreateGroup( theType, theGroupName.toLatin1().data() );
+        aGroup = theMesh->CreateGroup( theType, theGroupName.toUtf8().data() );
     }
     catch( const SALOME::SALOME_Exception& S_ex ) {
       SalomeApp_Tools::QtCatchCorbaException( S_ex );
index 878163738503d7c11750c49d8a28003c3fb89311..836c2e3609f2fe2b0a8b0dc9c2f516a54216239f 100644 (file)
@@ -91,21 +91,25 @@ namespace SMESH
 
   QList<HypothesesSet*> myListOfHypothesesSets;
 
-  void processHypothesisStatus(const int theHypStatus,
+  void processHypothesisStatus(const int                   theHypStatus,
                                SMESH::SMESH_Hypothesis_ptr theHyp,
-                               const bool theIsAddition)
+                               const bool                  theIsAddition,
+                               const char*                 theError = 0)
   {
     if (theHypStatus > SMESH::HYP_OK) {
       // get Hyp name
       QString aHypName ("NULL Hypothesis");
       if (!CORBA::is_nil(theHyp)) {
         _PTR(SObject) Shyp = SMESH::FindSObject(theHyp);
-        if (Shyp)
+        if (Shyp) {
           // name in study
           aHypName = Shyp->GetName().c_str();
-        else
+        }
+        else {
           // label in xml file
-          aHypName = GetHypothesisData(theHyp->GetName())->Label;
+          CORBA::String_var hypType = theHyp->GetName();
+          aHypName = GetHypothesisData( hypType.in() )->Label;
+        }
       }
 
       // message
@@ -116,12 +120,22 @@ namespace SMESH
       else
         aMsg = (isFatal ? "SMESH_CANT_RM_HYP"  : "SMESH_RM_HYP_WRN");
 
-      aMsg = QObject::tr(aMsg.toLatin1().data()).arg(aHypName) +
-        QObject::tr(QString("SMESH_HYP_%1").arg(theHypStatus).toLatin1().data());
+      aMsg = QObject::tr(aMsg.toLatin1().data()).arg(aHypName);
 
-      if ( theHypStatus == SMESH::HYP_HIDDEN_ALGO ) // PAL18501
-        aMsg = aMsg.arg( GetHypothesisData(theHyp->GetName())->Dim[0] );
+      if ( theError && theError[0] )
+      {
+        aMsg += theError;
+      }
+      else
+      {
+        aMsg += QObject::tr(QString("SMESH_HYP_%1").arg(theHypStatus).toLatin1().data());
 
+        if ( theHypStatus == SMESH::HYP_HIDDEN_ALGO ) { // PAL18501
+          CORBA::String_var hypType = theHyp->GetName();
+          if ( HypothesisData* hd = GetHypothesisData( hypType.in() ))
+            aMsg = aMsg.arg( hd->Dim[0] );
+        }
+      }
       SUIT_MessageBox::warning(SMESHGUI::desktop(),
                                QObject::tr("SMESH_WRN_WARNING"),
                                aMsg);
@@ -520,7 +534,8 @@ namespace SMESH
       _PTR(SObject) SM = SMESH::FindSObject(aMesh);
       GEOM::GEOM_Object_var aShapeObject = SMESH::GetShapeOnMeshOrSubMesh(SM);
       try {
-        res = aMesh->AddHypothesis(aShapeObject, aHyp);
+        CORBA::String_var error;
+        res = aMesh->AddHypothesis(aShapeObject, aHyp, error.out());
         if (res < SMESH::HYP_UNKNOWN_FATAL) {
           _PTR(SObject) aSH = SMESH::FindSObject(aHyp);
           if (SM && aSH) {
@@ -529,7 +544,7 @@ namespace SMESH
         }
         if (res > SMESH::HYP_OK) {
           wc.suspend();
-          processHypothesisStatus(res, aHyp, true);
+          processHypothesisStatus(res, aHyp, true, error.in() );
           wc.resume();
         }
       }
@@ -554,8 +569,10 @@ namespace SMESH
         SMESH::SMESH_Mesh_var aMesh = aSubMesh->GetFather();
         _PTR(SObject) SsubM = SMESH::FindSObject(aSubMesh);
         GEOM::GEOM_Object_var aShapeObject = SMESH::GetShapeOnMeshOrSubMesh(SsubM);
-        if (!aMesh->_is_nil() && SsubM && !aShapeObject->_is_nil()) {
-          res = aMesh->AddHypothesis(aShapeObject, aHyp);
+        if (!aMesh->_is_nil() && SsubM && !aShapeObject->_is_nil())
+        {
+          CORBA::String_var error;
+          res = aMesh->AddHypothesis( aShapeObject, aHyp, error.out() );
           if (res < SMESH::HYP_UNKNOWN_FATAL)  {
             _PTR(SObject) meshSO = SMESH::FindSObject(aMesh);
             if (meshSO)
@@ -563,7 +580,7 @@ namespace SMESH
           }
           if (res > SMESH::HYP_OK) {
             wc.suspend();
-            processHypothesisStatus(res, aHyp, true);
+            processHypothesisStatus( res, aHyp, true, error.in() );
             wc.resume();
           }
         }
index 6826732050f8621914adbfc85900e1eff8278548..f3a2719d41cfbbcb6e44b4b8f11b9ffb1f95a682 100644 (file)
 #include <SUIT_ResourceMgr.h>
 
 // Qt includes
-#include <QVBoxLayout>
+#include <QComboBox>
+#include <QCursor>
 #include <QGridLayout>
-#include <QLabel>
-#include <QTabWidget>
 #include <QGroupBox>
-#include <QToolButton>
-#include <QComboBox>
+#include <QLabel>
+#include <QListWidget>
 #include <QMenu>
-#include <QCursor>
 #include <QPushButton>
+#include <QTabWidget>
+#include <QToolButton>
+#include <QVBoxLayout>
+
+#include <Standard_Integer.hxx>
 
 #define SPACING 6
 #define MARGIN  11
@@ -65,62 +68,81 @@ SMESHGUI_MeshTab::SMESHGUI_MeshTab( QWidget* theParent )
   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
   QIcon aCreateIcon( aResMgr->loadPixmap( "SMESH", tr( "ICON_HYPO" ) ) );
   QIcon aEditIcon( aResMgr->loadPixmap( "SMESH", tr( "ICON_HYPO_EDIT" ) ) );
+  QIcon aPlusIcon( aResMgr->loadPixmap( "SMESH", tr( "ICON_PLUS" ) ) );
+  QIcon aMinusIcon( aResMgr->loadPixmap( "SMESH", tr( "ICON_MINUS" ) ) );
   
   // Algorifm
   QLabel* anAlgoLbl = new QLabel( tr( "ALGORITHM" ), this );
-  myHyp[ Algo ] = new QComboBox( this );
+  myHypCombo[ Algo ] = new QComboBox( this );
   
   // Hypothesis
   QLabel* aHypLbl = new QLabel( tr( "HYPOTHESIS" ), this );
-  myHyp[ MainHyp ] = new QComboBox( this );
-  myHyp[ MainHyp ]->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
-  myCreateHyp[ MainHyp ] = new QToolButton( this );
-  myCreateHyp[ MainHyp ]->setIcon( aCreateIcon );
-  myEditHyp[ MainHyp ] = new QToolButton( this );
-  myEditHyp[ MainHyp ]->setIcon( aEditIcon );
-  
+  myHypCombo[ MainHyp ] = new QComboBox( this );
+  myHypCombo[ MainHyp ]->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
+  myCreateHypBtn[ MainHyp ] = new QToolButton( this );
+  myCreateHypBtn[ MainHyp ]->setIcon( aCreateIcon );
+  myEditHypBtn[ MainHyp ] = new QToolButton( this );
+  myEditHypBtn[ MainHyp ]->setIcon( aEditIcon );
+
   // Line
   QFrame* aLine = new QFrame( this );
   aLine->setFrameStyle( QFrame::HLine | QFrame::Sunken );
-  
+
   // Add. hypothesis
   QLabel* anAddHypLbl = new QLabel( tr( "ADD_HYPOTHESIS" ), this );
-  myHyp[ AddHyp ] = new QComboBox( this );
-  myHyp[ AddHyp ]->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
-  myCreateHyp[ AddHyp ] = new QToolButton( this );
-  myCreateHyp[ AddHyp ]->setIcon( aCreateIcon );
-  myEditHyp[ AddHyp ] = new QToolButton( this );
-  myEditHyp[ AddHyp ]->setIcon( aEditIcon );
-  
+  myHypCombo[ AddHyp ] = new QComboBox( this );
+  myHypCombo[ AddHyp ]->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
+  myCreateHypBtn[ AddHyp ] = new QToolButton( this );
+  myCreateHypBtn[ AddHyp ]->setIcon( aCreateIcon );
+  myEditHypBtn[ AddHyp ] = new QToolButton( this );
+  myEditHypBtn[ AddHyp ]->setIcon( aEditIcon );
+  myEditHypBtn[ MoreAddHyp ] = new QToolButton( this );
+  myEditHypBtn[ MoreAddHyp ]->setIcon( aEditIcon );
+
+  myAddHypList = new QListWidget( this );
+  myMoreAddHypBtn = new QToolButton( this );
+  myMoreAddHypBtn->setIcon( aPlusIcon );
+  myLessAddHypBtn = new QToolButton( this );
+  myLessAddHypBtn->setIcon( aMinusIcon );
+
   // Fill layout
   QGridLayout* aLay = new QGridLayout( this );
   aLay->setMargin( MARGIN );
   aLay->setSpacing( SPACING );
 
   aLay->addWidget( anAlgoLbl, 0, 0 );
-  aLay->addWidget( myHyp[ Algo ], 0, 1 );
+  aLay->addWidget( myHypCombo[ Algo ], 0, 1 );
   aLay->addWidget( aHypLbl, 1, 0 );
-  aLay->addWidget( myHyp[ MainHyp ], 1, 1 );
-  aLay->addWidget( myCreateHyp[ MainHyp ], 1, 2 );
-  aLay->addWidget( myEditHyp[ MainHyp ], 1, 3 );
+  aLay->addWidget( myHypCombo[ MainHyp ], 1, 1 );
+  aLay->addWidget( myCreateHypBtn[ MainHyp ], 1, 2 );
+  aLay->addWidget( myEditHypBtn[ MainHyp ], 1, 3 );
   aLay->addWidget( aLine, 2, 0, 1, 4 );
   aLay->addWidget( anAddHypLbl, 3, 0 );
-  aLay->addWidget( myHyp[ AddHyp ], 3, 1 );
-  aLay->addWidget( myCreateHyp[ AddHyp ], 3, 2 );
-  aLay->addWidget( myEditHyp[ AddHyp ], 3, 3 );
-  aLay->addItem( new QSpacerItem( 0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding ), 4, 0 );
-    
+  aLay->addWidget( myHypCombo[ AddHyp ], 3, 1 );
+  aLay->addWidget( myCreateHypBtn[ AddHyp ], 3, 2 );
+  aLay->addWidget( myEditHypBtn[ AddHyp ], 3, 3 );
+  aLay->addWidget( myAddHypList, 4, 1, 2, 1 );
+  aLay->addWidget( myMoreAddHypBtn, 4, 2 );
+  aLay->addWidget( myEditHypBtn[ MoreAddHyp ], 4, 3 );
+  aLay->addWidget( myLessAddHypBtn, 5, 2 );
+  aLay->addItem( new QSpacerItem( 0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding ), 6, 0 );
+
   // Connect signals and slots
   for ( int i = MainHyp; i <= AddHyp; i++ )
   {
-    connect( myCreateHyp[ i ], SIGNAL( clicked() )       ,  SLOT( onCreateHyp() ) );
-    connect( myEditHyp[ i ]  , SIGNAL( clicked() )       ,  SLOT( onEditHyp() ) );
-    connect( myHyp[ i ]      , SIGNAL( activated( int ) ),  SLOT( onHyp( int ) ) );
+    connect( myCreateHypBtn[ i ], SIGNAL( clicked() )       ,  SLOT( onCreateHyp() ) );
+    connect( myEditHypBtn[ i ]  , SIGNAL( clicked() )       ,  SLOT( onEditHyp() ) );
+    connect( myHypCombo[ i ]    , SIGNAL( activated( int ) ),  SLOT( onHyp( int ) ) );
   }
-  connect( myHyp[ Algo ], SIGNAL( activated( int ) ), SLOT( onHyp( int ) ) );
-  
+  connect( myHypCombo[ Algo ], SIGNAL( activated( int ) ), SLOT( onHyp( int ) ) );
+
+  connect( myAddHypList, SIGNAL( currentRowChanged( int ) ), SLOT( onHyp( int ) ) );
+  connect( myEditHypBtn[ MoreAddHyp ], SIGNAL( clicked() ), SLOT( onEditHyp() ) );
+  connect( myMoreAddHypBtn, SIGNAL( clicked() ), SLOT( onMoreAddHyp() ));
+  connect( myLessAddHypBtn, SIGNAL( clicked() ), SLOT( onLessAddHyp() ));
+
   // Initialize controls
-  
+
   setAvailableHyps( Algo, QStringList() );
   setAvailableHyps( MainHyp, QStringList() );
   setAvailableHyps( AddHyp, QStringList() );
@@ -135,6 +157,49 @@ SMESHGUI_MeshTab::~SMESHGUI_MeshTab()
 {
 }
 
+//================================================================================
+/*!
+ * \brief Adds an item in a control corresponding to \a type
+ *  \param [in] txt - item text
+ *  \param [in] type - HypType
+ *  \param [in] index - index of item in a list of items
+ */
+//================================================================================
+
+void SMESHGUI_MeshTab::addItem( const QString& txt, const int type, const int index )
+{
+  if ( type <= AddHyp )
+  {
+    myHypCombo[ type ]->addItem( txt, QVariant( index ));
+  }
+  else
+  {
+    QListWidgetItem* item = new QListWidgetItem( txt, myAddHypList );
+    item->setData( Qt::UserRole, QVariant( index ));
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Returns index of hyp of a given type
+ */
+//================================================================================
+
+int SMESHGUI_MeshTab::getCurrentIndex( const int type, const bool curByType ) const
+{
+  if ( type <= AddHyp )
+  {
+    return myHypCombo[ type ]->itemData( myHypCombo[ type ]->currentIndex() ).toInt();
+  }
+  else
+  {
+    int row = curByType ? ( type - AddHyp - 1 ) : myAddHypList->currentRow();
+    if ( QListWidgetItem* item = myAddHypList->item( row ))
+      return item->data( Qt::UserRole ).toInt();
+  }
+  return -1;
+}
+
 //================================================================================
 /*!
  * \brief Sets available hypothesis or algorithms
@@ -146,25 +211,26 @@ SMESHGUI_MeshTab::~SMESHGUI_MeshTab()
 //================================================================================
 void SMESHGUI_MeshTab::setAvailableHyps( const int theId, const QStringList& theHyps )
 {
-  myAvailableHyps[ theId ] = theHyps;
+  myAvailableHypTypes[ theId ] = theHyps;
 
   bool enable = ! theHyps.isEmpty();
   if ( theId == Algo ) // fill list of algos
   {
-    myHyp[ Algo ]->clear();
+    myHypCombo[ Algo ]->clear();
     if ( enable )
     {
-      myHyp[ Algo ]->addItem( tr( "NONE" ) );
-      myHyp[ Algo ]->addItems( theHyps );
-      myHyp[ Algo ]->setCurrentIndex( 0 );
+      addItem( tr( "NONE"), Algo, 0 );
+      for ( int i = 0, nbHyp = theHyps.count(); i < nbHyp; ++i )
+        addItem( theHyps[i], Algo, i+1 );
+      myHypCombo[ Algo ]->setCurrentIndex( 0 );
     }
   }
   else // enable buttons
   {
-    myCreateHyp[ theId ]->setEnabled( enable );
-    myEditHyp  [ theId ]->setEnabled( false );
+    myCreateHypBtn[ theId ]->setEnabled( enable );
+    myEditHypBtn  [ theId ]->setEnabled( false );
   }
-  myHyp[ theId ]->setEnabled( enable );
+  myHypCombo[ theId ]->setEnabled( enable );
 }
 
 //================================================================================
@@ -172,7 +238,7 @@ void SMESHGUI_MeshTab::setAvailableHyps( const int theId, const QStringList& the
  * \brief Sets existing hypothesis
  * \param theId - identifier of hypothesis (main or additional, see HypType enumeration)
  * \param theHyps - list of available hypothesis names
- * \param theDefaultAvlbl - \c true means that the algorithm can with w/o hypothesis
+ * \param theDefaultAvlbl - \c true means that the algorithm can work w/o hypothesis
  *                          with some default parameters
  *
  * Sets existing main or additional hypothesis for this tab
@@ -184,17 +250,25 @@ void SMESHGUI_MeshTab::setExistingHyps( const int          theId,
 {
   if ( theId != Algo )
   {
-    bool enable = ! myAvailableHyps[ theId ].isEmpty();
-    myHyp[ theId ]->clear();
+    bool enable = ! myAvailableHypTypes[ theId ].isEmpty();
+    myHypCombo[ theId ]->clear();
     if ( enable )
     {
       QString none = tr( theDefaultAvlbl ? "DEFAULT" : ( theId == AddHyp ) ? "NONE" : "NONE" );
-      myHyp[ theId ]->addItem( none );
-      myHyp[ theId ]->addItems( theHyps );
-      myHyp[ theId ]->setCurrentIndex( 0 );
+      addItem( none, theId, 0 );
+      for ( int i = 0, nbHyp = theHyps.count(); i < nbHyp; ++i )
+        addItem( theHyps[i], theId, i+1 );
+      myHypCombo[ theId ]->setCurrentIndex( 0 );
+    }
+    myHypCombo  [ theId ]->setEnabled( enable );
+    myEditHypBtn[ theId ]->setEnabled( false );
+    if ( theId == AddHyp )
+    {
+      myAddHypList->clear();
+      myEditHypBtn[ MoreAddHyp ]->setEnabled( false );
+      myMoreAddHypBtn->setEnabled( false );
+      myLessAddHypBtn->setEnabled( false );
     }
-    myHyp    [ theId ]->setEnabled( enable );
-    myEditHyp[ theId ]->setEnabled( false );
   }
 }
 
@@ -210,46 +284,70 @@ void SMESHGUI_MeshTab::setExistingHyps( const int          theId,
 //================================================================================
 void SMESHGUI_MeshTab::addHyp( const int theId, const QString& theHyp )
 {
-  myHyp[ theId ]->addItem( theHyp );
-  myHyp[ theId ]->setCurrentIndex( myHyp[ theId ]->count() - 1 );
-  myEditHyp[ theId ]->setEnabled( true );
-  myHyp[ theId ]->setEnabled( true );
+  int index = myHypCombo[ theId ]->count();
+  if ( theId == AddHyp )
+    index += myAddHypList->count();
+  addItem( theHyp, theId, index );
+  myHypCombo[ theId ]->setCurrentIndex( myHypCombo[ theId ]->count() - 1 );
+  myEditHypBtn[ theId ]->setEnabled( true );
+  myHypCombo[ theId ]->setEnabled( true );
+  if ( theId == AddHyp )
+    myMoreAddHypBtn->setEnabled( true );
 }
 
 //================================================================================
 /*!
  * \brief Renames hypothesis
 * \param theId - identifier of hypothesis (main or additional, see HypType enumeration)
 * \param theIndex - index of hypothesis to be renamed
 * \param theNewName - new name of hypothesis to be renamed
- * 
+ * \param theId - identifier of hypothesis (main or additional, see HypType enumeration)
+ * \param theIndex - index of hypothesis to be renamed
+ * \param theNewName - new name of hypothesis to be renamed
+ *
  * Renames hypothesis
  */
 //================================================================================
-void SMESHGUI_MeshTab::renameHyp( const int theId, 
-                                  const int theIndex, 
-                                  const QString& theNewName )
-{
-  if ( theIndex > 0 && theIndex < myHyp[ theId ]->count() )
-    myHyp[ theId ]->setItemText( theIndex, theNewName );
-}                                  
+// void SMESHGUI_MeshTab::renameHyp( const int theId,
+//                                   const int theIndex,
+//                                   const QString& theNewName )
+// {
+//   if ( theIndex > 0 && theIndex < myHypCombo[ theId ]->count() )
+//     myHypCombo[ theId ]->setItemText( theIndex, theNewName );
+// }
 
 //================================================================================
 /*!
- * \brief Sets current hypothesis 
 * \param theId - identifier of hypothesis (main or additional, see HypType enumeration)
 * \param theIndex - index of hypothesis to be set as current
- * 
- * Sets current hypothesis 
+ * \brief Sets current hypothesis
+ * \param theId - identifier of hypothesis (main or additional, see HypType enumeration)
+ * \param theIndex - index of hypothesis to be set as current
+ *
+ * Sets current hypothesis
  */
 //================================================================================
 void SMESHGUI_MeshTab::setCurrentHyp( const int theId, const int theIndex )
 {
-  if ( theIndex >= 0 && theIndex < myHyp[ theId ]->count() )
+  if ( theId <= AddHyp )
   {
-    myHyp[ theId ]->setCurrentIndex( theIndex );
-    if ( myEditHyp[ theId ] )
-      myEditHyp[ theId ]->setEnabled( theIndex > 0 );
+    if ( theIndex >= 0 && theIndex < myHypCombo[ theId ]->count() )
+    {
+      myHypCombo[ theId ]->setCurrentIndex( theIndex );
+      if ( myEditHypBtn[ theId ] )
+        myEditHypBtn[ theId ]->setEnabled( theIndex > 0 );
+      if ( theId == AddHyp )
+        myMoreAddHypBtn      ->setEnabled( theIndex > 0 );
+    }
+  }
+  else // more than one additional hyp assigned
+  {
+    // move a hyp from myHypCombo[ AddHyp ] to myAddHypList
+    for ( int i = 1, nb = myHypCombo[ AddHyp ]->count(); i < nb; ++i )
+    {
+      int curIndex = myHypCombo[ AddHyp ]->itemData( i ).toInt();
+      if ( theIndex == curIndex )
+      {
+        addItem( myHypCombo[ AddHyp ]->itemText( i ), theId, theIndex );
+        myHypCombo[ AddHyp ]->removeItem( i );
+        break;
+      }
+    }
   }
 }
 
@@ -260,11 +358,26 @@ void SMESHGUI_MeshTab::setCurrentHyp( const int theId, const int theIndex )
   * \retval int - index of current hypothesis
  * 
  * Gets current hypothesis
+ * Use theId > AddHyp to get more than selected addetional hyps (see nbAddHypTypes()).
  */
 //================================================================================
 int SMESHGUI_MeshTab::currentHyp( const int theId ) const
 {
-  return myHyp[ theId ]->currentIndex();
+  return getCurrentIndex( theId, /*curByType=*/true );
+}
+
+//================================================================================
+/*!
+ * \brief Returns nb of selected supplementary additional hypotheses
+ * 
+ * Access to their indices is via currentHyp( AddHyp + i ) where i is within the
+ * range 0 <= i < this->nbAddHypTypes()
+ */
+//================================================================================
+
+int SMESHGUI_MeshTab::nbAddHypTypes() const
+{
+  return myAddHypList->count();
 }
 
 //================================================================================
@@ -277,12 +390,12 @@ int SMESHGUI_MeshTab::currentHyp( const int theId ) const
 //================================================================================
 void SMESHGUI_MeshTab::onCreateHyp()
 {
-  bool isMainHyp = sender() == myCreateHyp[ MainHyp ];
+  bool isMainHyp = ( sender() == myCreateHypBtn[ MainHyp ]);
 
   QMenu aPopup( this );
   
   QStringList aHypNames = isMainHyp ? 
-    myAvailableHyps[ MainHyp ] : myAvailableHyps[ AddHyp ];
+    myAvailableHypTypes[ MainHyp ] : myAvailableHypTypes[ AddHyp ];
 
   QList<QAction*> actions;
   for ( int i = 0, n = aHypNames.count(); i < n; i++ )
@@ -304,8 +417,12 @@ void SMESHGUI_MeshTab::onCreateHyp()
 void SMESHGUI_MeshTab::onEditHyp()
 {
   const QObject* aSender = sender();
-  int aHypType = aSender == myEditHyp[ MainHyp ] ? MainHyp : AddHyp;
-  emit editHyp( aHypType, myHyp[ aHypType ]->currentIndex() - 1 );  // - 1 because there is NONE on the top
+  int aHypType = MainHyp;
+  for ( ; aHypType <= MoreAddHyp; ++aHypType )
+    if ( aSender == myEditHypBtn[ aHypType ])
+      break;
+  emit editHyp( Min( aHypType, AddHyp ),
+                getCurrentIndex( aHypType ) - 1 );  // - 1 because there is NONE on the top
 }
 
 //================================================================================
@@ -320,11 +437,66 @@ void SMESHGUI_MeshTab::onEditHyp()
 void SMESHGUI_MeshTab::onHyp( int theIndex )
 {
   const QObject* aSender = sender();
-  if ( aSender == myHyp[ Algo ] )
+  if ( aSender == myHypCombo[ Algo ] )
+  {
     emit selectAlgo( theIndex - 1 ); // - 1 because there is NONE on the top
-  else {
-    int anIndex = aSender == myHyp[ MainHyp ] ? MainHyp : AddHyp;
-    myEditHyp[ anIndex ]->setEnabled( theIndex > 0 );
+  }
+  else if ( aSender == myAddHypList )
+  {
+    myEditHypBtn[ MoreAddHyp ]->setEnabled( theIndex >= 0 );
+    myLessAddHypBtn           ->setEnabled( theIndex >= 0 );
+  }
+  else
+  {
+    int type = ( aSender == myHypCombo[ MainHyp ] ? MainHyp : AddHyp );
+    myEditHypBtn[ type ]->setEnabled( theIndex > 0 );
+
+    if ( type == AddHyp )
+      myMoreAddHypBtn   ->setEnabled( theIndex > 0 );
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Adds a current additional hyp to myAddHypList
+ * 
+ * SLOT called when myMoreAddHypBtn ("plus") clicked
+ */
+//================================================================================
+
+void SMESHGUI_MeshTab::onMoreAddHyp()
+{
+  int hypIndex = currentHyp( AddHyp );
+  if ( hypIndex > 0 )
+  {
+    // move a hyp from myHypCombo[ AddHyp ] to myAddHypList
+    int comboIndex = myHypCombo[ AddHyp ]->currentIndex();
+    addItem( myHypCombo[ AddHyp ]->itemText( comboIndex ), MoreAddHyp, hypIndex );
+
+    myHypCombo[ AddHyp ]->removeItem( comboIndex );
+    myHypCombo[ AddHyp ]->setCurrentIndex( 0 );
+
+    myMoreAddHypBtn->setEnabled( false );
+    myEditHypBtn[ AddHyp ]->setEnabled( false );
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Removes a current additional hyp from myAddHypList
+ * 
+ * SLOT called when myLessAddHypBtn ("minus") clicked
+ */
+//================================================================================
+
+void SMESHGUI_MeshTab::onLessAddHyp()
+{
+  if ( QListWidgetItem * item = myAddHypList->currentItem() )
+  {
+    // move a hyp from myAddHypList to myHypCombo[ AddHyp ]
+    int hypIndex = item->data( Qt::UserRole ).toInt();
+    addItem( item->text(), AddHyp, hypIndex );
+    delete item;//myAddHypList->takeItem( myAddHypList->currentRow() );
   }
 }
 
@@ -334,14 +506,14 @@ void SMESHGUI_MeshTab::onHyp( int theIndex )
  *
  * Resets all tab fields
  */
-//================================================================================  
+//================================================================================
 void SMESHGUI_MeshTab::reset()
 {
   for ( int i = Algo; i <= AddHyp; i++ )
   {
-    myHyp[ i ]->setCurrentIndex( 0 );
-    if ( myEditHyp[ i ] )
-      myEditHyp[ i ]->setEnabled( false );
+    myHypCombo[ i ]->setCurrentIndex( 0 );
+    if ( myEditHypBtn[ i ] )
+      myEditHypBtn[ i ]->setEnabled( false );
   }
 }
 
index 2d0cdde7459bae9bf21f6e3759b457712977f4cb..f8d8b108e1d7db746ade6e4717979c321953389d 100644 (file)
 #include <QMap>
 
 class SMESHGUI_MeshTab;
-class QTabWidget;
+class QAction;
 class QComboBox;
-class QToolButton;
+class QListWidget;
 class QMenu;
-class QAction;
+class QTabWidget;
+class QToolButton;
 
 /*!
  * \brief Dialog for mech creation or editing
@@ -89,7 +90,7 @@ private slots:
   void                         onGeomSelectionButton( bool );
   void                         onChangedMeshType( const int );
 
-private:
+ private:
   QMap<int, SMESHGUI_MeshTab*> myTabs;
   QTabWidget*                  myTabWg;
   QToolButton*                 myHypoSetButton;
@@ -98,23 +99,26 @@ private:
 };
 
 /*!
- * \brief Tab for tab widget containing controls for definition of 
+ * \brief Tab for tab widget containing controls for definition of
  * algorithms and hypotheses
-*/ 
+ */
 
 class SMESHGUI_EXPORT SMESHGUI_MeshTab : public QFrame
 {
   Q_OBJECT
-      
-public:      
+
+    public:
   /*! To differ main algorithms, hypotheses and additional ones*/
   enum HypType
-  { 
+  {
     Algo = 0, //!< algorithms
     MainHyp,  //!< main hypothesis
-    AddHyp    //!< additional hypothesis
-  };            
-      
+    AddHyp,    //!< additional hypothesis
+    MoreAddHyp //! since several additional hypothesis are possible, the 2-nd, 3-d etc
+    // additional hypotheses are coded as being of HypType (AddHyp + 1), (AddHyp + 2) etc.
+    // Nb of HypType's after MainHyp is returned by SMESHGUI_MeshTab::nbAddHypTypes()
+  };
+
 public:      
   SMESHGUI_MeshTab( QWidget* );
   virtual ~SMESHGUI_MeshTab();
@@ -122,9 +126,10 @@ public:
   void                         setAvailableHyps( const int, const QStringList& );
   void                         setExistingHyps( const int, const QStringList&, bool=false);
   void                         addHyp( const int, const QString& );
-  void                         renameHyp( const int, const int, const QString& );
+  //void                         renameHyp( const int, const int, const QString& );
   void                         setCurrentHyp( const int, const int );
   int                          currentHyp( const int ) const;
+  int                          nbAddHypTypes() const;
   void                         reset();
 
 signals:  
@@ -139,14 +144,24 @@ private slots:
   void                         onCreateHyp();  
   void                         onEditHyp();
   void                         onHyp( int );
-  
-private:  
-  QMap<int, QComboBox*>        myHyp;
-  QMap<int, QToolButton*>      myCreateHyp;
-  QMap<int, QToolButton*>      myEditHyp;
-  
-  QMap<int, QStringList>       myAvailableHyps;
-  QMap<int, QStringList>       myExistingHyps;
+  void                         onMoreAddHyp();
+  void                         onLessAddHyp();
+
+private:
+
+  void                         addItem( const QString& txt, const int type, const int index );
+  int                          getCurrentIndex( const int type, const bool curByType=false) const;
+
+  QMap<int, QStringList>       myAvailableHypTypes;
+
+  QMap<int, QComboBox*>        myHypCombo;
+  QMap<int, QToolButton*>      myCreateHypBtn;
+  QMap<int, QToolButton*>      myEditHypBtn;
+
+  QToolButton*                 myMoreAddHypBtn;
+  QToolButton*                 myLessAddHypBtn;
+  QListWidget*                 myAddHypList; // 2-nd, etc. additional hyps
+
 };
 
 #endif // SMESHGUI_MESHDLG_H
index 10521987a966074700026710e6e62c04366ae7c3..ab8b437a638ddffa68e6aa84c62aeee6b73c6ad4 100644 (file)
@@ -398,7 +398,8 @@ char* SMESHGUI_MeshOp::isSubmeshIgnored() const
       THypList    algoList;
       existingHyps(3, Algo, pMesh, algoNames, algoList);
       if (!algoList.empty()) {
-        HypothesisData* algo = SMESH::GetHypothesisData( algoList[0].first->GetName() );
+        HypothesisData* algo =
+          SMESH::GetHypothesisData( SMESH::toQStr( algoList[0].first->GetName() ));
         if ( algo &&
              algo->InputTypes.empty() && // builds all dimensions it-self
              !algo->IsSupportSubmeshes )
@@ -412,7 +413,8 @@ char* SMESHGUI_MeshOp::isSubmeshIgnored() const
 //       if ( !geom->_is_nil() && geom->GetShapeType() >= GEOM::FACE ) { // WIRE, EDGE as well
         existingHyps(2, Algo, pMesh, algoNames, algoList);
         if (!algoList.empty()) {
-          HypothesisData* algo = SMESH::GetHypothesisData( algoList[0].first->GetName() );
+          HypothesisData* algo =
+            SMESH::GetHypothesisData( SMESH::toQStr( algoList[0].first->GetName() ));
           if ( algo &&
                algo->InputTypes.empty() && // builds all dimensions it-self
                !algo->IsSupportSubmeshes )
@@ -608,8 +610,8 @@ void SMESHGUI_MeshOp::selectionDone()
           myDlg->objectWg( SMESHGUI_MeshDlg::Geom, SMESHGUI_MeshDlg::Btn )->hide();
           myDlg->updateGeometry();
           myDlg->adjustSize();
-          readMesh();
           myIsMesh = submeshVar->_is_nil();
+          readMesh();
         }
         else
           myDlg->reset();
@@ -871,7 +873,11 @@ void SMESHGUI_MeshOp::availableHyps( const int       theDim,
  *  \param theAlgoData - to select hypos able to be used by this algo (optional)
  *
  * Gets existing (i.e. already created) hypotheses or algorithm in accordance with
- * input parameters
+ * input parameters.
+ *
+ * WARNING: when using this method to get hyps existing in Mesh component,
+ *          call availableHyps() before in order to get only hyps of available types
+ *          that was filtered by availableHyps()
  */
 //================================================================================
 void SMESHGUI_MeshOp::existingHyps( const int       theDim,
@@ -879,7 +885,7 @@ void SMESHGUI_MeshOp::existingHyps( const int       theDim,
                                     _PTR(SObject)   theFather,
                                     QStringList&    theHyps,
                                     THypList&       theHypList,
-                                    HypothesisData* theAlgoData)
+                                    HypothesisData* theAlgoData) const
 {
   // Clear hypoheses list
   theHyps.clear();
@@ -888,20 +894,21 @@ void SMESHGUI_MeshOp::existingHyps( const int       theDim,
   if ( !theFather )
     return;
 
-  const bool isAux  = ( theHypType == AddHyp );
-
   _PTR(SObject)          aHypRoot;
   _PTR(GenericAttribute) anAttr;
   _PTR(AttributeName)    aName;
   _PTR(AttributeIOR)     anIOR;
 
-  bool isMesh = !_CAST( SComponent, theFather );
+  const bool isMesh = !_CAST( SComponent, theFather );
   int aPart = -1;
   if ( isMesh )
     aPart = theHypType == Algo ? SMESH::Tag_RefOnAppliedAlgorithms : SMESH::Tag_RefOnAppliedHypothesis;
   else
     aPart = theHypType == Algo ? SMESH::Tag_AlgorithmsRoot : SMESH::Tag_HypothesisRoot;
 
+  const bool isAux   = ( theHypType == AddHyp );
+  const bool allHyps = ( !isMesh && theHypType != Algo && theDim > -1);
+
   if ( theFather->FindSubObject( aPart, aHypRoot ) )
   {
     _PTR(ChildIterator) anIter =
@@ -929,9 +936,10 @@ void SMESHGUI_MeshOp::existingHyps( const int       theDim,
             CORBA::String_var hypType = aHypVar->GetName();
             HypothesisData* aData = SMESH::GetHypothesisData( hypType.in() );
             if ( !aData) continue;
-            if ( ( theDim == -1 || aData->Dim.contains( theDim ) ) &&
-                 ( isCompatible ( theAlgoData, aData, theHypType )) &&
-                 ( theHypType == Algo || isAux == aData->IsAuxOrNeedHyp ))
+            if (( theDim == -1 || aData->Dim.contains( theDim ) ) &&
+                ( isCompatible ( theAlgoData, aData, theHypType )) &&
+                ( theHypType == Algo || isAux == aData->IsAuxOrNeedHyp ) &&
+                ( !allHyps || myAvailableHypData[theDim][theHypType].count(aData) ))
             {
               std::string aHypName = aName->Value();
               theHyps.append( aHypName.c_str() );
@@ -1031,6 +1039,71 @@ SMESHGUI_MeshOp::getInitParamsHypothesis( const QString& aHypType,
   return hyp;
 }
 
+//================================================================================
+/*!
+ * \brief initialize a hypothesis creator
+ */
+//================================================================================
+
+void SMESHGUI_MeshOp::initHypCreator( SMESHGUI_GenericHypothesisCreator* theCreator )
+{
+  if ( !theCreator ) return;
+
+  // Set shapes, of mesh and sub-mesh if any
+
+  // get Entry of the Geom object
+  QString aGeomEntry = "";
+  QString aMeshEntry = "";
+  QString anObjEntry = "";
+  aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
+  aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
+  anObjEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Obj );
+
+  if ( myToCreate && myIsMesh )
+    aMeshEntry = aGeomEntry;
+
+  if ( aMeshEntry != aGeomEntry ) { // Get Geom object from Mesh of a sub-mesh being edited
+    _PTR(SObject) pObj = studyDS()->FindObjectID( aMeshEntry.toLatin1().data() );
+    GEOM::GEOM_Object_var aGeomVar = SMESH::GetShapeOnMeshOrSubMesh( pObj );
+    aMeshEntry = ( aGeomVar->_is_nil() ) ? QString() : SMESH::toQStr( aGeomVar->GetStudyEntry() );
+  }
+
+  if ( aMeshEntry == "" && aGeomEntry == "" ) { // get geom of an object being edited
+    _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.toLatin1().data() );
+    bool isMesh;
+    GEOM::GEOM_Object_var aGeomVar = SMESH::GetShapeOnMeshOrSubMesh( pObj, &isMesh );
+    if ( !aGeomVar->_is_nil() )
+    {
+      aGeomEntry = SMESH::toQStr( aGeomVar->GetStudyEntry() );
+      if ( isMesh )
+        aMeshEntry = aGeomEntry;
+    }
+  }
+
+  if ( anObjEntry != "" && aGeomEntry != "" && aMeshEntry == "" ) {
+    // take geometry from submesh being created
+    _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.toLatin1().data() );
+    if ( pObj ) {
+      // if current object is sub-mesh
+      SMESH::SMESH_subMesh_var aSubMeshVar =
+        SMESH::SMESH_subMesh::_narrow( _CAST( SObject,pObj )->GetObject() );
+      if ( !aSubMeshVar->_is_nil() ) {
+        SMESH::SMESH_Mesh_var aMeshVar =  aSubMeshVar->GetFather();
+        if ( !aMeshVar->_is_nil() ) {
+          _PTR(SObject) aMeshSO = SMESH::FindSObject( aMeshVar );
+          GEOM::GEOM_Object_var aGeomVar = SMESH::GetShapeOnMeshOrSubMesh( aMeshSO );
+          if ( !aGeomVar->_is_nil() )
+            aMeshEntry = SMESH::toQStr( aGeomVar->GetStudyEntry() );
+        }
+      }
+    }
+  }
+
+  theCreator->setShapeEntry( aGeomEntry );
+  if ( aMeshEntry != "" )
+    theCreator->setMainShapeEntry( aMeshEntry );
+}
+
 //================================================================================
 /*!
  * \Brief Returns tab dimention
@@ -1106,6 +1179,8 @@ void SMESHGUI_MeshOp::createHypothesis(const int theDim,
 
   myDim = theDim;
   myType = theType;
+
+  // get a unique hyp name
   QStringList aHypNames;
   TDim2Type2HypList::const_iterator aDimIter = myExistingHyps.begin();
   for ( ; aDimIter != myExistingHyps.end(); aDimIter++) {
@@ -1138,64 +1213,17 @@ void SMESHGUI_MeshOp::createHypothesis(const int theDim,
     SMESHGUI_GenericHypothesisCreator* aCreator = SMESH::GetHypothesisCreator(theTypeName);
 
     // Create hypothesis
-    if (aCreator) {
+    if (aCreator)
+    {
       // Get parameters appropriate to initialize a new hypothesis
       SMESH::SMESH_Hypothesis_var initParamHyp =
         getInitParamsHypothesis(theTypeName, aData->ServerLibName);
 
       removeCustomFilters(); // Issue 0020170
 
-      // Get Entry of the Geom object
-      QString aGeomEntry = "";
-      QString aMeshEntry = "";
-      QString anObjEntry = "";
-      aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
-      aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
-      anObjEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Obj );
-
-      if ( myToCreate && myIsMesh )
-        aMeshEntry = aGeomEntry;
-
-      if ( aMeshEntry != aGeomEntry ) { // Get Geom object from Mesh of a sub-mesh being edited
-        _PTR(SObject) pObj = studyDS()->FindObjectID( aMeshEntry.toLatin1().data() );
-        GEOM::GEOM_Object_var aGeomVar = SMESH::GetShapeOnMeshOrSubMesh( pObj );
-        aMeshEntry = ( aGeomVar->_is_nil() ) ? "" : aMeshEntry = aGeomVar->GetStudyEntry();
-      }
-
-      if ( aMeshEntry == "" && aGeomEntry == "" ) { // get geom of an object being edited
-        _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.toLatin1().data() );
-        bool isMesh;
-        GEOM::GEOM_Object_var aGeomVar = SMESH::GetShapeOnMeshOrSubMesh( pObj, &isMesh );
-        if ( !aGeomVar->_is_nil() )
-        {
-          aGeomEntry = aGeomVar->GetStudyEntry();
-          if ( isMesh )
-            aMeshEntry = aGeomEntry;
-        }
-      }
-
-      if ( anObjEntry != "" && aGeomEntry != "" && aMeshEntry == "" ) {
-        // take geometry from submesh being created
-        _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.toLatin1().data() );
-        if ( pObj ) {
-          // if current object is sub-mesh
-          SMESH::SMESH_subMesh_var aSubMeshVar =
-            SMESH::SMESH_subMesh::_narrow( _CAST( SObject,pObj )->GetObject() );
-          if ( !aSubMeshVar->_is_nil() ) {
-            SMESH::SMESH_Mesh_var aMeshVar =  aSubMeshVar->GetFather();
-            if ( !aMeshVar->_is_nil() ) {
-              _PTR(SObject) aMeshSO = SMESH::FindSObject( aMeshVar );
-              GEOM::GEOM_Object_var aGeomVar = SMESH::GetShapeOnMeshOrSubMesh( aMeshSO );
-              if ( !aGeomVar->_is_nil() )
-                aMeshEntry = aGeomVar->GetStudyEntry();
-            }
-          }
-        }
-      }
+      // set shapes, of mesh and sub-mesh if any
+      initHypCreator( aCreator );
 
-      aCreator->setShapeEntry( aGeomEntry );
-      if ( aMeshEntry != "" )
-        aCreator->setMainShapeEntry( aMeshEntry );
       myDlg->setEnabled( false );
       aCreator->create(initParamHyp, aHypName, myDlg, this, SLOT( onHypoCreated( int ) ) );
       dialog = true;
@@ -1270,67 +1298,22 @@ void SMESHGUI_MeshOp::onEditHyp( const int theHypType, const int theIndex )
   if ( aHyp->_is_nil() )
     return;
 
-  SMESHGUI_GenericHypothesisCreator* aCreator = SMESH::GetHypothesisCreator(aHyp->GetName());
+  SMESHGUI_GenericHypothesisCreator* aCreator =
+    SMESH::GetHypothesisCreator( SMESH::toQStr( aHyp->GetName() ));
   if ( aCreator )
   {
-    // Get initial parameters
+    // set initial parameters
     SMESH::SMESH_Hypothesis_var initParamHyp =
-      getInitParamsHypothesis( aHyp->GetName(), aHyp->GetLibName());
+      getInitParamsHypothesis( SMESH::toQStr( aHyp->GetName() ),
+                               SMESH::toQStr( aHyp->GetLibName() ));
     aCreator->setInitParamsHypothesis( initParamHyp );
 
-    // Get Entry of the Geom object
-    QString aGeomEntry = "";
-    QString aMeshEntry = "";
-    QString anObjEntry = "";
-    aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
-    aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
-    anObjEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Obj );
-
-    if ( myToCreate && myIsMesh )
-      aMeshEntry = aGeomEntry;
+    // set shapes, of mesh and sub-mesh if any
+    initHypCreator( aCreator );
 
-    if ( aMeshEntry != aGeomEntry ) { // Get Geom object from Mesh of a sub-mesh being edited
-      _PTR(SObject) pObj = studyDS()->FindObjectID( aMeshEntry.toLatin1().data() );
-      GEOM::GEOM_Object_var aGeomVar = SMESH::GetShapeOnMeshOrSubMesh( pObj );
-      aMeshEntry = ( aGeomVar->_is_nil() ) ? "" : aMeshEntry = aGeomVar->GetStudyEntry();
-    }
-
-    if ( aMeshEntry == "" && aGeomEntry == "" ) { // get geom of an object being edited
-      _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.toLatin1().data() );
-      bool isMesh;
-      GEOM::GEOM_Object_var aGeomVar = SMESH::GetShapeOnMeshOrSubMesh( pObj, &isMesh );
-      if ( !aGeomVar->_is_nil() )
-      {
-        aGeomEntry = aGeomVar->GetStudyEntry();
-        if ( isMesh )
-          aMeshEntry = aGeomEntry;
-      }
-    }
-
-    if ( anObjEntry != "" && aGeomEntry != "" && aMeshEntry == "" ) {
-      // take geometry from submesh being created
-      _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.toLatin1().data() );
-      if ( pObj ) {
-        // if current object is sub-mesh
-        SMESH::SMESH_subMesh_var aSubMeshVar =
-          SMESH::SMESH_subMesh::_narrow( _CAST( SObject,pObj )->GetObject() );
-        if ( !aSubMeshVar->_is_nil() ) {
-          SMESH::SMESH_Mesh_var aMeshVar =  aSubMeshVar->GetFather();
-          if ( !aMeshVar->_is_nil() ) {
-            _PTR(SObject) aMeshSO = SMESH::FindSObject( aMeshVar );
-            GEOM::GEOM_Object_var aGeomVar = SMESH::GetShapeOnMeshOrSubMesh( aMeshSO );
-            if ( !aGeomVar->_is_nil() )
-              aMeshEntry = aGeomVar->GetStudyEntry();
-          }
-        }
-      }
-    }
-
-    aCreator->setShapeEntry( aGeomEntry );
-    if ( aMeshEntry != "" )
-      aCreator->setMainShapeEntry( aMeshEntry );
     removeCustomFilters(); // Issue 0020170
     myDlg->setEnabled( false );
+
     aCreator->edit( aHyp.in(), aHypItem.second, dlg(), this, SLOT( onHypoEdited( int ) ) );
   }
 }
@@ -1396,7 +1379,6 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
 
   const bool isSubmesh = ( myToCreate ? !myIsMesh : myDlg->isObjectShown( SMESHGUI_MeshDlg::Mesh ));
 
-  // if ( aDim >= SMESH::DIM_2D ) myAvailableHypData[ aDim ][ Algo ] = myFilteredAlgoData[aDim];
   HypothesisData* algoData = hypData( aDim, Algo, theIndex );
   HypothesisData* algoByDim[4];
   algoByDim[ aDim ] = algoData;
@@ -1507,13 +1489,14 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
   {
     if ( !isAccessibleDim( dim ))
       continue;
-    for ( int type = MainHyp; type < NbHypTypes; type++ )
+    for ( int dlgType = MainHyp; dlgType < nbDlgHypTypes(dim); dlgType++ )
     {
+      const int type = Min( dlgType, AddHyp );
       myAvailableHypData[ dim ][ type ].clear();
       QStringList anAvailable, anExisting;
 
       HypothesisData* curAlgo = algoByDim[ dim ];
-      int hypIndex = currentHyp( dim, type );
+      int hypIndex = currentHyp( dim, dlgType );
 
       SMESH::SMESH_Hypothesis_var curHyp;
       if ( hypIndex >= 0 && hypIndex < myExistingHyps[ dim ][ type ].count() )
@@ -1522,10 +1505,10 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
       if ( !myToCreate && !curAlgo && !curHyp->_is_nil() ) { // edition, algo not selected
         // try to find algo by selected hypothesis in order to keep it selected
         bool algoDeselectedByUser = ( theDim < 0 && aDim == dim );
-        CORBA::String_var curHypType = curHyp->GetName();
+        QString curHypType = SMESH::toQStr( curHyp->GetName() );
         if ( !algoDeselectedByUser &&
-            myObjHyps[ dim ][ type ].count() > 0 &&
-            !strcmp( curHypType, myObjHyps[ dim ][ type ].first().first->GetName()) )
+             myObjHyps[ dim ][ type ].count() > 0 &&
+             curHypType == SMESH::toQStr( myObjHyps[ dim ][ type ].first().first->GetName()) )
         {
           HypothesisData* hypData = SMESH::GetHypothesisData( curHyp->GetName() );
           for (int i = 0; i < myAvailableHypData[ dim ][ Algo ].count(); ++i) {
@@ -1547,8 +1530,8 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
           if ( !isCompatible( curAlgo, hypData, type ))
             curHyp = SMESH::SMESH_Hypothesis::_nil();
         }
-        existingHyps( dim, type, pObj, anExisting, myExistingHyps[ dim ][ type ], curAlgo);
         availableHyps( dim, type, anAvailable, myAvailableHypData[ dim ][ type ], curAlgo);
+        existingHyps( dim, type, pObj, anExisting, myExistingHyps[ dim ][ type ], curAlgo);
         defaulHypAvlbl = (type == MainHyp && !curAlgo->IsAuxOrNeedHyp );
       }
       // set list of hypotheses
@@ -1727,14 +1710,19 @@ bool SMESHGUI_MeshOp::createMesh( QString& theMess, QStringList& theEntryList )
       SMESH::SetName( aMeshSO, myDlg->objectText( SMESHGUI_MeshDlg::Obj ) );
     }
 
-    for ( int aDim = SMESH::DIM_0D; aDim <= SMESH::DIM_3D; aDim++ ) {
+    for ( int aDim = SMESH::DIM_0D; aDim <= SMESH::DIM_3D; aDim++ )
+    {
       if ( !isAccessibleDim( aDim )) continue;
 
       // assign hypotheses
-      for ( int aHypType = MainHyp; aHypType <= AddHyp; aHypType++ ) {
-        int aHypIndex = currentHyp( aDim, aHypType );
-        if ( aHypIndex >= 0 && aHypIndex < myExistingHyps[ aDim ][ aHypType ].count() ) {
-          SMESH::SMESH_Hypothesis_var aHypVar = myExistingHyps[ aDim ][ aHypType ][ aHypIndex ].first;
+      for ( int dlgType = MainHyp; dlgType < nbDlgHypTypes(aDim); dlgType++ )
+      {
+        const int aHypIndex = currentHyp( aDim, dlgType );
+        const int  aHypType = Min( dlgType, AddHyp );
+        if ( aHypIndex >= 0 && aHypIndex < myExistingHyps[ aDim ][ aHypType ].count() )
+        {
+          SMESH::SMESH_Hypothesis_var aHypVar =
+            myExistingHyps[ aDim ][ aHypType ][ aHypIndex ].first;
           if ( !aHypVar->_is_nil() )
             SMESH::AddHypothesisOnMesh( aMeshVar, aHypVar );
         }
@@ -1864,9 +1852,10 @@ bool SMESHGUI_MeshOp::createSubMesh( QString& theMess, QStringList& theEntryList
     if ( !anAlgoVar->_is_nil() )
       SMESH::AddHypothesisOnSubMesh( aSubMeshVar, anAlgoVar );
     // assign hypotheses
-    for ( int aHypType = MainHyp; aHypType <= AddHyp; aHypType++ )
+    for ( int dlgType = MainHyp; dlgType < nbDlgHypTypes(aDim); dlgType++ )
     {
-      int aHypIndex = currentHyp( aDim, aHypType );
+      const int aHypIndex = currentHyp( aDim, dlgType );
+      const int  aHypType = Min( dlgType, AddHyp );
       if ( aHypIndex >= 0 && aHypIndex < myExistingHyps[ aDim ][ aHypType ].count() )
       {
         SMESH::SMESH_Hypothesis_var aHypVar =
@@ -1902,6 +1891,36 @@ int SMESHGUI_MeshOp::currentHyp( const int theDim, const int theHypType ) const
   return myDlg->tab( theDim )->currentHyp( theHypType ) - 1;
 }
 
+//================================================================================
+/*!
+ * \brief Checks if a hypothesis is selected
+ */
+//================================================================================
+
+bool SMESHGUI_MeshOp::isSelectedHyp( int theDim, int theHypType, int theIndex) const
+{
+  if ( theHypType < AddHyp ) // only one hyp can be selected
+    return currentHyp( theDim, theHypType ) == theIndex;
+
+  for ( int dlgHypType = AddHyp; dlgHypType < nbDlgHypTypes( theDim ); ++dlgHypType )
+    if ( currentHyp( theDim, dlgHypType ) == theIndex )
+      return true;
+
+  return false;
+}
+
+//================================================================================
+/*!
+ * \brief Returns nb of HypType's taking into account possible several
+ *        selected additional hypotheses which are coded as additional HypType's.
+ */
+//================================================================================
+
+int SMESHGUI_MeshOp::nbDlgHypTypes( const int dim ) const
+{
+  return NbHypTypes + myDlg->tab( dim )->nbAddHypTypes();
+}
+
 //================================================================================
 /*!
  * \brief Returns true if hypotheses of given dim can be assigned
@@ -1995,8 +2014,7 @@ SMESH::SMESH_Hypothesis_var SMESHGUI_MeshOp::getAlgo( const int theDim )
   for ( ; anIter != aHypVarList.end(); anIter++)
   {
     SMESH::SMESH_Hypothesis_var aHypVar = (*anIter).first;
-    CORBA::String_var aName = aHypVar->GetName();
-    if ( !aHypVar->_is_nil() && !strcmp(aHypName.toLatin1().data(), aName) )
+    if ( !aHypVar->_is_nil() && aHypName == SMESH::toQStr( aHypVar->GetName() ))
     {
       anAlgoVar = aHypVar;
       break;
@@ -2039,8 +2057,7 @@ SMESH::SMESH_Hypothesis_var SMESHGUI_MeshOp::getAlgo( const int theDim )
     for ( anIter = aNewHypVarList.begin(); anIter != aNewHypVarList.end(); ++anIter )
     {
       SMESH::SMESH_Hypothesis_var aHypVar = (*anIter).first;
-      CORBA::String_var aName = aHypVar->GetName();
-      if ( !aHypVar->_is_nil() && !strcmp(aHypName.toLatin1().data(), aName) )
+      if ( !aHypVar->_is_nil() && aHypName == SMESH::toQStr( aHypVar->GetName() ))
       {
         anAlgoVar = aHypVar;
         break;
@@ -2102,11 +2119,11 @@ void SMESHGUI_MeshOp::readMesh()
       SMESH::SMESH_Hypothesis_var aVar = myObjHyps[ dim ][ Algo ].first().first;
       HypothesisData* algoData = SMESH::GetHypothesisData( aVar->GetName() );
       aHypIndex = myAvailableHypData[ dim ][ Algo ].indexOf ( algoData );
-//       if ( aHypIndex < 0 && algoData ) {
-//         // assigned algo is incompatible with other algorithms
-//         myAvailableHypData[ dim ][ Algo ].push_back( algoData );
-//         aHypIndex = myAvailableHypData[ dim ][ hypType ].count() - 1;
-//       }
+      //       if ( aHypIndex < 0 && algoData ) {
+      //         // assigned algo is incompatible with other algorithms
+      //         myAvailableHypData[ dim ][ Algo ].push_back( algoData );
+      //         aHypIndex = myAvailableHypData[ dim ][ hypType ].count() - 1;
+      //       }
       algoFound = ( aHypIndex > -1 );
     }
     setCurrentHyp( dim, Algo, aHypIndex );
@@ -2123,23 +2140,26 @@ void SMESHGUI_MeshOp::readMesh()
     {
       // get hypotheses
       existingHyps( dim, hypType, pObj, anExisting, myObjHyps[ dim ][ hypType ] );
-      // find index of requered hypothesis among existing ones for this dimension and type
-      int aHypIndex = -1;
-      if ( myObjHyps[ dim ][ hypType ].count() > 0 ) {
-        aHypIndex = find( myObjHyps[ dim ][ hypType ].first().first,
-                          myExistingHyps[ dim ][ hypType ] );
+      for ( int i = 0, nb = myObjHyps[ dim ][ hypType ].count(); i < nb; ++i )
+      {
+        // find index of required hypothesis among existing ones for this dimension and type
+        int aHypIndex = find( myObjHyps[ dim ][ hypType ][ i ].first,
+                              myExistingHyps[ dim ][ hypType ] );
         if ( aHypIndex < 0 ) {
           // assigned hypothesis is incompatible with the algorithm
           if ( currentHyp( dim, Algo ) < 0 )
           { // none algo selected; it is edition for sure, of submesh maybe
             hypWithoutAlgo = true;
-            myExistingHyps[ dim ][ hypType ].push_back( myObjHyps[ dim ][ hypType ].first() );
+            myExistingHyps[ dim ][ hypType ].push_back( myObjHyps[ dim ][ hypType ][ i ] );
+            anExisting.push_back( myObjHyps[ dim ][ hypType ][ i ].second );
             aHypIndex = myExistingHyps[ dim ][ hypType ].count() - 1;
             myDlg->tab( dim )->setExistingHyps( hypType, anExisting );
           }
         }
+        setCurrentHyp( dim, hypType + i, aHypIndex );
+
+        if ( hypType == MainHyp ) break; // only one main hyp allowed
       }
-      setCurrentHyp( dim, hypType, aHypIndex );
     }
   }
   // make available other hyps of same type as one without algo
@@ -2150,8 +2170,8 @@ void SMESHGUI_MeshOp::readMesh()
 //================================================================================
 /*!
  * \brief Gets name of object
 * \param theSO - SObject
 * \retval QString - name of object
+ * \param theSO - SObject
+ * \retval QString - name of object
  *
  * Gets name of object
  */
@@ -2277,37 +2297,38 @@ bool SMESHGUI_MeshOp::editMeshOrSubMesh( QString& theMess )
       myObjHyps[ dim ][ Algo ].append( THypItem( anAlgoVar, aName) );
     }
 
-    // assign hypotheses
+    // remove deselected hypotheses
     for ( int hypType = MainHyp; hypType <= AddHyp; hypType++ )
     {
-      int aNewHypIndex = currentHyp( dim, hypType );
-      int anOldHypIndex = -1;
-
-      // remove old hypotheses
-      if ( myObjHyps[ dim ][ hypType ].count() > 0 )
+      for ( int i = 0, nb = myObjHyps[ dim ][ hypType ].count(); i < nb; ++i )
       {
-        anOldHypIndex = find( myObjHyps[ dim ][ hypType ].first().first,
-                              myExistingHyps[ dim ][ hypType ] );
-        if ( aNewHypIndex != anOldHypIndex || // different hyps
-             anOldHypIndex == -1 )            // hyps of different algos
+        SMESH::SMESH_Hypothesis_var hyp = myObjHyps[ dim ][ hypType ][ i ].first;
+        int hypIndex = this->find( hyp, myExistingHyps[ dim ][ hypType ]);
+        if ( !isSelectedHyp( dim, hypType, hypIndex ) && !hyp->_is_nil() )
         {
-          SMESH::RemoveHypothesisOrAlgorithmOnMesh
-            ( pObj, myObjHyps[ dim ][ hypType ].first().first );
-          myObjHyps[ dim ][ hypType ].clear();
+          SMESH::RemoveHypothesisOrAlgorithmOnMesh( pObj, hyp );
         }
       }
-
-      // assign new hypotheses
-      if ( aNewHypIndex != anOldHypIndex && aNewHypIndex > -1 )
+    }
+    // assign newly selected hypotheses
+    for ( int dlgType = MainHyp; dlgType < nbDlgHypTypes(dim); dlgType++ )
+    {
+      const int curIndex = currentHyp( dim, dlgType );
+      const int  hypType = Min( dlgType, AddHyp );
+      if ( curIndex >= 0 && curIndex < myExistingHyps[ dim ][ hypType ].count() )
       {
-        if ( isMesh )
-          SMESH::AddHypothesisOnMesh
-            (aMeshVar, myExistingHyps[ dim ][ hypType ][ aNewHypIndex ].first );
-        else if ( !aSubMeshVar->_is_nil() )
-          SMESH::AddHypothesisOnSubMesh
-            ( aSubMeshVar, myExistingHyps[ dim ][ hypType ][ aNewHypIndex ].first );
+        SMESH::SMESH_Hypothesis_var hyp = myExistingHyps[ dim ][ hypType ][ curIndex ].first;
+
+        bool isAssigned = ( this->find( hyp, myObjHyps[ dim ][ hypType ]) >= 0 );
+        if ( !isAssigned )
+        {
+          if ( isMesh )
+            SMESH::AddHypothesisOnMesh (aMeshVar, hyp );
+          else if ( !aSubMeshVar->_is_nil() )
+            SMESH::AddHypothesisOnSubMesh ( aSubMeshVar, hyp );
+        }
       }
-      // reread all hypotheses of mesh if necessary
+      // reread all hypotheses of mesh
       QStringList anExisting;
       existingHyps( dim, hypType, pObj, anExisting, myObjHyps[ dim ][ hypType ] );
     }
@@ -2431,7 +2452,7 @@ void SMESHGUI_MeshOp::onPublishShapeByMeshDlg(SUIT_Operation* op)
     GEOM::GEOM_Object_var aGeomVar = myShapeByMeshOp->GetShape();
     if ( !aGeomVar->_is_nil() )
     {
-      QString ID = aGeomVar->GetStudyEntry();
+      QString ID = SMESH::toQStr( aGeomVar->GetStudyEntry() );
       if ( _PTR(SObject) aGeomSO = studyDS()->FindObjectID( ID.toLatin1().data() )) {
         selectObject( aGeomSO );
         selectionDone();
@@ -2568,7 +2589,7 @@ void SMESHGUI_MeshOp::setFilteredAlgoData( const int theTabIndex, const int theI
 
   if ( anCompareType == "ANY" )
   {
-    for ( int dim = SMESH::DIM_2D; dim <= SMESH::DIM_3D; dim++ )
+    for ( int dim = SMESH::DIM_3D; dim >= SMESH::DIM_2D; dim-- )
     {
       isNone = currentHyp( dim, Algo ) < 0;
       isAvailableChoiceAlgo = false;
@@ -2581,30 +2602,35 @@ void SMESHGUI_MeshOp::setFilteredAlgoData( const int theTabIndex, const int theI
       }
       myAvailableHypData[dim][Algo].clear();
       anAvailableAlgs.clear();
-      for (int i = 0 ; i < anAvailableAlgsData.count(); i++)
+      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() )
       {
-        HypothesisData* curAlgo = anAvailableAlgsData.at(i);
-        if ( aGeomVar->_is_nil() ||
-             SMESH::IsApplicable( curAlgo->TypeName, aGeomVar, toCheckIsApplicableToAll ))
+        for (int i = 0 ; i < anAvailableAlgsData.count(); i++)
         {
-          anAvailableAlgs.append( curAlgo->Label );
-          myAvailableHypData[dim][Algo].append( curAlgo );
+          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;
+        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 );
+        else if ( !isNone ) {
+          isAvailableChoiceAlgo = true;
+          anCurrentAvailableAlgo = currentHyp( dim, Algo );
+        }
       }
       myDlg->tab( dim )->setAvailableHyps( Algo, anAvailableAlgs );
       if ( isAvailableChoiceAlgo )
@@ -2730,11 +2756,24 @@ void SMESHGUI_MeshOp::setFilteredAlgoData( const int theTabIndex, const int theI
       {
         for (int i = SMESH::DIM_0D; i <= myMaxShapeDim; i++)
         {
-          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 ( 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 ( isAvailable ) break;
index fcaedabf3fe112271e81fb3281a8658a1c8aef9f..99a699ba489bc9244d3d62afb0048319c505b4a4 100644 (file)
@@ -36,6 +36,7 @@ class HypothesesSet;
 class SMESHGUI_MeshDlg;
 class SMESHGUI_ShapeByMeshOp;
 class HypothesisData;
+class SMESHGUI_GenericHypothesisCreator;
 
 /*!
  * \brief Operation for mech creation or editing
@@ -95,12 +96,12 @@ private:
                                                 QStringList&,
                                                 THypDataList&,
                                                 HypothesisData* = 0 ) const;
-  static void                    existingHyps( const int, 
+  void                           existingHyps( const int, 
                                                const int, 
                                                _PTR(SObject),
                                                QStringList&, 
                                                THypList&,
-                                               HypothesisData* = 0 );
+                                               HypothesisData* = 0 ) const;
   HypothesisData*                hypData( const int,
                                           const int,
                                           const int ); // access to myAvailableHypData
@@ -116,6 +117,8 @@ private:
                                                           bool                     askUser=false);
 
   int                            currentHyp( const int, const int ) const;
+  bool                           isSelectedHyp( int, int, int ) const;
+  int                            nbDlgHypTypes( const int ) const;
   bool                           isAccessibleDim( const int ) const;
   void                           setCurrentHyp( const int, const int, const int );
   void                           setDefaultName( const QString& prefix="" ) const;
@@ -126,6 +129,7 @@ private:
                                        const THypList& ) const;
   SMESH::SMESH_Hypothesis_var    getInitParamsHypothesis( const QString&,
                                                           const QString& ) const;
+  void                           initHypCreator( SMESHGUI_GenericHypothesisCreator* aCreator );
   bool                           isSubshapeOk() const;
   char*                          isSubmeshIgnored() const;
   _PTR(SObject)                  getSubmeshByGeom() const;
@@ -133,7 +137,9 @@ private:
   void                           createMeshTypeList( QStringList& );
   void                           setAvailableMeshType( const QStringList& );
   void                           setFilteredAlgoData( const int, const int );
+
 private:
+
   SMESHGUI_MeshDlg*              myDlg;
   SMESHGUI_ShapeByMeshOp*        myShapeByMeshOp;
   bool                           myToCreate;
diff --git a/src/SMESHGUI/SMESHGUI_Operations.h b/src/SMESHGUI/SMESHGUI_Operations.h
new file mode 100644 (file)
index 0000000..0d1cfe5
--- /dev/null
@@ -0,0 +1,228 @@
+// Copyright (C) 2007-2014  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   : SMESHGUI_Operations.h
+//  Author : IVAN MECHETIN, Open CASCADE S.A.S. (ivan.mechetin@opencascade.com)
+
+#ifndef SMESHGUI_OPERATIONS_H
+#define SMESHGUI_OPERATIONS_H
+
+namespace SMESHOp {
+  enum {
+    // Tools --------------------------//--------------------------------
+    OpDelete                 = 1000,   // DELETE
+    OpSelectFiltersLibrary   = 1010,   // MENU TOOLS - SELECTION FILTERS LIBRARY
+    OpReset                  = 1020,   // RESET
+    OpScalarBarProperties    = 1021,   // SCALAR BAR PROPERTIES
+    OpSaveDistribution       = 1030,   // SAVE DISTRIBUTION
+    OpShowDistribution       = 1031,   // SHOW DISTRIBUTION
+#ifndef DISABLE_PLOT2DVIEWER
+    OpPlotDistribution       = 1032,   // PLOT DISTRIBUTION
+#endif
+    OpFileInformation        = 1040,   // POPUP MENU - FILE INFORMATION
+    // Import -------------------------//--------------------------------
+    OpImportDAT              = 1100,   // MENU FILE - IMPORT - DAT FILE
+    OpImportUNV              = 1101,   // MENU FILE - IMPORT - UNV FILE
+    OpImportMED              = 1102,   // MENU FILE - IMPORT - MED FILE
+    OpImportSTL              = 1103,   // MENU FILE - IMPORT - STL FILE
+#ifdef WITH_CGNS
+    OpImportCGNS             = 1104,   // MENU FILE - IMPORT - CGNS FILE
+#endif
+    OpImportSAUV             = 1105,   // MENU FILE - IMPORT - SAUV FILE
+    OpImportGMF              = 1106,   // MENU FILE - IMPORT - GMF FILE
+    // Export -------------------------//--------------------------------
+    OpExportDAT              = 1200,   // MENU FILE  - EXPORT - DAT FILE
+    OpExportMED              = 1201,   // MENU FILE  - EXPORT - MED FILE
+    OpExportUNV              = 1202,   // MENU FILE  - EXPORT - UNV FILE
+    OpExportSTL              = 1203,   // MENU FILE  - EXPORT - STL FILE
+#ifdef WITH_CGNS
+    OpExportCGNS             = 1204,   // MENU FILE  - EXPORT - CGNS FILE
+#endif
+    OpExportSAUV             = 1205,   // MENU FILE  - EXPORT - SAUV FILE
+    OpExportGMF              = 1206,   // MENU FILE  - EXPORT - GMF FILE
+    OpPopupExportDAT         = 1210,   // POPUP MENU - EXPORT - DAT FILE
+    OpPopupExportMED         = 1211,   // POPUP MENU - EXPORT - MED FILE
+    OpPopupExportUNV         = 1212,   // POPUP MENU - EXPORT - UNV FILE
+    OpPopupExportSTL         = 1213,   // POPUP MENU - EXPORT - STL FILE
+#ifdef WITH_CGNS
+    OpPopupExportCGNS        = 1214,   // POPUP MENU - EXPORT - CGNS FILE
+#endif
+    OpPopupExportSAUV        = 1215,   // POPUP MENU - EXPORT - SAUV FILE
+    OpPopupExportGMF         = 1216,   // POPUP MENU - EXPORT - GMF FILE
+    // Mesh ---------------------------//--------------------------------
+    OpCreateMesh             = 2030,   // MENU MESH  - CREATE MESH
+    OpCreateSubMesh          = 2031,   // MENU MESH  - CREATE SUBMESH
+    OpEditMeshOrSubMesh      = 2032,   // MENU MESH  - EDIT MESH/SUBMESH
+    OpBuildCompoundMesh      = 2033,   // MENU MESH  - BUILD COMPOUND
+    OpCopyMesh               = 2034,   // MENU MESH  - COPY MESH
+    OpCompute                = 2040,   // MENU MESH  - COMPUTE
+    OpPreCompute             = 2041,   // MENU MESH  - PREVIEW
+    OpEvaluate               = 2042,   // MENU MESH  - EVALUATE
+    OpMeshOrder              = 2043,   // MENU MESH  - CHANGE SUBMESH PRIORITY
+    OpCreateGroup            = 2050,   // MENU MESH  - CREATE GROUP
+    OpCreateGeometryGroup    = 2051,   // MENU MESH  - CREATE GROUPS FROM GEOMETRY
+    OpConstructGroup         = 2052,   // MENU MESH  - CONSTRUCT GROUP
+    OpEditGroup              = 2053,   // MENU MESH  - EDIT GROUP
+    OpEditGeomGroupAsGroup   = 2054,   // MENU MESH  - EDIT GROUP AS STANDALONE
+    OpUnionGroups            = 2060,   // MENU MESH  - UNION GROUPS
+    OpIntersectGroups        = 2061,   // MENU MESH  - INTERSECT GROUPS
+    OpCutGroups              = 2062,   // MENU MESH  - CUT GROUPS
+    OpGroupUnderlyingElem    = 2070,   // MENU MESH  - GROUP OF UNDERLYING ENTITIES
+    OpEditGroupPopup         = 2080,   // POPUP MENU - EDIT GROUP
+    OpAddElemGroupPopup      = 2081,   // POPUP MENU - ADD ELEMENTS TO GROUP
+    OpRemoveElemGroupPopup   = 2082,   // POPUP MENU - REMOVE ELEMENTS FROM GROUP
+    OpMeshInformation        = 2100,   // MENU MESH  - MESH INFORMATION
+    OpWhatIs                 = 2101,   // MENU MESH  - MESH ELEMENT INFORMATION
+    OpStdInfo                = 2102,   // MENU MESH  - MESH STANDART INFORMATION
+    OpFindElementByPoint     = 2103,   // MENU MESH  - FIND ELEMENT BY POINT
+    OpUpdate                 = 2200,   // POPUP MENU - UPDATE
+    // Controls -----------------------//--------------------------------
+    OpFreeNode               = 3000,   // MENU CONTROLS - FREE NODES
+    OpEqualNode              = 3001,   // MENU CONTROLS - DOUBLE NODES
+    OpFreeEdge               = 3100,   // MENU CONTROLS - FREE EDGES
+    OpFreeBorder             = 3101,   // MENU CONTROLS - FREE BORDERS
+    OpLength                 = 3102,   // MENU CONTROLS - LENGTH
+    OpConnection             = 3103,   // MENU CONTROLS - DOUBLE NODES
+    OpEqualEdge              = 3104,   // MENU CONTROLS - BORDERS AT MULTICONNECTION
+    OpFreeFace               = 3200,   // MENU CONTROLS - FREE FACES
+    OpBareBorderFace         = 3201,   // MENU CONTROLS - FACES WITH BARE BORDER
+    OpOverConstrainedFace    = 3202,   // MENU CONTROLS - OVERCONSTRAINED FACES
+    OpLength2D               = 3203,   // MENU CONTROLS - LENGTH 2D
+    OpConnection2D           = 3204,   // MENU CONTROLS - BORDERS ON MULTICONNECTION 2D
+    OpArea                   = 3205,   // MENU CONTROLS - AREA
+    OpTaper                  = 3206,   // MENU CONTROLS - TAPER
+    OpAspectRatio            = 3207,   // MENU CONTROLS - ASPECT RATIO
+    OpMinimumAngle           = 3208,   // MENU CONTROLS - MINIMUM ANGLE
+    OpWarpingAngle           = 3209,   // MENU CONTROLS - WARPING ANGLE
+    OpSkew                   = 3210,   // MENU CONTROLS - SKEW
+    OpMaxElementLength2D     = 3211,   // MENU CONTROLS - ELEMENT DIAMETER 2D
+    OpEqualFace              = 3212,   // MENU CONTROLS - DOUBLE FACES
+    OpAspectRatio3D          = 3300,   // MENU CONTROLS - ASPECT RATIO 3D
+    OpVolume                 = 3301,   // MENU CONTROLS - VOLUME
+    OpMaxElementLength3D     = 3302,   // MENU CONTROLS - ELEMENT DIAMETER 3D
+    OpBareBorderVolume       = 3303,   // MENU CONTROLS - VOLUMES WITH BARE BORDER
+    OpOverConstrainedVolume  = 3304,   // MENU CONTROLS - OVERCONSTRAINED VOLUMES
+    OpEqualVolume            = 3305,   // MENU CONTROLS - DOUBLE VOLUMES
+    OpOverallMeshQuality     = 3400,   // MENU CONTROLS - OVERALL MESH QUALITY
+    // Modification -------------------//--------------------------------
+    OpNode                   = 4000,   // MENU MODIFICATION - ADD - NODE
+    OpElem0D                 = 4001,   // MENU MODIFICATION - ADD - 0D ELEMENT
+    OpElem0DOnElemNodes      = 4002,   // MENU MODIFICATION - ADD - 0D ELEMENTS ON ELEMENT NODES
+    OpBall                   = 4003,   // MENU MODIFICATION - ADD - BALL
+    OpEdge                   = 4004,   // MENU MODIFICATION - ADD - EDGE
+    OpTriangle               = 4005,   // MENU MODIFICATION - ADD - TRIANGLE
+    OpQuadrangle             = 4006,   // MENU MODIFICATION - ADD - QUADRANGLE
+    OpPolygon                = 4007,   // MENU MODIFICATION - ADD - POLYGON
+    OpTetrahedron            = 4008,   // MENU MODIFICATION - ADD - TETRAHEDRON
+    OpHexahedron             = 4009,   // MENU MODIFICATION - ADD - HEXAHEDRON
+    OpPentahedron            = 4010,   // MENU MODIFICATION - ADD - PENTAHEDRON
+    OpPyramid                = 4011,   // MENU MODIFICATION - ADD - PYRAMID
+    OpHexagonalPrism         = 4012,   // MENU MODIFICATION - ADD - HEXAGONAL PRISM
+    OpPolyhedron             = 4013,   // MENU MODIFICATION - ADD - POLYHEDRON
+    OpQuadraticEdge          = 4100,   // MENU MODIFICATION - ADD - QUADRATIC EDGE
+    OpQuadraticTriangle      = 4101,   // MENU MODIFICATION - ADD - QUADRATIC TRIANGLE
+    OpBiQuadraticTriangle    = 4102,   // MENU MODIFICATION - ADD - BIQUADRATIC TRIANGLE
+    OpQuadraticQuadrangle    = 4103,   // MENU MODIFICATION - ADD - QUADRATIC QUADRANGLE
+    OpBiQuadraticQuadrangle  = 4104,   // MENU MODIFICATION - ADD - BIQUADRATIC QUADRANGLE
+    OpQuadraticTetrahedron   = 4105,   // MENU MODIFICATION - ADD - QUADRATIC TETRAHEDRON
+    OpQuadraticPyramid       = 4106,   // MENU MODIFICATION - ADD - QUADRATIC PYRAMID
+    OpQuadraticPentahedron   = 4107,   // MENU MODIFICATION - ADD - QUADRATIC PENTAHEDRON
+    OpQuadraticHexahedron    = 4108,   // MENU MODIFICATION - ADD - QUADRATIC HEXAHEDRON
+    OpTriQuadraticHexahedron = 4109,   // MENU MODIFICATION - ADD - TRIQUADRATIC HEXAHEDRON
+    OpRemoveNodes            = 4200,   // MENU MODIFICATION - REMOVE - NODE
+    OpRemoveElements         = 4201,   // MENU MODIFICATION - REMOVE - ELEMENTS
+    OpRemoveOrphanNodes      = 4202,   // MENU MODIFICATION - REMOVE - ORPHAN NODES
+    OpDeleteGroup            = 4210,   // MENU MODIFICATION - REMOVE - DELETE GROUPS WITH CONTENTS
+    OpClearMesh              = 4220,   // MENU MODIFICATION - REMOVE - CLEAR MESH DATA
+    OpRenumberingNodes       = 4300,   // MENU MODIFICATION - RENUMBERING - NODES
+    OpRenumberingElements    = 4301,   // MENU MODIFICATION - RENUMBERING - ELEMENTS
+    OpTranslation            = 4400,   // MENU MODIFICATION - TRANSFORMATION - TRANSLATION
+    OpRotation               = 4401,   // MENU MODIFICATION - TRANSFORMATION - ROTATION
+    OpSymmetry               = 4402,   // MENU MODIFICATION - TRANSFORMATION - SYMMETRY
+    OpScale                  = 4403,   // MENU MODIFICATION - TRANSFORMATION - SCALE TRANSFORM
+    OpSewing                 = 4404,   // MENU MODIFICATION - TRANSFORMATION - SEWING
+    OpMergeNodes             = 4405,   // MENU MODIFICATION - TRANSFORMATION - MERGE NODES
+    OpMergeElements          = 4406,   // MENU MODIFICATION - TRANSFORMATION - MERGE ELEMENTS
+    OpDuplicateNodes         = 4407,   // MENU MODIFICATION - TRANSFORMATION - DUPLICATE NODES OR/AND ELEMENTS
+    OpMoveNode               = 4500,   // MENU MODIFICATION - MOVE NODE
+    OpDiagonalInversion      = 4501,   // MENU MODIFICATION - DIAGONAL INVERSION
+    OpUnionOfTwoTriangle     = 4502,   // MENU MODIFICATION - UNION OF TWO TRIANGLE
+    OpOrientation            = 4503,   // MENU MODIFICATION - ORIENTATION
+    OpReorientFaces          = 4504,   // MENU MODIFICATION - REORIENT FACES BY VECTOR
+    OpUnionOfTriangles       = 4505,   // MENU MODIFICATION - UNION OF TRIANGLES
+    OpCuttingOfQuadrangles   = 4506,   // MENU MODIFICATION - CUTTING OF QUADRANGLES
+    OpSplitVolumes           = 4507,   // MENU MODIFICATION - SPLIT VOLUMES
+    OpSmoothing              = 4508,   // MENU MODIFICATION - SMOOTHING
+    OpExtrusion              = 4509,   // MENU MODIFICATION - EXTRUSION
+    OpExtrusionAlongAPath    = 4510,   // MENU MODIFICATION - EXTRUSION ALONG A PATH
+    OpRevolution             = 4511,   // MENU MODIFICATION - REVOLUTION
+    OpPatternMapping         = 4512,   // MENU MODIFICATION - PATTERN MAPPING
+    OpConvertMeshToQuadratic = 4513,   // MENU MODIFICATION - CONVERT TO/FROM QUADRATIC
+    OpCreateBoundaryElements = 4514,   // MENU MODIFICATION - CREATE BOUNDARY ELEMENTS
+    // Measurements -------------------//--------------------------------
+    OpPropertiesLength       = 5000,   // MENU MEASUREMENTS - BASIC PROPERTIES - LENGTH
+    OpPropertiesArea         = 5001,   // MENU MEASUREMENTS - BASIC PROPERTIES - AREA
+    OpPropertiesVolume       = 5002,   // MENU MEASUREMENTS - BASIC PROPERTIES - VOLUME
+    OpMinimumDistance        = 5003,   // MENU MEASUREMENTS - MINIMUM DISTANCE
+    OpBoundingBox            = 5004,   // MENU MEASUREMENTS - BOUNDING BOX
+    // Hypothesis ---------------------//--------------------------------
+    OpEditHypothesis         = 6000,   // POPUP MENU - EDIT HYPOTHESIS
+    OpUnassign               = 6001,   // POPUP MENU - UNASSIGN
+    // Numbering ----------------------//--------------------------------
+    OpNumberingNodes         = 6010,   // POPUP MENU - NUMBERING - DISPLAY NODES
+    OpNumberingElements      = 6011,   // POPUP MENU - NUMBERING - DISPLAY ELEMENTS
+    // AutoColor ----------------------//--------------------------------
+    OpAutoColor              = 6020,   // POPUP MENU - AUTO COLOR
+    OpDisableAutoColor       = 6021,   // POPUP MENU - DISABLE AUTO COLOR
+    // DisplayMode --------------------//--------------------------------
+    OpDMWireframe            = 6030,   // POPUP MENU - DISPLAY MODE - WIREFRAME
+    OpDMShading              = 6031,   // POPUP MENU - DISPLAY MODE - SHADING
+    OpDMNodes                = 6032,   // POPUP MENU - DISPLAY MODE - NODES
+    OpDMShrink               = 6033,   // POPUP MENU - DISPLAY MODE - SHRINK
+    // DisplayEntity ------------------//--------------------------------
+    OpDE0DElements           = 6040,   // POPUP MENU - DISPLAY ENTITY - 0D ELEMENTS
+    OpDEEdges                = 6041,   // POPUP MENU - DISPLAY ENTITY - EDGES
+    OpDEFaces                = 6042,   // POPUP MENU - DISPLAY ENTITY - FACES
+    OpDEVolumes              = 6043,   // POPUP MENU - DISPLAY ENTITY - VOLUMES
+    OpDEBalls                = 6044,   // POPUP MENU - DISPLAY ENTITY - BALLS
+    OpDEAllEntity            = 6045,   // POPUP MENU - DISPLAY ENTITY - ALL ENTITY
+    // Representation -----------------//--------------------------------
+    OpRepresentationLines    = 6050,   // POPUP MENU - 2D QUADRATIC - LINES
+    OpRepresentationArcs     = 6051,   // POPUP MENU - 2D QUADRATIC - ARCS
+    // OrientationOnFaces -------------//--------------------------------
+    OpOrientationOnFaces     = 6060,   // POPUP MENU - ORIENTATION ON FACES
+    // PropertiesGUI ------------------//--------------------------------
+    OpProperties             = 6070,   // POPUP MENU - PROPERTIES
+    // Transparency -------------------//--------------------------------
+    OpTransparency           = 6080,   // POPUP MENU - TRANSPARENCY
+    // Display ------------------------//--------------------------------
+    OpShow                   = 6090,   // POPUP MENU - SHOW
+    OpHide                   = 6091,   // POPUP MENU - HIDE
+    OpShowOnly               = 6092,   // POPUP MENU - SHOW ONLY
+    // Clipping -----------------------//--------------------------------
+    OpClipping               = 6100,   // POPUP MENU - CLIPPING
+    // SortChild ----------------------//--------------------------------
+    OpSortChild              = 6110,   // POPUP MENU - SORT CHILDREN
+    // Advanced -----------------------//--------------------------------
+    OpAdvancedNoOp           = 10000,  // NO OPERATION (advanced operations base)
+    //@@ insert new functions before this line @@ do not remove this line @@//
+    OpLastOperationID        = 20000   // DO NOT USE OPERATION IDs MORE THAN 20000 !!!
+  };
+}
+
+#endif // SMESHGUI_OPERATIONS_H
index aee6f62d77c8ef99c6099ed1e93123038fbdc893..41e341cca25d88745de76600f38f7732a3e3b492 100644 (file)
@@ -92,8 +92,8 @@
 #define SPACING 6
 #define MARGIN  11
 
-enum { CONSTRUCTOR_POINT=0, CONSTRUCTOR_FACE,
-       EObject, EPoint, EFace, EDirection };
+enum { CONSTRUCTOR_POINT=0, CONSTRUCTOR_FACE, CONSTRUCTOR_VOLUME,
+       EObject, EPoint, EFace, EDirection, EVolumes };
 
 //=======================================================================
 /*!
@@ -131,6 +131,7 @@ QWidget* SMESHGUI_ReorientFacesDlg::createMainFrame (QWidget* theParent)
 
   QPixmap iconReoriPoint (resMgr()->loadPixmap("SMESH", tr("ICON_DLG_REORIENT2D_POINT")));
   QPixmap iconReoriFace  (resMgr()->loadPixmap("SMESH", tr("ICON_DLG_REORIENT2D_FACE")));
+  QPixmap iconReoriVolum (resMgr()->loadPixmap("SMESH", tr("ICON_DLG_REORIENT2D_VOLUME")));
 
   QGroupBox* aConstructorBox = new QGroupBox(tr("REORIENT_FACES"), aFrame);
   myConstructorGrp = new QButtonGroup(aConstructorBox);
@@ -149,6 +150,11 @@ QWidget* SMESHGUI_ReorientFacesDlg::createMainFrame (QWidget* theParent)
   aConstructorGrpLayout->addWidget(aFaceBut);
   myConstructorGrp->addButton(aFaceBut, CONSTRUCTOR_FACE);
 
+  QRadioButton* aVolBut= new QRadioButton(aConstructorBox);
+  aVolBut->setIcon(iconReoriVolum);
+  aConstructorGrpLayout->addWidget(aVolBut);
+  myConstructorGrp->addButton(aVolBut, CONSTRUCTOR_VOLUME);
+
   // Create other controls
 
   setObjectPixmap( "SMESH", tr( "ICON_SELECT" ) );
@@ -157,17 +163,22 @@ QWidget* SMESHGUI_ReorientFacesDlg::createMainFrame (QWidget* theParent)
   createObject( tr("POINT")    , aFrame, EPoint );
   createObject( tr("FACE")     , aFrame, EFace );
   createObject( tr("DIRECTION"), aFrame, EDirection );
+  createObject( tr("VOLUMES"),   aFrame, EVolumes );
   setNameIndication( EObject, OneName );
   setNameIndication( EFace, OneName );
   setReadOnly( EFace, false );
   if ( QLineEdit* le = qobject_cast<QLineEdit*>( objectWg( EFace, Control ) ))
     le->setValidator( new SMESHGUI_IdValidator( this,1 ));
 
-  const int width = aFaceBut->fontMetrics().width( tr("DIRECTION"));
+  int width = aFaceBut->fontMetrics().width( tr("DIRECTION"));
   objectWg( EDirection, Label )->setFixedWidth( width );
   objectWg( EObject   , Label )->setFixedWidth( width );
   objectWg( EPoint    , Label )->setFixedWidth( width );
   objectWg( EFace     , Label )->setFixedWidth( width );
+  objectWg( EVolumes  , Label )->setFixedWidth( width );
+
+  myOutsideChk = new QCheckBox( tr("OUTSIDE_VOLUME_NORMAL"), aFrame);
+  myOutsideChk->setChecked( true );
 
   QLabel* aXLabel = new QLabel(tr("SMESH_X"), aFrame);
   myX = new SMESHGUI_SpinBox(aFrame);
@@ -197,6 +208,15 @@ QWidget* SMESHGUI_ReorientFacesDlg::createMainFrame (QWidget* theParent)
   myDY->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
   myDZ->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
 
+  width = Max( aFaceBut->fontMetrics().width( tr("SMESH_X")),
+               aFaceBut->fontMetrics().width( tr("SMESH_DX")));
+  aXLabel->setFixedWidth( width );
+  aYLabel->setFixedWidth( width );
+  aZLabel->setFixedWidth( width );
+  aDXLabel->setFixedWidth( width );
+  aDYLabel->setFixedWidth( width );
+  aDZLabel->setFixedWidth( width );
+
   // Layouting
 
   QGroupBox* anObjectGrp = new QGroupBox(tr("FACES"), aFrame);
@@ -213,12 +233,12 @@ QWidget* SMESHGUI_ReorientFacesDlg::createMainFrame (QWidget* theParent)
   objectWg( EPoint, Control )->hide();
   aPointGrpLayout->addWidget( objectWg( EPoint, Label ) );
   aPointGrpLayout->addWidget( objectWg( EPoint, Btn ) );
-  aPointGrpLayout->addWidget( aXLabel );
-  aPointGrpLayout->addWidget( myX     );
-  aPointGrpLayout->addWidget( aYLabel );
-  aPointGrpLayout->addWidget( myY     );
-  aPointGrpLayout->addWidget( aZLabel );
-  aPointGrpLayout->addWidget( myZ     );
+  aPointGrpLayout->addWidget( aXLabel, 0 );
+  aPointGrpLayout->addWidget( myX,     1 );
+  aPointGrpLayout->addWidget( aYLabel, 0 );
+  aPointGrpLayout->addWidget( myY,     1 );
+  aPointGrpLayout->addWidget( aZLabel, 0 );
+  aPointGrpLayout->addWidget( myZ,     1 );
 
   myFaceFrm = new QFrame(aFrame);
   QHBoxLayout* aFaceGrpLayout = new QHBoxLayout(myFaceFrm);
@@ -227,25 +247,35 @@ QWidget* SMESHGUI_ReorientFacesDlg::createMainFrame (QWidget* theParent)
   aFaceGrpLayout->addWidget( objectWg( EFace, Btn ) );
   aFaceGrpLayout->addWidget( objectWg( EFace, Control ) );
 
-  QFrame* aDirectFrm = new QFrame(aFrame);
-  QHBoxLayout* aDirectGrpLayout = new QHBoxLayout(aDirectFrm);
+  myVolumFrm = new QFrame(aFrame);
+  QGridLayout* aVolumGrpLayout = new QGridLayout(myVolumFrm);
+  aVolumGrpLayout->setMargin(0);
+  aVolumGrpLayout->setSpacing(SPACING);
+  aVolumGrpLayout->addWidget( objectWg( EVolumes, Label ),   0, 0 );
+  aVolumGrpLayout->addWidget( objectWg( EVolumes, Btn ),     0, 1 );
+  aVolumGrpLayout->addWidget( objectWg( EVolumes, Control ), 0, 2 );
+  aVolumGrpLayout->addWidget( myOutsideChk,                  1, 0, 1, 3 );
+
+  myDirFrm = new QFrame(aFrame);
+  QHBoxLayout* aDirectGrpLayout = new QHBoxLayout(myDirFrm);
   aDirectGrpLayout->setMargin(0);
   objectWg( EDirection, Control )->hide();
   aDirectGrpLayout->addWidget( objectWg( EDirection, Label ) );
   aDirectGrpLayout->addWidget( objectWg( EDirection, Btn ) );
-  aDirectGrpLayout->addWidget(aDXLabel );
-  aDirectGrpLayout->addWidget(myDX );
-  aDirectGrpLayout->addWidget(aDYLabel );
-  aDirectGrpLayout->addWidget(myDY );
-  aDirectGrpLayout->addWidget(aDZLabel );
-  aDirectGrpLayout->addWidget(myDZ );
+  aDirectGrpLayout->addWidget( aDXLabel, 0 );
+  aDirectGrpLayout->addWidget( myDX,     1 );
+  aDirectGrpLayout->addWidget( aDYLabel, 0 );
+  aDirectGrpLayout->addWidget( myDY,     1 );
+  aDirectGrpLayout->addWidget( aDZLabel, 0 );
+  aDirectGrpLayout->addWidget( myDZ,     1 );
   
 
   QGroupBox* anOrientGrp = new QGroupBox(tr("ORIENTATION"), aFrame);
   QVBoxLayout* anOrientGrpLayout = new QVBoxLayout ( anOrientGrp );
   anOrientGrpLayout->addWidget(myPointFrm);
   anOrientGrpLayout->addWidget(myFaceFrm);
-  anOrientGrpLayout->addWidget(aDirectFrm);
+  anOrientGrpLayout->addWidget(myVolumFrm);
+  anOrientGrpLayout->addWidget(myDirFrm);
   
 
   QVBoxLayout* aLay = new QVBoxLayout(aFrame);
@@ -269,15 +299,27 @@ void SMESHGUI_ReorientFacesDlg::constructorChange(int id)
   if ( id == CONSTRUCTOR_FACE )
   {
     myPointFrm->hide();
+    myVolumFrm->hide();
     myFaceFrm->show();
+    myDirFrm->show();
     activateObject( EFace );
   }
-  else
+  else if ( id == CONSTRUCTOR_POINT )
   {
     myFaceFrm->hide();
+    myVolumFrm->hide();
     myPointFrm->show();
+    myDirFrm->show();
     activateObject( EPoint );
   }
+  else // CONSTRUCTOR_VOLUME
+  {
+    myFaceFrm->hide();
+    myPointFrm->hide();
+    myDirFrm->hide();
+    myVolumFrm->show();
+    activateObject( EVolumes );
+  }
 }
 
 //================================================================================
@@ -373,6 +415,7 @@ void SMESHGUI_ReorientFacesOp::onActivateObject( int what )
     SMESH::SetPickable();
     break;
   case EObject:
+  case EVolumes:
     SMESH::SetPointRepresentation(false);
     setSelectionMode( ActorSelection );
     break;
@@ -406,6 +449,14 @@ SUIT_SelectionFilter* SMESHGUI_ReorientFacesOp::createFilter( const int what ) c
       filters.append( new SMESH_TypeFilter( SMESH::GROUP_FACE ));
       return new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR );
     }
+  case EVolumes:
+    {
+      QList<SUIT_SelectionFilter*> filters;
+      filters.append( new SMESH_TypeFilter( SMESH::MESH ));
+      filters.append( new SMESH_TypeFilter( SMESH::SUBMESH_SOLID ));
+      filters.append( new SMESH_TypeFilter( SMESH::GROUP_VOLUME ));
+      return new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR );
+    }
   case EPoint:
     {
       QList<SUIT_SelectionFilter*> filters;
@@ -433,6 +484,12 @@ void SMESHGUI_ReorientFacesOp::selectionDone()
   if ( !myDlg->isVisible() || !myDlg->isEnabled() )
     return;
 
+  if ( mySelectionMode == EVolumes )
+  {
+    SMESHGUI_SelectionOp::selectionDone();
+    return;
+  }
+
   myDlg->clearSelection( mySelectionMode );
 
   SALOME_ListIO aList;
@@ -603,29 +660,45 @@ bool SMESHGUI_ReorientFacesOp::onApply()
 
   try {
     SUIT_OverrideCursor wc;
+
     SMESH::SMESH_Mesh_var aMesh = myObject->GetMesh();
     if ( aMesh->_is_nil() ) return false;
 
-    SMESH::DirStruct direction;
-    direction.PS.x = myDlg->myDX->GetValue();
-    direction.PS.y = myDlg->myDY->GetValue();
-    direction.PS.z = myDlg->myDZ->GetValue();
+    SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
+    if (aMeshEditor->_is_nil()) return false;
 
-    long face = myDlg->objectText( EFace ).toInt();
-    if ( myDlg->myConstructorGrp->checkedId() == CONSTRUCTOR_POINT )
-      face = -1;
+    int aResult = 0;
+    if ( myDlg->myConstructorGrp->checkedId() == CONSTRUCTOR_VOLUME )
+    {
+      SMESH::ListOfIDSources_var faceGroups = new SMESH::ListOfIDSources;
+      faceGroups->length(1);
+      faceGroups[0] = myObject;
 
-    SMESH::PointStruct point;
-    point.x = myDlg->myX->GetValue();
-    point.y = myDlg->myY->GetValue();
-    point.z = myDlg->myZ->GetValue();
+      bool outsideNormal = myDlg->myOutsideChk->isChecked();
 
-    SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
-    if (aMeshEditor->_is_nil()) return false;
+      aResult = aMeshEditor->Reorient2DBy3D( faceGroups, myVolumeObj, outsideNormal );
+    }
+    else
+    {
+      SMESH::DirStruct direction;
+      direction.PS.x = myDlg->myDX->GetValue();
+      direction.PS.y = myDlg->myDY->GetValue();
+      direction.PS.z = myDlg->myDZ->GetValue();
+
+      long face = myDlg->objectText( EFace ).toInt();
+      if ( myDlg->myConstructorGrp->checkedId() == CONSTRUCTOR_POINT )
+        face = -1;
+
+      SMESH::PointStruct point;
+      point.x = myDlg->myX->GetValue();
+      point.y = myDlg->myY->GetValue();
+      point.z = myDlg->myZ->GetValue();
+
+      aMesh->SetParameters( aParameters.join(":").toLatin1().constData() );
 
-    aMesh->SetParameters( aParameters.join(":").toLatin1().constData() );
+      aResult = aMeshEditor->Reorient2D( myObject, direction, face, point );
+    }
 
-    int aResult = aMeshEditor->Reorient2D( myObject, direction, face, point );
     if (aResult)
     {
       SALOME_ListIO aList;
@@ -673,6 +746,27 @@ bool SMESHGUI_ReorientFacesOp::isValid( QString& msg )
     return false;
   }
 
+  // check volume object
+  if ( myDlg->myConstructorGrp->checkedId() == CONSTRUCTOR_VOLUME )
+  {
+    objectEntry = myDlg->selectedObject( EVolumes );
+    _PTR(SObject) pSObject = studyDS()->FindObjectID( objectEntry.toLatin1().data() );
+    myVolumeObj = SMESH::SObjectToInterface< SMESH::SMESH_IDSource>( pSObject );
+    if ( myVolumeObj->_is_nil() )
+    {
+      msg = tr("NO_VOLUME_OBJECT_SELECTED");
+      return false;
+    }
+    bool hasVolumes = false;
+    types = myVolumeObj->GetTypes();
+    for ( size_t i = 0; i < types->length() && !hasVolumes; ++i )
+      hasVolumes = ( types[i] == SMESH::VOLUME );
+    if ( !hasVolumes )
+    {
+      msg = tr("NO_VOLUMES");
+      return false;
+    }
+  }
   // check vector
   gp_Vec vec( myDlg->myDX->GetValue(),
               myDlg->myDY->GetValue(),
index 400850b89a176b4218f259aa2143d12210c7df74..e0908171b24a3a222f6c99d88555d9e4544eef7e 100644 (file)
 #include "SMESHGUI_SelectionOp.h"
 
 class QButtonGroup;
+class QCheckBox;
 class QLineEdit;
 class SMESHGUI_SpinBox;
 class SMESHGUI_ReorientFacesDlg;
 
 /*!
- * \brief Operation to reorient faces acoording to vector
+ * \brief Operation to reorient faces acoording to some criterion
  */
 class SMESHGUI_EXPORT SMESHGUI_ReorientFacesOp: public SMESHGUI_SelectionOp
 {
@@ -76,6 +77,7 @@ private:
   int                           mySelectionMode;
 
   SMESH::SMESH_IDSource_var     myObject;
+  SMESH::SMESH_IDSource_var     myVolumeObj;
 };
 
 /*!
@@ -98,6 +100,9 @@ private:
   QButtonGroup*                 myConstructorGrp;
   QFrame*                       myFaceFrm;
   QFrame*                       myPointFrm;
+  QFrame*                       myDirFrm;
+  QFrame*                       myVolumFrm;
+  QCheckBox*                    myOutsideChk;
   SMESHGUI_SpinBox*             myX;
   SMESHGUI_SpinBox*             myY;
   SMESHGUI_SpinBox*             myZ;
index 2cf9eaac2896dabd7d51b2b33f3dfeb360afb6c2..d5ec25ed4a7134897d7371269f4a5a69f47d7e8f 100644 (file)
@@ -184,6 +184,30 @@ SMESHGUI_EXPORT
   // type to use instead of SMESH_IDSource_var for automatic UnRegister()
   typedef SALOME::GenericObj_wrap<SMESH_IDSource> SMESH_IDSource_wrap;
 
+  /*!
+   * \brief Class usefull to convert a string returned from a CORBA call
+   *        to other string types w/o memory leak.
+   *
+   *        Usage (of instantiations): QString s = toQStr( objVar->GetName() );
+   *                              std::string ss = toStdStr( objVar->GetName() );
+   */
+  template < class _STRING >
+  class toStrT : public _STRING {
+    CORBA::String_var myStr;
+  public:
+    toStrT( char* s ): myStr(s), _STRING( s )
+    {}
+    operator const char*() const
+    { return myStr.in(); }
+  };
+  // Instantiations:
+  struct toQStr : public toStrT< QString > {
+    toQStr( char* s ): toStrT< QString >(s) {}
+  };
+  class toStdStr : public toStrT< std::string > {
+    toStdStr( char* s ): toStrT< std::string >(s) {}
+  };
+
 }
 
 #endif // SMESHGUI_UTILS_H
index b27b101ca169423f5e611ff3e73dccd66ccc0137..80c04e7d6fd1047f241b3789b710df71c7834d03 100644 (file)
             <source>ICON_HYPO_EDIT</source>
             <translation>mesh_hypo_edit.png</translation>
         </message>
+        <message>
+            <source>ICON_PLUS</source>
+            <translation>mesh_plus.png</translation>
+        </message>
+        <message>
+            <source>ICON_MINUS</source>
+            <translation>mesh_minus.png</translation>
+        </message>
         <message>
             <source>ICON_INTERSECT</source>
             <translation>mesh_intersectGroups.png</translation>
             <source>ICON_DLG_REORIENT2D_FACE</source>
             <translation>reorient_faces_face.png</translation>
         </message>
+        <message>
+            <source>ICON_DLG_REORIENT2D_VOLUME</source>
+            <translation>reorient_faces_volume.png</translation>
+        </message>
         <message>
             <source>ICON_REORIENT_2D</source>
             <translation>reorient_faces_face.png</translation>
index 9b9183530da1a056070cc4ad44172bab53de8b36..fcb37740a87ebffa4867964e67ebe982162ea641 100644 (file)
     </message>
     <message>
         <source>TOP_REORIENT_2D</source>
-        <translation>Reorient faces by vector</translation>
+        <translation>Reorient faces</translation>
     </message>
     <message>
         <source>MEN_REORIENT_2D</source>
-        <translation>Reorient faces by vector</translation>
+        <translation>Reorient faces</translation>
     </message>
     <message>
         <source>STB_REORIENT_2D</source>
-        <translation>Reorient faces by vector</translation>
+        <translation>Reorient faces</translation>
     </message>
     <message>
         <source>TOP_FIND_ELEM</source>
@@ -6775,7 +6775,7 @@ It is impossible to read point coordinates from file</translation>
     </message>
     <message>
         <source>GROUP_VOLUME_GROUPS</source>
-        <translation>Groups of volumes</translation>
+        <translation>Groups (faces or volumes)</translation>
     </message>
     <message>
         <source>CONSTRUCT_NEW_GROUP_NODES</source>
@@ -7656,7 +7656,7 @@ as they are of improper type:
     <name>SMESHGUI_ReorientFacesDlg</name>
     <message>
         <source>CAPTION</source>
-        <translation>Reorient faces by vector</translation>
+        <translation>Reorient faces</translation>
     </message>
     <message>
         <source>REORIENT_FACES</source>
@@ -7686,6 +7686,14 @@ as they are of improper type:
         <source>ORIENTATION</source>
         <translation>Orientation</translation>
     </message>
+    <message>
+        <source>VOLUMES</source>
+        <translation>Volumes</translation>
+    </message>
+    <message>
+        <source>OUTSIDE_VOLUME_NORMAL</source>
+        <translation>Face normal outside volume</translation>
+    </message>
 </context>
 <context>
     <name>SMESHGUI_ReorientFacesOp</name>
@@ -7693,10 +7701,18 @@ as they are of improper type:
         <source>NO_OBJECT_SELECTED</source>
         <translation>No object selected</translation>
     </message>
+    <message>
+        <source>NO_VOLUME_OBJECT_SELECTED</source>
+        <translation>No volume object selected</translation>
+    </message>
     <message>
         <source>NO_FACES</source>
         <translation>Object includes no faces</translation>
     </message>
+    <message>
+        <source>NO_VOLUMES</source>
+        <translation>Volume object includes no volumes</translation>
+    </message>
     <message>
         <source>ZERO_SIZE_VECTOR</source>
         <translation>Zero size vector</translation>
index d4b783654c5b71732b475015a3f470b0cb128e63..f20d819eb85d5e11397a1739dd2aab121e88526d 100755 (executable)
@@ -6745,6 +6745,10 @@ Il y a trop peu de points dans le fichier </translation>
         <source>GROUP_ELEMS_TO_REPLACE</source>
         <translation>Groupe des éléments dont les nœuds sont à remplacer</translation>
     </message>
+    <message>
+        <source>GROUP_VOLUME_GROUPS</source>
+        <translation>Groupes (faces ou volumes)</translation>
+    </message>
     <message>
         <source>CONSTRUCT_NEW_GROUP_NODES</source>
         <translation>Construire un groupe avec les nœuds nouvellement créés</translation>
index f06bd740bf8a97622fcdd0d3f8d495c58c4dd206..5d6e78d2025c33134a83f2e47c2fcfadc16d0e3f 100644 (file)
     </message>
     <message>
       <source>MEN_COMPUTE</source>
-      <translation>計算します。</translation>
+      <translation>メッシュを作成</translation>
     </message>
     <message>
       <source>MEN_PRECOMPUTE</source>
     </message>
     <message>
       <source>MEN_CONV_TO_QUAD</source>
-      <translation>2次要素の追加</translation>
+      <translation>2次/1次要素への変換</translation>
     </message>
     <message>
       <source>MEN_2D_FROM_3D</source>
     </message>
     <message>
       <source>SMESH_BUT_OVERWRITE</source>
-      <translation>書換え(&amp;w)</translation>
+      <translation>上書き(&amp;w)</translation>
     </message>
     <message>
       <source>SMESH_BUT_APPLY_AND_CLOSE</source>
     </message>
     <message>
       <source>STB_COMPUTE</source>
-      <translation>計算します。</translation>
+      <translation>メッシュを作成します。</translation>
     </message>
     <message>
       <source>STB_PRECOMPUTE</source>
     </message>
     <message>
       <source>TOP_COMPUTE</source>
-      <translation>計算します。</translation>
+      <translation>メッシュを作成</translation>
     </message>
     <message>
       <source>TOP_PRECOMPUTE</source>
     <name>SMESHGUI_ConvToQuadDlg</name>
     <message>
       <source>CAPTION</source>
-      <translation>2次要素の追加</translation>
+      <translation>2次/1次要素への変換</translation>
     </message>
     <message>
       <source>MEDIUMNDS</source>
index 472061d248ed18d71fab520344a49eb9a4fc3f6b..1b519201b4af6b5e487cedb78ae369d2881ad1ca 100644 (file)
@@ -1464,7 +1464,7 @@ int SMESH_Block::GetShapeIDByParams ( const gp_XYZ& theCoord )
 /*!
  * \brief Return number of wires and a list of oredered edges.
  *  \param theFace - the face to process
- *  \param theEdges - all ordered edges of theFace (outer edges goes first).
+ *  \param theEdges - all ordered edges of theFace (outer edges go first).
  *  \param theNbEdgesInWires - nb of edges (== nb of vertices in closed wire) in each wire
  *  \param theFirstVertex - the vertex of the outer wire to set first in the returned
  *         list ( theFirstVertex may be NULL )
index 68a86787040d6bc2325150be924db80a7bd1830b..b5e9965bb33585860a2bb7dfc37b6f502f553a29 100644 (file)
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-//  File   : SMESH_Hypothesis.hxx
+//  File   : SMESH_ComputeError.hxx
 //  Author : Edward AGAPOV (eap)
 //  Module : SMESH
 //
 #ifndef SMESH_ComputeError_HeaderFile
 #define SMESH_ComputeError_HeaderFile
 
+#include "SMESH_Utils.hxx"
+
 #include <string>
 #include <list>
 #include <boost/shared_ptr.hpp>
@@ -67,7 +69,7 @@ enum SMESH_ComputeErrorName
  */
 // =============================================================
 
-struct SMESH_ComputeError
+struct SMESHUtils_EXPORT SMESH_ComputeError
 {
   int               myName; //!< SMESH_ComputeErrorName or anything algo specific
   std::string       myComment;
@@ -89,32 +91,15 @@ struct SMESH_ComputeError
   bool IsKO()        const { return myName != COMPERR_OK && myName != COMPERR_WARNING; }
   bool IsCommon()    const { return myName < 0 && myName > COMPERR_LAST_ALGO_ERROR; }
   bool HasBadElems() const { return !myBadElements.empty(); }
-  inline std::string CommonName() const;
 
-};
+  // not inline methods are implemented in   src/SMESHUtils/SMESH_TryCatch.cxx
 
-#define _case2char(err) case err: return #err;
+  // Return myName as text, to be used to dump errors in terminal
+  std::string CommonName() const;
 
-// Return myName as text, to be used to dump errors in terminal
-std::string SMESH_ComputeError::CommonName() const
-{
-  switch( myName ) {
-  _case2char(COMPERR_OK              );
-  _case2char(COMPERR_BAD_INPUT_MESH  );
-  _case2char(COMPERR_STD_EXCEPTION   );
-  _case2char(COMPERR_OCC_EXCEPTION   );
-  _case2char(COMPERR_SLM_EXCEPTION   );
-  _case2char(COMPERR_EXCEPTION       );
-  _case2char(COMPERR_MEMORY_PB       );
-  _case2char(COMPERR_ALGO_FAILED     );
-  _case2char(COMPERR_BAD_SHAPE       );
-  _case2char(COMPERR_WARNING         );
-  _case2char(COMPERR_CANCELED        );
-  _case2char(COMPERR_NO_MESH_ON_SHAPE);
-  _case2char(COMPERR_BAD_PARMETERS   );
-  default:;
-  }
-  return "";
-}
+  // Return the most severe error
+  static SMESH_ComputeErrorPtr Worst( SMESH_ComputeErrorPtr er1,
+                                      SMESH_ComputeErrorPtr er2 );
+};
 
 #endif
index eaac4e60d0a9769e91ad9afc1e9012f84e21ee9b..0dd02ca13e185df64816016bc425571e4ce1a5d9 100644 (file)
@@ -20,6 +20,7 @@
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
+// ------------------------------------------------------------------
 #include "SMESH_TryCatch.hxx"
 
 void SMESH::throwSalomeEx(const char* txt)
@@ -31,4 +32,51 @@ void SMESH::doNothing(const char* txt)
 {
   MESSAGE( txt << " " << __FILE__ << ": " << __LINE__ );
 }
+// ------------------------------------------------------------------
+#include "SMESH_ComputeError.hxx"
 
+#define _case2char(err) case err: return #err;
+
+// Return SMESH_ComputeError::myName as text, to be used to dump errors in terminal
+std::string SMESH_ComputeError::CommonName() const
+{
+  switch( myName ) {
+  _case2char(COMPERR_OK              );
+  _case2char(COMPERR_BAD_INPUT_MESH  );
+  _case2char(COMPERR_STD_EXCEPTION   );
+  _case2char(COMPERR_OCC_EXCEPTION   );
+  _case2char(COMPERR_SLM_EXCEPTION   );
+  _case2char(COMPERR_EXCEPTION       );
+  _case2char(COMPERR_MEMORY_PB       );
+  _case2char(COMPERR_ALGO_FAILED     );
+  _case2char(COMPERR_BAD_SHAPE       );
+  _case2char(COMPERR_WARNING         );
+  _case2char(COMPERR_CANCELED        );
+  _case2char(COMPERR_NO_MESH_ON_SHAPE);
+  _case2char(COMPERR_BAD_PARMETERS   );
+  default:;
+  }
+  return "";
+}
+
+// Return the most severe error
+SMESH_ComputeErrorPtr SMESH_ComputeError::Worst( SMESH_ComputeErrorPtr er1,
+                                                 SMESH_ComputeErrorPtr er2 )
+{
+  if ( !er1 ) return er2;
+  if ( !er2 ) return er1;
+  // both not NULL
+  if ( er1->IsOK() ) return er2;
+  if ( er2->IsOK() ) return er1;
+  // both not OK
+  if ( !er1->IsKO() ) return er2;
+  if ( !er2->IsKO() ) return er1;
+  // both KO
+  bool hasInfo1 = er1->myComment.size() || !er1->myBadElements.empty();
+  bool hasInfo2 = er2->myComment.size() || !er2->myBadElements.empty();
+  if ( er1->myName == er2->myName ||
+       hasInfo1    != hasInfo2 )
+    return hasInfo1 < hasInfo2 ? er2 : er1;
+
+  return er1->myName == COMPERR_CANCELED ? er2 : er1;
+}
index 2d116bf9c1efeb317c0a27ae29b4c3b9f1134e89..9fec2e5bd7079b6199259052ce53b59584b4215c 100644 (file)
@@ -183,7 +183,6 @@ class SMDS_MeshElement;
 
 typedef const SMDS_MeshElement* SMDS_MeshElementPtr;
 
-DEFINE_BASECOLLECTION (SMESH_BaseCollectionElemPtr, SMDS_MeshElementPtr)
 DEFINE_SEQUENCE (SMESH_SequenceOfElemPtr, SMESH_BaseCollectionElemPtr, SMDS_MeshElementPtr)
 
 
@@ -191,7 +190,6 @@ DEFINE_SEQUENCE (SMESH_SequenceOfElemPtr, SMESH_BaseCollectionElemPtr, SMDS_Mesh
 // class SMESH_SequenceOfNode
 typedef const SMDS_MeshNode* SMDS_MeshNodePtr;
 
-DEFINE_BASECOLLECTION (SMESH_BaseCollectionNodePtr, SMDS_MeshNodePtr)
 DEFINE_SEQUENCE(SMESH_SequenceOfNode,
                 SMESH_BaseCollectionNodePtr, SMDS_MeshNodePtr)
 
index b7b5b5f0fcd8e35589fb3017531b78b390a0c8ae..564632744b8c4f7c98413b5235e91c2183c21ca2 100644 (file)
@@ -2369,7 +2369,7 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand)
       "AddNode","Add0DElement","AddEdge","AddFace","AddPolygonalFace","AddBall",
       "AddVolume","AddPolyhedralVolume","AddPolyhedralVolumeByFaces",
       "MoveNode", "MoveClosestNodeToPoint",
-      "InverseDiag","DeleteDiag","Reorient","ReorientObject",
+      "InverseDiag","DeleteDiag","Reorient","ReorientObject","Reorient2DBy3D",
       "TriToQuad","TriToQuadObject", "QuadTo4Tri", "SplitQuad","SplitQuadObject",
       "BestSplit","Smooth","SmoothObject","SmoothParametric","SmoothParametricObject",
       "ConvertToQuadratic","ConvertFromQuadratic","RenumberNodes","RenumberElements",
@@ -3163,23 +3163,28 @@ void _pyComplexParamHypo::Process( const Handle(_pyCommand)& theCommand)
 
 void _pyComplexParamHypo::Flush()
 {
+  list < Handle(_pyCommand) >::iterator cmd;
   if ( IsWrapped() )
   {
-    list < Handle(_pyCommand) >::iterator cmd = myUnusedCommands.begin();
-    for ( ; cmd != myUnusedCommands.end(); ++cmd )
+    for ( cmd = myUnusedCommands.begin(); cmd != myUnusedCommands.end(); ++cmd )
       if ((*cmd)->GetMethod() == "SetObjectEntry" )
         (*cmd)->Clear();
-
-    if ( GetAlgoType() == "Cartesian_3D" )
-    {
-      _pyID algo = myCreationCmd->GetObject();
-      for ( cmd = myProcessedCmds.begin(); cmd != myProcessedCmds.end(); ++cmd )
-      {
-        StructToList( *cmd, /*checkMethod=*/false );
-        (*cmd)->SetObject( algo );
-      }
-    }
   }
+
+  // if ( GetAlgoType() == "Cartesian_3D" )
+  // {
+  //   _pyID algo = myCreationCmd->GetObject();
+  //   for ( cmd = myProcessedCmds.begin(); cmd != myProcessedCmds.end(); ++cmd )
+  //   {
+  //     if ( IsWrapped() )
+  //     {
+  //       StructToList( *cmd, /*checkMethod=*/false );
+  //       const _AString & method = (*cmd)->GetMethod();
+  //       if ( method == "SetFixedPoint" )
+  //         (*cmd)->SetObject( algo );
+  //     }
+  //   }
+  // }
 }
 
 //================================================================================
index 494722b8aee4837c73bfe0e7c9939e93aede4662..4289342dc1b83065d3918c7a358e7ab42a9ff9ea 100644 (file)
@@ -1209,6 +1209,7 @@ TCollection_AsciiString SMESH_Gen_i::DumpPython_impl
     if ( theNames.IsBound( anEntry ))
     {
       aGUIName = theNames.Find(anEntry);
+      aGUIName.RemoveAll('\''); // remove a quote from a name (issue 22360)
       setNamePart += nt + aSMESHGen + ".SetName(" + aName;
       if ( anEntry2AccessorMethod.IsBound( anEntry ) )
         setNamePart += helper + "." + anEntry2AccessorMethod( anEntry );
index 351a0f2683985d994b98e9231bd16631cf407dcd..0293f51a3a6889e011931c5ff38b81e7f6f8c9b9 100644 (file)
@@ -267,6 +267,7 @@ SMESH::Histogram* NumericalFunctor_i::GetLocalHistogram(CORBA::Short
        SMESH::DownCast< SMESH::Filter_i* >( object ))
   {
     elemIt = SMESH_Mesh_i::GetElements( object, GetElementType() );
+    if ( !elemIt ) return histogram._retn();
   }
   else
   {
@@ -3019,6 +3020,7 @@ CORBA::Boolean Filter_i::SetCriteria( const SMESH::Filter::Criteria& theCriteria
 
   SMESH::Predicate_ptr aPrevPredicate = SMESH::Predicate::_nil();
   int aPrevBinary = SMESH::FT_Undefined;
+  aBinaries.back() = SMESH::FT_Undefined;
 
   for ( aPredIter = aPredicates.begin(), aBinaryIter = aBinaries.begin();
         aPredIter != aPredicates.end() && aBinaryIter != aBinaries.end();
index a42b136d8bc2452ca0c42400d6fd619091dbfa01..b822651b7ee853da1a91cc152f911fc9fba7eb3a 100644 (file)
@@ -280,7 +280,7 @@ SMESH_Gen_i::SMESH_Gen_i( CORBA::ORB_ptr            orb,
                           PortableServer::ObjectId* contId,
                           const char*               instanceName,
                           const char*               interfaceName )
-     : Engines_Component_i( orb, poa, contId, instanceName, interfaceName )
+  : Engines_Component_i( orb, poa, contId, instanceName, interfaceName )
 {
   MESSAGE( "SMESH_Gen_i::SMESH_Gen_i : standard constructor" );
 
@@ -472,7 +472,7 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::createHypothesis(const char* theHypName
   // create a new hypothesis object, store its ref. in studyContext
   if(MYDEBUG) MESSAGE("Create Hypothesis " << theHypName);
   myHypothesis_i =
-      myHypCreatorMap[string(theHypName)]->Create(myPoa, GetCurrentStudyID(), &myGen);
+    myHypCreatorMap[string(theHypName)]->Create(myPoa, GetCurrentStudyID(), &myGen);
   myHypothesis_i->SetLibName(aPlatformLibName.c_str()); // for persistency assurance
 
   if (!myHypothesis_i)
@@ -495,7 +495,7 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::createHypothesis(const char* theHypName
  */
 //=============================================================================
 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::createMesh()
-     throw ( SALOME::SALOME_Exception )
+  throw ( SALOME::SALOME_Exception )
 {
   Unexpect aCatch(SALOME_SalomeException);
   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::createMesh" );
@@ -673,7 +673,7 @@ SALOMEDS::Study_ptr SMESH_Gen_i::GetCurrentStudy()
 StudyContext* SMESH_Gen_i::GetCurrentStudyContext()
 {
   if ( !CORBA::is_nil( myCurrentStudy ) &&
-      myStudyContextMap.find( GetCurrentStudyID() ) != myStudyContextMap.end() )
+       myStudyContextMap.find( GetCurrentStudyID() ) != myStudyContextMap.end() )
     return myStudyContextMap[ myCurrentStudy->StudyId() ];
   else
     return 0;
@@ -689,7 +689,7 @@ StudyContext* SMESH_Gen_i::GetCurrentStudyContext()
 
 SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::CreateHypothesis( const char* theHypName,
                                                            const char* theLibName )
-     throw ( SALOME::SALOME_Exception )
+  throw ( SALOME::SALOME_Exception )
 {
   Unexpect aCatch(SALOME_SalomeException);
   // Create hypothesis/algorithm
@@ -803,6 +803,97 @@ SMESH_Gen_i::GetHypothesisParameterValues (const char*           theHypType,
   return SMESH::SMESH_Hypothesis::_nil();
 }
 
+//=============================================================================
+/*!
+ * Returns \c True if a hypothesis is assigned to a sole sub-mesh in a current Study
+ *  \param [in] theHyp - the hypothesis of interest
+ *  \param [out] theMesh - the sole mesh using \a theHyp
+ *  \param [out] theShape - the sole geometry \a theHyp is assigned to
+ *  \return boolean - \c True if \a theMesh and \a theShape are sole using \a theHyp
+ *
+ * If two meshes on same shape have theHyp assigned to the same sub-shape, they are
+ * considered as SAME sub-mesh => result is \c true.
+ * This method ids used to initialize SMESHGUI_GenericHypothesisCreator with
+ * a shape to which an hyp being edited is assigned.
+ */
+//=============================================================================
+
+CORBA::Boolean SMESH_Gen_i::GetSoleSubMeshUsingHyp( SMESH::SMESH_Hypothesis_ptr theHyp,
+                                                    SMESH::SMESH_Mesh_out       theMesh,
+                                                    GEOM::GEOM_Object_out       theShape)
+{
+  if ( GetCurrentStudyID() < 0 || CORBA::is_nil( theHyp ))
+    return false;
+
+  // get Mesh component SO
+  CORBA::String_var compDataType = ComponentDataType();
+  SALOMEDS::SComponent_wrap comp = myCurrentStudy->FindComponent( compDataType.in() );
+  if ( CORBA::is_nil( comp ))
+    return false;
+
+  // look for child SO of meshes
+  SMESH::SMESH_Mesh_var foundMesh;
+  TopoDS_Shape          foundShape;
+  bool                  isSole = true;
+  SALOMEDS::ChildIterator_wrap meshIter = myCurrentStudy->NewChildIterator( comp );
+  for ( ; meshIter->More() && isSole; meshIter->Next() )
+  {
+    SALOMEDS::SObject_wrap curSO = meshIter->Value();
+    CORBA::Object_var        obj = SObjectToObject( curSO );
+    SMESH_Mesh_i*         mesh_i = SMESH::DownCast< SMESH_Mesh_i* >( obj );
+    if ( ! mesh_i )
+      continue;
+
+    // look for a sole shape where theHyp is assigned
+    bool isHypFound = false;
+    const ShapeToHypothesis & s2hyps = mesh_i->GetImpl().GetMeshDS()->GetHypotheses();
+    ShapeToHypothesis::Iterator s2hypsIt( s2hyps );
+    for ( ; s2hypsIt.More() && isSole; s2hypsIt.Next() )
+    {
+      const THypList& hyps = s2hypsIt.Value();
+      THypList::const_iterator h = hyps.begin();
+      for ( ; h != hyps.end(); ++h )
+        if ( (*h)->GetID() == theHyp->GetId() )
+          break;
+      if ( h != hyps.end()) // theHyp found
+      {
+        isHypFound = true;
+        if ( ! foundShape.IsNull() &&
+             ! foundShape.IsSame( s2hypsIt.Key() )) // not a sole sub-shape
+        {
+          foundShape.Nullify();
+          isSole = false;
+          break;
+        }
+        foundShape = s2hypsIt.Key();
+      }
+    } // loop on assigned hyps
+
+    if ( isHypFound && !foundShape.IsNull() ) // a mesh using theHyp is found
+    {
+      if ( !foundMesh->_is_nil() ) // not a sole mesh
+      {
+        GEOM::GEOM_Object_var s1 = mesh_i   ->GetShapeToMesh();
+        GEOM::GEOM_Object_var s2 = foundMesh->GetShapeToMesh();
+        if ( ! ( isSole = s1->IsSame( s2 )))
+          break;
+      }
+      foundMesh = SMESH::SMESH_Mesh::_narrow( obj );
+    }
+
+  } // loop on meshes
+
+  if ( isSole &&
+       ! foundMesh->_is_nil() &&
+       ! foundShape.IsNull() )
+  {
+    theMesh  = foundMesh._retn();
+    theShape = ShapeToGeomObject( foundShape );
+    return ( !theMesh->_is_nil() && !theShape->_is_nil() );
+  }
+  return false;
+}
+
 //=============================================================================
 /*!
  * Sets number of segments per diagonal of boundary box of geometry by which
@@ -1460,8 +1551,11 @@ SMESH::compute_error_array* SMESH_Gen_i::GetComputeErrors( SMESH::SMESH_Mesh_ptr
         // if ( sm->GetSubShape().ShapeType() == TopAbs_VERTEX )
         //   break;
         SMESH_ComputeErrorPtr error = sm->GetComputeError();
-        if ( error && !error->IsOK() && error->myAlgo )
+        if ( error && !error->IsOK() )
         {
+          if ( !( error->myAlgo ) &&
+               !( error->myAlgo = sm->GetAlgo() ))
+            continue;
           SMESH::ComputeError & errStruct = error_array[ nbErr++ ];
           errStruct.code       = -( error->myName < 0 ? error->myName + 1: error->myName ); // -1 -> 0
           errStruct.comment    = error->myComment.c_str();
@@ -3693,7 +3787,8 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                 myLocMesh.ShapeToMesh( nullShape ); // remove shape referring data
               }
 
-              if ( !mySMESHDSMesh->SubMeshes().empty() )
+              SMESHDS_SubMeshIteratorPtr smIt = mySMESHDSMesh->SubMeshes();
+              if ( smIt->more() )
               {
                 // Store submeshes
                 // ----------------
@@ -3703,52 +3798,9 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                 // each element belongs to one or none submesh,
                 // so for each node/element, we store a submesh ID
 
-                // Make maps of submesh IDs of elements sorted by element IDs
-                // typedef int TElemID;
-                // typedef int TSubMID;
-                // map< TElemID, TSubMID > eId2smId, nId2smId;
-                const map<int,SMESHDS_SubMesh*>& aSubMeshes = mySMESHDSMesh->SubMeshes();
-                map<int,SMESHDS_SubMesh*>::const_iterator itSubM ( aSubMeshes.begin() );
-                // SMDS_NodeIteratorPtr itNode;
-                // SMDS_ElemIteratorPtr itElem;
-                // for ( itSubM = aSubMeshes.begin(); itSubM != aSubMeshes.end() ; itSubM++ )
-                // {
-                //   TSubMID          aSubMeID = itSubM->first;
-                //   SMESHDS_SubMesh* aSubMesh = itSubM->second;
-                //   if ( aSubMesh->IsComplexSubmesh() )
-                //     continue; // sub-mesh containing other sub-meshes
-                //   // nodes
-                //   for ( itNode = aSubMesh->GetNodes(); itNode->more(); ++hint)
-                //     nId2smId.insert( nId2smId.back(), make_pair( itNode->next()->GetID(), aSubMeID ));
-                //   // elements
-                //   for ( itElem = aSubMesh->GetElements(); itElem->more(); ++hint)
-                //     hint = eId2smId.insert( eId2smId.back(), make_pair( itElem->next()->GetID(), aSubMeID ));
-                // }
-
-                // // Care of elements that are not on submeshes
-                // if ( mySMESHDSMesh->NbNodes() != nId2smId.size() ) {
-                //   for ( itNode = mySMESHDSMesh->nodesIterator(); itNode->more(); )
-                //     /*  --- stl_map.h says : */
-                //     /*  A %map relies on unique keys and thus a %pair is only inserted if its */
-                //     /*  first element (the key) is not already present in the %map.           */
-                //     nId2smId.insert( make_pair( itNode->next()->GetID(), 0 ));
-                // }
-                // int nbElems = mySMESHDSMesh->GetMeshInfo().NbElements();
-                // if ( nbElems != eId2smId.size() ) {
-                //   for ( itElem = mySMESHDSMesh->elementsIterator(); itElem->more(); )
-                //     eId2smId.insert( make_pair( itElem->next()->GetID(), 0 ));
-                // }
-
                 // Store submesh IDs
                 for ( int isNode = 0; isNode < 2; ++isNode )
                 {
-                  // map< TElemID, TSubMID >& id2smId = isNode ? nId2smId : eId2smId;
-                  // if ( id2smId.empty() ) continue;
-                  // map< TElemID, TSubMID >::const_iterator id_smId = id2smId.begin();
-                  // // make and fill array of submesh IDs
-                  // int* smIDs = new int [ id2smId.size() ];
-                  // for ( int i = 0; id_smId != id2smId.end(); ++id_smId, ++i )
-                  //   smIDs[ i ] = id_smId->second;
                   SMDS_ElemIteratorPtr eIt =
                     mySMESHDSMesh->elementsIterator( isNode ? SMDSAbs_Node : SMDSAbs_All );
                   int nbElems = isNode ? mySMESHDSMesh->NbNodes() : mySMESHDSMesh->GetMeshInfo().NbElements();
@@ -3787,15 +3839,15 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                 int nbEdgeNodes = 0, nbFaceNodes = 0;
                 list<SMESHDS_SubMesh*> aEdgeSM, aFaceSM;
                 // loop on SMESHDS_SubMesh'es
-                for ( itSubM = aSubMeshes.begin(); itSubM != aSubMeshes.end() ; itSubM++ )
+                while ( smIt->more() )
                 {
-                  SMESHDS_SubMesh* aSubMesh = (*itSubM).second;
+                  SMESHDS_SubMesh* aSubMesh = const_cast< SMESHDS_SubMesh* >( smIt->next() );
                   if ( aSubMesh->IsComplexSubmesh() )
                     continue; // submesh containing other submeshs
                   int nbNodes = aSubMesh->NbNodes();
                   if ( nbNodes == 0 ) continue;
 
-                  int aShapeID = (*itSubM).first;
+                  int aShapeID = aSubMesh->GetID();
                   if ( aShapeID < 1 || aShapeID > mySMESHDSMesh->MaxShapeIndex() )
                     continue;
                   int aShapeType = mySMESHDSMesh->IndexToShape( aShapeID ).ShapeType();
@@ -5101,10 +5153,18 @@ void SMESH_Gen_i::Move( const SMESH::sobject_list& what,
       useCaseBuilder->AppendTo( where, sobj );        // append to the end of list
   }
 }
-//=================================================================================
-// function : IsApplicable
-// purpose  : Return true if algorithm can be applied
-//=================================================================================
+//================================================================================
+/*!
+ * \brief Returns true if algorithm can be used to mesh a given geometry
+ *  \param [in] theAlgoType - the algorithm type
+ *  \param [in] theLibName - a name of the Plug-in library implementing the algorithm
+ *  \param [in] theGeomObject - the geometry to mesh
+ *  \param [in] toCheckAll - if \c True, returns \c True if all shapes are meshable,
+ *         else, returns \c True if at least one shape is meshable
+ *  \return CORBA::Boolean - can or can't
+ */
+//================================================================================
+
 CORBA::Boolean SMESH_Gen_i::IsApplicable ( const char*           theAlgoType,
                                            const char*           theLibName,
                                            GEOM::GEOM_Object_ptr theGeomObject,
@@ -5114,7 +5174,8 @@ CORBA::Boolean SMESH_Gen_i::IsApplicable ( const char*           theAlgoType,
 
   std::string aPlatformLibName;
   typedef GenericHypothesisCreator_i* (*GetHypothesisCreator)(const char*);
-  GenericHypothesisCreator_i* aCreator = getHypothesisCreator(theAlgoType, theLibName, aPlatformLibName);
+  GenericHypothesisCreator_i* aCreator =
+    getHypothesisCreator(theAlgoType, theLibName, aPlatformLibName);
   if (aCreator)
   {
     TopoDS_Shape shape = GeomObjectToShape( theGeomObject );
index 3405a83750840b9a68b6f6f72bec51f53d7b5671..ba4ed98b54d82430bb766ba2ce18efe56e74a8f1 100644 (file)
@@ -205,6 +205,13 @@ public:
                                                             CORBA::Boolean        byMesh)
     throw ( SALOME::SALOME_Exception );
 
+  /*
+   * Returns True if a hypothesis is assigned to a sole sub-mesh in a current Study
+   */
+  CORBA::Boolean GetSoleSubMeshUsingHyp( SMESH::SMESH_Hypothesis_ptr theHyp,
+                                         SMESH::SMESH_Mesh_out       theMesh,
+                                         GEOM::GEOM_Object_out       theShape);
+
   // Preferences
   // ------------
   /*!
index ebdd1052c2e599827517a3f5788f01985711aab8..d55846adebfc7455bb74af7b3ca29083cb5a9b42 100644 (file)
@@ -774,6 +774,9 @@ SMESH_PredicatePtr SMESH_GroupOnFilter_i::GetPredicate( SMESH::Filter_ptr filter
 
 void SMESH_GroupOnFilter_i::SetFilter(SMESH::Filter_ptr theFilter)
 {
+  if ( myFilter->_is_equivalent( theFilter ))
+    return;
+
   if ( myPreMeshInfo )
     myPreMeshInfo->FullLoadFromFile();
 
index 9de57c975706a25fbf79216219c01df44de7816e..c54b068cfec6e98d108d6b8001e9c8e626a4c0d3 100644 (file)
@@ -307,33 +307,56 @@ namespace MeshEditor_I {
    */
   //================================================================================
 
+  enum IDSource_Error { IDSource_OK, IDSource_INVALID, IDSource_EMPTY };
+
   bool idSourceToSet(SMESH::SMESH_IDSource_ptr  theIDSource,
                      const SMESHDS_Mesh*        theMeshDS,
                      TIDSortedElemSet&          theElemSet,
                      const SMDSAbs_ElementType  theType,
-                     const bool                 emptyIfIsMesh=false)
+                     const bool                 emptyIfIsMesh = false,
+                     IDSource_Error*            error = 0)
 
   {
+    if ( error ) *error = IDSource_OK;
+
     if ( CORBA::is_nil( theIDSource ) )
+    {
+      if ( error ) *error = IDSource_INVALID;
       return false;
+    }
     if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
+    {
+      if ( error && theMeshDS->GetMeshInfo().NbElements( theType ) == 0 )
+        *error = IDSource_EMPTY;
       return true;
-
+    }
     SMESH::long_array_var anIDs = theIDSource->GetIDs();
     if ( anIDs->length() == 0 )
+    {
+      if ( error ) *error = IDSource_EMPTY;
       return false;
+    }
     SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
     if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
     {
       if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
+      {
         arrayToSet( anIDs, theMeshDS, theElemSet, SMDSAbs_Node );
+      }
       else
+      {
+        if ( error ) *error = IDSource_INVALID;
         return false;
+      }
     }
     else
     {
       arrayToSet( anIDs, theMeshDS, theElemSet, theType);
-      return bool(anIDs->length()) == bool(theElemSet.size());
+      if ( bool(anIDs->length()) != bool(theElemSet.size()))
+      {
+        if ( error ) *error = IDSource_INVALID;
+        return false;
+      }
     }
     return true;
   }
@@ -1644,7 +1667,11 @@ CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
 
   TIDSortedElemSet elements;
   prepareIdSource( the2Dgroup );
-  if ( !idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1))
+  IDSource_Error error;
+  idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
+  if ( error == IDSource_EMPTY )
+    return 0;
+  if ( error == IDSource_INVALID )
     THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
 
 
@@ -1710,6 +1737,58 @@ CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
   return 0;
 }
 
+//=======================================================================
+//function : Reorient2DBy3D
+//purpose  : Reorient faces basing on orientation of adjacent volumes.
+//=======================================================================
+
+CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
+                                               SMESH::SMESH_IDSource_ptr     volumeGroup,
+                                               CORBA::Boolean                outsideNormal)
+  throw (SALOME::SALOME_Exception)
+{
+  SMESH_TRY;
+  initData();
+
+  TIDSortedElemSet volumes;
+  prepareIdSource( volumeGroup );
+  IDSource_Error volsError;
+  idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
+
+  int nbReori = 0;
+  for ( size_t i = 0; i < faceGroups.length(); ++i )
+  {
+    SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
+    prepareIdSource( faceGrp );
+
+    TIDSortedElemSet faces;
+    IDSource_Error error;
+    idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
+    if ( error == IDSource_INVALID && faceGroups.length() == 1 )
+      THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
+    if ( error == IDSource_OK && volsError != IDSource_OK )
+      THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
+
+    nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
+
+    if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
+      break;
+  }
+
+  if ( nbReori ) {
+    declareMeshModified( /*isReComputeSafe=*/false );
+  }
+  TPythonDump() << this << ".Reorient2DBy3D( "
+                << faceGroups << ", "
+                << volumeGroup << ", "
+                << outsideNormal << " )";
+
+  return nbReori;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
+}
+
 //=============================================================================
 /*!
  * \brief Fuse neighbour triangles into quadrangles.
index ead3048b05607721d39a334cef77fd3b6c75c736..bce7c4c4c4c291ca722a823ed11ea2b0033537f2 100644 (file)
@@ -203,6 +203,18 @@ public:
                          const SMESH::DirStruct&   theDirection,
                          CORBA::Long               theFace,
                          const SMESH::PointStruct& thePoint) throw (SALOME::SALOME_Exception);
+  /*!
+   * \brief Reorient faces basing on orientation of adjacent volumes.
+   * \param faces - a list of objects containing face to reorient
+   * \param volumes - an object containing volumes.
+   * \param outsideNormal - to orient faces to have their normal
+   *        pointing either \a outside or \a inside the adjacent volumes.
+   * \return number of reoriented faces.
+   */
+  CORBA::Long Reorient2DBy3D(const SMESH::ListOfIDSources & faces,
+                             SMESH::SMESH_IDSource_ptr      volumes,
+                             CORBA::Boolean                 outsideNormal)
+    throw (SALOME::SALOME_Exception);
 
   // Split/Join faces
   CORBA::Boolean TriToQuad       (const SMESH::long_array &   IDsOfElements,
index 3177257588f320f02b9b3692ead6e8e7d2e90f26..a5ed1ac3cc05f09eda82048861185dcef174f648 100644 (file)
@@ -549,6 +549,7 @@ SMESH::Hypothesis_Status SMESH_Mesh_i::ConvertHypothesisStatus
   RETURNCASE( HYP_BAD_SUBSHAPE  );
   RETURNCASE( HYP_BAD_GEOMETRY  );
   RETURNCASE( HYP_NEED_SHAPE    );
+  RETURNCASE( HYP_INCOMPAT_HYPS );
   default:;
   }
   return SMESH::HYP_UNKNOWN_FATAL;
@@ -564,33 +565,31 @@ SMESH::Hypothesis_Status SMESH_Mesh_i::ConvertHypothesisStatus
  */
 //=============================================================================
 
-SMESH::Hypothesis_Status SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
-                                                     SMESH::SMESH_Hypothesis_ptr anHyp)
+SMESH::Hypothesis_Status
+SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr       aSubShape,
+                            SMESH::SMESH_Hypothesis_ptr anHyp,
+                            CORBA::String_out           anErrorText)
   throw(SALOME::SALOME_Exception)
 {
   Unexpect aCatch(SALOME_SalomeException);
   if ( _preMeshInfo )
     _preMeshInfo->ForgetOrLoad();
 
-  SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShapeObject, anHyp );
+  std::string error;
+  SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShape, anHyp, &error );
+  anErrorText = error.c_str();
 
   SMESH::SMESH_Mesh_var mesh( _this() );
   if ( !SMESH_Hypothesis::IsStatusFatal(status) )
   {
     SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
-    _gen_i->AddHypothesisToShape( study, mesh, aSubShapeObject, anHyp );
+    _gen_i->AddHypothesisToShape( study, mesh, aSubShape, anHyp );
   }
   if(MYDEBUG) MESSAGE( " AddHypothesis(): status = " << status );
 
   // Update Python script
-  //if(_impl->HasShapeToMesh())
-  {
-    TPythonDump() << "status = " << mesh << ".AddHypothesis( "
-                  << aSubShapeObject << ", " << anHyp << " )";
-  }
-  // else {
-  //   TPythonDump() << "status = " << mesh << ".AddHypothesis( "<< anHyp << " )";
-  // }
+  TPythonDump() << "status = " << mesh << ".AddHypothesis( "
+                << aSubShape << ", " << anHyp << " )";
 
   return ConvertHypothesisStatus(status);
 }
@@ -602,12 +601,13 @@ SMESH::Hypothesis_Status SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr
 //=============================================================================
 
 SMESH_Hypothesis::Hypothesis_Status
-SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
-                            SMESH::SMESH_Hypothesis_ptr anHyp)
+SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr       aSubShape,
+                            SMESH::SMESH_Hypothesis_ptr anHyp,
+                            std::string*                anErrorText)
 {
   if(MYDEBUG) MESSAGE("addHypothesis");
 
-  if (CORBA::is_nil( aSubShapeObject ) && HasShapeToMesh())
+  if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference",SALOME::BAD_PARAM);
 
   if (CORBA::is_nil( anHyp ))
@@ -619,22 +619,28 @@ SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
     TopoDS_Shape myLocSubShape;
     //use PseudoShape in case if mesh has no shape
     if(HasShapeToMesh())
-      myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject);
+      myLocSubShape = _gen_i->GeomObjectToShape( aSubShape);
     else              
       myLocSubShape = _impl->GetShapeToMesh();
     
     const int hypId = anHyp->GetId();
-    status = _impl->AddHypothesis(myLocSubShape, hypId);
-    if ( !SMESH_Hypothesis::IsStatusFatal(status) ) {
+    std::string error;
+    status = _impl->AddHypothesis( myLocSubShape, hypId, &error );
+    if ( !SMESH_Hypothesis::IsStatusFatal(status) )
+    {
       _mapHypo[hypId] = SMESH::SMESH_Hypothesis::_duplicate( anHyp );
       anHyp->Register();
       // assure there is a corresponding submesh
       if ( !_impl->IsMainShape( myLocSubShape )) {
         int shapeId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
         if ( _mapSubMesh_i.find( shapeId ) == _mapSubMesh_i.end() )
-          SMESH::SMESH_subMesh_var( createSubMesh( aSubShapeObject ));
+          SMESH::SMESH_subMesh_var( createSubMesh( aSubShape ));
       }
     }
+    else if ( anErrorText )
+    {
+      *anErrorText = error;
+    }
   }
   catch(SALOME_Exception & S_ex)
   {
@@ -649,7 +655,7 @@ SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
  */
 //=============================================================================
 
-SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
+SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShape,
                                                         SMESH::SMESH_Hypothesis_ptr anHyp)
   throw(SALOME::SALOME_Exception)
 {
@@ -657,18 +663,18 @@ SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aS
   if ( _preMeshInfo )
     _preMeshInfo->ForgetOrLoad();
 
-  SMESH_Hypothesis::Hypothesis_Status status = removeHypothesis( aSubShapeObject, anHyp );
+  SMESH_Hypothesis::Hypothesis_Status status = removeHypothesis( aSubShape, anHyp );
   SMESH::SMESH_Mesh_var mesh = _this();
 
   if ( !SMESH_Hypothesis::IsStatusFatal(status) )
   {
     SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
-    _gen_i->RemoveHypothesisFromShape( study, mesh, aSubShapeObject, anHyp );
+    _gen_i->RemoveHypothesisFromShape( study, mesh, aSubShape, anHyp );
   }
   // Update Python script
   if(_impl->HasShapeToMesh())
     TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
-                  << aSubShapeObject << ", " << anHyp << " )";
+                  << aSubShape << ", " << anHyp << " )";
   else
     TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
                   << anHyp << " )";
@@ -683,12 +689,12 @@ SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aS
 //=============================================================================
 
 SMESH_Hypothesis::Hypothesis_Status
-SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
+SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr       aSubShape,
                                SMESH::SMESH_Hypothesis_ptr anHyp)
 {
   if(MYDEBUG) MESSAGE("removeHypothesis()");
 
-  if (CORBA::is_nil( aSubShapeObject ) && HasShapeToMesh())
+  if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
 
   if (CORBA::is_nil( anHyp ))
@@ -700,7 +706,7 @@ SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
     TopoDS_Shape myLocSubShape;
     //use PseudoShape in case if mesh has no shape
     if( _impl->HasShapeToMesh() )
-      myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject );
+      myLocSubShape = _gen_i->GeomObjectToShape( aSubShape );
     else
       myLocSubShape = _impl->GetShapeToMesh();
 
@@ -726,18 +732,18 @@ SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
 //=============================================================================
 
 SMESH::ListOfHypothesis *
-SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShapeObject)
+SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShape)
 throw(SALOME::SALOME_Exception)
 {
   Unexpect aCatch(SALOME_SalomeException);
   if (MYDEBUG) MESSAGE("GetHypothesisList");
-  if (_impl->HasShapeToMesh() && CORBA::is_nil(aSubShapeObject))
+  if (_impl->HasShapeToMesh() && CORBA::is_nil(aSubShape))
     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
 
   SMESH::ListOfHypothesis_var aList = new SMESH::ListOfHypothesis();
 
   try {
-    TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject);
+    TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShape);
     if ( myLocSubShape.IsNull() && !_impl->HasShapeToMesh() )
       myLocSubShape = _impl->GetShapeToMesh();
     const list<const SMESHDS_Hypothesis*>& aLocalList = _impl->GetHypothesisList( myLocSubShape );
@@ -803,18 +809,18 @@ SMESH::submesh_array* SMESH_Mesh_i::GetSubMeshes() throw (SALOME::SALOME_Excepti
  */
 //=============================================================================
 
-SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShapeObject,
+SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShape,
                                                   const char*           theName )
      throw(SALOME::SALOME_Exception)
 {
   Unexpect aCatch(SALOME_SalomeException);
-  if (CORBA::is_nil(aSubShapeObject))
+  if (CORBA::is_nil(aSubShape))
     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
 
   SMESH::SMESH_subMesh_var subMesh;
   SMESH::SMESH_Mesh_var    aMesh = _this();
   try {
-    TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject);
+    TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShape);
 
     //Get or Create the SMESH_subMesh object implementation
 
@@ -830,16 +836,16 @@ SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShap
 
     // create a new subMesh object servant if there is none for the shape
     if ( subMesh->_is_nil() )
-      subMesh = createSubMesh( aSubShapeObject );
+      subMesh = createSubMesh( aSubShape );
     if ( _gen_i->CanPublishInStudy( subMesh ))
     {
       SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
       SALOMEDS::SObject_wrap aSO =
-        _gen_i->PublishSubMesh( study, aMesh, subMesh, aSubShapeObject, theName );
+        _gen_i->PublishSubMesh( study, aMesh, subMesh, aSubShape, theName );
       if ( !aSO->_is_nil()) {
         // Update Python script
         TPythonDump() << aSO << " = " << aMesh << ".GetSubMesh( "
-                      << aSubShapeObject << ", '" << theName << "' )";
+                      << aSubShape << ", '" << theName << "' )";
       }
     }
   }
@@ -863,7 +869,7 @@ void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
   if ( theSubMesh->_is_nil() )
     return;
 
-  GEOM::GEOM_Object_var aSubShapeObject;
+  GEOM::GEOM_Object_var aSubShape;
   SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
   if ( !aStudy->_is_nil() )  {
     // Remove submesh's SObject
@@ -875,10 +881,10 @@ void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
            anObj->ReferencedObject( aRef.inout() ))
       {
         CORBA::Object_var obj = aRef->GetObject();
-        aSubShapeObject = GEOM::GEOM_Object::_narrow( obj );
+        aSubShape = GEOM::GEOM_Object::_narrow( obj );
       }
-      // if ( aSubShapeObject->_is_nil() ) // not published shape (IPAL13617)
-      //   aSubShapeObject = theSubMesh->GetSubShape();
+      // if ( aSubShape->_is_nil() ) // not published shape (IPAL13617)
+      //   aSubShape = theSubMesh->GetSubShape();
 
       SALOMEDS::StudyBuilder_var builder = aStudy->NewBuilder();
       builder->RemoveObjectWithChildren( anSO );
@@ -888,7 +894,7 @@ void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
     }
   }
 
-  if ( removeSubMesh( theSubMesh, aSubShapeObject.in() ))
+  if ( removeSubMesh( theSubMesh, aSubShape.in() ))
     if ( _preMeshInfo )
       _preMeshInfo->ForgetOrLoad();
 
@@ -1547,7 +1553,7 @@ SMESH_Mesh_i::CutListOfGroups(const SMESH::ListOfGroups& theMainGroups,
 
   // Update Python script
   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this() )
-         << ".CutListOfGroups( " << theMainGroups
+         << ".CutListOfGroups( " << theMainGroups << ", "
          << theToolGroups << ", '" << theName << "' )";
 
   SMESH_CATCH( SMESH::throwCorbaException );
index cd9a7a9166388121dc1a630f64fef47988f8102e..e4c1b634a93defe52ba8eaf37db6d731178ff546 100644 (file)
@@ -86,21 +86,22 @@ public:
   void ClearSubMesh(CORBA::Long ShapeID)
     throw (SALOME::SALOME_Exception);
 
-  SMESH::Hypothesis_Status AddHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
-                                         SMESH::SMESH_Hypothesis_ptr anHyp)
+  SMESH::Hypothesis_Status AddHypothesis(GEOM::GEOM_Object_ptr       aSubShape,
+                                         SMESH::SMESH_Hypothesis_ptr anHyp,
+                                         CORBA::String_out           anErrorText)
     throw (SALOME::SALOME_Exception);
 
-  SMESH::Hypothesis_Status RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
+  SMESH::Hypothesis_Status RemoveHypothesis(GEOM::GEOM_Object_ptr       aSubShape,
                                             SMESH::SMESH_Hypothesis_ptr anHyp)
     throw (SALOME::SALOME_Exception);
 
-  SMESH::ListOfHypothesis* GetHypothesisList(GEOM::GEOM_Object_ptr aSubShapeObject)
+  SMESH::ListOfHypothesis* GetHypothesisList(GEOM::GEOM_Object_ptr aSubShape)
     throw (SALOME::SALOME_Exception);
 
   SMESH::submesh_array* GetSubMeshes()
     throw (SALOME::SALOME_Exception);
 
-  SMESH::SMESH_subMesh_ptr GetSubMesh(GEOM::GEOM_Object_ptr aSubShapeObject, const char* theName)
+  SMESH::SMESH_subMesh_ptr GetSubMesh(GEOM::GEOM_Object_ptr aSubShape, const char* theName)
     throw (SALOME::SALOME_Exception);
 
   void RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
@@ -404,10 +405,11 @@ public:
 
   // Internal methods not available through CORBA
   // They are called by corresponding interface methods
-  SMESH_Hypothesis::Hypothesis_Status addHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
-                                                    SMESH::SMESH_Hypothesis_ptr anHyp);
+  SMESH_Hypothesis::Hypothesis_Status addHypothesis(GEOM::GEOM_Object_ptr       aSubShape,
+                                                    SMESH::SMESH_Hypothesis_ptr anHyp,
+                                                    std::string*                anErrorText=0);
 
-  SMESH_Hypothesis::Hypothesis_Status removeHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
+  SMESH_Hypothesis::Hypothesis_Status removeHypothesis(GEOM::GEOM_Object_ptr aSubShape,
                                                        SMESH::SMESH_Hypothesis_ptr anHyp);
 
   static SMESH::Hypothesis_Status
index 1e9c735332a99c79bbfadde90cb2a50c2a3eeb7f..1496202ffeaaf9884fddc74c4e92c65807e2caac 100644 (file)
@@ -385,7 +385,7 @@ class StdMeshersBuilder_Segment(Mesh_Algorithm):
             algo = self.mesh.smeshpyD.CreateHypothesis("SegmentAroundVertex_0D", "libStdMeshersEngine.so")
             pass
         status = self.mesh.mesh.AddHypothesis(self.geom, algo)
-        TreatHypoStatus(status, "SegmentAroundVertex_0D", name, True)
+        TreatHypoStatus(status, "SegmentAroundVertex_0D", name, True, self.mesh)
         #
         from salome.smesh.smeshBuilder import IsEqual
         comFun = lambda hyp, args: IsEqual(hyp.GetLength(), args[0])
@@ -830,12 +830,13 @@ class StdMeshersBuilder_Projection2D(Mesh_Algorithm):
             from salome.smesh.smeshBuilder import AssureGeomPublished
             AssureGeomPublished( self.mesh, geom )
         hyp = self.Hypothesis("ProjectionSource2D", [face,mesh,srcV1,tgtV1,srcV2,tgtV2],
-                              UseExisting=0)
+                              UseExisting=0, toAdd=False)
         # it does not seem to be useful to reuse the existing "SourceFace" hypothesis
                               #UseExisting=UseExisting, CompareMethod=self.CompareSourceFace)
         hyp.SetSourceFace( face )
         hyp.SetSourceMesh( mesh )
         hyp.SetVertexAssociation( srcV1, srcV2, tgtV1, tgtV2 )
+        self.mesh.AddHypothesis(hyp, self.geom)
         return hyp
 
     pass # end of StdMeshersBuilder_Projection2D class
index 6e0812455081549f998ed16694018a11e7158522..61c239b15741723c903ecfc8aefce0fdcb6d35cf 100644 (file)
@@ -207,12 +207,15 @@ def GetName(obj):
     raise RuntimeError, "Null or invalid object"
 
 ## Prints error message if a hypothesis was not assigned.
-def TreatHypoStatus(status, hypName, geomName, isAlgo):
+def TreatHypoStatus(status, hypName, geomName, isAlgo, mesh):
     if isAlgo:
         hypType = "algorithm"
     else:
         hypType = "hypothesis"
         pass
+    reason = ""
+    if hasattr( status, "__getitem__" ):
+        status,reason = status[0],status[1]
     if status == HYP_UNKNOWN_FATAL :
         reason = "for unknown reason"
     elif status == HYP_INCOMPATIBLE :
@@ -235,17 +238,24 @@ def TreatHypoStatus(status, hypName, geomName, isAlgo):
     elif status == HYP_HIDING_ALGO:
         reason = "it hides algorithms of lower dimensions by generating elements of all dimensions"
     elif status == HYP_NEED_SHAPE:
-        reason = "Algorithm can't work without shape"
+        reason = "algorithm can't work without shape"
+    elif status == HYP_INCOMPAT_HYPS:
+        pass
     else:
         return
-    hypName = '"' + hypName + '"'
-    geomName= '"' + geomName+ '"'
-    if status < HYP_UNKNOWN_FATAL and not geomName =='""':
-        print hypName, "was assigned to",    geomName,"but", reason
-    elif not geomName == '""':
-        print hypName, "was not assigned to",geomName,":", reason
+    where = geomName
+    if where:
+        where = '"%s"' % geomName
+        if mesh:
+            meshName = GetName( mesh )
+            if meshName and meshName != NO_NAME:
+                where = '"%s" in "%s"' % ( geomName, meshName )
+    if status < HYP_UNKNOWN_FATAL and where:
+        print '"%s" was assigned to %s but %s' %( hypName, where, reason )
+    elif where:
+        print '"%s" was not assigned to %s : %s' %( hypName, where, reason )
     else:
-        print hypName, "was not assigned:", reason
+        print '"%s" was not assigned : %s' %( hypName, reason )
         pass
 
 ## Private method. Add geom (sub-shape of the main shape) into the study if not yet there
@@ -456,7 +466,9 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
     #  @return SMESH.AxisStruct
     #  @ingroup l1_auxiliary
     def GetAxisStruct(self,theObj):
+        import GEOM
         edges = self.geompyD.SubShapeAll( theObj, geomBuilder.geomBuilder.ShapeType["EDGE"] )
+        axis = None
         if len(edges) > 1:
             vertex1, vertex2 = self.geompyD.SubShapeAll( edges[0], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
             vertex3, vertex4 = self.geompyD.SubShapeAll( edges[1], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
@@ -468,14 +480,18 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
             v2 = [vertex4[0]-vertex3[0], vertex4[1]-vertex3[1], vertex4[2]-vertex3[2]]
             normal = [ v1[1]*v2[2]-v2[1]*v1[2], v1[2]*v2[0]-v2[2]*v1[0], v1[0]*v2[1]-v2[0]*v1[1] ]
             axis = AxisStruct(vertex1[0], vertex1[1], vertex1[2], normal[0], normal[1], normal[2])
-            return axis
+            axis._mirrorType = SMESH.SMESH_MeshEditor.PLANE
         elif len(edges) == 1:
             vertex1, vertex2 = self.geompyD.SubShapeAll( edges[0], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
             p1 = self.geompyD.PointCoordinates( vertex1 )
             p2 = self.geompyD.PointCoordinates( vertex2 )
             axis = AxisStruct(p1[0], p1[1], p1[2], p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2])
-            return axis
-        return None
+            axis._mirrorType = SMESH.SMESH_MeshEditor.AXIS
+        elif theObj.GetShapeType() == GEOM.VERTEX:
+            x,y,z = self.geompyD.PointCoordinates( theObj )
+            axis = AxisStruct( x,y,z, 1,0,0,)
+            axis._mirrorType = SMESH.SMESH_MeshEditor.POINT
+        return axis
 
     # From SMESH_Gen interface:
     # ------------------------
@@ -1520,7 +1536,7 @@ class Mesh:
             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), False, True )
             salome.sg.updateObjBrowser(1)
 
-    ## Computes a tetrahedral mesh using AutomaticLength + MEFISTO + NETGEN
+    ## Computes a tetrahedral mesh using AutomaticLength + MEFISTO + Tetrahedron
     #  @param fineness [0.0,1.0] defines mesh fineness
     #  @return True or False
     #  @ingroup l3_algos_basic
@@ -1533,8 +1549,7 @@ class Mesh:
             self.Triangle().LengthFromEdges()
             pass
         if dim > 2 :
-            from salome.NETGENPlugin.NETGENPluginBuilder import NETGEN
-            self.Tetrahedron(NETGEN)
+            self.Tetrahedron()
             pass
         return self.Compute()
 
@@ -1581,13 +1596,13 @@ class Mesh:
             AssureGeomPublished( self, geom, "shape for %s" % hyp.GetName())
             status = self.mesh.AddHypothesis(geom, hyp)
         else:
-            status = HYP_BAD_GEOMETRY
+            status = HYP_BAD_GEOMETRY,""
         hyp_name = GetName( hyp )
         geom_name = ""
         if geom:
             geom_name = geom.GetName()
         isAlgo = hyp._narrow( SMESH_Algo )
-        TreatHypoStatus( status, hyp_name, geom_name, isAlgo )
+        TreatHypoStatus( status, hyp_name, geom_name, isAlgo, self )
         return status
 
     ## Return True if an algorithm of hypothesis is assigned to a given shape
@@ -1861,7 +1876,12 @@ class Mesh:
     #  @ingroup l2_grps_create
     def MakeGroupByIds(self, groupName, elementType, elemIDs):
         group = self.mesh.CreateGroup(elementType, groupName)
-        group.Add(elemIDs)
+        if hasattr( elemIDs, "GetIDs" ):
+            if hasattr( elemIDs, "SetMesh" ):
+                elemIDs.SetMesh( self.GetMesh() )
+            group.AddFrom( elemIDs )
+        else:
+            group.Add(elemIDs)
         return group
 
     ## Creates a mesh group by the given conditions
@@ -1873,7 +1893,7 @@ class Mesh:
     #  @param UnaryOp FT_LogicalNOT or FT_Undefined
     #  @param Tolerance the tolerance used by FT_BelongToGeom, FT_BelongToSurface,
     #         FT_LyingOnGeom, FT_CoplanarFaces criteria
-    #  @return SMESH_Group
+    #  @return SMESH_GroupOnFilter
     #  @ingroup l2_grps_create
     def MakeGroup(self,
                   groupName,
@@ -1890,40 +1910,32 @@ class Mesh:
     ## Creates a mesh group by the given criterion
     #  @param groupName the name of the mesh group
     #  @param Criterion the instance of Criterion class
-    #  @return SMESH_Group
+    #  @return SMESH_GroupOnFilter
     #  @ingroup l2_grps_create
     def MakeGroupByCriterion(self, groupName, Criterion):
-        aFilterMgr = self.smeshpyD.CreateFilterManager()
-        aFilter = aFilterMgr.CreateFilter()
-        aCriteria = []
-        aCriteria.append(Criterion)
-        aFilter.SetCriteria(aCriteria)
-        group = self.MakeGroupByFilter(groupName, aFilter)
-        aFilterMgr.UnRegister()
-        return group
+        return self.MakeGroupByCriteria( groupName, [Criterion] )
 
     ## Creates a mesh group by the given criteria (list of criteria)
     #  @param groupName the name of the mesh group
     #  @param theCriteria the list of criteria
-    #  @return SMESH_Group
+    #  @param binOp binary operator used when binary operator of criteria is undefined
+    #  @return SMESH_GroupOnFilter
     #  @ingroup l2_grps_create
-    def MakeGroupByCriteria(self, groupName, theCriteria):
-        aFilterMgr = self.smeshpyD.CreateFilterManager()
-        aFilter = aFilterMgr.CreateFilter()
-        aFilter.SetCriteria(theCriteria)
+    def MakeGroupByCriteria(self, groupName, theCriteria, binOp=SMESH.FT_LogicalAND):
+        aFilter = self.smeshpyD.GetFilterFromCriteria( theCriteria, binOp )
         group = self.MakeGroupByFilter(groupName, aFilter)
-        aFilterMgr.UnRegister()
         return group
 
     ## Creates a mesh group by the given filter
     #  @param groupName the name of the mesh group
     #  @param theFilter the instance of Filter class
-    #  @return SMESH_Group
+    #  @return SMESH_GroupOnFilter
     #  @ingroup l2_grps_create
     def MakeGroupByFilter(self, groupName, theFilter):
-        group = self.CreateEmptyGroup(theFilter.GetElementType(), groupName)
-        theFilter.SetMesh( self.mesh )
-        group.AddFrom( theFilter )
+        #group = self.CreateEmptyGroup(theFilter.GetElementType(), groupName)
+        #theFilter.SetMesh( self.mesh )
+        #group.AddFrom( theFilter )
+        group = self.GroupOnFilter( theFilter.GetElementType(), groupName, theFilter )
         return group
 
     ## Removes a group
@@ -2573,7 +2585,7 @@ class Mesh:
 
     ## Get measure structure specifying bounding box data of the specified object(s)
     #  @param IDs single source object or list of source objects or list of nodes/elements IDs
-    #  @param isElem if @a objects is a list of IDs, @c True value in this parameters specifies that @a objects are elements,
+    #  @param isElem if @a IDs is a list of IDs, @c True value in this parameters specifies that @a objects are elements,
     #  @c False specifies that @a objects are nodes
     #  @return Measure structure
     #  @sa BoundingBox()
@@ -2959,6 +2971,37 @@ class Mesh:
             theFace = -1
         return self.editor.Reorient2D( the2DObject, theDirection, theFace, thePoint )
 
+    ## Reorient faces according to adjacent volumes.
+    #  @param the2DObject is a mesh, sub-mesh, group or list of
+    #         either IDs of faces or face groups.
+    #  @param the3DObject is a mesh, sub-mesh, group or list of IDs of volumes.
+    #  @param theOutsideNormal to orient faces to have their normals
+    #         pointing either \a outside or \a inside the adjacent volumes.
+    #  @return number of reoriented faces.
+    #  @ingroup l2_modif_changori
+    def Reorient2DBy3D(self, the2DObject, the3DObject, theOutsideNormal=True ):
+        unRegister = genObjUnRegister()
+        # check the2DObject
+        if not isinstance( the2DObject, list ):
+            the2DObject = [ the2DObject ]
+        elif the2DObject and isinstance( the2DObject[0], int ):
+            the2DObject = self.GetIDSource( the2DObject, SMESH.FACE )
+            unRegister.set( the2DObject )
+            the2DObject = [ the2DObject ]
+        for i,obj2D in enumerate( the2DObject ):
+            if isinstance( obj2D, Mesh ):
+                the2DObject[i] = obj2D.GetMesh()
+            if isinstance( obj2D, list ):
+                the2DObject[i] = self.GetIDSource( obj2D, SMESH.FACE )
+                unRegister.set( the2DObject[i] )
+        # check the3DObject
+        if isinstance( the3DObject, Mesh ):
+            the3DObject = the3DObject.GetMesh()
+        if isinstance( the3DObject, list ):
+            the3DObject = self.GetIDSource( the3DObject, SMESH.VOLUME )
+            unRegister.set( the3DObject )
+        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
@@ -3931,12 +3974,14 @@ class Mesh:
     #  @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
     #  @ingroup l2_modif_trsf
-    def Mirror(self, IDsOfElements, Mirror, theMirrorType, Copy=0, MakeGroups=False):
+    def Mirror(self, IDsOfElements, Mirror, theMirrorType=None, Copy=0, MakeGroups=False):
         if IDsOfElements == []:
             IDsOfElements = self.GetElementsId()
         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
-            Mirror = self.smeshpyD.GetAxisStruct(Mirror)
-        self.mesh.SetParameters(Mirror.parameters)
+            Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
+            theMirrorType = Mirror._mirrorType
+        else:
+            self.mesh.SetParameters(Mirror.parameters)
         if Copy and MakeGroups:
             return self.editor.MirrorMakeGroups(IDsOfElements, Mirror, theMirrorType)
         self.editor.Mirror(IDsOfElements, Mirror, theMirrorType, Copy)
@@ -3951,12 +3996,14 @@ class Mesh:
     #  @param NewMeshName a name of the new mesh to create
     #  @return instance of Mesh class
     #  @ingroup l2_modif_trsf
-    def MirrorMakeMesh(self, IDsOfElements, Mirror, theMirrorType, MakeGroups=0, NewMeshName=""):
+    def MirrorMakeMesh(self, IDsOfElements, Mirror, theMirrorType=0, MakeGroups=0, NewMeshName=""):
         if IDsOfElements == []:
             IDsOfElements = self.GetElementsId()
         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
-            Mirror = self.smeshpyD.GetAxisStruct(Mirror)
-        self.mesh.SetParameters(Mirror.parameters)
+            Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
+            theMirrorType = Mirror._mirrorType
+        else:
+            self.mesh.SetParameters(Mirror.parameters)
         mesh = self.editor.MirrorMakeMesh(IDsOfElements, Mirror, theMirrorType,
                                           MakeGroups, NewMeshName)
         return Mesh(self.smeshpyD,self.geompyD,mesh)
@@ -3970,12 +4017,14 @@ class Mesh:
     #  @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
     #  @ingroup l2_modif_trsf
-    def MirrorObject (self, theObject, Mirror, theMirrorType, Copy=0, MakeGroups=False):
+    def MirrorObject (self, theObject, Mirror, theMirrorType=None, Copy=0, MakeGroups=False):
         if ( isinstance( theObject, Mesh )):
             theObject = theObject.GetMesh()
         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
-            Mirror = self.smeshpyD.GetAxisStruct(Mirror)
-        self.mesh.SetParameters(Mirror.parameters)
+            Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
+            theMirrorType = Mirror._mirrorType
+        else:
+            self.mesh.SetParameters(Mirror.parameters)
         if Copy and MakeGroups:
             return self.editor.MirrorObjectMakeGroups(theObject, Mirror, theMirrorType)
         self.editor.MirrorObject(theObject, Mirror, theMirrorType, Copy)
@@ -3990,12 +4039,14 @@ class Mesh:
     #  @param NewMeshName the name of the new mesh to create
     #  @return instance of Mesh class
     #  @ingroup l2_modif_trsf
-    def MirrorObjectMakeMesh (self, theObject, Mirror, theMirrorType,MakeGroups=0, NewMeshName=""):
+    def MirrorObjectMakeMesh (self, theObject, Mirror, theMirrorType=0,MakeGroups=0,NewMeshName=""):
         if ( isinstance( theObject, Mesh )):
             theObject = theObject.GetMesh()
-        if (isinstance(Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
-            Mirror = self.smeshpyD.GetAxisStruct(Mirror)
-        self.mesh.SetParameters(Mirror.parameters)
+        if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
+            Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
+            theMirrorType = Mirror._mirrorType
+        else:
+            self.mesh.SetParameters(Mirror.parameters)
         mesh = self.editor.MirrorObjectMakeMesh(theObject, Mirror, theMirrorType,
                                                 MakeGroups, NewMeshName)
         return Mesh( self.smeshpyD,self.geompyD,mesh )
@@ -4635,12 +4686,22 @@ class Mesh:
     ## Return minimal and maximal value of a given functor.
     #  @param funType a functor type, an item of SMESH.FunctorType enum
     #         (one of SMESH.FunctorType._items)
+    #  @param meshPart a part of mesh (group, sub-mesh) to treat
     #  @return tuple (min,max)
     #  @ingroup l1_measurements
-    def GetMinMax(self, funType):
+    def GetMinMax(self, funType, meshPart=None):
+        unRegister = genObjUnRegister()
+        if isinstance( meshPart, list ):
+            meshPart = self.GetIDSource( meshPart, SMESH.ALL )
+            unRegister.set( meshPart )
+        if isinstance( meshPart, Mesh ):
+            meshPart = meshPart.mesh
         fun = self._getFunctor( funType )
         if fun:
-            hist = fun.GetHistogram( 1, False )
+            if meshPart:
+                hist = fun.GetLocalHistogram( 1, False, meshPart )
+            else:
+                hist = fun.GetHistogram( 1, False )
             if hist:
                 return hist[0].min, hist[0].max
         return None
index cac705e124f8778b75257cd2bf081447e05d7e61..3623b51764acc807ff104349556ca42f6a423920 100644 (file)
@@ -214,7 +214,7 @@ class Mesh_Algorithm:
 
     ## Private method
     def Hypothesis (self, hyp, args=[], so="libStdMeshersEngine.so",
-                    UseExisting=0, CompareMethod=""):
+                    UseExisting=0, CompareMethod="", toAdd=True):
         from salome.smesh.smeshBuilder import TreatHypoStatus, GetName
         hypo = None
         if UseExisting:
@@ -243,8 +243,9 @@ class Mesh_Algorithm:
         geomName=""
         if self.geom:
             geomName = GetName(self.geom)
-        status = self.mesh.mesh.AddHypothesis(self.geom, hypo)
-        TreatHypoStatus( status, GetName(hypo), geomName, 0 )
+        if toAdd:
+            status = self.mesh.mesh.AddHypothesis(self.geom, hypo)
+            TreatHypoStatus( status, GetName(hypo), geomName, 0, self.mesh )
         return hypo
 
     ## Returns entry of the shape to mesh in the study
@@ -275,11 +276,13 @@ class Mesh_Algorithm:
         if faces and isinstance( faces[0], geomBuilder.GEOM._objref_GEOM_Object ):
             faces = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in faces ]
         hyp = self.Hypothesis("ViscousLayers",
-                              [thickness, numberOfLayers, stretchFactor, faces])
+                              [thickness, numberOfLayers, stretchFactor, faces, isFacesToIgnore],
+                              toAdd=False)
         hyp.SetTotalThickness(thickness)
         hyp.SetNumberLayers(numberOfLayers)
         hyp.SetStretchFactor(stretchFactor)
         hyp.SetFaces(faces, isFacesToIgnore)
+        self.mesh.AddHypothesis( hyp, self.geom )
         return hyp
 
     ## Defines "ViscousLayers2D" hypothesis to give parameters of layers of quadrilateral
@@ -303,12 +306,13 @@ class Mesh_Algorithm:
         if edges and isinstance( edges[0], geomBuilder.GEOM._objref_GEOM_Object ):
             edges = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in edges ]
         hyp = self.Hypothesis("ViscousLayers2D",
-                              [thickness, numberOfLayers, stretchFactor,
-                               edges, isEdgesToIgnore])
+                              [thickness, numberOfLayers, stretchFactor, edges, isEdgesToIgnore],
+                              toAdd=False)
         hyp.SetTotalThickness(thickness)
         hyp.SetNumberLayers(numberOfLayers)
         hyp.SetStretchFactor(stretchFactor)
         hyp.SetEdges(edges, isEdgesToIgnore)
+        self.mesh.AddHypothesis( hyp, self.geom )
         return hyp
 
     ## Transform a list of either edges or tuples (edge, 1st_vertex_of_edge)
index ecb30b1aa86f3821e5655b71fee58aa1abf382d9..62a2cf5a9f1706e34b34896276f4df040b3fc068 100644 (file)
 
 #include <BRepAdaptor_Curve.hxx>
 #include <BRepAdaptor_Surface.hxx>
+#include <BRepBndLib.hxx>
 #include <BRepMesh_IncrementalMesh.hxx>
 #include <BRep_Tool.hxx>
 #include <Bnd_B3d.hxx>
+#include <Bnd_Box.hxx>
 #include <GCPnts_AbscissaPoint.hxx>
 #include <GeomAdaptor_Curve.hxx>
 #include <Geom_Curve.hxx>
@@ -278,28 +280,6 @@ namespace // internal utils
     vector< int > _elementIDs;
   };
   //================================================================================
-  /*!
-   * \brief BRepMesh_IncrementalMesh with access to its protected Bnd_Box
-   */
-  struct IncrementalMesh : public BRepMesh_IncrementalMesh
-  {
-    IncrementalMesh(const TopoDS_Shape& shape,
-                    const Standard_Real deflection,
-                    const bool          relative):
-      BRepMesh_IncrementalMesh( shape, deflection, relative )
-    {
-    }
-    Bnd_B3d GetBox() const
-    {
-      Standard_Real TXmin, TYmin, TZmin, TXmax, TYmax, TZmax;
-      myBox.Get(TXmin, TYmin, TZmin, TXmax, TYmax, TZmax);
-      Bnd_B3d bb;
-      bb.Add( gp_XYZ( TXmin, TYmin, TZmin ));
-      bb.Add( gp_XYZ( TXmax, TYmax, TZmax ));
-      return bb;
-    }
-  };
-  //================================================================================
   /*!
    * \brief Link of two nodes
    */
@@ -1152,10 +1132,19 @@ bool AdaptiveAlgo::Compute(SMESH_Mesh &         theMesh,
   TopExp::MapShapes( theMesh.GetShapeToMesh(), TopAbs_FACE, faceMap );
 
   // Triangulate the shape with the given deflection ?????????
+  {
+    BRepMesh_IncrementalMesh im( theMesh.GetShapeToMesh(), myHyp->GetDeflection(), /*isRelatif=*/0);
+  }
+
+  // get a bnd box
   Bnd_B3d box;
   {
-    IncrementalMesh im( theMesh.GetShapeToMesh(), myHyp->GetDeflection(), /*Relatif=*/false);
-    box = im.GetBox();
+    Bnd_Box aBox;
+    BRepBndLib::Add( theMesh.GetShapeToMesh(), aBox);
+    Standard_Real TXmin, TYmin, TZmin, TXmax, TYmax, TZmax;
+    aBox.Get(TXmin, TYmin, TZmin, TXmax, TYmax, TZmax);
+    box.Add( gp_XYZ( TXmin, TYmin, TZmin ));
+    box.Add( gp_XYZ( TXmax, TYmax, TZmax ));
   }
   // *theProgress = 0.3;
 
index 8b40fe2d9510cb79979d8e80f8a5a0dde77d80e5..3cd23ff35d0a619006f38ac457062b5b1104f928 100644 (file)
@@ -3021,10 +3021,10 @@ namespace
     list< int >         nbEdges;
     int nbW = SMESH_Block::GetOrderedEdges (face, edges, nbEdges);
     if ( nbW > 1 ) {
-      // select a WIRE
+      // select a WIRE - remove EDGEs of irrelevant WIREs from edges
       list< TopoDS_Edge >::iterator e = edges.begin(), eEnd = e;
       list< int >::iterator nE = nbEdges.begin();
-      for ( ; nbW ; ++nE, --nbW )
+      for ( ; nbW > 0; ++nE, --nbW )
       {
         std::advance( eEnd, *nE );
         for ( ; e != eEnd; ++e )
@@ -3037,13 +3037,14 @@ namespace
                 ( std::find( &nShapeIds[0], nShapeIdsEnd, id ) != nShapeIdsEnd ))
             {
               edges.erase( eEnd, edges.end() ); // remove rest wires
-              e = eEnd;
+              e = eEnd = edges.end();
+              --e;
               nbW = 0;
               break;
             }
           }
         if ( nbW > 0 )
-          edges.erase( edges.begin(), eEnd ); // remove a current wire
+          edges.erase( edges.begin(), eEnd ); // remove a current irrelevant wire
       }
     }
     // rotate edges to have the first one at least partially out of the hexa
index b543928dcabd653c2e7adfda7f4f26fca61b11c5..c2596b4b6db521feefb7466ed7c2cbadd1ee138f 100644 (file)
@@ -1012,7 +1012,8 @@ TSideVector StdMeshers_FaceSide::GetFaceWires(const TopoDS_Face&   theFace,
                                               SMESH_Mesh &         theMesh,
                                               const bool           theIgnoreMediumNodes,
                                               TError &             theError,
-                                              SMESH_ProxyMesh::Ptr theProxyMesh)
+                                              SMESH_ProxyMesh::Ptr theProxyMesh,
+                                              const bool           theCheckVertexNodes)
 {
   list< TopoDS_Edge > edges, internalEdges;
   list< int > nbEdgesInWires;
@@ -1037,17 +1038,18 @@ TSideVector StdMeshers_FaceSide::GetFaceWires(const TopoDS_Face&   theFace,
     // as StdMeshers_FaceSide::GetUVPtStruct() requires
     if ( wireEdges.front().Orientation() != TopAbs_INTERNAL ) // Issue 0020676
     {
-      while ( !SMESH_Algo::VertexNode( TopExp::FirstVertex( wireEdges.front(), true),
-                                       theMesh.GetMeshDS()))
-      {
-        wireEdges.splice(wireEdges.end(), wireEdges,
-                         wireEdges.begin(), ++wireEdges.begin());
-        if ( from->IsSame( wireEdges.front() )) {
-          theError = TError
-            ( new SMESH_ComputeError(COMPERR_BAD_INPUT_MESH,"No nodes on vertices"));
-          return TSideVector(0);
+      if ( theCheckVertexNodes )
+        while ( !SMESH_Algo::VertexNode( TopExp::FirstVertex( wireEdges.front(), true),
+                                         theMesh.GetMeshDS()))
+        {
+          wireEdges.splice(wireEdges.end(), wireEdges,
+                           wireEdges.begin(), ++wireEdges.begin());
+          if ( from->IsSame( wireEdges.front() )) {
+            theError = TError
+              ( new SMESH_ComputeError(COMPERR_BAD_INPUT_MESH,"No nodes on vertices"));
+            return TSideVector(0);
+          }
         }
-      }
     }
     else if ( *nbE > 1 ) // Issue 0020676 (Face_pb_netgen.brep) - several internal edges in a wire
     {
index 4b8bf1d3306c62e6d9fae52c8707739c9bc47c24..30166d441e9bb11659a1373819779c8d712031f3 100644 (file)
@@ -141,7 +141,8 @@ public:
                                   SMESH_Mesh &         theMesh,
                                   const bool           theIgnoreMediumNodes,
                                   TError &             theError,
-                                  SMESH_ProxyMesh::Ptr theProxyMesh = SMESH_ProxyMesh::Ptr());
+                                  SMESH_ProxyMesh::Ptr theProxyMesh = SMESH_ProxyMesh::Ptr(),
+                                  const bool           theCheckVertexNodes=true);
   /*!
    * \brief Change orientation of side geometry
    */
index 0271fc41ce80197d965c1425b2d1ef587339a42d..8c54ad4e801a676338b67a2c7bbb0c2fa9290daa 100644 (file)
@@ -124,23 +124,17 @@ bool StdMeshers_Hexa_3D::CheckHypothesis
     return true;
   }
 
+  // only StdMeshers_ViscousLayers can be used
   aStatus = HYP_OK;
   for ( ; h != hyps.end(); ++h )
   {
-    string hypName = (*h)->GetName();
-    if ( find( _compatibleHypothesis.begin(),_compatibleHypothesis.end(),hypName )
-         != _compatibleHypothesis.end() )
-    {
-      _viscousLayersHyp = dynamic_cast< const StdMeshers_ViscousLayers*> ( *h );
-    }
-    else
-    {
-      aStatus = HYP_INCOMPATIBLE;
-    }
+    if ( !(_viscousLayersHyp = dynamic_cast< const StdMeshers_ViscousLayers*> ( *h )))
+      break;
   }
-
   if ( !_viscousLayersHyp )
     aStatus = HYP_INCOMPATIBLE;
+  else
+    error( _viscousLayersHyp->CheckHypothesis( aMesh, aShape, aStatus ));
 
   return aStatus == HYP_OK;
 }
@@ -371,8 +365,9 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh &         aMesh,
     for ( int i = 0; i < 6; ++i )
     {
       const TopoDS_Face& sideF = aCubeSide[i]._quad->face;
-      if ( !SMESH_MesherHelper::IsSameElemGeometry( meshDS->MeshElements( sideF ),
-                                                    SMDSGeom_QUADRANGLE,
+      const SMESHDS_SubMesh* smDS =
+        proxymesh ? proxymesh->GetSubMesh( sideF ) : meshDS->MeshElements( sideF );
+      if ( !SMESH_MesherHelper::IsSameElemGeometry( smDS, SMDSGeom_QUADRANGLE,
                                                     /*nullSubMeshRes=*/false ))
       {
         SMESH_ComputeErrorPtr err = ComputePentahedralMesh(aMesh, aShape, proxymesh.get());
index ee9fe4ef1032964c27bb5edec130bb6795b04a36..a69977dbe40c57c2054df1f7ca400c7fb13559f9 100644 (file)
@@ -70,47 +70,6 @@ StdMeshers_Import_1D::StdMeshers_Import_1D(int hypId, int studyId, SMESH_Gen * g
   _compatibleHypothesis.push_back("ImportSource1D");
 }
 
-//=============================================================================
-/*!
- * Check presence of a hypothesis
- */
-//=============================================================================
-
-bool StdMeshers_Import_1D::CheckHypothesis
-                         (SMESH_Mesh&                          aMesh,
-                          const TopoDS_Shape&                  aShape,
-                          SMESH_Hypothesis::Hypothesis_Status& aStatus)
-{
-  _sourceHyp = 0;
-
-  const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
-  if ( hyps.size() == 0 )
-  {
-    aStatus = SMESH_Hypothesis::HYP_MISSING;
-    return false;  // can't work with no hypothesis
-  }
-
-  if ( hyps.size() > 1 )
-  {
-    aStatus = SMESH_Hypothesis::HYP_ALREADY_EXIST;
-    return false;
-  }
-
-  const SMESHDS_Hypothesis *theHyp = hyps.front();
-
-  string hypName = theHyp->GetName();
-
-  if (hypName == _compatibleHypothesis.front())
-  {
-    _sourceHyp = (StdMeshers_ImportSource1D *)theHyp;
-    aStatus = SMESH_Hypothesis::HYP_OK;
-    return true;
-  }
-
-  aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
-  return true;
-}
-
 //================================================================================
 namespace // INTERNAL STUFF
 //================================================================================
@@ -346,7 +305,7 @@ namespace // INTERNAL STUFF
         bool rmGroups = (d->_copyGroupSubM.erase( sm ) && d->_copyGroupSubM.empty()) || rmMesh;
         if ( rmMesh )
           d->removeImportedMesh( sm->GetFather()->GetMeshDS() );
-        if ( rmGroups && data )
+        if ( rmGroups && data && data->myType == SRC_HYP )
           d->removeGroups( sm, data->_srcHyp );
       }
   }
@@ -383,7 +342,7 @@ namespace // INTERNAL STUFF
           // remove imported mesh and groups
           d->removeImportedMesh( sm->GetFather()->GetMeshDS() );
 
-          if ( data )
+          if ( data && data->myType == SRC_HYP )
             d->removeGroups( sm, data->_srcHyp );
 
           // clear the rest submeshes
@@ -395,7 +354,7 @@ namespace // INTERNAL STUFF
             {
               SMESH_subMesh* subM = *sub;
               _ListenerData* hypData = (_ListenerData*) subM->GetEventListenerData( get() );
-              if ( hypData )
+              if ( hypData && hypData->myType == SRC_HYP )
                 d->removeGroups( sm, hypData->_srcHyp );
 
               subM->ComputeStateEngine( SMESH_subMesh::CLEAN );
@@ -408,7 +367,7 @@ namespace // INTERNAL STUFF
         if ( sm->GetSubShape().ShapeType() == TopAbs_FACE )
           sm->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN );
       }
-      if ( data )
+      if ( data && data->myType == SRC_HYP )
         d->trackHypParams( sm, data->_srcHyp );
       d->_n2n.clear();
       d->_e2e.clear();
@@ -633,6 +592,48 @@ namespace // INTERNAL STUFF
 
 } // namespace
 
+//=============================================================================
+/*!
+ * Check presence of a hypothesis
+ */
+//=============================================================================
+
+bool StdMeshers_Import_1D::CheckHypothesis
+                         (SMESH_Mesh&                          aMesh,
+                          const TopoDS_Shape&                  aShape,
+                          SMESH_Hypothesis::Hypothesis_Status& aStatus)
+{
+  _sourceHyp = 0;
+
+  const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
+  if ( hyps.size() == 0 )
+  {
+    aStatus = SMESH_Hypothesis::HYP_MISSING;
+    return false;  // can't work with no hypothesis
+  }
+
+  if ( hyps.size() > 1 )
+  {
+    aStatus = SMESH_Hypothesis::HYP_ALREADY_EXIST;
+    return false;
+  }
+
+  const SMESHDS_Hypothesis *theHyp = hyps.front();
+
+  string hypName = theHyp->GetName();
+
+  if (hypName == _compatibleHypothesis.front())
+  {
+    _sourceHyp = (StdMeshers_ImportSource1D *)theHyp;
+    aStatus = _sourceHyp->GetGroups().empty() ? HYP_BAD_PARAMETER : HYP_OK;
+    if ( aStatus == HYP_BAD_PARAMETER )
+      _Listener::waitHypModification( aMesh.GetSubMesh( aShape ));
+    return aStatus == HYP_OK;
+  }
+
+  aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
+  return false;
+}
 
 //=============================================================================
 /*!
index 75db563136dd7a0ab154bcb6785bd8771646fc61..34003c6c9df03a5557a69e43f5c0acf4499b868b 100644 (file)
@@ -122,6 +122,9 @@ bool StdMeshers_MEFISTO_2D::CheckHypothesis
   _edgeLength = 0;
   _maxElementArea = 0;
 
+  if ( !error( StdMeshers_ViscousLayers2D::CheckHypothesis( aMesh, aShape, aStatus )))
+    return false;
+
   list <const SMESHDS_Hypothesis * >::const_iterator itl;
   const SMESHDS_Hypothesis *theHyp;
 
index 3b6cf64816c46f54fbdc81083d160747f42466c8..afac9bebe4ec2cc0f4dad6359f90c5ccb5a9aa2f 100644 (file)
 using namespace std;
 
 #define RETURN_BAD_RESULT(msg) { MESSAGE(")-: Error: " << msg); return false; }
-#define gpXYZ(n) gp_XYZ(n->X(),n->Y(),n->Z())
-#define SHOWYXZ(msg, xyz) // {\
-// gp_Pnt p (xyz); \
-// cout << msg << " ("<< p.X() << "; " <<p.Y() << "; " <<p.Z() << ") " <<endl;\
-// }
+#define gpXYZ(n) SMESH_TNodeXYZ(n)
+
 #ifdef _DEBUG_
 #define DBGOUT(msg) //cout << msg << endl;
+#define SHOWYXZ(msg, xyz)                                               \
+  // { gp_Pnt p (xyz);                                                     \
+  //   cout << msg << " ("<< p.X() << "; " <<p.Y() << "; " <<p.Z() << ") " <<endl; }
 #else
 #define DBGOUT(msg)
+#define SHOWYXZ(msg, xyz)
 #endif
 
 namespace TAssocTool = StdMeshers_ProjectionUtils;
@@ -190,7 +191,7 @@ namespace {
             ( sm->NbElements() > 0 ) &&
             ( !theHelper.IsSameElemGeometry( sm, SMDSGeom_QUADRANGLE ) ))
         {
-          faceFound;
+          faceFound = true;
           break;
         }
       if ( !faceFound )
@@ -426,10 +427,10 @@ namespace {
    */
   //================================================================================
 
-  double normAngle(const TopoDS_Edge & E1, const TopoDS_Edge & E2, const TopoDS_Face & F)
-  {
-    return SMESH_MesherHelper::GetAngle( E1, E2, F ) / ( 0.5 * M_PI );
-  }
+  // double normAngle(const TopoDS_Edge & E1, const TopoDS_Edge & E2, const TopoDS_Face & F)
+  // {
+  //   return SMESH_MesherHelper::GetAngle( E1, E2, F ) / ( 0.5 * M_PI );
+  // }
 
   //================================================================================
   /*!
@@ -1202,6 +1203,9 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism)
         // create a node
         node = meshDS->AddNode( coords.X(), coords.Y(), coords.Z() );
         meshDS->SetNodeInVolume( node, volumeID );
+
+        if ( _computeCanceled )
+          return false;
       }
     } // loop on bottom nodes
   }
@@ -1263,34 +1267,36 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
   TProjction1dAlgo*      projector1D = TProjction1dAlgo::instance( this );
   StdMeshers_Quadrangle_2D* quadAlgo = TQuadrangleAlgo::instance( this, myHelper );
 
-  SMESH_HypoFilter hyp1dFilter( SMESH_HypoFilter::IsAlgo(),/*not=*/true);
-  hyp1dFilter.And( SMESH_HypoFilter::HasDim( 1 ));
-  hyp1dFilter.And( SMESH_HypoFilter::IsMoreLocalThan( thePrism.myShape3D, *mesh ));
+  // SMESH_HypoFilter hyp1dFilter( SMESH_HypoFilter::IsAlgo(),/*not=*/true);
+  // hyp1dFilter.And( SMESH_HypoFilter::HasDim( 1 ));
+  // hyp1dFilter.And( SMESH_HypoFilter::IsMoreLocalThan( thePrism.myShape3D, *mesh ));
 
   // Discretize equally 'vertical' EDGEs
   // -----------------------------------
   // find source FACE sides for projection: either already computed ones or
   // the 'most composite' ones
-  multimap< int, int > wgt2quad;
-  for ( size_t iW = 0; iW != thePrism.myWallQuads.size(); ++iW )
+  const size_t nbWalls = thePrism.myWallQuads.size();
+  vector< int > wgt( nbWalls, 0 ); // "weight" of a wall
+  for ( size_t iW = 0; iW != nbWalls; ++iW )
   {
     Prism_3D::TQuadList::const_iterator quad = thePrism.myWallQuads[iW].begin();
-    int wgt = 0; // "weight"
     for ( ; quad != thePrism.myWallQuads[iW].end(); ++quad )
     {
       StdMeshers_FaceSidePtr lftSide = (*quad)->side[ QUAD_LEFT_SIDE ];
       for ( int i = 0; i < lftSide->NbEdges(); ++i )
       {
-        ++wgt;
+        ++wgt[ iW ];
         const TopoDS_Edge& E = lftSide->Edge(i);
         if ( mesh->GetSubMesh( E )->IsMeshComputed() )
-          wgt += 10;
-        else if ( mesh->GetHypothesis( E, hyp1dFilter, true )) // local hypothesis!
-          wgt += 100;
+        {
+          wgt[ iW ] += 100;
+          wgt[ myHelper->WrapIndex( iW+1, nbWalls)] += 10;
+          wgt[ myHelper->WrapIndex( iW-1, nbWalls)] += 10;
+        }
+        // else if ( mesh->GetHypothesis( E, hyp1dFilter, true )) // local hypothesis!
+        //   wgt += 100;
       }
     }
-    wgt2quad.insert( make_pair( wgt, iW ));
-
     // in quadratic mesh, pass ignoreMediumNodes to quad sides
     if ( myHelper->GetIsQuadratic() )
     {
@@ -1300,6 +1306,9 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
           (*quad)->side[ i ].grid->SetIgnoreMediumNodes( true );
     }
   }
+  multimap< int, int > wgt2quad;
+  for ( size_t iW = 0; iW != nbWalls; ++iW )
+    wgt2quad.insert( make_pair( wgt[ iW ], iW ));
 
   // Project 'vertical' EDGEs, from left to right
   multimap< int, int >::reverse_iterator w2q = wgt2quad.rbegin();
@@ -1348,7 +1357,11 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
       {
         const TopoDS_Edge& tgtE = rgtSide->Edge(i);
         SMESH_subMesh*    tgtSM = mesh->GetSubMesh( tgtE );
-        if (( isTgtEdgeComputed[ i ] = tgtSM->IsMeshComputed() )) {
+        if ( !( isTgtEdgeComputed[ i ] = tgtSM->IsMeshComputed() )) {
+          tgtSM->ComputeSubMeshStateEngine( SMESH_subMesh::COMPUTE );
+          tgtSM->ComputeStateEngine       ( SMESH_subMesh::COMPUTE );
+        }
+        if ( tgtSM->IsMeshComputed() ) {
           ++nbTgtMeshed;
           nbTgtSegments += tgtSM->GetSubMeshDS()->NbElements();
         }
@@ -1357,16 +1370,33 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
       {
         if ( nbTgtSegments != nbSrcSegments )
         {
-          for ( int i = 0; i < lftSide->NbEdges(); ++i )
-            addBadInputElements( meshDS->MeshElements( lftSide->Edge( i )));
+          bool badMeshRemoved = false;
+          // remove just computed segments
           for ( int i = 0; i < rgtSide->NbEdges(); ++i )
-            addBadInputElements( meshDS->MeshElements( rgtSide->Edge( i )));
-          return toSM( error( TCom("Different nb of segment on logically vertical edges #")
-                              << shapeID( lftSide->Edge(0) ) << " and #"
-                              << shapeID( rgtSide->Edge(0) ) << ": "
-                              << nbSrcSegments << " != " << nbTgtSegments ));
+            if ( !isTgtEdgeComputed[ i ])
+            {
+              const TopoDS_Edge& tgtE = rgtSide->Edge(i);
+              SMESH_subMesh*    tgtSM = mesh->GetSubMesh( tgtE );
+              tgtSM->ComputeStateEngine( SMESH_subMesh::CLEAN );
+              badMeshRemoved = true;
+              nbTgtMeshed--;
+            }
+          if ( !badMeshRemoved )
+          {
+            for ( int i = 0; i < lftSide->NbEdges(); ++i )
+              addBadInputElements( meshDS->MeshElements( lftSide->Edge( i )));
+            for ( int i = 0; i < rgtSide->NbEdges(); ++i )
+              addBadInputElements( meshDS->MeshElements( rgtSide->Edge( i )));
+            return toSM( error( TCom("Different nb of segment on logically vertical edges #")
+                                << shapeID( lftSide->Edge(0) ) << " and #"
+                                << shapeID( rgtSide->Edge(0) ) << ": "
+                                << nbSrcSegments << " != " << nbTgtSegments ));
+          }
+        }
+        else // if ( nbTgtSegments == nbSrcSegments )
+        {
+          continue;
         }
-        continue;
       }
       // Compute 'vertical projection'
       if ( nbTgtMeshed == 0 )
@@ -1408,13 +1438,22 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
             // new nodes are on different EDGEs; put one of them on VERTEX
             const int      edgeIndex = rgtSide->EdgeIndex( srcNodeStr[ iN-1 ].normParam );
             const double vertexParam = rgtSide->LastParameter( edgeIndex );
-            const gp_Pnt           p = BRep_Tool::Pnt( rgtSide->LastVertex( edgeIndex ));
+            TopoDS_Vertex     vertex = rgtSide->LastVertex( edgeIndex );
+            const SMDS_MeshNode*  vn = SMESH_Algo::VertexNode( vertex, meshDS );
+            const gp_Pnt           p = BRep_Tool::Pnt( vertex );
             const int         isPrev = ( Abs( srcNodeStr[ iN-1 ].normParam - vertexParam ) <
                                          Abs( srcNodeStr[ iN   ].normParam - vertexParam ));
             meshDS->UnSetNodeOnShape( newNodes[ iN-isPrev ] );
-            meshDS->SetNodeOnVertex ( newNodes[ iN-isPrev ], rgtSide->LastVertex( edgeIndex ));
+            meshDS->SetNodeOnVertex ( newNodes[ iN-isPrev ], vertex );
             meshDS->MoveNode        ( newNodes[ iN-isPrev ], p.X(), p.Y(), p.Z() );
             id2type.first = newNodes[ iN-(1-isPrev) ]->getshapeId();
+            if ( vn )
+            {
+              SMESH_MeshEditor::TListOfListOfNodes lln( 1, list< const SMDS_MeshNode* >() );
+              lln.back().push_back ( vn );
+              lln.back().push_front( newNodes[ iN-isPrev ] ); // to keep 
+              SMESH_MeshEditor( mesh ).MergeNodes( lln );
+            }
           }
           SMDS_MeshElement* newEdge = myHelper->AddEdge( newNodes[ iN-1 ], newNodes[ iN ] );
           meshDS->SetMeshElementOnShape( newEdge, id2type.first );
@@ -1822,7 +1861,7 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
 
   if ( !botSMDS || botSMDS->NbElements() == 0 )
   {
-    _gen->Compute( *myHelper->GetMesh(), botSM->GetSubShape() );
+    _gen->Compute( *myHelper->GetMesh(), botSM->GetSubShape(), /*aShapeOnly=*/true );
     botSMDS = botSM->GetSubMeshDS();
     if ( !botSMDS || botSMDS->NbElements() == 0 )
       return toSM( error(TCom("No elements on face #") << botSM->GetId() ));
@@ -3725,8 +3764,8 @@ gp_Pnt StdMeshers_PrismAsBlock::TSideFace::Value(const Standard_Real U,
     }
     if ( !edge.IsNull() )
     {
-      double u1 = myHelper.GetNodeU( edge, nn[0] );
-      double u3 = myHelper.GetNodeU( edge, nn[2] );
+      double u1 = myHelper.GetNodeU( edge, nn[0], nn[2] );
+      double u3 = myHelper.GetNodeU( edge, nn[2], nn[0] );
       double u = u1 * ( 1 - hR ) + u3 * hR;
       TopLoc_Location loc; double f,l;
       Handle(Geom_Curve) curve = BRep_Tool::Curve( edge,loc,f,l );
index 18c6f27d27500a5f6041dd2eacdfb30fa1985291..92474f20566a0831457ed48a5278a7a50c62215e 100644 (file)
@@ -529,6 +529,8 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the
     TShapePairsList::iterator s1_s2 = shapesQueue.begin();
     for ( ; s1_s2 != shapesQueue.end(); ++s1_s2 )
     {
+      if ( theMap.IsBound( s1_s2->first )) // avoid re-binding for a seam edge
+        continue; // to avoid this:           Forward seam -> Reversed seam
       InsertAssociation( s1_s2->first, s1_s2->second, theMap );
       TopoDS_Iterator s1It( s1_s2->first), s2It( s1_s2->second );
       for ( ; s1It.More(); s1It.Next(), s2It.Next() )
@@ -2130,7 +2132,7 @@ bool StdMeshers_ProjectionUtils::MakeComputed(SMESH_subMesh * sm, const int iter
           mesh->GetHypotheses( shape, hypoFilter, hyps, true, &assignedTo );
         if ( nbAlgos > 1 ) // concurrent algos
         {
-          list<SMESH_subMesh*> smList; // where an algo is assigned
+          vector<SMESH_subMesh*> smList; // where an algo is assigned
           list< TopoDS_Shape >::iterator shapeIt = assignedTo.begin();
           for ( ; shapeIt != assignedTo.end(); ++shapeIt )
             smList.push_back( mesh->GetSubMesh( *shapeIt ));
@@ -2381,9 +2383,21 @@ void StdMeshers_ProjectionUtils::SetEventListener(SMESH_subMesh* subMesh,
       }
       else
       {
-        subMesh->SetEventListener( getSrcSubMeshListener(),
-                                   SMESH_subMeshEventListenerData::MakeData( subMesh ),
-                                   srcShapeSM );
+        if ( SMESH_subMeshEventListenerData* data =
+             srcShapeSM->GetEventListenerData( getSrcSubMeshListener() ))
+        {
+          bool alreadyIn =
+            (std::find( data->mySubMeshes.begin(),
+                        data->mySubMeshes.end(), subMesh ) != data->mySubMeshes.end() );
+          if ( !alreadyIn )
+            data->mySubMeshes.push_back( subMesh );
+        }
+        else
+        {
+          subMesh->SetEventListener( getSrcSubMeshListener(),
+                                     SMESH_subMeshEventListenerData::MakeData( subMesh ),
+                                     srcShapeSM );
+        }
       }
     }
   }
index c4bbc0c6825a62e7c7cd539df111cb3cbc32d800..b0118c7199c8020693cc5056f2a5f1ccc69ac7d6 100644 (file)
@@ -139,6 +139,7 @@ bool StdMeshers_Projection_2D::CheckHypothesis(SMESH_Mesh&
            !SMESH_MesherHelper::IsSubShape( edge, _sourceHypo->GetSourceFace() ))
       {
         theStatus = HYP_BAD_PARAMETER;
+        error("Invalid source vertices");
         SCRUTE((edge.IsNull()));
         SCRUTE((SMESH_MesherHelper::IsSubShape( edge, srcMesh )));
         SCRUTE((SMESH_MesherHelper::IsSubShape( edge, _sourceHypo->GetSourceFace() )));
@@ -151,6 +152,7 @@ bool StdMeshers_Projection_2D::CheckHypothesis(SMESH_Mesh&
         if ( edge.IsNull() || !SMESH_MesherHelper::IsSubShape( edge, tgtMesh ))
         {
           theStatus = HYP_BAD_PARAMETER;
+          error("Invalid target vertices");
           SCRUTE((edge.IsNull()));
           SCRUTE((SMESH_MesherHelper::IsSubShape( edge, tgtMesh )));
         }
@@ -159,6 +161,7 @@ bool StdMeshers_Projection_2D::CheckHypothesis(SMESH_Mesh&
                   !SMESH_MesherHelper::IsSubShape( edge, theShape ))
         {
           theStatus = HYP_BAD_PARAMETER;
+          error("Invalid target vertices");
           SCRUTE((SMESH_MesherHelper::IsSubShape( edge, theShape )));
         }
       }
@@ -168,6 +171,7 @@ bool StdMeshers_Projection_2D::CheckHypothesis(SMESH_Mesh&
          ( srcMesh == tgtMesh && theShape == _sourceHypo->GetSourceFace() ))
     {
       theStatus = HYP_BAD_PARAMETER;
+      error("Invalid source face");
       SCRUTE((SMESH_MesherHelper::IsSubShape( _sourceHypo->GetSourceFace(), srcMesh )));
       SCRUTE((srcMesh == tgtMesh));
       SCRUTE(( theShape == _sourceHypo->GetSourceFace() ));
@@ -381,8 +385,10 @@ namespace {
                       SMESH_Mesh *                      srcMesh,
                       const TAssocTool::TShapeShapeMap& shape2ShapeMap)
   {
-    MESSAGE("projectPartner");
-    const double tol = 1.e-7*srcMesh->GetMeshDS()->getMaxDim();
+    SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
+    SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
+
+    const double tol = 1.e-7 * srcMeshDS->getMaxDim();
 
     gp_Trsf trsf; // transformation to get location of target nodes from source ones
     if ( tgtFace.IsPartner( srcFace ))
@@ -441,11 +447,11 @@ namespace {
             else
               pOK = (( tgtP.Distance( tgtPP[0] ) > tol*tol ) &&
                      ( tgtPP.size() == 1 || tgtP.Distance( tgtPP[1] ) > tol*tol ));
-            //cout << "V - nS " << p._node->GetID() << " - nT " << SMESH_Algo::VertexNode(TopoDS::Vertex( tgtShape),tgtMesh->GetMeshDS())->GetID() << endl;
+            //cout << "V - nS " << p._node->GetID() << " - nT " << SMESH_Algo::VertexNode(TopoDS::Vertex( tgtShape),tgtMeshDS)->GetID() << endl;
           }
           else if ( tgtPP.size() > 0 )
           {
-            if ( SMESHDS_SubMesh* tgtSmds = tgtMesh->GetMeshDS()->MeshElements( tgtShape ))
+            if ( SMESHDS_SubMesh* tgtSmds = tgtMeshDS->MeshElements( tgtShape ))
             {
               double srcDist = srcPP[0].Distance( p );
               double eTol = BRep_Tool::Tolerance( TopoDS::Edge( tgtShape ));
@@ -486,26 +492,36 @@ namespace {
     map<const SMDS_MeshNode* , const SMDS_MeshNode*> src2tgtNodes;
     map<const SMDS_MeshNode* , const SMDS_MeshNode*>::iterator srcN_tgtN;
 
-    for ( TopExp_Explorer srcEdge( srcFace, TopAbs_EDGE); srcEdge.More(); srcEdge.Next() )
+    bool tgtEdgesMeshed = false;
+    for ( TopExp_Explorer srcExp( srcFace, TopAbs_EDGE); srcExp.More(); srcExp.Next() )
     {
-      const TopoDS_Shape& tgtEdge = shape2ShapeMap( srcEdge.Current(), /*isSrc=*/true );
+      const TopoDS_Shape& srcEdge = srcExp.Current();
+      const TopoDS_Shape& tgtEdge = shape2ShapeMap( srcEdge, /*isSrc=*/true );
+      tgtEdgesMeshed != tgtMesh->GetSubMesh( tgtEdge )->IsEmpty();
+
+      if ( srcMesh->GetSubMesh( srcEdge )->IsEmpty() ||
+           tgtMesh->GetSubMesh( tgtEdge )->IsEmpty() )
+        continue;
 
       map< double, const SMDS_MeshNode* > srcNodes, tgtNodes;
-      if ( !SMESH_Algo::GetSortedNodesOnEdge( srcMesh->GetMeshDS(),
-                                              TopoDS::Edge( srcEdge.Current() ),
-                                              /*ignoreMediumNodes = */true,
-                                              srcNodes )
+      if (( ! SMESH_Algo::GetSortedNodesOnEdge( srcMeshDS,
+                                                TopoDS::Edge( srcEdge ),
+                                                /*ignoreMediumNodes = */true,
+                                                srcNodes ))
            ||
-           !SMESH_Algo::GetSortedNodesOnEdge( tgtMesh->GetMeshDS(),
-                                              TopoDS::Edge( tgtEdge ),
-                                              /*ignoreMediumNodes = */true,
-                                              tgtNodes )
+          ( ! SMESH_Algo::GetSortedNodesOnEdge( tgtMeshDS,
+                                                TopoDS::Edge( tgtEdge ),
+                                                /*ignoreMediumNodes = */true,
+                                                tgtNodes ))
            ||
-           srcNodes.size() != tgtNodes.size())
+          (( srcNodes.size() != tgtNodes.size() ) && tgtNodes.size() > 0 )
+          )
         return false;
 
-      if ( !tgtEdge.IsPartner( srcEdge.Current() ))
+      if ( !tgtEdge.IsPartner( srcEdge ))
       {
+        if ( tgtNodes.empty() )
+          return false;
         // check that transformation is OK by three nodes
         gp_Pnt p0S = SMESH_TNodeXYZ( (srcNodes.begin())  ->second);
         gp_Pnt p1S = SMESH_TNodeXYZ( (srcNodes.rbegin()) ->second);
@@ -527,20 +543,50 @@ namespace {
           return false;
         }
       }
+      if ( !tgtNodes.empty() )
+      {
+        map< double, const SMDS_MeshNode* >::iterator u_tn = tgtNodes.begin();
+        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 ));
+      }
+    }
+    // check nodes on VERTEXes for a case of not meshes EDGEs
+    for ( TopExp_Explorer srcExp( srcFace, TopAbs_VERTEX); srcExp.More(); srcExp.Next() )
+    {
+      const TopoDS_Shape&  srcV = srcExp.Current();
+      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 );
+      if ( !srcN )
+        continue;
+      if ( !tgtN || tgtV.ShapeType() != TopAbs_VERTEX )
+        return false;
 
-      map< double, const SMDS_MeshNode* >::iterator u_tn = tgtNodes.begin();
-      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 ));
+      if ( !tgtV.IsPartner( srcV ))
+      {
+        // check that transformation is OK by three nodes
+        gp_Pnt p0S = SMESH_TNodeXYZ( srcN );
+        gp_Pnt p0T = SMESH_TNodeXYZ( tgtN );
+        if ( p0T.SquareDistance( p0S.Transformed( trsf )) > tol )
+        {
+          return false;
+        }
+      }
+      src2tgtNodes.insert( make_pair( srcN, tgtN ));
     }
 
+
     // Make new faces
 
     // prepare the helper to adding quadratic elements if necessary
     SMESH_MesherHelper helper( *tgtMesh );
     helper.SetSubShape( tgtFace );
     helper.IsQuadraticSubMesh( tgtFace );
-    helper.SetElementsOnShape( true );
+
+    SMESHDS_SubMesh* srcSubDS = srcMeshDS->MeshElements( srcFace );
+    if ( !tgtEdgesMeshed && srcSubDS->NbElements() )
+      helper.SetIsQuadratic( srcSubDS->GetElements()->next()->IsQuadratic() );
 
     SMESH_MesherHelper srcHelper( *srcMesh );
     srcHelper.SetSubShape( srcFace );
@@ -548,11 +594,11 @@ namespace {
     const SMDS_MeshNode* nullNode = 0;
 
     // indices of nodes to create properly oriented faces
+    bool isReverse = ( trsf.Form() != gp_Identity );
     int tri1 = 1, tri2 = 2, quad1 = 1, quad3 = 3;
-    if ( trsf.Form() != gp_Identity )
+    if ( isReverse )
       std::swap( tri1, tri2 ), std::swap( quad1, quad3 );
 
-    SMESHDS_SubMesh* srcSubDS = srcMesh->GetMeshDS()->MeshElements( srcFace );
     SMDS_ElemIteratorPtr elemIt = srcSubDS->GetElements();
     vector< const SMDS_MeshNode* > tgtNodes;
     while ( elemIt->more() ) // loop on all mesh faces on srcFace
@@ -560,6 +606,7 @@ namespace {
       const SMDS_MeshElement* elem = elemIt->next();
       const int nbN = elem->NbCornerNodes(); 
       tgtNodes.resize( nbN );
+      helper.SetElementsOnShape( false );
       for ( int i = 0; i < nbN; ++i ) // loop on nodes of the source element
       {
         const SMDS_MeshNode* srcNode = elem->GetNode(i);
@@ -567,27 +614,117 @@ namespace {
         if ( srcN_tgtN->second == nullNode )
         {
           // create a new node
-          gp_Pnt tgtP = gp_Pnt(srcNode->X(),srcNode->Y(),srcNode->Z()).Transformed( trsf );
+          gp_Pnt tgtP = gp_Pnt( SMESH_TNodeXYZ( srcNode )).Transformed( trsf );
           SMDS_MeshNode* n = helper.AddNode( tgtP.X(), tgtP.Y(), tgtP.Z() );
           srcN_tgtN->second = n;
-
-          gp_Pnt2d srcUV = srcHelper.GetNodeUV( srcFace, srcNode,
-                                                elem->GetNode( helper.WrapIndex(i+1,nbN)));
-          n->SetPosition( new SMDS_FacePosition( srcUV.X(), srcUV.Y() ));
+          switch ( srcNode->GetPosition()->GetTypeOfPosition() )
+          {
+          case SMDS_TOP_FACE:
+          {
+            gp_Pnt2d srcUV = srcHelper.GetNodeUV( srcFace, srcNode );
+            tgtMeshDS->SetNodeOnFace( n, helper.GetSubShapeID(), srcUV.X(), srcUV.Y() );
+            break;
+          }
+          case SMDS_TOP_EDGE:
+          {
+            const TopoDS_Shape & srcE = srcMeshDS->IndexToShape( srcNode->getshapeId() );
+            const TopoDS_Shape & tgtE = shape2ShapeMap( srcE, /*isSrc=*/true );
+            double srcU = srcHelper.GetNodeU( TopoDS::Edge( srcE ), srcNode );
+            tgtMeshDS->SetNodeOnEdge( n, TopoDS::Edge( tgtE ), srcU );
+            break;
+          }
+          case SMDS_TOP_VERTEX:
+          {
+            const TopoDS_Shape & srcV = srcMeshDS->IndexToShape( srcNode->getshapeId() );
+            const TopoDS_Shape & tgtV = shape2ShapeMap( srcV, /*isSrc=*/true );
+            tgtMeshDS->SetNodeOnVertex( n, TopoDS::Vertex( tgtV ));
+            break;
+          }
+          default:;
+          }
         }
         tgtNodes[i] = srcN_tgtN->second;
       }
       // create a new face
+      helper.SetElementsOnShape( true );
       switch ( nbN )
       {
       case 3: helper.AddFace(tgtNodes[0], tgtNodes[tri1], tgtNodes[tri2]); break;
       case 4: helper.AddFace(tgtNodes[0], tgtNodes[quad1], tgtNodes[2], tgtNodes[quad3]); break;
+      default:
+        if ( isReverse ) std::reverse( tgtNodes.begin(), tgtNodes.end() );
+        helper.AddPolygonalFace( tgtNodes );
+      }
+    }
+
+    // check node positions
+
+    if ( !tgtFace.IsPartner( srcFace ) )
+    {
+      int nbOkPos = 0;
+      const double tol2d = 1e-12;
+      srcN_tgtN = src2tgtNodes.begin();
+      for ( ; srcN_tgtN != src2tgtNodes.end(); ++srcN_tgtN )
+      {
+        const SMDS_MeshNode* n = srcN_tgtN->second;
+        switch ( n->GetPosition()->GetTypeOfPosition() )
+        {
+        case SMDS_TOP_FACE:
+        {
+          gp_XY uv = helper.GetNodeUV( tgtFace, n ), uvBis = uv;
+          if (( helper.CheckNodeUV( tgtFace, n, uv, tol )) &&
+              (( uv - uvBis ).SquareModulus() < tol2d )    &&
+              ( ++nbOkPos > 10 ))
+            return true;
+          else
+            nbOkPos = 0;
+          break;
+        }
+        case SMDS_TOP_EDGE:
+        {
+          const TopoDS_Edge & tgtE = TopoDS::Edge( tgtMeshDS->IndexToShape( n->getshapeId() ));
+          double u = helper.GetNodeU( tgtE, n ), uBis = u;
+          if (( !helper.CheckNodeU( tgtE, n, u, tol )) ||
+              (( u - uBis ) < tol2d ))
+            nbOkPos = 0;
+          break;
+        }
+        default:;
+        }
       }
     }
+
     return true;
 
   } //   bool projectPartner()
 
+  //================================================================================
+  /*!
+   * \brief Check if two consecutive EDGEs are connected in 2D
+   *  \param [in] E1 - a well oriented non-seam EDGE
+   *  \param [in] E2 - a possibly well oriented seam EDGE
+   *  \param [in] F - a FACE
+   *  \return bool - result
+   */
+  //================================================================================
+
+  bool are2dConnected( const TopoDS_Edge & E1,
+                       const TopoDS_Edge & E2,
+                       const TopoDS_Face & F )
+  {
+    double f,l;
+    Handle(Geom2d_Curve) c1 = BRep_Tool::CurveOnSurface( E1, F, f, l );
+    gp_Pnt2d uvLast1 = c1->Value( E1.Orientation() == TopAbs_REVERSED ? f : l );
+
+    Handle(Geom2d_Curve) c2 = BRep_Tool::CurveOnSurface( E2, F, f, l );
+    gp_Pnt2d uvFirst2 = c2->Value( f );
+    gp_Pnt2d uvLast2  = c2->Value( l );
+    double tol2 = 1e-5 * uvLast2.SquareDistance( uvFirst2 );
+
+    return (( uvLast1.SquareDistance( uvFirst2 ) < tol2 ) ||
+            ( uvLast1.SquareDistance( uvLast2 ) < tol2 ));
+  }
+
   //================================================================================
   /*!
    * \brief Preform projection in case if the faces are similar in 2D space
@@ -612,19 +749,31 @@ namespace {
 
     // make corresponding sequence of tgt EDGEs
     TSideVector tgtWires( srcWires.size() );
-    for ( unsigned iW = 0; iW < srcWires.size(); ++iW )
+    for ( size_t iW = 0; iW < srcWires.size(); ++iW )
     {
       list< TopoDS_Edge > tgtEdges;
       StdMeshers_FaceSidePtr srcWire = srcWires[iW];
       TopTools_IndexedMapOfShape edgeMap; // to detect seam edges
       for ( int iE = 0; iE < srcWire->NbEdges(); ++iE )
       {
-        tgtEdges.push_back( TopoDS::Edge( shape2ShapeMap( srcWire->Edge( iE ), /*isSrc=*/true)));
+        TopoDS_Edge E = TopoDS::Edge( shape2ShapeMap( srcWire->Edge( iE ), /*isSrc=*/true));
         // reverse a seam edge encountered for the second time
-        const int oldExtent = edgeMap.Extent();
-        edgeMap.Add( tgtEdges.back() );
-        if ( oldExtent == edgeMap.Extent() )
-          tgtEdges.back().Reverse();
+        const int index = edgeMap.Add( E );
+        if ( index < edgeMap.Extent() ) // E is a seam
+        {
+          // check which of edges to reverse, E or one already being in tgtEdges
+          if ( are2dConnected( tgtEdges.back(), E, tgtFace ))
+          {
+            list< TopoDS_Edge >::iterator eIt = tgtEdges.begin();
+            std::advance( eIt, index-1 );
+            eIt->Reverse();
+          }
+          else
+          {
+            E.Reverse();
+          }
+        }
+        tgtEdges.push_back( E );
       }
       tgtWires[ iW ].reset( new StdMeshers_FaceSide( tgtFace, tgtEdges, tgtMesh,
                                                      /*theIsForward = */ true,
index 730bc5a52e11d78fe6ddae8575aa3e35673ce270..e8a55a2458e5696822669152649bbe16896b7d2b 100644 (file)
@@ -114,7 +114,17 @@ TopoDS_Edge StdMeshers_Propagation::GetPropagationSource(SMESH_Mesh&         the
   return PropagationMgr::GetSource( theMesh.GetSubMeshContaining( theEdge ),
                                     isPropagOfDistribution);
 }
-
+const SMESH_HypoFilter& StdMeshers_Propagation::GetFilter()
+{
+  static SMESH_HypoFilter propagHypFilter;
+  if ( propagHypFilter.IsEmpty() )
+  {
+    propagHypFilter.
+      Init( SMESH_HypoFilter::HasName( StdMeshers_Propagation::GetName ())).
+      Or  ( SMESH_HypoFilter::HasName( StdMeshers_PropagOfDistribution::GetName ()));
+  }
+  return propagHypFilter;
+}
 //=============================================================================
 //=============================================================================
 // PROPAGATION MANAGEMENT
@@ -209,30 +219,27 @@ namespace {
   /*!
    * \brief Returns a local 1D hypothesis used for theEdge
    */
-  const SMESH_Hypothesis* getLocal1DHyp (SMESH_Mesh&         theMesh,
-                                         const TopoDS_Shape& theEdge)
+  const SMESH_Hypothesis* getLocal1DHyp (SMESH_subMesh*      theSubMesh,
+                                         //const TopoDS_Shape& theEdge,
+                                         TopoDS_Shape*       theSssignedTo=0)
   {
     static SMESH_HypoFilter hypo;
     hypo.Init( hypo.HasDim( 1 )).
       AndNot ( hypo.IsAlgo() ).
-      AndNot ( hypo.IsAssignedTo( theMesh.GetMeshDS()->ShapeToMesh() ));
-    return theMesh.GetHypothesis( theEdge, hypo, true );
+      AndNot ( hypo.HasName( StdMeshers_Propagation::GetName() )).
+      AndNot ( hypo.HasName( StdMeshers_PropagOfDistribution::GetName() )).
+      AndNot ( hypo.IsAssignedTo( theSubMesh->GetFather()->GetShapeToMesh() ));
+
+    return theSubMesh->GetFather()->GetHypothesis( theSubMesh, hypo, true, theSssignedTo );
   }
   //=============================================================================
   /*!
    * \brief Returns a propagation hypothesis assigned to theEdge
    */
-  const SMESH_Hypothesis* getProagationHyp (SMESH_Mesh&         theMesh,
-                                            const TopoDS_Shape& theEdge)
+  const SMESH_Hypothesis* getProagationHyp (SMESH_subMesh* theSubMesh)
   {
-    static SMESH_HypoFilter propagHypFilter;
-    if ( propagHypFilter.IsEmpty() )
-    {
-      propagHypFilter.
-        Init( SMESH_HypoFilter::HasName( StdMeshers_Propagation::GetName ())).
-        Or  ( SMESH_HypoFilter::HasName( StdMeshers_PropagOfDistribution::GetName ()));
-    }
-    return theMesh.GetHypothesis( theEdge, propagHypFilter, true );
+    return theSubMesh->GetFather()->GetHypothesis
+      ( theSubMesh, StdMeshers_Propagation::GetFilter(), true );
   }
   //================================================================================
   /*!
@@ -258,10 +265,14 @@ namespace {
 
     SMESH_Mesh* mesh = theMainSubMesh->GetFather();
 
+    TopoDS_Shape shapeOfHyp1D; // shape to which an hyp being propagated is assigned
+    const SMESH_Hypothesis* hyp1D = getLocal1DHyp( theMainSubMesh, &shapeOfHyp1D );
+    SMESH_HypoFilter moreLocalCheck( SMESH_HypoFilter::IsMoreLocalThan( shapeOfHyp1D, *mesh ));
+
     PropagationMgrData* chainData = getData( theMainSubMesh );
     chainData->SetState( HAS_PROPAG_HYP );
 
-    if ( const SMESH_Hypothesis * propagHyp = getProagationHyp( *mesh, theMainEdge ))
+    if ( const SMESH_Hypothesis * propagHyp = getProagationHyp( theMainSubMesh ))
       chainData->myIsPropagOfDistribution =
         ( StdMeshers_PropagOfDistribution::GetName() == propagHyp->GetName() );
 
@@ -273,6 +284,8 @@ namespace {
     TopTools_MapOfShape checkedShapes;
     checkedShapes.Add( theMainEdge );
 
+    vector<TopoDS_Edge> edges;
+
     list<SMESH_subMesh*>::iterator smIt = chain.begin();
     for ( ; smIt != chain.end(); ++smIt )
     {
@@ -289,9 +302,8 @@ namespace {
           continue;
 
         // Get ordered edges and find index of anE in a sequence
+        edges.clear();
         BRepTools_WireExplorer aWE (TopoDS::Wire(itA.Value()));
-        vector<TopoDS_Edge> edges;
-        edges.reserve(4);
         int edgeIndex = 0;
         for (; aWE.More(); aWE.Next()) {
           TopoDS_Edge edge = aWE.Current();
@@ -355,7 +367,8 @@ namespace {
         if ( oppData->State() == WAIT_PROPAG_HYP ) // ... anOppE is not in any chain
         {
           oppData->SetSource( theMainSubMesh );
-          if ( !getLocal1DHyp( *mesh, anOppE )) // ... no 1d hyp on anOppE
+          if ( ! (hyp1D = getLocal1DHyp( oppSM, &shapeOfHyp1D )) || //...no 1d hyp on anOppE
+               ! (moreLocalCheck.IsOk( hyp1D, shapeOfHyp1D ))) // ... or hyp1D is "more global"
           {
             oppData->myForward = data->myForward;
             if ( edges[ edgeIndex ].Orientation() == anOppE.Orientation() )
@@ -366,8 +379,8 @@ namespace {
             DBGMSG( "set IN_CHAIN on " << oppSM->GetId() );
             if ( oppSM->GetAlgoState() != SMESH_subMesh::HYP_OK )
               // make oppSM check algo state
-              if ( SMESH_Algo* algo = mesh->GetGen()->GetAlgo( *mesh, anOppE ))
-                oppSM->AlgoStateEngine(SMESH_subMesh::ADD_FATHER_ALGO,algo);
+              if ( SMESH_Algo* algo = oppSM->GetAlgo() )
+                oppSM->AlgoStateEngine(SMESH_subMesh::ADD_FATHER_ALGO, algo);
           }
           else {
             oppData->SetState( LAST_IN_CHAIN );
@@ -483,7 +496,7 @@ namespace {
     submesh->SetEventListener( getListener(), data, submesh );
 
     const SMESH_Hypothesis * propagHyp =
-      getProagationHyp( *submesh->GetFather(), submesh->GetSubShape() );
+      getProagationHyp( submesh );
     if ( propagHyp )
     {
       data->myIsPropagOfDistribution =
@@ -549,11 +562,10 @@ namespace {
 
     case WAIT_PROPAG_HYP: { // propagation hyp or local 1D hyp is missing
       // --------------------------------------------------------
-      bool hasPropagHyp = ( isPropagHyp ||
-                            getProagationHyp( *subMesh->GetFather(), subMesh->GetSubShape()) );
+      bool hasPropagHyp = ( isPropagHyp || getProagationHyp( subMesh ));
       if ( !hasPropagHyp )
         return;
-      bool hasLocal1DHyp =  getLocal1DHyp( *subMesh->GetFather(), subMesh->GetSubShape());
+      bool hasLocal1DHyp =  getLocal1DHyp( subMesh );
       if ( !hasLocal1DHyp )
         return;
       if ( event == SMESH_subMesh::ADD_HYP ||
@@ -570,7 +582,7 @@ namespace {
       switch ( event ) {
       case SMESH_subMesh::REMOVE_HYP:
       case SMESH_subMesh::REMOVE_FATHER_HYP: // remove propagation hyp
-        if ( isPropagHyp && !getProagationHyp( *subMesh->GetFather(), subMesh->GetSubShape()) )
+        if ( isPropagHyp && !getProagationHyp( subMesh ))
         {
           DBGMSG( "REMOVE_HYP propagation from HAS_PROPAG_HYP " << subMesh->GetId() );
           // clear propagation chain
index fa6acfda3409f434dc9180e07b1eca46dc488438..ca697143bd042a518b1c851a912684fcf87eb297 100644 (file)
@@ -35,6 +35,7 @@
 
 #include <TopoDS_Edge.hxx>
 
+class SMESH_HypoFilter;
 
 // =======================================================================
 /*!
@@ -42,7 +43,7 @@
  */
 // =======================================================================
 
-class STDMESHERS_EXPORT StdMeshers_Propagation:public SMESH_Hypothesis
+class STDMESHERS_EXPORT StdMeshers_Propagation : public SMESH_Hypothesis
 {
  public:
   StdMeshers_Propagation(int hypId, int studyId, SMESH_Gen * gen);
@@ -51,7 +52,13 @@ class STDMESHERS_EXPORT StdMeshers_Propagation:public SMESH_Hypothesis
   virtual std::ostream & SaveTo(std::ostream & save);
   virtual std::istream & LoadFrom(std::istream & load);
 
-  static std::string GetName ();
+  static std::string GetName();
+
+  /*!
+   * \brief Returns a filter selecting both StdMeshers_Propagation and
+   *        StdMeshers_PropagOfDistribution hypotheses
+   */
+  static const SMESH_HypoFilter& GetFilter();
 
   /*!
    * \brief Set EventListener managing propagation of hypotheses
index 8ddd342ca519722167e21236d6cb4989f43209f2..6a0e88c61d9376d97bdc1385454a11d6beb53ff4 100644 (file)
@@ -25,7 +25,6 @@
 #include "StdMeshers_QuadToTriaAdaptor.hxx"
 
 #include "SMDS_SetIterator.hxx"
-
 #include "SMESHDS_GroupBase.hxx"
 #include "SMESH_Algo.hxx"
 #include "SMESH_Group.hxx"
@@ -41,6 +40,7 @@
 #include <TopoDS.hxx>
 #include <gp_Lin.hxx>
 #include <gp_Pln.hxx>
+
 #include "utilities.h"
 
 #include <string>
@@ -119,7 +119,7 @@ namespace
     bool tooClose = ( angle < 15. * M_PI / 180. );
 
     // Check if pyramids collide
-    if ( !tooClose && baI * baJ > 0 )
+    if ( !tooClose && ( baI * baJ > 0 ) && ( nI * nJ > 0 ))
     {
       // find out if nI points outside of PrmI or inside
       int dInd = baseNodesIndI[1] - baseNodesIndI[0];
@@ -1290,7 +1290,7 @@ bool StdMeshers_QuadToTriaAdaptor::Compute2ndPart(SMESH_Mesh&
             nodesToMove.insert( aNode1 );
             nodesToMove.insert( aNode2 );
           }
-          // fix intersections that could appear after apex movement
+          // fix intersections that can appear after apex movement
           MergeAdjacent( PrmI, nodesToMove );
           MergeAdjacent( PrmJ, nodesToMove );
 
index 6ff2210495b413f2bdfe3fc496809c0c47696e6b..a9990e5e7e7aaf475b764d56ac9e684aa8f92205 100644 (file)
@@ -67,9 +67,7 @@
 #ifndef StdMeshers_Array2OfNode_HeaderFile
 #define StdMeshers_Array2OfNode_HeaderFile
 typedef const SMDS_MeshNode* SMDS_MeshNodePtr;
-DEFINE_BASECOLLECTION (StdMeshers_BaseCollectionNodePtr, SMDS_MeshNodePtr)
-DEFINE_ARRAY2(StdMeshers_Array2OfNode,
-              StdMeshers_BaseCollectionNodePtr, SMDS_MeshNodePtr)
+typedef NCollection_Array2<SMDS_MeshNodePtr> StdMeshers_Array2OfNode;
 #endif
 
 using namespace std;
@@ -201,7 +199,9 @@ bool StdMeshers_Quadrangle_2D::CheckHypothesis
     }
   }
 
-  return isOk;
+  error( StdMeshers_ViscousLayers2D::CheckHypothesis( aMesh, aShape, aStatus ));
+
+  return aStatus == HYP_OK;
 }
 
 //=============================================================================
@@ -277,7 +277,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh&         aMesh,
                "two opposite sides should have same number of segments, "
                "but actual number of segments is different on all sides. "
                "'Standard' transion has been used.");
-      else
+      else if ( ! ( n1 == n3 && n2 == n4 ))
         error( COMPERR_WARNING,
                "To use 'Reduced' transition, "
                "two opposite sides should have an even difference in number of segments. "
@@ -4070,7 +4070,7 @@ bool StdMeshers_Quadrangle_2D::check()
       int iPrev = myHelper->WrapIndex( i-1, wire->NbEdges() );
       const TopoDS_Edge& e1 = wire->Edge( iPrev );
       const TopoDS_Edge& e2 = wire->Edge( i );
-      double angle = myHelper->GetAngle( e1, e2, geomFace );
+      double angle = myHelper->GetAngle( e1, e2, geomFace, wire->FirstVertex( i ));
       if (( maxAngle < angle ) &&
           ( 5.* M_PI/180 < angle && angle < 175.* M_PI/180  ))
       {
@@ -4224,7 +4224,7 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face&          theFace,
     TopoDS_Vertex v = helper.IthVertex( 0, *edge );
     if ( !theConsiderMesh || SMESH_Algo::VertexNode( v, helper.GetMeshDS() ))
     {
-      double angle = SMESH_MesherHelper::GetAngle( prevE, *edge, theFace );
+      double angle = SMESH_MesherHelper::GetAngle( prevE, *edge, theFace, v );
       vertexByAngle.insert( make_pair( angle, v ));
       angleByVertex.Bind( v, angle );
     }
index 30612ef3deb340ab1a367b5300866cf6979aa9cd..cb6aa8f7fa83e2b978a51e5d1ddb72f8dedda9ea 100644 (file)
@@ -994,9 +994,9 @@ bool StdMeshers_RadialQuadrangle_1D2D::computeLayerPositions(const gp_Pnt&
     if ( !edge.IsNull() )
     {
       // find a hyp usable by TNodeDistributor
-      SMESH_HypoFilter hypKind;
-      TNodeDistributor::GetDistributor(*mesh)->InitCompatibleHypoFilter(hypKind,/*ignoreAux=*/1);
-      hyp1D = mesh->GetHypothesis( edge, hypKind, /*fromAncestors=*/true);
+      const SMESH_HypoFilter* hypKind =
+        TNodeDistributor::GetDistributor(*mesh)->GetCompatibleHypoFilter(/*ignoreAux=*/true);
+      hyp1D = mesh->GetHypothesis( edge, *hypKind, /*fromAncestors=*/true);
     }
   }
   if ( hyp1D ) // try to compute with hyp1D
index f3449e85df61d1926df7074cbec8d7d107dbb9dc..cc964cfac209d603d8daf2111fc155f82f734529 100644 (file)
@@ -112,7 +112,7 @@ StdMeshers_Regular_1D::~StdMeshers_Regular_1D()
 
 //=============================================================================
 /*!
- *  
+ *
  */
 //=============================================================================
 
@@ -127,13 +127,18 @@ bool StdMeshers_Regular_1D::CheckHypothesis( SMESH_Mesh&         aMesh,
   const list <const SMESHDS_Hypothesis * > & hyps =
     GetUsedHypothesis(aMesh, aShape, /*ignoreAuxiliaryHyps=*/false);
 
+  const SMESH_HypoFilter & propagFilter = StdMeshers_Propagation::GetFilter();
+
   // find non-auxiliary hypothesis
   const SMESHDS_Hypothesis *theHyp = 0;
+  set< string > propagTypes;
   list <const SMESHDS_Hypothesis * >::const_iterator h = hyps.begin();
   for ( ; h != hyps.end(); ++h ) {
     if ( static_cast<const SMESH_Hypothesis*>(*h)->IsAuxiliary() ) {
       if ( strcmp( "QuadraticMesh", (*h)->GetName() ) == 0 )
         _quadraticMesh = true;
+      if ( propagFilter.IsOk( static_cast< const SMESH_Hypothesis*>( *h ), aShape ))
+        propagTypes.insert( (*h)->GetName() );
     }
     else {
       if ( !theHyp )
@@ -293,11 +298,48 @@ bool StdMeshers_Regular_1D::CheckHypothesis( SMESH_Mesh&         aMesh,
     ASSERT(_adaptiveHyp);
     _hypType = ADAPTIVE;
     _onlyUnaryInput = false;
+    aStatus = SMESH_Hypothesis::HYP_OK;
   }
   else
+  {
     aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
+  }
+
+  if ( propagTypes.size() > 1 && aStatus == HYP_OK )
+  {
+    // detect concurrent Propagation hyps
+    _usedHypList.clear();
+    list< TopoDS_Shape > assignedTo;
+    if ( aMesh.GetHypotheses( aShape, propagFilter, _usedHypList, true, &assignedTo ) > 1 )
+    {
+      // find most simple shape and a hyp on it
+      int simpleShape = TopAbs_COMPOUND;
+      const SMESHDS_Hypothesis* localHyp = 0;
+      list< TopoDS_Shape >::iterator            shape = assignedTo.begin();
+      list< const SMESHDS_Hypothesis *>::iterator hyp = _usedHypList.begin();
+      for ( ; shape != assignedTo.end(); ++shape )
+        if ( shape->ShapeType() > simpleShape )
+        {
+          simpleShape = shape->ShapeType();
+          localHyp = (*hyp);
+        }
+      // check if there a different hyp on simpleShape
+      shape = assignedTo.begin();
+      hyp = _usedHypList.begin();
+      for ( ; hyp != _usedHypList.end(); ++hyp, ++shape )
+        if ( shape->ShapeType() == simpleShape &&
+             !localHyp->IsSameName( **hyp ))
+        {
+          aStatus = HYP_INCOMPAT_HYPS;
+          return error( SMESH_Comment("Hypotheses of both \"")
+                        << StdMeshers_Propagation::GetName() << "\" and \""
+                        << StdMeshers_PropagOfDistribution::GetName()
+                        << "\" types can't be applied to the same edge");
+        }
+    }
+  }
 
-  return ( _hypType != NONE );
+  return ( aStatus == SMESH_Hypothesis::HYP_OK );
 }
 
 static bool computeParamByFunc(Adaptor3d_Curve& C3d, double first, double last,
@@ -1336,12 +1378,11 @@ StdMeshers_Regular_1D::GetUsedHypothesis(SMESH_Mesh &         aMesh,
   _usedHypList.clear();
   _mainEdge.Nullify();
 
-  SMESH_HypoFilter auxiliaryFilter, compatibleFilter;
-  auxiliaryFilter.Init( SMESH_HypoFilter::IsAuxiliary() );
-  InitCompatibleHypoFilter( compatibleFilter, /*ignoreAux=*/true );
+  SMESH_HypoFilter auxiliaryFilter( SMESH_HypoFilter::IsAuxiliary() );
+  const SMESH_HypoFilter* compatibleFilter = GetCompatibleHypoFilter(/*ignoreAux=*/true );
 
   // get non-auxiliary assigned directly to aShape
-  int nbHyp = aMesh.GetHypotheses( aShape, compatibleFilter, _usedHypList, false );
+  int nbHyp = aMesh.GetHypotheses( aShape, *compatibleFilter, _usedHypList, false );
 
   if (nbHyp == 0 && aShape.ShapeType() == TopAbs_EDGE)
   {
@@ -1352,7 +1393,7 @@ StdMeshers_Regular_1D::GetUsedHypothesis(SMESH_Mesh &         aMesh,
     {
       // Propagation of 1D hypothesis from <aMainEdge> on this edge;
       // get non-auxiliary assigned to _mainEdge
-      nbHyp = aMesh.GetHypotheses( _mainEdge, compatibleFilter, _usedHypList, true );
+      nbHyp = aMesh.GetHypotheses( _mainEdge, *compatibleFilter, _usedHypList, true );
     }
   }
 
index 71de50af30bef0f02252ae8e774da85d05b65560..db5469ea228a823a843cc75993ed49714f634883 100644 (file)
@@ -94,6 +94,14 @@ namespace VISCOUS_3D
 
   enum UIndex { U_TGT = 1, U_SRC, LEN_TGT };
 
+  const double theMinSmoothCosin = 0.1;
+  const double theSmoothThickToElemSizeRatio = 0.3;
+
+  bool needSmoothing( double cosin, double tgtThick, double elemSize )
+  {
+    return cosin * tgtThick > theSmoothThickToElemSizeRatio * elemSize;
+  }
+
   /*!
    * \brief SMESH_ProxyMesh computed by _ViscousBuilder for a SOLID.
    * It is stored in a SMESH_subMesh of the SOLID as SMESH_subMeshEventListenerData
@@ -284,6 +292,7 @@ namespace VISCOUS_3D
         c = new _Curvature;
         c->_r = avgDist * avgDist / avgNormProj;
         c->_k = avgDist * avgDist / c->_r / c->_r;
+        //c->_k = avgNormProj / c->_r;
         c->_k *= ( c->_r < 0 ? 1/1.1 : 1.1 ); // not to be too restrictive
         c->_h2lenRatio = avgNormProj / ( avgDist + avgDist );
       }
@@ -292,29 +301,7 @@ namespace VISCOUS_3D
     double lenDelta(double len) const { return _k * ( _r + len ); }
     double lenDeltaByDist(double dist) const { return dist * _h2lenRatio; }
   };
-  struct _LayerEdge;
-  //--------------------------------------------------------------------------------
-  /*!
-   * Structure used to smooth a _LayerEdge (master) based on an EDGE.
-   */
-  struct _2NearEdges
-  {
-    // target nodes of 2 neighbour _LayerEdge's based on the same EDGE
-    const SMDS_MeshNode* _nodes[2];
-    // vectors from source nodes of 2 _LayerEdge's to the source node of master _LayerEdge
-    //gp_XYZ               _vec[2];
-    double               _wgt[2]; // weights of _nodes
-    _LayerEdge*          _edges[2];
-
-     // normal to plane passing through _LayerEdge._normal and tangent of EDGE
-    gp_XYZ*              _plnNorm;
-
-    _2NearEdges() { _nodes[0]=_nodes[1]=0; _plnNorm = 0; }
-    void reverse() {
-      std::swap( _nodes[0], _nodes[1] );
-      std::swap( _wgt[0], _wgt[1] );
-    }
-  };
+  struct _2NearEdges;
   //--------------------------------------------------------------------------------
   /*!
    * \brief Edge normal to surface, connecting a node on solid surface (_nodes[0])
@@ -348,7 +335,7 @@ namespace VISCOUS_3D
     void SetDataByNeighbors( const SMDS_MeshNode* n1,
                              const SMDS_MeshNode* n2,
                              SMESH_MesherHelper&  helper);
-    void InvalidateStep( int curStep );
+    void InvalidateStep( int curStep, bool restoreLength=false );
     bool Smooth(int& badNb);
     bool SmoothOnEdge(Handle(Geom_Surface)& surface,
                       const TopoDS_Face&    F,
@@ -364,9 +351,11 @@ namespace VISCOUS_3D
                        double&              dist,
                        const double&        epsilon) const;
     gp_Ax1 LastSegment(double& segLen) const;
-    bool IsOnEdge() const { return _2neibors; }
+    gp_XY  LastUV( const TopoDS_Face& F ) const;
+    bool   IsOnEdge() const { return _2neibors; }
     gp_XYZ Copy( _LayerEdge& other, SMESH_MesherHelper& helper );
-    void SetCosin( double cosin );
+    void   SetCosin( double cosin );
+    int    NbSteps() const { return _pos.size() - 1; } // nb inlation steps
   };
   struct _LayerEdgeCmp
   {
@@ -376,6 +365,86 @@ namespace VISCOUS_3D
       return cmpNodes ? ( e1->_nodes[0]->GetID() < e2->_nodes[0]->GetID()) : ( e1 < e2 );
     }
   };
+  struct _LayerEdge;
+  //--------------------------------------------------------------------------------
+  /*!
+   * Structure used to smooth a _LayerEdge based on an EDGE.
+   */
+  struct _2NearEdges
+  {
+    double               _wgt  [2]; // weights of _nodes
+    _LayerEdge*          _edges[2];
+
+     // normal to plane passing through _LayerEdge._normal and tangent of EDGE
+    gp_XYZ*              _plnNorm;
+
+    _2NearEdges() { _edges[0]=_edges[1]=0; _plnNorm = 0; }
+    const SMDS_MeshNode* tgtNode(bool is2nd) {
+      return _edges[is2nd] ? _edges[is2nd]->_nodes.back() : 0;
+    }
+    const SMDS_MeshNode* srcNode(bool is2nd) {
+      return _edges[is2nd] ? _edges[is2nd]->_nodes[0] : 0;
+    }
+    void reverse() {
+      std::swap( _wgt  [0], _wgt  [1] );
+      std::swap( _edges[0], _edges[1] );
+    }
+  };
+  //--------------------------------------------------------------------------------
+  /*!
+   * \brief Convex FACE whose radius of curvature is less than the thickness of 
+   *        layers. It is used to detect distortion of prisms based on a convex
+   *        FACE and to update normals to enable further increasing the thickness
+   */
+  struct _ConvexFace
+  {
+    TopoDS_Face                     _face;
+
+    // edges whose _simplices are used to detect prism destorsion
+    vector< _LayerEdge* >           _simplexTestEdges;
+
+    // map a sub-shape to it's index in _SolidData::_endEdgeOnShape vector
+    map< TGeomID, int >             _subIdToEdgeEnd;
+
+    bool                            _normalsFixed;
+
+    bool GetCenterOfCurvature( _LayerEdge*         ledge,
+                               BRepLProp_SLProps&  surfProp,
+                               SMESH_MesherHelper& helper,
+                               gp_Pnt &            center ) const;
+    bool CheckPrisms() const;
+  };
+
+  //--------------------------------------------------------------------------------
+  /*!
+   * \brief Layers parameters got by averaging several hypotheses
+   */
+  struct AverageHyp
+  {
+    AverageHyp( const StdMeshers_ViscousLayers* hyp = 0 )
+      :_nbLayers(0), _nbHyps(0), _thickness(0), _stretchFactor(0)
+    {
+      Add( hyp );
+    }
+    void Add( const StdMeshers_ViscousLayers* hyp )
+    {
+      if ( hyp )
+      {
+        _nbHyps++;
+        _nbLayers       = hyp->GetNumberLayers();
+        //_thickness     += hyp->GetTotalThickness();
+        _thickness     = Max( _thickness, hyp->GetTotalThickness() );
+        _stretchFactor += hyp->GetStretchFactor();
+      }
+    }
+    double GetTotalThickness() const { return _thickness; /*_nbHyps ? _thickness / _nbHyps : 0;*/ }
+    double GetStretchFactor()  const { return _nbHyps ? _stretchFactor / _nbHyps : 0; }
+    int    GetNumberLayers()   const { return _nbLayers; }
+  private:
+    int     _nbLayers, _nbHyps;
+    double  _thickness, _stretchFactor;
+  };
+
   //--------------------------------------------------------------------------------
 
   typedef map< const SMDS_MeshNode*, _LayerEdge*, TIDCompare > TNode2Edge;
@@ -386,24 +455,26 @@ namespace VISCOUS_3D
    */
   struct _SolidData
   {
+    typedef const StdMeshers_ViscousLayers* THyp;
     TopoDS_Shape                    _solid;
-    const StdMeshers_ViscousLayers* _hyp;
-    TopoDS_Shape                    _hypShape;
+    TGeomID                         _index; // SOLID id
     _MeshOfSolid*                   _proxyMesh;
-    set<TGeomID>                    _reversedFaceIds;
-    set<TGeomID>                    _ignoreFaceIds;
+    list< THyp >                    _hyps;
+    list< TopoDS_Shape >            _hypShapes;
+    map< TGeomID, THyp >            _face2hyp; // filled if _hyps.size() > 1
+    set< TGeomID >                  _reversedFaceIds;
+    set< TGeomID >                  _ignoreFaceIds; // WOL FACEs and FACEs of other SOLIDs
 
-    double                          _stepSize, _stepSizeCoeff;
+    double                          _stepSize, _stepSizeCoeff, _geomSize;
     const SMDS_MeshNode*            _stepSizeNodes[2];
 
-    TNode2Edge                      _n2eMap;
+    TNode2Edge                      _n2eMap; // nodes and _LayerEdge's based on them
+
     // map to find _n2eMap of another _SolidData by a shrink shape shared by two _SolidData's
     map< TGeomID, TNode2Edge* >     _s2neMap;
     // edges of _n2eMap. We keep same data in two containers because
-    // iteration over the map is 5 time longer than over the vector
+    // iteration over the map is 5 times longer than over the vector
     vector< _LayerEdge* >           _edges;
-    // edges on EDGE's with null _sWOL, whose _simplices are used to stop inflation
-    vector< _LayerEdge* >           _simplexTestEdges;
 
     // key:   an id of shape (EDGE or VERTEX) shared by a FACE with
     //        layers and a FACE w/o layers
@@ -411,24 +482,30 @@ namespace VISCOUS_3D
     //       _LayerEdge's basing on nodes on key shape are inflated along the value shape
     map< TGeomID, TopoDS_Shape >     _shrinkShape2Shape;
 
-    // FACE's WOL, srink on which is forbiden due to algo on the adjacent SOLID
-    set< TGeomID >                   _noShrinkFaces;
+    // Convex FACEs whose radius of curvature is less than the thickness of layers
+    map< TGeomID, _ConvexFace >      _convexFaces;
 
-    // <EDGE to smooth on> to <it's curve>
+    // shapes (EDGEs and VERTEXes) srink from which is forbiden due to collisions with
+    // the adjacent SOLID
+    set< TGeomID >                   _noShrinkShapes;
+
+    // <EDGE to smooth on> to <it's curve> -- for analytic smooth
     map< TGeomID,Handle(Geom_Curve)> _edge2curve;
 
-    // end indices in _edges of _LayerEdge on one shape to smooth
-    vector< int >                    _endEdgeToSmooth;
+    // end indices in _edges of _LayerEdge on each shape, first go shapes to smooth
+    vector< int >                    _endEdgeOnShape;
+    int                              _nbShapesToSmooth;
 
-    double                           _epsilon; // precision for SegTriaInter()
+    // data of averaged StdMeshers_ViscousLayers parameters for each shape with _LayerEdge's
+    vector< AverageHyp >             _hypOnShape;
+    double                           _maxThickness; // of all _hyps
+    double                           _minThickness; // of all _hyps
 
-    int                              _index; // for debug
+    double                           _epsilon; // precision for SegTriaInter()
 
-    _SolidData(const TopoDS_Shape&             s=TopoDS_Shape(),
-               const StdMeshers_ViscousLayers* h=0,
-               const TopoDS_Shape&             hs=TopoDS_Shape(),
-               _MeshOfSolid*                   m=0)
-      :_solid(s), _hyp(h), _hypShape(hs), _proxyMesh(m) {}
+    _SolidData(const TopoDS_Shape& s=TopoDS_Shape(),
+               _MeshOfSolid*       m=0)
+      :_solid(s), _proxyMesh(m) {}
     ~_SolidData();
 
     Handle(Geom_Curve) CurveForSmooth( const TopoDS_Edge&    E,
@@ -437,6 +514,56 @@ namespace VISCOUS_3D
                                        Handle(Geom_Surface)& surface,
                                        const TopoDS_Face&    F,
                                        SMESH_MesherHelper&   helper);
+
+    void SortOnEdge( const TopoDS_Edge&  E,
+                     const int           iFrom,
+                     const int           iTo,
+                     SMESH_MesherHelper& helper);
+
+    _ConvexFace* GetConvexFace( const TGeomID faceID )
+    {
+      map< TGeomID, _ConvexFace >::iterator id2face = _convexFaces.find( faceID );
+      return id2face == _convexFaces.end() ? 0 : & id2face->second;
+    }
+    void GetEdgesOnShape( size_t end, int &  iBeg, int &  iEnd )
+    {
+      iBeg = end > 0 ? _endEdgeOnShape[ end-1 ] : 0;
+      iEnd = _endEdgeOnShape[ end ];
+    }
+
+    bool GetShapeEdges(const TGeomID shapeID, size_t& iEdgeEnd, int* iBeg=0, int* iEnd=0 ) const;
+
+    void AddShapesToSmooth( const set< TGeomID >& shapeIDs );
+  };
+  //--------------------------------------------------------------------------------
+  /*!
+   * \brief Container of centers of curvature at nodes on an EDGE bounding _ConvexFace
+   */
+  struct _CentralCurveOnEdge
+  {
+    bool                  _isDegenerated;
+    vector< gp_Pnt >      _curvaCenters;
+    vector< _LayerEdge* > _ledges;
+    vector< gp_XYZ >      _normals; // new normal for each of _ledges
+    vector< double >      _segLength2;
+
+    TopoDS_Edge           _edge;
+    TopoDS_Face           _adjFace;
+    bool                  _adjFaceToSmooth;
+
+    void Append( const gp_Pnt& center, _LayerEdge* ledge )
+    {
+      if ( _curvaCenters.size() > 0 )
+        _segLength2.push_back( center.SquareDistance( _curvaCenters.back() ));
+      _curvaCenters.push_back( center );
+      _ledges.push_back( ledge );
+      _normals.push_back( ledge->_normal );
+    }
+    bool FindNewNormal( const gp_Pnt& center, gp_XYZ& newNormal );
+    void SetShapes( const TopoDS_Edge&  edge,
+                    const _ConvexFace&  convFace,
+                    const _SolidData&   data,
+                    SMESH_MesherHelper& helper);
   };
   //--------------------------------------------------------------------------------
   /*!
@@ -445,7 +572,6 @@ namespace VISCOUS_3D
   struct _SmoothNode
   {
     const SMDS_MeshNode*         _node;
-    //vector<const SMDS_MeshNode*> _nodesAround;
     vector<_Simplex>             _simplices; // for quality check
 
     enum SmoothType { LAPLACIAN, CENTROIDAL, ANGULAR, TFI };
@@ -472,6 +598,9 @@ namespace VISCOUS_3D
     // does it's job
     SMESH_ComputeErrorPtr Compute(SMESH_Mesh&         mesh,
                                   const TopoDS_Shape& shape);
+    // check validity of hypotheses
+    SMESH_ComputeErrorPtr CheckHypotheses( SMESH_Mesh&         mesh,
+                                           const TopoDS_Shape& shape );
 
     // restore event listeners used to clear an inferior dim sub-mesh modified by viscous layers
     void RestoreListeners();
@@ -482,7 +611,11 @@ namespace VISCOUS_3D
   private:
 
     bool findSolidsWithLayers();
-    bool findFacesWithLayers();
+    bool findFacesWithLayers(const bool onlyWith=false);
+    void getIgnoreFaces(const TopoDS_Shape&             solid,
+                        const StdMeshers_ViscousLayers* hyp,
+                        const TopoDS_Shape&             hypShape,
+                        set<TGeomID>&                   ignoreFaces);
     bool makeLayer(_SolidData& data);
     bool setEdgeData(_LayerEdge& edge, const set<TGeomID>& subIds,
                      SMESH_MesherHelper& helper, _SolidData& data);
@@ -504,13 +637,13 @@ namespace VISCOUS_3D
                        const bool          toSort = false);
     void findSimplexTestEdges( _SolidData&                    data,
                                vector< vector<_LayerEdge*> >& edgesByGeom);
+    void computeGeomSize( _SolidData& data );
     bool sortEdges( _SolidData&                    data,
                     vector< vector<_LayerEdge*> >& edgesByGeom);
-    void limitStepSizeByCurvature( _SolidData&                    data,
-                                   vector< vector<_LayerEdge*> >& edgesByGeom);
+    void limitStepSizeByCurvature( _SolidData&  data );
     void limitStepSize( _SolidData&             data,
                         const SMDS_MeshElement* face,
-                        const double            cosin);
+                        const _LayerEdge*       maxCosinEdge );
     void limitStepSize( _SolidData& data, const double minSize);
     bool inflate(_SolidData& data);
     bool smoothAndCheck(_SolidData& data, const int nbSteps, double & distToIntersection);
@@ -520,12 +653,16 @@ namespace VISCOUS_3D
                              Handle(Geom_Surface)& surface,
                              const TopoDS_Face&    F,
                              SMESH_MesherHelper&   helper);
-    bool updateNormals( _SolidData& data, SMESH_MesherHelper& helper );
+    bool updateNormals( _SolidData& data, SMESH_MesherHelper& helper, int stepNb );
+    bool updateNormalsOfConvexFaces( _SolidData&         data,
+                                     SMESH_MesherHelper& helper,
+                                     int                 stepNb );
     bool refine(_SolidData& data);
     bool shrink();
     bool prepareEdgeToShrink( _LayerEdge& edge, const TopoDS_Face& F,
                               SMESH_MesherHelper& helper,
                               const SMESHDS_SubMesh* faceSubMesh );
+    void restoreNoShrink( _LayerEdge& edge ) const;
     void fixBadFaces(const TopoDS_Face&          F,
                      SMESH_MesherHelper&         helper,
                      const bool                  is2D,
@@ -534,7 +671,7 @@ namespace VISCOUS_3D
     bool addBoundaryElements();
 
     bool error( const string& text, int solidID=-1 );
-    SMESHDS_Mesh* getMeshDS() { return _mesh->GetMeshDS(); }
+    SMESHDS_Mesh* getMeshDS() const { return _mesh->GetMeshDS(); }
 
     // debug
     void makeGroupOfLE();
@@ -568,16 +705,17 @@ namespace VISCOUS_3D
    * We can't use SMDS_FaceOfNodes since it's impossible to set it's ID which is
    * needed because SMESH_ElementSearcher internaly uses set of elements sorted by ID
    */
-  struct TmpMeshFace : public SMDS_MeshElement
+  struct _TmpMeshFace : public SMDS_MeshElement
   {
     vector<const SMDS_MeshNode* > _nn;
-    TmpMeshFace( const vector<const SMDS_MeshNode*>& nodes, int id):
-      SMDS_MeshElement(id), _nn(nodes) {}
+    _TmpMeshFace( const vector<const SMDS_MeshNode*>& nodes, int id, int faceID=-1):
+      SMDS_MeshElement(id), _nn(nodes) { setShapeId(faceID); }
     virtual const SMDS_MeshNode* GetNode(const int ind) const { return _nn[ind]; }
     virtual SMDSAbs_ElementType  GetType() const              { return SMDSAbs_Face; }
     virtual vtkIdType GetVtkType() const                      { return -1; }
     virtual SMDSAbs_EntityType   GetEntityType() const        { return SMDSEntity_Last; }
-    virtual SMDSAbs_GeometryType GetGeomType() const          { return SMDSGeom_TRIANGLE; }
+    virtual SMDSAbs_GeometryType GetGeomType() const
+    { return _nn.size() == 3 ? SMDSGeom_TRIANGLE : SMDSGeom_QUADRANGLE; }
     virtual SMDS_ElemIteratorPtr elementsIterator(SMDSAbs_ElementType) const
     { return SMDS_ElemIteratorPtr( new SMDS_NodeVectorElemIterator( _nn.begin(), _nn.end()));}
   };
@@ -585,11 +723,11 @@ namespace VISCOUS_3D
   /*!
    * \brief Class of temporary mesh face storing _LayerEdge it's based on
    */
-  struct TmpMeshFaceOnEdge : public TmpMeshFace
+  struct _TmpMeshFaceOnEdge : public _TmpMeshFace
   {
     _LayerEdge *_le1, *_le2;
-    TmpMeshFaceOnEdge( _LayerEdge* le1, _LayerEdge* le2, int ID ):
-      TmpMeshFace( vector<const SMDS_MeshNode*>(4), ID ), _le1(le1), _le2(le2)
+    _TmpMeshFaceOnEdge( _LayerEdge* le1, _LayerEdge* le2, int ID ):
+      _TmpMeshFace( vector<const SMDS_MeshNode*>(4), ID ), _le1(le1), _le2(le2)
     {
       _nn[0]=_le1->_nodes[0];
       _nn[1]=_le1->_nodes.back();
@@ -602,14 +740,14 @@ namespace VISCOUS_3D
    * \brief Retriever of node coordinates either directly of from a surface by node UV.
    * \warning Location of a surface is ignored
    */
-  struct NodeCoordHelper
+  struct _NodeCoordHelper
   {
     SMESH_MesherHelper&        _helper;
     const TopoDS_Face&         _face;
     Handle(Geom_Surface)       _surface;
-    gp_XYZ (NodeCoordHelper::* _fun)(const SMDS_MeshNode* n) const;
+    gp_XYZ (_NodeCoordHelper::* _fun)(const SMDS_MeshNode* n) const;
 
-    NodeCoordHelper(const TopoDS_Face& F, SMESH_MesherHelper& helper, bool is2D)
+    _NodeCoordHelper(const TopoDS_Face& F, SMESH_MesherHelper& helper, bool is2D)
       : _helper( helper ), _face( F )
     {
       if ( is2D )
@@ -618,9 +756,9 @@ namespace VISCOUS_3D
         _surface = BRep_Tool::Surface( _face, loc );
       }
       if ( _surface.IsNull() )
-        _fun = & NodeCoordHelper::direct;
+        _fun = & _NodeCoordHelper::direct;
       else
-        _fun = & NodeCoordHelper::byUV;
+        _fun = & _NodeCoordHelper::byUV;
     }
     gp_XYZ operator()(const SMDS_MeshNode* n) const { return (this->*_fun)( n ); }
 
@@ -635,8 +773,11 @@ namespace VISCOUS_3D
       return _surface->Value( uv.X(), uv.Y() ).XYZ();
     }
   };
+
 } // namespace VISCOUS_3D
 
+
+
 //================================================================================
 // StdMeshers_ViscousLayers hypothesis
 //
@@ -733,6 +874,27 @@ bool StdMeshers_ViscousLayers::SetParametersByMesh(const SMESH_Mesh*   theMesh,
 {
   // TODO
   return false;
+} // --------------------------------------------------------------------------------
+SMESH_ComputeErrorPtr
+StdMeshers_ViscousLayers::CheckHypothesis(SMESH_Mesh&                          theMesh,
+                                          const TopoDS_Shape&                  theShape,
+                                          SMESH_Hypothesis::Hypothesis_Status& theStatus)
+{
+  VISCOUS_3D::_ViscousBuilder bulder;
+  SMESH_ComputeErrorPtr err = bulder.CheckHypotheses( theMesh, theShape );
+  if ( err && !err->IsOK() )
+    theStatus = SMESH_Hypothesis::HYP_INCOMPAT_HYPS;
+  else
+    theStatus = SMESH_Hypothesis::HYP_OK;
+
+  return err;
+}
+// --------------------------------------------------------------------------------
+bool StdMeshers_ViscousLayers::IsShapeWithLayers(int shapeIndex) const
+{
+  bool isIn =
+    ( std::find( _shapeIds.begin(), _shapeIds.end(), shapeIndex ) != _shapeIds.end() );
+  return IsToIgnoreShapes() ? !isIn : isIn;
 }
 // END StdMeshers_ViscousLayers hypothesis
 //================================================================================
@@ -758,22 +920,32 @@ namespace
     gp_Vec dir;
     double f,l; gp_Pnt p;
     Handle(Geom_Curve) c = BRep_Tool::Curve( E, f, l );
+    if ( c.IsNull() ) return gp_XYZ( 1e100, 1e100, 1e100 );
     double u = helper.GetNodeU( E, atNode );
     c->D1( u, p, dir );
     return dir.XYZ();
   }
   //--------------------------------------------------------------------------------
+  gp_XYZ getFaceDir( const TopoDS_Face& F, const TopoDS_Vertex& fromV,
+                     const SMDS_MeshNode* node, SMESH_MesherHelper& helper, bool& ok,
+                     double* cosin=0);
+  //--------------------------------------------------------------------------------
   gp_XYZ getFaceDir( const TopoDS_Face& F, const TopoDS_Edge& fromE,
                      const SMDS_MeshNode* node, SMESH_MesherHelper& helper, bool& ok)
   {
+    double f,l;
+    Handle(Geom_Curve) c = BRep_Tool::Curve( fromE, f, l );
+    if ( c.IsNull() )
+    {
+      TopoDS_Vertex v = helper.IthVertex( 0, fromE );
+      return getFaceDir( F, v, node, helper, ok );
+    }
     gp_XY uv = helper.GetNodeUV( F, node, 0, &ok );
     Handle(Geom_Surface) surface = BRep_Tool::Surface( F );
     gp_Pnt p; gp_Vec du, dv, norm;
     surface->D1( uv.X(),uv.Y(), p, du,dv );
     norm = du ^ dv;
 
-    double f,l;
-    Handle(Geom_Curve) c = BRep_Tool::Curve( fromE, f, l );
     double u = helper.GetNodeU( fromE, node, 0, &ok );
     c->D1( u, p, du );
     TopAbs_Orientation o = helper.GetSubShapeOri( F.Oriented(TopAbs_FORWARD), fromE);
@@ -797,7 +969,7 @@ namespace
   //--------------------------------------------------------------------------------
   gp_XYZ getFaceDir( const TopoDS_Face& F, const TopoDS_Vertex& fromV,
                      const SMDS_MeshNode* node, SMESH_MesherHelper& helper,
-                     bool& ok, double* cosin=0)
+                     bool& ok, double* cosin)
   {
     TopoDS_Face faceFrw = F;
     faceFrw.Orientation( TopAbs_FORWARD );
@@ -813,12 +985,12 @@ namespace
         if ( SMESH_Algo::isDegenerated( e )) continue;
         TopExp::Vertices( e, VV[0], VV[1], /*CumOri=*/true );
         if ( VV[1].IsSame( fromV )) {
+          nbEdges += edges[ 0 ].IsNull();
           edges[ 0 ] = e;
-          nbEdges++;
         }
         else if ( VV[0].IsSame( fromV )) {
+          nbEdges += edges[ 1 ].IsNull();
           edges[ 1 ] = e;
-          nbEdges++;
         }
       }
     }
@@ -838,7 +1010,7 @@ namespace
 
       // get angle between the 2 edges
       gp_Vec faceNormal;
-      double angle = helper.GetAngle( edges[0], edges[1], faceFrw, &faceNormal );
+      double angle = helper.GetAngle( edges[0], edges[1], faceFrw, fromV, &faceNormal );
       if ( Abs( angle ) < 5 * M_PI/180 )
       {
         dir = ( faceNormal.XYZ() ^ edgeDir[0].Reversed()) + ( faceNormal.XYZ() ^ edgeDir[1] );
@@ -856,7 +1028,7 @@ namespace
     }
     else if ( nbEdges == 1 )
     {
-      dir = getFaceDir( faceFrw, edges[0], node, helper, ok );
+      dir = getFaceDir( faceFrw, edges[ edges[0].IsNull() ], node, helper, ok );
       if ( cosin ) *cosin = 1.;
     }
     else
@@ -899,32 +1071,10 @@ namespace
           cross = -cross;
         isConvex = ( cross > 0.1 ); //-1e-9 );
       }
-      // check if concavity is strong enough to care about it
-      //const double maxAngle = 5 * Standard_PI180;
       if ( !isConvex )
       {
         //cout << "Concave FACE " << helper.GetMeshDS()->ShapeToIndex( F ) << endl;
         return true;
-        // map< double, const SMDS_MeshNode* > u2nodes;
-        // if ( !SMESH_Algo::GetSortedNodesOnEdge( helper.GetMeshDS(), E,
-        //                                         /*ignoreMedium=*/true, u2nodes))
-        //   continue;
-        // map< double, const SMDS_MeshNode* >::iterator u2n = u2nodes.begin();
-        // gp_Pnt2d uvPrev = helper.GetNodeUV( F, u2n->second );
-        // double    uPrev = u2n->first;
-        // for ( ++u2n; u2n != u2nodes.end(); ++u2n )
-        // {
-        //   gp_Pnt2d uv = helper.GetNodeUV( F, u2n->second );
-        //   gp_Vec2d segmentDir( uvPrev, uv );
-        //   curve.D1( uPrev, p, drv1 );
-        //   try {
-        //     if ( fabs( segmentDir.Angle( drv1 )) > maxAngle )
-        //       return true;
-        //   }
-        //   catch ( ... ) {}
-        //   uvPrev = uv;
-        //   uPrev = u2n->first;
-        // }
       }
     }
     // check angles at VERTEXes
@@ -942,17 +1092,74 @@ namespace
         while ( SMESH_Algo::isDegenerated( wires[iW]->Edge( iE2 )))
           iE2 = ( iE2 + 1 ) % nbEdges;
         double angle = helper.GetAngle( wires[iW]->Edge( iE1 ),
-                                        wires[iW]->Edge( iE2 ), F );
+                                        wires[iW]->Edge( iE2 ), F,
+                                        wires[iW]->FirstVertex( iE2 ));
         if ( angle < -5. * M_PI / 180. )
           return true;
       }
     }
     return false;
   }
+  //================================================================================
+  /*!
+   * \brief Computes mimimal distance of face in-FACE nodes from an EDGE
+   *  \param [in] face - the mesh face to treat
+   *  \param [in] nodeOnEdge - a node on the EDGE
+   *  \param [out] faceSize - the computed distance
+   *  \return bool - true if faceSize computed
+   */
+  //================================================================================
+
+  bool getDistFromEdge( const SMDS_MeshElement* face,
+                        const SMDS_MeshNode*    nodeOnEdge,
+                        double &                faceSize )
+  {
+    faceSize = Precision::Infinite();
+    bool done = false;
+
+    int nbN  = face->NbCornerNodes();
+    int iOnE = face->GetNodeIndex( nodeOnEdge );
+    int iNext[2] = { SMESH_MesherHelper::WrapIndex( iOnE+1, nbN ),
+                     SMESH_MesherHelper::WrapIndex( iOnE-1, nbN ) };
+    const SMDS_MeshNode* nNext[2] = { face->GetNode( iNext[0] ),
+                                      face->GetNode( iNext[1] ) };
+    gp_XYZ segVec, segEnd = SMESH_TNodeXYZ( nodeOnEdge ); // segment on EDGE
+    double segLen = -1.;
+    // look for two neighbor not in-FACE nodes of face
+    for ( int i = 0; i < 2; ++i )
+    {
+      if ( nNext[i]->GetPosition()->GetDim() != 2 &&
+           nNext[i]->GetID() < nodeOnEdge->GetID() )
+      {
+        // look for an in-FACE node
+        for ( int iN = 0; iN < nbN; ++iN )
+        {
+          if ( iN == iOnE || iN == iNext[i] )
+            continue;
+          SMESH_TNodeXYZ pInFace = face->GetNode( iN );
+          gp_XYZ v = pInFace - segEnd;
+          if ( segLen < 0 )
+          {
+            segVec = SMESH_TNodeXYZ( nNext[i] ) - segEnd;
+            segLen = segVec.Modulus();
+          }
+          double distToSeg = v.Crossed( segVec ).Modulus() / segLen;
+          faceSize = Min( faceSize, distToSeg );
+          done = true;
+        }
+        segLen = -1;
+      }
+    }
+    return done;
+  }
+
   //--------------------------------------------------------------------------------
   // DEBUG. Dump intermediate node positions into a python script
+  // HOWTO use: run python commands written in a console to see
+  //  construction steps of viscous layers
 #ifdef __myDEBUG
   ofstream* py;
+  int       theNbFunc;
   struct PyDump {
     PyDump() {
       const char* fname = "/tmp/viscous.py";
@@ -963,19 +1170,24 @@ namespace
           << "smesh  = smeshBuilder.New(salome.myStudy)" << endl
           << "meshSO = smesh.GetCurrentStudy().FindObjectID('0:1:2:3')" << endl
           << "mesh   = smesh.Mesh( meshSO.GetObject() )"<<endl;
+      theNbFunc = 0;
     }
     void Finish() {
-      if (py)
-        *py << "mesh.MakeGroup('Viscous Prisms',SMESH.VOLUME,SMESH.FT_ElemGeomType,'=',SMESH.Geom_PENTA)"<<endl;
+      if (py) {
+        *py << "mesh.GroupOnFilter(SMESH.VOLUME,'Viscous Prisms',"
+          "smesh.GetFilter(SMESH.VOLUME,SMESH.FT_ElemGeomType,'=',SMESH.Geom_PENTA))"<<endl;
+        *py << "mesh.GroupOnFilter(SMESH.VOLUME,'Neg Volumes',"
+          "smesh.GetFilter(SMESH.VOLUME,SMESH.FT_Volume3D,'<',0))"<<endl;
+      }
       delete py; py=0;
     }
-    ~PyDump() { Finish(); }
+    ~PyDump() { Finish(); cout << "NB FUNCTIONS: " << theNbFunc << endl; }
   };
 #define dumpFunction(f) { _dumpFunction(f, __LINE__);}
 #define dumpMove(n)     { _dumpMove(n, __LINE__);}
 #define dumpCmd(txt)    { _dumpCmd(txt, __LINE__);}
   void _dumpFunction(const string& fun, int ln)
-  { if (py) *py<< "def "<<fun<<"(): # "<< ln <<endl; cout<<fun<<"()"<<endl;}
+  { if (py) *py<< "def "<<fun<<"(): # "<< ln <<endl; cout<<fun<<"()"<<endl; ++theNbFunc; }
   void _dumpMove(const SMDS_MeshNode* n, int ln)
   { if (py) *py<< "  mesh.MoveNode( "<<n->GetID()<< ", "<< n->X()
                << ", "<<n->Y()<<", "<< n->Z()<< ")\t\t # "<< ln <<endl; }
@@ -987,6 +1199,7 @@ namespace
   { if (py) { *py<< "  mesh.ChangeElemNodes( " << f->GetID()<<", [";
       for ( int i=1; i < f->NbNodes(); ++i ) *py << f->GetNode(i-1)->GetID()<<", ";
       *py << f->GetNode( f->NbNodes()-1 )->GetID() << " ])"<< endl; }}
+#define debugMsg( txt ) { cout << txt << " (line: " << __LINE__ << ")" << endl; }
 #else
   struct PyDump { void Finish() {} };
 #define dumpFunction(f) f
@@ -994,6 +1207,7 @@ namespace
 #define dumpCmd(txt)
 #define dumpFunctionEnd()
 #define dumpChangeNodes(f)
+#define debugMsg( txt ) {}
 #endif
 }
 
@@ -1019,19 +1233,36 @@ _ViscousBuilder::_ViscousBuilder()
 
 bool _ViscousBuilder::error(const string& text, int solidId )
 {
+  const string prefix = string("Viscous layers builder: ");
   _error->myName    = COMPERR_ALGO_FAILED;
-  _error->myComment = string("Viscous layers builder: ") + text;
+  _error->myComment = prefix + text;
   if ( _mesh )
   {
     SMESH_subMesh* sm = _mesh->GetSubMeshContaining( solidId );
     if ( !sm && !_sdVec.empty() )
-      sm = _mesh->GetSubMeshContaining( _sdVec[0]._index );
+      sm = _mesh->GetSubMeshContaining( solidId = _sdVec[0]._index );
     if ( sm && sm->GetSubShape().ShapeType() == TopAbs_SOLID )
     {
       SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
       if ( smError && smError->myAlgo )
         _error->myAlgo = smError->myAlgo;
       smError = _error;
+      sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+    }
+    // set KO to all solids
+    for ( size_t i = 0; i < _sdVec.size(); ++i )
+    {
+      if ( _sdVec[i]._index == solidId )
+        continue;
+      sm = _mesh->GetSubMesh( _sdVec[i]._solid );
+      if ( !sm->IsEmpty() )
+        continue;
+      SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
+      if ( !smError || smError->IsOK() )
+      {
+        smError = SMESH_ComputeError::New( COMPERR_ALGO_FAILED, prefix + "failed");
+        sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+      }
     }
   }
   makeGroupOfLE(); // debug
@@ -1145,6 +1376,34 @@ SMESH_ComputeErrorPtr _ViscousBuilder::Compute(SMESH_Mesh&         theMesh,
   return _error;
 }
 
+//================================================================================
+/*!
+ * \brief Check validity of hypotheses
+ */
+//================================================================================
+
+SMESH_ComputeErrorPtr _ViscousBuilder::CheckHypotheses( SMESH_Mesh&         mesh,
+                                                        const TopoDS_Shape& shape )
+{
+  _mesh = & mesh;
+
+  if ( _ViscousListener::GetSolidMesh( _mesh, shape, /*toCreate=*/false))
+    return SMESH_ComputeErrorPtr(); // everything already computed
+
+
+  findSolidsWithLayers();
+  bool ok = findFacesWithLayers();
+
+  // remove _MeshOfSolid's of _SolidData's
+  for ( size_t i = 0; i < _sdVec.size(); ++i )
+    _ViscousListener::RemoveSolidMesh( _mesh, _sdVec[i]._solid );
+
+  if ( !ok )
+    return _error;
+
+  return SMESH_ComputeErrorPtr();
+}
+
 //================================================================================
 /*!
  * \brief Finds SOLIDs to compute using viscous layers. Fills _sdVec
@@ -1168,22 +1427,28 @@ bool _ViscousBuilder::findSolidsWithLayers()
     // TODO: check if algo is hidden
     const list <const SMESHDS_Hypothesis *> & allHyps =
       algo->GetUsedHypothesis(*_mesh, allSolids(i), /*ignoreAuxiliary=*/false);
+    _SolidData* soData = 0;
     list< const SMESHDS_Hypothesis *>::const_iterator hyp = allHyps.begin();
     const StdMeshers_ViscousLayers* viscHyp = 0;
-    for ( ; hyp != allHyps.end() && !viscHyp; ++hyp )
-      viscHyp = dynamic_cast<const StdMeshers_ViscousLayers*>( *hyp );
-    if ( viscHyp )
-    {
-      TopoDS_Shape hypShape;
-      filter.Init( filter.Is( viscHyp ));
-      _mesh->GetHypothesis( allSolids(i), filter, true, &hypShape );
+    for ( ; hyp != allHyps.end(); ++hyp )
+      if ( viscHyp = dynamic_cast<const StdMeshers_ViscousLayers*>( *hyp ))
+      {
+        TopoDS_Shape hypShape;
+        filter.Init( filter.Is( viscHyp ));
+        _mesh->GetHypothesis( allSolids(i), filter, true, &hypShape );
 
-      _MeshOfSolid* proxyMesh = _ViscousListener::GetSolidMesh( _mesh,
-                                                                allSolids(i),
-                                                                /*toCreate=*/true);
-      _sdVec.push_back( _SolidData( allSolids(i), viscHyp, hypShape, proxyMesh ));
-      _sdVec.back()._index = getMeshDS()->ShapeToIndex( allSolids(i));
-    }
+        if ( !soData )
+        {
+          _MeshOfSolid* proxyMesh = _ViscousListener::GetSolidMesh( _mesh,
+                                                                    allSolids(i),
+                                                                    /*toCreate=*/true);
+          _sdVec.push_back( _SolidData( allSolids(i), proxyMesh ));
+          soData = & _sdVec.back();
+          soData->_index = getMeshDS()->ShapeToIndex( allSolids(i));
+        }
+        soData->_hyps.push_back( viscHyp );
+        soData->_hypShapes.push_back( hypShape );
+      }
   }
   if ( _sdVec.empty() )
     return error
@@ -1198,7 +1463,7 @@ bool _ViscousBuilder::findSolidsWithLayers()
  */
 //================================================================================
 
-bool _ViscousBuilder::findFacesWithLayers()
+bool _ViscousBuilder::findFacesWithLayers(const bool onlyWith)
 {
   SMESH_MesherHelper helper( *_mesh );
   TopExp_Explorer exp;
@@ -1209,56 +1474,99 @@ bool _ViscousBuilder::findFacesWithLayers()
   {
     solids.Add( _sdVec[i]._solid );
 
-    vector<TGeomID> ids = _sdVec[i]._hyp->GetBndShapes();
-    if ( _sdVec[i]._hyp->IsToIgnoreShapes() ) // FACEs to ignore are given
+    // get faces to ignore defined by each hyp
+    typedef const StdMeshers_ViscousLayers* THyp;
+    typedef std::pair< set<TGeomID>, THyp > TFacesOfHyp;
+    list< TFacesOfHyp > ignoreFacesOfHyps;
+    list< THyp >::iterator              hyp = _sdVec[i]._hyps.begin();
+    list< TopoDS_Shape >::iterator hypShape = _sdVec[i]._hypShapes.begin();
+    for ( ; hyp != _sdVec[i]._hyps.end(); ++hyp, ++hypShape )
     {
-      for ( size_t ii = 0; ii < ids.size(); ++ii )
-      {
-        const TopoDS_Shape& s = getMeshDS()->IndexToShape( ids[ii] );
-        if ( !s.IsNull() && s.ShapeType() == TopAbs_FACE )
-          _sdVec[i]._ignoreFaceIds.insert( ids[ii] );
-      }
+      ignoreFacesOfHyps.push_back( TFacesOfHyp( set<TGeomID>(), *hyp ));
+      getIgnoreFaces( _sdVec[i]._solid, *hyp, *hypShape, ignoreFacesOfHyps.back().first );
     }
-    else // FACEs with layers are given
+
+    // fill _SolidData::_face2hyp and check compatibility of hypotheses
+    const int nbHyps = _sdVec[i]._hyps.size();
+    if ( nbHyps > 1 )
     {
-      exp.Init( _sdVec[i]._solid, TopAbs_FACE );
-      for ( ; exp.More(); exp.Next() )
+      // check if two hypotheses define different parameters for the same FACE
+      list< TFacesOfHyp >::iterator igFacesOfHyp;
+      for ( exp.Init( _sdVec[i]._solid, TopAbs_FACE ); exp.More(); exp.Next() )
       {
-        TGeomID faceInd = getMeshDS()->ShapeToIndex( exp.Current() );
-        if ( find( ids.begin(), ids.end(), faceInd ) == ids.end() )
-          _sdVec[i]._ignoreFaceIds.insert( faceInd );
+        const TGeomID faceID = getMeshDS()->ShapeToIndex( exp.Current() );
+        THyp hyp = 0;
+        igFacesOfHyp = ignoreFacesOfHyps.begin();
+        for ( ; igFacesOfHyp != ignoreFacesOfHyps.end(); ++igFacesOfHyp )
+          if ( ! igFacesOfHyp->first.count( faceID ))
+          {
+            if ( hyp )
+              return error(SMESH_Comment("Several hypotheses define "
+                                         "Viscous Layers on the face #") << faceID );
+            hyp = igFacesOfHyp->second;
+          }
+        if ( hyp )
+          _sdVec[i]._face2hyp.insert( make_pair( faceID, hyp ));
+        else
+          _sdVec[i]._ignoreFaceIds.insert( faceID );
       }
-    }
 
-    // ignore internal FACEs if inlets and outlets are specified
+      // check if two hypotheses define different number of viscous layers for
+      // adjacent faces of a solid
+      set< int > nbLayersSet;
+      igFacesOfHyp = ignoreFacesOfHyps.begin();
+      for ( ; igFacesOfHyp != ignoreFacesOfHyps.end(); ++igFacesOfHyp )
+      {
+        nbLayersSet.insert( igFacesOfHyp->second->GetNumberLayers() );
+      }
+      if ( nbLayersSet.size() > 1 )
+      {
+        for ( exp.Init( _sdVec[i]._solid, TopAbs_EDGE ); exp.More(); exp.Next() )
+        {
+          PShapeIteratorPtr fIt = helper.GetAncestors( exp.Current(), *_mesh, TopAbs_FACE );
+          THyp hyp1 = 0, hyp2 = 0;
+          while( const TopoDS_Shape* face = fIt->next() )
+          {
+            const TGeomID faceID = getMeshDS()->ShapeToIndex( *face );
+            map< TGeomID, THyp >::iterator f2h = _sdVec[i]._face2hyp.find( faceID );
+            if ( f2h != _sdVec[i]._face2hyp.end() )
+            {
+              ( hyp1 ? hyp2 : hyp1 ) = f2h->second;
+            }
+          }
+          if ( hyp1 && hyp2 &&
+               hyp1->GetNumberLayers() != hyp2->GetNumberLayers() )
+          {
+            return error("Two hypotheses define different number of "
+                         "viscous layers on adjacent faces");
+          }
+        }
+      }
+    } // if ( nbHyps > 1 )
+    else
     {
-      TopTools_IndexedDataMapOfShapeListOfShape solidsOfFace;
-      if ( _sdVec[i]._hyp->IsToIgnoreShapes() )
-        TopExp::MapShapesAndAncestors( _sdVec[i]._hypShape,
-                                       TopAbs_FACE, TopAbs_SOLID, solidsOfFace);
+      _sdVec[i]._ignoreFaceIds.swap( ignoreFacesOfHyps.back().first );
+    }
 
+    // fill _SolidData::_reversedFaceIds
+    {
       exp.Init( _sdVec[i]._solid.Oriented( TopAbs_FORWARD ), TopAbs_FACE );
       for ( ; exp.More(); exp.Next() )
       {
         const TopoDS_Face& face = TopoDS::Face( exp.Current() );
-        if ( helper.NbAncestors( face, *_mesh, TopAbs_SOLID ) < 2 )
-          continue;
-
-        const TGeomID faceInd = getMeshDS()->ShapeToIndex( face );
-        if ( _sdVec[i]._hyp->IsToIgnoreShapes() )
-        {
-          int nbSolids = solidsOfFace.FindFromKey( face ).Extent();
-          if ( nbSolids > 1 )
-            _sdVec[i]._ignoreFaceIds.insert( faceInd );
-        }
-
-        if ( helper.IsReversedSubMesh( face ))
+        const TGeomID faceID = getMeshDS()->ShapeToIndex( face );
+        if ( //!sdVec[i]._ignoreFaceIds.count( faceID ) && ???????
+             helper.NbAncestors( face, *_mesh, TopAbs_SOLID ) > 1 &&
+             helper.IsReversedSubMesh( face ))
         {
-          _sdVec[i]._reversedFaceIds.insert( faceInd );
+          _sdVec[i]._reversedFaceIds.insert( faceID );
         }
       }
     }
-  }
+  } // loop on _sdVec
+
+  if ( onlyWith ) // is called to check hypotheses compatibility only
+    return true;
 
   // Find faces to shrink mesh on (solution 2 in issue 0020832);
   TopTools_IndexedMapOfShape shapes;
@@ -1287,6 +1595,7 @@ bool _ViscousBuilder::findFacesWithLayers()
         continue; // nothing interesting
       TopoDS_Shape fWOL = FF[ ignore[0] ? 0 : 1 ];
       // check presence of layers on fWOL within an adjacent SOLID
+      bool collision = false;
       PShapeIteratorPtr sIt = helper.GetAncestors( fWOL, *_mesh, TopAbs_SOLID );
       while ( const TopoDS_Shape* solid = sIt->next() )
         if ( !solid->IsSame( _sdVec[i]._solid ))
@@ -1295,8 +1604,9 @@ bool _ViscousBuilder::findFacesWithLayers()
           int  iFace = getMeshDS()->ShapeToIndex( fWOL );
           if ( iSolid > 0 && !_sdVec[ iSolid-1 ]._ignoreFaceIds.count( iFace ))
           {
-            _sdVec[i]._noShrinkFaces.insert( iFace );
-            fWOL.Nullify();
+            //_sdVec[i]._noShrinkShapes.insert( iFace );
+            //fWOL.Nullify();
+            collision = true;
           }
         }
       // add edge to maps
@@ -1304,6 +1614,12 @@ bool _ViscousBuilder::findFacesWithLayers()
       {
         TGeomID edgeInd = getMeshDS()->ShapeToIndex( edge );
         _sdVec[i]._shrinkShape2Shape.insert( make_pair( edgeInd, fWOL ));
+        if ( collision )
+        {
+          // _shrinkShape2Shape will be used to temporary inflate _LayerEdge's based
+          // on the edge but shrink won't be performed
+          _sdVec[i]._noShrinkShapes.insert( edgeInd );
+        }
       }
     }
   }
@@ -1312,54 +1628,70 @@ bool _ViscousBuilder::findFacesWithLayers()
   set< string > notSupportAlgos; notSupportAlgos.insert("Hexa_3D");
   for ( size_t i = 0; i < _sdVec.size(); ++i )
   {
-    TopTools_MapOfShape noShrinkVertices;
     map< TGeomID, TopoDS_Shape >::iterator e2f = _sdVec[i]._shrinkShape2Shape.begin();
     for ( ; e2f != _sdVec[i]._shrinkShape2Shape.end(); ++e2f )
     {
       const TopoDS_Shape& fWOL = e2f->second;
-      TGeomID           edgeID = e2f->first;
+      const TGeomID     edgeID = e2f->first;
       bool notShrinkFace = false;
       PShapeIteratorPtr soIt = helper.GetAncestors(fWOL, *_mesh, TopAbs_SOLID);
-      while ( soIt->more())
+      while ( soIt->more() )
       {
         const TopoDS_Shape* solid = soIt->next();
         if ( _sdVec[i]._solid.IsSame( *solid )) continue;
         SMESH_Algo* algo = _mesh->GetGen()->GetAlgo( *_mesh, *solid );
         if ( !algo || !notSupportAlgos.count( algo->GetName() )) continue;
         notShrinkFace = true;
-        for ( size_t j = 0; j < _sdVec.size(); ++j )
+        size_t iSolid = 0;
+        for ( ; iSolid < _sdVec.size(); ++iSolid )
         {
-          if ( _sdVec[j]._solid.IsSame( *solid ) )
-            if ( _sdVec[j]._shrinkShape2Shape.count( edgeID ))
+          if ( _sdVec[iSolid]._solid.IsSame( *solid ) ) {
+            if ( _sdVec[iSolid]._shrinkShape2Shape.count( edgeID ))
               notShrinkFace = false;
+            break;
+          }
         }
-      }
-      if ( notShrinkFace )
-      {
-        _sdVec[i]._noShrinkFaces.insert( getMeshDS()->ShapeToIndex( fWOL ));
-        for ( TopExp_Explorer vExp( fWOL, TopAbs_VERTEX ); vExp.More(); vExp.Next() )
-          noShrinkVertices.Add( vExp.Current() );
-      }
-    }
-    // erase from _shrinkShape2Shape all srink EDGE's of a SOLID connected
-    // to the found not shrinked fWOL's
-    e2f = _sdVec[i]._shrinkShape2Shape.begin();
-    for ( ; e2f != _sdVec[i]._shrinkShape2Shape.end(); )
-    {
-      TGeomID edgeID = e2f->first;
-      TopoDS_Vertex VV[2];
-      TopExp::Vertices( TopoDS::Edge( getMeshDS()->IndexToShape( edgeID )),VV[0],VV[1]);
-      if ( noShrinkVertices.Contains( VV[0] ) || noShrinkVertices.Contains( VV[1] ))
-      {
-        _sdVec[i]._noShrinkFaces.insert( getMeshDS()->ShapeToIndex( e2f->second ));
-        _sdVec[i]._shrinkShape2Shape.erase( e2f++ );
-      }
-      else
-      {
-        e2f++;
-      }
-    }
-  }
+        if ( notShrinkFace )
+        {
+          _sdVec[i]._noShrinkShapes.insert( edgeID );
+
+          // add VERTEXes of the edge in _noShrinkShapes
+          TopoDS_Shape edge = getMeshDS()->IndexToShape( edgeID );
+          for ( TopoDS_Iterator vIt( edge ); vIt.More(); vIt.Next() )
+            _sdVec[i]._noShrinkShapes.insert( getMeshDS()->ShapeToIndex( vIt.Value() ));
+
+          // check if there is a collision with to-shrink-from EDGEs in iSolid
+          if ( iSolid == _sdVec.size() )
+            continue; // no VL in the solid
+          shapes.Clear();
+          TopExp::MapShapes( fWOL, TopAbs_EDGE, shapes);
+          for ( int iE = 1; iE <= shapes.Extent(); ++iE )
+          {
+            const TopoDS_Edge& E = TopoDS::Edge( shapes( iE ));
+            const TGeomID    eID = getMeshDS()->ShapeToIndex( E );
+            if ( eID == edgeID ||
+                 !_sdVec[iSolid]._shrinkShape2Shape.count( eID ) ||
+                 _sdVec[i]._noShrinkShapes.count( eID ))
+              continue;
+            for ( int is1st = 0; is1st < 2; ++is1st )
+            {
+              TopoDS_Vertex V = helper.IthVertex( is1st, E );
+              if ( _sdVec[i]._noShrinkShapes.count( getMeshDS()->ShapeToIndex( V ) ))
+              {
+                // _sdVec[i]._noShrinkShapes.insert( eID );
+                // V = helper.IthVertex( !is1st, E );
+                // _sdVec[i]._noShrinkShapes.insert( getMeshDS()->ShapeToIndex( V ));
+                //iE = 0; // re-start the loop on EDGEs of fWOL
+                return error("No way to make a conformal mesh with "
+                             "the given set of faces with layers", _sdVec[i]._index);
+              }
+            }
+          }
+        }
+
+      } // while ( soIt->more() )
+    } // loop on _sdVec[i]._shrinkShape2Shape
+  } // loop on _sdVec to fill in _SolidData::_noShrinkShapes
 
   // Find the SHAPE along which to inflate _LayerEdge based on VERTEX
 
@@ -1381,8 +1713,8 @@ bool _ViscousBuilder::findFacesWithLayers()
         {
           totalNbFaces++;
           const int fID = getMeshDS()->ShapeToIndex( *f );
-          if ( _sdVec[i]._ignoreFaceIds.count ( fID ) &&
-               !_sdVec[i]._noShrinkFaces.count( fID ))
+          if ( _sdVec[i]._ignoreFaceIds.count ( fID ) /*&&
+               !_sdVec[i]._noShrinkShapes.count( fID )*/)
             facesWOL.push_back( *f );
         }
       }
@@ -1450,6 +1782,60 @@ bool _ViscousBuilder::findFacesWithLayers()
   return true;
 }
 
+//================================================================================
+/*!
+ * \brief Finds FACEs w/o layers for a given SOLID by an hypothesis
+ */
+//================================================================================
+
+void _ViscousBuilder::getIgnoreFaces(const TopoDS_Shape&             solid,
+                                     const StdMeshers_ViscousLayers* hyp,
+                                     const TopoDS_Shape&             hypShape,
+                                     set<TGeomID>&                   ignoreFaceIds)
+{
+  TopExp_Explorer exp;
+
+  vector<TGeomID> ids = hyp->GetBndShapes();
+  if ( hyp->IsToIgnoreShapes() ) // FACEs to ignore are given
+  {
+    for ( size_t ii = 0; ii < ids.size(); ++ii )
+    {
+      const TopoDS_Shape& s = getMeshDS()->IndexToShape( ids[ii] );
+      if ( !s.IsNull() && s.ShapeType() == TopAbs_FACE )
+        ignoreFaceIds.insert( ids[ii] );
+    }
+  }
+  else // FACEs with layers are given
+  {
+    exp.Init( solid, TopAbs_FACE );
+    for ( ; exp.More(); exp.Next() )
+    {
+      TGeomID faceInd = getMeshDS()->ShapeToIndex( exp.Current() );
+      if ( find( ids.begin(), ids.end(), faceInd ) == ids.end() )
+        ignoreFaceIds.insert( faceInd );
+    }
+  }
+
+  // ignore internal FACEs if inlets and outlets are specified
+  if ( hyp->IsToIgnoreShapes() )
+  {
+    TopTools_IndexedDataMapOfShapeListOfShape solidsOfFace;
+    TopExp::MapShapesAndAncestors( hypShape,
+                                   TopAbs_FACE, TopAbs_SOLID, solidsOfFace);
+
+    for ( exp.Init( solid, TopAbs_FACE ); exp.More(); exp.Next() )
+    {
+      const TopoDS_Face& face = TopoDS::Face( exp.Current() );
+      if ( SMESH_MesherHelper::NbAncestors( face, *_mesh, TopAbs_SOLID ) < 2 )
+        continue;
+
+      int nbSolids = solidsOfFace.FindFromKey( face ).Extent();
+      if ( nbSolids > 1 )
+        ignoreFaceIds.insert( getMeshDS()->ShapeToIndex( face ));
+    }
+  }
+}
+
 //================================================================================
 /*!
  * \brief Create the inner surface of the viscous layer and prepare data for infation
@@ -1460,15 +1846,14 @@ bool _ViscousBuilder::makeLayer(_SolidData& data)
 {
   // get all sub-shapes to make layers on
   set<TGeomID> subIds, faceIds;
-  subIds = data._noShrinkFaces;
+  subIds = data._noShrinkShapes;
   TopExp_Explorer exp( data._solid, TopAbs_FACE );
   for ( ; exp.More(); exp.Next() )
     {
       SMESH_subMesh* fSubM = _mesh->GetSubMesh( exp.Current() );
-      if ( ! data._ignoreFaceIds.count( getMeshDS()->ShapeToIndex( exp.Current() )))
+      if ( ! data._ignoreFaceIds.count( fSubM->GetId() ))
         faceIds.insert( fSubM->GetId() );
-      SMESH_subMeshIteratorPtr subIt =
-        fSubM->getDependsOnIterator(/*includeSelf=*/true, /*complexShapeFirst=*/false);
+      SMESH_subMeshIteratorPtr subIt = fSubM->getDependsOnIterator(/*includeSelf=*/true);
       while ( subIt->more() )
         subIds.insert( subIt->next()->GetId() );
     }
@@ -1501,7 +1886,7 @@ bool _ViscousBuilder::makeLayer(_SolidData& data)
 
   SMESH_MesherHelper helper( *_mesh );
   helper.SetSubShape( data._solid );
-  helper.SetElementsOnShape(true);
+  helper.SetElementsOnShape( true );
 
   vector< const SMDS_MeshNode*> newNodes; // of a mesh face
   TNode2Edge::iterator n2e2;
@@ -1523,27 +1908,51 @@ bool _ViscousBuilder::makeLayer(_SolidData& data)
     while ( eIt->more() )
     {
       const SMDS_MeshElement* face = eIt->next();
+      double          faceMaxCosin = -1;
+      _LayerEdge*     maxCosinEdge = 0;
+      int             nbDegenNodes = 0;
+
       newNodes.resize( face->NbCornerNodes() );
-      double faceMaxCosin = -1;
-      for ( int i = 0 ; i < face->NbCornerNodes(); ++i )
+      for ( size_t i = 0 ; i < newNodes.size(); ++i )
       {
-        const SMDS_MeshNode* n = face->GetNode(i);
+        const SMDS_MeshNode* n = face->GetNode( i );
+        const int      shapeID = n->getshapeId();
+        const bool onDegenShap = helper.IsDegenShape( shapeID );
+        const bool onDegenEdge = ( onDegenShap && n->GetPosition()->GetDim() == 1 );
+        if ( onDegenShap )
+        {
+          if ( onDegenEdge )
+          {
+            // substitute n on a degenerated EDGE with a node on a corresponding VERTEX
+            const TopoDS_Shape& E = getMeshDS()->IndexToShape( shapeID );
+            TopoDS_Vertex       V = helper.IthVertex( 0, TopoDS::Edge( E ));
+            if ( const SMDS_MeshNode* vN = SMESH_Algo::VertexNode( V, getMeshDS() )) {
+              n = vN;
+              nbDegenNodes++;
+            }
+          }
+          else
+          {
+            nbDegenNodes++;
+          }
+        }
         TNode2Edge::iterator n2e = data._n2eMap.insert( make_pair( n, (_LayerEdge*)0 )).first;
         if ( !(*n2e).second )
         {
           // add a _LayerEdge
           _LayerEdge* edge = new _LayerEdge();
-          n2e->second = edge;
           edge->_nodes.push_back( n );
-          const int shapeID = n->getshapeId();
+          n2e->second = edge;
           edgesByGeom[ shapeID ].push_back( edge );
+          const bool noShrink = data._noShrinkShapes.count( shapeID );
 
           SMESH_TNodeXYZ xyz( n );
 
           // set edge data or find already refined _LayerEdge and get data from it
-          if ( n->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE &&
-               ( s2ne = data._s2neMap.find( shapeID )) != data._s2neMap.end() &&
-               ( n2e2 = (*s2ne).second->find( n )) != s2ne->second->end())
+          if (( !noShrink                                                     ) &&
+              ( n->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE        ) &&
+              (( s2ne = data._s2neMap.find( shapeID )) != data._s2neMap.end() ) &&
+              (( n2e2 = (*s2ne).second->find( n )) != s2ne->second->end()     ))
           {
             _LayerEdge* foundEdge = (*n2e2).second;
             gp_XYZ        lastPos = edge->Copy( *foundEdge, helper );
@@ -1554,26 +1963,38 @@ bool _ViscousBuilder::makeLayer(_SolidData& data)
           }
           else
           {
-            edge->_nodes.push_back( helper.AddNode( xyz.X(), xyz.Y(), xyz.Z() ));
+            if ( !noShrink )
+            {
+              edge->_nodes.push_back( helper.AddNode( xyz.X(), xyz.Y(), xyz.Z() ));
+            }
             if ( !setEdgeData( *edge, subIds, helper, data ))
               return false;
           }
           dumpMove(edge->_nodes.back());
-          if ( edge->_cosin > 0.01 )
+
+          if ( edge->_cosin > faceMaxCosin )
           {
-            if ( edge->_cosin > faceMaxCosin )
-              faceMaxCosin = edge->_cosin;
+            faceMaxCosin = edge->_cosin;
+            maxCosinEdge = edge;
           }
         }
         newNodes[ i ] = n2e->second->_nodes.back();
+
+        if ( onDegenEdge )
+          data._n2eMap.insert( make_pair( face->GetNode( i ), n2e->second ));
       }
+      if ( newNodes.size() - nbDegenNodes < 2 )
+        continue;
+
       // create a temporary face
-      const SMDS_MeshElement* newFace = new TmpMeshFace( newNodes, --_tmpFaceID );
+      const SMDS_MeshElement* newFace =
+        new _TmpMeshFace( newNodes, --_tmpFaceID, face->getshapeId() );
       proxySub->AddElement( newFace );
 
       // compute inflation step size by min size of element on a convex surface
-      if ( faceMaxCosin > 0.1 )
-        limitStepSize( data, face, faceMaxCosin );
+      if ( faceMaxCosin > theMinSmoothCosin )
+        limitStepSize( data, face, maxCosinEdge );
+
     } // loop on 2D elements on a FACE
   } // loop on FACEs of a SOLID
 
@@ -1581,38 +2002,68 @@ bool _ViscousBuilder::makeLayer(_SolidData& data)
   if ( data._stepSize < 1. )
     data._epsilon *= data._stepSize;
 
-  // fill data._simplexTestEdges
-  findSimplexTestEdges( data, edgesByGeom );
-
-  // limit data._stepSize depending on surface curvature
-  limitStepSizeByCurvature( data, edgesByGeom );
-
   // Put _LayerEdge's into the vector data._edges
   if ( !sortEdges( data, edgesByGeom ))
     return false;
 
-  // Set target nodes into _Simplex and _2NearEdges of _LayerEdge's
+  // limit data._stepSize depending on surface curvature and fill data._convexFaces
+  limitStepSizeByCurvature( data ); // !!! it must be before node substitution in _Simplex
+
+  // Set target nodes into _Simplex and _LayerEdge's to _2NearEdges
   TNode2Edge::iterator n2e;
+  const SMDS_MeshNode* nn[2];
   for ( size_t i = 0; i < data._edges.size(); ++i )
   {
-    if ( data._edges[i]->IsOnEdge())
+    _LayerEdge* edge = data._edges[i];
+    if ( edge->IsOnEdge() )
+    {
+      // get neighbor nodes
+      bool hasData = ( edge->_2neibors->_edges[0] );
+      if ( hasData ) // _LayerEdge is a copy of another one
+      {
+        nn[0] = edge->_2neibors->srcNode(0);
+        nn[1] = edge->_2neibors->srcNode(1);
+      }
+      else if ( !findNeiborsOnEdge( edge, nn[0],nn[1], data ))
+      {
+        return false;
+      }
+      // set neighbor _LayerEdge's
       for ( int j = 0; j < 2; ++j )
       {
-        if ( data._edges[i]->_nodes.back()->NbInverseElements(SMDSAbs_Volume) > 0 )
-          break; // _LayerEdge is shared by two _SolidData's
-        const SMDS_MeshNode* & n = data._edges[i]->_2neibors->_nodes[j];
-        if (( n2e = data._n2eMap.find( n )) == data._n2eMap.end() )
+        if (( n2e = data._n2eMap.find( nn[j] )) == data._n2eMap.end() )
           return error("_LayerEdge not found by src node", data._index);
-        n = (*n2e).second->_nodes.back();
-        data._edges[i]->_2neibors->_edges[j] = n2e->second;
+        edge->_2neibors->_edges[j] = n2e->second;
       }
-    //else
-    for ( size_t j = 0; j < data._edges[i]->_simplices.size(); ++j )
-    {
-      _Simplex& s = data._edges[i]->_simplices[j];
+      if ( !hasData )
+        edge->SetDataByNeighbors( nn[0], nn[1], helper);
+    }
+
+    for ( size_t j = 0; j < edge->_simplices.size(); ++j )
+    {
+      _Simplex& s = edge->_simplices[j];
       s._nNext = data._n2eMap[ s._nNext ]->_nodes.back();
       s._nPrev = data._n2eMap[ s._nPrev ]->_nodes.back();
     }
+
+    // For an _LayerEdge on a degenerated EDGE, copy some data from
+    // a corresponding _LayerEdge on a VERTEX
+    // (issue 52453, pb on a downloaded SampleCase2-Tet-netgen-mephisto.hdf)
+    if ( helper.IsDegenShape( edge->_nodes[0]->getshapeId() ))
+    {
+      // Generally we should not get here
+      const TopoDS_Shape& E = getMeshDS()->IndexToShape( edge->_nodes[0]->getshapeId() );
+      if ( E.ShapeType() != TopAbs_EDGE )
+        continue;
+      TopoDS_Vertex V = helper.IthVertex( 0, TopoDS::Edge( E ));
+      const SMDS_MeshNode* vN = SMESH_Algo::VertexNode( V, getMeshDS() );
+      if (( n2e = data._n2eMap.find( vN )) == data._n2eMap.end() )
+        continue;
+      const _LayerEdge* vEdge = n2e->second;
+      edge->_normal    = vEdge->_normal;
+      edge->_lenFactor = vEdge->_lenFactor;
+      edge->_cosin     = vEdge->_cosin;
+    }
   }
 
   dumpFunctionEnd();
@@ -1627,7 +2078,7 @@ bool _ViscousBuilder::makeLayer(_SolidData& data)
 
 void _ViscousBuilder::limitStepSize( _SolidData&             data,
                                      const SMDS_MeshElement* face,
-                                     const double            cosin)
+                                     const _LayerEdge*       maxCosinEdge )
 {
   int iN = 0;
   double minSize = 10 * data._stepSize;
@@ -1635,20 +2086,20 @@ void _ViscousBuilder::limitStepSize( _SolidData&             data,
   for ( int i = 0; i < nbNodes; ++i )
   {
     const SMDS_MeshNode* nextN = face->GetNode( SMESH_MesherHelper::WrapIndex( i+1, nbNodes ));
-    const SMDS_MeshNode* curN = face->GetNode( i );
+    const SMDS_MeshNode*  curN = face->GetNode( i );
     if ( nextN->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ||
-         curN->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
+         curN-> GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
     {
-      double dist = SMESH_TNodeXYZ( face->GetNode(i)).Distance( nextN );
+      double dist = SMESH_TNodeXYZ( curN ).Distance( nextN );
       if ( dist < minSize )
         minSize = dist, iN = i;
     }
   }
-  double newStep = 0.8 * minSize / cosin;
+  double newStep = 0.8 * minSize / maxCosinEdge->_lenFactor;
   if ( newStep < data._stepSize )
   {
     data._stepSize = newStep;
-    data._stepSizeCoeff = 0.8 / cosin;
+    data._stepSizeCoeff = 0.8 / maxCosinEdge->_lenFactor;
     data._stepSizeNodes[0] = face->GetNode( iN );
     data._stepSizeNodes[1] = face->GetNode( SMESH_MesherHelper::WrapIndex( iN+1, nbNodes ));
   }
@@ -1676,148 +2127,129 @@ void _ViscousBuilder::limitStepSize( _SolidData& data, const double minSize )
 
 //================================================================================
 /*!
- * \brief Limit data._stepSize by evaluating curvature of shapes
+ * \brief Limit data._stepSize by evaluating curvature of shapes and fill data._convexFaces
  */
 //================================================================================
 
-void _ViscousBuilder::limitStepSizeByCurvature( _SolidData&                    data,
-                                                vector< vector<_LayerEdge*> >& edgesByGeom)
+void _ViscousBuilder::limitStepSizeByCurvature( _SolidData& data )
 {
-  const int nbTestPnt = 5;
-  const double minCurvature = 0.9 / data._hyp->GetTotalThickness();
+  const int nbTestPnt = 5; // on a FACE sub-shape
 
   BRepLProp_SLProps surfProp( 2, 1e-6 );
   SMESH_MesherHelper helper( *_mesh );
 
+  data._convexFaces.clear();
+
   TopExp_Explorer face( data._solid, TopAbs_FACE );
   for ( ; face.More(); face.Next() )
   {
     const TopoDS_Face& F = TopoDS::Face( face.Current() );
+    SMESH_subMesh *   sm = _mesh->GetSubMesh( F );
+    const TGeomID faceID = sm->GetId();
+    if ( data._ignoreFaceIds.count( faceID )) continue;
+
     BRepAdaptor_Surface surface( F, false );
     surfProp.SetSurface( surface );
 
-    SMESH_subMesh *   sm = _mesh->GetSubMesh( F );
+    bool isTooCurved = false;
+    int iBeg, iEnd;
+
+    _ConvexFace cnvFace;
+    const double        oriFactor = ( F.Orientation() == TopAbs_REVERSED ? +1. : -1. );
     SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true);
     while ( smIt->more() )
     {
       sm = smIt->next();
-      const vector<_LayerEdge*>& ledges = edgesByGeom[ sm->GetId() ];
-      int step = Max( 1, int( ledges.size()) / nbTestPnt );
-      for ( size_t i = 0; i < ledges.size(); i += step )
+      const TGeomID subID = sm->GetId();
+      // find _LayerEdge's of a sub-shape
+      size_t edgesEnd;
+      if ( data.GetShapeEdges( subID, edgesEnd, &iBeg, &iEnd ))
+        cnvFace._subIdToEdgeEnd.insert( make_pair( subID, edgesEnd ));
+      else
+        continue;
+      // check concavity and curvature and limit data._stepSize
+      const double minCurvature = 0.9 / data._hypOnShape[ edgesEnd ].GetTotalThickness();
+      int nbLEdges = iEnd - iBeg;
+      int iStep    = Max( 1, nbLEdges / nbTestPnt );
+      for ( ; iBeg < iEnd; iBeg += iStep )
       {
-        gp_XY uv = helper.GetNodeUV( F, ledges[i]->_nodes[0] );
+        gp_XY uv = helper.GetNodeUV( F, data._edges[ iBeg ]->_nodes[0] );
         surfProp.SetParameters( uv.X(), uv.Y() );
         if ( !surfProp.IsCurvatureDefined() )
           continue;
-        double surfCurvature = Max( Abs( surfProp.MaxCurvature() ),
-                                    Abs( surfProp.MinCurvature() ));
-        if ( surfCurvature < minCurvature )
-          continue;
-
-        gp_Dir minDir, maxDir;
-        surfProp.CurvatureDirections( maxDir, minDir );
-        if ( F.Orientation() == TopAbs_REVERSED ) {
-          maxDir.Reverse(); minDir.Reverse();
+        if ( surfProp.MaxCurvature() * oriFactor > minCurvature )
+        {
+          limitStepSize( data, 0.9 / surfProp.MaxCurvature() * oriFactor );
+          isTooCurved = true;
+        }
+        if ( surfProp.MinCurvature() * oriFactor > minCurvature )
+        {
+          limitStepSize( data, 0.9 / surfProp.MinCurvature() * oriFactor );
+          isTooCurved = true;
         }
-        const gp_XYZ& inDir = ledges[i]->_normal;
-        if ( inDir * maxDir.XYZ() < 0 &&
-             inDir * minDir.XYZ() < 0 )
-          continue;
-
-        limitStepSize( data, 0.9 / surfCurvature );
       }
-    }
-  }
-}
-
-//================================================================================
-/*!
- * Fill data._simplexTestEdges. These _LayerEdge's are used to stop inflation
- * in the case where there are no _LayerEdge's on a curved convex FACE,
- * as e.g. on a fillet surface with no internal nodes - issue 22580,
- * so that collision of viscous internal faces is not detected by check of
- * intersection of _LayerEdge's with the viscous internal faces.
- */
-//================================================================================
-
-void _ViscousBuilder::findSimplexTestEdges( _SolidData&                    data,
-                                            vector< vector<_LayerEdge*> >& edgesByGeom)
-{
-  data._simplexTestEdges.clear();
+    } // loop on sub-shapes of the FACE
 
-  SMESH_MesherHelper helper( *_mesh );
-
-  vector< vector<_LayerEdge*> * > ledgesOnEdges;
-  set< const SMDS_MeshNode* > usedNodes;
+    if ( !isTooCurved ) continue;
 
-  const double minCurvature = 1. / data._hyp->GetTotalThickness();
+    _ConvexFace & convFace =
+      data._convexFaces.insert( make_pair( faceID, cnvFace )).first->second;
 
-  for ( size_t iS = 1; iS < edgesByGeom.size(); ++iS )
-  {
-    // look for a FACE with layers and w/o _LayerEdge's
-    const vector<_LayerEdge*>& eS = edgesByGeom[iS];
-    if ( !eS.empty() ) continue;
-    const TopoDS_Shape& S = getMeshDS()->IndexToShape( iS );
-    if ( S.IsNull() || S.ShapeType() != TopAbs_FACE ) continue;
-    if ( data._ignoreFaceIds.count( iS )) continue;
+    convFace._face = F;
+    convFace._normalsFixed = false;
 
-    const TopoDS_Face& F = TopoDS::Face( S );
-
-    // look for _LayerEdge's on EDGEs with null _sWOL
-    ledgesOnEdges.clear();
-    TopExp_Explorer eExp( F, TopAbs_EDGE );
-    for ( ; eExp.More(); eExp.Next() )
+    // Fill _ConvexFace::_simplexTestEdges. These _LayerEdge's are used to detect
+    // prism distortion.
+    map< TGeomID, int >::iterator id2end = convFace._subIdToEdgeEnd.find( faceID );
+    if ( id2end != convFace._subIdToEdgeEnd.end() )
     {
-      TGeomID iE = getMeshDS()->ShapeToIndex( eExp.Current() );
-      vector<_LayerEdge*>& eE = edgesByGeom[iE];
-      if ( !eE.empty() && eE[0]->_sWOL.IsNull() )
-        ledgesOnEdges.push_back( & eE );
+      // there are _LayerEdge's on the FACE it-self;
+      // select _LayerEdge's near EDGEs
+      data.GetEdgesOnShape( id2end->second, iBeg, iEnd );
+      for ( ; iBeg < iEnd; ++iBeg )
+      {
+        _LayerEdge* ledge = data._edges[ iBeg ];
+        for ( size_t j = 0; j < ledge->_simplices.size(); ++j )
+          if ( ledge->_simplices[j]._nNext->GetPosition()->GetDim() < 2 )
+          {
+            convFace._simplexTestEdges.push_back( ledge );
+            break;
+          }
+      }
     }
-    if ( ledgesOnEdges.empty() ) continue;
-
-    // check FACE convexity
-    const _LayerEdge* le = ledgesOnEdges[0]->back();
-    gp_XY uv = helper.GetNodeUV( F, le->_nodes[0] );
-    BRepAdaptor_Surface surf( F );
-    BRepLProp_SLProps surfProp( surf, uv.X(), uv.Y(), 2, 1e-6 );
-    if ( !surfProp.IsCurvatureDefined() )
-      continue;
-    double surfCurvature = Max( Abs( surfProp.MaxCurvature() ),
-                                Abs( surfProp.MinCurvature() ));
-    if ( surfCurvature < minCurvature )
-      continue;
-    gp_Dir minDir, maxDir;
-    surfProp.CurvatureDirections( maxDir, minDir );
-    if ( F.Orientation() == TopAbs_REVERSED ) {
-      maxDir.Reverse(); minDir.Reverse();
-    }
-    const gp_XYZ& inDir = le->_normal;
-    if ( inDir * maxDir.XYZ() < 0 &&
-         inDir * minDir.XYZ() < 0 )
-      continue;
+    else
+    {
+      // where there are no _LayerEdge's on a _ConvexFace,
+      // as e.g. on a fillet surface with no internal nodes - issue 22580,
+      // so that collision of viscous internal faces is not detected by check of
+      // intersection of _LayerEdge's with the viscous internal faces.
 
-    limitStepSize( data, 0.9 / surfCurvature );
+      set< const SMDS_MeshNode* > usedNodes;
 
-    // add _simplices to the _LayerEdge's
-    for ( size_t iE = 0; iE < ledgesOnEdges.size(); ++iE )
-    {
-      const vector<_LayerEdge*>& ledges = *ledgesOnEdges[iE];
-      for ( size_t iLE = 0; iLE < ledges.size(); ++iLE )
+      // look for _LayerEdge's with null _sWOL
+      map< TGeomID, int >::iterator id2end = convFace._subIdToEdgeEnd.begin();
+      for ( ; id2end != convFace._subIdToEdgeEnd.end(); ++id2end )
       {
-        _LayerEdge* ledge = ledges[iLE];
-        const SMDS_MeshNode* srcNode = ledge->_nodes[0];
-        if ( !usedNodes.insert( srcNode ).second ) continue;
-
-        getSimplices( srcNode, ledge->_simplices, data._ignoreFaceIds, &data );
-        for ( size_t i = 0; i < ledge->_simplices.size(); ++i )
+        data.GetEdgesOnShape( id2end->second, iBeg, iEnd );
+        if ( iBeg >= iEnd || !data._edges[ iBeg ]->_sWOL.IsNull() )
+          continue;
+        for ( ; iBeg < iEnd; ++iBeg )
         {
-          usedNodes.insert( ledge->_simplices[i]._nPrev );
-          usedNodes.insert( ledge->_simplices[i]._nNext );
+          _LayerEdge* ledge = data._edges[ iBeg ];
+          const SMDS_MeshNode* srcNode = ledge->_nodes[0];
+          if ( !usedNodes.insert( srcNode ).second ) continue;
+
+          getSimplices( srcNode, ledge->_simplices, data._ignoreFaceIds, &data );
+          for ( size_t i = 0; i < ledge->_simplices.size(); ++i )
+          {
+            usedNodes.insert( ledge->_simplices[i]._nPrev );
+            usedNodes.insert( ledge->_simplices[i]._nNext );
+          }
+          convFace._simplexTestEdges.push_back( ledge );
         }
-        data._simplexTestEdges.push_back( ledge );
       }
     }
-  }
+  } // loop on FACEs of data._solid
 }
 
 //================================================================================
@@ -1829,8 +2261,21 @@ void _ViscousBuilder::findSimplexTestEdges( _SolidData&                    data,
 bool _ViscousBuilder::sortEdges( _SolidData&                    data,
                                  vector< vector<_LayerEdge*> >& edgesByGeom)
 {
+  // define allowed thickness
+  computeGeomSize( data ); // compute data._geomSize
+
+  data._maxThickness = 0;
+  data._minThickness = 1e100;
+  list< const StdMeshers_ViscousLayers* >::iterator hyp = data._hyps.begin();
+  for ( ; hyp != data._hyps.end(); ++hyp )
+  {
+    data._maxThickness = Max( data._maxThickness, (*hyp)->GetTotalThickness() );
+    data._minThickness = Min( data._minThickness, (*hyp)->GetTotalThickness() );
+  }
+  const double tgtThick = /*Min( 0.5 * data._geomSize, */data._maxThickness;
+
   // Find shapes needing smoothing; such a shape has _LayerEdge._normal on it's
-  // boundry inclined at a sharp angle to the shape
+  // boundry inclined to the shape at a sharp angle
 
   list< TGeomID > shapesToSmooth;
   
@@ -1847,28 +2292,33 @@ bool _ViscousBuilder::sortEdges( _SolidData&                    data,
     {
     case TopAbs_EDGE: {
 
-      bool isShrinkEdge = !eS[0]->_sWOL.IsNull();
+      if ( SMESH_Algo::isDegenerated( TopoDS::Edge( S )))
+        break;
+      //bool isShrinkEdge = !eS[0]->_sWOL.IsNull();
       for ( TopoDS_Iterator vIt( S ); vIt.More() && !needSmooth; vIt.Next() )
       {
         TGeomID iV = getMeshDS()->ShapeToIndex( vIt.Value() );
         vector<_LayerEdge*>& eV = edgesByGeom[ iV ];
         if ( eV.empty() ) continue;
-        double cosin = eV[0]->_cosin;
-        bool badCosin =
-          ( !eV[0]->_sWOL.IsNull() && ( eV[0]->_sWOL.ShapeType() == TopAbs_EDGE || !isShrinkEdge));
-        if ( badCosin )
+        gp_Vec eDir = getEdgeDir( TopoDS::Edge( S ), TopoDS::Vertex( vIt.Value() ));
+        double angle = eDir.Angle( eV[0]->_normal );
+        double cosin = Cos( angle );
+        if ( cosin > theMinSmoothCosin )
         {
-          gp_Vec dir1, dir2;
-          if ( eV[0]->_sWOL.ShapeType() == TopAbs_EDGE )
-            dir1 = getEdgeDir( TopoDS::Edge( eV[0]->_sWOL ), TopoDS::Vertex( vIt.Value() ));
-          else
-            dir1 = getFaceDir( TopoDS::Face( eV[0]->_sWOL ), TopoDS::Vertex( vIt.Value() ),
-                               eV[0]->_nodes[0], helper, ok);
-          dir2 = getEdgeDir( TopoDS::Edge( S ), TopoDS::Vertex( vIt.Value() ));
-          double angle = dir1.Angle( dir2 );
-          cosin = cos( angle );
+          // compare tgtThick with the length of an end segment
+          SMDS_ElemIteratorPtr eIt = eV[0]->_nodes[0]->GetInverseElementIterator(SMDSAbs_Edge);
+          while ( eIt->more() )
+          {
+            const SMDS_MeshElement* endSeg = eIt->next();
+            if ( endSeg->getshapeId() == iS )
+            {
+              double segLen =
+                SMESH_TNodeXYZ( endSeg->GetNode(0) ).Distance( endSeg->GetNode(1 ));
+              needSmooth = needSmoothing( cosin, tgtThick, segLen );
+              break;
+            }
+          }
         }
-        needSmooth = ( cosin > 0.1 );
       }
       break;
     }
@@ -1879,25 +2329,38 @@ bool _ViscousBuilder::sortEdges( _SolidData&                    data,
         TGeomID iE = getMeshDS()->ShapeToIndex( eExp.Current() );
         vector<_LayerEdge*>& eE = edgesByGeom[ iE ];
         if ( eE.empty() ) continue;
-        if ( eE[0]->_sWOL.IsNull() )
+        // TopLoc_Location loc;
+        // Handle(Geom_Surface) surface = BRep_Tool::Surface( TopoDS::Face( S ), loc );
+        // bool isPlane = GeomLib_IsPlanarSurface( surface ).IsPlanar();
+        //if ( eE[0]->_sWOL.IsNull() )
         {
+          double faceSize;
           for ( size_t i = 0; i < eE.size() && !needSmooth; ++i )
-            needSmooth = ( eE[i]->_cosin > 0.1 );
-        }
-        else
-        {
-          const TopoDS_Face& F1 = TopoDS::Face( S );
-          const TopoDS_Face& F2 = TopoDS::Face( eE[0]->_sWOL );
-          const TopoDS_Edge& E  = TopoDS::Edge( eExp.Current() );
-          for ( size_t i = 0; i < eE.size() && !needSmooth; ++i )
-          {
-            gp_Vec dir1 = getFaceDir( F1, E, eE[i]->_nodes[0], helper, ok );
-            gp_Vec dir2 = getFaceDir( F2, E, eE[i]->_nodes[0], helper, ok );
-            double angle = dir1.Angle( dir2 );
-            double cosin = cos( angle );
-            needSmooth = ( cosin > 0.1 );
-          }
+            if ( eE[i]->_cosin > theMinSmoothCosin )
+            {
+              SMDS_ElemIteratorPtr fIt = eE[i]->_nodes[0]->GetInverseElementIterator(SMDSAbs_Face);
+              while ( fIt->more() && !needSmooth )
+              {
+                const SMDS_MeshElement* face = fIt->next();
+                if ( getDistFromEdge( face, eE[i]->_nodes[0], faceSize ))
+                  needSmooth = needSmoothing( eE[i]->_cosin, tgtThick, faceSize );
+              }
+            }
         }
+        // else
+        // {
+        //   const TopoDS_Face& F1 = TopoDS::Face( S );
+        //   const TopoDS_Face& F2 = TopoDS::Face( eE[0]->_sWOL );
+        //   const TopoDS_Edge& E  = TopoDS::Edge( eExp.Current() );
+        //   for ( size_t i = 0; i < eE.size() && !needSmooth; ++i )
+        //   {
+        //     gp_Vec dir1 = getFaceDir( F1, E, eE[i]->_nodes[0], helper, ok );
+        //     gp_Vec dir2 = getFaceDir( F2, E, eE[i]->_nodes[0], helper, ok );
+        //     double angle = dir1.Angle(  );
+        //     double cosin = cos( angle );
+        //     needSmooth = ( cosin > theMinSmoothCosin );
+        //   }
+        // }
       }
       break;
     }
@@ -1905,6 +2368,7 @@ bool _ViscousBuilder::sortEdges( _SolidData&                    data,
       continue;
     default:;
     }
+
     if ( needSmooth )
     {
       if ( S.ShapeType() == TopAbs_EDGE ) shapesToSmooth.push_front( iS );
@@ -1914,16 +2378,18 @@ bool _ViscousBuilder::sortEdges( _SolidData&                    data,
   } // loop on edgesByGeom
 
   data._edges.reserve( data._n2eMap.size() );
-  data._endEdgeToSmooth.clear();
+  data._endEdgeOnShape.clear();
 
   // first we put _LayerEdge's on shapes to smooth
+  data._nbShapesToSmooth = 0;
   list< TGeomID >::iterator gIt = shapesToSmooth.begin();
   for ( ; gIt != shapesToSmooth.end(); ++gIt )
   {
     vector<_LayerEdge*>& eVec = edgesByGeom[ *gIt ];
     if ( eVec.empty() ) continue;
     data._edges.insert( data._edges.end(), eVec.begin(), eVec.end() );
-    data._endEdgeToSmooth.push_back( data._edges.size() );
+    data._endEdgeOnShape.push_back( data._edges.size() );
+    data._nbShapesToSmooth++;
     eVec.clear();
   }
 
@@ -1931,8 +2397,49 @@ bool _ViscousBuilder::sortEdges( _SolidData&                    data,
   for ( size_t iS = 0; iS < edgesByGeom.size(); ++iS )
   {
     vector<_LayerEdge*>& eVec = edgesByGeom[iS];
+    if ( eVec.empty() ) continue;
     data._edges.insert( data._edges.end(), eVec.begin(), eVec.end() );
-    eVec.clear();
+    data._endEdgeOnShape.push_back( data._edges.size() );
+    //eVec.clear();
+  }
+
+  // compute average StdMeshers_ViscousLayers parameters for each shape
+
+  data._hypOnShape.clear();
+  if ( data._hyps.size() == 1 )
+  {
+    data._hypOnShape.resize( data._endEdgeOnShape.size(), AverageHyp( data._hyps.back() ));
+  }
+  else
+  {
+    data._hypOnShape.resize( data._endEdgeOnShape.size() );
+    map< TGeomID, const StdMeshers_ViscousLayers* >::iterator f2hyp;
+    for ( size_t i = 0; i < data._endEdgeOnShape.size(); ++i )
+    {
+      int       iEnd = data._endEdgeOnShape[i];
+      _LayerEdge* LE = data._edges[ iEnd-1 ];
+      TGeomID iShape = LE->_nodes[0]->getshapeId();
+      const TopoDS_Shape& S = getMeshDS()->IndexToShape( iShape );
+      if ( S.ShapeType() == TopAbs_FACE )
+      {
+        if (( f2hyp = data._face2hyp.find( iShape )) != data._face2hyp.end() )
+        {
+          data._hypOnShape[ i ].Add( f2hyp->second );
+        }
+      }
+      else
+      {
+        PShapeIteratorPtr fIt = SMESH_MesherHelper::GetAncestors( S, *_mesh, TopAbs_FACE );
+        while ( const TopoDS_Shape* face = fIt->next() )
+        {
+          TGeomID faceID = getMeshDS()->ShapeToIndex( *face );
+          if (( f2hyp = data._face2hyp.find( faceID )) != data._face2hyp.end() )
+          {
+            data._hypOnShape[ i ].Add( f2hyp->second );
+          }
+        }
+      }
+    }
   }
 
   return ok;
@@ -1955,8 +2462,8 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge&         edge,
   const SMDS_MeshNode* node = edge._nodes[0]; // source node
   SMDS_TypeOfPosition posType = node->GetPosition()->GetTypeOfPosition();
 
-  edge._len = 0;
-  edge._2neibors = 0;
+  edge._len       = 0;
+  edge._2neibors  = 0;
   edge._curvature = 0;
 
   // --------------------------
@@ -1967,18 +2474,16 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge&         edge,
   edge._normal.SetCoord(0,0,0);
 
   int totalNbFaces = 0;
-  gp_Pnt p;
-  gp_Vec du, dv, geomNorm;
+  gp_Vec geomNorm;
   bool normOK = true;
 
-  TGeomID shapeInd = node->getshapeId();
+  const TGeomID shapeInd = node->getshapeId();
   map< TGeomID, TopoDS_Shape >::const_iterator s2s = data._shrinkShape2Shape.find( shapeInd );
-  bool onShrinkShape ( s2s != data._shrinkShape2Shape.end() );
-  TopoDS_Shape vertEdge;
+  const bool onShrinkShape ( s2s != data._shrinkShape2Shape.end() );
 
   if ( onShrinkShape ) // one of faces the node is on has no layers
   {
-    vertEdge = getMeshDS()->IndexToShape( s2s->first ); // vertex or edge
+    TopoDS_Shape vertEdge = getMeshDS()->IndexToShape( s2s->first ); // vertex or edge
     if ( s2s->second.ShapeType() == TopAbs_EDGE )
     {
       // inflate from VERTEX along EDGE
@@ -2107,14 +2612,16 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge&         edge,
     if ( edge._sWOL.ShapeType() == TopAbs_EDGE )
     {
       double u = helper.GetNodeU( TopoDS::Edge( edge._sWOL ), node, 0, &normOK );
-      edge._pos.push_back( gp_XYZ( u, 0, 0));
-      getMeshDS()->SetNodeOnEdge( tgtNode, TopoDS::Edge( edge._sWOL ), u );
+      edge._pos.push_back( gp_XYZ( u, 0, 0 ));
+      if ( edge._nodes.size() > 1 )
+        getMeshDS()->SetNodeOnEdge( tgtNode, TopoDS::Edge( edge._sWOL ), u );
     }
     else // TopAbs_FACE
     {
       gp_XY uv = helper.GetNodeUV( TopoDS::Face( edge._sWOL ), node, 0, &normOK );
       edge._pos.push_back( gp_XYZ( uv.X(), uv.Y(), 0));
-      getMeshDS()->SetNodeOnFace( tgtNode, TopoDS::Face( edge._sWOL ), uv.X(), uv.Y() );
+      if ( edge._nodes.size() > 1 )
+        getMeshDS()->SetNodeOnFace( tgtNode, TopoDS::Face( edge._sWOL ), uv.X(), uv.Y() );
     }
   }
   else
@@ -2144,14 +2651,14 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge&         edge,
   {
     edge._2neibors = new _2NearEdges;
     // target node instead of source ones will be set later
-    if ( ! findNeiborsOnEdge( &edge,
-                              edge._2neibors->_nodes[0],
-                              edge._2neibors->_nodes[1],
-                              data))
-      return false;
-    edge.SetDataByNeighbors( edge._2neibors->_nodes[0],
-                             edge._2neibors->_nodes[1],
-                             helper);
+    // if ( ! findNeiborsOnEdge( &edge,
+    //                           edge._2neibors->_nodes[0],
+    //                           edge._2neibors->_nodes[1],
+    //                           data))
+    //   return false;
+    // edge.SetDataByNeighbors( edge._2neibors->_nodes[0],
+    //                          edge._2neibors->_nodes[1],
+    //                          helper);
   }
 
   edge.SetCosin( edge._cosin ); // to update edge._lenFactor
@@ -2226,12 +2733,30 @@ gp_XYZ _ViscousBuilder::getFaceNormal(const SMDS_MeshNode* node,
   isOK = false;
 
   Handle(Geom_Surface) surface = BRep_Tool::Surface( face );
-  if ( GeomLib::NormEstim( surface, uv, 1e-10, normal ) < 3 )
+  int pointKind = GeomLib::NormEstim( surface, uv, 1e-5, normal );
+  enum { REGULAR = 0, QUASYSINGULAR, CONICAL, IMPOSSIBLE };
+
+  if ( pointKind == IMPOSSIBLE &&
+       node->GetPosition()->GetDim() == 2 ) // node inside the FACE
+  {
+    // probably NormEstim() failed due to a too high tolerance
+    pointKind = GeomLib::NormEstim( surface, uv, 1e-20, normal );
+    isOK = ( pointKind < IMPOSSIBLE );
+  }
+  if ( pointKind < IMPOSSIBLE )
   {
-    normal;
+    if ( pointKind != REGULAR &&
+         !shiftInside &&
+         node->GetPosition()->GetDim() < 2 ) // FACE boundary
+    {
+      gp_XYZ normShift = getFaceNormal( node, face, helper, isOK, /*shiftInside=*/true );
+      if ( normShift * normal.XYZ() < 0. )
+        normal = normShift;
+    }
     isOK = true;
   }
-  else // hard singularity
+
+  if ( !isOK ) // hard singularity, to call with shiftInside=true ?
   {
     const TGeomID faceID = helper.GetMeshDS()->ShapeToIndex( face );
 
@@ -2244,7 +2769,9 @@ gp_XYZ _ViscousBuilder::getFaceNormal(const SMDS_MeshNode* node,
         isOK = SMESH_MeshAlgos::FaceNormal( f, (gp_XYZ&) normal.XYZ(), /*normalized=*/true );
         if ( isOK )
         {
-          if ( helper.IsReversedSubMesh( face ))
+          TopoDS_Face ff = face;
+          ff.Orientation( TopAbs_FORWARD );
+          if ( helper.IsReversedSubMesh( ff ))
             normal.Reverse();
           break;
         }
@@ -2314,12 +2841,10 @@ gp_XYZ _ViscousBuilder::getWeigthedNormal( const SMDS_MeshNode*         n,
     }
     else
     {
-      TopoDS_Vertex v10 = SMESH_MesherHelper::IthVertex( 1, ee[ 0 ]);
-      TopoDS_Vertex v01 = SMESH_MesherHelper::IthVertex( 0, ee[ 1 ]);
-      if ( !v10.IsSame( v01 ))
+      if ( !V.IsSame( SMESH_MesherHelper::IthVertex( 0, ee[ 1 ] )))
         std::swap( ee[0], ee[1] );
     }
-    angles[i] = SMESH_MesherHelper::GetAngle( ee[0], ee[1], F );
+    angles[i] = SMESH_MesherHelper::GetAngle( ee[0], ee[1], F, TopoDS::Vertex( V ));
   }
 
   // compute a weighted normal
@@ -2347,11 +2872,10 @@ bool _ViscousBuilder::findNeiborsOnEdge(const _LayerEdge*     edge,
                                         _SolidData&           data)
 {
   const SMDS_MeshNode* node = edge->_nodes[0];
-  const int shapeInd = node->getshapeId();
-  SMESHDS_SubMesh* edgeSM = 0;
+  const int        shapeInd = node->getshapeId();
+  SMESHDS_SubMesh*   edgeSM = 0;
   if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_EDGE )
   {
-    
     edgeSM = getMeshDS()->MeshElements( shapeInd );
     if ( !edgeSM || edgeSM->NbElements() == 0 )
       return error(SMESH_Comment("Not meshed EDGE ") << shapeInd, data._index);
@@ -2399,30 +2923,31 @@ void _LayerEdge::SetDataByNeighbors( const SMDS_MeshNode* n1,
 
   // Set _curvature
 
-  double sumLen = vec1.Modulus() + vec2.Modulus();
+  double      sumLen = vec1.Modulus() + vec2.Modulus();
   _2neibors->_wgt[0] = 1 - vec1.Modulus() / sumLen;
   _2neibors->_wgt[1] = 1 - vec2.Modulus() / sumLen;
   double avgNormProj = 0.5 * ( _normal * vec1 + _normal * vec2 );
-  double avgLen = 0.5 * ( vec1.Modulus() + vec2.Modulus() );
+  double      avgLen = 0.5 * ( vec1.Modulus() + vec2.Modulus() );
   if ( _curvature ) delete _curvature;
   _curvature = _Curvature::New( avgNormProj, avgLen );
-#ifdef __myDEBUG
-//     if ( _curvature )
-//       cout << _nodes[0]->GetID()
-//            << " CURV r,k: " << _curvature->_r<<","<<_curvature->_k
-//            << " proj = "<<avgNormProj<< " len = " << avgLen << "| lenDelta(0) = "
-//            << _curvature->lenDelta(0) << endl;
-#endif
+  // if ( _curvature )
+  //   debugMsg( _nodes[0]->GetID()
+  //             << " CURV r,k: " << _curvature->_r<<","<<_curvature->_k
+  //             << " proj = "<<avgNormProj<< " len = " << avgLen << "| lenDelta(0) = "
+  //             << _curvature->lenDelta(0) );
 
   // Set _plnNorm
 
   if ( _sWOL.IsNull() )
   {
     TopoDS_Shape S = helper.GetSubShapeByNode( _nodes[0], helper.GetMeshDS() );
-    gp_XYZ dirE = getEdgeDir( TopoDS::Edge( S ), _nodes[0], helper );
+    TopoDS_Edge  E = TopoDS::Edge( S );
+    // if ( SMESH_Algo::isDegenerated( E ))
+    //   return;
+    gp_XYZ dirE    = getEdgeDir( E, _nodes[0], helper );
     gp_XYZ plnNorm = dirE ^ _normal;
-    double proj0 = plnNorm * vec1;
-    double proj1 = plnNorm * vec2;
+    double proj0   = plnNorm * vec1;
+    double proj1   = plnNorm * vec2;
     if ( fabs( proj0 ) > 1e-10 || fabs( proj1 ) > 1e-10 )
     {
       if ( _2neibors->_plnNorm ) delete _2neibors->_plnNorm;
@@ -2545,11 +3070,6 @@ void _ViscousBuilder::makeGroupOfLE()
   for ( size_t i = 0 ; i < _sdVec.size(); ++i )
   {
     if ( _sdVec[i]._edges.empty() ) continue;
-//     string name = SMESH_Comment("_LayerEdge's_") << i;
-//     int id;
-//     SMESH_Group* g = _mesh->AddGroup(SMDSAbs_Edge, name.c_str(), id );
-//     SMESHDS_Group* gDS = (SMESHDS_Group*)g->GetGroupDS();
-//     SMESHDS_Mesh* mDS = _mesh->GetMeshDS();
 
     dumpFunction( SMESH_Comment("make_LayerEdge_") << i );
     for ( size_t j = 0 ; j < _sdVec[i]._edges.size(); ++j )
@@ -2558,7 +3078,6 @@ void _ViscousBuilder::makeGroupOfLE()
       for ( size_t iN = 1; iN < le->_nodes.size(); ++iN )
         dumpCmd(SMESH_Comment("mesh.AddEdge([ ") <<le->_nodes[iN-1]->GetID()
                 << ", " << le->_nodes[iN]->GetID() <<"])");
-      //gDS->SMDSGroup().Add( mDS->AddEdge( le->_nodes[iN-1], le->_nodes[iN]));
     }
     dumpFunctionEnd();
 
@@ -2573,10 +3092,6 @@ void _ViscousBuilder::makeGroupOfLE()
     }
     dumpFunctionEnd();
 
-//     name = SMESH_Comment("tmp_faces ") << i;
-//     g = _mesh->AddGroup(SMDSAbs_Face, name.c_str(), id );
-//     gDS = (SMESHDS_Group*)g->GetGroupDS();
-//     SMESH_MeshEditor editor( _mesh );
     dumpFunction( SMESH_Comment("makeTmpFaces_") << i );
     TopExp_Explorer fExp( _sdVec[i]._solid, TopAbs_FACE );
     for ( ; fExp.More(); fExp.Next() )
@@ -2591,8 +3106,6 @@ void _ViscousBuilder::makeGroupOfLE()
           for ( int j=0; j < e->NbCornerNodes(); ++j )
             cmd << e->GetNode(j)->GetID() << (j+1<e->NbCornerNodes() ? ",": "])");
           dumpCmd( cmd );
-          //vector<const SMDS_MeshNode*> nodes( e->begin_nodes(), e->end_nodes() );
-          //gDS->SMDSGroup().Add( editor.AddElement( nodes, e->GetType(), e->IsPoly()));
         }
       }
     }
@@ -2601,6 +3114,31 @@ void _ViscousBuilder::makeGroupOfLE()
 #endif
 }
 
+//================================================================================
+/*!
+ * \brief Find maximal _LayerEdge length (layer thickness) limited by geometry
+ */
+//================================================================================
+
+void _ViscousBuilder::computeGeomSize( _SolidData& data )
+{
+  data._geomSize = Precision::Infinite();
+  double intersecDist;
+  auto_ptr<SMESH_ElementSearcher> searcher
+    ( SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(),
+                                           data._proxyMesh->GetFaces( data._solid )) );
+
+  TNode2Edge::iterator n2e = data._n2eMap.begin(), n2eEnd = data._n2eMap.end();
+  for ( ; n2e != n2eEnd; ++n2e )
+  {
+    _LayerEdge* edge = n2e->second;
+    if ( edge->IsOnEdge() ) continue;
+    edge->FindIntersection( *searcher, intersecDist, data._epsilon );
+    if ( data._geomSize > intersecDist && intersecDist > 0 )
+      data._geomSize = intersecDist;
+  }
+}
+
 //================================================================================
 /*!
  * \brief Increase length of _LayerEdge's to reach the required thickness of layers
@@ -2613,54 +3151,45 @@ bool _ViscousBuilder::inflate(_SolidData& data)
 
   // Limit inflation step size by geometry size found by itersecting
   // normals of _LayerEdge's with mesh faces
-  double geomSize = Precision::Infinite(), intersecDist;
-  auto_ptr<SMESH_ElementSearcher> searcher
-    ( SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(),
-                                           data._proxyMesh->GetFaces( data._solid )) );
-  for ( size_t i = 0; i < data._edges.size(); ++i )
-  {
-    if ( data._edges[i]->IsOnEdge() ) continue;
-    data._edges[i]->FindIntersection( *searcher, intersecDist, data._epsilon );
-    if ( geomSize > intersecDist && intersecDist > 0 )
-      geomSize = intersecDist;
-  }
-  if ( data._stepSize > 0.3 * geomSize )
-    limitStepSize( data, 0.3 * geomSize );
+  if ( data._stepSize > 0.3 * data._geomSize )
+    limitStepSize( data, 0.3 * data._geomSize );
 
-  const double tgtThick = data._hyp->GetTotalThickness();
-  if ( data._stepSize > tgtThick )
-    limitStepSize( data, tgtThick );
+  const double tgtThick = data._maxThickness;
+  if ( data._stepSize > data._minThickness )
+    limitStepSize( data, data._minThickness );
 
   if ( data._stepSize < 1. )
     data._epsilon = data._stepSize * 1e-7;
 
-#ifdef __myDEBUG
-  cout << "-- geomSize = " << geomSize << ", stepSize = " << data._stepSize << endl;
-#endif
+  debugMsg( "-- geomSize = " << data._geomSize << ", stepSize = " << data._stepSize );
 
   double avgThick = 0, curThick = 0, distToIntersection = Precision::Infinite();
   int nbSteps = 0, nbRepeats = 0;
-  while ( 1.01 * avgThick < tgtThick )
+  int iBeg, iEnd, iS;
+  while ( avgThick < 0.99 )
   {
     // new target length
     curThick += data._stepSize;
     if ( curThick > tgtThick )
     {
-      curThick = tgtThick + ( tgtThick-avgThick ) * nbRepeats;
+      curThick = tgtThick + tgtThick*( 1.-avgThick ) * nbRepeats;
       nbRepeats++;
     }
 
     // Elongate _LayerEdge's
     dumpFunction(SMESH_Comment("inflate")<<data._index<<"_step"<<nbSteps); // debug
-    for ( size_t i = 0; i < data._edges.size(); ++i )
+    for ( iBeg = 0, iS = 0; iS < data._endEdgeOnShape.size(); ++iS )
     {
-      data._edges[i]->SetNewLength( curThick, helper );
+      const double shapeCurThick = Min( curThick, data._hypOnShape[ iS ].GetTotalThickness() );
+      for ( iEnd = data._endEdgeOnShape[ iS ]; iBeg < iEnd; ++iBeg )
+      {
+        data._edges[iBeg]->SetNewLength( shapeCurThick, helper );
+      }
     }
     dumpFunctionEnd();
 
-    if ( !nbSteps )
-      if ( !updateNormals( data, helper ) )
-        return false;
+    if ( !updateNormals( data, helper, nbSteps ))
+      return false;
 
     // Improve and check quality
     if ( !smoothAndCheck( data, nbSteps, distToIntersection ))
@@ -2680,19 +3209,22 @@ bool _ViscousBuilder::inflate(_SolidData& data)
 
     // Evaluate achieved thickness
     avgThick = 0;
-    for ( size_t i = 0; i < data._edges.size(); ++i )
-      avgThick += data._edges[i]->_len;
+    for ( iBeg = 0, iS = 0; iS < data._endEdgeOnShape.size(); ++iS )
+    {
+      const double shapeTgtThick = data._hypOnShape[ iS ].GetTotalThickness();
+      for ( iEnd = data._endEdgeOnShape[ iS ]; iBeg < iEnd; ++iBeg )
+      {
+        avgThick += Min( 1., data._edges[iBeg]->_len / shapeTgtThick );
+      }
+    }
     avgThick /= data._edges.size();
-#ifdef __myDEBUG
-    cout << "-- Thickness " << avgThick << " reached" << endl;
-#endif
+    debugMsg( "-- Thickness " << curThick << " ("<< avgThick*100 << "%) reached" );
 
-    if ( distToIntersection < avgThick*1.5 )
+    if ( distToIntersection < tgtThick*avgThick*1.5 )
     {
-#ifdef __myDEBUG
-      cout << "-- Stop inflation since distToIntersection( "<<distToIntersection<<" ) < avgThick( "
-           << avgThick << " ) * 1.5" << endl;
-#endif
+      debugMsg( "-- Stop inflation since "
+                << " distToIntersection( "<<distToIntersection<<" ) < avgThick( "
+                << tgtThick*avgThick << " ) * 1.5" );
       break;
     }
     // new step size
@@ -2700,11 +3232,39 @@ bool _ViscousBuilder::inflate(_SolidData& data)
     if ( data._stepSizeNodes[0] )
       data._stepSize = data._stepSizeCoeff *
         SMESH_TNodeXYZ(data._stepSizeNodes[0]).Distance(data._stepSizeNodes[1]);
-  }
+
+  } // while ( avgThick < 0.99 )
 
   if (nbSteps == 0 )
     return error("failed at the very first inflation step", data._index);
 
+  if ( avgThick < 0.99 )
+    if ( SMESH_subMesh* sm = _mesh->GetSubMeshContaining( data._index ))
+    {
+      SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
+      if ( !smError || smError->IsOK() )
+        smError.reset
+          ( new SMESH_ComputeError (COMPERR_WARNING,
+                                    SMESH_Comment("Thickness ") << tgtThick <<
+                                    " of viscous layers not reached,"
+                                    " average reached thickness is " << avgThick*tgtThick));
+    }
+
+
+  // Restore position of src nodes moved by infaltion on _noShrinkShapes
+  dumpFunction(SMESH_Comment("restoNoShrink_So")<<data._index); // debug
+  for ( iEnd = iS = 0; iS < data._endEdgeOnShape.size(); ++iS )
+  {
+    iBeg = iEnd;
+    iEnd = data._endEdgeOnShape[ iS ];
+    if ( data._edges[ iBeg ]->_nodes.size() == 1 )
+      for ( ; iBeg < iEnd; ++iBeg )
+      {
+        restoreNoShrink( *data._edges[ iBeg ] );
+      }
+  }
+  dumpFunctionEnd();
+
   return true;
 }
 
@@ -2718,7 +3278,7 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
                                      const int   nbSteps,
                                      double &    distToIntersection)
 {
-  if ( data._endEdgeToSmooth.empty() )
+  if ( data._nbShapesToSmooth == 0 )
     return true; // no shapes needing smoothing
 
   bool moved, improved;
@@ -2728,10 +3288,20 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
   TopoDS_Face F;
 
   int iBeg, iEnd = 0;
-  for ( size_t iS = 0; iS < data._endEdgeToSmooth.size(); ++iS )
+  for ( int iS = 0; iS < data._nbShapesToSmooth; ++iS )
   {
     iBeg = iEnd;
-    iEnd = data._endEdgeToSmooth[ iS ];
+    iEnd = data._endEdgeOnShape[ iS ];
+
+    // bool toSmooth = false;
+    // for ( int i = iBeg; i < iEnd; ++i )
+    //   toSmooth = data._edges[ iBeg ]->NbSteps() >= nbSteps+1;
+    // if ( !toSmooth )
+    // {
+    //   if ( iS+1 == data._nbShapesToSmooth )
+    //     data._nbShapesToSmooth--;
+    //   continue; // target length reached some steps before
+    // }
 
     if ( !data._edges[ iBeg ]->_sWOL.IsNull() &&
          data._edges[ iBeg ]->_sWOL.ShapeType() == TopAbs_FACE )
@@ -2766,7 +3336,6 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
           dumpCmd( SMESH_Comment("# end step ")<<step);
         }
         while ( moved && step++ < 5 );
-        //cout << " NB STEPS: " << step << endl;
       }
       dumpFunctionEnd();
     }
@@ -2781,11 +3350,15 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
         int oldBadNb = badNb;
         badNb = 0;
         moved = false;
-        for ( int i = iBeg; i < iEnd; ++i )
-          moved |= data._edges[i]->Smooth(badNb);
+        if ( step % 2 )
+          for ( int i = iBeg; i < iEnd; ++i ) // iterate forward
+            moved |= data._edges[i]->Smooth(badNb);
+        else
+          for ( int i = iEnd-1; i >= iBeg; --i ) // iterate backward
+            moved |= data._edges[i]->Smooth(badNb);
         improved = ( badNb < oldBadNb );
 
-        // issue 22576. no bad faces but still there are intersections to fix
+        // issue 22576 -- no bad faces but still there are intersections to fix
         if ( improved && badNb == 0 )
           stepLimit = step + 3;
 
@@ -2813,22 +3386,17 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
     }
   } // loop on shapes to smooth
 
-  // Check orientation of simplices of _simplexTestEdges
-  for ( size_t i = 0; i < data._simplexTestEdges.size(); ++i )
+  // Check orientation of simplices of _ConvexFace::_simplexTestEdges
+  map< TGeomID, _ConvexFace >::iterator id2face = data._convexFaces.begin();
+  for ( ; id2face != data._convexFaces.end(); ++id2face )
   {
-    const _LayerEdge* edge = data._simplexTestEdges[i];
-    SMESH_TNodeXYZ tgtXYZ( edge->_nodes.back() );
-    for ( size_t j = 0; j < edge->_simplices.size(); ++j )
-      if ( !edge->_simplices[j].IsForward( edge->_nodes[0], &tgtXYZ ))
-      {
-#ifdef __myDEBUG
-        cout << "Bad simplex of _simplexTestEdges ("
-             << " "<< edge->_nodes[0]->GetID()<< " "<< tgtXYZ._node->GetID()
-             << " "<< edge->_simplices[j]._nPrev->GetID()
-             << " "<< edge->_simplices[j]._nNext->GetID() << " )" << endl;
-#endif
-        return false;
-      }
+    _ConvexFace & convFace = (*id2face).second;
+    if ( !convFace._simplexTestEdges.empty() &&
+         convFace._simplexTestEdges[0]->_nodes[0]->GetPosition()->GetDim() == 2 )
+      continue; // _simplexTestEdges are based on FACE -- already checked while smoothing
+
+    if ( !convFace.CheckPrisms() )
+      return false;
   }
 
   // Check if the last segments of _LayerEdge intersects 2D elements;
@@ -2841,21 +3409,25 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
   distToIntersection = Precision::Infinite();
   double dist;
   const SMDS_MeshElement* intFace = 0;
-#ifdef __myDEBUG
   const SMDS_MeshElement* closestFace = 0;
   int iLE = 0;
-#endif
   for ( size_t i = 0; i < data._edges.size(); ++i )
   {
+    if ( !data._edges[i]->_sWOL.IsNull() )
+      continue;
     if ( data._edges[i]->FindIntersection( *searcher, dist, data._epsilon, &intFace ))
       return false;
     if ( distToIntersection > dist )
     {
+      // ignore intersection of a _LayerEdge based on a _ConvexFace with a face
+      // lying on this _ConvexFace
+      if ( _ConvexFace* convFace = data.GetConvexFace( intFace->getshapeId() ))
+        if ( convFace->_subIdToEdgeEnd.count ( data._edges[i]->_nodes[0]->getshapeId() ))
+          continue;
+
       distToIntersection = dist;
-#ifdef __myDEBUG
       iLE = i;
       closestFace = intFace;
-#endif
     }
   }
 #ifdef __myDEBUG
@@ -2893,24 +3465,7 @@ Handle(Geom_Curve) _SolidData::CurveForSmooth( const TopoDS_Edge&    E,
   if ( i2curve == _edge2curve.end() )
   {
     // sort _LayerEdge's by position on the EDGE
-    {
-      map< double, _LayerEdge* > u2edge;
-      for ( int i = iFrom; i < iTo; ++i )
-        u2edge.insert( make_pair( helper.GetNodeU( E, _edges[i]->_nodes[0] ), _edges[i] ));
-
-      ASSERT( u2edge.size() == iTo - iFrom );
-      map< double, _LayerEdge* >::iterator u2e = u2edge.begin();
-      for ( int i = iFrom; i < iTo; ++i, ++u2e )
-        _edges[i] = u2e->second;
-
-      // set _2neibors according to the new order
-      for ( int i = iFrom; i < iTo-1; ++i )
-        if ( _edges[i]->_2neibors->_nodes[1] != _edges[i+1]->_nodes.back() )
-          _edges[i]->_2neibors->reverse();
-      if ( u2edge.size() > 1 &&
-           _edges[iTo-1]->_2neibors->_nodes[0] != _edges[iTo-2]->_nodes.back() )
-        _edges[iTo-1]->_2neibors->reverse();
-    }
+    SortOnEdge( E, iFrom, iTo, helper );
 
     SMESHDS_SubMesh* smDS = helper.GetMeshDS()->MeshElements( eIndex );
 
@@ -2939,8 +3494,8 @@ Handle(Geom_Curve) _SolidData::CurveForSmooth( const TopoDS_Edge&    E,
           bndBox.Add( SMESH_TNodeXYZ( nIt->next() ));
         gp_XYZ size = bndBox.CornerMax() - bndBox.CornerMin();
 
-        SMESH_TNodeXYZ p0( _edges[iFrom]->_2neibors->_nodes[0] );
-        SMESH_TNodeXYZ p1( _edges[iFrom]->_2neibors->_nodes[1] );
+        SMESH_TNodeXYZ p0( _edges[iFrom]->_2neibors->tgtNode(0) );
+        SMESH_TNodeXYZ p1( _edges[iFrom]->_2neibors->tgtNode(1) );
         const double lineTol = 1e-2 * ( p0 - p1 ).Modulus();
         for ( int i = 0; i < 3 && !isLine; ++i )
           isLine = ( size.Coord( i+1 ) <= lineTol );
@@ -3001,6 +3556,121 @@ Handle(Geom_Curve) _SolidData::CurveForSmooth( const TopoDS_Edge&    E,
   return i2curve->second;
 }
 
+//================================================================================
+/*!
+ * \brief Sort _LayerEdge's by a parameter on a given EDGE
+ */
+//================================================================================
+
+void _SolidData::SortOnEdge( const TopoDS_Edge&  E,
+                             const int           iFrom,
+                             const int           iTo,
+                             SMESH_MesherHelper& helper)
+{
+  map< double, _LayerEdge* > u2edge;
+  for ( int i = iFrom; i < iTo; ++i )
+    u2edge.insert( make_pair( helper.GetNodeU( E, _edges[i]->_nodes[0] ), _edges[i] ));
+
+  ASSERT( u2edge.size() == iTo - iFrom );
+  map< double, _LayerEdge* >::iterator u2e = u2edge.begin();
+  for ( int i = iFrom; i < iTo; ++i, ++u2e )
+    _edges[i] = u2e->second;
+
+  // set _2neibors according to the new order
+  for ( int i = iFrom; i < iTo-1; ++i )
+    if ( _edges[i]->_2neibors->tgtNode(1) != _edges[i+1]->_nodes.back() )
+      _edges[i]->_2neibors->reverse();
+  if ( u2edge.size() > 1 &&
+       _edges[iTo-1]->_2neibors->tgtNode(0) != _edges[iTo-2]->_nodes.back() )
+    _edges[iTo-1]->_2neibors->reverse();
+}
+
+//================================================================================
+/*!
+ * \brief Return index corresponding to the shape in _endEdgeOnShape
+ */
+//================================================================================
+
+bool _SolidData::GetShapeEdges(const TGeomID shapeID,
+                               size_t &      iEdgesEnd,
+                               int*          iBeg,
+                               int*          iEnd ) const
+{
+  int beg = 0, end = 0;
+  for ( iEdgesEnd = 0; iEdgesEnd < _endEdgeOnShape.size(); ++iEdgesEnd )
+  {
+    end = _endEdgeOnShape[ iEdgesEnd ];
+    TGeomID sID = _edges[ beg ]->_nodes[0]->getshapeId();
+    if ( sID == shapeID )
+    {
+      if ( iBeg ) *iBeg = beg;
+      if ( iEnd ) *iEnd = end;
+      return true;
+    }
+    beg = end;
+  }
+  return false;
+}
+
+//================================================================================
+/*!
+ * \brief Add faces for smoothing
+ */
+//================================================================================
+
+void _SolidData::AddShapesToSmooth( const set< TGeomID >& faceIDs )
+{
+  // convert faceIDs to indices in _endEdgeOnShape
+  set< size_t > iEnds;
+  size_t end;
+  set< TGeomID >::const_iterator fId = faceIDs.begin();
+  for ( ; fId != faceIDs.end(); ++fId )
+    if ( GetShapeEdges( *fId, end ) && end >= _nbShapesToSmooth )
+      iEnds.insert( end );
+
+  set< size_t >::iterator endsIt = iEnds.begin();
+
+  // "add" by move of _nbShapesToSmooth
+  int nbFacesToAdd = iEnds.size();
+  while ( endsIt != iEnds.end() && *endsIt == _nbShapesToSmooth )
+  {
+    ++endsIt;
+    ++_nbShapesToSmooth;
+    --nbFacesToAdd;
+  }
+  if ( endsIt == iEnds.end() )
+    return;
+
+  // Move _LayerEdge's on FACEs just after _nbShapesToSmooth
+
+  vector< _LayerEdge* > nonSmoothLE, smoothLE;
+  size_t lastSmooth = *iEnds.rbegin();
+  int iBeg, iEnd;
+  for ( size_t i = _nbShapesToSmooth; i <= lastSmooth; ++i )
+  {
+    vector< _LayerEdge* > & edgesVec = iEnds.count(i) ? smoothLE : nonSmoothLE;
+    iBeg = i ? _endEdgeOnShape[ i-1 ] : 0;
+    iEnd = _endEdgeOnShape[ i ];
+    edgesVec.insert( edgesVec.end(), _edges.begin() + iBeg, _edges.begin() + iEnd ); 
+  }
+
+  iBeg = _nbShapesToSmooth ? _endEdgeOnShape[ _nbShapesToSmooth-1 ] : 0;
+  std::copy( smoothLE.begin(),    smoothLE.end(),    &_edges[ iBeg ] );
+  std::copy( nonSmoothLE.begin(), nonSmoothLE.end(), &_edges[ iBeg + smoothLE.size()]);
+
+  // update _endEdgeOnShape
+  for ( size_t i = _nbShapesToSmooth; i < _endEdgeOnShape.size(); ++i )
+  {
+    TGeomID curShape = _edges[ iBeg ]->_nodes[0]->getshapeId();
+    while ( ++iBeg < _edges.size() &&
+            curShape == _edges[ iBeg ]->_nodes[0]->getshapeId() );
+
+    _endEdgeOnShape[ i ] = iBeg;
+  }
+
+  _nbShapesToSmooth += nbFacesToAdd;
+}
+
 //================================================================================
 /*!
  * \brief smooth _LayerEdge's on a staight EDGE or circular EDGE
@@ -3037,8 +3707,8 @@ bool _ViscousBuilder::smoothAnalyticEdge( _SolidData&           data,
   {
     if ( F.IsNull() ) // 3D
     {
-      SMESH_TNodeXYZ p0( data._edges[iFrom]->_2neibors->_nodes[0]);
-      SMESH_TNodeXYZ p1( data._edges[iTo-1]->_2neibors->_nodes[1]);
+      SMESH_TNodeXYZ p0( data._edges[iFrom]->_2neibors->tgtNode(0));
+      SMESH_TNodeXYZ p1( data._edges[iTo-1]->_2neibors->tgtNode(1));
       for ( int i = iFrom; i < iTo; ++i )
       {
         double r = len[i-iFrom] / len.back();
@@ -3051,10 +3721,12 @@ bool _ViscousBuilder::smoothAnalyticEdge( _SolidData&           data,
     }
     else
     {
-      gp_XY uv0 = helper.GetNodeUV( F, data._edges[iFrom]->_2neibors->_nodes[0]);
-      gp_XY uv1 = helper.GetNodeUV( F, data._edges[iTo-1]->_2neibors->_nodes[1]);
-      if ( data._edges[iFrom]->_2neibors->_nodes[0] ==
-           data._edges[iTo-1]->_2neibors->_nodes[1] ) // closed edge
+      // gp_XY uv0 = helper.GetNodeUV( F, data._edges[iFrom]->_2neibors->tgtNode(0));
+      // gp_XY uv1 = helper.GetNodeUV( F, data._edges[iTo-1]->_2neibors->tgtNode(1));
+      gp_XY uv0 = data._edges[iFrom]->_2neibors->_edges[0]->LastUV( F );
+      gp_XY uv1 = data._edges[iTo-1]->_2neibors->_edges[1]->LastUV( F );
+      if ( data._edges[iFrom]->_2neibors->tgtNode(0) ==
+           data._edges[iTo-1]->_2neibors->tgtNode(1) ) // closed edge
       {
         int iPeriodic = helper.GetPeriodicIndex();
         if ( iPeriodic == 1 || iPeriodic == 2 )
@@ -3091,8 +3763,8 @@ bool _ViscousBuilder::smoothAnalyticEdge( _SolidData&           data,
 
     if ( F.IsNull() ) // 3D
     {
-      if ( data._edges[iFrom]->_2neibors->_nodes[0] ==
-           data._edges[iTo-1]->_2neibors->_nodes[1] )
+      if ( data._edges[iFrom]->_2neibors->tgtNode(0) ==
+           data._edges[iTo-1]->_2neibors->tgtNode(1) )
         return true; // closed EDGE - nothing to do
 
       return false; // TODO ???
@@ -3101,9 +3773,12 @@ bool _ViscousBuilder::smoothAnalyticEdge( _SolidData&           data,
     {
       const gp_XY center( center3D.X(), center3D.Y() );
 
-      gp_XY uv0 = helper.GetNodeUV( F, data._edges[iFrom]->_2neibors->_nodes[0]);
-      gp_XY uvM = helper.GetNodeUV( F, data._edges[iFrom]->_nodes.back());
-      gp_XY uv1 = helper.GetNodeUV( F, data._edges[iTo-1]->_2neibors->_nodes[1]);
+      gp_XY uv0 = data._edges[iFrom]->_2neibors->_edges[0]->LastUV( F );
+      gp_XY uvM = data._edges[iFrom]->LastUV( F );
+      gp_XY uv1 = data._edges[iTo-1]->_2neibors->_edges[1]->LastUV( F );
+      // gp_XY uv0 = helper.GetNodeUV( F, data._edges[iFrom]->_2neibors->tgtNode(0));
+      // gp_XY uvM = helper.GetNodeUV( F, data._edges[iFrom]->_nodes.back());
+      // gp_XY uv1 = helper.GetNodeUV( F, data._edges[iTo-1]->_2neibors->tgtNode(1));
       gp_Vec2d vec0( center, uv0 );
       gp_Vec2d vecM( center, uvM );
       gp_Vec2d vec1( center, uv1 );
@@ -3145,8 +3820,12 @@ bool _ViscousBuilder::smoothAnalyticEdge( _SolidData&           data,
 //================================================================================
 
 bool _ViscousBuilder::updateNormals( _SolidData&         data,
-                                     SMESH_MesherHelper& helper )
+                                     SMESH_MesherHelper& helper,
+                                     int                 stepNb )
 {
+  if ( stepNb > 0 )
+    return updateNormalsOfConvexFaces( data, helper, stepNb );
+
   // make temporary quadrangles got by extrusion of
   // mesh edges along _LayerEdge._normal's
 
@@ -3163,7 +3842,7 @@ bool _ViscousBuilder::updateNormals( _SolidData&         data,
       const SMDS_MeshNode* tgt1 = edge->_nodes.back();
       for ( int j = 0; j < 2; ++j ) // loop on _2NearEdges
       {
-        const SMDS_MeshNode* tgt2 = edge->_2neibors->_nodes[j];
+        const SMDS_MeshNode* tgt2 = edge->_2neibors->tgtNode(j);
         pair< set< SMESH_TLink >::iterator, bool > link_isnew =
           extrudedLinks.insert( SMESH_TLink( tgt1, tgt2 ));
         if ( !link_isnew.second )
@@ -3171,21 +3850,10 @@ bool _ViscousBuilder::updateNormals( _SolidData&         data,
           extrudedLinks.erase( link_isnew.first );
           continue; // already extruded and will no more encounter
         }
-        // look for a _LayerEdge containg tgt2
-//         _LayerEdge* neiborEdge = 0;
-//         size_t di = 0; // check _edges[i+di] and _edges[i-di]
-//         while ( !neiborEdge && ++di <= data._edges.size() )
-//         {
-//           if ( i+di < data._edges.size() && data._edges[i+di]->_nodes.back() == tgt2 )
-//             neiborEdge = data._edges[i+di];
-//           else if ( di <= i && data._edges[i-di]->_nodes.back() == tgt2 )
-//             neiborEdge = data._edges[i-di];
-//         }
-//         if ( !neiborEdge )
-//           return error("updateNormals(): neighbor _LayerEdge not found", data._index);
+        // a _LayerEdge containg tgt2
         _LayerEdge* neiborEdge = edge->_2neibors->_edges[j];
 
-        TmpMeshFaceOnEdge* f = new TmpMeshFaceOnEdge( edge, neiborEdge, --_tmpFaceID );
+        _TmpMeshFaceOnEdge* f = new _TmpMeshFaceOnEdge( edge, neiborEdge, --_tmpFaceID );
         tmpFaces.push_back( f );
 
         dumpCmd(SMESH_Comment("mesh.AddFace([ ")
@@ -3215,10 +3883,12 @@ bool _ViscousBuilder::updateNormals( _SolidData&         data,
   for ( size_t i = 0; i < data._edges.size(); ++i )
   {
     _LayerEdge* edge = data._edges[i];
-    if ( !edge->IsOnEdge() || !edge->_sWOL.IsNull() ) continue;
+    if (( !edge->IsOnEdge() ) &&
+        ( edge->_sWOL.IsNull() || edge->_sWOL.ShapeType() != TopAbs_FACE ))
+      continue;
     if ( edge->FindIntersection( *searcher, dist, eps, &face ))
     {
-      const TmpMeshFaceOnEdge* f = (const TmpMeshFaceOnEdge*) face;
+      const _TmpMeshFaceOnEdge* f = (const _TmpMeshFaceOnEdge*) face;
       set< _LayerEdge*, _LayerEdgeCmp > & ee = edge2CloseEdge[ edge ];
       ee.insert( f->_le1 );
       ee.insert( f->_le2 );
@@ -3235,158 +3905,699 @@ bool _ViscousBuilder::updateNormals( _SolidData&         data,
   {
     dumpFunction(SMESH_Comment("updateNormals")<<data._index);
 
+    set< TGeomID > shapesToSmooth;
+
+    // vector to store new _normal and _cosin for each edge in edge2CloseEdge
+    vector< pair< _LayerEdge*, _LayerEdge > > edge2newEdge( edge2CloseEdge.size() );
+
     TLEdge2LEdgeSet::iterator e2ee = edge2CloseEdge.begin();
-    for ( ; e2ee != edge2CloseEdge.end(); ++e2ee )
+    for ( size_t iE = 0; e2ee != edge2CloseEdge.end(); ++e2ee, ++iE )
+    {
+      _LayerEdge* edge1 = e2ee->first;
+      _LayerEdge* edge2 = 0;
+      set< _LayerEdge*, _LayerEdgeCmp >& ee = e2ee->second;
+
+      edge2newEdge[ iE ].first = NULL;
+
+      // find EDGEs the edges reside
+      // TopoDS_Edge E1, E2;
+      // TopoDS_Shape S = helper.GetSubShapeByNode( edge1->_nodes[0], getMeshDS() );
+      // if ( S.ShapeType() != TopAbs_EDGE )
+      //   continue; // TODO: find EDGE by VERTEX
+      // E1 = TopoDS::Edge( S );
+      set< _LayerEdge*, _LayerEdgeCmp >::iterator eIt = ee.begin();
+      for ( ; !edge2 && eIt != ee.end(); ++eIt )
+      {
+        if ( edge1->_sWOL == (*eIt)->_sWOL )
+          edge2 = *eIt;
+      }
+      if ( !edge2 ) continue;
+
+      edge2newEdge[ iE ].first = edge1;
+      _LayerEdge& newEdge = edge2newEdge[ iE ].second;
+      // while ( E2.IsNull() && eIt != ee.end())
+      // {
+      //   _LayerEdge* e2 = *eIt++;
+      //   TopoDS_Shape S = helper.GetSubShapeByNode( e2->_nodes[0], getMeshDS() );
+      //   if ( S.ShapeType() == TopAbs_EDGE )
+      //     E2 = TopoDS::Edge( S ), edge2 = e2;
+      // }
+      // if ( E2.IsNull() ) continue; // TODO: find EDGE by VERTEX
+
+      // find 3 FACEs sharing 2 EDGEs
+
+      // TopoDS_Face FF1[2], FF2[2];
+      // PShapeIteratorPtr fIt = helper.GetAncestors(E1, *_mesh, TopAbs_FACE);
+      // while ( fIt->more() && FF1[1].IsNull() )
+      // {
+      //   const TopoDS_Face *F = (const TopoDS_Face*) fIt->next();
+      //   if ( helper.IsSubShape( *F, data._solid))
+      //     FF1[ FF1[0].IsNull() ? 0 : 1 ] = *F;
+      // }
+      // fIt = helper.GetAncestors(E2, *_mesh, TopAbs_FACE);
+      // while ( fIt->more() && FF2[1].IsNull())
+      // {
+      //   const TopoDS_Face *F = (const TopoDS_Face*) fIt->next();
+      //   if ( helper.IsSubShape( *F, data._solid))
+      //     FF2[ FF2[0].IsNull() ? 0 : 1 ] = *F;
+      // }
+      // // exclude a FACE common to E1 and E2 (put it to FFn[1] )
+      // if ( FF1[0].IsSame( FF2[0]) || FF1[0].IsSame( FF2[1]))
+      //   std::swap( FF1[0], FF1[1] );
+      // if ( FF2[0].IsSame( FF1[0]) )
+      //   std::swap( FF2[0], FF2[1] );
+      // if ( FF1[0].IsNull() || FF2[0].IsNull() )
+      //   continue;
+
+      // get a new normal for edge1
+      //bool ok;
+      gp_Vec dir1 = edge1->_normal, dir2 = edge2->_normal;
+      // if ( edge1->_cosin < 0 )
+      //   dir1 = getFaceDir( FF1[0], E1, edge1->_nodes[0], helper, ok ).Normalized();
+      // if ( edge2->_cosin < 0 )
+      //   dir2 = getFaceDir( FF2[0], E2, edge2->_nodes[0], helper, ok ).Normalized();
+
+      double cos1 = Abs( edge1->_cosin ), cos2 = Abs( edge2->_cosin );
+      double wgt1 = ( cos1 + 0.001 ) / ( cos1 + cos2 + 0.002 );
+      double wgt2 = ( cos2 + 0.001 ) / ( cos1 + cos2 + 0.002 );
+      newEdge._normal = ( wgt1 * dir1 + wgt2 * dir2 ).XYZ();
+      newEdge._normal.Normalize();
+
+      // cout << edge1->_nodes[0]->GetID() << " "
+      //      << edge2->_nodes[0]->GetID() << " NORM: "
+      //      << newEdge._normal.X() << ", " << newEdge._normal.Y() << ", " << newEdge._normal.Z() << endl;
+
+      // get new cosin
+      if ( cos1 < theMinSmoothCosin )
+      {
+        newEdge._cosin = edge2->_cosin;
+      }
+      else if ( cos2 > theMinSmoothCosin ) // both cos1 and cos2 > theMinSmoothCosin
+      {
+        // gp_Vec dirInFace;
+        // if ( edge1->_cosin < 0 )
+        //   dirInFace = dir1;
+        // else
+        //   dirInFace = getFaceDir( FF1[0], E1, edge1->_nodes[0], helper, ok );
+        // double angle = dirInFace.Angle( edge1->_normal ); // [0,PI]
+        // edge1->SetCosin( Cos( angle ));
+        //newEdge._cosin = 0; // ???????????
+        newEdge._cosin = ( wgt1 * cos1 + wgt2 * cos2 ) * edge1->_cosin / cos1;
+      }
+      else
+      {
+        newEdge._cosin = edge1->_cosin;
+      }
+
+      // find shapes that need smoothing due to change of _normal
+      if ( edge1->_cosin  < theMinSmoothCosin &&
+           newEdge._cosin > theMinSmoothCosin )
+      {
+        if ( edge1->_sWOL.IsNull() )
+        {
+          SMDS_ElemIteratorPtr fIt = edge1->_nodes[0]->GetInverseElementIterator(SMDSAbs_Face);
+          while ( fIt->more() )
+            shapesToSmooth.insert( fIt->next()->getshapeId() );
+          //limitStepSize( data, fIt->next(), edge1->_cosin ); // too late
+        }
+        else // edge1 inflates along a FACE
+        {
+          TopoDS_Shape V = helper.GetSubShapeByNode( edge1->_nodes[0], getMeshDS() );
+          PShapeIteratorPtr eIt = helper.GetAncestors( V, *_mesh, TopAbs_EDGE );
+          while ( const TopoDS_Shape* E = eIt->next() )
+          {
+            if ( !helper.IsSubShape( *E, /*FACE=*/edge1->_sWOL ))
+              continue;
+            gp_Vec edgeDir = getEdgeDir( TopoDS::Edge( *E ), TopoDS::Vertex( V ));
+            double   angle = edgeDir.Angle( newEdge._normal ); // [0,PI]
+            if ( angle < M_PI / 2 )
+              shapesToSmooth.insert( getMeshDS()->ShapeToIndex( *E ));
+          }
+        }
+      }
+    }
+
+    data.AddShapesToSmooth( shapesToSmooth );
+
+    // Update data of edges depending on a new _normal
+
+    for ( size_t iE = 0; iE < edge2newEdge.size(); ++iE )
+    {
+      _LayerEdge*   edge1 = edge2newEdge[ iE ].first;
+      _LayerEdge& newEdge = edge2newEdge[ iE ].second;
+      if ( !edge1 ) continue;
+
+      edge1->_normal = newEdge._normal;
+      edge1->SetCosin( newEdge._cosin );
+      edge1->InvalidateStep( 1 );
+      edge1->_len = 0;
+      edge1->SetNewLength( data._stepSize, helper );
+      if ( edge1->IsOnEdge() )
+      {
+        const SMDS_MeshNode * n1 = edge1->_2neibors->srcNode(0);
+        const SMDS_MeshNode * n2 = edge1->_2neibors->srcNode(1);
+        edge1->SetDataByNeighbors( n1, n2, helper );
+      }
+
+      // Update normals and other dependent data of not intersecting _LayerEdge's
+      // neighboring the intersecting ones
+
+      if ( !edge1->_2neibors )
+        continue;
+      for ( int j = 0; j < 2; ++j ) // loop on 2 neighbors
+      {
+        _LayerEdge* neighbor = edge1->_2neibors->_edges[j];
+        if ( edge2CloseEdge.count ( neighbor ))
+          continue; // j-th neighbor is also intersected
+        _LayerEdge* prevEdge = edge1;
+        const int nbSteps = 10;
+        for ( int step = nbSteps; step; --step ) // step from edge1 in j-th direction
+        {
+          if ( !neighbor->_2neibors )
+            break; // neighbor is on VERTEX
+          int iNext = 0;
+          _LayerEdge* nextEdge = neighbor->_2neibors->_edges[iNext];
+          if ( nextEdge == prevEdge )
+            nextEdge = neighbor->_2neibors->_edges[ ++iNext ];
+          double r = double(step-1)/nbSteps;
+          if ( !nextEdge->_2neibors )
+            r = 0.5;
+
+          gp_XYZ newNorm = prevEdge->_normal * r + nextEdge->_normal * (1-r);
+          newNorm.Normalize();
+
+          neighbor->_normal = newNorm;
+          neighbor->SetCosin( prevEdge->_cosin * r + nextEdge->_cosin * (1-r) );
+          neighbor->SetDataByNeighbors( prevEdge->_nodes[0], nextEdge->_nodes[0], helper );
+
+          neighbor->InvalidateStep( 1 );
+          neighbor->_len = 0;
+          neighbor->SetNewLength( data._stepSize, helper );
+
+          // goto the next neighbor
+          prevEdge = neighbor;
+          neighbor = nextEdge;
+        }
+      }
+    }
+    dumpFunctionEnd();
+  }
+  // 2) Check absence of intersections
+  // TODO?
+
+  for ( size_t i = 0 ; i < tmpFaces.size(); ++i )
+    delete tmpFaces[i];
+
+  return true;
+}
+
+//================================================================================
+/*!
+ * \brief Modify normals of _LayerEdge's on _ConvexFace's
+ */
+//================================================================================
+
+bool _ViscousBuilder::updateNormalsOfConvexFaces( _SolidData&         data,
+                                                  SMESH_MesherHelper& helper,
+                                                  int                 stepNb )
+{
+  SMESHDS_Mesh* meshDS = helper.GetMeshDS();
+  bool isOK;
+
+  map< TGeomID, _ConvexFace >::iterator id2face = data._convexFaces.begin();
+  for ( ; id2face != data._convexFaces.end(); ++id2face )
+  {
+    _ConvexFace & convFace = (*id2face).second;
+    if ( convFace._normalsFixed )
+      continue; // already fixed
+    if ( convFace.CheckPrisms() )
+      continue; // nothing to fix
+
+    convFace._normalsFixed = true;
+
+    BRepAdaptor_Surface surface ( convFace._face, false );
+    BRepLProp_SLProps   surfProp( surface, 2, 1e-6 );
+
+    // check if the convex FACE is of spherical shape
+
+    Bnd_B3d centersBox; // bbox of centers of curvature of _LayerEdge's on VERTEXes
+    Bnd_B3d nodesBox;
+    gp_Pnt  center;
+    int     iBeg, iEnd;
+
+    map< TGeomID, int >::iterator id2end = convFace._subIdToEdgeEnd.begin();
+    for ( ; id2end != convFace._subIdToEdgeEnd.end(); ++id2end )
+    {
+      data.GetEdgesOnShape( id2end->second, iBeg, iEnd );
+
+      if ( meshDS->IndexToShape( id2end->first ).ShapeType() == TopAbs_VERTEX )
+      {
+        _LayerEdge* ledge = data._edges[ iBeg ];
+        if ( convFace.GetCenterOfCurvature( ledge, surfProp, helper, center ))
+          centersBox.Add( center );
+      }
+      for ( ; iBeg < iEnd; ++iBeg )
+        nodesBox.Add( SMESH_TNodeXYZ( data._edges[ iBeg ]->_nodes[0] ));
+    }
+    if ( centersBox.IsVoid() )
     {
-      _LayerEdge* edge1       = e2ee->first;
-      _LayerEdge* edge2       = 0;
-      set< _LayerEdge*, _LayerEdgeCmp >& ee  = e2ee->second;
+      debugMsg( "Error: centersBox.IsVoid()" );
+      return false;
+    }
+    const bool isSpherical =
+      ( centersBox.SquareExtent() < 1e-6 * nodesBox.SquareExtent() );
+
+    int nbEdges = helper.Count( convFace._face, TopAbs_EDGE, /*ignoreSame=*/false );
+    vector < _CentralCurveOnEdge > centerCurves( nbEdges );
+
+    if ( isSpherical )
+    {
+      // set _LayerEdge::_normal as average of all normals
+
+      // WARNING: different density of nodes on EDGEs is not taken into account that
+      // can lead to an improper new normal
+
+      gp_XYZ avgNormal( 0,0,0 );
+      nbEdges = 0;
+      id2end = convFace._subIdToEdgeEnd.begin();
+      for ( ; id2end != convFace._subIdToEdgeEnd.end(); ++id2end )
+      {
+        data.GetEdgesOnShape( id2end->second, iBeg, iEnd );
+        // set data of _CentralCurveOnEdge
+        const TopoDS_Shape& S = meshDS->IndexToShape( id2end->first );
+        if ( S.ShapeType() == TopAbs_EDGE )
+        {
+          _CentralCurveOnEdge& ceCurve = centerCurves[ nbEdges++ ];
+          ceCurve.SetShapes( TopoDS::Edge(S), convFace, data, helper );
+          if ( !data._edges[ iBeg ]->_sWOL.IsNull() )
+            ceCurve._adjFace.Nullify();
+          else
+            ceCurve._ledges.insert( ceCurve._ledges.end(),
+                                    &data._edges[ iBeg ], &data._edges[ iEnd ]);
+        }
+        // summarize normals
+        for ( ; iBeg < iEnd; ++iBeg )
+          avgNormal += data._edges[ iBeg ]->_normal;
+      }
+      double normSize = avgNormal.SquareModulus();
+      if ( normSize < 1e-200 )
+      {
+        debugMsg( "updateNormalsOfConvexFaces(): zero avgNormal" );
+        return false;
+      }
+      avgNormal /= Sqrt( normSize );
+
+      // compute new _LayerEdge::_cosin on EDGEs
+      double avgCosin = 0;
+      int     nbCosin = 0;
+      gp_Vec inFaceDir;
+      for ( size_t iE = 0; iE < centerCurves.size(); ++iE )
+      {
+        _CentralCurveOnEdge& ceCurve = centerCurves[ iE ];
+        if ( ceCurve._adjFace.IsNull() )
+          continue;
+        for ( size_t iLE = 0; iLE < ceCurve._ledges.size(); ++iLE )
+        {
+          const SMDS_MeshNode* node = ceCurve._ledges[ iLE ]->_nodes[0];
+          inFaceDir = getFaceDir( ceCurve._adjFace, ceCurve._edge, node, helper, isOK );
+          if ( isOK )
+          {
+            double angle = inFaceDir.Angle( avgNormal ); // [0,PI]
+            ceCurve._ledges[ iLE ]->_cosin = Cos( angle );
+            avgCosin += ceCurve._ledges[ iLE ]->_cosin;
+            nbCosin++;
+          }
+        }
+      }
+      if ( nbCosin > 0 )
+        avgCosin /= nbCosin;
+
+      // set _LayerEdge::_normal = avgNormal
+      id2end = convFace._subIdToEdgeEnd.begin();
+      for ( ; id2end != convFace._subIdToEdgeEnd.end(); ++id2end )
+      {
+        data.GetEdgesOnShape( id2end->second, iBeg, iEnd );
+        const TopoDS_Shape& S = meshDS->IndexToShape( id2end->first );
+        if ( S.ShapeType() != TopAbs_EDGE )
+          for ( int i = iBeg; i < iEnd; ++i )
+            data._edges[ i ]->_cosin = avgCosin;
+
+        for ( ; iBeg < iEnd; ++iBeg )
+          data._edges[ iBeg ]->_normal = avgNormal;
+      }
+    }
+    else // if ( isSpherical )
+    {
+      // We suppose that centers of curvature at all points of the FACE
+      // lie on some curve, let's call it "central curve". For all _LayerEdge's
+      // having a common center of curvature we define the same new normal
+      // as a sum of normals of _LayerEdge's on EDGEs among them.
+
+      // get all centers of curvature for each EDGE
+
+      helper.SetSubShape( convFace._face );
+      _LayerEdge* vertexLEdges[2], **edgeLEdge, **edgeLEdgeEnd;
+
+      TopExp_Explorer edgeExp( convFace._face, TopAbs_EDGE );
+      for ( int iE = 0; edgeExp.More(); edgeExp.Next(), ++iE )
+      {
+        const TopoDS_Edge& edge = TopoDS::Edge( edgeExp.Current() );
+
+        // set adjacent FACE
+        centerCurves[ iE ].SetShapes( edge, convFace, data, helper );
+
+        // get _LayerEdge's of the EDGE
+        TGeomID edgeID = meshDS->ShapeToIndex( edge );
+        id2end = convFace._subIdToEdgeEnd.find( edgeID );
+        if ( id2end == convFace._subIdToEdgeEnd.end() )
+        {
+          // no _LayerEdge's on EDGE, use _LayerEdge's on VERTEXes
+          for ( int iV = 0; iV < 2; ++iV )
+          {
+            TopoDS_Vertex v = helper.IthVertex( iV, edge );
+            TGeomID     vID = meshDS->ShapeToIndex( v );
+            int  end = convFace._subIdToEdgeEnd[ vID ];
+            int iBeg = end > 0 ? data._endEdgeOnShape[ end-1 ] : 0;
+            vertexLEdges[ iV ] = data._edges[ iBeg ];
+          }
+          edgeLEdge    = &vertexLEdges[0];
+          edgeLEdgeEnd = edgeLEdge + 2;
+
+          centerCurves[ iE ]._adjFace.Nullify();
+        }
+        else
+        {
+          data.GetEdgesOnShape( id2end->second, iBeg, iEnd );
+          if ( id2end->second >= data._nbShapesToSmooth )
+            data.SortOnEdge( edge, iBeg, iEnd, helper );
+          edgeLEdge    = &data._edges[ iBeg ];
+          edgeLEdgeEnd = edgeLEdge + iEnd - iBeg;
+          vertexLEdges[0] = data._edges[ iBeg   ]->_2neibors->_edges[0];
+          vertexLEdges[1] = data._edges[ iEnd-1 ]->_2neibors->_edges[1];
+
+          if ( ! data._edges[ iBeg ]->_sWOL.IsNull() )
+            centerCurves[ iE ]._adjFace.Nullify();
+        }
+
+        // Get curvature centers
+
+        centersBox.Clear();
+
+        if ( edgeLEdge[0]->IsOnEdge() &&
+             convFace.GetCenterOfCurvature( vertexLEdges[0], surfProp, helper, center ))
+        { // 1st VERTEX
+          centerCurves[ iE ].Append( center, vertexLEdges[0] );
+          centersBox.Add( center );
+        }
+        for ( ; edgeLEdge < edgeLEdgeEnd; ++edgeLEdge )
+          if ( convFace.GetCenterOfCurvature( *edgeLEdge, surfProp, helper, center ))
+          { // EDGE or VERTEXes
+            centerCurves[ iE ].Append( center, *edgeLEdge );
+            centersBox.Add( center );
+          }
+        if ( edgeLEdge[-1]->IsOnEdge() &&
+             convFace.GetCenterOfCurvature( vertexLEdges[1], surfProp, helper, center ))
+        { // 2nd VERTEX
+          centerCurves[ iE ].Append( center, vertexLEdges[1] );
+          centersBox.Add( center );
+        }
+        centerCurves[ iE ]._isDegenerated =
+          ( centersBox.IsVoid() || centersBox.SquareExtent() < 1e-6 * nodesBox.SquareExtent() );
+
+      } // loop on EDGES of convFace._face to set up data of centerCurves
+
+      // Compute new normals for _LayerEdge's on EDGEs
+
+      double avgCosin = 0;
+      int     nbCosin = 0;
+      gp_Vec inFaceDir;
+      for ( size_t iE1 = 0; iE1 < centerCurves.size(); ++iE1 )
+      {
+        _CentralCurveOnEdge& ceCurve = centerCurves[ iE1 ];
+        if ( ceCurve._isDegenerated )
+          continue;
+        const vector< gp_Pnt >& centers = ceCurve._curvaCenters;
+        vector< gp_XYZ > &   newNormals = ceCurve._normals;
+        for ( size_t iC1 = 0; iC1 < centers.size(); ++iC1 )
+        {
+          isOK = false;
+          for ( size_t iE2 = 0; iE2 < centerCurves.size() && !isOK; ++iE2 )
+          {
+            if ( iE1 != iE2 )
+              isOK = centerCurves[ iE2 ].FindNewNormal( centers[ iC1 ], newNormals[ iC1 ]);
+          }
+          if ( isOK && !ceCurve._adjFace.IsNull() )
+          {
+            // compute new _LayerEdge::_cosin
+            const SMDS_MeshNode* node = ceCurve._ledges[ iC1 ]->_nodes[0];
+            inFaceDir = getFaceDir( ceCurve._adjFace, ceCurve._edge, node, helper, isOK );
+            if ( isOK )
+            {
+              double angle = inFaceDir.Angle( newNormals[ iC1 ] ); // [0,PI]
+              ceCurve._ledges[ iC1 ]->_cosin = Cos( angle );
+              avgCosin += ceCurve._ledges[ iC1 ]->_cosin;
+              nbCosin++;
+            }
+          }
+        }
+      }
+      // set new normals to _LayerEdge's of NOT degenerated central curves
+      for ( size_t iE = 0; iE < centerCurves.size(); ++iE )
+      {
+        if ( centerCurves[ iE ]._isDegenerated )
+          continue;
+        for ( size_t iLE = 0; iLE < centerCurves[ iE ]._ledges.size(); ++iLE )
+          centerCurves[ iE ]._ledges[ iLE ]->_normal = centerCurves[ iE ]._normals[ iLE ];
+      }
+      // set new normals to _LayerEdge's of     degenerated central curves
+      for ( size_t iE = 0; iE < centerCurves.size(); ++iE )
+      {
+        if ( !centerCurves[ iE ]._isDegenerated ||
+             centerCurves[ iE ]._ledges.size() < 3 )
+          continue;
+        // new normal is an average of new normals at VERTEXes that
+        // was computed on non-degenerated _CentralCurveOnEdge's
+        gp_XYZ newNorm = ( centerCurves[ iE ]._ledges.front()->_normal +
+                           centerCurves[ iE ]._ledges.back ()->_normal );
+        double sz = newNorm.Modulus();
+        if ( sz < 1e-200 )
+          continue;
+        newNorm /= sz;
+        double newCosin = ( 0.5 * centerCurves[ iE ]._ledges.front()->_cosin +
+                            0.5 * centerCurves[ iE ]._ledges.back ()->_cosin );
+        for ( size_t iLE = 1, nb = centerCurves[ iE ]._ledges.size() - 1; iLE < nb; ++iLE )
+        {
+          centerCurves[ iE ]._ledges[ iLE ]->_normal = newNorm;
+          centerCurves[ iE ]._ledges[ iLE ]->_cosin  = newCosin;
+        }
+      }
+
+      // Find new normals for _LayerEdge's based on FACE
+
+      if ( nbCosin > 0 )
+        avgCosin /= nbCosin;
+      const TGeomID faceID = meshDS->ShapeToIndex( convFace._face );
+      map< TGeomID, int >::iterator id2end = convFace._subIdToEdgeEnd.find( faceID );
+      if ( id2end != convFace._subIdToEdgeEnd.end() )
+      {
+        int iE = 0;
+        gp_XYZ newNorm;
+        data.GetEdgesOnShape( id2end->second, iBeg, iEnd );
+        for ( ; iBeg < iEnd; ++iBeg )
+        {
+          _LayerEdge* ledge = data._edges[ iBeg ];
+          if ( !convFace.GetCenterOfCurvature( ledge, surfProp, helper, center ))
+            continue;
+          for ( size_t i = 0; i < centerCurves.size(); ++i, ++iE )
+          {
+            iE = iE % centerCurves.size();
+            if ( centerCurves[ iE ]._isDegenerated )
+              continue;
+            newNorm.SetCoord( 0,0,0 );
+            if ( centerCurves[ iE ].FindNewNormal( center, newNorm ))
+            {
+              ledge->_normal = newNorm;
+              ledge->_cosin  = avgCosin;
+              break;
+            }
+          }
+        }
+      }
+
+    } // not a quasi-spherical FACE
+
+    // Update _LayerEdge's data according to a new normal
+
+    dumpFunction(SMESH_Comment("updateNormalsOfConvexFaces")<<data._index
+                 <<"_F"<<meshDS->ShapeToIndex( convFace._face ));
+
+    id2end = convFace._subIdToEdgeEnd.begin();
+    for ( ; id2end != convFace._subIdToEdgeEnd.end(); ++id2end )
+    {
+      data.GetEdgesOnShape( id2end->second, iBeg, iEnd );
+      for ( ; iBeg < iEnd; ++iBeg )
+      {
+        _LayerEdge* & ledge = data._edges[ iBeg ];
+        double len = ledge->_len;
+        ledge->InvalidateStep( stepNb + 1, /*restoreLength=*/true );
+        ledge->SetCosin( ledge->_cosin );
+        ledge->SetNewLength( len, helper );
+      }
+
+    } // loop on sub-shapes of convFace._face
+
+    // Find FACEs adjacent to convFace._face that got necessity to smooth
+    // as a result of normals modification
+
+    set< TGeomID > adjFacesToSmooth;
+    for ( size_t iE = 0; iE < centerCurves.size(); ++iE )
+    {
+      if ( centerCurves[ iE ]._adjFace.IsNull() ||
+           centerCurves[ iE ]._adjFaceToSmooth )
+        continue;
+      for ( size_t iLE = 0; iLE < centerCurves[ iE ]._ledges.size(); ++iLE )
+      {
+        if ( centerCurves[ iE ]._ledges[ iLE ]->_cosin > theMinSmoothCosin )
+        {
+          adjFacesToSmooth.insert( meshDS->ShapeToIndex( centerCurves[ iE ]._adjFace ));
+          break;
+        }
+      }
+    }
+    data.AddShapesToSmooth( adjFacesToSmooth );
+
+    dumpFunctionEnd();
+
+
+  } // loop on data._convexFaces
+
+  return true;
+}
+
+//================================================================================
+/*!
+ * \brief Finds a center of curvature of a surface at a _LayerEdge
+ */
+//================================================================================
 
-      // find EDGEs the edges reside
-      TopoDS_Edge E1, E2;
-      TopoDS_Shape S = helper.GetSubShapeByNode( edge1->_nodes[0], getMeshDS() );
-      if ( S.ShapeType() != TopAbs_EDGE )
-        continue; // TODO: find EDGE by VERTEX
-      E1 = TopoDS::Edge( S );
-      set< _LayerEdge*, _LayerEdgeCmp >::iterator eIt = ee.begin();
-      while ( E2.IsNull() && eIt != ee.end())
-      {
-        _LayerEdge* e2 = *eIt++;
-        TopoDS_Shape S = helper.GetSubShapeByNode( e2->_nodes[0], getMeshDS() );
-        if ( S.ShapeType() == TopAbs_EDGE )
-          E2 = TopoDS::Edge( S ), edge2 = e2;
-      }
-      if ( E2.IsNull() ) continue; // TODO: find EDGE by VERTEX
+bool _ConvexFace::GetCenterOfCurvature( _LayerEdge*         ledge,
+                                        BRepLProp_SLProps&  surfProp,
+                                        SMESH_MesherHelper& helper,
+                                        gp_Pnt &            center ) const
+{
+  gp_XY uv = helper.GetNodeUV( _face, ledge->_nodes[0] );
+  surfProp.SetParameters( uv.X(), uv.Y() );
+  if ( !surfProp.IsCurvatureDefined() )
+    return false;
 
-      // find 3 FACEs sharing 2 EDGEs
+  const double oriFactor = ( _face.Orientation() == TopAbs_REVERSED ? +1. : -1. );
+  double surfCurvatureMax = surfProp.MaxCurvature() * oriFactor;
+  double surfCurvatureMin = surfProp.MinCurvature() * oriFactor;
+  if ( surfCurvatureMin > surfCurvatureMax )
+    center = surfProp.Value().Translated( surfProp.Normal().XYZ() / surfCurvatureMin * oriFactor );
+  else
+    center = surfProp.Value().Translated( surfProp.Normal().XYZ() / surfCurvatureMax * oriFactor );
 
-      TopoDS_Face FF1[2], FF2[2];
-      PShapeIteratorPtr fIt = helper.GetAncestors(E1, *_mesh, TopAbs_FACE);
-      while ( fIt->more() && FF1[1].IsNull())
-      {
-        const TopoDS_Face *F = (const TopoDS_Face*) fIt->next();
-        if ( helper.IsSubShape( *F, data._solid))
-          FF1[ FF1[0].IsNull() ? 0 : 1 ] = *F;
-      }
-      fIt = helper.GetAncestors(E2, *_mesh, TopAbs_FACE);
-      while ( fIt->more() && FF2[1].IsNull())
-      {
-        const TopoDS_Face *F = (const TopoDS_Face*) fIt->next();
-        if ( helper.IsSubShape( *F, data._solid))
-          FF2[ FF2[0].IsNull() ? 0 : 1 ] = *F;
-      }
-      // exclude a FACE common to E1 and E2 (put it at [1] in FF* )
-      if ( FF1[0].IsSame( FF2[0]) || FF1[0].IsSame( FF2[1]))
-        std::swap( FF1[0], FF1[1] );
-      if ( FF2[0].IsSame( FF1[0]) )
-        std::swap( FF2[0], FF2[1] );
-      if ( FF1[0].IsNull() || FF2[0].IsNull() )
-        continue;
+  return true;
+}
 
-      // get a new normal for edge1
-      bool ok;
-      gp_Vec dir1 = edge1->_normal, dir2 = edge2->_normal;
-      if ( edge1->_cosin < 0 )
-        dir1 = getFaceDir( FF1[0], E1, edge1->_nodes[0], helper, ok ).Normalized();
-      if ( edge2->_cosin < 0 )
-        dir2 = getFaceDir( FF2[0], E2, edge2->_nodes[0], helper, ok ).Normalized();
-      // gp_Vec dir1 = getFaceDir( FF1[0], E1, edge1->_nodes[0], helper, ok );
-      // gp_Vec dir2 = getFaceDir( FF2[0], E2, edge2->_nodes[0], helper, ok2 );
-      // double wgt1 = ( edge1->_cosin + 1 ) / ( edge1->_cosin + edge2->_cosin + 2 );
-      // double wgt2 = ( edge2->_cosin + 1 ) / ( edge1->_cosin + edge2->_cosin + 2 );
-      // gp_Vec newNorm = wgt1 * dir1 + wgt2 * dir2;
-      // newNorm.Normalize();
-
-      double wgt1 = ( edge1->_cosin + 1 ) / ( edge1->_cosin + edge2->_cosin + 2 );
-      double wgt2 = ( edge2->_cosin + 1 ) / ( edge1->_cosin + edge2->_cosin + 2 );
-      gp_Vec newNorm = wgt1 * dir1 + wgt2 * dir2;
-      newNorm.Normalize();
-
-      edge1->_normal = newNorm.XYZ();
-
-      // update data of edge1 depending on _normal
-      const SMDS_MeshNode *n1, *n2;
-      n1 = edge1->_2neibors->_edges[0]->_nodes[0];
-      n2 = edge1->_2neibors->_edges[1]->_nodes[0];
-      //if ( !findNeiborsOnEdge( edge1, n1, n2, data ))
-      //  continue;
-      edge1->SetDataByNeighbors( n1, n2, helper );
-      gp_Vec dirInFace;
-      if ( edge1->_cosin < 0 )
-        dirInFace = dir1;
-      else
-        dirInFace = getFaceDir( FF1[0], E1, edge1->_nodes[0], helper, ok );
-      double angle = dir1.Angle( edge1->_normal ); // [0,PI]
-      edge1->SetCosin( cos( angle ));
+//================================================================================
+/*!
+ * \brief Check that prisms are not distorted
+ */
+//================================================================================
 
-      // limit data._stepSize
-      if ( edge1->_cosin > 0.1 )
+bool _ConvexFace::CheckPrisms() const
+{
+  for ( size_t i = 0; i < _simplexTestEdges.size(); ++i )
+  {
+    const _LayerEdge* edge = _simplexTestEdges[i];
+    SMESH_TNodeXYZ tgtXYZ( edge->_nodes.back() );
+    for ( size_t j = 0; j < edge->_simplices.size(); ++j )
+      if ( !edge->_simplices[j].IsForward( edge->_nodes[0], &tgtXYZ ))
       {
-        SMDS_ElemIteratorPtr fIt = edge1->_nodes[0]->GetInverseElementIterator(SMDSAbs_Face);
-        while ( fIt->more() )
-          limitStepSize( data, fIt->next(), edge1->_cosin );
+        debugMsg( "Bad simplex of _simplexTestEdges ("
+                  << " "<< edge->_nodes[0]->GetID()<< " "<< tgtXYZ._node->GetID()
+                  << " "<< edge->_simplices[j]._nPrev->GetID()
+                  << " "<< edge->_simplices[j]._nNext->GetID() << " )" );
+        return false;
       }
-      // set new XYZ of target node
-      edge1->InvalidateStep( 1 );
-      edge1->_len = 0;
-      edge1->SetNewLength( data._stepSize, helper );
-    }
+  }
+  return true;
+}
 
-    // Update normals and other dependent data of not intersecting _LayerEdge's
-    // neighboring the intersecting ones
+//================================================================================
+/*!
+ * \brief Try to compute a new normal by interpolating normals of _LayerEdge's
+ *        stored in this _CentralCurveOnEdge.
+ *  \param [in] center - curvature center of a point of another _CentralCurveOnEdge.
+ *  \param [in,out] newNormal - current normal at this point, to be redefined
+ *  \return bool - true if succeeded.
+ */
+//================================================================================
 
-    for ( e2ee = edge2CloseEdge.begin(); e2ee != edge2CloseEdge.end(); ++e2ee )
-    {
-      _LayerEdge* edge1 = e2ee->first;
-      if ( !edge1->_2neibors )
-        continue;
-      for ( int j = 0; j < 2; ++j ) // loop on 2 neighbors
-      {
-        _LayerEdge* neighbor = edge1->_2neibors->_edges[j];
-        if ( edge2CloseEdge.count ( neighbor ))
-          continue; // j-th neighbor is also intersected
-        _LayerEdge* prevEdge = edge1;
-        const int nbSteps = 6;
-        for ( int step = nbSteps; step; --step ) // step from edge1 in j-th direction
-        {
-          if ( !neighbor->_2neibors )
-            break; // neighbor is on VERTEX
-          int iNext = 0;
-          _LayerEdge* nextEdge = neighbor->_2neibors->_edges[iNext];
-          if ( nextEdge == prevEdge )
-            nextEdge = neighbor->_2neibors->_edges[ ++iNext ];
-//           const double&  wgtPrev = neighbor->_2neibors->_wgt[1-iNext];
-//           const double&  wgtNext = neighbor->_2neibors->_wgt[iNext];
-          double r = double(step-1)/nbSteps;
-          if ( !nextEdge->_2neibors )
-            r = 0.5;
+bool _CentralCurveOnEdge::FindNewNormal( const gp_Pnt& center, gp_XYZ& newNormal )
+{
+  if ( this->_isDegenerated )
+    return false;
 
-          gp_XYZ newNorm = prevEdge->_normal * r + nextEdge->_normal * (1-r);
-          newNorm.Normalize();
+  // find two centers the given one lies between
 
-          neighbor->_normal = newNorm;
-          neighbor->SetCosin( prevEdge->_cosin * r + nextEdge->_cosin * (1-r) );
-          neighbor->SetDataByNeighbors( prevEdge->_nodes[0], nextEdge->_nodes[0], helper );
+  for ( size_t i = 0, nb = _curvaCenters.size()-1;  i < nb;  ++i )
+  {
+    double sl2 = 1.001 * _segLength2[ i ];
 
-          neighbor->InvalidateStep( 1 );
-          neighbor->_len = 0;
-          neighbor->SetNewLength( data._stepSize, helper );
+    double d1 = center.SquareDistance( _curvaCenters[ i ]);
+    if ( d1 > sl2 )
+      continue;
+    
+    double d2 = center.SquareDistance( _curvaCenters[ i+1 ]);
+    if ( d2 > sl2 || d2 + d1 < 1e-100 )
+      continue;
 
-          // goto the next neighbor
-          prevEdge = neighbor;
-          neighbor = nextEdge;
-        }
-      }
-    }
-    dumpFunctionEnd();
+    d1 = Sqrt( d1 );
+    d2 = Sqrt( d2 );
+    double r = d1 / ( d1 + d2 );
+    gp_XYZ norm = (( 1. - r ) * _ledges[ i   ]->_normal +
+                   (      r ) * _ledges[ i+1 ]->_normal );
+    norm.Normalize();
+
+    newNormal += norm;
+    double sz = newNormal.Modulus();
+    if ( sz < 1e-200 )
+      break;
+    newNormal /= sz;
+    return true;
   }
-  // 2) Check absence of intersections
-  // TODO?
+  return false;
+}
 
-  for ( size_t i = 0 ; i < tmpFaces.size(); ++i )
-    delete tmpFaces[i];
+//================================================================================
+/*!
+ * \brief Set shape members
+ */
+//================================================================================
 
-  return true;
+void _CentralCurveOnEdge::SetShapes( const TopoDS_Edge&  edge,
+                                     const _ConvexFace&  convFace,
+                                     const _SolidData&   data,
+                                     SMESH_MesherHelper& helper)
+{
+  _edge = edge;
+
+  PShapeIteratorPtr fIt = helper.GetAncestors( edge, *helper.GetMesh(), TopAbs_FACE );
+  while ( const TopoDS_Shape* F = fIt->next())
+    if ( !convFace._face.IsSame( *F ))
+    {
+      _adjFace = TopoDS::Face( *F );
+      _adjFaceToSmooth = false;
+      // _adjFace already in a smoothing queue ?
+      size_t end;
+      TGeomID adjFaceID = helper.GetMeshDS()->ShapeToIndex( *F );
+      if ( data.GetShapeEdges( adjFaceID, end ))
+        _adjFaceToSmooth = ( end < data._nbShapesToSmooth );
+      break;
+    }
 }
 
 //================================================================================
@@ -3409,7 +4620,7 @@ bool _LayerEdge::FindIntersection( SMESH_ElementSearcher&   searcher,
   bool segmentIntersected = false;
   distance = Precision::Infinite();
   int iFace = -1; // intersected face
-  for ( size_t j = 0 ; j < suspectFaces.size() && !segmentIntersected; ++j )
+  for ( size_t j = 0 ; j < suspectFaces.size() /*&& !segmentIntersected*/; ++j )
   {
     const SMDS_MeshElement* face = suspectFaces[j];
     if ( face->GetNodeIndex( _nodes.back() ) >= 0 ||
@@ -3427,7 +4638,7 @@ bool _LayerEdge::FindIntersection( SMESH_ElementSearcher&   searcher,
     {
       const SMDS_MeshNode* tria[3];
       tria[0] = *nIt++;
-      tria[1] = *nIt++;;
+      tria[1] = *nIt++;
       for ( int n2 = 2; n2 < nbNodes && !intFound; ++n2 )
       {
         tria[2] = *nIt++;
@@ -3437,21 +4648,14 @@ bool _LayerEdge::FindIntersection( SMESH_ElementSearcher&   searcher,
     }
     if ( intFound )
     {
-      if ( dist < segLen*(1.01) && dist > -(_len-segLen) )
+      if ( dist < segLen*(1.01) && dist > -(_len*_lenFactor-segLen) )
         segmentIntersected = true;
       if ( distance > dist )
         distance = dist, iFace = j;
     }
   }
   if ( iFace != -1 && face ) *face = suspectFaces[iFace];
-//   if ( distance && iFace > -1 )
-//   {
-//     // distance is used to limit size of inflation step which depends on
-//     // whether the intersected face bears viscous layers or not
-//     bool faceHasVL = suspectFaces[iFace]->GetID() < 1;
-//     if ( faceHasVL )
-//       *distance /= 2;
-//   }
+
   if ( segmentIntersected )
   {
 #ifdef __myDEBUG
@@ -3526,6 +4730,31 @@ gp_Ax1 _LayerEdge::LastSegment(double& segLen) const
   return segDir;
 }
 
+//================================================================================
+/*!
+ * \brief Return the last position of the target node on a FACE. 
+ *  \param [in] F - the FACE this _LayerEdge is inflated along
+ *  \return gp_XY - result UV
+ */
+//================================================================================
+
+gp_XY _LayerEdge::LastUV( const TopoDS_Face& F ) const
+{
+  if ( F.IsSame( _sWOL )) // F is my FACE
+    return gp_XY( _pos.back().X(), _pos.back().Y() );
+
+  if ( _sWOL.IsNull() || _sWOL.ShapeType() != TopAbs_EDGE ) // wrong call
+    return gp_XY( 1e100, 1e100 );
+
+  // _sWOL is EDGE of F; _pos.back().X() is the last U on the EDGE
+  double f, l, u = _pos.back().X();
+  Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface( TopoDS::Edge(_sWOL), F, f,l);
+  if ( !C2d.IsNull() && f <= u && u <= l )
+    return C2d->Value( u ).XY();
+
+  return gp_XY( 1e100, 1e100 );
+}
+
 //================================================================================
 /*!
  * \brief Test intersection of the last segment with a given triangle
@@ -3553,9 +4782,9 @@ bool _LayerEdge::SegTriaInter( const gp_Ax1&        lastSegment,
   /* calculate distance from vert0 to ray origin */
   gp_XYZ tvec = orig - vert0;
 
-  if ( tvec * dir > EPSILON )
+  //if ( tvec * dir > EPSILON )
     // intersected face is at back side of the temporary face this _LayerEdge belongs to
-    return false;
+    //return false;
 
   gp_XYZ edge1 = vert1 - vert0;
   gp_XYZ edge2 = vert2 - vert0;
@@ -3567,52 +4796,29 @@ bool _LayerEdge::SegTriaInter( const gp_Ax1&        lastSegment,
   double det = edge1 * pvec;
 
   if (det > -EPSILON && det < EPSILON)
-    return 0;
+    return false;
   double inv_det = 1.0 / det;
 
   /* calculate U parameter and test bounds */
   double u = ( tvec * pvec ) * inv_det;
-  if (u < 0.0 || u > 1.0)
-    return 0;
+  //if (u < 0.0 || u > 1.0)
+  if (u < -EPSILON || u > 1.0 + EPSILON)
+    return false;
 
   /* prepare to test V parameter */
   gp_XYZ qvec = tvec ^ edge1;
 
   /* calculate V parameter and test bounds */
   double v = (dir * qvec) * inv_det;
-  if ( v < 0.0 || u + v > 1.0 )
-    return 0;
+  //if ( v < 0.0 || u + v > 1.0 )
+  if ( v < -EPSILON || u + v > 1.0 + EPSILON)
+    return false;
 
   /* calculate t, ray intersects triangle */
   t = (edge2 * qvec) * inv_det;
 
-  //   if (det < EPSILON)
-  //     return false;
-
-  //   /* calculate distance from vert0 to ray origin */
-  //   gp_XYZ tvec = orig - vert0;
-
-  //   /* calculate U parameter and test bounds */
-  //   double u = tvec * pvec;
-  //   if (u < 0.0 || u > det)
-//     return 0;
-
-//   /* prepare to test V parameter */
-//   gp_XYZ qvec = tvec ^ edge1;
-
-//   /* calculate V parameter and test bounds */
-//   double v = dir * qvec;
-//   if (v < 0.0 || u + v > det)
-//     return 0;
-
-//   /* calculate t, scale parameters, ray intersects triangle */
-//   double t = edge2 * qvec;
-//   double inv_det = 1.0 / det;
-//   t *= inv_det;
-//   //u *= inv_det;
-//   //v *= inv_det;
-
-  return true;
+  //return true;
+  return t > 0.;
 }
 
 //================================================================================
@@ -3632,9 +4838,9 @@ bool _LayerEdge::SmoothOnEdge(Handle(Geom_Surface)& surface,
   SMESH_TNodeXYZ oldPos( tgtNode );
   double dist01, distNewOld;
   
-  SMESH_TNodeXYZ p0( _2neibors->_nodes[0]);
-  SMESH_TNodeXYZ p1( _2neibors->_nodes[1]);
-  dist01 = p0.Distance( _2neibors->_nodes[1] );
+  SMESH_TNodeXYZ p0( _2neibors->tgtNode(0));
+  SMESH_TNodeXYZ p1( _2neibors->tgtNode(1));
+  dist01 = p0.Distance( _2neibors->tgtNode(1) );
 
   gp_Pnt newPos = p0 * _2neibors->_wgt[0] + p1 * _2neibors->_wgt[1];
   double lenDelta = 0;
@@ -3701,27 +4907,27 @@ bool _LayerEdge::Smooth(int& badNb)
     newPos += SMESH_TNodeXYZ( _simplices[i]._nPrev );
   newPos /= _simplices.size();
 
+  const gp_XYZ& curPos ( _pos.back() );
+  const gp_Pnt  prevPos( _pos[ _pos.size()-2 ]);
   if ( _curvature )
-    newPos += _normal * _curvature->lenDelta( _len );
-
-  gp_Pnt prevPos( _pos[ _pos.size()-2 ]);
-//   if ( _cosin < -0.1)
-//   {
-//     // Avoid decreasing length of edge on concave surface
-//     //gp_Vec oldMove( _pos[ _pos.size()-2 ], _pos.back() );
-//     gp_Vec newMove( prevPos, newPos );
-//     newPos = _pos.back() + newMove.XYZ();
-//   }
-//   else if ( _cosin > 0.3 )
-//   {
-//     // Avoid increasing length of edge too much
-
-//   }
+  {
+    double delta  = _curvature->lenDelta( _len );
+    if ( delta > 0 )
+      newPos += _normal * delta;
+    else
+    {
+      double segLen = _normal * ( newPos - prevPos.XYZ() );
+      if ( segLen + delta > 0 )
+        newPos += _normal * delta;
+    }
+    // double segLenChange = _normal * ( curPos - newPos );
+    // newPos += 0.5 * _normal * segLenChange;
+  }
+
   // count quality metrics (orientation) of tetras around _tgtNode
   int nbOkBefore = 0;
-  SMESH_TNodeXYZ tgtXYZ( _nodes.back() );
   for ( size_t i = 0; i < _simplices.size(); ++i )
-    nbOkBefore += _simplices[i].IsForward( _nodes[0], &tgtXYZ );
+    nbOkBefore += _simplices[i].IsForward( _nodes[0], &curPos );
 
   int nbOkAfter = 0;
   for ( size_t i = 0; i < _simplices.size(); ++i )
@@ -3755,7 +4961,7 @@ void _LayerEdge::SetNewLength( double len, SMESH_MesherHelper& helper )
 {
   if ( _len - len > -1e-6 )
   {
-    _pos.push_back( _pos.back() );
+    //_pos.push_back( _pos.back() );
     return;
   }
 
@@ -3774,17 +4980,23 @@ void _LayerEdge::SetNewLength( double len, SMESH_MesherHelper& helper )
       double u = Precision::Infinite(); // to force projection w/o distance check
       helper.CheckNodeU( TopoDS::Edge( _sWOL ), n, u, 1e-10, /*force=*/true, distXYZ );
       _pos.back().SetCoord( u, 0, 0 );
-      SMDS_EdgePosition* pos = static_cast<SMDS_EdgePosition*>( n->GetPosition() );
-      pos->SetUParameter( u );
+      if ( _nodes.size() > 1 )
+      {
+        SMDS_EdgePosition* pos = static_cast<SMDS_EdgePosition*>( n->GetPosition() );
+        pos->SetUParameter( u );
+      }
     }
     else //  TopAbs_FACE
     {
       gp_XY uv( Precision::Infinite(), 0 );
       helper.CheckNodeUV( TopoDS::Face( _sWOL ), n, uv, 1e-10, /*force=*/true, distXYZ );
       _pos.back().SetCoord( uv.X(), uv.Y(), 0 );
-      SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( n->GetPosition() );
-      pos->SetUParameter( uv.X() );
-      pos->SetVParameter( uv.Y() );
+      if ( _nodes.size() > 1 )
+      {
+        SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( n->GetPosition() );
+        pos->SetUParameter( uv.X() );
+        pos->SetVParameter( uv.Y() );
+      }
     }
     n->setXYZ( distXYZ[1], distXYZ[2], distXYZ[3]);
   }
@@ -3797,10 +5009,13 @@ void _LayerEdge::SetNewLength( double len, SMESH_MesherHelper& helper )
  */
 //================================================================================
 
-void _LayerEdge::InvalidateStep( int curStep )
+void _LayerEdge::InvalidateStep( int curStep, bool restoreLength )
 {
   if ( _pos.size() > curStep )
   {
+    if ( restoreLength )
+      _len -= ( _pos[ curStep-1 ] - _pos.back() ).Modulus();
+
     _pos.resize( curStep );
     gp_Pnt nXYZ = _pos.back();
     SMDS_MeshNode* n = const_cast< SMDS_MeshNode*>( _nodes.back() );
@@ -3854,10 +5069,22 @@ bool _ViscousBuilder::refine(_SolidData& data)
   TNode2Edge* n2eMap = 0;
   TNode2Edge::iterator n2e;
 
+  // Create intermediate nodes on each _LayerEdge
+
+  int iS = 0, iEnd = data._endEdgeOnShape[ iS ];
+
   for ( size_t i = 0; i < data._edges.size(); ++i )
   {
     _LayerEdge& edge = *data._edges[i];
 
+    if ( edge._nodes.size() < 2 )
+      continue; // on _noShrinkShapes
+
+    // get parameters of layers for the edge
+    if ( i == iEnd )
+      iEnd = data._endEdgeOnShape[ ++iS ];
+    const AverageHyp& hyp = data._hypOnShape[ iS ];
+
     // get accumulated length of segments
     vector< double > segLen( edge._pos.size() );
     segLen[0] = 0.0;
@@ -3868,7 +5095,7 @@ bool _ViscousBuilder::refine(_SolidData& data)
     const SMDS_MeshNode* tgtNode = edge._nodes.back();
     if ( edge._nodes.size() == 2 )
     {
-      edge._nodes.resize( data._hyp->GetNumberLayers() + 1, 0 );
+      edge._nodes.resize( hyp.GetNumberLayers() + 1, 0 );
       edge._nodes[1] = 0;
       edge._nodes.back() = tgtNode;
     }
@@ -3896,28 +5123,29 @@ bool _ViscousBuilder::refine(_SolidData& data)
       n2eMap = ( s2ne == data._s2neMap.end() ) ? 0 : n2eMap = s2ne->second;
       prevBaseId = baseShapeId;
     }
+    _LayerEdge* edgeOnSameNode = 0;
     if ( n2eMap && (( n2e = n2eMap->find( edge._nodes[0] )) != n2eMap->end() ))
     {
-      _LayerEdge*  foundEdge = n2e->second;
-      const gp_XYZ& foundPos = foundEdge->_pos.back();
-      SMDS_PositionPtr lastPos = tgtNode->GetPosition();
+      edgeOnSameNode = n2e->second;
+      const gp_XYZ& otherTgtPos = edgeOnSameNode->_pos.back();
+      SMDS_PositionPtr  lastPos = tgtNode->GetPosition();
       if ( isOnEdge )
       {
         SMDS_EdgePosition* epos = static_cast<SMDS_EdgePosition*>( lastPos );
-        epos->SetUParameter( foundPos.X() );
+        epos->SetUParameter( otherTgtPos.X() );
       }
       else
       {
         SMDS_FacePosition* fpos = static_cast<SMDS_FacePosition*>( lastPos );
-        fpos->SetUParameter( foundPos.X() );
-        fpos->SetVParameter( foundPos.Y() );
+        fpos->SetUParameter( otherTgtPos.X() );
+        fpos->SetVParameter( otherTgtPos.Y() );
       }
     }
     // calculate height of the first layer
     double h0;
     const double T = segLen.back(); //data._hyp.GetTotalThickness();
-    const double f = data._hyp->GetStretchFactor();
-    const int    N = data._hyp->GetNumberLayers();
+    const double f = hyp.GetStretchFactor();
+    const int    N = hyp.GetNumberLayers();
     const double fPowN = pow( f, N );
     if ( fPowN - 1 <= numeric_limits<double>::min() )
       h0 = T / N;
@@ -3942,7 +5170,7 @@ bool _ViscousBuilder::refine(_SolidData& data)
       double r = ( segLen[iSeg] - hSum ) / ( segLen[iSeg] - segLen[iPrevSeg] );
       gp_Pnt pos = r * edge._pos[iPrevSeg] + (1-r) * edge._pos[iSeg];
 
-      SMDS_MeshNode*& node = const_cast< SMDS_MeshNode*& >(edge._nodes[ iStep ]);
+      SMDS_MeshNode*& node = const_cast< SMDS_MeshNode*& >( edge._nodes[ iStep ]);
       if ( !edge._sWOL.IsNull() )
       {
         // compute XYZ by parameters <pos>
@@ -4000,8 +5228,20 @@ bool _ViscousBuilder::refine(_SolidData& data)
         }
         node->setXYZ( pos.X(), pos.Y(), pos.Z() );
       }
+    } // loop on edge._nodes
+
+    if ( !edge._sWOL.IsNull() ) // prepare for shrink()
+    {
+      if ( isOnEdge )
+        edge._pos.back().SetCoord( u, 0,0);
+      else
+        edge._pos.back().SetCoord( uv.X(), uv.Y() ,0);
+
+      if ( edgeOnSameNode )
+        edgeOnSameNode->_pos.back() = edge._pos.back();
     }
-  }
+
+  } // loop on data._edges to create nodes
 
   if ( !getMeshDS()->IsEmbeddedMode() )
     // Log node movement
@@ -4012,50 +5252,154 @@ bool _ViscousBuilder::refine(_SolidData& data)
       getMeshDS()->MoveNode( p._node, p.X(), p.Y(), p.Z() );
     }
 
-  // TODO: make quadratic prisms and polyhedrons(?)
+  // Create volumes
 
   helper.SetElementsOnShape(true);
 
+  vector< vector<const SMDS_MeshNode*>* > nnVec;
+  set< vector<const SMDS_MeshNode*>* >    nnSet;
+  set< int > degenEdgeInd;
+  vector<const SMDS_MeshElement*> degenVols;
+
   TopExp_Explorer exp( data._solid, TopAbs_FACE );
   for ( ; exp.More(); exp.Next() )
   {
-    if ( data._ignoreFaceIds.count( getMeshDS()->ShapeToIndex( exp.Current() )))
+    const TGeomID faceID = getMeshDS()->ShapeToIndex( exp.Current() );
+    if ( data._ignoreFaceIds.count( faceID ))
       continue;
-    SMESHDS_SubMesh* fSubM = getMeshDS()->MeshElements( exp.Current() );
-    SMDS_ElemIteratorPtr fIt = fSubM->GetElements();
-    vector< vector<const SMDS_MeshNode*>* > nnVec;
+    const bool isReversedFace = data._reversedFaceIds.count( faceID );
+    SMESHDS_SubMesh*    fSubM = getMeshDS()->MeshElements( exp.Current() );
+    SMDS_ElemIteratorPtr  fIt = fSubM->GetElements();
     while ( fIt->more() )
     {
       const SMDS_MeshElement* face = fIt->next();
-      int nbNodes = face->NbCornerNodes();
+      const int            nbNodes = face->NbCornerNodes();
       nnVec.resize( nbNodes );
-      SMDS_ElemIteratorPtr nIt = face->nodesIterator();
+      nnSet.clear();
+      degenEdgeInd.clear();
+      int nbZ = 0;
+      SMDS_NodeIteratorPtr nIt = face->nodeIterator();
       for ( int iN = 0; iN < nbNodes; ++iN )
       {
-        const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nIt->next() );
-        nnVec[ iN ] = & data._n2eMap[ n ]->_nodes;
+        const SMDS_MeshNode* n = nIt->next();
+        const int i = isReversedFace ? nbNodes-1-iN : iN;
+        nnVec[ i ] = & data._n2eMap[ n ]->_nodes;
+        if ( nnVec[ i ]->size() < 2 )
+          degenEdgeInd.insert( iN );
+        else
+          nbZ = nnVec[ i ]->size();
+
+        if ( helper.HasDegeneratedEdges() )
+          nnSet.insert( nnVec[ i ]);
       }
+      if ( nbZ == 0 )
+        continue;
+      if ( 0 < nnSet.size() && nnSet.size() < 3 )
+        continue;
 
-      int nbZ = nnVec[0]->size();
       switch ( nbNodes )
       {
       case 3:
-        for ( int iZ = 1; iZ < nbZ; ++iZ )
-          helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1], (*nnVec[2])[iZ-1],
-                            (*nnVec[0])[iZ],   (*nnVec[1])[iZ],   (*nnVec[2])[iZ]);
+        switch ( degenEdgeInd.size() )
+        {
+        case 0: // PENTA
+        {
+          for ( int iZ = 1; iZ < nbZ; ++iZ )
+            helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1], (*nnVec[2])[iZ-1],
+                              (*nnVec[0])[iZ],   (*nnVec[1])[iZ],   (*nnVec[2])[iZ]);
+          break;
+        }
+        case 1: // PYRAM
+        {
+          int i2 = *degenEdgeInd.begin();
+          int i0 = helper.WrapIndex( i2 - 1, nbNodes );
+          int i1 = helper.WrapIndex( i2 + 1, nbNodes );
+          for ( int iZ = 1; iZ < nbZ; ++iZ )
+            helper.AddVolume( (*nnVec[i0])[iZ-1], (*nnVec[i1])[iZ-1],
+                              (*nnVec[i1])[iZ],   (*nnVec[i0])[iZ],   (*nnVec[i2])[0]);
+          break;
+        }
+        case 2: // TETRA
+        {
+          int i3 = !degenEdgeInd.count(0) ? 0 : !degenEdgeInd.count(1) ? 1 : 2;
+          for ( int iZ = 1; iZ < nbZ; ++iZ )
+            helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1], (*nnVec[2])[iZ-1],
+                              (*nnVec[i3])[iZ]);
+          break;
+        }
+        }
         break;
+
       case 4:
-        for ( int iZ = 1; iZ < nbZ; ++iZ )
-          helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1],
-                            (*nnVec[2])[iZ-1], (*nnVec[3])[iZ-1],
-                            (*nnVec[0])[iZ],   (*nnVec[1])[iZ],
-                            (*nnVec[2])[iZ],   (*nnVec[3])[iZ]);
+        switch ( degenEdgeInd.size() )
+        {
+        case 0: // HEX
+        {
+          for ( int iZ = 1; iZ < nbZ; ++iZ )
+            helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1],
+                              (*nnVec[2])[iZ-1], (*nnVec[3])[iZ-1],
+                              (*nnVec[0])[iZ],   (*nnVec[1])[iZ],
+                              (*nnVec[2])[iZ],   (*nnVec[3])[iZ]);
+          break;
+        }
+        case 2: // PENTA?
+        {
+          int i2 = *degenEdgeInd.begin();
+          int i3 = *degenEdgeInd.rbegin();
+          bool ok = ( i3 - i2 == 1 );
+          if ( i2 == 0 && i3 == 3 ) { i2 = 3; i3 = 0; ok = true; }
+          int i0 = helper.WrapIndex( i3 + 1, nbNodes );
+          int i1 = helper.WrapIndex( i0 + 1, nbNodes );
+          for ( int iZ = 1; iZ < nbZ; ++iZ )
+          {
+            const SMDS_MeshElement* vol =
+              helper.AddVolume( (*nnVec[i3])[0], (*nnVec[i0])[iZ], (*nnVec[i0])[iZ-1],
+                                (*nnVec[i2])[0], (*nnVec[i1])[iZ], (*nnVec[i1])[iZ-1]);
+            if ( !ok && vol )
+              degenVols.push_back( vol );
+          }
+          break;
+        }
+        case 3: // degen HEX
+        {
+          const SMDS_MeshNode* nn[8];
+          for ( int iZ = 1; iZ < nbZ; ++iZ )
+          {
+            const SMDS_MeshElement* vol =
+              helper.AddVolume( nnVec[0]->size() > 1 ? (*nnVec[0])[iZ-1] : (*nnVec[0])[0],
+                                nnVec[1]->size() > 1 ? (*nnVec[1])[iZ-1] : (*nnVec[1])[0],
+                                nnVec[2]->size() > 1 ? (*nnVec[2])[iZ-1] : (*nnVec[2])[0],
+                                nnVec[3]->size() > 1 ? (*nnVec[3])[iZ-1] : (*nnVec[3])[0],
+                                nnVec[0]->size() > 1 ? (*nnVec[0])[iZ]   : (*nnVec[0])[0],
+                                nnVec[1]->size() > 1 ? (*nnVec[1])[iZ]   : (*nnVec[1])[0],
+                                nnVec[2]->size() > 1 ? (*nnVec[2])[iZ]   : (*nnVec[2])[0],
+                                nnVec[3]->size() > 1 ? (*nnVec[3])[iZ]   : (*nnVec[3])[0]);
+            degenVols.push_back( vol );
+          }
+        }
         break;
+        }
+        break;
+
       default:
         return error("Not supported type of element", data._index);
-      }
+
+      } // switch ( nbNodes )
+    } // while ( fIt->more() )
+  } // loop on FACEs
+
+  if ( !degenVols.empty() )
+  {
+    SMESH_ComputeErrorPtr& err = _mesh->GetSubMesh( data._solid )->GetComputeError();
+    if ( !err || err->IsOK() )
+    {
+      err.reset( new SMESH_ComputeError( COMPERR_WARNING,
+                                         "Degenerated volumes created" ));
+      err->myBadElements.insert( err->myBadElements.end(),
+                                 degenVols.begin(),degenVols.end() );
     }
   }
+
   return true;
 }
 
@@ -4101,20 +5445,19 @@ bool _ViscousBuilder::shrink()
 
   // EDGE's to shrink
   map< TGeomID, _Shrinker1D > e2shrMap;
+  vector< _LayerEdge* > lEdges;
 
   // loop on FACES to srink mesh on
   map< TGeomID, _SolidData* >::iterator f2sd = f2sdMap.begin();
   for ( ; f2sd != f2sdMap.end(); ++f2sd )
   {
-    _SolidData&     data = *f2sd->second;
-    TNode2Edge&   n2eMap = data._n2eMap;
-    const TopoDS_Face& F = TopoDS::Face( getMeshDS()->IndexToShape( f2sd->first ));
-
-    Handle(Geom_Surface) surface = BRep_Tool::Surface(F);
-
+    _SolidData&      data = *f2sd->second;
+    const TopoDS_Face&  F = TopoDS::Face( getMeshDS()->IndexToShape( f2sd->first ));
     SMESH_subMesh*     sm = _mesh->GetSubMesh( F );
     SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
 
+    Handle(Geom_Surface) surface = BRep_Tool::Surface(F);
+
     helper.SetSubShape(F);
 
     // ===========================
@@ -4149,23 +5492,30 @@ bool _ViscousBuilder::shrink()
     }
 
     // Find _LayerEdge's inflated along F
-    vector< _LayerEdge* > lEdges;
+    lEdges.clear();
     {
-      SMESH_subMeshIteratorPtr subIt =
-        sm->getDependsOnIterator(/*includeSelf=*/false, /*complexShapeFirst=*/false);
+      set< TGeomID > subIDs;
+      SMESH_subMeshIteratorPtr subIt = sm->getDependsOnIterator(/*includeSelf=*/false);
       while ( subIt->more() )
+        subIDs.insert( subIt->next()->GetId() );
+
+      int iBeg, iEnd = 0;
+      for ( int iS = 0; iS < data._endEdgeOnShape.size() && !subIDs.empty(); ++iS )
       {
-        SMESH_subMesh*     sub = subIt->next();
-        SMESHDS_SubMesh* subDS = sub->GetSubMeshDS();
-        if ( subDS->NbNodes() == 0 || !n2eMap.count( subDS->GetNodes()->next() ))
-          continue;
-        SMDS_NodeIteratorPtr nIt = subDS->GetNodes();
-        while ( nIt->more() )
-        {
-          _LayerEdge* edge = n2eMap[ nIt->next() ];
-          lEdges.push_back( edge );
-          prepareEdgeToShrink( *edge, F, helper, smDS );
-        }
+        iBeg = iEnd;
+        iEnd = data._endEdgeOnShape[ iS ];
+        TGeomID shapeID = data._edges[ iBeg ]->_nodes[0]->getshapeId();
+        set< TGeomID >::iterator idIt = subIDs.find( shapeID );
+        if ( idIt == subIDs.end() ||
+             data._edges[ iBeg ]->_sWOL.IsNull() ) continue;
+        subIDs.erase( idIt );
+
+        if ( !data._noShrinkShapes.count( shapeID ))
+          for ( ; iBeg < iEnd; ++iBeg )
+          {
+            lEdges.push_back( data._edges[ iBeg ] );
+            prepareEdgeToShrink( *data._edges[ iBeg ], F, helper, smDS );
+          }
       }
     }
 
@@ -4176,6 +5526,7 @@ bool _ViscousBuilder::shrink()
         dumpChangeNodes( f );
 
     // Replace source nodes by target nodes in mesh faces to shrink
+    dumpFunction(SMESH_Comment("replNodesOnFace")<<f2sd->first); // debug
     const SMDS_MeshNode* nodes[20];
     for ( size_t i = 0; i < lEdges.size(); ++i )
     {
@@ -4195,6 +5546,7 @@ bool _ViscousBuilder::shrink()
           nodes[iN] = ( n == srcNode ? tgtNode : n );
         }
         helper.GetMeshDS()->ChangeElementNodes( f, nodes, f->NbNodes() );
+        dumpChangeNodes( f );
       }
     }
 
@@ -4204,6 +5556,7 @@ bool _ViscousBuilder::shrink()
     // Create _SmoothNode's on face F
     vector< _SmoothNode > nodesToSmooth( smoothNodes.size() );
     {
+      dumpFunction(SMESH_Comment("fixUVOnFace")<<f2sd->first); // debug
       const bool sortSimplices = isConcaveFace;
       for ( size_t i = 0; i < smoothNodes.size(); ++i )
       {
@@ -4344,6 +5697,17 @@ bool _ViscousBuilder::shrink()
           }
         }
       }
+      // TODO: check effect of this additional smooth
+      // additional laplacian smooth to increase allowed shrink step
+      // for ( int st = 1; st; --st )
+      // {
+      //   dumpFunction(SMESH_Comment("shrinkFace")<<f2sd->first<<"_st"<<++smooStep); // debug
+      //   for ( size_t i = 0; i < nodesToSmooth.size(); ++i )
+      //   {
+      //     nodesToSmooth[i].Smooth( badNb,surface,helper,refSign,
+      //                              _SmoothNode::LAPLACIAN,/*set3D=*/false);
+      //   }
+      // }
     } // while ( shrinked )
 
     // No wrongly shaped faces remain; final smooth. Set node XYZ.
@@ -4408,66 +5772,19 @@ bool _ViscousBuilder::prepareEdgeToShrink( _LayerEdge&            edge,
   const SMDS_MeshNode* srcNode = edge._nodes[0];
   const SMDS_MeshNode* tgtNode = edge._nodes.back();
 
-  edge._pos.clear();
-
   if ( edge._sWOL.ShapeType() == TopAbs_FACE )
   {
-    gp_XY srcUV = helper.GetNodeUV( F, srcNode );
-    gp_XY tgtUV = helper.GetNodeUV( F, tgtNode );
+    gp_XY srcUV( edge._pos[0].X(), edge._pos[0].Y() );//helper.GetNodeUV( F, srcNode );
+    gp_XY tgtUV = edge.LastUV( F );                   //helper.GetNodeUV( F, tgtNode );
     gp_Vec2d uvDir( srcUV, tgtUV );
     double uvLen = uvDir.Magnitude();
     uvDir /= uvLen;
-    edge._normal.SetCoord( uvDir.X(),uvDir.Y(), 0);
+    edge._normal.SetCoord( uvDir.X(),uvDir.Y(), 0 );
     edge._len = uvLen;
 
-    // // IMPORTANT to have src nodes NOT yet REPLACED by tgt nodes in shrinked faces
-    // vector<const SMDS_MeshElement*> faces;
-    // multimap< double, const SMDS_MeshNode* > proj2node;
-    // SMDS_ElemIteratorPtr fIt = srcNode->GetInverseElementIterator(SMDSAbs_Face);
-    // while ( fIt->more() )
-    // {
-    //   const SMDS_MeshElement* f = fIt->next();
-    //   if ( faceSubMesh->Contains( f ))
-    //     faces.push_back( f );
-    // }
-    // for ( size_t i = 0; i < faces.size(); ++i )
-    // {
-    //   const int nbNodes = faces[i]->NbCornerNodes();
-    //   for ( int j = 0; j < nbNodes; ++j )
-    //   {
-    //     const SMDS_MeshNode* n = faces[i]->GetNode(j);
-    //     if ( n == srcNode ) continue;
-    //     if ( n->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE &&
-    //          ( faces.size() > 1 || nbNodes > 3 ))
-    //       continue;
-    //     gp_Pnt2d uv = helper.GetNodeUV( F, n );
-    //     gp_Vec2d uvDirN( srcUV, uv );
-    //     double proj = uvDirN * uvDir;
-    //     proj2node.insert( make_pair( proj, n ));
-    //   }
-    // }
-
-    // multimap< double, const SMDS_MeshNode* >::iterator p2n = proj2node.begin(), p2nEnd;
-    // const double       minProj = p2n->first;
-    // const double projThreshold = 1.1 * uvLen;
-    // if ( minProj > projThreshold )
-    // {
-    //   // tgtNode is located so that it does not make faces with wrong orientation
-    //   return true;
-    // }
     edge._pos.resize(1);
     edge._pos[0].SetCoord( tgtUV.X(), tgtUV.Y(), 0 );
 
-    // store most risky nodes in _simplices
-    // p2nEnd = proj2node.lower_bound( projThreshold );
-    // int nbSimpl = ( std::distance( p2n, p2nEnd ) + 1) / 2;
-    // edge._simplices.resize( nbSimpl );
-    // for ( int i = 0; i < nbSimpl; ++i )
-    // {
-    //   edge._simplices[i]._nPrev = p2n->second;
-    //   if ( ++p2n != p2nEnd )
-    //     edge._simplices[i]._nNext = p2n->second;
-    // }
     // set UV of source node to target node
     SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() );
     pos->SetUParameter( srcUV.X() );
@@ -4475,7 +5792,7 @@ bool _ViscousBuilder::prepareEdgeToShrink( _LayerEdge&            edge,
   }
   else // _sWOL is TopAbs_EDGE
   {
-    TopoDS_Edge E = TopoDS::Edge( edge._sWOL);
+    const TopoDS_Edge&    E = TopoDS::Edge( edge._sWOL );
     SMESHDS_SubMesh* edgeSM = getMeshDS()->MeshElements( E );
     if ( !edgeSM || edgeSM->NbElements() == 0 )
       return error(SMESH_Comment("Not meshed EDGE ") << getMeshDS()->ShapeToIndex( E ));
@@ -4494,7 +5811,9 @@ bool _ViscousBuilder::prepareEdgeToShrink( _LayerEdge&            edge,
 
     double uSrc = helper.GetNodeU( E, srcNode, n2 );
     double uTgt = helper.GetNodeU( E, tgtNode, srcNode );
-    double u2   = helper.GetNodeU( E, n2,      srcNode );
+    double u2   = helper.GetNodeU( E, n2, srcNode );
+
+    edge._pos.clear();
 
     if ( fabs( uSrc-uTgt ) < 0.99 * fabs( uSrc-u2 ))
     {
@@ -4509,64 +5828,54 @@ bool _ViscousBuilder::prepareEdgeToShrink( _LayerEdge&            edge,
     edge._simplices.resize( 1 );
     edge._simplices[0]._nPrev = n2;
 
-    // set UV of source node to target node
+    // set U of source node to the target node
     SMDS_EdgePosition* pos = static_cast<SMDS_EdgePosition*>( tgtNode->GetPosition() );
     pos->SetUParameter( uSrc );
   }
   return true;
+}
 
-  //================================================================================
-  /*!
-   * \brief Compute positions (UV) to set to a node on edge moved during shrinking
-   */
-  //================================================================================
-  
-  // Compute UV to follow during shrinking
-
-//   const SMDS_MeshNode* srcNode = edge._nodes[0];
-//   const SMDS_MeshNode* tgtNode = edge._nodes.back();
-
-//   gp_XY srcUV = helper.GetNodeUV( F, srcNode );
-//   gp_XY tgtUV = helper.GetNodeUV( F, tgtNode );
-//   gp_Vec2d uvDir( srcUV, tgtUV );
-//   double uvLen = uvDir.Magnitude();
-//   uvDir /= uvLen;
-
-//   // Select shrinking step such that not to make faces with wrong orientation.
-//   // IMPORTANT to have src nodes NOT yet REPLACED by tgt nodes in shrinked faces
-//   const double minStepSize = uvLen / 20;
-//   double stepSize = uvLen;
-//   SMDS_ElemIteratorPtr fIt = srcNode->GetInverseElementIterator(SMDSAbs_Face);
-//   while ( fIt->more() )
-//   {
-//     const SMDS_MeshElement* f = fIt->next();
-//     if ( !faceSubMesh->Contains( f )) continue;
-//     const int nbNodes = f->NbCornerNodes();
-//     for ( int i = 0; i < nbNodes; ++i )
-//     {
-//       const SMDS_MeshNode* n = f->GetNode(i);
-//       if ( n->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE || n == srcNode)
-//         continue;
-//       gp_XY uv = helper.GetNodeUV( F, n );
-//       gp_Vec2d uvDirN( srcUV, uv );
-//       double proj = uvDirN * uvDir;
-//       if ( proj < stepSize && proj > minStepSize )
-//         stepSize = proj;
-//     }
-//   }
-//   stepSize *= 0.8;
-
-//   const int nbSteps = ceil( uvLen / stepSize );
-//   gp_XYZ srcUV0( srcUV.X(), srcUV.Y(), 0 );
-//   gp_XYZ tgtUV0( tgtUV.X(), tgtUV.Y(), 0 );
-//   edge._pos.resize( nbSteps );
-//   edge._pos[0] = tgtUV0;
-//   for ( int i = 1; i < nbSteps; ++i )
-//   {
-//     double r = i / double( nbSteps );
-//     edge._pos[i] = (1-r) * tgtUV0 + r * srcUV0;
-//   }
-//   return true;
+//================================================================================
+/*!
+ * \brief Restore position of a sole node of a _LayerEdge based on _noShrinkShapes
+ */
+//================================================================================
+
+void _ViscousBuilder::restoreNoShrink( _LayerEdge& edge ) const
+{
+  if ( edge._nodes.size() == 1 )
+  {
+    edge._pos.clear();
+    edge._len = 0;
+
+    const SMDS_MeshNode* srcNode = edge._nodes[0];
+    TopoDS_Shape S = SMESH_MesherHelper::GetSubShapeByNode( srcNode, getMeshDS() );
+    if ( S.IsNull() ) return;
+
+    gp_Pnt p;
+
+    switch ( S.ShapeType() )
+    {
+    case TopAbs_EDGE:
+    {
+      double f,l;
+      TopLoc_Location loc;
+      Handle(Geom_Curve) curve = BRep_Tool::Curve( TopoDS::Edge( S ), loc, f, l );
+      if ( curve.IsNull() ) return;
+      SMDS_EdgePosition* ePos = static_cast<SMDS_EdgePosition*>( srcNode->GetPosition() );
+      p = curve->Value( ePos->GetUParameter() );
+      break;
+    }
+    case TopAbs_VERTEX:
+    {
+      p = BRep_Tool::Pnt( TopoDS::Vertex( S ));
+      break;
+    }
+    default: return;
+    }
+    getMeshDS()->MoveNode( srcNode, p.X(), p.Y(), p.Z() );
+    dumpMove( srcNode );
+  }
 }
 
 //================================================================================
@@ -4584,7 +5893,7 @@ void _ViscousBuilder::fixBadFaces(const TopoDS_Face&          F,
   SMESH::Controls::AspectRatio qualifier;
   SMESH::Controls::TSequenceOfXYZ points(3), points1(3), points2(3);
   const double maxAspectRatio = is2D ? 4. : 2;
-  NodeCoordHelper xyz( F, helper, is2D );
+  _NodeCoordHelper xyz( F, helper, is2D );
 
   // find bad triangles
 
@@ -4745,7 +6054,7 @@ bool _LayerEdge::SetNewLength2d( Handle(Geom_Surface)& surface,
     const double kSafe = Max( 0.5, 1. - 0.1 * _simplices.size() );
 
     // Select shrinking step such that not to make faces with wrong orientation.
-    double stepSize = uvLen;
+    double stepSize = 1e100;
     for ( size_t i = 0; i < _simplices.size(); ++i )
     {
       // find intersection of 2 lines: curUV-tgtUV and that connecting simplex nodes
@@ -4760,7 +6069,7 @@ bool _LayerEdge::SetNewLength2d( Handle(Geom_Surface)& surface,
         stepSize = Min( step, stepSize );
     }
     gp_Pnt2d newUV;
-    if ( uvLen - stepSize < _len / 200. )
+    if ( uvLen <= stepSize )
     {
       newUV = tgtUV;
       _pos.clear();
@@ -4785,11 +6094,11 @@ bool _LayerEdge::SetNewLength2d( Handle(Geom_Surface)& surface,
   }
   else // _sWOL is TopAbs_EDGE
   {
-    TopoDS_Edge E = TopoDS::Edge( _sWOL );
-    const SMDS_MeshNode* n2 = _simplices[0]._nPrev;
+    const TopoDS_Edge&      E = TopoDS::Edge( _sWOL );
+    const SMDS_MeshNode*   n2 = _simplices[0]._nPrev;
     SMDS_EdgePosition* tgtPos = static_cast<SMDS_EdgePosition*>( tgtNode->GetPosition() );
 
-    const double u2 = helper.GetNodeU( E, n2, tgtNode );
+    const double u2     = helper.GetNodeU( E, n2, tgtNode );
     const double uSrc   = _pos[0].Coord( U_SRC );
     const double lenTgt = _pos[0].Coord( LEN_TGT );
 
@@ -5196,6 +6505,8 @@ bool _ViscousBuilder::addBoundaryElements()
 {
   SMESH_MesherHelper helper( *_mesh );
 
+  vector< const SMDS_MeshNode* > faceNodes;
+
   for ( size_t i = 0; i < _sdVec.size(); ++i )
   {
     _SolidData& data = _sdVec[i];
@@ -5204,6 +6515,8 @@ bool _ViscousBuilder::addBoundaryElements()
     for ( int iE = 1; iE <= geomEdges.Extent(); ++iE )
     {
       const TopoDS_Edge& E = TopoDS::Edge( geomEdges(iE));
+      if ( data._noShrinkShapes.count( getMeshDS()->ShapeToIndex( E )))
+        continue;
 
       // Get _LayerEdge's based on E
 
@@ -5236,8 +6549,13 @@ bool _ViscousBuilder::addBoundaryElements()
         if ( nbSharedPyram > 1 )
           continue; // not free border of the pyramid
 
-        if ( getMeshDS()->FindFace( ledges[0]->_nodes[0], ledges[0]->_nodes[1],
-                                    ledges[1]->_nodes[0], ledges[1]->_nodes[1]))
+        faceNodes.clear();
+        faceNodes.push_back( ledges[0]->_nodes[0] );
+        faceNodes.push_back( ledges[1]->_nodes[0] );
+        if ( ledges[0]->_nodes.size() > 1 ) faceNodes.push_back( ledges[0]->_nodes[1] );
+        if ( ledges[1]->_nodes.size() > 1 ) faceNodes.push_back( ledges[1]->_nodes[1] );
+
+        if ( getMeshDS()->FindElement( faceNodes, SMDSAbs_Face, /*noMedium=*/true))
           continue; // faces already created
       }
       for ( ++u2n; u2n != u2nodes.end(); ++u2n )
@@ -5287,12 +6605,33 @@ bool _ViscousBuilder::addBoundaryElements()
       {
         vector< const SMDS_MeshNode*>&  nn1 = ledges[j-dj1]->_nodes;
         vector< const SMDS_MeshNode*>&  nn2 = ledges[j-dj2]->_nodes;
-        if ( isOnFace )
-          for ( size_t z = 1; z < nn1.size(); ++z )
-            sm->AddElement( getMeshDS()->AddFace( nn1[z-1], nn2[z-1], nn2[z], nn1[z] ));
+        if ( nn1.size() == nn2.size() )
+        {
+          if ( isOnFace )
+            for ( size_t z = 1; z < nn1.size(); ++z )
+              sm->AddElement( getMeshDS()->AddFace( nn1[z-1], nn2[z-1], nn2[z], nn1[z] ));
+          else
+            for ( size_t z = 1; z < nn1.size(); ++z )
+              sm->AddElement( new SMDS_FaceOfNodes( nn1[z-1], nn2[z-1], nn2[z], nn1[z] ));
+        }
+        else if ( nn1.size() == 1 )
+        {
+          if ( isOnFace )
+            for ( size_t z = 1; z < nn2.size(); ++z )
+              sm->AddElement( getMeshDS()->AddFace( nn1[0], nn2[z-1], nn2[z] ));
+          else
+            for ( size_t z = 1; z < nn2.size(); ++z )
+              sm->AddElement( new SMDS_FaceOfNodes( nn1[0], nn2[z-1], nn2[z] ));
+        }
         else
-          for ( size_t z = 1; z < nn1.size(); ++z )
-            sm->AddElement( new SMDS_FaceOfNodes( nn1[z-1], nn2[z-1], nn2[z], nn1[z]));
+        {
+          if ( isOnFace )
+            for ( size_t z = 1; z < nn1.size(); ++z )
+              sm->AddElement( getMeshDS()->AddFace( nn1[z-1], nn2[0], nn1[z] ));
+          else
+            for ( size_t z = 1; z < nn1.size(); ++z )
+              sm->AddElement( new SMDS_FaceOfNodes( nn1[z-1], nn2[0], nn2[z] ));
+        }
       }
 
       // Make edges
@@ -5302,7 +6641,7 @@ bool _ViscousBuilder::addBoundaryElements()
         if ( !edge->_sWOL.IsNull() && edge->_sWOL.ShapeType() == TopAbs_EDGE )
         {
           vector< const SMDS_MeshNode*>&  nn = edge->_nodes;
-          if ( nn[1]->GetInverseElementIterator( SMDSAbs_Edge )->more() )
+          if ( nn.size() < 2 || nn[1]->GetInverseElementIterator( SMDSAbs_Edge )->more() )
             continue;
           helper.SetSubShape( edge->_sWOL );
           helper.SetElementsOnShape( true );
index 5fe0a7b804cb5569b237aedc453dbfacc6f7d6c0..9c26048b637c2fa135218649d179e8e0de887db9 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "SMESH_Hypothesis.hxx"
 #include "SMESH_ProxyMesh.hxx"
+#include "SMESH_ComputeError.hxx"
 
 #include <vector>
 
@@ -39,7 +40,7 @@ class STDMESHERS_EXPORT StdMeshers_ViscousLayers : public SMESH_Hypothesis
 public:
   StdMeshers_ViscousLayers(int hypId, int studyId, SMESH_Gen* gen);
 
-  // Set boundary shapes, faces in 3D, edges in 2D, either to exclude from
+  // Set boundary shapes (faces in 3D, edges in 2D) either to exclude from
   // treatment or to make the Viscous Layers on
   void SetBndShapes(const std::vector<int>& shapeIds, bool toIgnore);
   std::vector<int> GetBndShapes() const { return _shapeIds; }
@@ -63,6 +64,15 @@ public:
                                const TopoDS_Shape& theShape,
                                const bool          toMakeN2NMap=false) const;
 
+  // Checks compatibility of assigned StdMeshers_ViscousLayers hypotheses 
+  static SMESH_ComputeErrorPtr
+    CheckHypothesis(SMESH_Mesh&                          aMesh,
+                    const TopoDS_Shape&                  aShape,
+                    SMESH_Hypothesis::Hypothesis_Status& aStatus);
+
+  // Checks if viscous layers should be constructed on a shape
+  bool IsShapeWithLayers(int shapeIndex) const;
+
   virtual std::ostream & SaveTo(std::ostream & save);
   virtual std::istream & LoadFrom(std::istream & load);
 
index 7e51343806582b8efe075c49f1ae779e1d08eeee..013e2d9d94d5f2747d825dc0d68687f8e39f5811 100644 (file)
@@ -256,6 +256,7 @@ namespace VISCOUS_2D
     _PolyLine*           _rightLine;
     int                  _firstPntInd; // index in vector<UVPtStruct> of _wire
     int                  _lastPntInd;
+    int                  _index;       // index in _ViscousBuilder2D::_polyLineVec
 
     vector< _LayerEdge > _lEdges;      /* _lEdges[0] is usually is not treated
                                           as it is equal to the last one of the _leftLine */
@@ -325,6 +326,7 @@ namespace VISCOUS_2D
   //--------------------------------------------------------------------------------
 
   typedef map< const SMDS_MeshNode*, _LayerEdge*, TIDCompare > TNode2Edge;
+  typedef StdMeshers_ViscousLayers2D                           THypVL;
   
   //--------------------------------------------------------------------------------
   /*!
@@ -335,14 +337,17 @@ namespace VISCOUS_2D
   public:
     _ViscousBuilder2D(SMESH_Mesh&                       theMesh,
                       const TopoDS_Face&                theFace,
-                      const StdMeshers_ViscousLayers2D* theHyp);
+                      vector< const THypVL* > &         theHyp,
+                      vector< TopoDS_Shape > &          theHypShapes);
     SMESH_ComputeErrorPtr GetError() const { return _error; }
     // does it's job
-    SMESH_ProxyMesh::Ptr  Compute(const TopoDS_Shape& theShapeHypAssignedTo);
+    SMESH_ProxyMesh::Ptr  Compute();
 
   private:
 
-    bool findEdgesWithLayers(const TopoDS_Shape& theShapeHypAssignedTo);
+    friend class ::StdMeshers_ViscousLayers2D;
+
+    bool findEdgesWithLayers();
     bool makePolyLines();
     bool inflate();
     bool fixCollisions();
@@ -362,9 +367,13 @@ namespace VISCOUS_2D
                            GeomAPI_ProjectPointOnSurf* faceProj);
     void adjustCommonEdge( _PolyLine& LL, _PolyLine& LR );
     void calcLayersHeight(const double    totalThick,
-                          vector<double>& heights);
+                          vector<double>& heights,
+                          const THypVL*   hyp);
     bool removeMeshFaces(const TopoDS_Shape& face);
 
+    const THypVL*     getLineHypothesis(int iPL);
+    double            getLineThickness (int iPL);
+
     bool              error( const string& text );
     SMESHDS_Mesh*     getMeshDS() { return _mesh->GetMeshDS(); }
     _ProxyMeshOfFace* getProxyMesh();
@@ -377,7 +386,8 @@ namespace VISCOUS_2D
     // input data
     SMESH_Mesh*                 _mesh;
     TopoDS_Face                 _face;
-    const StdMeshers_ViscousLayers2D* _hyp;
+    vector< const THypVL* >     _hyps;
+    vector< TopoDS_Shape >      _hypShapes;
 
     // result data
     SMESH_ProxyMesh::Ptr        _proxyMesh;
@@ -388,11 +398,12 @@ namespace VISCOUS_2D
     SMESH_MesherHelper          _helper;
     TSideVector                 _faceSideVec; // wires (StdMeshers_FaceSide) of _face
     vector<_PolyLine>           _polyLineVec; // fronts to advance
+    vector< const THypVL* >     _hypOfEdge; // a hyp per an EDGE of _faceSideVec
     bool                        _is2DIsotropic; // is same U and V resoulution of _face
     vector<TopoDS_Face>         _clearedFaces; // FACEs whose mesh was removed by shrink()
 
-    double                      _fPowN; // to compute thickness of layers
-    double                      _thickness; // required or possible layers thickness
+    //double                      _fPowN; // to compute thickness of layers
+    double                      _maxThickness; // max possible layers thickness
 
     // sub-shapes of _face 
     set<TGeomID>                _ignoreShapeIds; // ids of EDGEs w/o layers
@@ -409,15 +420,32 @@ namespace VISCOUS_2D
   /*!
    * \brief Returns StdMeshers_ViscousLayers2D for the FACE
    */
-  const StdMeshers_ViscousLayers2D* findHyp(SMESH_Mesh&        theMesh,
-                                            const TopoDS_Face& theFace,
-                                            TopoDS_Shape*      assignedTo=0)
+  bool findHyps(SMESH_Mesh&                                   theMesh,
+                const TopoDS_Face&                            theFace,
+                vector< const StdMeshers_ViscousLayers2D* > & theHyps,
+                vector< TopoDS_Shape > &                      theAssignedTo)
   {
+    theHyps.clear();
+    theAssignedTo.clear();
     SMESH_HypoFilter hypFilter
       ( SMESH_HypoFilter::HasName( StdMeshers_ViscousLayers2D::GetHypType() ));
-    const SMESH_Hypothesis * hyp =
-      theMesh.GetHypothesis( theFace, hypFilter, /*ancestors=*/true, assignedTo );
-    return dynamic_cast< const StdMeshers_ViscousLayers2D* > ( hyp );
+    list< const SMESHDS_Hypothesis * > hypList;
+    list< TopoDS_Shape >               hypShapes;
+    int nbHyps = theMesh.GetHypotheses
+      ( theFace, hypFilter, hypList, /*ancestors=*/true, &hypShapes );
+    if ( nbHyps )
+    {
+      theHyps.reserve( nbHyps );
+      theAssignedTo.reserve( nbHyps );
+      list< const SMESHDS_Hypothesis * >::iterator hyp = hypList.begin();
+      list< TopoDS_Shape >::iterator               shape = hypShapes.begin();
+      for ( ; hyp != hypList.end(); ++hyp, ++shape )
+      {
+        theHyps.push_back( static_cast< const StdMeshers_ViscousLayers2D* > ( *hyp ));
+        theAssignedTo.push_back( *shape );
+      }
+    }
+    return nbHyps;
   }
 
   //================================================================================
@@ -436,7 +464,7 @@ namespace VISCOUS_2D
                         const SMESHDS_Mesh*               theMesh,
                         set< int > &                      theEdgeIds)
   {
-    int nbToEdgesIgnore = 0;
+    int nbEdgesToIgnore = 0;
     vector<TGeomID> ids = theHyp->GetBndShapes();
     if ( theHyp->IsToIgnoreShapes() ) // EDGEs to ignore are given
     {
@@ -448,20 +476,20 @@ namespace VISCOUS_2D
              SMESH_MesherHelper::IsSubShape( E, theFace ))
         {
           theEdgeIds.insert( ids[i] );
-          ++nbToEdgesIgnore;
+          ++nbEdgesToIgnore;
         }
       }
     }
     else // EDGEs to make the Viscous Layers on are given
     {
       TopExp_Explorer E( theFace, TopAbs_EDGE );
-      for ( ; E.More(); E.Next(), ++nbToEdgesIgnore )
+      for ( ; E.More(); E.Next(), ++nbEdgesToIgnore )
         theEdgeIds.insert( theMesh->ShapeToIndex( E.Current() ));
 
       for ( size_t i = 0; i < ids.size(); ++i )
-        nbToEdgesIgnore -= theEdgeIds.erase( ids[i] );
+        nbEdgesToIgnore -= theEdgeIds.erase( ids[i] );
     }
-    return nbToEdgesIgnore;
+    return nbEdgesToIgnore;
   }
 
 } // namespace VISCOUS_2D
@@ -489,12 +517,12 @@ StdMeshers_ViscousLayers2D::Compute(SMESH_Mesh&        theMesh,
 {
   SMESH_ProxyMesh::Ptr pm;
 
-  TopoDS_Shape hypAssignedTo;
-  const StdMeshers_ViscousLayers2D* vlHyp = VISCOUS_2D::findHyp( theMesh, theFace, &hypAssignedTo );
-  if ( vlHyp )
+  vector< const StdMeshers_ViscousLayers2D* > hyps;
+  vector< TopoDS_Shape >                      hypShapes;
+  if ( VISCOUS_2D::findHyps( theMesh, theFace, hyps, hypShapes ))
   {
-    VISCOUS_2D::_ViscousBuilder2D builder( theMesh, theFace, vlHyp );
-    pm = builder.Compute( hypAssignedTo );
+    VISCOUS_2D::_ViscousBuilder2D builder( theMesh, theFace, hyps, hypShapes );
+    pm = builder.Compute();
     SMESH_ComputeErrorPtr error = builder.GetError();
     if ( error && !error->IsOK() )
       theMesh.GetSubMesh( theFace )->GetComputeError() = error;
@@ -510,6 +538,38 @@ StdMeshers_ViscousLayers2D::Compute(SMESH_Mesh&        theMesh,
   return pm;
 }
 // --------------------------------------------------------------------------------
+SMESH_ComputeErrorPtr
+StdMeshers_ViscousLayers2D::CheckHypothesis(SMESH_Mesh&                          theMesh,
+                                            const TopoDS_Shape&                  theShape,
+                                            SMESH_Hypothesis::Hypothesis_Status& theStatus)
+{
+  SMESH_ComputeErrorPtr error = SMESH_ComputeError::New(COMPERR_OK);
+  theStatus = SMESH_Hypothesis::HYP_OK;
+
+  TopExp_Explorer exp( theShape, TopAbs_FACE );
+  for ( ; exp.More() && theStatus == SMESH_Hypothesis::HYP_OK; exp.Next() )
+  {
+    const TopoDS_Face& face = TopoDS::Face( exp.Current() );
+    vector< const StdMeshers_ViscousLayers2D* > hyps;
+    vector< TopoDS_Shape >                      hypShapes;
+    if ( VISCOUS_2D::findHyps( theMesh, face, hyps, hypShapes ))
+    {
+      VISCOUS_2D::_ViscousBuilder2D builder( theMesh, face, hyps, hypShapes );
+      builder._faceSideVec =
+        StdMeshers_FaceSide::GetFaceWires( face, theMesh, true, error,
+                                           SMESH_ProxyMesh::Ptr(),
+                                           /*theCheckVertexNodes=*/false);
+      if ( error->IsOK() && !builder.findEdgesWithLayers())
+      {
+        error = builder.GetError();
+        if ( error && !error->IsOK() )
+          theStatus = SMESH_Hypothesis::HYP_INCOMPAT_HYPS;
+      }
+    }
+  }
+  return error;
+}
+// --------------------------------------------------------------------------------
 void StdMeshers_ViscousLayers2D::RestoreListeners() const
 {
   StudyContextStruct* sc = _gen->GetStudyContext( _studyId );
@@ -547,19 +607,22 @@ using namespace VISCOUS_2D;
  */
 //================================================================================
 
-_ViscousBuilder2D::_ViscousBuilder2D(SMESH_Mesh&                       theMesh,
-                                     const TopoDS_Face&                theFace,
-                                     const StdMeshers_ViscousLayers2D* theHyp):
-  _mesh( &theMesh ), _face( theFace ), _hyp( theHyp ), _helper( theMesh )
+_ViscousBuilder2D::_ViscousBuilder2D(SMESH_Mesh&               theMesh,
+                                     const TopoDS_Face&        theFace,
+                                     vector< const THypVL* > & theHyps,
+                                     vector< TopoDS_Shape > &  theAssignedTo):
+  _mesh( &theMesh ), _face( theFace ), _helper( theMesh )
 {
+  _hyps.swap( theHyps );
+  _hypShapes.swap( theAssignedTo );
+
   _helper.SetSubShape( _face );
   _helper.SetElementsOnShape( true );
 
   _face.Orientation( TopAbs_FORWARD ); // 2D logic works only in this case
   _surface = BRep_Tool::Surface( _face );
 
-  if ( _hyp )
-    _fPowN = pow( _hyp->GetStretchFactor(), _hyp->GetNumberLayers() );
+  _error = SMESH_ComputeError::New(COMPERR_OK);
 
   _nbLE = 0;
 }
@@ -593,14 +656,14 @@ bool _ViscousBuilder2D::error(const string& text )
  */
 //================================================================================
 
-SMESH_ProxyMesh::Ptr _ViscousBuilder2D::Compute(const TopoDS_Shape& theShapeHypAssignedTo)
+SMESH_ProxyMesh::Ptr _ViscousBuilder2D::Compute()
 {
-  _error       = SMESH_ComputeError::New(COMPERR_OK);
-  _faceSideVec = StdMeshers_FaceSide::GetFaceWires( _face, *_mesh, true, _error );
+  _faceSideVec = StdMeshers_FaceSide::GetFaceWires( _face, *_mesh, true, _error);
+
   if ( !_error->IsOK() )
     return _proxyMesh;
 
-  if ( !findEdgesWithLayers(theShapeHypAssignedTo) ) // analysis of a shape
+  if ( !findEdgesWithLayers() ) // analysis of a shape
     return _proxyMesh;
 
   if ( ! makePolyLines() ) // creation of fronts
@@ -629,21 +692,79 @@ SMESH_ProxyMesh::Ptr _ViscousBuilder2D::Compute(const TopoDS_Shape& theShapeHypA
  */
 //================================================================================
 
-bool _ViscousBuilder2D::findEdgesWithLayers(const TopoDS_Shape& theShapeHypAssignedTo)
+bool _ViscousBuilder2D::findEdgesWithLayers()
 {
-  // collect all EDGEs to ignore defined by hyp
-  int nbMyEdgesIgnored = getEdgesToIgnore( _hyp, _face, getMeshDS(), _ignoreShapeIds );
+  // collect all EDGEs to ignore defined by _hyps
+  typedef std::pair< set<TGeomID>, const THypVL* > TEdgesOfHyp;
+  vector< TEdgesOfHyp > ignoreEdgesOfHyp( _hyps.size() );
+  for ( size_t i = 0; i < _hyps.size(); ++i )
+  {
+    ignoreEdgesOfHyp[i].second = _hyps[i];
+    getEdgesToIgnore( _hyps[i], _face, getMeshDS(), ignoreEdgesOfHyp[i].first );
+  }
 
   // get all shared EDGEs
   TopTools_MapOfShape sharedEdges;
+  TopTools_IndexedMapOfShape hypFaces; // faces with VL hyps
+  for ( size_t i = 0; i < _hypShapes.size(); ++i )
+    TopExp::MapShapes( _hypShapes[i], TopAbs_FACE, hypFaces );
   TopTools_IndexedDataMapOfShapeListOfShape facesOfEdgeMap;
-  TopExp::MapShapesAndAncestors( theShapeHypAssignedTo,
-                                 TopAbs_EDGE, TopAbs_FACE, facesOfEdgeMap);
+  for ( int iF = 1; iF <= hypFaces.Extent(); ++iF )
+    TopExp::MapShapesAndAncestors( hypFaces(iF), TopAbs_EDGE, TopAbs_FACE, facesOfEdgeMap);
   for ( int iE = 1; iE <= facesOfEdgeMap.Extent(); ++iE )
     if ( facesOfEdgeMap( iE ).Extent() > 1 )
       sharedEdges.Add( facesOfEdgeMap.FindKey( iE ));
 
-  // check all EDGEs of the _face
+  // fill _hypOfEdge
+  if ( _hyps.size() > 1 )
+  {
+    // check if two hypotheses define different parameters for the same EDGE
+    for ( size_t iWire = 0; iWire < _faceSideVec.size(); ++iWire )
+    {
+      StdMeshers_FaceSidePtr wire = _faceSideVec[ iWire ];
+      for ( int iE = 0; iE < wire->NbEdges(); ++iE )
+      {
+        const THypVL* hyp = 0;
+        const TGeomID edgeID = wire->EdgeID( iE );
+        if ( !sharedEdges.Contains( wire->Edge( iE )))
+        {
+          for ( size_t i = 0; i < ignoreEdgesOfHyp.size(); ++i )
+            if ( ! ignoreEdgesOfHyp[i].first.count( edgeID ))
+            {
+              if ( hyp )
+                return error(SMESH_Comment("Several hypotheses define "
+                                           "Viscous Layers on the edge #") << edgeID );
+              hyp = ignoreEdgesOfHyp[i].second;
+            }
+        }
+        _hypOfEdge.push_back( hyp );
+        if ( !hyp )
+          _ignoreShapeIds.insert( edgeID );
+      }
+      // check if two hypotheses define different number of viscous layers for
+      // adjacent EDGEs
+      const THypVL *hyp, *prevHyp = _hypOfEdge.back();
+      size_t iH = _hypOfEdge.size() - wire->NbEdges();
+      for ( ; iH < _hypOfEdge.size(); ++iH )
+      {
+        hyp = _hypOfEdge[ iH ];
+        if ( hyp && prevHyp &&
+             hyp->GetNumberLayers() != prevHyp->GetNumberLayers() )
+        {
+          return error("Two hypotheses define different number of "
+                       "viscous layers on adjacent edges");
+        }
+        prevHyp = hyp;
+      }
+    }
+  }
+  else if ( _hyps.size() == 1 )
+  {
+    _ignoreShapeIds.swap( ignoreEdgesOfHyp[0].first );
+  }
+
+  // check all EDGEs of the _face to fill _ignoreShapeIds and _noShrinkVert
+
   int totalNbEdges = 0;
   for ( size_t iWire = 0; iWire < _faceSideVec.size(); ++iWire )
   {
@@ -674,9 +795,9 @@ bool _ViscousBuilder2D::findEdgesWithLayers(const TopoDS_Shape& theShapeHypAssig
           for ( ; hyp != allHyps.end() && !viscHyp; ++hyp )
             viscHyp = dynamic_cast<const StdMeshers_ViscousLayers2D*>( *hyp );
 
-          set<TGeomID> neighbourIgnoreEdges;
-          if (viscHyp)
-            getEdgesToIgnore( viscHyp, neighbourFace, getMeshDS(), neighbourIgnoreEdges );
+          // set<TGeomID> neighbourIgnoreEdges;
+          // if (viscHyp)
+          //   getEdgesToIgnore( viscHyp, neighbourFace, getMeshDS(), neighbourIgnoreEdges );
 
           for ( int iV = 0; iV < 2; ++iV )
           {
@@ -688,12 +809,22 @@ bool _ViscousBuilder2D::findEdgesWithLayers(const TopoDS_Shape& theShapeHypAssig
               PShapeIteratorPtr edgeIt = _helper.GetAncestors( vertex, *_mesh, TopAbs_EDGE );
               while ( const TopoDS_Shape* edge = edgeIt->next() )
                 if ( !edge->IsSame( wire->Edge( iE )) &&
-                     _helper.IsSubShape( *edge, neighbourFace ) &&
-                     ( neighbourIgnoreEdges.count( getMeshDS()->ShapeToIndex( *edge )) ||
-                       sharedEdges.Contains( *edge )))
+                     _helper.IsSubShape( *edge, neighbourFace ))
                 {
-                  _noShrinkVert.insert( getMeshDS()->ShapeToIndex( vertex ));
-                  break;
+                  const TGeomID neighbourID = getMeshDS()->ShapeToIndex( *edge );
+                  bool hasVL = !sharedEdges.Contains( *edge );
+                  if ( hasVL )
+                  {
+                    hasVL = false;
+                    for ( hyp = allHyps.begin(); hyp != allHyps.end() && !hasVL; ++hyp )
+                      if ( viscHyp = dynamic_cast<const THypVL*>( *hyp ))
+                        hasVL = viscHyp->IsShapeWithLayers( neighbourID );
+                  }
+                  if ( !hasVL )
+                  {
+                    _noShrinkVert.insert( getMeshDS()->ShapeToIndex( vertex ));
+                    break;
+                  }
                 }
             }
           }
@@ -702,18 +833,20 @@ bool _ViscousBuilder2D::findEdgesWithLayers(const TopoDS_Shape& theShapeHypAssig
     }
   }
 
+  int nbMyEdgesIgnored = _ignoreShapeIds.size();
+
   // add VERTEXes w/o layers to _ignoreShapeIds (this is used by toShrinkForAdjacent())
-  for ( size_t iWire = 0; iWire < _faceSideVec.size(); ++iWire )
-  {
-    StdMeshers_FaceSidePtr wire = _faceSideVec[ iWire ];
-    for ( int iE = 0; iE < wire->NbEdges(); ++iE )
-    {
-      TGeomID edge1 = wire->EdgeID( iE );
-      TGeomID edge2 = wire->EdgeID( iE+1 );
-      if ( _ignoreShapeIds.count( edge1 ) && _ignoreShapeIds.count( edge2 ))
-        _ignoreShapeIds.insert( getMeshDS()->ShapeToIndex( wire->LastVertex( iE )));
-    }
-  }
+  // for ( size_t iWire = 0; iWire < _faceSideVec.size(); ++iWire )
+  // {
+  //   StdMeshers_FaceSidePtr wire = _faceSideVec[ iWire ];
+  //   for ( int iE = 0; iE < wire->NbEdges(); ++iE )
+  //   {
+  //     TGeomID edge1 = wire->EdgeID( iE );
+  //     TGeomID edge2 = wire->EdgeID( iE+1 );
+  //     if ( _ignoreShapeIds.count( edge1 ) && _ignoreShapeIds.count( edge2 ))
+  //       _ignoreShapeIds.insert( getMeshDS()->ShapeToIndex( wire->LastVertex( iE )));
+  //   }
+  // }
 
   return ( nbMyEdgesIgnored < totalNbEdges );
 }
@@ -772,6 +905,7 @@ bool _ViscousBuilder2D::makePolyLines()
     for ( int iE = 0; iE < wire->NbEdges(); ++iE )
     {
       _PolyLine& L  = _polyLineVec[ iPoLine++ ];
+      L._index      = iPoLine-1;
       L._wire       = wire.get();
       L._edgeInd    = iE;
       L._advancable = !_ignoreShapeIds.count( wire->EdgeID( iE ));
@@ -846,13 +980,16 @@ bool _ViscousBuilder2D::makePolyLines()
   // Evaluate max possible _thickness if required layers thickness seems too high
   // ----------------------------------------------------------------------------
 
-  _thickness = _hyp->GetTotalThickness();
+  _maxThickness = _hyps[0]->GetTotalThickness();
+  for ( size_t iH = 1; iH < _hyps.size(); ++iH )
+    _maxThickness = Max( _maxThickness, _hyps[iH]->GetTotalThickness() );
+
   _SegmentTree::box_type faceBndBox2D;
   for ( iPoLine = 0; iPoLine < _polyLineVec.size(); ++iPoLine )
     faceBndBox2D.Add( *_polyLineVec[ iPoLine]._segTree->getBox() );
-  double boxTol = 1e-3 * sqrt( faceBndBox2D.SquareExtent() );
-  //
-  if ( _thickness * maxLen2dTo3dRatio > sqrt( faceBndBox2D.SquareExtent() ) / 10 )
+  const double boxTol = 1e-3 * sqrt( faceBndBox2D.SquareExtent() );
+
+  if ( _maxThickness * maxLen2dTo3dRatio > sqrt( faceBndBox2D.SquareExtent() ) / 10 )
   {
     vector< const _Segment* > foundSegs;
     double maxPossibleThick = 0;
@@ -885,7 +1022,7 @@ bool _ViscousBuilder2D::makePolyLines()
       }
     }
     if ( maxPossibleThick > 0. )
-      _thickness = Min( _hyp->GetTotalThickness(), maxPossibleThick );
+      _maxThickness = Min( _maxThickness, maxPossibleThick );
   }
 
   // Adjust _LayerEdge's at _PolyLine's extremities
@@ -930,13 +1067,14 @@ bool _ViscousBuilder2D::makePolyLines()
   for ( iPoLine = 0; iPoLine < _polyLineVec.size(); ++iPoLine )
   {
     lineBoxes[ iPoLine ] = *_polyLineVec[ iPoLine ]._segTree->getBox();
-    lineBoxes[ iPoLine ].Enlarge( maxLen2dTo3dRatio * _thickness * 
+    lineBoxes[ iPoLine ].Enlarge( maxLen2dTo3dRatio * getLineThickness( iPoLine ) * 
                                   ( _polyLineVec[ iPoLine ]._advancable ? 2. : 1.2 ));
   }
   // _reachableLines
   for ( iPoLine = 0; iPoLine < _polyLineVec.size(); ++iPoLine )
   {
     _PolyLine& L1 = _polyLineVec[ iPoLine ];
+    const double thick1 = getLineThickness( iPoLine );
     for ( size_t iL2 = 0; iL2 < _polyLineVec.size(); ++iL2 )
     {
       _PolyLine& L2 = _polyLineVec[ iL2 ];
@@ -950,7 +1088,7 @@ bool _ViscousBuilder2D::makePolyLines()
       {
         _LayerEdge& LE = L1._lEdges[iLE];
         if ( !lineBoxes[ iL2 ].IsOut ( LE._uvOut,
-                                       LE._uvOut + LE._normal2D *_thickness * LE._len2dTo3dRatio ))
+                                       LE._uvOut + LE._normal2D * thick1 * LE._len2dTo3dRatio ))
         {
           L1._reachableLines.push_back( & L2 );
           break;
@@ -1023,10 +1161,10 @@ void _ViscousBuilder2D::adjustCommonEdge( _PolyLine& LL, _PolyLine& LR )
       // Remove _LayerEdge's intersecting the normAvg to avoid collisions
       // during inflate().
       //
-      // find max length of the VERTEX based _LayerEdge whose direction is normAvg
-      double maxLen2D       = _thickness * EL._len2dTo3dRatio;
-      const gp_XY& pCommOut = ER._uvOut;
-      gp_XY        pCommIn  = pCommOut + normAvg * maxLen2D;
+      // find max length of the VERTEX-based _LayerEdge whose direction is normAvg
+      double       maxLen2D  = _maxThickness * EL._len2dTo3dRatio;
+      const gp_XY& pCommOut  = ER._uvOut;
+      gp_XY        pCommIn   = pCommOut + normAvg * maxLen2D;
       _Segment segCommon( pCommOut, pCommIn );
       _SegmentIntersection intersection;
       vector< const _Segment* > foundSegs;
@@ -1067,7 +1205,7 @@ void _ViscousBuilder2D::adjustCommonEdge( _PolyLine& LL, _PolyLine& LR )
         _SegmentIntersection lastIntersection;
         for ( ; iLE < L._lEdges.size(); ++iLE, eIt += dIt )
         {
-          gp_XY uvIn = eIt->_uvOut + eIt->_normal2D * _thickness * eIt->_len2dTo3dRatio;
+          gp_XY uvIn = eIt->_uvOut + eIt->_normal2D * _maxThickness * eIt->_len2dTo3dRatio;
           _Segment segOfEdge( eIt->_uvOut, uvIn );
           if ( !intersection.Compute( segCommon, segOfEdge ))
             break;
@@ -1148,7 +1286,7 @@ void _ViscousBuilder2D::setLayerEdgeData( _LayerEdge&                 lEdge,
     gp_Vec faceNorm = du ^ dv;
     gp_Vec normal   = faceNorm ^ tangent;
     normal.Normalize();
-    p = pOut.XYZ() + normal.XYZ() * /*1e-2 * */_hyp->GetTotalThickness() / _hyp->GetNumberLayers();
+    p = pOut.XYZ() + normal.XYZ() * /*1e-2 * */_hyps[0]->GetTotalThickness() / _hyps[0]->GetNumberLayers();
     faceProj->Perform( p );
     if ( !faceProj->IsDone() || faceProj->NbPoints() < 1 )
       return setLayerEdgeData( lEdge, u, pcurve, curve, p, reverse, NULL );
@@ -1205,7 +1343,7 @@ bool _ViscousBuilder2D::inflate()
 {
   // Limit size of inflation step by geometry size found by
   // itersecting _LayerEdge's with _Segment's
-  double minSize = _thickness, maxSize = 0;
+  double minSize = _maxThickness, maxSize = 0;
   vector< const _Segment* > foundSegs;
   _SegmentIntersection intersection;
   for ( size_t iL1 = 0; iL1 < _polyLineVec.size(); ++iL1 )
@@ -1233,29 +1371,30 @@ bool _ViscousBuilder2D::inflate()
     }
   }
   if ( minSize > maxSize ) // no collisions possible
-    maxSize = _thickness;
+    maxSize = _maxThickness;
 #ifdef __myDEBUG
   cout << "-- minSize = " << minSize << ", maxSize = " << maxSize << endl;
 #endif
 
   double curThick = 0, stepSize = minSize;
   int nbSteps = 0;
-  if ( maxSize > _thickness )
-    maxSize = _thickness;
+  if ( maxSize > _maxThickness )
+    maxSize = _maxThickness;
   while ( curThick < maxSize )
   {
     curThick += stepSize * 1.25;
-    if ( curThick > _thickness )
-      curThick = _thickness;
+    if ( curThick > _maxThickness )
+      curThick = _maxThickness;
 
     // Elongate _LayerEdge's
     for ( size_t iL = 0; iL < _polyLineVec.size(); ++iL )
     {
       _PolyLine& L = _polyLineVec[ iL ];
       if ( !L._advancable ) continue;
+      const double lineThick = Min( curThick, getLineThickness( iL ));
       bool lenChange = false;
       for ( size_t iLE = L.FirstLEdge(); iLE < L._lEdges.size(); ++iLE )
-        lenChange |= L._lEdges[iLE].SetNewLength( curThick );
+        lenChange |= L._lEdges[iLE].SetNewLength( lineThick );
       // for ( int k=0; k<L._segments.size(); ++k)
       //   cout << "( " << L._segments[k].p1().X() << ", " <<L._segments[k].p1().Y() << " ) "
       //        << "( " << L._segments[k].p2().X() << ", " <<L._segments[k].p2().Y() << " ) "
@@ -1270,7 +1409,7 @@ bool _ViscousBuilder2D::inflate()
     {
       break; // no more inflating possible
     }
-    stepSize = Max( stepSize , _thickness / 10. );
+    stepSize = Max( stepSize , _maxThickness / 10. );
     nbSteps++;
   }
 
@@ -1533,26 +1672,28 @@ bool _ViscousBuilder2D::shrink()
           int iPFrom = L._firstPntInd, iPTo = L._lastPntInd;
           if ( isShrinkableL )
           {
+            const THypVL* hyp = getLineHypothesis( L._leftLine->_index );
             vector<gp_XY>& uvVec = L._lEdges.front()._uvRefined;
-            for ( int i = 0; i < _hyp->GetNumberLayers(); ++i ) {
+            for ( int i = 0; i < hyp->GetNumberLayers(); ++i ) {
               const UVPtStruct& uvPt = points[ iPFrom + i + 1 ];
               L._leftNodes.push_back( uvPt.node );
               uvVec.push_back ( pcurve->Value( uvPt.param ).XY() );
             }
+            iPFrom += hyp->GetNumberLayers();
           }
           if ( isShrinkableR )
           {
+            const THypVL* hyp = getLineHypothesis( L._rightLine->_index );
             vector<gp_XY>& uvVec = L._lEdges.back()._uvRefined;
-            for ( int i = 0; i < _hyp->GetNumberLayers(); ++i ) {
+            for ( int i = 0; i < hyp->GetNumberLayers(); ++i ) {
               const UVPtStruct& uvPt = points[ iPTo - i - 1 ];
               L._rightNodes.push_back( uvPt.node );
               uvVec.push_back ( pcurve->Value( uvPt.param ).XY() );
             }
+            iPTo -= hyp->GetNumberLayers();
           }
           // make proxy sub-mesh data of present nodes
           //
-          if ( isShrinkableL ) iPFrom += _hyp->GetNumberLayers();
-          if ( isShrinkableR ) iPTo   -= _hyp->GetNumberLayers();
           UVPtStructVec nodeDataVec( & points[ iPFrom ], & points[ iPTo + 1 ]);
 
           double normSize = nodeDataVec.back().normParam - nodeDataVec.front().normParam;
@@ -1571,9 +1712,46 @@ bool _ViscousBuilder2D::shrink()
           myEdgeSM->SetUVPtStructVec( nodeDataVec );
 
           existingNodesFound = true;
+          break;
         }
       } // loop on FACEs sharing E
 
+    // Commented as a case with a seam EDGE (issue 0052461) is hard to support
+    // because SMESH_ProxyMesh can't hold different sub-meshes for two
+    // 2D representations of the seam. But such a case is not a real practice one.
+    // Check if L is an already shrinked seam
+    // if ( adjFace.IsNull() && _helper.IsRealSeam( edgeID ))
+    // {
+    //   for ( int iL2 = iL1-1; iL2 > -1; --iL2 )
+    //   {
+    //     _PolyLine& L2 = _polyLineVec[ iL2 ];
+    //     if ( edgeID == L2._wire->EdgeID( L2._edgeInd ))
+    //     {
+    //       // copy layer nodes
+    //       const int seamPar = _helper.GetPeriodicIndex();
+    //       vector<gp_XY>& uvVec = L._lEdges.front()._uvRefined;
+    //       if ( isShrinkableL )
+    //       {
+    //         L._leftNodes = L2._rightNodes;
+    //         uvVec = L2._lEdges.back()._uvRefined;
+    //       }
+    //       if ( isShrinkableR )
+    //       {
+    //         L._rightNodes = L2._leftNodes;
+    //         uvVec = L2._lEdges.front()._uvRefined;
+    //       }
+    //       for ( size_t i = 0; i < uvVec.size(); ++i )
+    //       {
+    //         gp_XY & uv = uvVec[i];
+    //         uv.SetCoord( seamPar, _helper.GetOtherParam( uv.Coord( seamPar )));
+    //       }
+
+    //       existingNodesFound = true;
+    //       break;
+    //     }
+    //   }
+    // }
+
     if ( existingNodesFound )
       continue; // nothing more to do in this case
 
@@ -1686,14 +1864,14 @@ bool _ViscousBuilder2D::shrink()
             ( isR ? L._leftLine->_lEdges.back() : L._rightLine->_lEdges.front() );
           length2D = neighborLE._length2D;
           if ( length2D == 0 )
-            length2D = _thickness * nearLE._len2dTo3dRatio;
+            length2D = _maxThickness * nearLE._len2dTo3dRatio;
         }
       }
 
       // move u to the internal boundary of layers
       //  u --> u
       //  x-x-x-x-----x-----x----
-      double maxLen3D = Min( _thickness, edgeLen / ( 1 + nbAdvancable ));
+      double maxLen3D = Min( _maxThickness, edgeLen / ( 1 + nbAdvancable ));
       double maxLen2D = maxLen3D * nearLE._len2dTo3dRatio;
       if ( !length2D ) length2D = length1D / len1dTo2dRatio;
       if ( Abs( length2D ) > maxLen2D )
@@ -1709,7 +1887,8 @@ bool _ViscousBuilder2D::shrink()
 
       // compute params of layers on L
       vector<double> heights;
-      calcLayersHeight( u - u0, heights );
+      const THypVL* hyp = getLineHypothesis( L2->_index );
+      calcLayersHeight( u - u0, heights, hyp );
       //
       vector< double > params( heights.size() );
       for ( size_t i = 0; i < params.size(); ++i )
@@ -1719,13 +1898,13 @@ bool _ViscousBuilder2D::shrink()
       //  x-x-x-x---
       vector< const SMDS_MeshNode* >& layersNode = isR ? L._rightNodes : L._leftNodes;
       vector<gp_XY>& nodeUV = ( isR ? L._lEdges.back() : L._lEdges[0] )._uvRefined;
-      nodeUV.resize    ( _hyp->GetNumberLayers() );
-      layersNode.resize( _hyp->GetNumberLayers() );
+      nodeUV.resize    ( hyp->GetNumberLayers() );
+      layersNode.resize( hyp->GetNumberLayers() );
       const SMDS_MeshNode* vertexNode = nodeDataVec[ iPEnd ].node;
       const SMDS_MeshNode *  prevNode = vertexNode;
       for ( size_t i = 0; i < params.size(); ++i )
       {
-        gp_Pnt p        = curve.Value( params[i] );
+        const gp_Pnt p  = curve.Value( params[i] );
         layersNode[ i ] = helper.AddNode( p.X(), p.Y(), p.Z(), /*id=*/0, params[i] );
         nodeUV    [ i ] = pcurve->Value( params[i] ).XY();
         helper.AddEdge( prevNode, layersNode[ i ] );
@@ -1736,7 +1915,7 @@ bool _ViscousBuilder2D::shrink()
       if ( !L2->_advancable )
       {
         isRShrinkedForAdjacent = isR;
-        nodeDataForAdjacent.resize( _hyp->GetNumberLayers() );
+        nodeDataForAdjacent.resize( hyp->GetNumberLayers() );
 
         size_t iFrw = 0, iRev = nodeDataForAdjacent.size()-1, *i = isR ? &iRev : &iFrw;
         nodeDataForAdjacent[ *i ] = points[ isR ? L._lastPntInd : L._firstPntInd ];
@@ -1853,11 +2032,11 @@ bool _ViscousBuilder2D::shrink()
       {
         // refine the not shared _LayerEdge
         vector<double> layersHeight;
-        calcLayersHeight( LE2._length2D, layersHeight );
+        calcLayersHeight( LE2._length2D, layersHeight, getLineHypothesis( L2._index ));
 
         vector<gp_XY>& nodeUV2 = LE2._uvRefined;
-        nodeUV2.resize    ( _hyp->GetNumberLayers() );
-        layerNodes2.resize( _hyp->GetNumberLayers() );
+        nodeUV2.resize    ( layersHeight.size() );
+        layerNodes2.resize( layersHeight.size() );
         for ( size_t i = 0; i < layersHeight.size(); ++i )
         {
           gp_XY uv = LE2._uvOut + LE2._normal2D * layersHeight[i];
@@ -1912,15 +2091,16 @@ bool _ViscousBuilder2D::toShrinkForAdjacent( const TopoDS_Face&   adjFace,
                                              const TopoDS_Edge&   E,
                                              const TopoDS_Vertex& V)
 {
-  if ( _noShrinkVert.count( getMeshDS()->ShapeToIndex( V )))
+  if ( _noShrinkVert.count( getMeshDS()->ShapeToIndex( V )) || adjFace.IsNull() )
     return false;
 
-  TopoDS_Shape hypAssignedTo;
-  if ( const StdMeshers_ViscousLayers2D* vlHyp = findHyp( *_mesh, adjFace, &hypAssignedTo ))
+  vector< const StdMeshers_ViscousLayers2D* > hyps;
+  vector< TopoDS_Shape >                      hypShapes;
+  if ( VISCOUS_2D::findHyps( *_mesh, adjFace, hyps, hypShapes ))
   {
-    VISCOUS_2D::_ViscousBuilder2D builder( *_mesh, adjFace, vlHyp );
+    VISCOUS_2D::_ViscousBuilder2D builder( *_mesh, adjFace, hyps, hypShapes );
     builder._faceSideVec = StdMeshers_FaceSide::GetFaceWires( adjFace, *_mesh, true, _error );
-    builder.findEdgesWithLayers( hypAssignedTo );
+    builder.findEdgesWithLayers();
 
     PShapeIteratorPtr edgeIt = _helper.GetAncestors( V, *_mesh, TopAbs_EDGE );
     while ( const TopoDS_Shape* edgeAtV = edgeIt->next() )
@@ -1973,89 +2153,64 @@ bool _ViscousBuilder2D::refine()
     }
 
     // limit length of neighbour _LayerEdge's to avoid sharp change of layers thickness
+
     vector< double > segLen( L._lEdges.size() );
     segLen[0] = 0.0;
-    for ( size_t i = 1; i < segLen.size(); ++i )
-    {
-      // accumulate length of segments
-      double sLen = (L._lEdges[i-1]._uvOut - L._lEdges[i]._uvOut ).Modulus();
-      segLen[i] = segLen[i-1] + sLen;
-    }
-    for ( int isR = 0; isR < 2; ++isR )
+
+    // check if length modification is usefull: look for _LayerEdge's
+    // with length limited due to collisions
+    bool lenLimited = false;
+    for ( size_t iLE = 1; ( iLE < L._lEdges.size()-1 && !lenLimited ); ++iLE )
+      lenLimited = L._lEdges[ iLE ]._isBlocked;
+
+    if ( lenLimited )
     {
-      size_t iF = 0, iL = L._lEdges.size()-1;
-      size_t *i = isR ? &iL : &iF;
-      _LayerEdge* prevLE = & L._lEdges[ *i ];
-      double weight = 0;
-      for ( ++iF, --iL; iF < L._lEdges.size()-1; ++iF, --iL )
+      for ( size_t i = 1; i < segLen.size(); ++i )
+      {
+        // accumulate length of segments
+        double sLen = (L._lEdges[i-1]._uvOut - L._lEdges[i]._uvOut ).Modulus();
+        segLen[i] = segLen[i-1] + sLen;
+      }
+      const double totSegLen = segLen.back();
+      // normalize the accumulated length
+      for ( size_t iS = 1; iS < segLen.size(); ++iS )
+        segLen[iS] /= totSegLen;
+
+      for ( int isR = 0; isR < 2; ++isR )
       {
-        _LayerEdge& LE = L._lEdges[*i];
-        if ( prevLE->_length2D > 0 )
+        size_t iF = 0, iL = L._lEdges.size()-1;
+        size_t *i = isR ? &iL : &iF;
+        _LayerEdge* prevLE = & L._lEdges[ *i ];
+        double weight = 0;
+        for ( ++iF, --iL; iF < L._lEdges.size()-1; ++iF, --iL )
         {
-          gp_XY tangent ( LE._normal2D.Y(), -LE._normal2D.X() );
-          weight += Abs( tangent * ( prevLE->_uvIn - LE._uvIn )) / segLen.back();
-          // gp_XY prevTang( LE._uvOut - prevLE->_uvOut );
-          // gp_XY prevNorm( -prevTang.Y(), prevTang.X() );
-          gp_XY prevNorm = LE._normal2D;
-          double prevProj = prevNorm * ( prevLE->_uvIn - prevLE->_uvOut );
-          if ( prevProj > 0 ) {
-            prevProj /= prevNorm.Modulus();
-            if ( LE._length2D < prevProj )
-              weight += 0.75 * ( 1 - weight ); // length decrease is more preferable
-            LE._length2D  = weight * LE._length2D + ( 1 - weight ) * prevProj;
-            LE._uvIn = LE._uvOut + LE._normal2D * LE._length2D;
+          _LayerEdge& LE = L._lEdges[*i];
+          if ( prevLE->_length2D > 0 )
+          {
+            gp_XY tangent ( LE._normal2D.Y(), -LE._normal2D.X() );
+            weight += Abs( tangent * ( prevLE->_uvIn - LE._uvIn )) / totSegLen;
+            // gp_XY prevTang( LE._uvOut - prevLE->_uvOut );
+            // gp_XY prevNorm( -prevTang.Y(), prevTang.X() );
+            gp_XY prevNorm = LE._normal2D;
+            double prevProj = prevNorm * ( prevLE->_uvIn - prevLE->_uvOut );
+            if ( prevProj > 0 ) {
+              prevProj /= prevNorm.Modulus();
+              if ( LE._length2D < prevProj )
+                weight += 0.75 * ( 1 - weight ); // length decrease is more preferable
+              LE._length2D  = weight * LE._length2D + ( 1 - weight ) * prevProj;
+              LE._uvIn = LE._uvOut + LE._normal2D * LE._length2D;
+            }
           }
+          prevLE = & LE;
         }
-        prevLE = & LE;
       }
     }
     // DEBUG:  to see _uvRefined. cout can be redirected to hide NETGEN output
     // cerr << "import smesh" << endl << "mesh = smesh.Mesh()"<< endl;
 
-    // calculate intermediate UV on _LayerEdge's ( _LayerEdge::_uvRefined )   
-    size_t iLE = 0, nbLE = L._lEdges.size();
-    if ( ! L._lEdges[0]._uvRefined.empty() )     ++iLE;
-    if ( ! L._lEdges.back()._uvRefined.empty() ) --nbLE;
-    for ( ; iLE < nbLE; ++iLE )
-    {
-      _LayerEdge& LE = L._lEdges[iLE];
-      if ( fabs( LE._length2D - prevLen2D ) > LE._length2D / 100. )
-      {
-        calcLayersHeight( LE._length2D, layersHeight );
-        prevLen2D = LE._length2D;
-      }
-      for ( size_t i = 0; i < layersHeight.size(); ++i )
-        LE._uvRefined.push_back( LE._uvOut + LE._normal2D * layersHeight[i] );
-
-      // DEBUG:  to see _uvRefined
-      // for ( size_t i = 0; i < LE._uvRefined.size(); ++i )
-      // {
-      //   gp_XY uv = LE._uvRefined[i];
-      //   gp_Pnt p = _surface->Value( uv.X(), uv.Y() );
-      //   cerr << "mesh.AddNode( " << p.X() << ", "  << p.Y() << ", "  << p.Z() << " )" << endl;
-      // }
-    }
-
-    // nodes to create 1 layer of faces
-    vector< const SMDS_MeshNode* > outerNodes( L._lastPntInd - L._firstPntInd + 1 );
-    vector< const SMDS_MeshNode* > innerNodes( L._lastPntInd - L._firstPntInd + 1 );
-
-    // initialize outerNodes by nodes of the L._wire
     const vector<UVPtStruct>& points = L._wire->GetUVPtStruct();
-    for ( int i = L._firstPntInd; i <= L._lastPntInd; ++i )
-      outerNodes[ i-L._firstPntInd ] = points[i].node;
-
-    // compute normalized [0;1] node parameters of outerNodes
-    vector< double > normPar( L._lastPntInd - L._firstPntInd + 1 );
-    const double
-      normF    = L._wire->FirstParameter( L._edgeInd ),
-      normL    = L._wire->LastParameter ( L._edgeInd ),
-      normDist = normL - normF;
-    for ( int i = L._firstPntInd; i <= L._lastPntInd; ++i )
-      normPar[ i - L._firstPntInd ] = ( points[i].normParam - normF ) / normDist;
 
-    // Create layers of faces
-    
+    // analyse extremities of the _PolyLine to find existing nodes
     const TopoDS_Vertex&  V1 = L._wire->FirstVertex( L._edgeInd );
     const TopoDS_Vertex&  V2 = L._wire->LastVertex ( L._edgeInd );
     const int           v1ID = getMeshDS()->ShapeToIndex( V1 );
@@ -2067,28 +2222,81 @@ bool _ViscousBuilder2D::refine()
     bool hasRightNode    = ( !L._rightLine->_leftNodes.empty() && rightEdgeShared );
     bool hasOwnLeftNode  = ( !L._leftNodes.empty() );
     bool hasOwnRightNode = ( !L._rightNodes.empty() );
-    bool isClosedEdge    = ( outerNodes.front() == outerNodes.back() );
-    size_t iS,
+    bool isClosedEdge    = ( points[ L._firstPntInd ].node == points[ L._lastPntInd ].node );
+    const size_t
+      nbN = L._lastPntInd - L._firstPntInd + 1,
       iN0 = ( hasLeftNode || hasOwnLeftNode || isClosedEdge || !isShrinkableL ),
-      nbN = innerNodes.size() - ( hasRightNode || hasOwnRightNode || !isShrinkableR);
-    L._leftNodes .reserve( _hyp->GetNumberLayers() );
-    L._rightNodes.reserve( _hyp->GetNumberLayers() );
-    int cur = 0, prev = -1; // to take into account orientation of _face
-    if ( isReverse ) std::swap( cur, prev );
-    for ( int iF = 0; iF < _hyp->GetNumberLayers(); ++iF ) // loop on layers of faces
+      iNE = nbN - ( hasRightNode || hasOwnRightNode || !isShrinkableR );
+
+    // update _uvIn of end _LayerEdge's by existing nodes
+    const SMDS_MeshNode *nL = 0, *nR = 0;
+    if ( hasOwnLeftNode )    nL = L._leftNodes.back();
+    else if ( hasLeftNode )  nL = L._leftLine->_rightNodes.back();
+    if ( hasOwnRightNode )   nR = L._rightNodes.back();
+    else if ( hasRightNode ) nR = L._rightLine->_leftNodes.back();
+    if ( nL )
+      L._lEdges[0]._uvIn = _helper.GetNodeUV( _face, nL, points[ L._firstPntInd + 1 ].node );
+    if ( nR )
+      L._lEdges.back()._uvIn = _helper.GetNodeUV( _face, nR, points[ L._lastPntInd - 1 ].node );
+
+    // compute normalized [0;1] node parameters of nodes on a _PolyLine
+    vector< double > normPar( nbN );
+    const double
+      normF    = L._wire->FirstParameter( L._edgeInd ),
+      normL    = L._wire->LastParameter ( L._edgeInd ),
+      normDist = normL - normF;
+    for ( int i = L._firstPntInd; i <= L._lastPntInd; ++i )
+      normPar[ i - L._firstPntInd ] = ( points[i].normParam - normF ) / normDist;
+
+    // Calculate UV of most inner nodes
+
+    vector< gp_XY > innerUV( nbN );
+
+    // check if innerUV should be interpolated between _LayerEdge::_uvIn's
+    const size_t nbLE = L._lEdges.size();
+    bool needInterpol = ( nbN != nbLE );
+    if ( !needInterpol )
+    {
+      // more check: compare length of inner and outer end segments
+      double lenIn, lenOut;
+      for ( int isR = 0; isR < 2 && !needInterpol; ++isR )
+      {
+        const _Segment& segIn = isR ? L._segments.back() : L._segments[0];
+        const gp_XY&   uvIn1  = segIn.p1();
+        const gp_XY&   uvIn2  = segIn.p2();
+        const gp_XY&   uvOut1 = L._lEdges[ isR ? nbLE-1 : 0 ]._uvOut;
+        const gp_XY&   uvOut2 = L._lEdges[ isR ? nbLE-2 : 1 ]._uvOut;
+        if ( _is2DIsotropic )
+        {
+          lenIn  = ( uvIn1  - uvIn2  ).Modulus();
+          lenOut = ( uvOut1 - uvOut2 ).Modulus();
+        }
+        else
+        {
+          lenIn  = _surface->Value( uvIn1.X(), uvIn1.Y() )
+            .Distance( _surface->Value( uvIn2.X(), uvIn2.Y() ));
+          lenOut  = _surface->Value( uvOut1.X(), uvOut1.Y() )
+            .Distance( _surface->Value( uvOut2.X(), uvOut2.Y() ));
+        }
+        needInterpol = ( lenIn < 0.66 * lenOut );
+      }
+    }
+
+    if ( needInterpol )
     {
-      // get accumulated length of intermediate segments
+      // compute normalized accumulated length of inner segments
+      size_t iS;
       if ( _is2DIsotropic )
         for ( iS = 1; iS < segLen.size(); ++iS )
         {
-          double sLen = (L._lEdges[iS-1]._uvRefined[iF] - L._lEdges[iS]._uvRefined[iF] ).Modulus();
+          double sLen = ( L._lEdges[iS-1]._uvIn - L._lEdges[iS]._uvIn ).Modulus();
           segLen[iS] = segLen[iS-1] + sLen;
         }
       else
         for ( iS = 1; iS < segLen.size(); ++iS )
         {
-          const gp_XY& uv1 = L._lEdges[iS-1]._uvRefined[iF];
-          const gp_XY& uv2 = L._lEdges[iS  ]._uvRefined[iF];
+          const gp_XY& uv1 = L._lEdges[iS-1]._uvIn;
+          const gp_XY& uv2 = L._lEdges[iS  ]._uvIn;
           gp_Pnt p1 = _surface->Value( uv1.X(), uv1.Y() );
           gp_Pnt p2 = _surface->Value( uv2.X(), uv2.Y() );
           double sLen = p1.Distance( p2 );
@@ -2098,15 +2306,49 @@ bool _ViscousBuilder2D::refine()
       for ( iS = 1; iS < segLen.size(); ++iS )
         segLen[iS] /= segLen.back();
 
-      // create innerNodes of a current layer
+      // calculate UV of most inner nodes according to the normalized node parameters
       iS = 0;
-      for ( size_t i = iN0; i < nbN; ++i )
+      for ( size_t i = 0; i < innerUV.size(); ++i )
       {
         while ( normPar[i] > segLen[iS+1] )
           ++iS;
         double r = ( normPar[i] - segLen[iS] ) / ( segLen[iS+1] - segLen[iS] );
-        gp_XY uv = r * L._lEdges[iS+1]._uvRefined[iF] + (1-r) * L._lEdges[iS]._uvRefined[iF];
-        gp_Pnt p = _surface->Value( uv.X(), uv.Y() );
+        innerUV[ i ] = r * L._lEdges[iS+1]._uvIn + (1-r) * L._lEdges[iS]._uvIn;
+      }
+    }
+    else // ! needInterpol
+    {
+      for ( size_t i = 0; i < nbLE; ++i )
+        innerUV[ i ] = L._lEdges[i]._uvIn;
+    }
+
+    // normalized height of layers
+    const THypVL* hyp = getLineHypothesis( iL );
+    calcLayersHeight( 1., layersHeight, hyp);
+
+    // Create layers of faces
+
+    // nodes to create 1 layer of faces
+    vector< const SMDS_MeshNode* > outerNodes( nbN );
+    vector< const SMDS_MeshNode* > innerNodes( nbN );
+
+    // initialize outerNodes by nodes of the L._wire
+    for ( int i = L._firstPntInd; i <= L._lastPntInd; ++i )
+      outerNodes[ i-L._firstPntInd ] = points[i].node;
+
+    L._leftNodes .reserve( hyp->GetNumberLayers() );
+    L._rightNodes.reserve( hyp->GetNumberLayers() );
+    int cur = 0, prev = -1; // to take into account orientation of _face
+    if ( isReverse ) std::swap( cur, prev );
+    for ( int iF = 0; iF < hyp->GetNumberLayers(); ++iF ) // loop on layers of faces
+    {
+      // create innerNodes of a current layer
+      for ( size_t i = iN0; i < iNE; ++i )
+      {
+        gp_XY uvOut = points[ L._firstPntInd + i ].UV();
+        gp_XY& uvIn = innerUV[ i ];
+        gp_XY    uv = layersHeight[ iF ] * uvIn + ( 1.-layersHeight[ iF ]) * uvOut;
+        gp_Pnt    p = _surface->Value( uv.X(), uv.Y() );
         innerNodes[i] = _helper.AddNode( p.X(), p.Y(), p.Z(), /*id=*/0, uv.X(), uv.Y() );
       }
       // use nodes created for adjacent _PolyLine's
@@ -2128,6 +2370,7 @@ bool _ViscousBuilder2D::refine()
 
       outerNodes.swap( innerNodes );
     }
+
     // faces between not shared _LayerEdge's (at concave VERTEX)
     for ( int isR = 0; isR < 2; ++isR )
     {
@@ -2259,6 +2502,30 @@ bool _ViscousBuilder2D::removeMeshFaces(const TopoDS_Shape& face)
   return thereWereElems;
 }
 
+//================================================================================
+/*!
+ * \brief Returns a hypothesis for a _PolyLine
+ */
+//================================================================================
+
+const StdMeshers_ViscousLayers2D* _ViscousBuilder2D::getLineHypothesis(int iPL)
+{
+  return iPL < (int)_hypOfEdge.size() ? _hypOfEdge[ iPL ] : _hyps[0];
+}
+
+//================================================================================
+/*!
+ * \brief Returns a layers thickness for a _PolyLine
+ */
+//================================================================================
+
+double _ViscousBuilder2D::getLineThickness(int iPL)
+{
+  if ( const StdMeshers_ViscousLayers2D* h = getLineHypothesis( iPL ))
+    return Min( _maxThickness, h->GetTotalThickness() );
+  return _maxThickness;
+}
+
 //================================================================================
 /*!
  * \brief Creates a _ProxyMeshOfFace and store it in a sub-mesh of FACE
@@ -2285,21 +2552,23 @@ _ProxyMeshOfFace* _ViscousBuilder2D::getProxyMesh()
 //================================================================================
 
 void _ViscousBuilder2D::calcLayersHeight(const double    totalThick,
-                                         vector<double>& heights)
+                                         vector<double>& heights,
+                                         const THypVL*   hyp)
 {
-  heights.resize( _hyp->GetNumberLayers() );
+  const double fPowN = pow( hyp->GetStretchFactor(), hyp->GetNumberLayers() );
+  heights.resize( hyp->GetNumberLayers() );
   double h0;
-  if ( _fPowN - 1 <= numeric_limits<double>::min() )
-    h0 = totalThick / _hyp->GetNumberLayers();
+  if ( fPowN - 1 <= numeric_limits<double>::min() )
+    h0 = totalThick / hyp->GetNumberLayers();
   else
-    h0 = totalThick * ( _hyp->GetStretchFactor() - 1 )/( _fPowN - 1 );
+    h0 = totalThick * ( hyp->GetStretchFactor() - 1 )/( fPowN - 1 );
 
   double hSum = 0, hi = h0;
-  for ( int i = 0; i < _hyp->GetNumberLayers(); ++i )
+  for ( int i = 0; i < hyp->GetNumberLayers(); ++i )
   {
     hSum += hi;
     heights[ i ] = hSum;
-    hi *= _hyp->GetStretchFactor();
+    hi *= hyp->GetStretchFactor();
   }
 }
 
index a7b6c9c45a8d4df0dd74f30481a1992cee5769c2..f9fab2b338c25cc01f2faddc143c59ab7aede241 100644 (file)
@@ -35,9 +35,10 @@ class STDMESHERS_EXPORT StdMeshers_ViscousLayers2D : public StdMeshers_ViscousLa
 {
 public:
   StdMeshers_ViscousLayers2D(int hypId, int studyId, SMESH_Gen* gen);
-
-  // Computes temporary 2D mesh to be used by 2D algorithm.
-  // Return SMESH_ProxyMesh for the given FACE, or NULL in case of error
+  /*!
+   * \brief Computes temporary 2D mesh to be used by 2D algorithm.
+   *        Return SMESH_ProxyMesh for the given FACE, or NULL in case of error
+   */
   static SMESH_ProxyMesh::Ptr Compute(SMESH_Mesh&        theMesh,
                                       const TopoDS_Face& theShape);
   /*!
@@ -46,13 +47,19 @@ public:
    */
   void RestoreListeners() const;
 
+  /*!
+   * \brief Checks compatibility of assigned StdMeshers_ViscousLayers2D hypotheses
+   */
+  static SMESH_ComputeErrorPtr CheckHypothesis(SMESH_Mesh&         aMesh,
+                                               const TopoDS_Shape& aShape,
+                                               Hypothesis_Status&  aStatus);
   /*!
    * \brief Initialize my parameter values by the mesh built on the geometry
-    * \param theMesh - the built mesh
-    * \param theShape - the geometry of interest
-    * \retval bool - true if parameter values have been successfully defined
-    *
-    * Just return false as this hypothesis does not have parameters values
+   * \param theMesh - the built mesh
+   * \param theShape - the geometry of interest
+   * \retval bool - true if parameter values have been successfully defined
+   *
+   * Just return false as this hypothesis does not have parameters values
    */
   virtual bool SetParametersByMesh(const SMESH_Mesh* theMesh, const TopoDS_Shape& theShape);
 
index 88ad6ddc365c25c9465b4933239af2a301aef088..4cdd2b92ef943cb9fc99d28cd705adf41e9dbc60 100644 (file)
@@ -58,6 +58,7 @@
 #include <QApplication>
 #include <QButtonGroup>
 #include <QCheckBox>
+#include <QFontMetrics>
 #include <QGridLayout>
 #include <QGroupBox>
 #include <QHBoxLayout>
@@ -677,6 +678,22 @@ namespace
     dirs[( iOk+2 ) % 3] = dirs[ iOk ] ^ dirs[ ( iOk+1 ) % 3 ];
     dirs[( iOk+1 ) % 3] = dirs[ ( iOk+2 ) % 3 ] ^ dirs[ iOk ];
   }
+
+  //================================================================================
+  /*!
+   * \brief Returns a minimal width of a SpinBox depending on a precision type
+   */
+  //================================================================================
+
+  int getMinWidth( const char* precisionType )
+  {
+    int nb = SMESHGUI::resourceMgr()->integerValue( "SMESH", precisionType, -3 );
+    QString s;
+    s.fill('0', qAbs(nb)+7 );
+    QLineEdit le;
+    QFontMetrics metrics( le.font() );
+    return metrics.width( s );
+  }
 }
 
 //================================================================================
@@ -858,7 +875,9 @@ QFrame* StdMeshersGUI_CartesianParamCreator::buildFrame()
   axisLbl[2] = new QLabel( tr( "AXIS_Z"), axesDirGrp );
   QLabel* dLbl[3];
   myAxisBtnGrp = new QButtonGroup( axesDirGrp );
-  SMESHGUI_SpinBox** spins[3] = { &myXDirSpin[0], &myYDirSpin[0], &myZDirSpin[0] };
+  // get spin width
+  const char * const precisionType = "len_tol_precision";
+  int minWidth = getMinWidth( precisionType );
   for ( int i = 0; i < 3; ++i )
   {
     QPushButton* axisBtn = new QPushButton( QIcon(aPix), "", axesDirGrp );
@@ -867,9 +886,12 @@ QFrame* StdMeshersGUI_CartesianParamCreator::buildFrame()
     myXDirSpin[i] = new SMESHGUI_SpinBox( axesDirGrp );
     myYDirSpin[i] = new SMESHGUI_SpinBox( axesDirGrp );
     myZDirSpin[i] = new SMESHGUI_SpinBox( axesDirGrp );
-    myXDirSpin[i]->RangeStepAndValidator( -1, 1, 0.1, "len_tol_precision" );
-    myYDirSpin[i]->RangeStepAndValidator( -1, 1, 0.1, "len_tol_precision" );
-    myZDirSpin[i]->RangeStepAndValidator( -1, 1, 0.1, "len_tol_precision" );
+    myXDirSpin[i]->RangeStepAndValidator( -1, 1, 0.1, precisionType );
+    myYDirSpin[i]->RangeStepAndValidator( -1, 1, 0.1, precisionType );
+    myZDirSpin[i]->RangeStepAndValidator( -1, 1, 0.1, precisionType );
+    myXDirSpin[i]->setMinimumWidth( minWidth );
+    myYDirSpin[i]->setMinimumWidth( minWidth );
+    myZDirSpin[i]->setMinimumWidth( minWidth );
     dLbl[0] = new QLabel( tr("SMESH_DX"), axesDirGrp );
     dLbl[1] = new QLabel( tr("SMESH_DY"), axesDirGrp );
     dLbl[2] = new QLabel( tr("SMESH_DZ"), axesDirGrp );
index 85b048d6e959636c6767e424cac1b8c931917d34..9e5768402b62d3a3b6a735ac28e558dc8f7f0113 100644 (file)
@@ -210,8 +210,8 @@ void StdMeshersGUI_ObjectReferenceParamWdg::SetObject(CORBA::Object_ptr obj)
     myObjNameLineEdit->setStyleSheet("");
     myObjects.push_back( CORBA::Object::_duplicate( obj ));
     myParamValue = sobj->GetID().c_str();
-    emit contentModified();
   }
+  emit contentModified();
 }
 
 //================================================================================
index 891b2c0c86170a4fdc62f383ba55a3eb9d44303d..c481eea7e9b598017fce4bc1e545826bf002bce4 100644 (file)
@@ -47,6 +47,7 @@
 
 // SALOME GUI includes
 #include <SUIT_ResourceMgr.h>
+#include <SUIT_MessageBox.h>
 
 // IDL includes
 #include <SALOMEconfig.h>
@@ -1265,8 +1266,15 @@ bool StdMeshersGUI_StdHypothesisCreator::stdParams( ListOfStdParams& p ) const
 
       idsWg->SetMainShapeEntry( aMainEntry );
       idsWg->SetGeomShapeEntry( aSubEntry.isEmpty() ? aMainEntry : aSubEntry );
-      idsWg->SetListOfIDs( h->GetFaces() );
-      idsWg->showPreview( true );
+      if ( idsWg->SetListOfIDs( h->GetFaces() ))
+      {
+        idsWg->showPreview( true );
+      }
+      else
+      {
+        SUIT_MessageBox::warning( dlg(),tr( "SMESH_WRN_WARNING" ),tr( "BAD_FACES_WARNING" ));
+        idsWg->setEnabled( false );
+      }
       customWidgets()->append ( idsWg );
     }
   }
@@ -1317,8 +1325,15 @@ bool StdMeshersGUI_StdHypothesisCreator::stdParams( ListOfStdParams& p ) const
 
       idsWg->SetMainShapeEntry( aMainEntry );
       idsWg->SetGeomShapeEntry( aSubEntry.isEmpty() ? aMainEntry : aSubEntry );
-      idsWg->SetListOfIDs( h->GetEdges() );
-      idsWg->showPreview( true );
+      if ( idsWg->SetListOfIDs( h->GetEdges() ))
+      {
+        idsWg->showPreview( true );
+      }
+      else
+      {
+        SUIT_MessageBox::warning( dlg(),tr( "SMESH_WRN_WARNING" ),tr( "BAD_EDGES_WARNING" ));
+        idsWg->setEnabled( false );
+      }
       customWidgets()->append ( idsWg );
     }
   }
index 935df0cc39f7119edfdc249b0711beff7ed24f2f..9cd4ff727ecf397522f681e0509c74b2921c9f41 100644 (file)
@@ -515,9 +515,9 @@ SMESH::long_array_var StdMeshersGUI_SubShapeSelectorWdg::GetListOfIDs()
 
 //=================================================================================
 // function : SetListOfIds
-// purpose  : Called to set the list of SubShapes IDs
+// purpose  : Called to set the list of SubShapes IDs. Returns false if any ID is invalid
 //=================================================================================
-void StdMeshersGUI_SubShapeSelectorWdg::SetListOfIDs( SMESH::long_array_var theIds)
+bool StdMeshersGUI_SubShapeSelectorWdg::SetListOfIDs( SMESH::long_array_var theIds)
 {
   mySelectedIDs.clear();
   myListOfIDs.clear();
@@ -525,8 +525,10 @@ void StdMeshersGUI_SubShapeSelectorWdg::SetListOfIDs( SMESH::long_array_var theI
   for ( int i = 0; i < size; i++ )
     mySelectedIDs.append( theIds[ i ] );
 
-  mySelectedIDs = GetCorrectedListOfIDs( false );
+  bool isOk;
+  mySelectedIDs = GetCorrectedListOfIDs( false, &isOk );
   onAdd();
+  return isOk;
 }
 
 //=================================================================================
@@ -556,35 +558,74 @@ const char* StdMeshersGUI_SubShapeSelectorWdg::GetMainShapeEntry()
 // 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 )
+QList<int>
+StdMeshersGUI_SubShapeSelectorWdg::GetCorrectedListOfIDs( bool fromSubshapeToMainshape,
+                                                          bool* isOK )
 {
-  if ( ( myMainShape.IsNull() || myGeomShape.IsNull() ) &&  fromSubshapeToMainshape )
+  if (( myMainShape.IsNull() || myGeomShape.IsNull() ) &&  fromSubshapeToMainshape )
     return myListOfIDs;
-  else   if ( ( myMainShape.IsNull() || myGeomShape.IsNull() ) &&  !fromSubshapeToMainshape )
+  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;
-  TopTools_IndexedMapOfShape   aMainMap;
-  TopExp::MapShapes(myGeomShape, aGeomMap);
+  TopTools_IndexedMapOfShape aGeomMap, aMainMap;
   TopExp::MapShapes(myMainShape, aMainMap);
+  if ( !myGeomShape.IsNull() )
+    TopExp::MapShapes(myGeomShape, aGeomMap);
 
-  if ( fromSubshapeToMainshape ) { // convert indexes from sub-shape to mainshape
+  bool ok = true;
+  if ( fromSubshapeToMainshape ) // convert indexes from sub-shape to mainshape
+  {
     int size = myListOfIDs.size();
     for (int i = 0; i < size; i++) {
-      TopoDS_Shape aSubShape = aGeomMap.FindKey( myListOfIDs.at(i) );
-      int index = aMainMap.FindIndex( aSubShape );
+      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
+  }
+  else // convert indexes from main shape to sub-shape, or just check indices
+  {
     int size = mySelectedIDs.size();
     for (int i = 0; i < size; i++) {
-      TopoDS_Shape aSubShape = aMainMap.FindKey( mySelectedIDs.at(i) );
-      int index = aGeomMap.FindIndex( aSubShape );
+      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;
 }
index f8ea6e9e1ec43b38f1ab004ffad66998d0bfa412..7793817be8419c5a208e519dcf66c7eaac8dfb1d 100644 (file)
@@ -58,7 +58,7 @@ public:
   ~StdMeshersGUI_SubShapeSelectorWdg();
 
   SMESH::long_array_var          GetListOfIDs();
-  void                           SetListOfIDs( SMESH::long_array_var );
+  bool                           SetListOfIDs( SMESH::long_array_var );
 
   void                           SetGeomShapeEntry( const QString& theEntry );
   const char*                    GetGeomShapeEntry() { return myEntry.toLatin1().data();}
@@ -69,7 +69,8 @@ public:
   TopoDS_Shape                   GetGeomShape() { return myGeomShape; }
   TopoDS_Shape                   GetMainShape() { return myMainShape; }
 
-  QList<int>                     GetCorrectedListOfIDs( bool fromSubshapeToMainshape = true );
+  QList<int>                     GetCorrectedListOfIDs( bool fromSubshapeToMainshape,
+                                                        bool* isOK=0);
 
   static GEOM::GEOM_Object_var   GetGeomObjectByEntry( const QString& );
   static TopoDS_Shape            GetTopoDSByEntry( const QString& );
index 08dcd56718567ff24e3e5fafeca25a544978d25e..5e38ea864680f4124b287528f9e406bd4b5972e3 100644 (file)
         <source>TO_IGNORE_FACES</source>
         <translation>Faces without layers (inlets and oulets)</translation>
     </message>
+    <message>
+        <source>BAD_FACES_WARNING</source>
+        <translation>
+Specified faces are not sub-shapes of the shape of 
+mesh/sub-mesh.
+Consider creating another hypothesis instead of using
+this one for this mesh/sub-mesh.</translation>
+    </message>
+    <message>
+        <source>BAD_EDGES_WARNING</source>
+        <translation>
+Specified edges are not sub-shapes of the shape of 
+mesh/sub-mesh.
+Consider creating another hypothesis instead of using
+this one for this mesh/sub-mesh.</translation>
+    </message>
 </context>
 <context>
     <name>@default</name>