Salome HOME
Merge from BR_imps_2013 14/01/2014
authorvsr <vsr@opencascade.com>
Wed, 15 Jan 2014 09:41:17 +0000 (09:41 +0000)
committervsr <vsr@opencascade.com>
Wed, 15 Jan 2014 09:41:17 +0000 (09:41 +0000)
82 files changed:
doc/salome/examples/defining_hypotheses_ex01.py
doc/salome/examples/defining_hypotheses_ex08.py
doc/salome/gui/SMESH/images/a-geometric1d.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/viscous_layers_hyp.png
doc/salome/gui/SMESH/input/1d_meshing_hypo.doc
doc/salome/gui/SMESH/input/about_hypo.doc
doc/salome/gui/SMESH/input/additional_hypo.doc
doc/salome/gui/SMESH/input/tui_defining_hypotheses.doc
idl/SMESH_BasicHypothesis.idl
idl/SMESH_Mesh.idl
resources/StdMeshers.xml.in
src/SMESH/SMESH_Algo.cxx
src/SMESH/SMESH_MesherHelper.cxx
src/SMESH/SMESH_Pattern.cxx
src/SMESH/SMESH_Pattern.hxx
src/SMESHGUI/SMESHGUI_Hypotheses.cxx
src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx
src/SMESHGUI/SMESHGUI_HypothesesUtils.h
src/SMESHGUI/SMESHGUI_MeshDlg.cxx
src/SMESHGUI/SMESHGUI_MeshDlg.h
src/SMESHGUI/SMESHGUI_MeshOp.cxx
src/SMESHGUI/SMESHGUI_MeshOp.h
src/SMESHGUI/SMESH_msg_en.ts
src/SMESHGUI/SMESH_msg_fr.ts
src/SMESHUtils/SMESH_Block.cxx
src/SMESHUtils/SMESH_Block.hxx
src/SMESHUtils/SMESH_MeshAlgos.cxx
src/SMESHUtils/SMESH_MeshAlgos.hxx
src/SMESHUtils/SMESH_TypeDefs.hxx
src/SMESH_I/SMESH_2smeshpy.cxx
src/SMESH_I/SMESH_DumpPython.cxx
src/SMESH_I/SMESH_Mesh_i.cxx
src/SMESH_I/SMESH_Mesh_i.hxx
src/SMESH_I/SMESH_PythonDump.hxx
src/SMESH_SWIG/StdMeshersBuilder.py
src/SMESH_SWIG/smeshBuilder.py
src/SMESH_SWIG/smesh_algorithm.py
src/StdMeshers/CMakeLists.txt
src/StdMeshers/StdMeshers_CartesianParameters3D.cxx
src/StdMeshers/StdMeshers_CartesianParameters3D.hxx
src/StdMeshers/StdMeshers_Cartesian_3D.cxx
src/StdMeshers/StdMeshers_FaceSide.cxx
src/StdMeshers/StdMeshers_FaceSide.hxx
src/StdMeshers/StdMeshers_Geometric1D.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_Geometric1D.hxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_Hexa_3D.cxx
src/StdMeshers/StdMeshers_Prism_3D.cxx
src/StdMeshers/StdMeshers_Projection_2D.cxx
src/StdMeshers/StdMeshers_Propagation.cxx
src/StdMeshers/StdMeshers_Propagation.hxx
src/StdMeshers/StdMeshers_QuadrangleParams.cxx
src/StdMeshers/StdMeshers_QuadrangleParams.hxx
src/StdMeshers/StdMeshers_Quadrangle_2D.cxx
src/StdMeshers/StdMeshers_Quadrangle_2D.hxx
src/StdMeshers/StdMeshers_Regular_1D.cxx
src/StdMeshers/StdMeshers_Regular_1D.hxx
src/StdMeshers/StdMeshers_Reversible1D.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_Reversible1D.hxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_UseExisting_1D2D.cxx
src/StdMeshers/StdMeshers_ViscousLayers.cxx
src/StdMeshersGUI/StdMeshersGUI_CartesianParamCreator.cxx
src/StdMeshersGUI/StdMeshersGUI_CartesianParamCreator.h
src/StdMeshersGUI/StdMeshersGUI_StdHypothesisCreator.cxx
src/StdMeshersGUI/StdMeshers_images.ts
src/StdMeshersGUI/StdMeshers_msg_en.ts
src/StdMeshersGUI/StdMeshers_msg_fr.ts
src/StdMeshers_I/CMakeLists.txt
src/StdMeshers_I/StdMeshers_CartesianParameters3D_i.cxx
src/StdMeshers_I/StdMeshers_CartesianParameters3D_i.hxx
src/StdMeshers_I/StdMeshers_Geometric1D_i.cxx [new file with mode: 0644]
src/StdMeshers_I/StdMeshers_Geometric1D_i.hxx [new file with mode: 0644]
src/StdMeshers_I/StdMeshers_ObjRefUlils.cxx
src/StdMeshers_I/StdMeshers_ObjRefUlils.hxx
src/StdMeshers_I/StdMeshers_Propagation_i.cxx
src/StdMeshers_I/StdMeshers_Propagation_i.hxx
src/StdMeshers_I/StdMeshers_QuadrangleParams_i.cxx
src/StdMeshers_I/StdMeshers_QuadrangleParams_i.hxx
src/StdMeshers_I/StdMeshers_Reversible1D_i.cxx [new file with mode: 0644]
src/StdMeshers_I/StdMeshers_Reversible1D_i.hxx [new file with mode: 0644]
src/StdMeshers_I/StdMeshers_ViscousLayers_i.cxx
src/StdMeshers_I/StdMeshers_ViscousLayers_i.hxx
src/StdMeshers_I/StdMeshers_i.cxx

index 4bb75c56b3b45a5e8b3fd802f8a22bf0317bae16..1d5d281c8f798665d75b01154bb9912d3a0eadfe 100644 (file)
@@ -1,12 +1,11 @@
-# Arithmetic 1D
+# Arithmetic 1D and Geometric Progression
 
 import salome
 salome.salome_init()
-import GEOM
+
 from salome.geom import geomBuilder
 geompy = geomBuilder.New(salome.myStudy)
 
-import SMESH, SALOMEDS
 from salome.smesh import smeshBuilder
 smesh =  smeshBuilder.New(salome.myStudy)
 
@@ -21,12 +20,20 @@ hexa = smesh.Mesh(box, "Box : hexahedrical mesh")
 algo1D = hexa.Segment()
 
 # optionally reverse node distribution on certain edges
-allEdges = geompy.SubShapeAllSortedIDs( box, geompy.ShapeType["EDGE"])
+allEdges = geompy.SubShapeAllSorted( box, geompy.ShapeType["EDGE"])
 reversedEdges = [ allEdges[0], allEdges[4] ]
 
 # define "Arithmetic1D" hypothesis to cut all edges in several segments with increasing arithmetic length 
 algo1D.Arithmetic1D(1, 4, reversedEdges)
 
+# define "Geometric Progression" hypothesis on one edge to cut this edge in segments with length increasing by 20% starting from 1
+gpAlgo = hexa.Segment( allEdges[1] )
+gpAlgo.GeometricProgression( 1, 1.2 )
+
+# propagate distribution of nodes computed using "Geometric Progression" to parallel edges
+gpAlgo.PropagationOfDistribution() 
+
+
 # create a quadrangle 2D algorithm for faces
 hexa.Quadrangle()
 
index 34fcbc37789f885feaa07b77de169fbcf349c28b..3c877f3dae45e8a6edf4e58273178c8c17725508 100644 (file)
@@ -11,7 +11,8 @@ from salome.smesh import smeshBuilder
 smesh =  smeshBuilder.New(salome.myStudy)
 
 # create a box
-box = geompy.MakeBoxDXDYDZ(10., 10., 10.)
+base = geompy.MakeSketcher("Sketcher:F 0 0:TT 10 0:TT 20 10:TT 0 10:WF", theName="F")
+box  = geompy.MakePrismDXDYDZ( base, 0,0,10 )
 geompy.addToStudy(box, "Box")
 
 # get one edge of the box to put local hypothesis on
@@ -20,7 +21,7 @@ EdgeX = geompy.GetEdgeNearPoint(box, p5)
 geompy.addToStudyInFather(box, EdgeX, "Edge [0,0,0 - 10,0,0]")
 
 # create a hexahedral mesh on the box
-hexa = smesh.Mesh(box, "Box : hexahedrical mesh")
+hexa = smesh.Mesh(box, "Propagation of hypothesis")
 
 # set global algorithms and hypotheses
 algo1D = hexa.Segment()
@@ -28,15 +29,37 @@ hexa.Quadrangle()
 hexa.Hexahedron()
 algo1D.NumberOfSegments(4)
 
-# create a sub-mesh with local 1D hypothesis and propagation
+# create a sub-mesh with local 1D hypothesis and "Propagation of 1D Hypothesis"
 algo_local = hexa.Segment(EdgeX)
 
 # define "Arithmetic1D" hypothesis to cut an edge in several segments with increasing length
 algo_local.Arithmetic1D(1, 4)
 
-# define "Propagation" hypothesis that propagates all other 1D hypotheses
-# from all edges on the opposite side of a face in case of quadrangular faces
+# define "Propagation" hypothesis that propagates "Arithmetic1D" hypothesis
+# from 'EdgeX' on opposite sides of all quadilateral faces
 algo_local.Propagation()
 
-# compute the mesh
+# compute the mesh which contains prisms
 hexa.Compute()
+
+
+# create another mesh on the box
+mesh = smesh.Mesh(box, "Propagation of distribution of nodes")
+
+# set global algorithms and hypotheses
+algo1D = mesh.Segment()
+mesh.Quadrangle()
+mesh.Hexahedron()
+algo1D.NumberOfSegments(4)
+
+# create a sub-mesh with local 1D hypothesis and "Propagation of Node Distribution"
+algo_local = mesh.Segment(EdgeX)
+algo_local.Arithmetic1D(1, 4)
+
+# define "Propagation Of Distribution" hypothesis that propagates
+# distribution of nodes generated by "Arithmetic1D" hypothesis
+# from 'EdgeX' on opposite sides of all quadilateral faces
+algo_local.PropagationOfDistribution()
+
+# compute the mesh which contains hexahedra only
+mesh.Compute()
diff --git a/doc/salome/gui/SMESH/images/a-geometric1d.png b/doc/salome/gui/SMESH/images/a-geometric1d.png
new file mode 100644 (file)
index 0000000..a60be94
Binary files /dev/null and b/doc/salome/gui/SMESH/images/a-geometric1d.png differ
index 9c99303174b63c523c1b60e0786734da882b99af..717819138f562b963c2216308af12346e1f883cd 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/viscous_layers_hyp.png and b/doc/salome/gui/SMESH/images/viscous_layers_hyp.png differ
index 470fe0c4dcd70cb7fa1f0af3b7a45e1873046436..b992bc8e2e2d53ed1299e360af991aa6798b3e0a 100644 (file)
@@ -6,6 +6,7 @@
 <ul>
 <li>\ref adaptive_1d_anchor "Adaptive"</li>
 <li>\ref arithmetic_1d_anchor "Arithmetic 1D"</li>
+<li>\ref geometric_1d_anchor "Geometric Progression"</li>
 <li>\ref average_length_anchor "Local Length"</li>
 <li>\ref max_length_anchor "Max Size"</li>
 <li>\ref deflection_1d_anchor "Deflection 1D"</li>
@@ -55,7 +56,30 @@ picking them in the 3D viewer or by selecting the edges or groups of edges in th
 \image html b-ithmetic1d.png "Arithmetic 1D hypothesis - the size of mesh elements gradually increases"
 
 <b>See Also</b> a sample TUI Script of a 
-\ref tui_1d_arithmetic "Defining Arithmetic 1D hypothesis" operation.  
+\ref tui_1d_arithmetic "Defining Arithmetic 1D and Geometric Progression hypothesis" operation.  
+
+<br>
+\anchor geometric_1d_anchor
+<h2>Geometric Progression hypothesis</h2>
+
+<b>Geometric Progression</b> hypothesis allows to split edges into
+segments with a length that changes in geometric progression (Lk =
+Lk-1 * d) beginning from a given starting length and with a given
+common ratio.
+
+The direction of the splitting is defined by the orientation of the
+underlying geometrical edge. <b>"Reverse Edges"</b> list box allows to
+specify the edges for which the splitting should be made in the
+direction opposing to their orientation. This list box is enabled only
+if the geometry object is selected for the meshing. In this case the
+user can select edges to be reversed either directly picking them in
+the 3D viewer or by selecting the edges or groups of edges in the
+Object Browser. 
+
+\image html a-geometric1d.png
+
+<b>See Also</b> a sample TUI Script of a 
+\ref tui_1d_arithmetic "Defining Arithmetic 1D and Geometric Progression hypothesis" operation.  
 
 <br>
 \anchor deflection_1d_anchor
index 09768cc7cb2a6fc6c8ae86258edb61a869f02d6e..65d5c7ad0b24550bdb198ab9d10499364296cd4f 100644 (file)
@@ -20,6 +20,7 @@ In \b MESH there are the following Basic Hypotheses:
 <li>\ref max_length_anchor "Max Size"</li>
 <li>\ref adaptive_1d_anchor "Adaptive"</li>
 <li>\ref arithmetic_1d_anchor "Arithmetic 1D"</li>
+<li>\ref geometric_1d_anchor "Geometric 1D"</li>
 <li>\ref start_and_end_length_anchor "Start and end length"</li>
 <li>\ref deflection_1d_anchor "Deflection 1D"</li>
 <li>\ref automatic_length_anchor "Automatic Length"</li>
@@ -41,6 +42,7 @@ There also exist
 with other hypotheses:
 <ul>
 <li>\ref propagation_anchor "Propagation of 1D Hypothesis on opposite edges"</li>
+<li>\ref propagofdistribution_anchor "Propagation of Node Distribution on Opposite Edges"</li>
 <li>\ref viscous_layers_anchor "Viscous layers"</li>
 <li>\ref quadratic_mesh_anchor "Quadratic mesh"</li>
 <li>\ref non_conform_allowed_anchor "Non conform mesh allowed"</li>
index 938c7870e213fc7bea88e806c18154c993dcabf7..adccc49aadb51367b2a0bf94d3e4e0c797045cd1 100644 (file)
@@ -38,6 +38,19 @@ has been locally defined on the opposite edge.
 <br><b>See Also</b> a sample TUI Script of a 
 \ref tui_propagation "Propagation hypothesis" operation
 
+\anchor propagofdistribution_anchor
+<h2>Propagation of Node Distribution on Opposite Edges</h2>
+
+<b>Propagation of Node Distribution on Opposite Edges</b> allows to propagate
+distribution of nodes onto an opposite edge. If a local hypothesis and
+propagation are defined on an edge of a quadrangular face, the
+opposite edge will have the same number of nodes and the same
+relations between segment lengths, unless another hypothesis
+has been locally defined on the opposite edge.
+<br><b>See Also</b> a sample TUI Script of a 
+\ref tui_propagation "Propagation hypothesis" operation
+
 \anchor quadrangle_preference_anchor
 <h2>Quadrangle Preference</h2>
 
@@ -68,29 +81,29 @@ computations.
 <li><b>Number of layers</b> - defines the number of element layers.</li>
 <li><b>Stretch factor</b> - defines the growth factor of element height
   from the mesh boundary inwards.</li>
-<li><b>Specified Edges are</b> - defines how the shapes specified by
+<li><b>Specified Faces/Edges are</b> - defines how the shapes specified by
   the next parameter are used.
-<li><b>Faces without layers</b> and <b>Edges with/without layers</b> - 
-  in the 3D case it defines geometrical faces on which element layers
-  should not be constructed; in the 2D case it defines geometrical edges
-  on which element layers either should be or should not be
-  constructed, depending on the value of the previous parameter
-  (<b>Specified Edges are</b>). 
+<li><b> Faces/Edges with/without layers</b> - 
+  defines geometrical faces or edges on which element layers
+  either should be or should not be constructed, depending on the
+  value of the previous parameter (<b>Specified Faces/Edges are</b>). 
+  Faces (or edges) can be selected either in the Object Browser or in
+  the VTK Viewer.
   \note A mesh shown in the 3D Viewer can prevent selection of faces
   and edges, just hide the mesh to avoid this. 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>
 
-  Whatever shapes are specified by this
-  parameter, the element layers are not constructed on geometrical
-  faces shared by several solids in 3D case and edges shared by
-  several faces in 2D case. In other words the element layers can be
-  constructed on boundary faces and edges, and are not constructed on
-  internal faces and edges. There is an exception to this rule in 2D
-  case: if "Viscous Layers 2D" hypothesis is assigned to a sub-mesh,
-  the element layers can be constructed on boundary edges of the shape
-  of this sub-mesh.
+  If faces/edges without layers are specified, the element layers are
+  not constructed on geometrical faces shared by several solids in 3D
+  case and edges shared by several faces in 2D case. In other words,
+  in this mode the element layers can be constructed on boundary faces
+  and edges only, and are not constructed on internal faces and
+  edges. There is an exception to this rule: if a hypothesis is
+  assigned to a sub-mesh, the element layers can be constructed on
+  boundary faces/edges of the shape of this sub-mesh, at same time
+  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.
 
 </li>
@@ -101,5 +114,4 @@ computations.
 <br><b>See also</b> a sample TUI script of a \ref tui_viscous_layers
 "Viscous layers construction".
 
-
 */
index 333017d774aa8ca4d5a5bb9e834869528805f98e..863bf76e7e031d051e49937154b03c659820e22d 100644 (file)
@@ -9,6 +9,7 @@ This page provides example codes of \ref tui_defining_meshing_algos
   <ul>
     <li>\ref tui_1d_adaptive "Adaptive 1D" hypothesis</li>
     <li>\ref tui_1d_arithmetic "Arithmetic 1D" hypothesis</li>
+    <li>\ref tui_1d_arithmetic "Geometric Progression" hypothesis</li>
     <li>\ref tui_deflection_1d "Deflection 1D and Number of Segments" hypotheses</li>
     <li>\ref tui_start_and_end_length "Start and End Length" hypotheses</li>
     <li>\ref tui_average_length "Local Length"</li>
@@ -44,7 +45,7 @@ This page provides example codes of \ref tui_defining_meshing_algos
 
 <br>
 \anchor tui_1d_arithmetic
-<h3>Arithmetic 1D</h3>
+<h3>Arithmetic 1D and Geometric Progression</h3>
 \tui_script{defining_hypotheses_ex01.py}
 
 <br>
index 798475b30318eb0a013fc77ebdabaccfd1c90f38..186b066810f8dfa2267aaaa9ad1a16498a9e4fe1 100644 (file)
@@ -127,10 +127,36 @@ module StdMeshers
     double GetFineness();
   };
 
+  /*!
+   * Common inteface of 1D hypotheses that can be reversed
+   */
+  interface Reversible1D
+  {
+    /*!
+     * Set list of edges to reverse
+     */
+    void SetReversedEdges( in SMESH::long_array list );
+    
+    /*!
+     * Returns list of edges to reverse
+     */
+    SMESH::long_array GetReversedEdges();
+    
+    /*!
+     * Set entry of the main object
+     */
+    void SetObjectEntry( in string entry );
+    
+    /*!
+     * Get the entry of the main object
+     */
+    string GetObjectEntry();
+  };
+
   /*!
    * StdMeshers_NumberOfSegments: interface of "Nb. Segments" hypothesis
    */
-  interface StdMeshers_NumberOfSegments : SMESH::SMESH_Hypothesis
+  interface StdMeshers_NumberOfSegments : SMESH::SMESH_Hypothesis, Reversible1D
   {
     /*!
      * Builds and returns point distribution according to passed density function
@@ -209,32 +235,12 @@ module StdMeshers
      */
     long ConversionMode()
       raises (SALOME::SALOME_Exception);
-
-    /*!
-     * Set list of edges to reverse
-     */
-    void SetReversedEdges( in SMESH::long_array list );
-    
-    /*!
-     * Returns list of edges to reverse
-     */
-    SMESH::long_array GetReversedEdges();
-    
-    /*!
-     * Set entry of the main object
-     */
-    void SetObjectEntry( in string entry );
-    
-    /*!
-     * Get the entry of the main object
-     */
-    string GetObjectEntry();
   };
 
   /*!
    * StdMeshers_Arithmetic1D: interface of "Arithmetic 1D" hypothesis
    */
-  interface StdMeshers_Arithmetic1D : SMESH::SMESH_Hypothesis
+  interface StdMeshers_Arithmetic1D : SMESH::SMESH_Hypothesis, Reversible1D
   {
     /*!
      * Sets <start segment length> or <end segment length> parameter value
@@ -260,26 +266,36 @@ module StdMeshers
      * Returns <start segment length> or <end segment length> parameter value
      */
     double GetLength(in boolean isStartLength);
-    
+
+  };
+
+  /*!
+   * StdMeshers_Arithmetic1D: interface of "Geometric 1D" hypothesis
+   */
+  interface StdMeshers_Geometric1D : SMESH::SMESH_Hypothesis, Reversible1D
+  {
     /*!
-     * Set list of edges to reverse
+     * Sets length of the first segment
      */
-    void SetReversedEdges( in SMESH::long_array list );
-    
+    void SetStartLength(in double length) 
+      raises (SALOME::SALOME_Exception);
+
     /*!
-     * Returns list of edges to reverse
+     * Sets value of Common Ratio
      */
-    SMESH::long_array GetReversedEdges();
-    
+    void SetCommonRatio(in double factor)
+      raises (SALOME::SALOME_Exception);
+
     /*!
-     * Set entry of the main object
+     * Returns length of the first segment
      */
-    void SetObjectEntry( in string entry );
-    
+    double GetStartLength();
+
     /*!
-     * Get the entry of the main object
+     * Returns value of Common Ratio
      */
-    string GetObjectEntry();
+    double GetCommonRatio();
+
   };
 
   /*!
@@ -319,7 +335,7 @@ module StdMeshers
   /*!
    * StdMeshers_StartEndLength: interface of "Start and End Length" hypothesis
    */
-  interface StdMeshers_StartEndLength : SMESH::SMESH_Hypothesis
+  interface StdMeshers_StartEndLength : SMESH::SMESH_Hypothesis, Reversible1D
   {
     /*!
      * Sets <start segment length> or <end segment length> parameter value
@@ -346,25 +362,6 @@ module StdMeshers
      */
     double GetLength(in boolean isStartLength);
 
-    /*!
-     * Set list of edges to reverse
-     */
-    void SetReversedEdges( in SMESH::long_array list );
-    
-    /*!
-     * Returns list of edges to reverse
-     */
-    SMESH::long_array GetReversedEdges();
-    
-    /*!
-     * Set entry of the main object
-     */
-    void SetObjectEntry( in string entry );
-    
-    /*!
-     * Get the entry of the main object
-     */
-    string GetObjectEntry();
   };
 
 
@@ -388,7 +385,7 @@ module StdMeshers
   /*!
    * StdMeshers_FixedPoints1D: interface of "Fixed points 1D" hypothesis
    */
-  interface StdMeshers_FixedPoints1D : SMESH::SMESH_Hypothesis
+  interface StdMeshers_FixedPoints1D : SMESH::SMESH_Hypothesis, Reversible1D
   {
     /*!
      * Sets some points on edge using parameter on curve from 0 to 1
@@ -410,26 +407,7 @@ module StdMeshers
      * Returns list of numbers of segments
      */
     SMESH::long_array GetNbSegments();
-    
-    /*!
-     * Set list of edges to reverse
-     */
-    void SetReversedEdges( in SMESH::long_array list );
-    
-    /*!
-     * Returns list of edges to reverse
-     */
-    SMESH::long_array GetReversedEdges();
-    
-    /*!
-     * Set entry of the main object
-     */
-    void SetObjectEntry( in string entry );
-    
-    /*!
-     * Get the entry of the main object
-     */
-    string GetObjectEntry();
+
   };
 
   /*!
@@ -483,7 +461,8 @@ module StdMeshers
   };
 
   /*!
-   * StdMeshers_Propagation: interface of "Propagation" hypothesis.
+   * StdMeshers_Propagation: interface of "Propagation of 1D Hyp. on
+   * Opposite Edges" hypothesis.
    * Presence of this hypothesis on any edge propagates any other 1D
    * hypothesis from this edge on all edges, opposite to it.
    * It concerns only edges of quadrangle faces.
@@ -492,6 +471,17 @@ module StdMeshers
   {
   };
 
+  /*!
+   * StdMeshers_Propagation: interface of "Propagation of Node
+   * Distribution on Opposite Edges" hypothesis.
+   * Presence of this hypothesis on any edge propagates distribution of nodes
+   * from this edge on all edges, opposite to it.
+   * It concerns only edges of quadrangle faces.
+   */
+  interface StdMeshers_PropagOfDistribution : SMESH::SMESH_Hypothesis
+  {
+  };
+
   /*!
    * StdMeshers_QuadranglePreference: interface of "QuadranglePreference" hypothesis.
    * This hypothesis is used by StdMeshers_Quadrangle_2D algorithm.
@@ -807,6 +797,22 @@ module StdMeshers
      * Get the type of quadrangulation
      */
     QuadType GetQuadType();
+
+    /*!
+     * Set positions of enforced nodes
+     */
+    void SetEnforcedNodes(in GEOM::ListOfGO vertices, in SMESH::nodes_array points)
+      raises (SALOME::SALOME_Exception);
+
+    /*!
+     * Returns positions of enforced nodes
+     */
+    void GetEnforcedNodes(out GEOM::ListOfGO vertices, out SMESH::nodes_array points);
+
+    /*!
+     * Returns entries of shapes defining enforced nodes
+     */
+    SMESH::string_array GetEnfVertices();
   };
 
   /*!
@@ -865,6 +871,14 @@ module StdMeshers
     void SetIgnoreFaces(in SMESH::long_array faceIDs) raises (SALOME::SALOME_Exception);
     SMESH::long_array GetIgnoreFaces();
 
+    /*!
+     * Set faces either to exclude from treatment or to make the Viscous Layers on.
+     */
+    void SetFaces(in SMESH::long_array faceIDs,
+                  in boolean           toIgnore) raises (SALOME::SALOME_Exception);
+    SMESH::long_array GetFaces();
+    boolean           GetIsToIgnoreFaces();
+
     /*!
      * Set total thickness of layers of prisms
      */
@@ -936,7 +950,7 @@ module StdMeshers
     /*!
      * Set size threshold. A polyhedral cell got by cutting an initial
      * hexahedron by geometry boundary is considered small and is removed if
-     * it's size is \athreshold times less than the size of the initial hexahedron. 
+     * it's size is \a threshold times less than the size of the initial hexahedron. 
      * threshold must be > 1.0
      */
     void SetSizeThreshold(in double threshold) raises (SALOME::SALOME_Exception);
@@ -971,6 +985,13 @@ module StdMeshers
     void GetGridSpacing(out SMESH::string_array spaceFunctions,
                         out SMESH::double_array internalPoints,
                         in short                axis) raises (SALOME::SALOME_Exception);
+    /*!
+     * Enables implementation of geometrical edges into the mesh. If this feature
+     * is disabled, sharp edges of the shape are lost ("smoothed") in the mesh if
+     * they don't coincide with the grid lines
+     */
+    void SetToAddEdges(in boolean toAdd);
+    boolean GetToAddEdges();
 
     /*!
      * \brief Computes node coordinates by spacing functions
@@ -978,13 +999,15 @@ module StdMeshers
      *  \param x1 - upper coordinate
      *  \param spaceFuns - space functions
      *  \param points - internal points
-     *  \param coords - the computed coordinates
+     *  \param axisName - e.g. "X"
+     *  \return the computed coordinates
      */
     SMESH::double_array ComputeCoordinates(in double              x0,
                                            in double              x1,
                                            in SMESH::string_array spaceFuns,
                                            in SMESH::double_array points,
-                                           in string              axisName ) raises (SALOME::SALOME_Exception);
+                                           in string              axisName ) 
+      raises (SALOME::SALOME_Exception);
   };
 
   /*!
index fb85b15af69d8137c4083069867938990e1ab2d7..ff60e68addfeb99c2097d0bc9d314d6c444dac1e 100644 (file)
@@ -925,6 +925,11 @@ module SMESH
      */
     long_array GetElemFaceNodes(in long elemId, in short faceIndex);
 
+    /*!
+     * Returns three components of normal of given mesh face (or an empty array in KO case)
+     */
+    double_array GetFaceNormal(in long faceId);
+
     /*!
      * Returns an element based on all given nodes.
      */
index d80b4e7d997f9004e31774b651f44cd1cbff54a9..d6f6527b673c12940f03a821817b69d3c24a6ce8 100644 (file)
                 icon-id  ="mesh_hypo_length.png"
                 dim      ="1"/>
 
+    <hypothesis type     ="GeometricProgression"
+                label-id ="Geometric Progression"
+                icon-id  ="mesh_hypo_length.png"
+                dim      ="1"/>
+
     <hypothesis type     ="FixedPoints1D"
                 label-id ="Fixed Points 1D"
                 icon-id  ="mesh_hypo_length.png"
                 dim      ="1"
                 auxiliary="true"/>
 
+    <hypothesis type     ="PropagOfDistribution"
+                label-id ="Propagation of Node Distribution on Opposite Edges"
+                icon-id  ="mesh_hypo_length.png"
+                dim      ="1"
+                auxiliary="true"/>
+
     <hypothesis type     ="AutomaticLength"
                 label-id ="Automatic Length"
                 icon-id  ="mesh_hypo_length.png"
     <algorithm type     ="Regular_1D"
               label-id ="Wire Discretisation"
               icon-id  ="mesh_algo_regular.png"
-               hypos    ="Adaptive1D,LocalLength,MaxLength,Arithmetic1D,StartEndLength,NumberOfSegments,Deflection1D,AutomaticLength,FixedPoints1D"
-               opt-hypos="Propagation,QuadraticMesh"
+               hypos    ="Adaptive1D,LocalLength,MaxLength,Arithmetic1D,GeometricProgression,StartEndLength,NumberOfSegments,Deflection1D,AutomaticLength,FixedPoints1D"
+               opt-hypos="Propagation,PropagOfDistribution,QuadraticMesh"
                input    ="VERTEX"
                output   ="EDGE"
                dim      ="1">
         <hypo>LocalLength=LocalLength(SetLength(1),,SetPrecision(1))</hypo>
         <hypo>MaxLength=MaxSize(SetLength(1))</hypo>
         <hypo>Arithmetic1D=Arithmetic1D(SetStartLength(),SetEndLength(),SetReversedEdges())</hypo>
+        <hypo>GeometricProgression=GeometricProgression(SetStartLength(),SetCommonRatio(),SetReversedEdges())</hypo>
         <hypo>StartEndLength=StartEndLength(SetStartLength(),SetEndLength(),SetReversedEdges())</hypo>
         <hypo>Deflection1D=Deflection1D(SetDeflection())</hypo>
         <hypo>Adaptive1D=Adaptive(SetMinSize(),SetMaxSize(),SetDeflection())</hypo>
         <hypo>AutomaticLength=AutomaticLength(SetFineness())</hypo>
         <hypo>FixedPoints1D=FixedPoints1D(SetPoints(),SetNbSegments(),SetReversedEdges())</hypo>
         <hypo>Propagation=Propagation()</hypo>
+        <hypo>PropagOfDistribution=PropagationOfDistribution()</hypo>
         <hypo>QuadraticMesh=QuadraticMesh()</hypo>
       </python-wrap>
     </algorithm>
     <algorithm type     ="CompositeSegment_1D"
               label-id ="Composite Side Discretisation"
               icon-id  ="mesh_algo_regular.png"
-               hypos    ="Adaptive1D,LocalLength,MaxLength,Arithmetic1D,StartEndLength,NumberOfSegments,Deflection1D,AutomaticLength,FixedPoints1D"
-               opt-hypos="Propagation,QuadraticMesh"
+               hypos    ="Adaptive1D,LocalLength,MaxLength,Arithmetic1D,GeometricProgression,StartEndLength,NumberOfSegments,Deflection1D,AutomaticLength,FixedPoints1D"
+               opt-hypos="Propagation,PropagOfDistribution,QuadraticMesh"
                input    ="VERTEX"
                output   ="EDGE"
                dim      ="1">
         <hypo>LocalLength=LocalLength(SetLength(), ,SetPrecision())</hypo>
         <hypo>MaxLength=MaxSize(SetLength())</hypo>
         <hypo>Arithmetic1D=Arithmetic1D(SetStartLength(),SetEndLength(),SetReversedEdges())</hypo>
+        <hypo>GeometricProgression=GeometricProgression(SetStartLength(),SetCommonRatio(),SetReversedEdges())</hypo>
         <hypo>StartEndLength=StartEndLength(SetStartLength(),SetEndLength(),SetReversedEdges())</hypo>
         <hypo>Deflection1D=Deflection1D(SetDeflection())</hypo>
         <hypo>Adaptive1D=Adaptive(SetMinSize(),SetMaxSize(),SetDeflection())</hypo>
         <hypo>AutomaticLength=AutomaticLength(SetFineness())</hypo>
         <hypo>FixedPoints1D=FixedPoints1D(SetPoints(),SetNbSegments(),SetReversedEdges())</hypo>
         <hypo>Propagation=Propagation()</hypo>
+        <hypo>PropagOfDistribution=PropagationOfDistribution()</hypo>
         <hypo>QuadraticMesh=QuadraticMesh()</hypo>
       </python-wrap>
     </algorithm>
                label-id ="Hexahedron (i,j,k)"
                icon-id  ="mesh_algo_hexa.png"
                input    ="QUAD"
+               output   ="HEXA,PENTA"
               need-geom="false"
                opt-hypos="ViscousLayers"
                dim      ="3">
                label-id="3D Extrusion"
                icon-id ="mesh_algo_hexa.png"
                input   ="QUAD,TRIA"
+               output  ="HEXA,PENTA,OCTA,POLYHEDRON"
                dim     ="3">
       <python-wrap>
         <algo>Prism_3D=Prism()</algo>
                icon-id ="mesh_algo_hexa.png"
                hypos   ="NumberOfLayers, LayerDistribution"
                input   ="QUAD,TRIA"
+               output  ="HEXA,PENTA,OCTA,POLYHEDRON"
                dim     ="3">
       <python-wrap>
         <algo>RadialPrism_3D=Prism('RadialPrism_3D')</algo>
                icon-id ="mesh_algo_quad.png"
                hypos   ="NumberOfLayers2D, LayerDistribution2D"
                input   ="EDGE"
-               output  ="QUAD,TRIA"
+               output  ="QUAD"
                dim     ="2">
       <python-wrap>
         <algo>RadialQuadrangle_1D2D=Quadrangle(algo=smeshBuilder.RADIAL_QUAD)</algo>
                icon-id          ="mesh_algo_hexa.png"
                hypos            ="CartesianParameters3D"
                support-submeshes="false"
+               output           ="HEXA"
                dim              ="3">
       <python-wrap>
         <algo>Cartesian_3D=BodyFitted()</algo>
index 19a1e4b0916dee1a2e9fb8b251008e6287959381..8beda034e2fc3fedfdceb0efe6a1ef87f09ebccb 100644 (file)
@@ -410,7 +410,7 @@ bool SMESH_Algo::GetSortedNodesOnEdge(const SMESHDS_Mesh*                   theM
     return false;
 
   SMESHDS_SubMesh * eSubMesh = theMesh->MeshElements( theEdge );
-  if ( !eSubMesh || !eSubMesh->GetElements()->more() )
+  if ( !eSubMesh || ( eSubMesh->NbElements()==0 && eSubMesh->NbNodes() == 0))
     return false; // edge is not meshed
 
   int nbNodes = 0;
index b7d8759e9dc2b56710b655bbf2f07288cd6f0142..06f247009317d9c124714536411ce6d7063e953b 100644 (file)
@@ -896,7 +896,7 @@ bool SMESH_MesherHelper::CheckNodeU(const TopoDS_Edge&   E,
                                     const bool           force,
                                     double               distXYZ[4]) const
 {
-  int shapeID = n->getshapeId();
+  int  shapeID = n->getshapeId();
   bool infinit = Precision::IsInfinite( u );
   if ( force || toCheckPosOnShape( shapeID ) || infinit )
   {
index 63e6f365fec9b754dcd2b74514a75e0a0ccd3688..5d0f5e536984c7ffdf44aedda7ba2f0a95feb98c 100644 (file)
@@ -2641,10 +2641,10 @@ bool SMESH_Pattern::Apply (const SMDS_MeshFace* theFace,
 
   list< const SMDS_MeshNode* > nodes;
   list< const SMDS_MeshNode* >::iterator n = nodes.end();
-  SMDS_ElemIteratorPtr noIt = theFace->nodesIterator();
+  SMDS_NodeIteratorPtr noIt = theFace->nodeIterator();
   int iSub = 0;
   while ( noIt->more() && iSub < nbFaceNodes ) {
-    const SMDS_MeshNode* node = smdsNode( noIt->next() );
+    const SMDS_MeshNode* node = noIt->next();
     nodes.push_back( node );
     if ( iSub++ == theNodeIndexOnKeyPoint1 )
       n = --nodes.end();
@@ -2661,7 +2661,7 @@ bool SMESH_Pattern::Apply (const SMDS_MeshFace* theFace,
   list< gp_XYZ > xyzList;
   myOrderedNodes.resize( nbFaceNodes );
   for ( iSub = 0, n = nodes.begin(); n != nodes.end(); ++n ) {
-    xyzList.push_back( gp_XYZ( (*n)->X(), (*n)->Y(), (*n)->Z() ));
+    xyzList.push_back( SMESH_TNodeXYZ( *n ));
     myOrderedNodes[ iSub++] = *n;
   }
 
@@ -2963,11 +2963,6 @@ bool SMESH_Pattern::Apply (SMESH_Mesh*                     theMesh,
   myXYZ.resize( myPoints.size() * theFaces.size(), undefinedXYZ() );
   myElements.reserve( theFaces.size() );
 
-  // to find point index
-  map< TPoint*, int > pointIndex;
-  for ( int i = 0; i < myPoints.size(); i++ )
-    pointIndex.insert( make_pair( & myPoints[ i ], i ));
-
   int ind1 = 0; // lowest point index for a face
 
   // meshed geometry
@@ -3019,7 +3014,7 @@ bool SMESH_Pattern::Apply (SMESH_Mesh*                     theMesh,
     {
       list< TPoint* > & linkPoints = getShapePoints( eID++ );
       const SMDS_MeshNode* n1 = myOrderedNodes[ i ];
-      const SMDS_MeshNode* n2 = myOrderedNodes[ i + 1 == nbNodes ? 0 : i + 1 ];
+      const SMDS_MeshNode* n2 = myOrderedNodes[( i+1 ) % nbNodes ];
       // make a link and a node set
       TNodeSet linkSet, node1Set;
       linkSet.insert( n1 );
@@ -3028,7 +3023,7 @@ bool SMESH_Pattern::Apply (SMESH_Mesh*                     theMesh,
       list< TPoint* >::iterator p = linkPoints.begin();
       {
         // map the first link point to n1
-        int nId = pointIndex[ *p ] + ind1;
+        int nId = ( *p - &myPoints[0] ) + ind1;
         myXYZIdToNodeMap[ nId ] = n1;
         list< list< int > >& groups = myIdsOnBoundary[ node1Set ];
         groups.push_back(list< int > ());
@@ -3040,7 +3035,7 @@ bool SMESH_Pattern::Apply (SMESH_Mesh*                     theMesh,
       list< int >& indList = groups.back();
       // add points to the map excluding the end points
       for ( p++; *p != linkPoints.back(); p++ )
-        indList.push_back( pointIndex[ *p ] + ind1 );
+        indList.push_back( ( *p - &myPoints[0] ) + ind1 );
     }
     ind1 += myPoints.size();
   }
@@ -3443,7 +3438,7 @@ void SMESH_Pattern::mergePoints (const bool uniteGroups)
       Bnd_Box box;
       TNodeSet::const_iterator n = nodes.begin();
       for ( ; n != nodes.end(); ++n )
-        box.Add( gp_Pnt( (*n)->X(), (*n)->Y(), (*n)->Z() ));
+        box.Add( gp_Pnt( SMESH_TNodeXYZ( *n )));
       double x, y, z, X, Y, Z;
       box.Get( x, y, z, X, Y, Z );
       gp_Pnt p( x, y, z ), P( X, Y, Z );
@@ -3454,7 +3449,7 @@ void SMESH_Pattern::mergePoints (const bool uniteGroups)
     bool unite = ( uniteGroups && nodes.size() == 2 );
     map< double, int > distIndMap;
     const SMDS_MeshNode* node = *nodes.begin();
-    gp_Pnt P( node->X(), node->Y(), node->Z() );
+    gp_Pnt P = SMESH_TNodeXYZ( node );
 
     // compare points, replace indices
 
@@ -3928,32 +3923,142 @@ bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh,
                                              myXYZ[ i ].Y(),
                                              myXYZ[ i ].Z());
     }
-  }
+    if ( theMesh->HasShapeToMesh() )
+    {
+      // set nodes on EDGEs (IMP 22368)
+      SMESH_MesherHelper helper( *theMesh );
+      helper.ToFixNodeParameters( true );
+      map< TNodeSet, list< list< int > > >::iterator idListIt = myIdsOnBoundary.begin();
+      for ( ; idListIt != myIdsOnBoundary.end(); idListIt++ )
+      {
+        list<list< int > >& groups = idListIt->second;
+        const TNodeSet&      nodes = idListIt->first;
+        if ( nodes.size() != 2 )
+          continue; // not a link
+        const SMDS_MeshNode* n1 = *nodes.begin();
+        const SMDS_MeshNode* n2 = *nodes.rbegin();
+        TopoDS_Shape S1 = helper.GetSubShapeByNode( n1, aMeshDS );
+        TopoDS_Shape S2 = helper.GetSubShapeByNode( n2, aMeshDS );
+        if ( S1.IsNull() || S1.ShapeType() < TopAbs_EDGE ||
+             S2.IsNull() || S2.ShapeType() < TopAbs_EDGE )
+          continue;
+        TopoDS_Shape S;
+        if ( S1.ShapeType() == TopAbs_EDGE )
+        {
+          if ( S1 == S2 || helper.IsSubShape( S2, S1 ))
+            S = S1;
+        }
+        else if ( S2.ShapeType() == TopAbs_EDGE )
+        {
+          if ( helper.IsSubShape( S1, S2 ))
+            S = S2;
+        }
+        else
+        {
+          S = helper.GetCommonAncestor( S1, S2, *theMesh, TopAbs_EDGE );
+        } 
+        if ( S.IsNull() )
+          continue;
+        const TopoDS_Edge & E = TopoDS::Edge( S );
+        helper.SetSubShape( E );
+        list<list< int > >::iterator g = groups.begin();
+        for ( ; g != groups.end(); ++g )
+        {
+          list< int >& ids = *g;
+          list< int >::iterator id = ids.begin();
+          for ( ; id != ids.end(); ++id )
+            if ( nodesVector[ *id ] && nodesVector[ *id ]->getshapeId() < 1 )
+            {
+              double u = 1e100;
+              aMeshDS->SetNodeOnEdge( nodesVector[ *id ], E, u );
+              helper.CheckNodeU( E, nodesVector[ *id ], u, 1e-7, true );
+            }
+        }
+      }
+    }
+  }  // if ( onMeshElements )
+
   else
   {
     nodesVector.resize( myPoints.size(), 0 );
 
-    // to find point index
-    map< TPoint*, int > pointIndex;
-    for ( int i = 0; i < myPoints.size(); i++ )
-      pointIndex.insert( make_pair( & myPoints[ i ], i ));
+    // 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;
+          while ( u2n != u2nEnd && pItF != points.end() )
+          {
+            const double         u = u2n->first;
+            const SMDS_MeshNode* n = u2n->second;
+            const double       tol = ( (++u2n)->first - u ) / 20;
+            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
-    map< int, list< TPoint* > >::iterator idPointIt = myShapeIDToPointsMap.begin();
+    idPointIt = myShapeIDToPointsMap.begin();
     for ( ; idPointIt != myShapeIDToPointsMap.end(); idPointIt++ )
     {
       TopoDS_Shape S;
-      //SMESHDS_SubMesh * subMeshDS = 0;
       if ( !myShapeIDMap.IsEmpty() ) {
         S = myShapeIDMap( idPointIt->first );
-        //subMeshDS = aMeshDS->MeshElements( S );
       }
       list< TPoint* > & points = idPointIt->second;
       list< TPoint* >::iterator pIt = points.begin();
       for ( ; pIt != points.end(); pIt++ )
       {
         TPoint* point = *pIt;
-        int pIndex = pointIndex[ point ];
+        //int pIndex = pointIndex[ point ];
+        int pIndex = point - &myPoints[0];
         if ( nodesVector [ pIndex ] )
           continue;
         SMDS_MeshNode* node = aMeshDS->AddNode (point->myXYZ.X(),
@@ -4148,8 +4253,9 @@ void SMESH_Pattern::createElements(SMESH_Mesh*                            theMes
         SMDS_ElemIteratorPtr noIt = elem->nodesIterator();
         while ( noIt->more() ) {
           SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>(smdsNode( noIt->next() ));
-          if (!node->getshapeId() &&
-              shellNodes.find( node ) == shellNodes.end() ) {
+          if ( node->getshapeId() < 1 &&
+               shellNodes.find( node ) == shellNodes.end() )
+          {
             if ( S.ShapeType() == TopAbs_FACE )
               aMeshDS->SetNodeOnFace( node, shapeID,
                                       Precision::Infinite(),// <- it's a sign that UV is not set
index b2606e46382521a200fbd38ebd850be139725953..b57624c2d7c91d8b3eacd857c545d57164c0b5e9 100644 (file)
@@ -356,7 +356,7 @@ private:
   // all functions assure that shapes are indexed so that first go
   // ordered vertices, then ordered edge, then faces and maybe a shell
   TopTools_IndexedMapOfOrientedShape   myShapeIDMap;
-  std::map< int, std::list< TPoint* > >     myShapeIDToPointsMap;
+  std::map< int, std::list< TPoint*> > myShapeIDToPointsMap;
 
   // for the 2d case:
   // nb of key-points in each of pattern boundaries
index fa9add8e0b6a73cffd1ccfe5c1feb9e8bccb49ec..e8ebeea2509dfa5c9af015401730ce9f719a7c60 100644 (file)
@@ -551,6 +551,8 @@ QString SMESHGUI_GenericHypothesisCreator::helpPage() const
     aHelpFileName = "a1d_meshing_hypo_page.html#max_length_anchor";
   else if ( aHypType == "Arithmetic1D")
     aHelpFileName = "a1d_meshing_hypo_page.html#arithmetic_1d_anchor";
+  else if ( aHypType == "GeometricProgression")
+    aHelpFileName = "a1d_meshing_hypo_page.html#geometric_1d_anchor";
   else if ( aHypType == "FixedPoints1D")
     aHelpFileName = "a1d_meshing_hypo_page.html#fixed_points_1d_anchor";
   else if ( aHypType == "MaxElementArea")
index 2d45966ed0e57c053497f9b1af845a4817ba8d18..58003954a6ff4cf0d17aa303fed10166e9a85bbe 100644 (file)
@@ -296,24 +296,45 @@ namespace SMESH
   }
 
 
-  QStringList GetHypothesesSets(int maxDim)
+  QStringList GetHypothesesSets(int maxDim, const QString& MeshType)
   {
     QStringList aSetNameList;
 
     // Init list of available hypotheses, if needed
     InitAvailableHypotheses();
-
     QList<HypothesesSet*>::iterator hypoSet;
-    for ( hypoSet  = myListOfHypothesesSets.begin(); 
+    for ( hypoSet  = myListOfHypothesesSets.begin();
           hypoSet != myListOfHypothesesSets.end();
           ++hypoSet ) {
       HypothesesSet* aSet = *hypoSet;
-      if ( aSet &&
-           ( aSet->count( true ) || aSet->count( false )) &&
-           aSet->maxDim() <= maxDim)
+      bool isAvailable = false;
+      if ( !MeshType.isEmpty() )
+      {
+        if ( aSet->maxDim() != maxDim)
+          continue;
+        aSet->init( true );
+        while ( aSet->next(), aSet->more() )
+        {
+          if ( HypothesisData* hypData = SMESH::GetHypothesisData( aSet->current() ) )
+          {
+            QStringList::const_iterator inElemType = hypData->OutputTypes.begin();
+            for ( ; inElemType != hypData->OutputTypes.end(); inElemType++ )
+            {
+              if ( *inElemType == MeshType ){
+                isAvailable = true;
+                break;
+              }
+            }
+          }
+          if ( isAvailable ) break;
+        }
+      }
+      else if ( aSet && ( aSet->count( true ) || aSet->count( false )) &&
+                aSet->maxDim() <= maxDim)
       {
-        aSetNameList.append( mangledHypoSetName( aSet ));
+        isAvailable = true;
       }
+      if ( isAvailable ) aSetNameList.append( mangledHypoSetName( aSet ));
     }
     aSetNameList.removeDuplicates();
     aSetNameList.sort();
index a2c12f5950f83be89e43e13801bd9dccd7ffcdc3..333418b317612e592dd0dc44738b9f21fee30fba 100644 (file)
@@ -71,7 +71,7 @@ namespace SMESH
                                       const bool = false,
                                       const bool = true);
   SMESHGUI_EXPORT
-  QStringList GetHypothesesSets( int maxDim );
+  QStringList GetHypothesesSets( int, const QString& );
 
   SMESHGUI_EXPORT
   HypothesesSet* GetHypothesesSet( const QString& );
index 4b030bbc0025a2e8904db42b24f56794fc2273f6..94d9ce681cceee02ec7c919312b68995647f6de7 100644 (file)
@@ -364,6 +364,9 @@ SMESHGUI_MeshDlg::SMESHGUI_MeshDlg( const bool theToCreate, const bool theIsMesh
   // geometry
   createObject( tr( "GEOMETRY" ), mainFrame(), Geom );
   myGeomPopup = 0;
+  // mesh type
+  QLabel* anMeshTypeLbl = new QLabel( tr( "MESH_TYPE" ), this );
+  myMeshType = new QComboBox( this );
   
   // Create tab widget
   
@@ -398,10 +401,16 @@ SMESHGUI_MeshDlg::SMESHGUI_MeshDlg( const bool theToCreate, const bool theIsMesh
   aLay->addWidget( objectWg( Geom, Label ),   2, 0 );
   aLay->addWidget( objectWg( Geom, Btn ),     2, 1 );
   aLay->addWidget( objectWg( Geom, Control ), 2, 2 );
-  aLay->addWidget( myTabWg,                   4, 0, 1, 3 );
-  aLay->addWidget( myHypoSetButton,           5, 0, 1, 3 );
+  aLay->addWidget( anMeshTypeLbl,             3, 0 );
+  aLay->addWidget( myMeshType,                3, 2 );
+  aLay->addWidget( myTabWg,                   5, 0, 1, 3 );
+  aLay->addWidget( myHypoSetButton,           6, 0, 1, 3 );
   aLay->setRowMinimumHeight( 3, 20 );
 
+  myMeshType->clear();
+
+  // Connect signals and slots
+  connect( myMeshType, SIGNAL( activated( int ) ), SLOT( onChangedMeshType( int ) ) );
   // Disable controls if necessary
   setObjectShown( Mesh, false );
   if ( theToCreate )
@@ -615,3 +624,36 @@ int SMESHGUI_MeshDlg::getActiveObject()
       return i;
   return -1;
 }
+//================================================================================
+/*!
+ * \brief Sets available types of mesh
+ * \param theTypeMesh - list of available types of mesh
+ */
+//================================================================================
+void SMESHGUI_MeshDlg::setAvailableMeshType( const QStringList& theTypeMesh )
+{
+  myMeshType->clear();
+  myMeshType->addItems(theTypeMesh);
+}
+//================================================================================
+/*!
+ * \brief Emits selectMeshType( const int, const int ) signal
+ *
+ * SLOT is called when a combo box "mesh type" is selected.
+ */
+//================================================================================
+void SMESHGUI_MeshDlg::onChangedMeshType( const int isIndex )
+{
+  emit selectMeshType( Dim3D - myTabWg->currentIndex(), isIndex );
+}
+//================================================================================
+/*!
+ * \brief Get current index types of mesh
+ */
+//================================================================================
+int SMESHGUI_MeshDlg::currentMeshType( )
+{
+  return myMeshType->currentIndex( );
+}
+
+
index 6ba8e6cb94c0f5cc34998266c1d6ccb283021264..08f11ff6fee6755b3418db23aaeaaf5b38d23aff 100644 (file)
@@ -74,21 +74,26 @@ public:
   void                         enableTab(const int);
   bool                         isTabEnabled(const int) const;
   int                          getActiveObject();
+  void                         setAvailableMeshType(const QStringList& );
+  int                          currentMeshType();
 
 signals:
   void                         hypoSet( const QString& );
   void                         geomSelectionByMesh( bool );
+  void                         selectMeshType( const int, const int );
 
 private slots:  
   void                         onHypoSetPopup( QAction* );
   void                         onGeomPopup( QAction* );
   void                         onGeomSelectionButton( bool );
+  void                         onChangedMeshType( const int );
 
 private:
   QMap<int, SMESHGUI_MeshTab*> myTabs;
   QTabWidget*                  myTabWg;
   QToolButton*                 myHypoSetButton;
   QMenu*                       myGeomPopup;
+  QComboBox*                   myMeshType;
 };
 
 /*!
index 62a5c4b74c2118780fbf3076eb71e228ac25a159..eb0a30ed7404c011882de86d866b5829cf0bf8d9 100644 (file)
@@ -95,6 +95,7 @@ SMESHGUI_MeshOp::SMESHGUI_MeshOp( const bool theToCreate, const bool theIsMesh )
   if ( GeometryGUI::GetGeomGen()->_is_nil() )// check that GEOM_Gen exists
     GeometryGUI::InitGeomGen();
   myIsOnGeometry = true;
+  myMaxShapeDim = -1;
 }
 
 //================================================================================
@@ -211,14 +212,13 @@ void SMESHGUI_MeshOp::startOperation()
     }
     connect( myDlg, SIGNAL( hypoSet( const QString& )), SLOT( onHypoSet( const QString& )));
     connect( myDlg, SIGNAL( geomSelectionByMesh( bool )), SLOT( onGeomSelectionByMesh( bool )));
-
+    connect( myDlg, SIGNAL( selectMeshType( const int, const int ) ), SLOT( onAlgoSetByMeshType( const int, const int)));
     if ( myToCreate )
       if ( myIsMesh ) myHelpFileName = "constructing_meshes_page.html";
       else myHelpFileName = "constructing_submeshes_page.html";
     else myHelpFileName = "editing_meshes_page.html";
   }
   SMESHGUI_SelectionOp::startOperation();
-
   // iterate through dimensions and get available algoritms, set them to the dialog
   _PTR(SComponent) aFather = SMESH::GetActiveStudyDocument()->FindComponent( "SMESH" );
   for ( int i = SMESH::DIM_0D; i <= SMESH::DIM_3D; i++ )
@@ -245,6 +245,11 @@ void SMESHGUI_MeshOp::startOperation()
     myDlg->activateObject( SMESHGUI_MeshDlg::Obj );
 
   myDlg->setCurrentTab( SMESH::DIM_3D );
+
+  QStringList TypeMeshList;
+  createMeshTypeList( TypeMeshList );
+  setAvailableMeshType( TypeMeshList );
+
   myDlg->show();
   myDlg->setGeomPopupEnabled(false);
   selectionDone();
@@ -582,7 +587,8 @@ void SMESHGUI_MeshOp::selectionDone()
         onAlgoSelected(-1, i);
       }
       myDlg->setMaxHypoDim( shapeDim );
-      myDlg->setHypoSets( SMESH::GetHypothesesSets( shapeDim ));
+      myMaxShapeDim = shapeDim;
+      myDlg->setHypoSets( SMESH::GetHypothesesSets( shapeDim, "" ));
 
       if (!myToCreate) // edition: read hypotheses
       {
@@ -669,12 +675,16 @@ void SMESHGUI_MeshOp::selectionDone()
       for (int i = SMESH::DIM_0D;i < SMESH::DIM_3D; ++i) {
         myDlg->disableTab(i);
       }
+      myMaxShapeDim = -1;
       //Hide labels and fields (Mesh ang Geometry)
       myDlg->setObjectShown( SMESHGUI_MeshDlg::Mesh, false );
       myDlg->setObjectShown( SMESHGUI_MeshDlg::Geom, false );
       myDlg->adjustSize();
       readMesh();
     }
+    QStringList TypeMeshList;
+    createMeshTypeList( TypeMeshList );
+    setAvailableMeshType( TypeMeshList );
   }
   catch ( const SALOME::SALOME_Exception& S_ex )
   {
@@ -1380,7 +1390,19 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
     availableHyps( aDim, Algo, anAvailable, myAvailableHypData[ aDim ][ Algo ]);
     myDlg->tab( aDim )->setAvailableHyps( Algo, anAvailable );
   }
-
+  // check that tab enable, if algorithm building needed algo is one less than dimension
+  if ( algoData && myIsOnGeometry && !algoData->InputTypes.isEmpty() &&
+     ( aDim > SMESH::DIM_0D ) && !isAccessibleDim( aDim - 1 ) ){
+    myDlg->enableTab( aDim - 1 );
+  }
+  if ( (myDlg->currentMeshType() != MT_ANY) &&
+          (( !algoData && ( aDim > SMESH::DIM_0D ) && isAccessibleDim( aDim - 1 )) ||
+       ( algoData && myIsOnGeometry && algoData->InputTypes.isEmpty() &&
+       ( aDim > SMESH::DIM_0D ) && isAccessibleDim( aDim - 1 ) ) ) ){
+    for (int i = aDim - 1; i >= SMESH::DIM_0D; i--){
+      if ( isAccessibleDim( i ) ) myDlg->disableTab( i );
+    }
+  }
   // check that algorithms of other dimentions are compatible with
   // the selected one
 
@@ -2343,3 +2365,193 @@ void SMESHGUI_MeshOp::selectObject( _PTR(SObject) theSObj ) const
     sm->setSelectedObjects( anIOList, false );
   }
 }
+//================================================================================
+/*!
+ * \brief Create available list types of mesh
+  * \param theTypeMesh - Output list of available types of mesh
+ */
+//================================================================================
+void SMESHGUI_MeshOp::createMeshTypeList( QStringList& theTypeMesh)
+{
+  theTypeMesh.clear();
+  theTypeMesh.append( tr( "MT_ANY" ) );
+  if ( myIsOnGeometry &&  ( myMaxShapeDim >= 2 || myMaxShapeDim == -1 ) )
+  {
+    theTypeMesh.append( tr( "MT_TRIANGULAR" ) );
+    theTypeMesh.append( tr( "MT_QUADRILATERAL" ) );
+  }
+  if ( myIsOnGeometry && ( myMaxShapeDim == 3 || myMaxShapeDim == -1 ) )
+  {
+    theTypeMesh.append( tr( "MT_TETRAHEDRAL" ) );
+    theTypeMesh.append( tr( "MT_HEXAHEDRAL" ) );
+  }
+
+}
+//================================================================================
+/*!
+ * \brief Set available types of mesh
+  * \param theTypeMesh - List of available types of mesh
+ */
+//================================================================================
+void SMESHGUI_MeshOp::setAvailableMeshType( const QStringList& theTypeMesh )
+{
+  myDlg->setAvailableMeshType( theTypeMesh );
+}
+
+//================================================================================
+/*!
+ * \brief SLOT. Is called when the user select type of mesh
+  * \param theTabIndex - Index of current active tab
+  * \param theIndex - Index of current type of mesh
+ */
+//================================================================================
+void SMESHGUI_MeshOp::onAlgoSetByMeshType( const int theTabIndex, const int theIndex)
+{
+  int aDim;
+  if ( !myIsOnGeometry ) return;
+  THypDataList anAvailableAlgsData;
+  QStringList anAvailableAlgs;
+  QString anCompareType = "ANY";
+  bool isAvailableChoiceAlgo = false;
+  int anCurrentAvailableAlgo = 0;
+  bool isNone = true;
+  switch ( theIndex ) {
+    case MT_ANY:
+    {
+      for ( int dim = SMESH::DIM_2D; dim <= SMESH::DIM_3D; dim++ )
+      {
+        isNone = currentHyp( dim, Algo ) < 0;
+        isAvailableChoiceAlgo = false;
+        // retrieves a list of available algorithms from resources
+        availableHyps( dim, Algo, anAvailableAlgs, anAvailableAlgsData );
+        //return current algo in current tab
+        if ( !isNone && !myAvailableHypData[dim][Algo].empty() ){
+          for (int i = 0 ; i < anAvailableAlgsData.count(); i++)
+          {
+            HypothesisData* algoAny = anAvailableAlgsData.at(i);
+            HypothesisData* algoCur = myAvailableHypData[dim][Algo].at( currentHyp( dim, Algo ) );
+            QString tem = algoAny->Label;
+            if ( algoAny->Label == algoCur->Label ){
+              isAvailableChoiceAlgo = true;
+              anCurrentAvailableAlgo = i;
+              break;
+            }
+          }
+        }
+        else if ( !isNone ){
+          isAvailableChoiceAlgo = true;
+          anCurrentAvailableAlgo = currentHyp( dim, Algo );
+        }
+        //set new algorithm list and select the current algorithm
+        myAvailableHypData[dim][Algo] = anAvailableAlgsData;
+        myDlg->tab( dim )->setAvailableHyps( Algo, anAvailableAlgs );
+        if ( isAvailableChoiceAlgo )
+          setCurrentHyp( dim, Algo, anCurrentAvailableAlgo );
+      }
+      int aMaxShapeDim = ( myMaxShapeDim == -1 ) ? SMESH::DIM_3D : myMaxShapeDim;
+      for ( int i = SMESH::DIM_0D; i <= aMaxShapeDim; i++ ) {
+        myDlg->enableTab( i );
+      }
+      myDlg->setCurrentTab( theTabIndex );
+      myDlg->setHypoSets( SMESH::GetHypothesesSets( aMaxShapeDim, "" ) );
+    }
+    break;
+    case MT_TRIANGULAR:{
+      aDim = SMESH::DIM_2D;
+      anCompareType = "TRIA";
+    }
+    break;
+    case MT_QUADRILATERAL:{
+      aDim = SMESH::DIM_2D;
+      anCompareType = "QUAD";
+    }
+    break;
+    case MT_TETRAHEDRAL:{
+      aDim = SMESH::DIM_3D;
+      anCompareType = "TETRA";
+    }
+    break;
+    case MT_HEXAHEDRAL:{
+      aDim = SMESH::DIM_3D;
+      anCompareType = "HEXA";
+    }
+    break;
+    default:;
+  }
+  if ( anCompareType != "ANY" )
+  {
+    QString anCurrentAlgo;
+    bool isReqDisBound = true;
+    isNone = currentHyp( aDim, Algo ) < 0;
+    // retrieves a list of available algorithms from resources
+    availableHyps( aDim, Algo, anAvailableAlgs, anAvailableAlgsData );
+    // finding algorithm which is selected
+    if ( !isNone && !myAvailableHypData[aDim][Algo].empty() &&
+         myAvailableHypData[aDim][Algo].count() != anAvailableAlgsData.count() ){
+      anCurrentAlgo = myAvailableHypData[aDim][Algo].at( currentHyp( aDim, Algo ) )->Label;
+      isReqDisBound = myAvailableHypData[aDim][Algo].at( currentHyp( aDim, Algo ) )->InputTypes.isEmpty();
+    }
+    else if ( !isNone ){
+      anCurrentAlgo = anAvailableAlgsData.at( currentHyp( aDim, Algo ) )->Label;
+      isReqDisBound = anAvailableAlgsData.at( currentHyp( aDim, Algo ) )->InputTypes.isEmpty();
+    }
+    anAvailableAlgs.clear();
+    myAvailableHypData[aDim][Algo].clear();
+    // finding and adding algorithm depending on the type mesh
+    for ( int i = 0 ; i < anAvailableAlgsData.count(); i++ )
+    {
+      HypothesisData* algoIn = anAvailableAlgsData.at( i );
+      bool isAvailableAlgo = ( algoIn->OutputTypes.count() == 0 );
+      QStringList::const_iterator inElemType = algoIn->OutputTypes.begin();
+      for ( ; inElemType != algoIn->OutputTypes.end(); inElemType++ )
+      {
+        if ( *inElemType == anCompareType ){
+          isAvailableAlgo = true;
+          break;
+        }
+      }
+      if ( isAvailableAlgo || algoIn->OutputTypes.count()==0 ){
+        anAvailableAlgs.append( algoIn->Label );
+        myAvailableHypData[aDim][Algo].append( algoIn );
+      }
+      //algorithm will be active, if the chosen algorithm available in the current mesh type
+      if ( !isNone &&  isAvailableAlgo && algoIn->Label == anCurrentAlgo ){
+        isAvailableChoiceAlgo = true;
+        anCurrentAvailableAlgo = anAvailableAlgs.count() - 1 ;
+      }
+    }
+    //set new algorithm list and select the current algorithm
+    myDlg->tab( aDim )->setAvailableHyps( Algo, anAvailableAlgs );
+    if ( isAvailableChoiceAlgo )
+      setCurrentHyp( aDim, Algo, anCurrentAvailableAlgo );
+    int aMaxShapeDim = ( myMaxShapeDim == -1 ) ? SMESH::DIM_3D : myMaxShapeDim;
+    if ( isNone || isReqDisBound || !isAvailableChoiceAlgo ) {
+      for ( int i = SMESH::DIM_0D; i <= aMaxShapeDim; i++ ) {
+        if ( aDim != i ) {
+          myDlg->disableTab( i );
+          setCurrentHyp(i, Algo, -1);
+        }
+      }
+    }
+    else if ( !isNone ){
+      if ( aDim == SMESH::DIM_2D){
+        myDlg->disableTab( SMESH::DIM_3D );
+        setCurrentHyp( SMESH::DIM_3D, Algo, -1);
+      }
+      for ( int i = aMaxShapeDim; i > SMESH::DIM_0D; i-- )
+      {
+        isReqDisBound = ( currentHyp( i, Algo ) < 0 ) ? true : myAvailableHypData[i][Algo].at( currentHyp( i, Algo ) )->InputTypes.isEmpty();
+        if ( aMaxShapeDim != i && isReqDisBound) {
+          for (int j = i - 1; j >= SMESH::DIM_0D; j--){
+            myDlg->disableTab( j );
+            setCurrentHyp( j , Algo, -1 );
+          }
+          break;
+        }
+      }
+    }
+    myDlg->setHypoSets( SMESH::GetHypothesesSets( aDim, anCompareType ) );
+    myDlg->enableTab( aDim );
+    myDlg->setCurrentTab( aDim );
+  }
+}
index 91c39ed72bb8b16ce305e4630a9d3cf2d5f35d9c..5f56882675f6d1ed831ca342eface4965b7d43a8 100644 (file)
@@ -48,6 +48,7 @@ class SMESHGUI_EXPORT SMESHGUI_MeshOp : public SMESHGUI_SelectionOp
       
 public:
   enum HypType{ Algo = 0, MainHyp, AddHyp, NbHypTypes };
+  enum MeshType{ MT_ANY = 0, MT_TRIANGULAR, MT_QUADRILATERAL, MT_TETRAHEDRAL, MT_HEXAHEDRAL };
 
   typedef std::pair<SMESH::SMESH_Hypothesis_var, QString> THypItem;
   typedef QList< THypItem > THypList;
@@ -83,6 +84,7 @@ protected slots:
   void                           processSet();
   void                           onHypoCreated( int );
   void                           onHypoEdited( int );
+  void                           onAlgoSetByMeshType( const int, const int );
 
 private:
   typedef QList<HypothesisData*> THypDataList; // typedef: list of hypothesis data
@@ -125,7 +127,8 @@ private:
   char*                          isSubmeshIgnored() const;
   _PTR(SObject)                  getSubmeshByGeom() const;
   void                           selectObject( _PTR(SObject) ) const;
-
+  void                           createMeshTypeList( QStringList& );
+  void                           setAvailableMeshType( const QStringList& );
 private:
   SMESHGUI_MeshDlg*              myDlg;
   SMESHGUI_ShapeByMeshOp*        myShapeByMeshOp;
@@ -136,13 +139,12 @@ private:
   TDim2Type2HypList              myExistingHyps; //!< all hypothesis of SMESH module
   TDim2Type2HypList              myObjHyps;      //!< hypothesis assigned to the current 
                                                  //   edited mesh/sub-mesh
-
   // hypdata corresponding to hypotheses present in myDlg
   THypDataList                   myAvailableHypData[4][NbHypTypes];
 
   bool                           myIgnoreAlgoSelection;
   HypothesesSet* myHypoSet;
-  int myDim, myType;
+  int myDim, myType, myMaxShapeDim;
 
   QString                        myObjectToSelect;
 };
index 174bcf16528015b0f8c79d064d9d9d36ea684e96..df41ace147f67e21abb4a4ef529b461a1f3cb027 100644 (file)
@@ -5977,6 +5977,10 @@ Please specify them and try again</translation>
         <source>MESH</source>
         <translation>Mesh</translation>
     </message>
+    <message>
+        <source>MESH_TYPE</source>
+        <translation>Mesh type</translation>
+    </message>
     <message>
         <source>NAME</source>
         <translation>Name</translation>
@@ -6032,6 +6036,26 @@ Please specify it and try again</translation>
         <source>MESH_IS_NULL</source>
         <translation>Mesh is null</translation>
     </message>
+    <message>
+        <source>MT_ANY</source>
+        <translation>Any</translation>
+    </message>
+    <message>
+        <source>MT_HEXAHEDRAL</source>
+        <translation>Hexahedral</translation>
+    </message>
+    <message>
+        <source>MT_TETRAHEDRAL</source>
+        <translation>Tetrahedral</translation>
+    </message>
+    <message>
+        <source>MT_TRIANGULAR</source>
+        <translation>Triangular</translation>
+    </message>
+    <message>
+        <source>MT_QUADRILATERAL</source>
+        <translation>Quadrilaterial</translation>
+    </message>
     <message>
         <source>NAME_OF_MESH_IS_EMPTY</source>
         <translation>Name of mesh is empty
index 749b17e7e8af0afad7d4f3d373b060d9e1762b2f..b8ddd3e1bc005a776e9f0b4707fa87415d999708 100755 (executable)
@@ -5971,6 +5971,10 @@ Indiquez-les et essayez de nouveau</translation>
         <source>MESH</source>
         <translation>Maillage</translation>
     </message>
+    <message>
+        <source>MESH_TYPE</source>
+        <translation type="unfinished">Mesh type</translation>
+    </message>
     <message>
         <source>NAME</source>
         <translation>Nom</translation>
@@ -6026,6 +6030,26 @@ Spécifiez-le et essayez de nouveau</translation>
         <source>MESH_IS_NULL</source>
         <translation>Le maillage est nul</translation>
     </message>
+    <message>
+        <source>MT_ANY</source>
+        <translation type="unfinished">Any</translation>
+    </message>
+    <message>
+        <source>MT_HEXAHEDRAL</source>
+        <translation type="unfinished">Hexahedral</translation>
+    </message>
+    <message>
+        <source>MT_TETRAHEDRAL</source>
+        <translation type="unfinished">Tetrahedral</translation>
+    </message>
+    <message>
+        <source>MT_TRIANGULAR</source>
+        <translation type="unfinished">Triangular</translation>
+    </message>
+    <message>
+        <source>MT_QUADRILATERAL</source>
+        <translation>Quadrilaterial</translation>
+    </message>
     <message>
         <source>NAME_OF_MESH_IS_EMPTY</source>
         <translation>Le nom du maillage est vide
index 7d2ed2a7127da1630f6cb0586ea11dc6761197a0..fd40175d8bfb14f5309ef6837a30bb7ce7b88d55 100644 (file)
 //
 #include "SMESH_Block.hxx"
 
+#include "SMDS_MeshNode.hxx"
+#include "SMDS_MeshVolume.hxx"
+#include "SMDS_VolumeTool.hxx"
+#include "SMESH_MeshAlgos.hxx"
+
 #include <BRepAdaptor_Curve.hxx>
 #include <BRepAdaptor_Curve2d.hxx>
 #include <BRepAdaptor_Surface.hxx>
 #include <math_Matrix.hxx>
 #include <math_Vector.hxx>
 
-#include "SMDS_MeshNode.hxx"
-#include "SMDS_MeshVolume.hxx"
-#include "SMDS_VolumeTool.hxx"
-#include "utilities.h"
+#include <utilities.h>
 
 #include <list>
 #include <limits>
@@ -309,24 +311,15 @@ gp_XYZ SMESH_Block::TFace::Point( const gp_XYZ& theParams ) const
 
 namespace
 {
+  inline
   bool isPntInTria( const gp_XY& p, const gp_XY& t0, const gp_XY& t1, const gp_XY& t2  )
   {
-    const double // matrix 2x2
-      T11 = t0.X()-t2.X(), T12 = t1.X()-t2.X(),
-      T21 = t0.Y()-t2.Y(), T22 = t1.Y()-t2.Y();
-    const double Tdet = T11*T22 - T12*T21; // matrix determinant
-    if ( Abs( Tdet ) < std::numeric_limits<double>::min() )
-      return false;
-    // matrix inverse
-    const double t11 = T22, t12 = -T12, t21 = -T21, t22 = T11;
-    // vector
-    const double r11 = p.X()-t2.X(), r12 = p.Y()-t2.Y();
-    // barycentric coordinates: mutiply matrix by vector
-    const double bc0 = (t11 * r11 + t12 * r12)/Tdet;
-    const double bc1 = (t21 * r11 + t22 * r12)/Tdet;
+    double bc0, bc1;
+    SMESH_MeshAlgos::GetBarycentricCoords( p, t0, t1, t2, bc0, bc1 );
     return ( bc0 >= 0. && bc1 >= 0. && bc0 + bc1 <= 1. );
   }
 
+  inline
   bool isPntInQuad( const gp_XY& p,
                     const gp_XY& q0, const gp_XY& q1, const gp_XY& q2, const gp_XY& q3 )
   {
index a2fcd0a1ab8e7709dbdcc447240f645b15c232da..4fc6901370ce49104eb72795b3ebd3d8a12f870d 100644 (file)
@@ -68,20 +68,19 @@ class SMESHUtils_EXPORT SMESH_Block: public math_FunctionSetWithDerivatives
     // ----------------------------
     ID_NONE = 0,
 
-    ID_V000 = 1, ID_V100, ID_V010, ID_V110, ID_V001, ID_V101, ID_V011, ID_V111,
+    ID_V000 = 1, ID_V100, ID_V010, ID_V110, ID_V001, ID_V101, ID_V011, ID_V111, // 1-8
 
-    ID_Ex00, ID_Ex10, ID_Ex01, ID_Ex11,
-    ID_E0y0, ID_E1y0, ID_E0y1, ID_E1y1,
-    ID_E00z, ID_E10z, ID_E01z, ID_E11z,
+    ID_Ex00, ID_Ex10, ID_Ex01, ID_Ex11, // 9-12
+    ID_E0y0, ID_E1y0, ID_E0y1, ID_E1y1, // 13-16
+    ID_E00z, ID_E10z, ID_E01z, ID_E11z, // 17-20
 
-    ID_Fxy0, ID_Fxy1, ID_Fx0z, ID_Fx1z, ID_F0yz, ID_F1yz,
+    ID_Fxy0, ID_Fxy1, ID_Fx0z, ID_Fx1z, ID_F0yz, ID_F1yz, // 21-26
 
-    ID_Shell
-    };
-  enum { // to use TShapeID for indexing certain type subshapes
+    ID_Shell, // 27
 
-    ID_FirstV = ID_V000, ID_FirstE = ID_Ex00, ID_FirstF = ID_Fxy0
+    // to use TShapeID for indexing certain type subshapes
 
+    ID_FirstV = ID_V000, ID_FirstE = ID_Ex00, ID_FirstF = ID_Fxy0
   };
 
 
@@ -285,7 +284,7 @@ public:
                               std::list< int >  &       theNbEdgesInWires,
                               TopoDS_Vertex             theFirstVertex=TopoDS_Vertex(),
                               const bool                theShapeAnalysisAlgo=false);
-  // Return nb wires and a list of oredered edges.
+  // Return nb wires and a list of ordered edges.
   // It is used to assign indices to subshapes.
   // theFirstVertex may be NULL.
   // Always try to set a seam edge first
index 45acf33b115cb4067aa23516ee4a774f59d5fdec..2ecd29a9044f5b483c2645a8b13e7be1a4b700cf 100644 (file)
@@ -1386,6 +1386,39 @@ double SMESH_MeshAlgos::GetDistance( const SMDS_MeshFace* face,
   return badDistance;
 }
 
+//================================================================================
+/*!
+ * \brief Returns barycentric coordinates of a point within a triangle.
+ *        A not returned bc2 = 1. - bc0 - bc1.
+ *        The point lies within the triangle if ( bc0 >= 0 && bc1 >= 0 && bc0+bc1 <= 1 )
+ */
+//================================================================================
+
+void SMESH_MeshAlgos::GetBarycentricCoords( const gp_XY& p,
+                                            const gp_XY& t0,
+                                            const gp_XY& t1,
+                                            const gp_XY& t2,
+                                            double &     bc0,
+                                            double &     bc1)
+{
+  const double // matrix 2x2
+    T11 = t0.X()-t2.X(), T12 = t1.X()-t2.X(),
+    T21 = t0.Y()-t2.Y(), T22 = t1.Y()-t2.Y();
+  const double Tdet = T11*T22 - T12*T21; // matrix determinant
+  if ( Abs( Tdet ) < std::numeric_limits<double>::min() )
+  {
+    bc0 = bc1 = 2.;
+    return;
+  }
+  // matrix inverse
+  const double t11 = T22, t12 = -T12, t21 = -T21, t22 = T11;
+  // vector
+  const double r11 = p.X()-t2.X(), r12 = p.Y()-t2.Y();
+  // barycentric coordinates: mutiply matrix by vector
+  bc0 = (t11 * r11 + t12 * r12)/Tdet;
+  bc1 = (t21 * r11 + t22 * r12)/Tdet;
+}
+
 //=======================================================================
 //function : FindFaceInSet
 //purpose  : Return a face having linked nodes n1 and n2 and which is
index a02ba10ddd73db31e0fd470bc5c4ae2132558e2a..dc4d8fcb451831dd2c82253c6ab910e16183352f 100644 (file)
@@ -97,9 +97,16 @@ namespace SMESH_MeshAlgos
   /*!
    * \brief Return true if the point is IN or ON of the element
    */
-  SMESHUtils_EXPORT bool IsOut( const SMDS_MeshElement* element, const gp_Pnt& point, double tol );
+  SMESHUtils_EXPORT
+  bool IsOut( const SMDS_MeshElement* element, const gp_Pnt& point, double tol );
 
-  SMESHUtils_EXPORT double GetDistance( const SMDS_MeshFace* face, const gp_Pnt& point );
+  SMESHUtils_EXPORT
+  double GetDistance( const SMDS_MeshFace* face, const gp_Pnt& point );
+
+  SMESHUtils_EXPORT
+  void GetBarycentricCoords( const gp_XY& point,
+                             const gp_XY& t0, const gp_XY& t1, const gp_XY& t2,
+                             double &    bc0, double &    bc1);
 
   /*!
    * Return a face having linked nodes n1 and n2 and which is
@@ -107,35 +114,40 @@ namespace SMESH_MeshAlgos
    * - in elemSet provided that !elemSet.empty()
    * i1 and i2 optionally returns indices of n1 and n2
    */
-  SMESHUtils_EXPORT const SMDS_MeshElement* 
-    FindFaceInSet(const SMDS_MeshNode*    n1,
-                  const SMDS_MeshNode*    n2,
-                  const TIDSortedElemSet& elemSet,
-                  const TIDSortedElemSet& avoidSet,
-                  int*                    i1=0,
-                  int*                    i2=0);
+  SMESHUtils_EXPORT
+  const SMDS_MeshElement* FindFaceInSet(const SMDS_MeshNode*    n1,
+                                        const SMDS_MeshNode*    n2,
+                                        const TIDSortedElemSet& elemSet,
+                                        const TIDSortedElemSet& avoidSet,
+                                        int*                    i1=0,
+                                        int*                    i2=0);
   /*!
    * \brief Calculate normal of a mesh face
    */
-  SMESHUtils_EXPORT bool FaceNormal(const SMDS_MeshElement* F, gp_XYZ& normal, bool normalized=true);
+  SMESHUtils_EXPORT
+  bool FaceNormal(const SMDS_MeshElement* F, gp_XYZ& normal, bool normalized=true);
 
   /*!
    * \brief Return nodes common to two elements
    */
-  SMESHUtils_EXPORT std::vector< const SMDS_MeshNode*> GetCommonNodes(const SMDS_MeshElement* e1,
+  SMESHUtils_EXPORT
+  std::vector< const SMDS_MeshNode*> GetCommonNodes(const SMDS_MeshElement* e1,
                                                     const SMDS_MeshElement* e2);
 
   /*!
    * \brief Return SMESH_NodeSearcher. The caller is responsible for deleteing it
    */
-  SMESHUtils_EXPORT SMESH_NodeSearcher* GetNodeSearcher( SMDS_Mesh& mesh );
+  SMESHUtils_EXPORT
+  SMESH_NodeSearcher* GetNodeSearcher( SMDS_Mesh& mesh );
 
   /*!
    * \brief Return SMESH_ElementSearcher. The caller is responsible for deleting it
    */
-  SMESHUtils_EXPORT SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh );
-  SMESHUtils_EXPORT SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh,
-                                                               SMDS_ElemIteratorPtr elemIt );
+  SMESHUtils_EXPORT
+  SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh );
+  SMESHUtils_EXPORT
+  SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh,
+                                             SMDS_ElemIteratorPtr elemIt );
 }
 
 #endif
index 2555cc371e6581ba8f0c9b870639b71fda071ef8..6e5bda2a523c08584bb425a22c886229b8bc8433 100644 (file)
 
 #include "SMESH_Utils.hxx"
 
-#include <SMDS_MeshNode.hxx>
+#include "SMDS_MeshNode.hxx"
 
 #include <gp_XYZ.hxx>
+#include <gp_XY.hxx>
 
 #include <map>
 #include <list>
@@ -42,7 +43,7 @@ typedef std::map<const SMDS_MeshElement*,
                  std::list<const SMDS_MeshElement*>, TIDCompare > TElemOfElemListMap;
 typedef std::map<const SMDS_MeshElement*,
                  std::list<const SMDS_MeshNode*>,    TIDCompare > TElemOfNodeListMap;
-typedef std::map<const SMDS_MeshNode*, const SMDS_MeshNode*> TNodeNodeMap;
+typedef std::map<const SMDS_MeshNode*, const SMDS_MeshNode*>      TNodeNodeMap;
 
 //!< Set of elements sorted by ID, to be used to assure predictability of edition
 typedef std::set< const SMDS_MeshElement*, TIDCompare >      TIDSortedElemSet;
@@ -50,8 +51,8 @@ typedef std::set< const SMDS_MeshNode*,    TIDCompare >      TIDSortedNodeSet;
 
 typedef std::pair< const SMDS_MeshNode*, const SMDS_MeshNode* >   NLink;
 
-struct faceQuadStruct; // defined in StdMeshers_Quadrangle_2D.hxx
-typedef boost::shared_ptr<faceQuadStruct> TFaceQuadStructPtr;
+struct FaceQuadStruct; // defined in StdMeshers_Quadrangle_2D.hxx
+typedef boost::shared_ptr<FaceQuadStruct> TFaceQuadStructPtr;
 
 
 namespace SMESHUtils
@@ -137,6 +138,10 @@ typedef struct uvPtStruct
   double x, y; // 2d parameter, normalized [0,1]
   const SMDS_MeshNode * node;
 
+  uvPtStruct(): node(NULL) {}
+
+  inline gp_XY UV() const { return gp_XY( u, v ); }
+
   struct NodeAccessor // accessor to iterate on nodes in UVPtStructVec
   {
     static const SMDS_MeshNode* value(std::vector< uvPtStruct >::const_iterator it)
index 929da0dcf43bc2518b5e946ff3dd1d90e88374f8..7a59ad87f56ac39b331d0d70496c12d659572ae9 100644 (file)
@@ -2075,6 +2075,7 @@ bool _pyMesh::NeedMeshAccess( const Handle(_pyCommand)& theCommand )
         "GetSubMeshElementsId","GetSubMeshNodesId","GetSubMeshElementType","Dump","GetNodeXYZ",
         "GetNodeInverseElements","GetShapeID","GetShapeIDForElem","GetElemNbNodes",
         "GetElemNode","IsMediumNode","IsMediumNodeOfAnyElem","ElemNbEdges","ElemNbFaces",
+        "GetElemFaceNodes", "GetFaceNormal", "FindElementByNodes",
         "IsPoly","IsQuadratic","BaryCenter","GetHypothesisList", "SetAutoColor", "GetAutoColor",
         "Clear", "ConvertToStandalone", "GetMeshOrder", "SetMeshOrder"
         ,"" }; // <- mark of end
index 43ffd029bf2d152242bcdc67fd1a3983183b5dfe..78d9bf959534dcecbbb1574f5456a515bc71a12a 100644 (file)
@@ -240,13 +240,20 @@ namespace SMESH
   template<class TArray>
   void DumpArray(const TArray& theArray, TPythonDump & theStream)
   {
-    theStream << "[ ";
-    for (int i = 1; i <= theArray.length(); i++) {
-      theStream << theArray[i-1];
-      if ( i < theArray.length() )
-        theStream << ", ";
+    if ( theArray.length() == 0 )
+    {
+      theStream << "[]";
+    }
+    else
+    {
+      theStream << "[ ";
+      for (int i = 1; i <= theArray.length(); i++) {
+        theStream << theArray[i-1];
+        if ( i < theArray.length() )
+          theStream << ", ";
+      }
+      theStream << " ]";
     }
-    theStream << " ]";
   }
 
   TPythonDump&
@@ -263,6 +270,13 @@ namespace SMESH
     return *this;
   }
 
+  TPythonDump&
+  TPythonDump::operator<<(const SMESH::nodes_array& theArg)
+  {
+    DumpArray( theArg, *this );
+    return *this;
+  }
+
   TPythonDump&
   TPythonDump::operator<<(const SMESH::string_array& theArray)
   {
@@ -517,6 +531,11 @@ namespace SMESH
     DumpArray( *theList, *this );
     return *this;
   }
+  TPythonDump& TPythonDump::operator<<(const GEOM::ListOfGO& theList)
+  {
+    DumpArray( theList, *this );
+    return *this;
+  }
   TPythonDump& TPythonDump::operator<<(const SMESH::ListOfIDSources& theList)
   {
     DumpArray( theList, *this );
index 812d3c0cdb83a5a751ef9fa17182ed741e66d24d..f6beb92d5de1d36f109f00675350b6a200a2cd4b 100644 (file)
@@ -44,6 +44,7 @@
 #include "SMESH_Gen_i.hxx"
 #include "SMESH_Group.hxx"
 #include "SMESH_Group_i.hxx"
+#include "SMESH_MeshAlgos.hxx"
 #include "SMESH_MeshEditor.hxx"
 #include "SMESH_MeshEditor_i.hxx"
 #include "SMESH_MeshPartDS.hxx"
@@ -4023,6 +4024,32 @@ SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long  elemId,
   return aResult._retn();
 }
 
+//=======================================================================
+//function : GetElemFaceNodes
+//purpose  : Returns three components of normal of given mesh face.
+//=======================================================================
+
+SMESH::double_array* SMESH_Mesh_i::GetFaceNormal(CORBA::Long  elemId)
+{
+  if ( _preMeshInfo )
+    _preMeshInfo->FullLoadFromFile();
+
+  SMESH::double_array_var aResult = new SMESH::double_array();
+
+  if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
+  {
+    gp_XYZ normal;
+    if ( SMESH_MeshAlgos::FaceNormal( mesh->FindElement(elemId), normal, /*normalized=*/true ))
+    {
+      aResult->length( 3 );
+      aResult[ 0 ] = normal.X();
+      aResult[ 1 ] = normal.Y();
+      aResult[ 2 ] = normal.Z();
+    }
+  }
+  return aResult._retn();
+}
+
 //=======================================================================
 //function : FindElementByNodes
 //purpose  : Returns an element based on all given nodes.
index c52699bb2bdec9fa699849cfe43ae7f4ffaa76a3..2615bef48a20cce6f2091a08826494627e1885e2 100644 (file)
@@ -532,6 +532,11 @@ public:
    */
   SMESH::long_array* GetElemFaceNodes(CORBA::Long elemId, CORBA::Short faceIndex);
 
+  /*!
+   * Returns three components of normal of given mesh face (or an empty array in KO case)
+   */
+  SMESH::double_array* GetFaceNormal(CORBA::Long faceId);
+
   /*!
    * Returns an element based on all given nodes.
    */
index 595e732fa952be39a50f2372bba61d872e0bdae4..1f9d5a623c597e851ddd2e790c786e02db2d8048 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <SALOMEconfig.h>
 #include CORBA_SERVER_HEADER(SMESH_Mesh)
+#include CORBA_SERVER_HEADER(GEOM_Gen)
 #include CORBA_SERVER_HEADER(SALOMEDS)
 
 #include <TCollection_AsciiString.hxx>
@@ -162,6 +163,9 @@ namespace SMESH
     TPythonDump&
     operator<<(const SMESH::string_array& theArg);
 
+    TPythonDump&
+    operator<<(const SMESH::nodes_array& theArg);
+
     TPythonDump&
     operator<<(SMESH::SMESH_Hypothesis_ptr theArg);
 
@@ -216,6 +220,9 @@ namespace SMESH
     TPythonDump&
     operator<<(const SMESH::ListOfGroups * theList);
 
+    TPythonDump&
+    operator<<(const GEOM::ListOfGO& theList);
+
     TPythonDump&
     operator<<(const SMESH::ListOfIDSources& theList);
 
index e28659b556cf8f9bd2159991c95910487f1b918b..4e5b2d217cf13a4f5c29ad59304fb1cc18930c79 100644 (file)
@@ -199,7 +199,8 @@ class StdMeshersBuilder_Segment(Mesh_Algorithm):
         hyp.SetDeflection(deflection)
         return hyp
 
-    ## Defines "Arithmetic1D" hypothesis to cut an edge in several segments with increasing arithmetic length
+    ## Defines "Arithmetic1D" hypothesis to cut an edge in several segments with a length
+    #  that changes in arithmetic progression
     #  @param start defines the length of the first segment
     #  @param end   defines the length of the last  segment
     #  @param reversedEdges is a list of edges to mesh using reversed orientation.
@@ -226,6 +227,32 @@ class StdMeshersBuilder_Segment(Mesh_Algorithm):
         hyp.SetObjectEntry( entry )
         return hyp
 
+    ## Defines "GeometricProgression" hypothesis to cut an edge in several
+    #  segments with a length that changes in Geometric progression
+    #  @param start defines the length of the first segment
+    #  @param ratio defines the common ratio of the geometric progression
+    #  @param reversedEdges is a list of edges to mesh using reversed orientation.
+    #                       A list item can also be a tuple (edge, 1st_vertex_of_edge)
+    #  @param UseExisting if ==true - searches for an existing hypothesis created with
+    #                     the same parameters, else (default) - creates a new one
+    #  @return an instance of StdMeshers_Geometric1D hypothesis
+    #  @ingroup l3_hypos_1dhyps
+    def GeometricProgression(self, start, ratio, reversedEdges=[], UseExisting=0):
+        reversedEdgeInd = self.ReversedEdgeIndices(reversedEdges)
+        entry = self.MainShapeEntry()
+        from salome.smesh.smeshBuilder import IsEqual
+        compFun = lambda hyp, args: ( IsEqual(hyp.GetLength(1), args[0]) and \
+                                      IsEqual(hyp.GetLength(0), args[1]) and \
+                                      hyp.GetReversedEdges() == args[2]  and \
+                                      (not args[2] or hyp.GetObjectEntry() == args[3]))
+        hyp = self.Hypothesis("GeometricProgression", [start, ratio, reversedEdgeInd, entry],
+                              UseExisting=UseExisting, CompareMethod=compFun)
+        hyp.SetStartLength( start )
+        hyp.SetCommonRatio( ratio )
+        hyp.SetReversedEdges( reversedEdgeInd )
+        hyp.SetObjectEntry( entry )
+        return hyp
+
     ## Defines "FixedPoints1D" hypothesis to cut an edge using parameter
     # on curve from 0 to 1 (additionally it is neecessary to check
     # orientation of edges and create list of reversed edges if it is
@@ -237,7 +264,7 @@ class StdMeshersBuilder_Segment(Mesh_Algorithm):
     #                       A list item can also be a tuple (edge, 1st_vertex_of_edge)
     #  @param UseExisting if ==true - searches for an existing hypothesis created with
     #                     the same parameters, else (default) - creates a new one
-    #  @return an instance of StdMeshers_Arithmetic1D hypothesis
+    #  @return an instance of StdMeshers_FixedPoints1D hypothesis
     #  @ingroup l3_hypos_1dhyps
     def FixedPoints1D(self, points, nbSegs=[1], reversedEdges=[], UseExisting=0):
         if not isinstance(reversedEdges,list): #old version script, before adding reversedEdges
@@ -295,12 +322,23 @@ class StdMeshersBuilder_Segment(Mesh_Algorithm):
         hyp.SetDeflection(d)
         return hyp
 
-    ## Defines "Propagation" hypothesis that propagates all other hypotheses on all other edges that are at
-    #  the opposite side in case of quadrangular faces
+    ## Defines "Propagation" hypothesis that propagates 1D hypotheses
+    #  from an edge where this hypothesis is assigned to
+    #  on all other edges that are at the opposite side in case of quadrangular faces
+    #  This hypothesis should be assigned to an edge to propagate a hypothesis from.
     #  @ingroup l3_hypos_additi
     def Propagation(self):
         return self.Hypothesis("Propagation", UseExisting=1, CompareMethod=self.CompareEqualHyp)
 
+    ## Defines "Propagation of Node Distribution" hypothesis that propagates
+    #  distribution of nodes from an edge where this hypothesis is assigned to,
+    #  to opposite edges of quadrangular faces, so that number of segments on all these
+    #  edges will be the same, as well as relations between segment lengths. 
+    #  @ingroup l3_hypos_additi
+    def PropagationOfDistribution(self):
+        return self.Hypothesis("PropagOfDistribution", UseExisting=1,
+                               CompareMethod=self.CompareEqualHyp)
+
     ## Defines "AutomaticLength" hypothesis
     #  @param fineness for the fineness [0-1]
     #  @param UseExisting if ==true - searches for an existing hypothesis created with the
@@ -552,28 +590,56 @@ class StdMeshersBuilder_Quadrangle(Mesh_Algorithm):
     #                    same number of segments, the other pair must have an even difference
     #                    between the numbers of segments on the sides.
     #  @param triangleVertex: vertex of a trilateral geometrical face, around which triangles
-    #                  will be created while other elements will be quadrangles.
-    #                  Vertex can be either a GEOM_Object or a vertex ID within the
-    #                  shape to mesh
-    #  @param UseExisting: if ==true - searches for the existing hypothesis created with
-    #                  the same parameters, else (default) - creates a new one
+    #                    will be created while other elements will be quadrangles.
+    #                    Vertex can be either a GEOM_Object or a vertex ID within the
+    #                    shape to mesh
+    #  @param enfVertices: list of shapes defining positions where nodes (enforced nodes)
+    #                    must be created by the mesher. Shapes can be of any type,
+    #                    vertices of given shapes define positions of enforced nodes.
+    #                    Only vertices successfully projected to the face are used.
+    #  @param enfPoint: list of points giving positions of enforced nodes.
+    #                    Point can be defined either as SMESH.PointStruct's
+    #                    ([SMESH.PointStruct(x1,y1,z1), SMESH.PointStruct(x2,y2,z2),...])
+    #                    or triples of values ([[x1,y1,z1], [x2,y2,z2], ...]).
+    #                    In the case if the defined QuadrangleParameters() refer to a sole face,
+    #                    all given points must lie on this face, else the mesher fails.
+    #  @param UseExisting: if \c True - searches for the existing hypothesis created with
+    #                    the same parameters, else (default) - creates a new one
     #  @ingroup l3_hypos_quad
-    def QuadrangleParameters(self, quadType=StdMeshers.QUAD_STANDARD, triangleVertex=0, UseExisting=0):
-        import GEOM
+    def QuadrangleParameters(self, quadType=StdMeshers.QUAD_STANDARD, triangleVertex=0,
+                             enfVertices=[],enfPoints=[],UseExisting=0):
+        import GEOM, SMESH
         vertexID = triangleVertex
         if isinstance( triangleVertex, GEOM._objref_GEOM_Object ):
             vertexID = self.mesh.geompyD.GetSubShapeID( self.mesh.geom, triangleVertex )
+        if isinstance( enfVertices, int ) and not enfPoints and not UseExisting:
+            # a call of old syntax, before inserting enfVertices and enfPoints before UseExisting
+            UseExisting, enfVertices = enfVertices, []
+        pStructs, xyz = [], []
+        for p in enfPoints:
+            if isinstance( p, SMESH.PointStruct ):
+                xyz.append(( p.x, p.y, p.z ))
+                pStructs.append( p )
+            else:
+                xyz.append(( p[0], p[1], p[2] ))
+                pStructs.append( SMESH.PointStruct( p[0], p[1], p[2] ))
         if not self.params:
             compFun = lambda hyp,args: \
                       hyp.GetQuadType() == args[0] and \
-                      ( hyp.GetTriaVertex()==args[1] or ( hyp.GetTriaVertex()<1 and args[1]<1))
-            self.params = self.Hypothesis("QuadrangleParams", [quadType,vertexID],
+                      (hyp.GetTriaVertex()==args[1] or ( hyp.GetTriaVertex()<1 and args[1]<1)) and \
+                      ((hyp.GetEnforcedNodes()) == (args[2],args[3])) # True w/o enfVertices only
+            entries = [ shape.GetStudyEntry() for shape in enfVertices ]
+            self.params = self.Hypothesis("QuadrangleParams", [quadType,vertexID,entries,xyz],
                                           UseExisting = UseExisting, CompareMethod=compFun)
             pass
         if self.params.GetQuadType() != quadType:
             self.params.SetQuadType(quadType)
         if vertexID > 0:
             self.params.SetTriaVertex( vertexID )
+        from salome.smesh.smeshBuilder import AssureGeomPublished
+        for v in enfVertices:
+            AssureGeomPublished( self.mesh, v )
+        self.params.SetEnforcedNodes( enfVertices, pStructs )
         return self.params
 
     ## Defines "QuadrangleParams" hypothesis with a type of quadrangulation that only
@@ -980,7 +1046,8 @@ class StdMeshersBuilder_Prism3D(Mesh_Algorithm):
         return hyp
 
     ## Defines "Arithmetic1D" hypothesis, specifying the distribution of segments
-    #  to build between the inner and the outer shells with a length that changes in arithmetic progression
+    #  to build between the inner and the outer shells with a length that changes
+    #  in arithmetic progression
     #  @param start  the length of the first segment
     #  @param end    the length of the last  segment
     def Arithmetic1D(self, start, end ):
@@ -992,6 +1059,20 @@ class StdMeshersBuilder_Prism3D(Mesh_Algorithm):
         hyp.SetLength(end  , 0)
         return hyp
 
+    ## Defines "GeometricProgression" hypothesis, specifying the distribution of segments
+    #  to build between the inner and the outer shells with a length that changes
+    #  in Geometric progression
+    #  @param start  the length of the first segment
+    #  @param ratio  the common ratio of the geometric progression
+    def GeometricProgression(self, start, ratio ):
+        if self.algoType != "RadialPrism_3D":
+            print "Prism_3D algorith doesn't support any hyposesis"
+            return None
+        hyp = self.OwnHypothesis("GeometricProgression", [start, ratio])
+        hyp.SetStartLength( start )
+        hyp.SetCommonRatio( ratio )
+        return hyp
+
     ## Defines "StartEndLength" hypothesis, specifying distribution of segments
     #  to build between the inner and the outer shells as geometric length increasing
     #  @param start for the length of the first segment
@@ -1148,6 +1229,16 @@ class StdMeshersBuilder_RadialQuadrangle1D2D(Mesh_Algorithm):
         hyp.SetLength(end  , 0)
         return hyp
 
+    ## Defines "GeometricProgression" hypothesis, specifying the distribution of segments
+    #  with a length that changes in Geometric progression
+    #  @param start  the length of the first segment
+    #  @param ratio  the common ratio of the geometric progression
+    def GeometricProgression(self, start, ratio ):
+        hyp = self.OwnHypothesis("GeometricProgression", [start, ratio])
+        hyp.SetStartLength( start )
+        hyp.SetCommonRatio( ratio )
+        return hyp
+
     ## Defines "StartEndLength" hypothesis, specifying distribution of segments
     #  as geometric length increasing
     #  @param start for the length of the first segment
index 5e68dc230b7992786766b656063a8299b19e2ce2..a5aae93d2898f2142e804323fa31d6d2b0058435 100644 (file)
@@ -2418,6 +2418,12 @@ class Mesh:
     def GetElemFaceNodes(self,elemId, faceIndex):
         return self.mesh.GetElemFaceNodes(elemId, faceIndex)
 
+    ## Returns three components of normal of given mesh face
+    #  (or an empty array in KO case)
+    #  @ingroup l1_meshinfo
+    def GetFaceNormal(self, faceId):
+        return self.mesh.GetFaceNormal(faceId)
+
     ## Returns an element based on all given nodes.
     #  @ingroup l1_meshinfo
     def FindElementByNodes(self,nodes):
@@ -3181,7 +3187,8 @@ class Mesh:
     #  Note that nodes built on edges and boundary nodes are always fixed.
     #  @param MaxNbOfIterations the maximum number of iterations
     #  @param MaxAspectRatio varies in range [1.0, inf]
-    #  @param Method is Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH)
+    #  @param Method is either Laplacian (SMESH.SMESH_MeshEditor.LAPLACIAN_SMOOTH)
+    #         or Centroidal (SMESH.SMESH_MeshEditor.CENTROIDAL_SMOOTH)
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_smooth
     def Smooth(self, IDsOfElements, IDsOfFixedNodes,
@@ -3199,7 +3206,8 @@ class Mesh:
     #  Note that nodes built on edges and boundary nodes are always fixed.
     #  @param MaxNbOfIterations the maximum number of iterations
     #  @param MaxAspectRatio varies in range [1.0, inf]
-    #  @param Method is Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH)
+    #  @param Method is either Laplacian (SMESH.SMESH_MeshEditor.LAPLACIAN_SMOOTH)
+    #         or Centroidal (SMESH.SMESH_MeshEditor.CENTROIDAL_SMOOTH)
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_smooth
     def SmoothObject(self, theObject, IDsOfFixedNodes,
@@ -3215,7 +3223,8 @@ class Mesh:
     #  Note that nodes built on edges and boundary nodes are always fixed.
     #  @param MaxNbOfIterations the maximum number of iterations
     #  @param MaxAspectRatio varies in range [1.0, inf]
-    #  @param Method is Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH)
+    #  @param Method is either Laplacian (SMESH.SMESH_MeshEditor.LAPLACIAN_SMOOTH)
+    #         or Centroidal (SMESH.SMESH_MeshEditor.CENTROIDAL_SMOOTH)
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_smooth
     def SmoothParametric(self, IDsOfElements, IDsOfFixedNodes,
@@ -3233,7 +3242,8 @@ class Mesh:
     #  Note that nodes built on edges and boundary nodes are always fixed.
     #  @param MaxNbOfIterations the maximum number of iterations
     #  @param MaxAspectRatio varies in range [1.0, inf]
-    #  @param Method Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH)
+    #  @param Method is either Laplacian (SMESH.SMESH_MeshEditor.LAPLACIAN_SMOOTH)
+    #         or Centroidal (SMESH.SMESH_MeshEditor.CENTROIDAL_SMOOTH)
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_smooth
     def SmoothParametricObject(self, theObject, IDsOfFixedNodes,
index a81f825a6ac4ebd2440f3d079bb63423a13a8340..0d018d52ec4e9554b8ac0b0f1fb7d5ea4d10b48d 100644 (file)
@@ -267,21 +267,26 @@ class Mesh_Algorithm:
     #  @param thickness total thickness of layers of prisms
     #  @param numberOfLayers number of layers of prisms
     #  @param stretchFactor factor (>1.0) of growth of layer thickness towards inside of mesh
-    #  @param ignoreFaces list of geometrical faces (or their ids) not to generate layers on
+    #  @param faces list of geometrical faces (or their ids).
+    #         Viscous layers are either generated on these faces or not, depending on
+    #         the value of \a isFacesToIgnore parameter.
+    #  @param isFacesToIgnore if \c True, the Viscous layers are not generated on the
+    #         faces specified by the previous parameter (\a faces).
     #  @ingroup l3_hypos_additi
-    def ViscousLayers(self, thickness, numberOfLayers, stretchFactor, ignoreFaces=[]):
+    def ViscousLayers(self, thickness, numberOfLayers, stretchFactor,
+                      faces=[], isFacesToIgnore=True ):
         if not isinstance(self.algo, SMESH._objref_SMESH_3D_Algo):
             raise TypeError, "ViscousLayers are supported by 3D algorithms only"
         if not "ViscousLayers" in self.GetCompatibleHypothesis():
             raise TypeError, "ViscousLayers are not supported by %s"%self.algo.GetName()
-        if ignoreFaces and isinstance( ignoreFaces[0], geomBuilder.GEOM._objref_GEOM_Object ):
-            ignoreFaces = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in ignoreFaces ]
+        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, ignoreFaces])
+                              [thickness, numberOfLayers, stretchFactor, faces])
         hyp.SetTotalThickness(thickness)
         hyp.SetNumberLayers(numberOfLayers)
         hyp.SetStretchFactor(stretchFactor)
-        hyp.SetIgnoreFaces(ignoreFaces)
+        hyp.SetFaces(faces, isFacesToIgnore)
         return hyp
 
     ## Defines "ViscousLayers2D" hypothesis to give parameters of layers of quadrilateral
@@ -290,9 +295,9 @@ class Mesh_Algorithm:
     #  @param thickness total thickness of layers of quadrilaterals
     #  @param numberOfLayers number of layers
     #  @param stretchFactor factor (>1.0) of growth of layer thickness towards inside of mesh
-    #  @param edges list of geometrical edge (or their ids).
+    #  @param edges list of geometrical edges (or their ids).
     #         Viscous layers are either generated on these edges or not, depending on
-    #         the values of \a isEdgesToIgnore parameter.
+    #         the value of \a isEdgesToIgnore parameter.
     #  @param isEdgesToIgnore if \c True, the Viscous layers are not generated on the
     #         edges specified by the previous parameter (\a edges).
     #  @ingroup l3_hypos_additi
@@ -313,7 +318,7 @@ class Mesh_Algorithm:
         hyp.SetEdges(edges, isEdgesToIgnore)
         return hyp
 
-    ## Transform a list of ether edges or tuples (edge, 1st_vertex_of_edge)
+    ## Transform a list of either edges or tuples (edge, 1st_vertex_of_edge)
     #  into a list acceptable to SetReversedEdges() of some 1D hypotheses
     #  @ingroup l3_hypos_1dhyps
     def ReversedEdgeIndices(self, reverseList):
index de84b50262e8a2ad60486d545355d343ac43a2d1..2dde1b291e4c8f0faa8aba9db668a1ae7acb95ec 100644 (file)
@@ -75,8 +75,10 @@ ENDIF(SALOME_SMESH_ENABLE_MEFISTO)
 # header files / no moc processing
 SET(StdMeshers_HEADERS
   StdMeshers_LocalLength.hxx
+  StdMeshers_Reversible1D.hxx
   StdMeshers_StartEndLength.hxx
   StdMeshers_Arithmetic1D.hxx
+  StdMeshers_Geometric1D.hxx
   StdMeshers_FixedPoints1D.hxx
   StdMeshers_NumberOfSegments.hxx
   StdMeshers_Deflection1D.hxx
@@ -136,8 +138,10 @@ ENDIF(SALOME_SMESH_ENABLE_MEFISTO)
 # sources / static
 SET(StdMeshers_SOURCES
   StdMeshers_LocalLength.cxx
+  StdMeshers_Reversible1D.cxx
   StdMeshers_StartEndLength.cxx
   StdMeshers_Arithmetic1D.cxx
+  StdMeshers_Geometric1D.cxx
   StdMeshers_FixedPoints1D.cxx
   StdMeshers_NumberOfSegments.cxx
   StdMeshers_Deflection1D.cxx
index fa4aa909f70bbb4552187ed3de3d359f22426b4f..369d4e424151d5fc98bc5a89379911ca15926c25 100644 (file)
 
 #include "utilities.h"
 
-#include <Precision.hxx>
-#include <Bnd_Box.hxx>
-
 #include <limits>
 
+#include <Bnd_Box.hxx>
+#include <Precision.hxx>
+#include <gp_Vec.hxx>
+
 using namespace std;
 
 //=======================================================================
@@ -48,10 +49,23 @@ StdMeshers_CartesianParameters3D::StdMeshers_CartesianParameters3D(int         h
                                                                    int         studyId,
                                                                    SMESH_Gen * gen)
   : SMESH_Hypothesis(hypId, studyId, gen),
-    _sizeThreshold( 4.0 ) // default according to the customer specification
+    _sizeThreshold( 4.0 ), // default according to the customer specification
+    _toAddEdges( false )
 {
   _name = "CartesianParameters3D"; // used by "Cartesian_3D"
   _param_algo_dim = 3; // 3D
+
+  _axisDirs[0] = 1.;
+  _axisDirs[1] = 0.;
+  _axisDirs[2] = 0.;
+
+  _axisDirs[3] = 0.;
+  _axisDirs[4] = 1.;
+  _axisDirs[5] = 0.;
+
+  _axisDirs[6] = 0.;
+  _axisDirs[7] = 0.;
+  _axisDirs[8] = 1.;
 }
 
 
@@ -308,6 +322,44 @@ void StdMeshers_CartesianParameters3D::GetCoordinates(std::vector<double>& xNode
     zNodes = _coords[2];
 }
 
+//=======================================================================
+//function : SetAxisDirs
+//purpose  : Sets directions of axes
+//=======================================================================
+
+void StdMeshers_CartesianParameters3D::SetAxisDirs(const double* the9DirComps)
+  throw ( SALOME_Exception )
+{
+  gp_Vec x( the9DirComps[0],
+            the9DirComps[1],
+            the9DirComps[2] );
+  gp_Vec y( the9DirComps[3],
+            the9DirComps[4],
+            the9DirComps[5] );
+  gp_Vec z( the9DirComps[6],
+            the9DirComps[7],
+            the9DirComps[8] );
+  if ( x.Magnitude() < RealSmall() ||
+       y.Magnitude() < RealSmall() ||
+       z.Magnitude() < RealSmall() )
+    throw SALOME_Exception("Zero magnitude of axis direction");
+
+  if ( x.IsParallel( y, M_PI / 180. ) ||
+       x.IsParallel( z, M_PI / 180. ) ||
+       y.IsParallel( z, M_PI / 180. ))
+    throw SALOME_Exception("Parallel axis directions");
+
+  bool isChanged = false;
+  for ( int i = 0; i < 9; ++i )
+  {
+    if ( Abs( _axisDirs[i] - the9DirComps[i] ) > 1e-7 )
+      isChanged = true;
+    _axisDirs[i] = the9DirComps[i];
+  }
+  if ( isChanged )
+    NotifySubMeshesHypothesisModification();
+}
+
 //=======================================================================
 //function : GetGrid
 //purpose  : Return coordinates of node positions along the three axes
@@ -332,6 +384,33 @@ double StdMeshers_CartesianParameters3D::GetSizeThreshold() const
   return _sizeThreshold;
 }
 
+//=======================================================================
+//function : SetToAddEdges
+//purpose  : Enables implementation of geometrical edges into the mesh. If this feature
+//           is disabled, sharp edges of the shape are lost ("smoothed") in the mesh if
+//           they don't coincide with the grid lines
+//=======================================================================
+
+void StdMeshers_CartesianParameters3D::SetToAddEdges(bool toAdd)
+{
+  if ( _toAddEdges != toAdd )
+  {
+    _toAddEdges = toAdd;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=======================================================================
+//function : GetToAddEdges
+//purpose  : Returns true if implementation of geometrical edges into the
+//           mesh is enabled
+//=======================================================================
+
+bool StdMeshers_CartesianParameters3D::GetToAddEdges() const
+{
+  return _toAddEdges;
+}
+
 //=======================================================================
 //function : IsDefined
 //purpose  : Return true if parameters are well defined
@@ -369,6 +448,7 @@ std::ostream & StdMeshers_CartesianParameters3D::SaveTo(std::ostream & save)
     for ( size_t j = 0; j < _spaceFunctions[i].size(); ++j )
       save << _spaceFunctions[i][j] << " ";
   }
+  save << _toAddEdges << " ";
 
   return save;
 }
@@ -382,7 +462,7 @@ std::istream & StdMeshers_CartesianParameters3D::LoadFrom(std::istream & load)
 {
   bool ok;
 
-  ok = (load >> _sizeThreshold  );
+  ok = ( load >> _sizeThreshold );
   for ( int ax = 0; ax < 3; ++ax )
   {
     if (ok)
@@ -419,6 +499,9 @@ std::istream & StdMeshers_CartesianParameters3D::LoadFrom(std::istream & load)
       }
     }
   }
+
+  load >> _toAddEdges;
+
   return load;
 }
 
index adb22f00c777f6b832cb3af2446a1ff7f417ce1d..98970956bc8dcc2a62f80a9d2b789fbe5a8b73e5 100644 (file)
@@ -100,6 +100,10 @@ public:
                       std::vector<double>& yNodes,
                       std::vector<double>& zNodes,
                       const Bnd_Box&       bndBox) const throw ( SALOME_Exception );
+
+  void SetAxisDirs(const double* the9DirComps) throw ( SALOME_Exception );
+  const double* GetAxisDirs() const { return _axisDirs; }
+
   /*!
    * Set size threshold. A polyhedral cell got by cutting an initial
    * hexahedron by geometry boundary is considered small and is removed if
@@ -111,6 +115,14 @@ public:
    */
   double GetSizeThreshold() const;
 
+  /*!
+   * \brief Enables implementation of geometrical edges into the mesh. If this feature
+   *        is disabled, sharp edges of the shape are lost ("smoothed") in the mesh if
+   *        they don't coincide with the grid lines
+   */
+  void SetToAddEdges(bool toAdd);
+  bool GetToAddEdges() const;
+
   /*!
    * \brief Return true if parameters are well defined
    */
@@ -138,7 +150,10 @@ public:
   std::vector<std::string> _spaceFunctions[3];
   std::vector<double>      _internalPoints[3];
 
+  double _axisDirs[9];
+
   double _sizeThreshold;
+  bool   _toAddEdges;
 };
 
 #endif
index 83447b16ad03c512985434201081969d430a388b..36b2e2d486ba7abc93a35a86feec2001d705e019 100644 (file)
 #include "SMESH_subMeshEventListener.hxx"
 #include "StdMeshers_CartesianParameters3D.hxx"
 
-#include "utilities.h"
-#include "Utils_ExceptHandlers.hxx"
+#include <utilities.h>
+#include <Utils_ExceptHandlers.hxx>
 #include <Basics_OCCTVersion.hxx>
 
+#include <BRepAdaptor_Curve.hxx>
 #include <BRepAdaptor_Surface.hxx>
 #include <BRepBndLib.hxx>
 #include <BRepBuilderAPI_Copy.hxx>
@@ -44,6 +45,7 @@
 #include <BRep_Tool.hxx>
 #include <Bnd_Box.hxx>
 #include <ElSLib.hxx>
+#include <GCPnts_UniformDeflection.hxx>
 #include <Geom2d_BSplineCurve.hxx>
 #include <Geom2d_BezierCurve.hxx>
 #include <Geom2d_TrimmedCurve.hxx>
@@ -63,7 +65,6 @@
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
 #include <TopLoc_Location.hxx>
-#include <TopTools_MapIteratorOfMapOfShape.hxx>
 #include <TopTools_MapOfShape.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Face.hxx>
@@ -76,7 +77,7 @@
 #include <gp_Sphere.hxx>
 #include <gp_Torus.hxx>
 
-//#undef WITH_TBB
+#undef WITH_TBB
 #ifdef WITH_TBB
 #include <tbb/parallel_for.h>
 //#include <tbb/enumerable_thread_specific.h>
@@ -150,6 +151,8 @@ bool StdMeshers_Cartesian_3D::CheckHypothesis (SMESH_Mesh&          aMesh,
 
 namespace
 {
+  typedef int TGeomID;
+
   //=============================================================================
   // Definitions of internal utils
   // --------------------------------------------------------------------------
@@ -161,17 +164,40 @@ namespace
   };
   // --------------------------------------------------------------------------
   /*!
-   * \brief Data of intersection between a GridLine and a TopoDS_Face
+   * \brief Common data of any intersection between a Grid and a shape
    */
-  struct IntersectionPoint
+  struct B_IntersectPoint
   {
-    double                       _paramOnLine;
-    mutable Transition           _transition;
     mutable const SMDS_MeshNode* _node;
-    mutable size_t               _indexOnLine;
+    mutable vector< TGeomID >    _faceIDs;
+
+    B_IntersectPoint(): _node(NULL) {}
+    void Add( const vector< TGeomID >& fIDs, const SMDS_MeshNode* n=0 ) const;
+    bool HasCommonFace( const B_IntersectPoint * other ) const;
+    bool IsOnFace( int faceID ) const;
+    virtual ~B_IntersectPoint() {}
+  };
+  // --------------------------------------------------------------------------
+  /*!
+   * \brief Data of intersection between a GridLine and a TopoDS_Face
+   */
+  struct F_IntersectPoint : public B_IntersectPoint
+  {
+    double             _paramOnLine;
+    mutable Transition _transition;
+    mutable size_t     _indexOnLine;
 
-    IntersectionPoint(): _node(0) {}
-    bool operator< ( const IntersectionPoint& o ) const { return _paramOnLine < o._paramOnLine; }
+    bool operator< ( const F_IntersectPoint& o ) const { return _paramOnLine < o._paramOnLine; }
+  };
+  // --------------------------------------------------------------------------
+  /*!
+   * \brief Data of intersection between GridPlanes and a TopoDS_EDGE
+   */
+  struct E_IntersectPoint : public B_IntersectPoint
+  {
+    gp_Pnt  _point;
+    double  _uvw[3];
+    TGeomID _shapeID;
   };
   // --------------------------------------------------------------------------
   /*!
@@ -181,10 +207,23 @@ namespace
   {
     gp_Lin _line;
     double _length; // line length
-    multiset< IntersectionPoint > _intPoints;
+    multiset< F_IntersectPoint > _intPoints;
 
     void RemoveExcessIntPoints( const double tol );
-    bool GetIsOutBefore( multiset< IntersectionPoint >::iterator ip, bool prevIsOut );
+    bool GetIsOutBefore( multiset< F_IntersectPoint >::iterator ip, bool prevIsOut );
+  };
+  // --------------------------------------------------------------------------
+  /*!
+   * \brief Planes of the grid used to find intersections of an EDGE with a hexahedron
+   */
+  struct GridPlanes
+  {
+    double _factor;
+    gp_XYZ _uNorm, _vNorm, _zNorm;
+    vector< gp_XYZ > _origins; // origin points of all planes in one direction
+    vector< double > _zProjs;  // projections of origins to _zNorm
+
+    gp_XY GetUV( const gp_Pnt& p, const gp_Pnt& origin );
   };
   // --------------------------------------------------------------------------
   /*!
@@ -234,11 +273,15 @@ namespace
   struct Grid
   {
     vector< double >   _coords[3]; // coordinates of grid nodes
+    gp_XYZ             _axes  [3]; // axis directions
     vector< GridLine > _lines [3]; //  in 3 directions
     double             _tol, _minCellSize;
 
-    vector< const SMDS_MeshNode* > _nodes; // mesh nodes at grid nodes
-    vector< bool >                 _isBndNode; // is mesh node at intersection with geometry
+    vector< const SMDS_MeshNode* >    _nodes; // mesh nodes at grid nodes
+    vector< const F_IntersectPoint* > _gridIntP; // grid node intersection with geometry
+
+    list< E_IntersectPoint >          _edgeIntP; // intersections with EDGEs
+    TopTools_IndexedMapOfShape        _shapes;
 
     size_t CellIndex( size_t i, size_t j, size_t k ) const
     {
@@ -257,6 +300,7 @@ namespace
     void SetCoordinates(const vector<double>& xCoords,
                         const vector<double>& yCoords,
                         const vector<double>& zCoords,
+                        const double*         axesDirs,
                         const TopoDS_Shape&   shape );
     void ComputeNodes(SMESH_MesherHelper& helper);
   };
@@ -302,10 +346,11 @@ namespace
   struct FaceGridIntersector
   {
     TopoDS_Face _face;
+    TGeomID     _faceID;
     Grid*       _grid;
     Bnd_Box     _bndBox;
     __IntCurvesFace_Intersector* _surfaceInt;
-    vector< std::pair< GridLine*, IntersectionPoint > > _intersections;
+    vector< std::pair< GridLine*, F_IntersectPoint > > _intersections;
 
     FaceGridIntersector(): _grid(0), _surfaceInt(0) {}
     void Intersect();
@@ -314,7 +359,12 @@ namespace
     void StoreIntersections()
     {
       for ( size_t i = 0; i < _intersections.size(); ++i )
-        _intersections[i].first->_intPoints.insert( _intersections[i].second );
+      {
+        multiset< F_IntersectPoint >::iterator ip = 
+          _intersections[i].first->_intPoints.insert( _intersections[i].second );
+        ip->_faceIDs.reserve( 1 );
+        ip->_faceIDs.push_back( _faceID );
+      }
     }
     const Bnd_Box& GetFaceBndBox()
     {
@@ -352,7 +402,7 @@ namespace
     gp_Torus    _torus;
     __IntCurvesFace_Intersector* _surfaceInt;
 
-    vector< IntersectionPoint > _intPoints;
+    vector< F_IntersectPoint > _intPoints;
 
     void IntersectWithPlane   (const GridLine& gridLine);
     void IntersectWithCylinder(const GridLine& gridLine);
@@ -381,20 +431,54 @@ namespace
     struct _Face;
     struct _Link;
     // --------------------------------------------------------------------------------
-    struct _Node //!< node either at a hexahedron corner or at GridLine intersection
+    struct _Node //!< node either at a hexahedron corner or at intersection
     {
-      const SMDS_MeshNode*     _node; // mesh node at hexahedron corner
-      const IntersectionPoint* _intPoint;
-
-      _Node(const SMDS_MeshNode* n=0, const IntersectionPoint* ip=0):_node(n), _intPoint(ip) {} 
-      const SMDS_MeshNode* Node() const { return _intPoint ? _intPoint->_node : _node; }
-      //bool IsCorner() const { return _node; }
+      const SMDS_MeshNode*       _node; // mesh node at hexahedron corner
+      const B_IntersectPoint* _intPoint;
+
+      _Node(const SMDS_MeshNode* n=0, const B_IntersectPoint* ip=0):_node(n), _intPoint(ip) {} 
+      const SMDS_MeshNode*    Node() const
+      { return ( _intPoint && _intPoint->_node ) ? _intPoint->_node : _node; }
+      const F_IntersectPoint* FaceIntPnt() const
+      { return static_cast< const F_IntersectPoint* >( _intPoint ); }
+      const E_IntersectPoint* EdgeIntPnt() const
+      { return static_cast< const E_IntersectPoint* >( _intPoint ); }
+      void Add( const E_IntersectPoint* ip )
+      {
+        if ( !_intPoint ) {
+          _intPoint = ip;
+        }
+        else if ( !_intPoint->_node ) {
+          ip->Add( _intPoint->_faceIDs );
+          _intPoint = ip;
+        }
+        else  {
+          _intPoint->Add( ip->_faceIDs );
+        }
+      }
+      bool IsLinked( const B_IntersectPoint* other ) const
+      {
+        return _intPoint && _intPoint->HasCommonFace( other );
+      }
+      bool IsOnFace( int faceID ) const // returns true if faceID is found
+      {
+        return _intPoint ? _intPoint->IsOnFace( faceID ) : false;
+      }
+      gp_Pnt Point() const
+      {
+        if ( const SMDS_MeshNode* n = Node() )
+          return SMESH_TNodeXYZ( n );
+        if ( const E_IntersectPoint* eip =
+             dynamic_cast< const E_IntersectPoint* >( _intPoint ))
+          return eip->_point;
+        return gp_Pnt( 1e100, 0, 0 );
+      }
     };
     // --------------------------------------------------------------------------------
     struct _Link // link connecting two _Node's
     {
       _Node* _nodes[2];
-      vector< _Node _intNodes; // _Node's at GridLine intersections
+      vector< _Node > _intNodes; // _Node's at GridLine intersections
       vector< _Link > _splits;
       vector< _Face*> _faces;
     };
@@ -412,21 +496,38 @@ namespace
       }
       _Node* FirstNode() const { return _link->_nodes[ _reverse ]; }
       _Node* LastNode() const { return _link->_nodes[ !_reverse ]; }
+      operator bool() const { return _link; }
+      vector< TGeomID > GetNotUsedFace(const set<TGeomID>& usedIDs ) const // returns a supporting FACEs
+      {
+        vector< TGeomID > faces;
+        const B_IntersectPoint *ip0, *ip1;
+        if (( ip0 = _link->_nodes[0]->_intPoint ) &&
+            ( ip1 = _link->_nodes[1]->_intPoint ))
+        {
+          for ( size_t i = 0; i < ip0->_faceIDs.size(); ++i )
+            if ( ip1->IsOnFace ( ip0->_faceIDs[i] ) &&
+                 !usedIDs.count( ip0->_faceIDs[i] ) )
+              faces.push_back( ip0->_faceIDs[i] );
+        }
+        return faces;
+      }
     };
     // --------------------------------------------------------------------------------
     struct _Face
     {
-      vector< _OrientedLink > _links;
-      vector< _Link >         _polyLinks; // links added to close a polygonal face
+      vector< _OrientedLink > _links;       // links on GridLine's
+      vector< _Link >         _polyLinks;   // links added to close a polygonal face
+      vector< _Node >         _edgeNodes;   // nodes at intersection with EDGEs
     };
     // --------------------------------------------------------------------------------
     struct _volumeDef // holder of nodes of a volume mesh element
     {
-      vector< const SMDS_MeshNode* > _nodes;
-      vector< int >                  _quantities;
+      //vector< const SMDS_MeshNode* > _nodes;
+      vector< _Node* > _nodes;
+      vector< int >    _quantities;
       typedef boost::shared_ptr<_volumeDef> Ptr;
-      void set( const vector< const SMDS_MeshNode* >& nodes,
-                const vector< int > quant = vector< int >() )
+      void set( const vector< _Node* >& nodes,
+                const vector< int >&    quant = vector< int >() )
       { _nodes = nodes; _quantities = quant; }
       // static Ptr New( const vector< const SMDS_MeshNode* >& nodes,
       //                 const vector< int > quant = vector< int >() )
@@ -440,13 +541,19 @@ namespace
 
     // topology of a hexahedron
     int   _nodeShift[8];
-    _Node _hexNodes[8];
-    _Link _hexLinks[12];
-    _Face _hexQuads[6];
+    _Node _hexNodes [8];
+    _Link _hexLinks [12];
+    _Face _hexQuads [6];
 
     // faces resulted from hexahedron intersection
     vector< _Face > _polygons;
 
+    // intresections with EDGEs
+    vector< const E_IntersectPoint* > _edgeIntPnts;
+
+    // nodes inside the hexahedron (at VERTEXes)
+    vector< _Node > _vertexNodes;
+
     // computed volume elements
     //vector< _volumeDef::Ptr > _volumeDefs;
     _volumeDef _volumeDefs;
@@ -459,7 +566,8 @@ namespace
 
   public:
     Hexahedron(const double sizeThreshold, Grid* grid);
-    int MakeElements(SMESH_MesherHelper& helper);
+    int MakeElements(SMESH_MesherHelper&                      helper,
+                     const map< TGeomID, vector< TGeomID > >& edge2faceIDsMap);
     void ComputeElements();
     void Init() { init( _i, _j, _k ); }
 
@@ -467,6 +575,17 @@ namespace
     Hexahedron(const Hexahedron& other );
     void init( size_t i, size_t j, size_t k );
     void init( size_t i );
+    void addEdges(SMESH_MesherHelper&                      helper,
+                  vector< Hexahedron* >&                   intersectedHex,
+                  const map< TGeomID, vector< TGeomID > >& edge2faceIDsMap);
+    gp_Pnt findIntPoint( double u1, double proj1, double u2, double proj2,
+                         double proj, BRepAdaptor_Curve& curve,
+                         const gp_XYZ& axis, const gp_XYZ& origin );
+    int  getEntity( const E_IntersectPoint* ip, int* facets, int& sub );
+    bool addIntersection( const E_IntersectPoint& ip,
+                          vector< Hexahedron* >&  hexes,
+                          int ijk[], int dIJK[] );
+    bool findChain( _Node* n1, _Node* n2, _Face& quad, vector<_Node*>& chainNodes );
     int  addElements(SMESH_MesherHelper& helper);
     bool isInHole() const;
     bool checkPolyhedronSize() const;
@@ -474,8 +593,17 @@ namespace
     bool addTetra();
     bool addPenta();
     bool addPyra ();
+    _Node* FindEqualNode( vector< _Node >&        nodes,
+                          const E_IntersectPoint* ip,
+                          const double            tol2 )
+    {
+      for ( size_t i = 0; i < nodes.size(); ++i )
+        if ( nodes[i].Point().SquareDistance( ip->_point ) <= tol2 )
+          return & nodes[i];
+      return 0;
+    }
   };
+
 #ifdef WITH_TBB
   // --------------------------------------------------------------------------
   /*!
@@ -507,11 +635,34 @@ namespace
         _faceVec[i].Intersect();
     }
   };
-
 #endif
+
   //=============================================================================
   // Implementation of internal utils
   //=============================================================================
+  /*!
+   * \brief adjust \a i to have \a val between values[i] and values[i+1]
+   */
+  inline void locateValue( int & i, double val, const vector<double>& values,
+                           int& di, double tol )
+  {
+    val += values[0]; // input \a val is measured from 0.
+    if ( i > values.size()-2 )
+      i = values.size()-2;
+    else
+      while ( i+2 < values.size() && val > values[ i+1 ])
+        ++i;
+    while ( i > 0 && val < values[ i ])
+      --i;
+
+    if ( i > 0 && val - values[ i ] < tol )
+      di = -1;
+    else if ( i+2 < values.size() && values[ i+1 ] - val < tol )
+      di = 1;
+    else
+      di = 0;
+  }
+  //=============================================================================
   /*
    * Remove coincident intersection points
    */
@@ -520,15 +671,16 @@ namespace
     if ( _intPoints.size() < 2 ) return;
 
     set< Transition > tranSet;
-    multiset< IntersectionPoint >::iterator ip1, ip2 = _intPoints.begin();
+    multiset< F_IntersectPoint >::iterator ip1, ip2 = _intPoints.begin();
     while ( ip2 != _intPoints.end() )
     {
       tranSet.clear();
       ip1 = ip2++;
-      while ( ip2->_paramOnLine - ip1->_paramOnLine <= tol  && ip2 != _intPoints.end())
+      while ( ip2 != _intPoints.end() && ip2->_paramOnLine - ip1->_paramOnLine <= tol )
       {
         tranSet.insert( ip1->_transition );
         tranSet.insert( ip2->_transition );
+        ip2->Add( ip1->_faceIDs );
         _intPoints.erase( ip1 );
         ip1 = ip2++;
       }
@@ -547,7 +699,7 @@ namespace
   /*
    * Return "is OUT" state for nodes before the given intersection point
    */
-  bool GridLine::GetIsOutBefore( multiset< IntersectionPoint >::iterator ip, bool prevIsOut )
+  bool GridLine::GetIsOutBefore( multiset< F_IntersectPoint >::iterator ip, bool prevIsOut )
   {
     if ( ip->_transition == Trans_IN )
       return true;
@@ -558,7 +710,7 @@ namespace
       // singularity point (apex of a cone)
       if ( _intPoints.size() == 1 || ip == _intPoints.begin() )
         return true;
-      multiset< IntersectionPoint >::iterator ipBef = ip, ipAft = ++ip;
+      multiset< F_IntersectPoint >::iterator ipBef = ip, ipAft = ++ip;
       if ( ipAft == _intPoints.end() )
         return false;
       --ipBef;
@@ -569,13 +721,65 @@ namespace
     return prevIsOut; // _transition == Trans_TANGENT
   }
   //================================================================================
+  /*
+   * Returns parameters of a point in i-th plane
+   */
+  gp_XY GridPlanes::GetUV( const gp_Pnt& p, const gp_Pnt& origin )
+  {
+    gp_Vec v( origin, p );
+    return gp_XY( v.Dot( _uNorm ) * _factor,
+                  v.Dot( _vNorm ) * _factor );
+  }
+  //================================================================================
+  /*
+   * Adds face IDs
+   */
+  void B_IntersectPoint::Add( const vector< TGeomID >& fIDs,
+                              const SMDS_MeshNode*     n) const
+  {
+    if ( _faceIDs.empty() )
+      _faceIDs = fIDs;
+    else
+      for ( size_t i = 0; i < fIDs.size(); ++i )
+      {
+        vector< TGeomID >::iterator it =
+          std::find( _faceIDs.begin(), _faceIDs.end(), fIDs[i] );
+        if ( it == _faceIDs.end() )
+          _faceIDs.push_back( fIDs[i] );
+      }
+    if ( !_node )
+      _node = n;
+  }
+  //================================================================================
+  /*
+   * Returns \c true if \a other B_IntersectPoint holds the same face ID
+   */
+  bool B_IntersectPoint::HasCommonFace( const B_IntersectPoint * other ) const
+  {
+    if ( other )
+      for ( size_t i = 0; i < other->_faceIDs.size(); ++i )
+        if ( IsOnFace( other->_faceIDs[i] ) )
+          return true;
+    return false;
+  }
+  //================================================================================
+  /*
+   * Returns \c true if \a faceID in in this->_faceIDs
+   */
+  bool B_IntersectPoint::IsOnFace( int faceID ) const // returns true if faceID is found
+  {
+    vector< TGeomID >::const_iterator it =
+      std::find( _faceIDs.begin(), _faceIDs.end(), faceID );
+    return ( it != _faceIDs.end() );
+  }
+  //================================================================================
   /*
    * Return an iterator on GridLine's in a given direction
    */
   LineIndexer Grid::GetLineIndexer(size_t iDir) const
   {
     const size_t indices[] = { 1,2,0, 0,2,1, 0,1,2 };
-    const string s[] = { "X", "Y", "Z" };
+    const string s      [] = { "X", "Y", "Z" };
     LineIndexer li( _coords[0].size(),  _coords[1].size(),    _coords[2].size(),
                     indices[iDir*3],    indices[iDir*3+1],    indices[iDir*3+2],
                     s[indices[iDir*3]], s[indices[iDir*3+1]], s[indices[iDir*3+2]]);
@@ -588,11 +792,21 @@ namespace
   void Grid::SetCoordinates(const vector<double>& xCoords,
                             const vector<double>& yCoords,
                             const vector<double>& zCoords,
+                            const double*         axesDirs,
                             const TopoDS_Shape&   shape)
   {
     _coords[0] = xCoords;
     _coords[1] = yCoords;
     _coords[2] = zCoords;
+    _axes[0].SetCoord( axesDirs[0],
+                       axesDirs[1],
+                       axesDirs[2]);
+    _axes[1].SetCoord( axesDirs[3],
+                       axesDirs[4],
+                       axesDirs[5]);
+    _axes[2].SetCoord( axesDirs[6],
+                       axesDirs[7],
+                       axesDirs[8]);
 
     // compute tolerance
     _minCellSize = Precision::Infinite();
@@ -649,7 +863,7 @@ namespace
     const size_t nbGridNodes = _coords[0].size() * _coords[1].size() * _coords[2].size();
     vector< bool > isNodeOut( nbGridNodes, false );
     _nodes.resize( nbGridNodes, 0 );
-    _isBndNode.resize( nbGridNodes, false );
+    _gridIntP.resize( nbGridNodes, NULL );
 
     for ( int iDir = 0; iDir < 3; ++iDir ) // loop on 3 line directions
     {
@@ -669,8 +883,8 @@ namespace
 
         GridLine& line = _lines[ iDir ][ li.LineIndex() ];
         line.RemoveExcessIntPoints( _tol );
-        multiset< IntersectionPoint >& intPnts = _lines[ iDir ][ li.LineIndex() ]._intPoints;
-        multiset< IntersectionPoint >::iterator ip = intPnts.begin();
+        multiset< F_IntersectPoint >& intPnts = _lines[ iDir ][ li.LineIndex() ]._intPoints;
+        multiset< F_IntersectPoint >::iterator ip = intPnts.begin();
 
         bool isOut = true;
         const double* nodeCoord = & coords[0], *coord0 = nodeCoord, *coordEnd = coord0 + coords.size();
@@ -706,14 +920,18 @@ namespace
           else
           {
             int nodeIndex = nIndex0 + nShift * ( nodeCoord-coord0 );
-            if ( ! _nodes[ nodeIndex ] )
+            if ( !_nodes[ nodeIndex ] )
             {
               li.SetIndexOnLine( nodeCoord-coord0 );
               double xyz[3] = { _coords[0][ li.I() ], _coords[1][ li.J() ], _coords[2][ li.K() ]};
-              _nodes[ nodeIndex ] = helper.AddNode( xyz[0], xyz[1], xyz[2] );
-              _isBndNode[ nodeIndex ] = true;
+              _nodes   [ nodeIndex ] = helper.AddNode( xyz[0], xyz[1], xyz[2] );
+              _gridIntP[ nodeIndex ] = & * ip;
             }
-            //ip->_node = _nodes[ nodeIndex ];
+            if ( _gridIntP[ nodeIndex ] )
+              _gridIntP[ nodeIndex ]->Add( ip->_faceIDs );
+            else
+              _gridIntP[ nodeIndex ] = & * ip;
+            // ip->_node        = _nodes[ nodeIndex ]; -- to differ from ip on links
             ip->_indexOnLine = nodeCoord-coord0;
             if ( ++nodeCoord < coordEnd )
               nodeParam = *nodeCoord - *coord0;
@@ -744,7 +962,7 @@ namespace
       LineIndexer li = GetLineIndexer( iDir );
       for ( ; li.More(); ++li )
       {
-        multiset< IntersectionPoint >& intPnts = _lines[ iDir ][ li.LineIndex() ]._intPoints;
+        multiset< F_IntersectPoint >& intPnts = _lines[ iDir ][ li.LineIndex() ]._intPoints;
         if ( intPnts.empty() ) continue;
         if ( intPnts.size() == 1 )
         {
@@ -944,7 +1162,7 @@ namespace
   {
     if ( !toClassify || UVIsOnFace() )
     {
-      IntersectionPoint p;
+      F_IntersectPoint p;
       p._paramOnLine = _w;
       p._transition  = _transition;
       _intPoints.push_back( p );
@@ -1291,16 +1509,18 @@ namespace
     _origNodeInd   = _grid->NodeIndex( i,j,k );
     for ( int iN = 0; iN < 8; ++iN )
     {
-      _hexNodes[iN]._node = _grid->_nodes[ _origNodeInd + _nodeShift[iN] ];
+      _hexNodes[iN]._node     = _grid->_nodes   [ _origNodeInd + _nodeShift[iN] ];
+      _hexNodes[iN]._intPoint = _grid->_gridIntP[ _origNodeInd + _nodeShift[iN] ];
       _nbCornerNodes += bool( _hexNodes[iN]._node );
-      _nbBndNodes    += _grid->_isBndNode[ _origNodeInd + _nodeShift[iN] ];
+      _nbBndNodes    += bool( _hexNodes[iN]._intPoint );
     }
 
     _sideLength[0] = _grid->_coords[0][i+1] - _grid->_coords[0][i];
     _sideLength[1] = _grid->_coords[1][j+1] - _grid->_coords[1][j];
     _sideLength[2] = _grid->_coords[2][k+1] - _grid->_coords[2][k];
 
-    if ( _nbCornerNodes < 8 && _nbIntNodes + _nbCornerNodes > 3)
+    if ( _nbIntNodes + _edgeIntPnts.size() > 0 &&
+         _nbIntNodes + _nbCornerNodes + _edgeIntPnts.size() > 3)
     {
       _Link split;
       // create sub-links (_splits) by splitting links with _intNodes
@@ -1309,21 +1529,120 @@ namespace
         _Link& link = _hexLinks[ iLink ];
         link._splits.clear();
         split._nodes[ 0 ] = link._nodes[0];
-        for ( size_t i = 0; i < link._intNodes.size(); ++ i )
+        bool isOut = ( ! link._nodes[0]->Node() );
+        //int iEnd = link._intNodes.size() - bool( link._nodes[1]->_intPoint );
+        for ( size_t i = 0; i < link._intNodes.size(); ++i )
         {
-          if ( split._nodes[ 0 ]->Node() )
+          if ( link._intNodes[i].Node() )
           {
-            split._nodes[ 1 ] = &link._intNodes[i];
-            link._splits.push_back( split );
+            if ( split._nodes[ 0 ]->Node() && !isOut )
+            {
+              split._nodes[ 1 ] = &link._intNodes[i];
+              link._splits.push_back( split );
+            }
+            split._nodes[ 0 ] = &link._intNodes[i];
+          }
+          switch ( link._intNodes[i].FaceIntPnt()->_transition ) {
+          case Trans_OUT: isOut = true; break;
+          case Trans_IN : isOut = false; break;
+          default:; // isOut remains the same
           }
-          split._nodes[ 0 ] = &link._intNodes[i];
         }
-        if ( link._nodes[ 1 ]->Node() && split._nodes[ 0 ]->Node() )
+        if ( link._nodes[ 1 ]->Node() && split._nodes[ 0 ]->Node() && !isOut )
         {
           split._nodes[ 1 ] = link._nodes[1];
           link._splits.push_back( split );
         }
       }
+
+      // Create _Node's at intersections with EDGEs.
+
+      const double tol2 = _grid->_tol * _grid->_tol;
+      int facets[3], nbFacets, subEntity;
+
+      for ( size_t iP = 0; iP < _edgeIntPnts.size(); ++iP )
+      {
+        nbFacets = getEntity( _edgeIntPnts[iP], facets, subEntity );
+        _Node* equalNode = 0;
+        switch( nbFacets ) {
+        case 1: // in a _Face
+        {
+          _Face& quad = _hexQuads[ facets[0] - SMESH_Block::ID_FirstF ];
+          equalNode = FindEqualNode( quad._edgeNodes, _edgeIntPnts[ iP ], tol2 );
+          if ( equalNode ) {
+            equalNode->Add( _edgeIntPnts[ iP ] );
+          }
+          else {
+            quad._edgeNodes.push_back( _Node( 0, _edgeIntPnts[ iP ]));
+            ++_nbIntNodes;
+          }
+          break;
+        }
+        case 2: // on a _Link
+        {
+          _Link& link = _hexLinks[ subEntity - SMESH_Block::ID_FirstE ];
+          if ( link._splits.size() > 0 )
+          {
+            equalNode = FindEqualNode( link._intNodes, _edgeIntPnts[ iP ], tol2 );
+            if ( equalNode )
+              equalNode->Add( _edgeIntPnts[ iP ] );
+          }
+          else
+          {
+            for ( int iF = 0; iF < 2; ++iF )
+            {
+              _Face& quad = _hexQuads[ facets[iF] - SMESH_Block::ID_FirstF ];
+              equalNode = FindEqualNode( quad._edgeNodes, _edgeIntPnts[ iP ], tol2 );
+              if ( equalNode ) {
+                equalNode->Add( _edgeIntPnts[ iP ] );
+              }
+              else {
+                quad._edgeNodes.push_back( _Node( 0, _edgeIntPnts[ iP ]));
+                ++_nbIntNodes;
+              }
+            }
+          }
+          break;
+        }
+        case 3: // at a corner
+        {
+          _Node& node = _hexNodes[ subEntity - SMESH_Block::ID_FirstV ];
+          if ( node.Node() > 0 )
+          {
+            if ( node._intPoint )
+              node._intPoint->Add( _edgeIntPnts[ iP ]->_faceIDs, _edgeIntPnts[ iP ]->_node );
+          }
+          else
+          {
+            for ( int iF = 0; iF < 3; ++iF )
+            {
+              _Face& quad = _hexQuads[ facets[iF] - SMESH_Block::ID_FirstF ];
+              equalNode = FindEqualNode( quad._edgeNodes, _edgeIntPnts[ iP ], tol2 );
+              if ( equalNode ) {
+                equalNode->Add( _edgeIntPnts[ iP ] );
+              }
+              else {
+                quad._edgeNodes.push_back( _Node( 0, _edgeIntPnts[ iP ]));
+                ++_nbIntNodes;
+              }
+            }
+          }
+          break;
+        }
+        default: // inside a hex
+        {
+          equalNode = FindEqualNode( _vertexNodes, _edgeIntPnts[ iP ], tol2 );
+          if ( equalNode ) {
+            equalNode->Add( _edgeIntPnts[ iP ] );
+          }
+          else {
+            _vertexNodes.push_back( _Node( 0, _edgeIntPnts[iP] ));
+            ++_nbIntNodes;
+          }
+        }
+        } // switch( nbFacets )
+
+      } // loop on _edgeIntPnts
     }
   }
   //================================================================================
@@ -1351,87 +1670,173 @@ namespace
     if ( _nbCornerNodes + _nbIntNodes < 4 )
       return;
 
-    if ( _nbBndNodes == _nbCornerNodes && isInHole() )
+    if ( _nbBndNodes == _nbCornerNodes && _nbIntNodes == 0 && isInHole() )
       return;
 
     _polygons.clear();
-
-    vector<const SMDS_MeshNode* > polyhedraNodes;
-    vector<int>                   quantities;
+    _polygons.reserve( 10 );
 
     // create polygons from quadrangles and get their nodes
 
-    vector<_Node*> nodes;
-    nodes.reserve( _nbCornerNodes + _nbIntNodes );
-
     _Link polyLink;
-    polyLink._faces.reserve( 1 );
+    vector< _OrientedLink > splits;
+    vector<_Node*> chainNodes;
+
+    bool hasEdgeIntersections = !_edgeIntPnts.empty();
 
     for ( int iF = 0; iF < 6; ++iF ) // loop on 6 sides of a hexahedron
     {
-      const _Face& quad = _hexQuads[ iF ] ;
+      _Face& quad = _hexQuads[ iF ] ;
 
       _polygons.resize( _polygons.size() + 1 );
-      _Face& polygon = _polygons.back();
-      polygon._links.clear();
-      polygon._polyLinks.clear(); polygon._polyLinks.reserve( 10 );
+      _Face* polygon = &_polygons.back();
+      polygon->_polyLinks.reserve( 20 );
 
-      // add splits of a link to a polygon and collect info on nodes
-      //int nbIn = 0, nbOut = 0, nbCorners = 0;
-      nodes.clear();
+      splits.clear();
       for ( int iE = 0; iE < 4; ++iE ) // loop on 4 sides of a quadrangle
+        for ( int iS = 0; iS < quad._links[ iE ].NbResultLinks(); ++iS )
+          splits.push_back( quad._links[ iE ].ResultLink( iS ));
+
+      // add splits of links to a polygon and add _polyLinks to make
+      // polygon's boundary closed
+
+      int nbSplits = splits.size();
+      if ( nbSplits < 2 && quad._edgeNodes.empty() )
+        nbSplits = 0;
+
+      if ( nbSplits == 0 && !quad._edgeNodes.empty() )
+      {
+        // make _vertexNodes from _edgeNodes of an empty quad
+        const double tol2 = _grid->_tol * _grid->_tol;
+        for ( size_t iP = 0; iP < quad._edgeNodes.size(); ++iP )
+        {
+          _Node* equalNode =
+            FindEqualNode( _vertexNodes, quad._edgeNodes[ iP ].EdgeIntPnt(), tol2 );
+          if ( equalNode )
+            equalNode->Add( quad._edgeNodes[ iP ].EdgeIntPnt() );
+          else
+            _vertexNodes.push_back( quad._edgeNodes[ iP ]);
+        }
+      }
+
+      while ( nbSplits > 0 )
       {
-        int nbSpits = quad._links[ iE ].NbResultLinks();
-        for ( int iS = 0; iS < nbSpits; ++iS )
+        size_t iS = 0;
+        while ( !splits[ iS ] )
+          ++iS;
+
+        if ( !polygon->_links.empty() )
+        {
+          _polygons.resize( _polygons.size() + 1 );
+          polygon = &_polygons.back();
+          polygon->_polyLinks.reserve( 20 );
+        }
+        polygon->_links.push_back( splits[ iS ] );
+        splits[ iS++ ]._link = 0;
+        --nbSplits;
+
+        _Node* nFirst = polygon->_links.back().FirstNode();
+        _Node *n1,*n2 = polygon->_links.back().LastNode();
+        for ( ; nFirst != n2 && iS < splits.size(); ++iS )
         {
-          _OrientedLink split = quad._links[ iE ].ResultLink( iS );
-          _Node* n = split.FirstNode();
-          if ( !polygon._links.empty() )
+          _OrientedLink& split = splits[ iS ];
+          if ( !split ) continue;
+
+          n1 = split.FirstNode();
+          if ( n1 != n2 )
           {
-            _Node* nPrev = polygon._links.back().LastNode();
-            if ( nPrev != n )
+            // try to connect to intersections with EDGES
+            if ( quad._edgeNodes.size() > 0  &&
+                 findChain( n2, n1, quad, chainNodes ))
             {
-              polyLink._nodes[0] = nPrev;
-              polyLink._nodes[1] = n;
-              polygon._polyLinks.push_back( polyLink );
-              polygon._links.push_back( _OrientedLink( &polygon._polyLinks.back() ));
-              nodes.push_back( nPrev );
+              for ( size_t i = 1; i < chainNodes.size(); ++i )
+              {
+                polyLink._nodes[0] = chainNodes[i-1];
+                polyLink._nodes[1] = chainNodes[i];
+                polygon->_polyLinks.push_back( polyLink );
+                polygon->_links.push_back( _OrientedLink( &polygon->_polyLinks.back() ));
+              }
             }
+            // try to connect to a split ending on the same FACE
+            else
+            {
+              _OrientedLink foundSplit;
+              for ( int i = iS; i < splits.size() && !foundSplit; ++i )
+                if (( foundSplit = splits[ i ]) &&
+                    ( n2->IsLinked( foundSplit.FirstNode()->_intPoint )))
+                {
+                  polyLink._nodes[0] = n2;
+                  polyLink._nodes[1] = foundSplit.FirstNode();
+                  polygon->_polyLinks.push_back( polyLink );
+                  polygon->_links.push_back( _OrientedLink( &polygon->_polyLinks.back() ));
+                  iS = i - 1;
+                }
+                else
+                {
+                  foundSplit._link = 0;
+                }
+              if ( foundSplit )
+              {
+                n2 = foundSplit.FirstNode();
+                continue;
+              }
+              else
+              {
+                if ( n2->IsLinked( nFirst->_intPoint ))
+                  break;
+                polyLink._nodes[0] = n2;
+                polyLink._nodes[1] = n1;
+                polygon->_polyLinks.push_back( polyLink );
+                polygon->_links.push_back( _OrientedLink( &polygon->_polyLinks.back() ));
+              }
+            }
+          }
+          polygon->_links.push_back( split );
+          split._link = 0;
+          --nbSplits;
+          n2 = polygon->_links.back().LastNode();
+
+        } // loop on splits
+
+        if ( nFirst != n2 ) // close a polygon
+        {
+          findChain( n2, nFirst, quad, chainNodes );
+          for ( size_t i = 1; i < chainNodes.size(); ++i )
+          {
+            polyLink._nodes[0] = chainNodes[i-1];
+            polyLink._nodes[1] = chainNodes[i];
+            polygon->_polyLinks.push_back( polyLink );
+            polygon->_links.push_back( _OrientedLink( &polygon->_polyLinks.back() ));
           }
-          polygon._links.push_back( split );
-          nodes.push_back( n );
         }
-      }
-      if ( polygon._links.size() > 1 )
-      {
-        _Node* n1 = polygon._links.back().LastNode();
-        _Node* n2 = polygon._links.front().FirstNode();
-        if ( n1 != n2 )
+
+        if ( polygon->_links.size() < 3 && nbSplits > 0 )
         {
-          polyLink._nodes[0] = n1;
-          polyLink._nodes[1] = n2;
-          polygon._polyLinks.push_back( polyLink );
-          polygon._links.push_back( _OrientedLink( &polygon._polyLinks.back() ));
-          nodes.push_back( n1 );
+          polygon->_polyLinks.clear();
+          polygon->_links.clear();
         }
-        // add polygon to its links
-        for ( size_t iL = 0; iL < polygon._links.size(); ++iL )
-          polygon._links[ iL ]._link->_faces.push_back( &polygon );
-        // store polygon nodes
-        quantities.push_back( nodes.size() );
-        for ( size_t i = 0; i < nodes.size(); ++i )
-          polyhedraNodes.push_back( nodes[i]->Node() );
-      }
-      else
-      {
-        _polygons.resize( _polygons.size() - 1 );
-      }
-    }
+      } // while ( nbSplits > 0 )
+
+      if ( polygon->_links.size() < 3 )
+        _polygons.pop_back();
+
+    }  // loop on 6 sides of a hexahedron
 
     // create polygons closing holes in a polyhedron
 
+    // add polygons to their links
+    for ( size_t iP = 0; iP < _polygons.size(); ++iP )
+    {
+      _Face& polygon = _polygons[ iP ];
+      for ( size_t iL = 0; iL < polygon._links.size(); ++iL )
+      {
+        polygon._links[ iL ]._link->_faces.reserve( 2 );
+        polygon._links[ iL ]._link->_faces.push_back( &polygon );
+      }
+    }
     // find free links
     vector< _OrientedLink* > freeLinks;
+    freeLinks.reserve(20);
     for ( size_t iP = 0; iP < _polygons.size(); ++iP )
     {
       _Face& polygon = _polygons[ iP ];
@@ -1439,58 +1844,157 @@ namespace
         if ( polygon._links[ iL ]._link->_faces.size() < 2 )
           freeLinks.push_back( & polygon._links[ iL ]);
     }
-    // make closed chains of free links
     int nbFreeLinks = freeLinks.size();
     if ( 0 < nbFreeLinks && nbFreeLinks < 3 ) return;
+
+    set<TGeomID> usedFaceIDs;
+
+    // make closed chains of free links
     while ( nbFreeLinks > 0 )
     {
-      nodes.clear();
       _polygons.resize( _polygons.size() + 1 );
       _Face& polygon = _polygons.back();
-      polygon._links.clear();
+      polygon._polyLinks.reserve( 20 );
+      polygon._links.reserve( 20 );
 
-      // get a remaining link to start from
       _OrientedLink* curLink = 0;
-      for ( size_t iL = 0; iL < freeLinks.size() && !curLink; ++iL )
-        if (( curLink = freeLinks[ iL ] ))
-          freeLinks[ iL ] = 0;
-      nodes.push_back( curLink->LastNode() );
-      polygon._links.push_back( *curLink );
-
-      // find all links connected to curLink
-      _Node* curNode = 0;
-      do
+      _Node*         curNode;
+      if ( !hasEdgeIntersections )
       {
-        curNode = curLink->FirstNode();
-        curLink = 0;
+        // get a remaining link to start from
         for ( size_t iL = 0; iL < freeLinks.size() && !curLink; ++iL )
-          if ( freeLinks[ iL ] && freeLinks[ iL ]->LastNode() == curNode )
-          {
-            curLink = freeLinks[ iL ];
+          if (( curLink = freeLinks[ iL ] ))
             freeLinks[ iL ] = 0;
-            nodes.push_back( curNode );
-            polygon._links.push_back( *curLink );
+        polygon._links.push_back( *curLink );
+        --nbFreeLinks;
+        do
+        {
+          // find all links connected to curLink
+          curNode = curLink->FirstNode();
+          curLink = 0;
+          for ( size_t iL = 0; iL < freeLinks.size() && !curLink; ++iL )
+            if ( freeLinks[ iL ] && freeLinks[ iL ]->LastNode() == curNode )
+            {
+              curLink = freeLinks[ iL ];
+              freeLinks[ iL ] = 0;
+              polygon._links.push_back( *curLink );
+              --nbFreeLinks;
+            }
+        } while ( curLink );
+      }
+      else // there are intersections with EDGEs
+      {
+        TGeomID curFace;
+        // get a remaining link to start from, one lying on minimal
+        // nb of FACEs
+        {
+          map< vector< TGeomID >, int > facesOfLink;
+          map< vector< TGeomID >, int >::iterator f2l;
+          for ( size_t iL = 0; iL < freeLinks.size(); ++iL )
+            if ( freeLinks[ iL ] )
+            {
+              f2l = facesOfLink.insert
+                ( make_pair( freeLinks[ iL ]->GetNotUsedFace( usedFaceIDs ), iL )).first;
+              if ( f2l->first.size() == 1 )
+                break;
+            }
+          f2l = facesOfLink.begin();
+          if ( f2l->first.empty() )
+            return;
+          curFace = f2l->first[0];
+          curLink = freeLinks[ f2l->second ];
+          freeLinks[ f2l->second ] = 0;
+        }
+        usedFaceIDs.insert( curFace );
+        polygon._links.push_back( *curLink );
+        --nbFreeLinks;
+
+        // find all links bounding a FACE of curLink
+        do
+        {
+          // go forward from curLink
+          curNode = curLink->LastNode();
+          curLink = 0;
+          for ( size_t iL = 0; iL < freeLinks.size() && !curLink; ++iL )
+            if ( freeLinks[ iL ] &&
+                 freeLinks[ iL ]->FirstNode() == curNode &&
+                 freeLinks[ iL ]->LastNode()->IsOnFace( curFace ))
+            {
+              curLink = freeLinks[ iL ];
+              freeLinks[ iL ] = 0;
+              polygon._links.push_back( *curLink );
+              --nbFreeLinks;
+            }
+        } while ( curLink );
+
+        std::reverse( polygon._links.begin(), polygon._links.end() );
+
+        curLink = & polygon._links.back();
+        do
+        {
+          // go backward from curLink
+          curNode = curLink->FirstNode();
+          curLink = 0;
+          for ( size_t iL = 0; iL < freeLinks.size() && !curLink; ++iL )
+            if ( freeLinks[ iL ] &&
+                 freeLinks[ iL ]->LastNode() == curNode &&
+                 freeLinks[ iL ]->FirstNode()->IsOnFace( curFace ))
+            {
+              curLink = freeLinks[ iL ];
+              freeLinks[ iL ] = 0;
+              polygon._links.push_back( *curLink );
+              --nbFreeLinks;
+            }
+        } while ( curLink );
+
+        curNode = polygon._links.back().FirstNode();
+
+        if ( polygon._links[0].LastNode() != curNode )
+        {
+          if ( !_vertexNodes.empty() )
+          {
+            // add links with _vertexNodes if not already used
+            for ( size_t iN = 0; iN < _vertexNodes.size(); ++iN )
+              if ( _vertexNodes[ iN ].IsOnFace( curFace ))
+              {
+                bool used = ( curNode == &_vertexNodes[ iN ] );
+                for ( size_t iL = 0; iL < polygon._links.size() && !used; ++iL )
+                  used = ( &_vertexNodes[ iN ] ==  polygon._links[ iL ].LastNode() );
+                if ( !used )
+                {
+                  polyLink._nodes[0] = &_vertexNodes[ iN ];
+                  polyLink._nodes[1] = curNode;
+                  polygon._polyLinks.push_back( polyLink );
+                  polygon._links.push_back( _OrientedLink( &polygon._polyLinks.back() ));
+                  freeLinks.push_back( &polygon._links.back() );
+                  ++nbFreeLinks;
+                  curNode = &_vertexNodes[ iN ];
+                }
+                // TODO: to reorder _vertexNodes within polygon, if there are several ones
+              }
           }
-      } while ( curLink );
+          polyLink._nodes[0] = polygon._links[0].LastNode();
+          polyLink._nodes[1] = curNode;
+          polygon._polyLinks.push_back( polyLink );
+          polygon._links.push_back( _OrientedLink( &polygon._polyLinks.back() ));
+          freeLinks.push_back( &polygon._links.back() );
+          ++nbFreeLinks;
+        }
 
-      nbFreeLinks -= polygon._links.size();
+      } // if there are intersections with EDGEs
 
-      if ( curNode != nodes.front() || polygon._links.size() < 3 )
+      if ( polygon._links.size() < 3 ||
+           polygon._links[0].LastNode() != polygon._links.back().FirstNode() )
         return; // closed polygon not found -> invalid polyhedron
 
-      quantities.push_back( nodes.size() );
-      for ( size_t i = 0; i < nodes.size(); ++i )
-        polyhedraNodes.push_back( nodes[i]->Node() );
-
-      // add polygon to its links and reverse links
-      for ( size_t i = 0; i < polygon._links.size(); ++i )
+      // add polygon to its links
+      for ( size_t iL = 0; iL < polygon._links.size(); ++iL )
       {
-        polygon._links[i].Reverse();
-        polygon._links[i]._link->_faces.push_back( &polygon );
+        polygon._links[ iL ]._link->_faces.reserve( 2 );
+        polygon._links[ iL ]._link->_faces.push_back( &polygon );
+        polygon._links[ iL ].Reverse();
       }
-
-      //const size_t firstPoly = _polygons.size();
-    }
+    } // while ( nbFreeLinks > 0 )
 
     if ( ! checkPolyhedronSize() )
     {
@@ -1505,20 +2009,32 @@ namespace
     else if ( nbNodes == 6 && _polygons.size() == 5 ) isClassicElem = addPenta();
     else if ( nbNodes == 5 && _polygons.size() == 5 ) isClassicElem = addPyra ();
     if ( !isClassicElem )
-      _volumeDefs.set( polyhedraNodes, quantities );
+    {
+      _volumeDefs._nodes.clear();
+      _volumeDefs._quantities.clear();
+
+      for ( size_t iF = 0; iF < _polygons.size(); ++iF )
+      {
+        const size_t nbLinks = _polygons[ iF ]._links.size();
+        _volumeDefs._quantities.push_back( nbLinks );
+        for ( size_t iL = 0; iL < nbLinks; ++iL )
+          _volumeDefs._nodes.push_back( _polygons[ iF ]._links[ iL ].FirstNode() );
+      }
+    }
   }
   //================================================================================
   /*!
    * \brief Create elements in the mesh
    */
-  int Hexahedron::MakeElements(SMESH_MesherHelper& helper)
+  int Hexahedron::MakeElements(SMESH_MesherHelper&                      helper,
+                               const map< TGeomID, vector< TGeomID > >& edge2faceIDsMap)
   {
     SMESHDS_Mesh* mesh = helper.GetMeshDS();
 
     size_t nbCells[3] = { _grid->_coords[0].size() - 1,
                           _grid->_coords[1].size() - 1,
                           _grid->_coords[2].size() - 1 };
-    const size_t nbGridCells = nbCells[0] *nbCells [1] * nbCells[2];
+    const size_t nbGridCells = nbCells[0] * nbCells[1] * nbCells[2];
     vector< Hexahedron* > intersectedHex( nbGridCells, 0 );
     int nbIntHex = 0;
 
@@ -1535,10 +2051,10 @@ namespace
       for ( ; lineInd.More(); ++lineInd )
       {
         GridLine& line = _grid->_lines[ iDir ][ lineInd.LineIndex() ];
-        multiset< IntersectionPoint >::const_iterator ip = line._intPoints.begin();
+        multiset< F_IntersectPoint >::const_iterator ip = line._intPoints.begin();
         for ( ; ip != line._intPoints.end(); ++ip )
         {
-          if ( !ip->_node ) continue;
+          //if ( !ip->_node ) continue;
           lineInd.SetIndexOnLine( ip->_indexOnLine );
           for ( int iL = 0; iL < 4; ++iL ) // loop on 4 cells sharing a link
           {
@@ -1561,12 +2077,15 @@ namespace
             }
             const int iLink = iL + iDir * 4;
             hex->_hexLinks[iLink]._intNodes.push_back( _Node( 0, &(*ip) ));
-            hex->_nbIntNodes++;
+            hex->_nbIntNodes += bool( ip->_node );
           }
         }
       }
     }
 
+    // implement geom edges into the mesh
+    addEdges( helper, intersectedHex, edge2faceIDsMap );
+
     // add not split hexadrons to the mesh
     int nbAdded = 0;
     vector<int> intHexInd( nbIntHex );
@@ -1636,6 +2155,366 @@ namespace
     return nbAdded;
   }
 
+  //================================================================================
+  /*!
+   * \brief Implements geom edges into the mesh
+   */
+  void Hexahedron::addEdges(SMESH_MesherHelper&                      helper,
+                            vector< Hexahedron* >&                   hexes,
+                            const map< TGeomID, vector< TGeomID > >& edge2faceIDsMap)
+  {
+    if ( edge2faceIDsMap.empty() ) return;
+
+    // Prepare planes for intersecting with EDGEs
+    GridPlanes pln[3];
+    {
+      gp_XYZ origPnt = ( _grid->_coords[0][0] * _grid->_axes[0] +
+                         _grid->_coords[1][0] * _grid->_axes[1] +
+                         _grid->_coords[2][0] * _grid->_axes[2] );
+      for ( int iDirZ = 0; iDirZ < 3; ++iDirZ ) // iDirZ gives normal direction to planes
+      {
+        GridPlanes& planes = pln[ iDirZ ];
+        int iDirX = ( iDirZ + 1 ) % 3;
+        int iDirY = ( iDirZ + 2 ) % 3;
+        planes._uNorm  = ( _grid->_axes[ iDirY ] ^ _grid->_axes[ iDirZ ] ).Normalized();
+        planes._vNorm  = ( _grid->_axes[ iDirZ ] ^ _grid->_axes[ iDirX ] ).Normalized();
+        planes._zNorm  = ( _grid->_axes[ iDirX ] ^ _grid->_axes[ iDirY ] ).Normalized();
+        double   uvDot = planes._uNorm * planes._vNorm;
+        planes._factor = sqrt( 1. - uvDot * uvDot );
+        planes._origins.resize( _grid->_coords[ iDirZ ].size() );
+        planes._zProjs.resize ( _grid->_coords[ iDirZ ].size() );
+        planes._origins[0] = origPnt;
+        planes._zProjs [0] = 0;
+        const double       zFactor = _grid->_axes[ iDirZ ] * planes._zNorm;
+        const vector< double > & u = _grid->_coords[ iDirZ ];
+        for ( int i = 1; i < planes._origins.size(); ++i )
+        {
+          planes._origins[i] = origPnt + _grid->_axes[ iDirZ ] * ( u[i] - u[0] );
+          planes._zProjs [i] = zFactor * ( u[i] - u[0] );
+        }
+      }
+    }
+    const double deflection = _grid->_minCellSize / 20.;
+    const double tol        = _grid->_tol;
+    // int facets[6] = { SMESH_Block::ID_F0yz, SMESH_Block::ID_F1yz,
+    //                   SMESH_Block::ID_Fx0z, SMESH_Block::ID_Fx1z,
+    //                   SMESH_Block::ID_Fxy0, SMESH_Block::ID_Fxy1 };
+    E_IntersectPoint ip;
+    //ip._faceIDs.reserve(2);
+
+    // Intersect EDGEs with the planes
+    map< TGeomID, vector< TGeomID > >::const_iterator e2fIt = edge2faceIDsMap.begin();
+    for ( ; e2fIt != edge2faceIDsMap.end(); ++e2fIt )
+    {
+      const TGeomID  edgeID = e2fIt->first;
+      const TopoDS_Edge & E = TopoDS::Edge( _grid->_shapes( edgeID ));
+      BRepAdaptor_Curve curve( E );
+
+      ip._faceIDs = e2fIt->second;
+      ip._shapeID = edgeID;
+
+      // discretize the EGDE
+      GCPnts_UniformDeflection discret( curve, deflection, true );
+      if ( !discret.IsDone() || discret.NbPoints() < 2 )
+        continue;
+
+      // perform intersection
+      for ( int iDirZ = 0; iDirZ < 3; ++iDirZ )
+      {
+        GridPlanes& planes = pln[ iDirZ ];
+        int      iDirX = ( iDirZ + 1 ) % 3;
+        int      iDirY = ( iDirZ + 2 ) % 3;
+        double    xLen = _grid->_coords[ iDirX ].back() - _grid->_coords[ iDirX ][0];
+        double    yLen = _grid->_coords[ iDirY ].back() - _grid->_coords[ iDirY ][0];
+        double zFactor = _grid->_axes[ iDirZ ] * planes._zNorm;
+        int dIJK[3], d000[3] = { 0,0,0 };
+
+        // locate the 1st point of a segment within the grid
+        gp_XYZ p1     = discret.Value( 1 ).XYZ();
+        double u1     = discret.Parameter( 1 );
+        double zProj1 = planes._zNorm * ( p1 - planes._origins[0] );
+        gp_Pnt orig   = planes._origins[0] + planes._zNorm * zProj1;
+        gp_XY uv      = planes.GetUV( p1, orig );
+        int iX1       = int( uv.X() / xLen * ( _grid->_coords[ iDirX ].size() - 1. ));
+        int iY1       = int( uv.Y() / yLen * ( _grid->_coords[ iDirY ].size() - 1. ));
+        int iZ1       = int( zProj1 / planes._zProjs.back() * ( planes._zProjs.size() - 1. ));
+        locateValue( iX1, uv.X(), _grid->_coords[ iDirX ], dIJK[ iDirX ], tol );
+        locateValue( iY1, uv.Y(), _grid->_coords[ iDirY ], dIJK[ iDirY ], tol );
+        locateValue( iZ1, zProj1, planes._zProjs         , dIJK[ iDirZ ], tol );
+
+        int ijk[3]; // grid index where a segment intersect a plane
+        ijk[ iDirX ] = iX1;
+        ijk[ iDirY ] = iY1;
+        ijk[ iDirZ ] = iZ1;
+        ip._uvw[ iDirX ] = uv.X()           + _grid->_coords[ iDirX ][0];
+        ip._uvw[ iDirY ] = uv.Y()           + _grid->_coords[ iDirY ][0];
+        ip._uvw[ iDirZ ] = zProj1 / zFactor + _grid->_coords[ iDirZ ][0];
+
+        // add the 1st vertex point to a hexahedron
+        if ( iDirZ == 0 )
+        {
+          //ip._shapeID = _grid->_shapes.Add( helper.IthVertex( 0, curve.Edge(),/*CumOri=*/false));
+          ip._point   = p1;
+          _grid->_edgeIntP.push_back( ip );
+          if ( !addIntersection( _grid->_edgeIntP.back(), hexes, ijk, d000 ))
+            _grid->_edgeIntP.pop_back();
+        }
+        for ( int iP = 2; iP <= discret.NbPoints(); ++iP )
+        {
+          // locate the 2nd point of a segment within the grid
+          gp_XYZ p2     = discret.Value( iP ).XYZ();
+          double u2     = discret.Parameter( iP );
+          double zProj2 = planes._zNorm * ( p2 - planes._origins[0] );
+          int iZ2       = iZ1;
+          locateValue( iZ2, zProj2, planes._zProjs, dIJK[ iDirZ ], tol );
+
+          // treat intersections with planes between 2 end points of a segment
+          int dZ = ( iZ1 <= iZ2 ) ? +1 : -1;
+          int iZ = iZ1 + ( iZ1 < iZ2 );
+          for ( int i = 0, nb = Abs( iZ1 - iZ2 ); i < nb; ++i, iZ += dZ )
+          {
+            ip._point = findIntPoint( u1, zProj1, u2, zProj2,
+                                      planes._zProjs[ iZ ],
+                                      curve, planes._zNorm, planes._origins[0] );
+            gp_XY uv  = planes.GetUV( ip._point, planes._origins[ iZ ]);
+            locateValue( ijk[ iDirX ], uv.X(), _grid->_coords[ iDirX ], dIJK[ iDirX ], tol );
+            locateValue( ijk[ iDirY ], uv.Y(), _grid->_coords[ iDirY ], dIJK[ iDirY ], tol );
+            ijk[ iDirZ ] = iZ;
+            ip._uvw[ iDirX ] = uv.X()                         + _grid->_coords[ iDirX ][0];
+            ip._uvw[ iDirY ] = uv.Y()                         + _grid->_coords[ iDirY ][0];
+            ip._uvw[ iDirZ ] = planes._zProjs[ iZ ] / zFactor + _grid->_coords[ iDirZ ][0];
+
+            // add ip to hex "above" the plane
+            _grid->_edgeIntP.push_back( ip );
+            dIJK[ iDirZ ] = 0;
+            bool added = addIntersection(_grid->_edgeIntP.back(), hexes, ijk, dIJK);
+
+            // add ip to hex "below" the plane
+            ijk[ iDirZ ] = iZ-1;
+            if ( !addIntersection( _grid->_edgeIntP.back(), hexes, ijk, dIJK ) &&
+                 !added)
+              _grid->_edgeIntP.pop_back();
+          }
+          iZ1    = iZ2;
+          p1     = p2;
+          u1     = u2;
+          zProj1 = zProj2;
+        }
+        // add the 2nd vertex point to a hexahedron
+        if ( iDirZ == 0 )
+        {
+          orig = planes._origins[0] + planes._zNorm * zProj1;
+          uv   = planes.GetUV( p1, orig );
+          locateValue( ijk[ iDirX ], uv.X(), _grid->_coords[ iDirX ], dIJK[ iDirX ], tol );
+          locateValue( ijk[ iDirY ], uv.Y(), _grid->_coords[ iDirY ], dIJK[ iDirY ], tol );
+          ijk[ iDirZ ] = iZ1;
+          ip._uvw[ iDirX ] = uv.X()           + _grid->_coords[ iDirX ][0];
+          ip._uvw[ iDirY ] = uv.Y()           + _grid->_coords[ iDirY ][0];
+          ip._uvw[ iDirZ ] = zProj1 / zFactor + _grid->_coords[ iDirZ ][0];
+          ip._point = p1;
+          _grid->_edgeIntP.push_back( ip );
+          if ( !addIntersection( _grid->_edgeIntP.back(), hexes, ijk, d000 ))
+            _grid->_edgeIntP.pop_back();
+        }
+      } // loop on 3 grid directions
+    } // loop on EDGEs
+
+    // Create nodes at found intersections
+    // const E_IntersectPoint* eip;
+    // for ( size_t i = 0; i < hexes.size(); ++i )
+    // {
+    //   Hexahedron* h = hexes[i];
+    //   if ( !h ) continue;
+    //   for ( int iF = 0; iF < 6; ++iF )
+    //   {
+    //     _Face& quad = h->_hexQuads[ iF ];
+    //     for ( size_t iP = 0; iP < quad._edgeNodes.size(); ++iP )
+    //       if ( !quad._edgeNodes[ iP ]._node )
+    //         if (( eip = quad._edgeNodes[ iP ].EdgeIntPnt() ))
+    //           quad._edgeNodes[ iP ]._intPoint->_node = helper.AddNode( eip->_point.X(),
+    //                                                                    eip->_point.Y(),
+    //                                                                    eip->_point.Z() );
+    //   }
+    //   for ( size_t iP = 0; iP < hexes[i]->_vertexNodes.size(); ++iP )
+    //     if (( eip = h->_vertexNodes[ iP ].EdgeIntPnt() ))
+    //       h->_vertexNodes[ iP ]._intPoint->_node = helper.AddNode( eip->_point.X(),
+    //                                                                eip->_point.Y(),
+    //                                                                eip->_point.Z() );
+    // }
+  }
+
+  //================================================================================
+  /*!
+   * \brief Finds intersection of a curve with a plane
+   *  \param [in] u1 - parameter of one curve point
+   *  \param [in] proj1 - projection of the curve point to the plane normal
+   *  \param [in] u2 - parameter of another curve point
+   *  \param [in] proj2 - projection of the other curve point to the plane normal
+   *  \param [in] proj - projection of a point where the curve intersects the plane
+   *  \param [in] curve - the curve
+   *  \param [in] axis - the plane normal
+   *  \param [in] origin - the plane origin
+   *  \return gp_Pnt - the found intersection point
+   */
+  //================================================================================
+
+  gp_Pnt Hexahedron::findIntPoint( double u1, double proj1,
+                                   double u2, double proj2,
+                                   double proj,
+                                   BRepAdaptor_Curve& curve,
+                                   const gp_XYZ& axis,
+                                   const gp_XYZ& origin)
+  {
+    double r = (( proj - proj1 ) / ( proj2 - proj1 ));
+    double u = u1 * ( 1 - r ) + u2 * r;
+    gp_Pnt p = curve.Value( u );
+    double newProj =  axis * ( p.XYZ() - origin );
+    if ( Abs( proj - newProj ) > _grid->_tol / 10. )
+    {
+      if ( r > 0.5 )
+        return findIntPoint( u2, proj2, u, newProj, proj, curve, axis, origin );
+      else
+        return findIntPoint( u1, proj2, u, newProj, proj, curve, axis, origin );
+    }
+    return p;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Returns index of a hexahedron sub-entities holding a point
+   *  \param [in] ip - intersection point
+   *  \param [out] facets - 0-3 facets holding a point
+   *  \param [out] sub - index of a vertex or an edge holding a point
+   *  \return int - number of facets holding a point
+   */
+  int Hexahedron::getEntity( const E_IntersectPoint* ip, int* facets, int& sub )
+  {
+    enum { X = 1, Y = 2, Z = 4 }; // == 001, 010, 100
+    int nbFacets = 0;
+    int vertex = 0, egdeMask = 0;
+
+    if ( Abs( _grid->_coords[0][ _i   ] - ip->_uvw[0] ) < _grid->_tol ) {
+      facets[ nbFacets++ ] = SMESH_Block::ID_F0yz;
+      egdeMask |= X;
+    }
+    else if ( Abs( _grid->_coords[0][ _i+1 ] - ip->_uvw[0] ) < _grid->_tol ) {
+      facets[ nbFacets++ ] = SMESH_Block::ID_F1yz;
+      vertex   |= X;
+      egdeMask |= X;
+    }
+    if ( Abs( _grid->_coords[1][ _j   ] - ip->_uvw[1] ) < _grid->_tol ) {
+      facets[ nbFacets++ ] = SMESH_Block::ID_Fx0z;
+      egdeMask |= Y;
+    }
+    else if ( Abs( _grid->_coords[1][ _j+1 ] - ip->_uvw[1] ) < _grid->_tol ) {
+      facets[ nbFacets++ ] = SMESH_Block::ID_Fx1z;
+      vertex   |= Y;
+      egdeMask |= Y;
+    }
+    if ( Abs( _grid->_coords[2][ _k   ] - ip->_uvw[2] ) < _grid->_tol ) {
+      facets[ nbFacets++ ] = SMESH_Block::ID_Fxy0;
+      egdeMask |= Z;
+    }
+    else if ( Abs( _grid->_coords[2][ _k+1 ] - ip->_uvw[2] ) < _grid->_tol ) {
+      facets[ nbFacets++ ] = SMESH_Block::ID_Fxy1;
+      vertex   |= Z;
+      egdeMask |= Z;
+    }
+
+    switch ( nbFacets )
+    {
+    case 0: sub = 0;         break;
+    case 1: sub = facets[0]; break;
+    case 2: {
+      const int edge [3][8] = {
+        { SMESH_Block::ID_E00z, SMESH_Block::ID_E10z,
+          SMESH_Block::ID_E01z, SMESH_Block::ID_E11z },
+        { SMESH_Block::ID_E0y0, SMESH_Block::ID_E1y0, 0, 0,
+          SMESH_Block::ID_E0y1, SMESH_Block::ID_E1y1 },
+        { SMESH_Block::ID_Ex00, 0, SMESH_Block::ID_Ex10, 0,
+          SMESH_Block::ID_Ex01, 0, SMESH_Block::ID_Ex11 }
+      };
+      switch ( egdeMask ) {
+      case X | Y: sub = edge[ 0 ][ vertex ]; break;
+      case X | Z: sub = edge[ 1 ][ vertex ]; break;
+      default:    sub = edge[ 2 ][ vertex ];
+      }
+      break;
+    }
+    //case 3:
+    default:
+      sub = vertex + SMESH_Block::ID_FirstV;
+    }
+
+    return nbFacets;
+  }
+  //================================================================================
+  /*!
+   * \brief Adds intersection with an EDGE
+   */
+  bool Hexahedron::addIntersection( const E_IntersectPoint& ip,
+                                    vector< Hexahedron* >&  hexes,
+                                    int ijk[], int dIJK[] )
+  {
+    bool added = false;
+
+    size_t hexIndex[4] = {
+      _grid->CellIndex( ijk[0], ijk[1], ijk[2] ),
+      dIJK[0] ? _grid->CellIndex( ijk[0]+dIJK[0], ijk[1], ijk[2] ) : -1,
+      dIJK[1] ? _grid->CellIndex( ijk[0], ijk[1]+dIJK[1], ijk[2] ) : -1,
+      dIJK[2] ? _grid->CellIndex( ijk[0], ijk[1], ijk[2]+dIJK[2] ) : -1
+    };
+    for ( int i = 0; i < 4; ++i )
+    {
+      if ( 0 <= hexIndex[i] && hexIndex[i] < hexes.size() && hexes[ hexIndex[i] ] )
+      {
+        Hexahedron* h = hexes[ hexIndex[i] ];
+        // check if ip is really inside the hex
+#ifdef _DEBUG_
+        if (( _grid->_coords[0][ h->_i   ] - _grid->_tol > ip._uvw[0] ) ||
+            ( _grid->_coords[0][ h->_i+1 ] + _grid->_tol < ip._uvw[0] ) ||
+            ( _grid->_coords[1][ h->_j   ] - _grid->_tol > ip._uvw[1] ) ||
+            ( _grid->_coords[1][ h->_j+1 ] + _grid->_tol < ip._uvw[1] ) ||
+            ( _grid->_coords[2][ h->_k   ] - _grid->_tol > ip._uvw[2] ) ||
+            ( _grid->_coords[2][ h->_k+1 ] + _grid->_tol < ip._uvw[2] ))
+          throw SALOME_Exception("ip outside a hex");
+#endif
+        h->_edgeIntPnts.push_back( & ip );
+        added = true;
+      }
+    }
+    return added;
+  }
+  //================================================================================
+  /*!
+   * \brief Finds nodes at a path from one node to another via intersections with EDGEs
+   */
+  bool Hexahedron::findChain( _Node*          n1,
+                              _Node*          n2,
+                              _Face&          quad,
+                              vector<_Node*>& chn )
+  {
+    chn.clear();
+    chn.push_back( n1 );
+    bool found = false;
+    do
+    {
+      found = false;
+      for ( size_t iP = 0; iP < quad._edgeNodes.size(); ++iP )
+        if (( std::find( ++chn.begin(), chn.end(), & quad._edgeNodes[iP]) == chn.end()) &&
+            chn.back()->IsLinked( quad._edgeNodes[ iP ]._intPoint ))
+        {
+          chn.push_back( & quad._edgeNodes[ iP ]);
+          found = true;
+          break;
+        }
+    } while ( found && chn.back() != n2 );
+
+    if ( chn.back() != n2 )
+      chn.push_back( n2 );
+
+    return chn.size() > 2;
+  }
   //================================================================================
   /*!
    * \brief Adds computed elements to the mesh
@@ -1646,8 +2525,19 @@ namespace
     // add elements resulted from hexahedron intersection
     //for ( size_t i = 0; i < _volumeDefs.size(); ++i )
     {
-      vector< const SMDS_MeshNode* >& nodes = _volumeDefs._nodes;
-      
+      vector< const SMDS_MeshNode* > nodes( _volumeDefs._nodes.size() );
+      for ( size_t iN = 0; iN < nodes.size(); ++iN )
+        if ( !( nodes[iN] = _volumeDefs._nodes[iN]->Node() ))
+        {
+          if ( const E_IntersectPoint* eip = _volumeDefs._nodes[iN]->EdgeIntPnt() )
+            nodes[iN] = _volumeDefs._nodes[iN]->_intPoint->_node =
+              helper.AddNode( eip->_point.X(),
+                              eip->_point.Y(),
+                              eip->_point.Z() );
+          else
+            throw SALOME_Exception("Bug: no node at intersection point");
+        }
+
       if ( !_volumeDefs._quantities.empty() )
       {
         helper.AddPolyhedralVolume( nodes, _volumeDefs._quantities );
@@ -1679,8 +2569,11 @@ namespace
    */
   bool Hexahedron::isInHole() const
   {
+    if ( !_vertexNodes.empty() )
+      return false;
+
     const int ijk[3] = { _i, _j, _k };
-    IntersectionPoint curIntPnt;
+    F_IntersectPoint curIntPnt;
 
     // consider a cell to be in a hole if all links in any direction
     // comes OUT of geometry
@@ -1698,19 +2591,19 @@ namespace
       {
         const _Link& link = _hexLinks[ iL + 4*iDir ];
         // check transition of the first node of a link
-        const IntersectionPoint* firstIntPnt = 0;
+        const F_IntersectPoint* firstIntPnt = 0;
         if ( link._nodes[0]->Node() ) // 1st node is a hexa corner
         {
           curIntPnt._paramOnLine = coords[ ijk[ iDir ]] - coords[0];
           const GridLine& line = _grid->_lines[ iDir ][ lineIndex[ iL ]];
-          multiset< IntersectionPoint >::const_iterator ip =
+          multiset< F_IntersectPoint >::const_iterator ip =
             line._intPoints.upper_bound( curIntPnt );
           --ip;
           firstIntPnt = &(*ip);
         }
         else if ( !link._intNodes.empty() )
         {
-          firstIntPnt = link._intNodes[0]._intPoint;
+          firstIntPnt = link._intNodes[0].FaceIntPnt();
         }
 
         if ( firstIntPnt )
@@ -1736,10 +2629,10 @@ namespace
     {
       const _Face& polygon = _polygons[iP];
       gp_XYZ area (0,0,0);
-      SMESH_TNodeXYZ p1 ( polygon._links[ 0 ].FirstNode()->Node() );
+      gp_XYZ p1 = polygon._links[ 0 ].FirstNode()->Point().XYZ();
       for ( size_t iL = 0; iL < polygon._links.size(); ++iL )
       {
-        SMESH_TNodeXYZ p2 ( polygon._links[ iL ].LastNode()->Node() );
+        gp_XYZ p2 = polygon._links[ iL ].LastNode()->Point().XYZ();
         area += p1 ^ p2;
         p1 = p2;
       }
@@ -1764,12 +2657,12 @@ namespace
          _polygons[4]._links.size() != 4 ||
          _polygons[5]._links.size() != 4   )
       return false;
-    const SMDS_MeshNode* nodes[8];
+    _Node* nodes[8];
     int nbN = 0;
     for ( int iL = 0; iL < 4; ++iL )
     {
       // a base node
-      nodes[iL] = _polygons[0]._links[iL].FirstNode()->Node();
+      nodes[iL] = _polygons[0]._links[iL].FirstNode();
       ++nbN;
 
       // find a top node above the base node
@@ -1781,13 +2674,13 @@ namespace
         if ( quad->_links[i]._link == link )
         {
           // 1st node of a link opposite to <link> in <quad>
-          nodes[iL+4] = quad->_links[(i+2)%4].FirstNode()->Node();
+          nodes[iL+4] = quad->_links[(i+2)%4].FirstNode();
           ++nbN;
           break;
         }
     }
     if ( nbN == 8 )
-      _volumeDefs.set( vector< const SMDS_MeshNode* >( nodes, nodes+8 ));
+      _volumeDefs.set( vector< _Node* >( nodes, nodes+8 ));
 
     return nbN == 8;
   }
@@ -1797,10 +2690,10 @@ namespace
    */
   bool Hexahedron::addTetra()
   {
-    const SMDS_MeshNode* nodes[4];
-    nodes[0] = _polygons[0]._links[0].FirstNode()->Node();
-    nodes[1] = _polygons[0]._links[1].FirstNode()->Node();
-    nodes[2] = _polygons[0]._links[2].FirstNode()->Node();
+    _Node* nodes[4];
+    nodes[0] = _polygons[0]._links[0].FirstNode();
+    nodes[1] = _polygons[0]._links[1].FirstNode();
+    nodes[2] = _polygons[0]._links[2].FirstNode();
 
     _Link* link = _polygons[0]._links[0]._link;
     ASSERT( link->_faces.size() > 1 );
@@ -1810,8 +2703,8 @@ namespace
     for ( int i = 0; i < 3; ++i )
       if ( tria->_links[i]._link == link )
       {
-        nodes[3] = tria->_links[(i+1)%3].LastNode()->Node();
-        _volumeDefs.set( vector< const SMDS_MeshNode* >( nodes, nodes+4 ));
+        nodes[3] = tria->_links[(i+1)%3].LastNode();
+        _volumeDefs.set( vector< _Node* >( nodes, nodes+4 ));
         return true;
       }
 
@@ -1831,12 +2724,12 @@ namespace
     if ( iTri < 0 ) return false;
 
     // find nodes
-    const SMDS_MeshNode* nodes[6];
+    _Node* nodes[6];
     int nbN = 0;
     for ( int iL = 0; iL < 3; ++iL )
     {
       // a base node
-      nodes[iL] = _polygons[ iTri ]._links[iL].FirstNode()->Node();
+      nodes[iL] = _polygons[ iTri ]._links[iL].FirstNode();
       ++nbN;
 
       // find a top node above the base node
@@ -1849,13 +2742,13 @@ namespace
         if ( quad->_links[i]._link == link )
         {
           // 1st node of a link opposite to <link> in <quad>
-          nodes[iL+3] = quad->_links[(i+2)%4].FirstNode()->Node();
+          nodes[iL+3] = quad->_links[(i+2)%4].FirstNode();
           ++nbN;
           break;
         }
     }
     if ( nbN == 6 )
-      _volumeDefs.set( vector< const SMDS_MeshNode* >( nodes, nodes+6 ));
+      _volumeDefs.set( vector< _Node* >( nodes, nodes+6 ));
 
     return ( nbN == 6 );
   }
@@ -1873,11 +2766,11 @@ namespace
     if ( iQuad < 0 ) return false;
 
     // find nodes
-    const SMDS_MeshNode* nodes[5];
-    nodes[0] = _polygons[iQuad]._links[0].FirstNode()->Node();
-    nodes[1] = _polygons[iQuad]._links[1].FirstNode()->Node();
-    nodes[2] = _polygons[iQuad]._links[2].FirstNode()->Node();
-    nodes[3] = _polygons[iQuad]._links[3].FirstNode()->Node();
+    _Node* nodes[5];
+    nodes[0] = _polygons[iQuad]._links[0].FirstNode();
+    nodes[1] = _polygons[iQuad]._links[1].FirstNode();
+    nodes[2] = _polygons[iQuad]._links[2].FirstNode();
+    nodes[3] = _polygons[iQuad]._links[3].FirstNode();
 
     _Link* link = _polygons[iQuad]._links[0]._link;
     ASSERT( link->_faces.size() > 1 );
@@ -1888,8 +2781,8 @@ namespace
     for ( int i = 0; i < 3; ++i )
       if ( tria->_links[i]._link == link )
       {
-        nodes[4] = tria->_links[(i+1)%3].LastNode()->Node();
-        _volumeDefs.set( vector< const SMDS_MeshNode* >( nodes, nodes+5 ));
+        nodes[4] = tria->_links[(i+1)%3].LastNode();
+        _volumeDefs.set( vector< _Node* >( nodes, nodes+5 ));
         return true;
       }
 
@@ -1930,25 +2823,37 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh &         theMesh,
   {
     Grid grid;
 
-    TopTools_MapOfShape faceMap;
-    for ( TopExp_Explorer fExp( theShape, TopAbs_FACE ); fExp.More(); fExp.Next() )
-      if ( !faceMap.Add( fExp.Current() ))
-        faceMap.Remove( fExp.Current() ); // remove a face shared by two solids
-
+    vector< TopoDS_Shape > faceVec;
+    {
+      TopTools_MapOfShape faceMap;
+      for ( TopExp_Explorer fExp( theShape, TopAbs_FACE ); fExp.More(); fExp.Next() )
+        if ( faceMap.Add( fExp.Current() )) // skip a face shared by two solids
+          faceVec.push_back( fExp.Current() );
+    }
     Bnd_Box shapeBox;
-    vector<FaceGridIntersector> facesItersectors( faceMap.Extent() );
-    TopTools_MapIteratorOfMapOfShape faceMppIt( faceMap );
-    for ( int i = 0; faceMppIt.More(); faceMppIt.Next(), ++i )
+    vector<FaceGridIntersector> facesItersectors( faceVec.size() );
+    map< TGeomID, vector< TGeomID > > edge2faceIDsMap;
+    TopExp_Explorer eExp;
+    for ( int i = 0; i < faceVec.size(); ++i )
     {
-      facesItersectors[i]._face = TopoDS::Face( faceMppIt.Key() );
-      facesItersectors[i]._grid = &grid;
+      facesItersectors[i]._face   = TopoDS::Face    ( faceVec[i] );
+      facesItersectors[i]._faceID = grid._shapes.Add( faceVec[i] );
+      facesItersectors[i]._grid   = &grid;
       shapeBox.Add( facesItersectors[i].GetFaceBndBox() );
+
+      if ( _hyp->GetToAddEdges() )
+        for ( eExp.Init( faceVec[i], TopAbs_EDGE ); eExp.More(); eExp.Next() )
+        {
+          const TopoDS_Edge& edge = TopoDS::Edge( eExp.Current() );
+          if ( !SMESH_Algo::isDegenerated( edge ))
+            edge2faceIDsMap[ grid._shapes.Add( edge )].push_back( facesItersectors[i]._faceID );
+        }
     }
 
     vector<double> xCoords, yCoords, zCoords;
     _hyp->GetCoordinates( xCoords, yCoords, zCoords, shapeBox );
 
-    grid.SetCoordinates( xCoords, yCoords, zCoords, theShape );
+    grid.SetCoordinates( xCoords, yCoords, zCoords, _hyp->GetAxisDirs(), theShape );
 
     // check if the grid encloses the shape
     if ( !_hyp->IsGridBySpacing(0) ||
@@ -2015,12 +2920,12 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh &         theMesh,
 
     // create volume elements
     Hexahedron hex( _hyp->GetSizeThreshold(), &grid );
-    int nbAdded = hex.MakeElements( helper );
+    int nbAdded = hex.MakeElements( helper, edge2faceIDsMap );
 
     SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
     if ( nbAdded > 0 )
     {
-      // make all SOLIDS computed
+      // make all SOLIDs computed
       if ( SMESHDS_SubMesh* sm1 = meshDS->MeshElements( solidExp.Current()) )
       {
         SMDS_ElemIteratorPtr volIt = sm1->GetElements();
@@ -2038,23 +2943,28 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh &         theMesh,
     // remove free nodes
     if ( SMESHDS_SubMesh * smDS = meshDS->MeshElements( helper.GetSubShapeID() ))
     {
-      // intersection nodes
+      TIDSortedNodeSet nodesToRemove;
+      // get intersection nodes
       for ( int iDir = 0; iDir < 3; ++iDir )
       {
         vector< GridLine >& lines = grid._lines[ iDir ];
         for ( size_t i = 0; i < lines.size(); ++i )
         {
-          multiset< IntersectionPoint >::iterator ip = lines[i]._intPoints.begin();
+          multiset< F_IntersectPoint >::iterator ip = lines[i]._intPoints.begin();
           for ( ; ip != lines[i]._intPoints.end(); ++ip )
             if ( ip->_node && ip->_node->NbInverseElements() == 0 )
-              meshDS->RemoveFreeNode( ip->_node, smDS, /*fromGroups=*/false );
+              nodesToRemove.insert( nodesToRemove.end(), ip->_node );
         }
       }
-      // grid nodes
+      // get grid nodes
       for ( size_t i = 0; i < grid._nodes.size(); ++i )
-        if ( !grid._isBndNode[i] ) // nodes on boundary are already removed
-          if ( grid._nodes[i] && grid._nodes[i]->NbInverseElements() == 0 )
-            meshDS->RemoveFreeNode( grid._nodes[i], smDS, /*fromGroups=*/false );
+        if ( grid._nodes[i] && grid._nodes[i]->NbInverseElements() == 0 )
+          nodesToRemove.insert( nodesToRemove.end(), grid._nodes[i] );
+
+      // do remove
+      TIDSortedNodeSet::iterator n = nodesToRemove.begin();
+      for ( ; n != nodesToRemove.end(); ++n )
+        meshDS->RemoveFreeNode( *n, smDS, /*fromGroups=*/false );
     }
 
     return nbAdded;
index 4e5e0478af102aa743419d1065ede20a14e6f9e1..5382b7e87eb9a52bcc04ccc2426a97f3526dba9c 100644 (file)
@@ -251,7 +251,8 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const StdMeshers_FaceSide*  theSide,
  */
 //================================================================================
 
-StdMeshers_FaceSide::StdMeshers_FaceSide(UVPtStructVec& theSideNodes)
+StdMeshers_FaceSide::StdMeshers_FaceSide(UVPtStructVec&     theSideNodes,
+                                         const TopoDS_Face& theFace)
 {
   myEdge.resize( 1 );
   myEdgeID.resize( 1, -1 );
@@ -272,12 +273,42 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(UVPtStructVec& theSideNodes)
   if ( !myPoints.empty() )
   {
     myPoints[0].normParam = 0;
-    gp_Pnt pPrev = SMESH_TNodeXYZ( myPoints[0].node );
-    for ( size_t i = 1; i < myPoints.size(); ++i )
+    if ( myPoints[0].node &&
+         myPoints.back().node &&
+         myPoints[ myNbPonits/2 ].node )
     {
-      gp_Pnt p = SMESH_TNodeXYZ( myPoints[i].node );
-      myLength += ( myPoints[i].normParam = p.Distance( pPrev ));
-      pPrev = p;
+      gp_Pnt pPrev = SMESH_TNodeXYZ( myPoints[0].node );
+      for ( size_t i = 1; i < myPoints.size(); ++i )
+      {
+        gp_Pnt p = SMESH_TNodeXYZ( myPoints[i].node );
+        myLength += p.Distance( pPrev );
+        myPoints[i].normParam = myLength;
+        pPrev = p;
+      }
+    }
+    else if ( !theFace.IsNull() )
+    {
+      TopLoc_Location loc;
+      Handle(Geom_Surface) surf = BRep_Tool::Surface( theFace, loc );
+      gp_Pnt pPrev = surf->Value( myPoints[0].u, myPoints[0].v );
+      for ( size_t i = 1; i < myPoints.size(); ++i )
+      {
+        gp_Pnt p = surf->Value( myPoints[i].u, myPoints[i].v );
+        myLength += p.Distance( pPrev );
+        myPoints[i].normParam = myLength;
+        pPrev = p;
+      }
+    }
+    else
+    {
+      gp_Pnt2d pPrev = myPoints[0].UV();
+      for ( size_t i = 1; i < myPoints.size(); ++i )
+      {
+        gp_Pnt2d p = myPoints[i].UV();
+        myLength += p.Distance( pPrev );
+        myPoints[i].normParam = myLength;
+        pPrev = p;
+      }
     }
     if ( myLength > std::numeric_limits<double>::min() )
       for ( size_t i = 1; i < myPoints.size(); ++i )
@@ -926,6 +957,18 @@ gp_Pnt2d StdMeshers_FaceSide::Value2d(double U) const
     return myC2d[ i ]->Value(par);
 
   }
+  else if ( !myPoints.empty() )
+  {
+    int i = U * double( myPoints.size()-1 );
+    while ( i > 0 && myPoints[ i ].normParam > U )
+      --i;
+    while ( i+1 < myPoints.size() && myPoints[ i+1 ].normParam < U )
+      ++i;
+    double r = (( U - myPoints[ i ].normParam ) /
+                ( myPoints[ i+1 ].normParam - myPoints[ i ].normParam ));
+    return ( myPoints[ i   ].UV() * ( 1 - r ) +
+             myPoints[ i+1 ].UV() * r );
+  }
   return myDefaultPnt2d;
 }
 
index 4f714d4bf0c111960747d3f004d4a895d507f2ec..c08d75cc348d2e22b306276e63c6c269da33f1fe 100644 (file)
@@ -35,6 +35,7 @@
 #include <Geom2d_Curve.hxx>
 #include <GeomAdaptor_Curve.hxx>
 #include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
 #include <TopoDS_Vertex.hxx>
 #include <gp_Pnt2d.hxx>
 
@@ -47,7 +48,6 @@ class SMESH_Mesh;
 class Adaptor2d_Curve2d;
 class Adaptor3d_Curve;
 class BRepAdaptor_CompCurve;
-class TopoDS_Face;
 struct SMESH_ComputeError;
 class StdMeshers_FaceSide;
 
@@ -96,7 +96,43 @@ public:
   /*!
    * \brief Create a side from an UVPtStructVec
    */
-  StdMeshers_FaceSide(UVPtStructVec& theSideNodes);
+  StdMeshers_FaceSide(UVPtStructVec&     theSideNodes,
+                      const TopoDS_Face& theFace = TopoDS_Face());
+
+  // static "consrtuctors"
+  static StdMeshers_FaceSidePtr New(const TopoDS_Face&   Face,
+                                    const TopoDS_Edge&   Edge,
+                                    SMESH_Mesh*          Mesh,
+                                    const bool           IsForward,
+                                    const bool           IgnoreMediumNodes,
+                                    SMESH_ProxyMesh::Ptr ProxyMesh = SMESH_ProxyMesh::Ptr())
+  { return StdMeshers_FaceSidePtr
+      ( new StdMeshers_FaceSide( Face,Edge,Mesh,IsForward,IgnoreMediumNodes,ProxyMesh ));
+  }
+  static StdMeshers_FaceSidePtr New (const TopoDS_Face&      Face,
+                                     std::list<TopoDS_Edge>& Edges,
+                                     SMESH_Mesh*             Mesh,
+                                     const bool              IsForward,
+                                     const bool              IgnoreMediumNodes,
+                                     SMESH_ProxyMesh::Ptr    ProxyMesh = SMESH_ProxyMesh::Ptr())
+  { return StdMeshers_FaceSidePtr
+      ( new StdMeshers_FaceSide( Face,Edges,Mesh,IsForward,IgnoreMediumNodes,ProxyMesh ));
+  }
+  static StdMeshers_FaceSidePtr New (const StdMeshers_FaceSide*  Side,
+                                     const SMDS_MeshNode*        Node,
+                                     const gp_Pnt2d*             Pnt2d1,
+                                     const gp_Pnt2d*             Pnt2d2=NULL,
+                                     const Handle(Geom2d_Curve)& C2d=NULL,
+                                     const double                UFirst=0.,
+                                     const double                ULast=1.)
+  { return StdMeshers_FaceSidePtr
+      ( new StdMeshers_FaceSide( Side,Node,Pnt2d1,Pnt2d2,C2d,UFirst,ULast ));
+  }
+  static StdMeshers_FaceSidePtr New (UVPtStructVec&     theSideNodes,
+                                     const TopoDS_Face& theFace = TopoDS_Face())
+  {
+    return StdMeshers_FaceSidePtr( new StdMeshers_FaceSide( theSideNodes, theFace ));
+  }
 
   /*!
    * \brief Return wires of a face as StdMeshers_FaceSide's
diff --git a/src/StdMeshers/StdMeshers_Geometric1D.cxx b/src/StdMeshers/StdMeshers_Geometric1D.cxx
new file mode 100644 (file)
index 0000000..8d2be97
--- /dev/null
@@ -0,0 +1,204 @@
+// Copyright (C) 2007-2013  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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH SMESH : implementaion of SMESH idl descriptions
+//  File   : StdMeshers_Geometric1D.cxx
+//  Module : SMESH
+//
+#include "StdMeshers_Geometric1D.hxx"
+
+#include "SMESH_Mesh.hxx"
+
+#include <BRepAdaptor_Curve.hxx>
+#include <GCPnts_AbscissaPoint.hxx>
+#include <SMESH_Algo.hxx>
+#include <TopExp.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Edge.hxx>
+
+//=============================================================================
+/*!
+ * Constructor
+ */
+//=============================================================================
+
+StdMeshers_Geometric1D::StdMeshers_Geometric1D(int hypId, int studyId, SMESH_Gen * gen)
+  :StdMeshers_Reversible1D(hypId, studyId, gen)
+{
+  _begLength = 1.;
+  _ratio = 1.;
+  _name = "GeometricProgression";
+}
+
+//=============================================================================
+/*!
+ * Sets length of the first segment
+ */
+//=============================================================================
+
+void StdMeshers_Geometric1D::SetStartLength(double length)
+  throw(SALOME_Exception)
+{
+  if ( _begLength != length )
+  {
+    if (length <= 0)
+      throw SALOME_Exception(LOCALIZED("length must be positive"));
+    _begLength = length;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+/*!
+ * Sets value of Common Ratio
+ */
+//=============================================================================
+
+void StdMeshers_Geometric1D::SetCommonRatio(double factor)
+  throw(SALOME_Exception)
+{
+  if ( _ratio != factor )
+  {
+    if (factor == 0)
+      throw SALOME_Exception(LOCALIZED("Zero factor is not allowed"));
+    _ratio = factor;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+/*!
+ * Returns length of the first segment 
+ */
+//=============================================================================
+
+double StdMeshers_Geometric1D::GetStartLength() const
+{
+  return _begLength;
+}
+
+//=============================================================================
+/*!
+ * Returns value of Common Ratio
+ */
+//=============================================================================
+
+double StdMeshers_Geometric1D::GetCommonRatio() const
+{
+  return _ratio;
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+ostream & StdMeshers_Geometric1D::SaveTo(ostream & save)
+{
+  save << _begLength << " " << _ratio << " ";
+
+  StdMeshers_Reversible1D::SaveTo( save );
+
+  return save;
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+istream & StdMeshers_Geometric1D::LoadFrom(istream & load)
+{
+  bool isOK = true;
+  isOK = (load >> _begLength);
+  isOK = (load >> _ratio);
+
+  if (isOK)
+    StdMeshers_Reversible1D::LoadFrom( load );
+
+  return load;
+}
+
+//================================================================================
+/*!
+ * \brief Initialize start and end length 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
+ */
+//================================================================================
+
+bool StdMeshers_Geometric1D::SetParametersByMesh(const SMESH_Mesh*   theMesh,
+                                                 const TopoDS_Shape& theShape)
+{
+  if ( !theMesh || theShape.IsNull() )
+    return false;
+
+  _begLength = _ratio = 0.;
+
+  int nbEdges = 0;
+  TopTools_IndexedMapOfShape edgeMap;
+  TopExp::MapShapes( theShape, TopAbs_EDGE, edgeMap );
+  for ( int i = 1; i <= edgeMap.Extent(); ++i )
+  {
+    const TopoDS_Edge& edge = TopoDS::Edge( edgeMap( i ));
+    BRepAdaptor_Curve C( edge );
+
+    vector< double > params;
+    if ( SMESH_Algo::GetNodeParamOnEdge( theMesh->GetMeshDS(), edge, params ))
+    {
+      nbEdges++;
+      double l1 = GCPnts_AbscissaPoint::Length( C, params[0], params[1] );
+      _begLength += l1;
+      if ( params.size() > 2 && l1 > 1e-100 )
+        _ratio += GCPnts_AbscissaPoint::Length( C, params[1], params[2]) / l1;
+      else
+        _ratio += 1;
+    }
+  }
+  if ( nbEdges ) {
+    _begLength /= nbEdges;
+    _ratio     /= nbEdges;
+  }
+  else {
+    _begLength = 1;
+    _ratio     = 1;
+  }
+  return nbEdges;
+}
+
+//================================================================================
+/*!
+ * \brief Initialize my parameter values by default parameters.
+ *  \retval bool - true if parameter values have been successfully defined
+ */
+//================================================================================
+
+bool StdMeshers_Geometric1D::SetParametersByDefaults(const TDefaults&  dflts,
+                                                     const SMESH_Mesh* /*mesh*/)
+{
+  return ( _begLength = dflts._elemLength );
+}
+
diff --git a/src/StdMeshers/StdMeshers_Geometric1D.hxx b/src/StdMeshers/StdMeshers_Geometric1D.hxx
new file mode 100644 (file)
index 0000000..436c317
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright (C) 2007-2013  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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH SMESH : implementaion of SMESH idl descriptions
+//  File   : StdMeshers_Geometric1D.hxx
+//  Module : SMESH
+//
+#ifndef _SMESH_Geometric1D_HXX_
+#define _SMESH_Geometric1D_HXX_
+
+#include "SMESH_StdMeshers.hxx"
+
+#include "StdMeshers_Reversible1D.hxx"
+#include "Utils_SALOME_Exception.hxx"
+
+class STDMESHERS_EXPORT StdMeshers_Geometric1D: public StdMeshers_Reversible1D
+{
+public:
+  StdMeshers_Geometric1D(int hypId, int studyId, SMESH_Gen* gen);
+
+  void SetStartLength(double length) throw(SALOME_Exception);
+  void SetCommonRatio(double factor) throw(SALOME_Exception);
+
+  double GetStartLength() const;
+  double GetCommonRatio() const;
+
+  virtual std::ostream & SaveTo(std::ostream & save);
+  virtual std::istream & LoadFrom(std::istream & load);
+
+  /*!
+   * \brief Initialize start and end length 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
+   */
+  virtual bool SetParametersByMesh(const SMESH_Mesh* theMesh, const TopoDS_Shape& theShape);
+
+  /*!
+   * \brief Initialize my parameter values by default parameters.
+   *  \retval bool - true if parameter values have been successfully defined
+   */
+  virtual bool SetParametersByDefaults(const TDefaults& dflts, const SMESH_Mesh* theMesh=0);
+
+protected:
+  double _begLength, _ratio;
+};
+
+#endif
index 949ba6709144546c007b1d6e02a5a90e0830734e..a0d205bd1f8036d74df69815c35514606a10671e 100644 (file)
@@ -222,8 +222,8 @@ namespace
    * \brief Finds FaceQuadStruct having a side equal to a given one and rearranges
    *  the found FaceQuadStruct::side to have the given side at a Q_BOTTOM place
    */
-  FaceQuadStructPtr getQuadWithBottom( StdMeshers_FaceSide* side,
-                                       FaceQuadStructPtr    quad[ 6 ])
+  FaceQuadStructPtr getQuadWithBottom( StdMeshers_FaceSidePtr side,
+                                       FaceQuadStructPtr      quad[ 6 ])
   {
     FaceQuadStructPtr foundQuad;
     for ( int i = 1; i < 6; ++i )
@@ -231,7 +231,7 @@ namespace
       if ( !quad[i] ) continue;
       for ( unsigned iS = 0; iS < quad[i]->side.size(); ++iS )
       {
-        const StdMeshers_FaceSide* side2 = quad[i]->side[iS];
+        const StdMeshers_FaceSidePtr side2 = quad[i]->side[iS];
         if (( side->FirstVertex().IsSame( side2->FirstVertex() ) ||
               side->FirstVertex().IsSame( side2->LastVertex() ))
             &&
@@ -241,7 +241,7 @@ namespace
         {
           if ( iS != Q_BOTTOM )
           {
-            vector< StdMeshers_FaceSide*> newSides;
+            vector< FaceQuadStruct::Side > newSides;
             for ( unsigned j = iS; j < quad[i]->side.size(); ++j )
               newSides.push_back( quad[i]->side[j] );
             for ( unsigned j = 0; j < iS; ++j )
@@ -391,7 +391,7 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh &         aMesh,
   for ( int i = 0; i < 6; ++i )
   {
     const TopoDS_Face& F = aCubeSide[i]._quad->face;
-    StdMeshers_FaceSide* baseQuadSide = aCubeSide[i]._quad->side[ Q_BOTTOM ];
+    StdMeshers_FaceSidePtr baseQuadSide = aCubeSide[i]._quad->side[ Q_BOTTOM ];
     list<TopoDS_Edge> baseEdges( baseQuadSide->Edges().begin(), baseQuadSide->Edges().end() );
 
     // assure correctness of node positions on baseE:
index 07e9a166d838772b7633130ec1f1613038a434ed..33bd5e1dcfc2397a2370dff82b9401318a59898b 100644 (file)
@@ -107,7 +107,7 @@ namespace {
            algo->myProxyMesh->GetMesh() != helper->GetMesh() )
         algo->myProxyMesh.reset( new SMESH_ProxyMesh( *helper->GetMesh() ));
 
-      algo->myQuadStruct.reset();
+      algo->myQuadList.clear();
 
       if ( helper )
         algo->_quadraticMesh = helper->GetIsQuadratic();
@@ -166,15 +166,15 @@ namespace {
   //================================================================================
 
   bool setBottomEdge( const TopoDS_Edge&   botE,
-                      faceQuadStruct::Ptr& quad,
+                      FaceQuadStruct::Ptr& quad,
                       const TopoDS_Shape&  face)
   {
-    quad->side[ QUAD_TOP_SIDE  ]->Reverse();
-    quad->side[ QUAD_LEFT_SIDE ]->Reverse();
+    quad->side[ QUAD_TOP_SIDE  ].grid->Reverse();
+    quad->side[ QUAD_LEFT_SIDE ].grid->Reverse();
     int edgeIndex = 0;
     for ( size_t i = 0; i < quad->side.size(); ++i )
     {
-      StdMeshers_FaceSide* quadSide = quad->side[i];
+      StdMeshers_FaceSidePtr quadSide = quad->side[i];
       for ( int iE = 0; iE < quadSide->NbEdges(); ++iE )
         if ( botE.IsSame( quadSide->Edge( iE )))
         {
@@ -681,7 +681,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
               continue; // already computed prism
             }
             // find a source FACE of the SOLID: it's a FACE sharing a bottom EDGE with wFace
-            const TopoDS_Edge& wEdge = (*wQuad)->side[ QUAD_TOP_SIDE ]->Edge(0);
+            const TopoDS_Edge& wEdge = (*wQuad)->side[ QUAD_TOP_SIDE ].grid->Edge(0);
             PShapeIteratorPtr faceIt = myHelper->GetAncestors( wEdge, *myHelper->GetMesh(),
                                                                TopAbs_FACE);
             while ( const TopoDS_Shape* f = faceIt->next() )
@@ -879,7 +879,7 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism,
     int nbKnownFaces;
     do {
       nbKnownFaces = faceMap.Extent();
-      StdMeshers_FaceSide *rightSide, *topSide; // sides of the quad
+      StdMeshers_FaceSidePtr rightSide, topSide; // sides of the quad
       for ( size_t i = 0; i < thePrism.myWallQuads.size(); ++i )
       {
         rightSide = thePrism.myWallQuads[i].back()->side[ QUAD_RIGHT_SIDE ];
@@ -911,8 +911,8 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism,
     {
       for ( size_t i = 0; i < thePrism.myWallQuads.size(); ++i )
       {
-        StdMeshers_FaceSide* topSide = thePrism.myWallQuads[i].back()->side[ QUAD_TOP_SIDE ];
-        const TopoDS_Edge &     topE = topSide->Edge( 0 );
+        StdMeshers_FaceSidePtr topSide = thePrism.myWallQuads[i].back()->side[ QUAD_TOP_SIDE ];
+        const TopoDS_Edge &       topE = topSide->Edge( 0 );
         if ( topSide->NbEdges() > 1 )
           return toSM( error(COMPERR_BAD_SHAPE, TCom("Side face #") <<
                              shapeID( thePrism.myWallQuads[i].back()->face )
@@ -958,8 +958,8 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism,
   // Check that the top FACE shares all the top EDGEs
   for ( size_t i = 0; i < thePrism.myWallQuads.size(); ++i )
   {
-    StdMeshers_FaceSide* topSide = thePrism.myWallQuads[i].back()->side[ QUAD_TOP_SIDE ];
-    const TopoDS_Edge &     topE = topSide->Edge( 0 );
+    StdMeshers_FaceSidePtr topSide = thePrism.myWallQuads[i].back()->side[ QUAD_TOP_SIDE ];
+    const TopoDS_Edge &       topE = topSide->Edge( 0 );
     if ( !myHelper->IsSubShape( topE, thePrism.myTop ))
       return toSM( error( TCom("Wrong source face (#") << shapeID( thePrism.myBottom )));
   }
@@ -1205,7 +1205,7 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
     int wgt = 0; // "weight"
     for ( ; quad != thePrism.myWallQuads[iW].end(); ++quad )
     {
-      StdMeshers_FaceSide* lftSide = (*quad)->side[ QUAD_LEFT_SIDE ];
+      StdMeshers_FaceSidePtr lftSide = (*quad)->side[ QUAD_LEFT_SIDE ];
       for ( int i = 0; i < lftSide->NbEdges(); ++i )
       {
         ++wgt;
@@ -1224,7 +1224,7 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
       quad = thePrism.myWallQuads[iW].begin();
       for ( ; quad != thePrism.myWallQuads[iW].end(); ++quad )
         for ( int i = 0; i < NB_QUAD_SIDES; ++i )
-          (*quad)->side[ i ]->SetIgnoreMediumNodes( true );
+          (*quad)->side[ i ].grid->SetIgnoreMediumNodes( true );
     }
   }
 
@@ -1237,8 +1237,8 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
     Prism_3D::TQuadList::const_iterator quad = quads.begin();
     for ( ; quad != quads.end(); ++quad )
     {
-      StdMeshers_FaceSide* rgtSide = (*quad)->side[ QUAD_RIGHT_SIDE ]; // tgt
-      StdMeshers_FaceSide* lftSide = (*quad)->side[ QUAD_LEFT_SIDE ];  // src
+      StdMeshers_FaceSidePtr rgtSide = (*quad)->side[ QUAD_RIGHT_SIDE ]; // tgt
+      StdMeshers_FaceSidePtr lftSide = (*quad)->side[ QUAD_LEFT_SIDE ];  // src
       bool swapLeftRight = ( lftSide->NbSegments( /*update=*/true ) == 0 &&
                              rgtSide->NbSegments( /*update=*/true )  > 0 );
       if ( swapLeftRight )
@@ -1373,8 +1373,8 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
       // to compute stuctured quad mesh on wall FACEs
       // ---------------------------------------------------
       {
-        const TopoDS_Edge& botE = (*quad)->side[ QUAD_BOTTOM_SIDE ]->Edge(0);
-        const TopoDS_Edge& topE = (*quad)->side[ QUAD_TOP_SIDE    ]->Edge(0);
+        const TopoDS_Edge& botE = (*quad)->side[ QUAD_BOTTOM_SIDE ].grid->Edge(0);
+        const TopoDS_Edge& topE = (*quad)->side[ QUAD_TOP_SIDE    ].grid->Edge(0);
         SMESH_subMesh*    botSM = mesh->GetSubMesh( botE );
         SMESH_subMesh*    topSM = mesh->GetSubMesh( topE );
         SMESH_subMesh*    srcSM = botSM;
@@ -2352,7 +2352,7 @@ bool StdMeshers_PrismAsBlock::Init(SMESH_MesherHelper*         helper,
     Prism_3D::TQuadList::const_iterator quad = thePrism.myWallQuads[ iE ].begin();
     for ( ; quad != thePrism.myWallQuads[ iE ].end(); ++quad )
     {
-      const TopoDS_Edge& quadBot = (*quad)->side[ QUAD_BOTTOM_SIDE ]->Edge( 0 );
+      const TopoDS_Edge& quadBot = (*quad)->side[ QUAD_BOTTOM_SIDE ].grid->Edge( 0 );
       if ( !myHelper->LoadNodeColumns( faceColumns, (*quad)->face, quadBot, meshDS ))
         return error(COMPERR_BAD_INPUT_MESH, TCom("Can't find regular quadrangle mesh ")
                      << "on a side face #" << MeshDS()->ShapeToIndex( (*quad)->face ));
@@ -2373,7 +2373,7 @@ bool StdMeshers_PrismAsBlock::Init(SMESH_MesherHelper*         helper,
     Prism_3D::TQuadList::const_iterator quad = thePrism.myWallQuads[ iE ].begin();
     for ( ; quad != thePrism.myWallQuads[ iE ].end(); ++quad )
     {
-      const TopoDS_Edge& quadBot = (*quad)->side[ QUAD_BOTTOM_SIDE ]->Edge( 0 );
+      const TopoDS_Edge& quadBot = (*quad)->side[ QUAD_BOTTOM_SIDE ].grid->Edge( 0 );
       if ( !myHelper->LoadNodeColumns( faceColumns, (*quad)->face, quadBot, meshDS ))
         return error(COMPERR_BAD_INPUT_MESH, TCom("Can't find regular quadrangle mesh ")
                      << "on a side face #" << MeshDS()->ShapeToIndex( (*quad)->face ));
index 6bb6adc1fa94d0693d7d55fbf7bf1679d003fc12..96570ecdd98a8683969fe700361bffd2459d1a5f 100644 (file)
@@ -1018,9 +1018,9 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
       map< double, const SMDS_MeshNode* >::iterator u_oldNode, u_newNode, u_newOnSeam, newEnd;
       set< const SMDS_MeshNode* > seamNodes;
 
-      // mapper puts on a seam edge nodes from 2 edges
+      // mapper changed, no more "mapper puts on a seam edge nodes from 2 edges"
       if ( isSeam && ! getBoundaryNodes ( sm, tgtFace, u2nodesOnSeam, seamNodes ))
-        RETURN_BAD_RESULT("getBoundaryNodes() failed");
+        ;//RETURN_BAD_RESULT("getBoundaryNodes() failed");
 
       SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
       while ( nIt->more() )
index bfe999db9ecd4c4204b36863b7f464100838e1ee..15bd1944cc121a3faad57c2caa4a587848ec2e59 100644 (file)
@@ -64,7 +64,8 @@ namespace {
     /*!
      * \brief Return an edge from which hypotheses are propagated from
      */
-    static TopoDS_Edge GetSource(SMESH_subMesh * submesh);
+    static TopoDS_Edge GetSource(SMESH_subMesh * submesh,
+                                 bool&           isPropagOfDistribution);
     /*!
      * \brief Does it's main job
      */
@@ -90,23 +91,28 @@ StdMeshers_Propagation::StdMeshers_Propagation (int hypId, int studyId, SMESH_Ge
   _name = GetName();
   _param_algo_dim = -1; // 1D auxiliary
 }
+StdMeshers_PropagOfDistribution::StdMeshers_PropagOfDistribution (int hypId,
+                                                                  int studyId,
+                                                                  SMESH_Gen * gen)
+  : StdMeshers_Propagation(hypId, studyId, gen)                        { _name = GetName(); }
 StdMeshers_Propagation::~StdMeshers_Propagation()                      {}
 string StdMeshers_Propagation::GetName ()                              { return "Propagation"; }
+string StdMeshers_PropagOfDistribution::GetName ()                     { return "PropagOfDistribution"; }
 ostream & StdMeshers_Propagation::SaveTo (ostream & save)              { return save; }
 istream & StdMeshers_Propagation::LoadFrom (istream & load)            { return load; }
-ostream & operator << (ostream & save, StdMeshers_Propagation & hyp)   { return hyp.SaveTo(save); }
-istream & operator >> (istream & load, StdMeshers_Propagation & hyp)   { return hyp.LoadFrom(load); }
 bool StdMeshers_Propagation::SetParametersByMesh(const SMESH_Mesh*,
                                                  const TopoDS_Shape& ) { return false; }
 bool StdMeshers_Propagation::SetParametersByDefaults(const TDefaults&,const SMESH_Mesh*) { return false; }
 void StdMeshers_Propagation::SetPropagationMgr(SMESH_subMesh* subMesh) { PropagationMgr::Set( subMesh ); }
 /*!
- * \brief Return an edge from which hypotheses are propagated from
+ * \brief Return an edge from which hypotheses are propagated
  */
-TopoDS_Edge StdMeshers_Propagation::GetPropagationSource(SMESH_Mesh& theMesh,
-                                                         const TopoDS_Shape& theEdge)
+TopoDS_Edge StdMeshers_Propagation::GetPropagationSource(SMESH_Mesh&         theMesh,
+                                                         const TopoDS_Shape& theEdge,
+                                                         bool&               isPropagOfDistribution)
 {
-  return PropagationMgr::GetSource(theMesh.GetSubMeshContaining( theEdge ));
+  return PropagationMgr::GetSource( theMesh.GetSubMeshContaining( theEdge ),
+                                    isPropagOfDistribution);
 }
 
 //=============================================================================
@@ -126,11 +132,13 @@ namespace {
   struct PropagationMgrData : public EventListenerData
   {
     bool myForward; //!< true if a curve of edge in chain is codirected with one of source edge
+    bool myIsPropagOfDistribution; //!< type of Propagation hyp
     PropagationMgrData( SubMeshState state=WAIT_PROPAG_HYP ): EventListenerData(true) {
-      myType = state; myForward = true;
+      myType = state; myForward = true; myIsPropagOfDistribution = false;
     }
     void Init() {
       myType = WAIT_PROPAG_HYP;  mySubMeshes.clear(); myForward = true;
+      myIsPropagOfDistribution = false;
     }
     SubMeshState State() const {
       return (SubMeshState) myType;
@@ -217,8 +225,13 @@ namespace {
   const SMESH_Hypothesis* getProagationHyp (SMESH_Mesh&         theMesh,
                                             const TopoDS_Shape& theEdge)
   {
-    static SMESH_HypoFilter propagHypFilter
-      ( SMESH_HypoFilter::HasName( StdMeshers_Propagation::GetName ()));
+    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 );
   }
   //================================================================================
@@ -248,6 +261,10 @@ namespace {
     PropagationMgrData* chainData = getData( theMainSubMesh );
     chainData->SetState( HAS_PROPAG_HYP );
 
+    if ( const SMESH_Hypothesis * propagHyp = getProagationHyp( *mesh, theMainEdge ))
+      chainData->myIsPropagOfDistribution =
+        ( StdMeshers_PropagOfDistribution::GetName() == propagHyp->GetName() );
+
     // Edge submeshes, to which the 1D hypothesis will be propagated from theMainEdge
     list<SMESH_subMesh*> & chain = chainData->mySubMeshes;
     chain.clear();
@@ -462,17 +479,21 @@ namespace {
   {
     if ( findData( submesh )) return;
     DBGMSG( "PropagationMgr::Set() on  " << submesh->GetId() );
-    EventListenerData* data = new PropagationMgrData();
+    PropagationMgrData* data = new PropagationMgrData();
     submesh->SetEventListener( getListener(), data, submesh );
 
     const SMESH_Hypothesis * propagHyp =
       getProagationHyp( *submesh->GetFather(), submesh->GetSubShape() );
     if ( propagHyp )
+    {
+      data->myIsPropagOfDistribution =
+        ( StdMeshers_PropagOfDistribution::GetName() == propagHyp->GetName() );
       getListener()->ProcessEvent( SMESH_subMesh::ADD_HYP,
                                    SMESH_subMesh::ALGO_EVENT,
                                    submesh,
                                    data,
                                    propagHyp);
+    }
   }
   //================================================================================
   /*!
@@ -480,7 +501,8 @@ namespace {
    */
   //================================================================================
 
-  TopoDS_Edge PropagationMgr::GetSource(SMESH_subMesh * submesh)
+  TopoDS_Edge PropagationMgr::GetSource(SMESH_subMesh * submesh,
+                                        bool&           isPropagOfDistribution)
   {
     if ( PropagationMgrData* data = findData( submesh )) {
       if ( data->State() == IN_CHAIN ) {
@@ -489,6 +511,9 @@ namespace {
           TopoDS_Shape edge = sm->GetSubShape();
           edge = edge.Oriented( data->myForward ? TopAbs_FORWARD : TopAbs_REVERSED );
           DBGMSG( " GetSource() = edge " << sm->GetId() << " REV = " << (!data->myForward));
+          isPropagOfDistribution = false;
+          if ( PropagationMgrData* data = findData( sm ))
+            isPropagOfDistribution = data->myIsPropagOfDistribution;
           if ( edge.ShapeType() == TopAbs_EDGE )
             return TopoDS::Edge( edge );
         }
@@ -502,9 +527,9 @@ namespace {
    */
   //================================================================================
 
-  void PropagationMgr::ProcessEvent(const int          event,
-                                    const int          eventType,
-                                    SMESH_subMesh*     subMesh,
+  void PropagationMgr::ProcessEvent(const int                       event,
+                                    const int                       eventType,
+                                    SMESH_subMesh*                  subMesh,
                                     SMESH_subMeshEventListenerData* listenerData,
                                     const SMESH_Hypothesis*         hyp)
   {
@@ -516,7 +541,8 @@ namespace {
       return;
     DBGMSG( "PropagationMgr::ProcessEvent() on  " << subMesh->GetId() );
 
-    bool isPropagHyp = ( StdMeshers_Propagation::GetName() == hyp->GetName() );
+    bool isPropagHyp = ( StdMeshers_Propagation::GetName()          == hyp->GetName() ||
+                         StdMeshers_PropagOfDistribution::GetName() == hyp->GetName() );
 
     PropagationMgrData* data = static_cast<PropagationMgrData*>( listenerData );
     switch ( data->State() ) {
index c5a1616f7d5347b716ccf04650a518df8f207310..e8a2b6e7afb29cccffaccd0377272057a2909aa6 100644 (file)
@@ -50,8 +50,6 @@ class STDMESHERS_EXPORT StdMeshers_Propagation:public SMESH_Hypothesis
 
   virtual std::ostream & SaveTo(std::ostream & save);
   virtual std::istream & LoadFrom(std::istream & load);
-  friend std::ostream & operator <<(std::ostream & save, StdMeshers_Propagation & hyp);
-  friend std::istream & operator >>(std::istream & load, StdMeshers_Propagation & hyp);
 
   static std::string GetName ();
 
@@ -69,7 +67,9 @@ class STDMESHERS_EXPORT StdMeshers_Propagation:public SMESH_Hypothesis
     * \param theEdge - edge to which hypotheses are propagated
     * \retval TopoDS_Edge - source edge, also passing orientation
    */
-  static TopoDS_Edge GetPropagationSource(SMESH_Mesh& theMesh, const TopoDS_Shape& theEdge);
+  static TopoDS_Edge GetPropagationSource(SMESH_Mesh&         theMesh,
+                                          const TopoDS_Shape& theEdge,
+                                          bool&               isPropagOfDistribution );
 
   /*!
    * \brief Initialize my parameter values by the mesh built on the geometry
@@ -88,4 +88,19 @@ class STDMESHERS_EXPORT StdMeshers_Propagation:public SMESH_Hypothesis
   virtual bool SetParametersByDefaults(const TDefaults& dflts, const SMESH_Mesh* theMesh=0);
 
 };
+
+// =======================================================================
+/*!
+ * \brief Propagation Of Distribution hypothesis
+ */
+// =======================================================================
+
+class STDMESHERS_EXPORT StdMeshers_PropagOfDistribution: public StdMeshers_Propagation
+{
+ public:
+  StdMeshers_PropagOfDistribution(int hypId, int studyId, SMESH_Gen * gen);
+
+  static std::string GetName();
+};
+
 #endif
index 5369e598cb38ca23f8947b46840af3de870f5932..e8ab5ad6abec5e56575f3ed6d7ba50f6fb48dabf 100644 (file)
@@ -87,6 +87,43 @@ void StdMeshers_QuadrangleParams::SetQuadType (StdMeshers_QuadType type)
   }
 }
 
+//================================================================================
+/*!
+ * \brief Set positions of enforced nodes
+ */
+//================================================================================
+
+void StdMeshers_QuadrangleParams::
+SetEnforcedNodes( const std::vector< TopoDS_Shape >& shapes,
+                  const std::vector< gp_Pnt >&       points )
+{
+  bool isChanged = ( shapes        != _enforcedVertices ||
+                     points.size() != _enforcedPoints.size() );
+  for ( size_t i = 0; i < points.size() && !isChanged; ++i )
+    isChanged = ( _enforcedPoints[ i ].SquareDistance( points[i] ) > 1e-100 );
+      
+  if ( isChanged )
+  {
+    _enforcedVertices = shapes;
+    _enforcedPoints   = points;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Returns positions of enforced nodes
+ */
+//================================================================================
+
+void StdMeshers_QuadrangleParams::
+GetEnforcedNodes( std::vector< TopoDS_Shape >& shapes,
+                  std::vector< gp_Pnt >&       points ) const
+{
+  shapes = _enforcedVertices;
+  points = _enforcedPoints;
+}
+
 //=============================================================================
 /*!
  *
@@ -98,6 +135,13 @@ ostream & StdMeshers_QuadrangleParams::SaveTo(ostream & save)
     save << _triaVertexID << " UNDEFINED " << int(_quadType);
   else
     save << _triaVertexID << " " << _objEntry << " " << int(_quadType);
+
+  save << " " << _enforcedPoints.size();
+  for ( size_t i = 0; i < _enforcedPoints.size(); ++i )
+    save << " " << _enforcedPoints[i].X()
+         << " " << _enforcedPoints[i].Y()
+         << " " << _enforcedPoints[i].Z();
+
   return save;
 }
 
@@ -122,29 +166,25 @@ istream & StdMeshers_QuadrangleParams::LoadFrom(istream & load)
   if (isOK)
     _quadType = StdMeshers_QuadType(type);
 
+  // _enforcedVertices are loaded at StdMeshers_I level
+  // because GEOM objects are referred by study entry.
+
+  int nbP = 0;
+  double x,y,z;
+  if ( load >> nbP && nbP > 0 )
+  {
+    _enforcedPoints.reserve( nbP );
+    while ( _enforcedPoints.size() < _enforcedPoints.capacity() )
+      if ( load >> x &&
+           load >> y &&
+           load >> z )
+        _enforcedPoints.push_back( gp_Pnt( x,y,z ));
+      else
+        break;
+  }
   return load;
 }
 
-//=============================================================================
-/*!
- *
- */
-//=============================================================================
-ostream & operator <<(ostream & save, StdMeshers_QuadrangleParams & hyp)
-{
-  return hyp.SaveTo( save );
-}
-
-//=============================================================================
-/*!
- *
- */
-//=============================================================================
-istream & operator >>(istream & load, StdMeshers_QuadrangleParams & hyp)
-{
-  return hyp.LoadFrom( load );
-}
-
 //================================================================================
 /*!
  * \brief Redifined method
index 9d8374daa47ae2584e808177cccfb23e028f1a62..afc6a8523a7a1cb6ee957e7d2f166262372d0b32 100644 (file)
 #define _SMESH_QUADRANGLEPARAMS_HXX_
 
 #include "SMESH_StdMeshers.hxx"
-
 #include "SMESH_Hypothesis.hxx"
-#include "Utils_SALOME_Exception.hxx"
+
+#include <gp_Pnt.hxx>
+
+#include <vector>
+#include <string>
 
 enum StdMeshers_QuadType
   {
@@ -38,8 +41,7 @@ enum StdMeshers_QuadType
     QUAD_NB_TYPES
   };
 
-class STDMESHERS_EXPORT StdMeshers_QuadrangleParams:
-  public SMESH_Hypothesis
+class STDMESHERS_EXPORT StdMeshers_QuadrangleParams: public SMESH_Hypothesis
 {
 public:
   StdMeshers_QuadrangleParams(int hypId, int studyId, SMESH_Gen* gen);
@@ -54,12 +56,13 @@ public:
   void SetQuadType (StdMeshers_QuadType type);
   StdMeshers_QuadType GetQuadType() const { return _quadType; }
 
+  void SetEnforcedNodes( const std::vector< TopoDS_Shape >& shapes,
+                         const std::vector< gp_Pnt >&       points );
+  void GetEnforcedNodes( std::vector< TopoDS_Shape >& shapes,
+                         std::vector< gp_Pnt >&       points ) const;
+
   virtual std::ostream & SaveTo(std::ostream & save);
   virtual std::istream & LoadFrom(std::istream & load);
-  friend std::ostream& operator << (std::ostream & save,
-                                    StdMeshers_QuadrangleParams & hyp);
-  friend std::istream& operator >> (std::istream & load,
-                                    StdMeshers_QuadrangleParams & hyp);
 
   /*!
    * \brief Initialize start and end length by the mesh built on the geometry
@@ -78,9 +81,11 @@ public:
                                        const SMESH_Mesh* theMesh=0);
 
 protected:
-  int                 _triaVertexID;
-  std::string         _objEntry;
-  StdMeshers_QuadType _quadType;
+  int                         _triaVertexID;
+  std::string                 _objEntry;
+  StdMeshers_QuadType         _quadType;
+  std::vector< TopoDS_Shape > _enforcedVertices;
+  std::vector< gp_Pnt >       _enforcedPoints;
 };
 
 #endif
index 62fadc505d62aee51cbe755056e3b12f4581aa06..1275988675e93267201dc26caaf5a346007792a8 100644 (file)
 #include "SMESH_Block.hxx"
 #include "SMESH_Comment.hxx"
 #include "SMESH_Gen.hxx"
+#include "SMESH_HypoFilter.hxx"
 #include "SMESH_Mesh.hxx"
+#include "SMESH_MeshAlgos.hxx"
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_subMesh.hxx"
 #include "StdMeshers_FaceSide.hxx"
 #include "StdMeshers_QuadrangleParams.hxx"
 #include "StdMeshers_ViscousLayers2D.hxx"
 
+#include <BRepClass_FaceClassifier.hxx>
 #include <BRep_Tool.hxx>
 #include <GeomAPI_ProjectPointOnSurf.hxx>
 #include <Geom_Surface.hxx>
@@ -85,8 +88,9 @@ StdMeshers_Quadrangle_2D::StdMeshers_Quadrangle_2D (int hypId, int studyId,
     myTrianglePreference(false),
     myTriaVertexID(-1),
     myNeedSmooth(false),
+    myParams( NULL ),
     myQuadType(QUAD_STANDARD),
-    myHelper( 0 )
+    myHelper( NULL )
 {
   MESSAGE("StdMeshers_Quadrangle_2D::StdMeshers_Quadrangle_2D");
   _name = "Quadrangle_2D";
@@ -119,15 +123,16 @@ bool StdMeshers_Quadrangle_2D::CheckHypothesis
                           const TopoDS_Shape&                  aShape,
                           SMESH_Hypothesis::Hypothesis_Status& aStatus)
 {
-  myTriaVertexID = -1;
-  myQuadType = QUAD_STANDARD;
+  myTriaVertexID         = -1;
+  myQuadType             = QUAD_STANDARD;
   myQuadranglePreference = false;
-  myTrianglePreference = false;
-  myQuadStruct.reset();
-  myHelper = NULL;
+  myTrianglePreference   = false;
+  myHelper               = (SMESH_MesherHelper*)NULL;
+  myParams               = NULL;
+  myQuadList.clear();
 
   bool isOk = true;
-  aStatus = SMESH_Hypothesis::HYP_OK;
+  aStatus   = SMESH_Hypothesis::HYP_OK;
 
   const list <const SMESHDS_Hypothesis * >& hyps =
     GetUsedHypothesis(aMesh, aShape, false);
@@ -138,11 +143,11 @@ bool StdMeshers_Quadrangle_2D::CheckHypothesis
   // First assigned hypothesis (if any) is processed now
   if (hyps.size() > 0) {
     aHyp = hyps.front();
-    if (strcmp("QuadrangleParams", aHyp->GetName()) == 0) {
-      const StdMeshers_QuadrangleParams* aHyp1 = 
-        (const StdMeshers_QuadrangleParams*)aHyp;
-      myTriaVertexID = aHyp1->GetTriaVertex();
-      myQuadType = aHyp1->GetQuadType();
+    if (strcmp("QuadrangleParams", aHyp->GetName()) == 0)
+    {
+      myParams = (const StdMeshers_QuadrangleParams*)aHyp;
+      myTriaVertexID = myParams->GetTriaVertex();
+      myQuadType     = myParams->GetQuadType();
       if (myQuadType == QUAD_QUADRANGLE_PREF ||
           myQuadType == QUAD_QUADRANGLE_PREF_REVERSED)
         myQuadranglePreference = true;
@@ -221,22 +226,25 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh&         aMesh,
   FaceQuadStruct::Ptr quad = CheckNbEdges( aMesh, F, /*considerMesh=*/true );
   if (!quad)
     return false;
-  myQuadStruct = quad;
+  myQuadList.clear();
+  myQuadList.push_back( quad );
+
+  if ( !getEnforcedUV() )
+    return false;
 
   updateDegenUV( quad );
 
+  int n1 = quad->side[0].NbPoints();
+  int n2 = quad->side[1].NbPoints();
+  int n3 = quad->side[2].NbPoints();
+  int n4 = quad->side[3].NbPoints();
+
   enum { NOT_COMPUTED = -1, COMPUTE_FAILED = 0, COMPUTE_OK = 1 };
   int res = NOT_COMPUTED;
   if (myQuadranglePreference)
   {
-    int n1    = quad->side[0]->NbPoints();
-    int n2    = quad->side[1]->NbPoints();
-    int n3    = quad->side[2]->NbPoints();
-    int n4    = quad->side[3]->NbPoints();
     int nfull = n1+n2+n3+n4;
-    int ntmp  = nfull/2;
-    ntmp = ntmp*2;
-    if (nfull == ntmp && ((n1 != n3) || (n2 != n4)))
+    if ((nfull % 2) == 0 && ((n1 != n3) || (n2 != n4)))
     {
       // special path genarating only quandrangle faces
       res = computeQuadPref( aMesh, F, quad );
@@ -244,10 +252,6 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh&         aMesh,
   }
   else if (myQuadType == QUAD_REDUCED)
   {
-    int n1     = quad->side[0]->NbPoints();
-    int n2     = quad->side[1]->NbPoints();
-    int n3     = quad->side[2]->NbPoints();
-    int n4     = quad->side[3]->NbPoints();
     int n13    = n1 - n3;
     int n24    = n2 - n4;
     int n13tmp = n13/2; n13tmp = n13tmp*2;
@@ -275,7 +279,10 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh&         aMesh,
 
   if ( res == NOT_COMPUTED )
   {
-    res = computeQuadDominant( aMesh, F, quad );
+    if ( n1 != n3 || n2 != n4 )
+      res = computeTriangles( aMesh, F, quad );
+    else
+      res = computeQuadDominant( aMesh, F );
   }
 
   if ( res == COMPUTE_OK && myNeedSmooth )
@@ -284,6 +291,83 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh&         aMesh,
   return ( res == COMPUTE_OK );
 }
 
+//================================================================================
+/*!
+ * \brief Compute quadrangles and triangles on the quad
+ */
+//================================================================================
+
+bool StdMeshers_Quadrangle_2D::computeTriangles(SMESH_Mesh&         aMesh,
+                                                const TopoDS_Face&  aFace,
+                                                FaceQuadStruct::Ptr quad)
+{
+  int nb = quad->side[0].grid->NbPoints();
+  int nr = quad->side[1].grid->NbPoints();
+  int nt = quad->side[2].grid->NbPoints();
+  int nl = quad->side[3].grid->NbPoints();
+
+  // rotate the quad to have nbNodeOut sides on TOP [and LEFT]
+  if ( nb > nt )
+    quad->shift( nl > nr ? 3 : 2, true );
+  else if ( nr > nl )
+    quad->shift( 1, true );
+  else if ( nl > nr )
+    quad->shift( nt > nb ? 0 : 3, true );
+
+  if ( !setNormalizedGrid( quad ))
+    return false;
+
+  if ( quad->nbNodeOut( QUAD_BOTTOM_SIDE ))
+  {
+    splitQuad( quad, 0, 1 );
+  }
+  if ( quad->nbNodeOut( QUAD_TOP_SIDE    ))
+  {
+    splitQuad( quad, 0, quad->jSize-2 );
+  }
+  FaceQuadStruct::Ptr newQuad = myQuadList.back();
+  if ( quad != newQuad ) // split done
+  {
+    // make quad be a greatest one
+    if ( quad->side[ QUAD_LEFT_SIDE ].NbPoints() == 2 ||
+         quad->side[ QUAD_RIGHT_SIDE ].NbPoints() == 2  )
+      quad = newQuad;
+    if ( !setNormalizedGrid( quad ))
+      return false;
+  }
+
+  if ( quad->nbNodeOut( QUAD_RIGHT_SIDE ))
+  {
+    splitQuad( quad, quad->iSize-2, 0 );
+  }
+  if ( quad->nbNodeOut( QUAD_LEFT_SIDE    ))
+  {
+    splitQuad( quad, 1, 0 );
+  }
+
+  return computeQuadDominant( aMesh, aFace );
+}
+
+//================================================================================
+/*!
+ * \brief Compute quadrangles and possibly triangles on all quads of myQuadList
+ */
+//================================================================================
+
+bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
+                                                   const TopoDS_Face&  aFace)
+{
+  if ( !addEnforcedNodes() )
+    return false;
+
+  std::list< FaceQuadStruct::Ptr >::iterator quad = myQuadList.begin();
+  for ( ; quad != myQuadList.end(); ++quad )
+    if ( !computeQuadDominant( aMesh, aFace, *quad ))
+      return false;
+
+  return true;
+}
+
 //================================================================================
 /*!
  * \brief Compute quadrangles and possibly triangles
@@ -294,37 +378,28 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
                                                    const TopoDS_Face&  aFace,
                                                    FaceQuadStruct::Ptr quad)
 {
-  // set normalized grid on unit square in parametric domain
+  // --- set normalized grid on unit square in parametric domain
 
-  if (!setNormalizedGrid(aMesh, aFace, quad))
+  if ( !setNormalizedGrid( quad ))
     return false;
 
-  // --- compute 3D values on points, store points & quadrangles
-
-  int nbdown  = quad->side[0]->NbPoints();
-  int nbup    = quad->side[2]->NbPoints();
-
-  int nbright = quad->side[1]->NbPoints();
-  int nbleft  = quad->side[3]->NbPoints();
+  // --- create nodes on points, and create quadrangles
 
-  int nbhoriz  = Min(nbdown, nbup);
-  int nbvertic = Min(nbright, nbleft);
+  int nbhoriz  = quad->iSize;
+  int nbvertic = quad->jSize;
 
   // internal mesh nodes
   SMESHDS_Mesh *  meshDS = aMesh.GetMeshDS();
   Handle(Geom_Surface) S = BRep_Tool::Surface(aFace);
-  int i, j, geomFaceID = meshDS->ShapeToIndex(aFace);
-  for (i = 1; i < nbhoriz - 1; i++) {
-    for (j = 1; j < nbvertic - 1; j++) {
-      int ij = j * nbhoriz + i;
-      double u = quad->uv_grid[ij].u;
-      double v = quad->uv_grid[ij].v;
-      gp_Pnt P = S->Value(u, v);
-      SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
-      meshDS->SetNodeOnFace(node, geomFaceID, u, v);
-      quad->uv_grid[ij].node = node;
+  int i,j,    geomFaceID = meshDS->ShapeToIndex(aFace);
+  for (i = 1; i < nbhoriz - 1; i++)
+    for (j = 1; j < nbvertic - 1; j++)
+    {
+      UVPtStruct& uvPnt = quad->UVPt( i, j );
+      gp_Pnt P          = S->Value( uvPnt.u, uvPnt.v );
+      uvPnt.node        = meshDS->AddNode(P.X(), P.Y(), P.Z());
+      meshDS->SetNodeOnFace( uvPnt.node, geomFaceID, uvPnt.u, uvPnt.v );
     }
-  }
   
   // mesh faces
 
@@ -340,21 +415,20 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
   //              i
   //             [0]
   
-  i = 0;
   int ilow = 0;
   int iup = nbhoriz - 1;
-  if (quad->isEdgeOut[3]) { ilow++; } else { if (quad->isEdgeOut[1]) iup--; }
+  if (quad->nbNodeOut(3)) { ilow++; } else { if (quad->nbNodeOut(1)) iup--; }
   
   int jlow = 0;
   int jup = nbvertic - 1;
-  if (quad->isEdgeOut[0]) { jlow++; } else { if (quad->isEdgeOut[2]) jup--; }
+  if (quad->nbNodeOut(0)) { jlow++; } else { if (quad->nbNodeOut(2)) jup--; }
   
   // regular quadrangles
   for (i = ilow; i < iup; i++) {
     for (j = jlow; j < jup; j++) {
       const SMDS_MeshNode *a, *b, *c, *d;
-      a = quad->uv_grid[      * nbhoriz + i    ].node;
-      b = quad->uv_grid[      * nbhoriz + i + 1].node;
+      a = quad->uv_grid[ j      * nbhoriz + i    ].node;
+      b = quad->uv_grid[ j      * nbhoriz + i + 1].node;
       c = quad->uv_grid[(j + 1) * nbhoriz + i + 1].node;
       d = quad->uv_grid[(j + 1) * nbhoriz + i    ].node;
       SMDS_MeshFace* face = myHelper->AddFace(a, b, c, d);
@@ -364,19 +438,25 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
     }
   }
 
-  const vector<UVPtStruct>& uv_e0 = quad->side[0]->GetUVPtStruct(true,0);
-  const vector<UVPtStruct>& uv_e1 = quad->side[1]->GetUVPtStruct(false,1);
-  const vector<UVPtStruct>& uv_e2 = quad->side[2]->GetUVPtStruct(true,1);
-  const vector<UVPtStruct>& uv_e3 = quad->side[3]->GetUVPtStruct(false,0);
+  // Boundary elements (must always be on an outer boundary of the FACE)
+  
+  const vector<UVPtStruct>& uv_e0 = quad->side[0].grid->GetUVPtStruct();
+  const vector<UVPtStruct>& uv_e1 = quad->side[1].grid->GetUVPtStruct();
+  const vector<UVPtStruct>& uv_e2 = quad->side[2].grid->GetUVPtStruct();
+  const vector<UVPtStruct>& uv_e3 = quad->side[3].grid->GetUVPtStruct();
 
   if (uv_e0.empty() || uv_e1.empty() || uv_e2.empty() || uv_e3.empty())
     return error(COMPERR_BAD_INPUT_MESH);
 
   double eps = Precision::Confusion();
 
-  // Boundary quadrangles
-  
-  if (quad->isEdgeOut[0]) {
+  int nbdown  = (int) uv_e0.size();
+  int nbup    = (int) uv_e2.size();
+  int nbright = (int) uv_e1.size();
+  int nbleft  = (int) uv_e3.size();
+
+  if (quad->nbNodeOut(0) && nbvertic == 2)
+  {
     // Down edge is out
     // 
     // |___|___|___|___|___|___|
@@ -393,8 +473,12 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
     // number of last node of the down edge to be processed
     int stop = nbdown - 1;
     // if right edge is out, we will stop at a node, previous to the last one
-    if (quad->isEdgeOut[1]) stop--;
-    
+    //if (quad->nbNodeOut(1)) stop--;
+    if ( quad->nbNodeOut( QUAD_RIGHT_SIDE ))
+      quad->UVPt( nbhoriz-1, 1 ).node = uv_e1[1].node;
+    if ( quad->nbNodeOut( QUAD_LEFT_SIDE ))
+      quad->UVPt( 0, 1 ).node = uv_e3[1].node;
+
     // for each node of the down edge find nearest node
     // in the first row of the regular grid and link them
     for (i = 0; i < stop; i++) {
@@ -449,7 +533,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
           if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
         }
         else {
-          splitQuad(meshDS, geomFaceID, a, b, c, d);
+          splitQuadFace(meshDS, geomFaceID, a, b, c, d);
         }
 
         // if node d is not at position g - make additional triangles
@@ -468,7 +552,8 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
       }
     }
   } else {
-    if (quad->isEdgeOut[2]) {
+    if (quad->nbNodeOut(2) && nbvertic == 2)
+    {
       // Up edge is out
       // 
       // <-<-<-<-<-<-<-<-<-<-<-<-< -- direction of processing
@@ -483,9 +568,16 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
 
       int g = nbhoriz - 1; // last processed node in the regular grid
 
+      ilow = 0;
+      iup = nbhoriz - 1;
+
       int stop = 0;
       // if left edge is out, we will stop at a second node
-      if (quad->isEdgeOut[3]) stop++;
+      //if (quad->nbNodeOut(3)) stop++;
+      if ( quad->nbNodeOut( QUAD_RIGHT_SIDE ))
+        quad->UVPt( nbhoriz-1, 0 ).node = uv_e1[ nbright-2 ].node;
+      if ( quad->nbNodeOut( QUAD_LEFT_SIDE ))
+        quad->UVPt( 0, 0 ).node = uv_e3[ nbleft-2 ].node;
 
       // for each node of the up edge find nearest node
       // in the first row of the regular grid and link them
@@ -536,10 +628,10 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
             if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
           }
           else {
-            splitQuad(meshDS, geomFaceID, a, b, c, d);
+            splitQuadFace(meshDS, geomFaceID, a, b, c, d);
           }
 
-          if (near + 1 < g) { // if d not is at g - make additional triangles
+          if (near + 1 < g) { // if d is not at g - make additional triangles
             for (int k = near + 1; k < g; k++) {
               c = quad->uv_grid[nbhoriz*(nbvertic - 2) + k].node;
               if (k + 1 > iup)
@@ -557,12 +649,14 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
   }
 
   // right or left boundary quadrangles
-  if (quad->isEdgeOut[1]) {
-//    MESSAGE("right edge is out");
+  if (quad->nbNodeOut( QUAD_RIGHT_SIDE ) && nbhoriz == 2)
+  {
     int g = 0; // last processed node in the grid
     int stop = nbright - 1;
-    if (quad->isEdgeOut[2]) stop--;
-    for (i = 0; i < stop; i++) {
+    i = 0;
+    if (quad->side[ QUAD_RIGHT_SIDE ].from != i    ) i++;
+    if (quad->side[ QUAD_RIGHT_SIDE ].to   != stop ) stop--;
+    for ( ; i < stop; i++) {
       const SMDS_MeshNode *a, *b, *c, *d;
       a = uv_e1[i].node;
       b = uv_e1[i + 1].node;
@@ -609,7 +703,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
           if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
         }
         else {
-          splitQuad(meshDS, geomFaceID, a, b, c, d);
+          splitQuadFace(meshDS, geomFaceID, a, b, c, d);
         }
 
         if (near - 1 > g) { // if d not is at g - make additional triangles
@@ -627,12 +721,14 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
       }
     }
   } else {
-    if (quad->isEdgeOut[3]) {
+    if (quad->nbNodeOut(3) && nbhoriz == 2) {
 //      MESSAGE("left edge is out");
       int g = nbvertic - 1; // last processed node in the grid
       int stop = 0;
-      if (quad->isEdgeOut[0]) stop++;
-      for (i = nbleft - 1; i > stop; i--) {
+      i = nbleft - 1;
+      if (quad->side[3].from != stop ) stop++;
+      if (quad->side[3].to   != i    ) i--;
+      for (; i > stop; i--) {
         const SMDS_MeshNode *a, *b, *c, *d;
         a = uv_e3[i].node;
         b = uv_e3[i - 1].node;
@@ -678,7 +774,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh&         aMesh,
             if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
           }
           else {
-            splitQuad(meshDS, geomFaceID, a, b, c, d);
+            splitQuadFace(meshDS, geomFaceID, a, b, c, d);
           }
 
           if (near + 1 < g) { // if d not is at g - make additional triangles
@@ -828,8 +924,8 @@ FaceQuadStruct::Ptr StdMeshers_Quadrangle_2D::CheckNbEdges(SMESH_Mesh &
                                                            const TopoDS_Shape & aShape,
                                                            const bool           considerMesh)
 {
-  if ( myQuadStruct && myQuadStruct->face.IsSame( aShape ))
-    return myQuadStruct;
+  if ( !myQuadList.empty() && myQuadList.front()->face.IsSame( aShape ))
+    return myQuadList.front();
 
   TopoDS_Face F = TopoDS::Face(aShape);
   if ( F.Orientation() >= TopAbs_INTERNAL ) F.Orientation( TopAbs_FORWARD );
@@ -852,7 +948,6 @@ FaceQuadStruct::Ptr StdMeshers_Quadrangle_2D::CheckNbEdges(SMESH_Mesh &
     return FaceQuadStruct::Ptr();
   }
   FaceQuadStruct::Ptr quad( new FaceQuadStruct );
-  quad->uv_grid = 0;
   quad->side.reserve(nbEdgesInWire.front());
   quad->face = F;
 
@@ -870,17 +965,17 @@ FaceQuadStruct::Ptr StdMeshers_Quadrangle_2D::CheckNbEdges(SMESH_Mesh &
         else
           sideEdges.push_back( *edgeIt++ );
       if ( !sideEdges.empty() )
-        quad->side.push_back(new StdMeshers_FaceSide(F, sideEdges, &aMesh, iSide < QUAD_TOP_SIDE,
-                                                     ignoreMediumNodes, myProxyMesh));
+        quad->side.push_back( StdMeshers_FaceSide::New(F, sideEdges, &aMesh, iSide < QUAD_TOP_SIDE,
+                                                       ignoreMediumNodes, myProxyMesh));
       else
         --iSide;
     }
-    const vector<UVPtStruct>& UVPSleft  = quad->side[0]->GetUVPtStruct(true,0);
-    /*  vector<UVPtStruct>& UVPStop   = */quad->side[1]->GetUVPtStruct(false,1);
-    /*  vector<UVPtStruct>& UVPSright = */quad->side[2]->GetUVPtStruct(true,1);
+    const vector<UVPtStruct>& UVPSleft  = quad->side[0].GetUVPtStruct(true,0);
+    /*  vector<UVPtStruct>& UVPStop   = */quad->side[1].GetUVPtStruct(false,1);
+    /*  vector<UVPtStruct>& UVPSright = */quad->side[2].GetUVPtStruct(true,1);
     const SMDS_MeshNode* aNode = UVPSleft[0].node;
-    gp_Pnt2d aPnt2d(UVPSleft[0].u, UVPSleft[0].v);
-    quad->side.push_back(new StdMeshers_FaceSide(quad->side[1], aNode, &aPnt2d));
+    gp_Pnt2d aPnt2d = UVPSleft[0].UV();
+    quad->side.push_back( StdMeshers_FaceSide::New( quad->side[1].grid.get(), aNode, &aPnt2d ));
     myNeedSmooth = ( nbDegenEdges > 0 );
     return quad;
   }
@@ -922,15 +1017,15 @@ FaceQuadStruct::Ptr StdMeshers_Quadrangle_2D::CheckNbEdges(SMESH_Mesh &
       }
       if ( !sideEdges.empty() )
       {
-        quad->side.push_back(new StdMeshers_FaceSide(F, sideEdges, &aMesh, iSide < QUAD_TOP_SIDE,
-                                                     ignoreMediumNodes, myProxyMesh));
+        quad->side.push_back( StdMeshers_FaceSide::New( F, sideEdges, &aMesh, iSide < QUAD_TOP_SIDE,
+                                                        ignoreMediumNodes, myProxyMesh ));
         ++iSide;
       }
       else if ( !SMESH_Algo::isDegenerated( *edgeIt ) && // closed EDGE
                 myHelper->IthVertex( 0, *edgeIt ).IsSame( myHelper->IthVertex( 1, *edgeIt )))
       {
-        quad->side.push_back(new StdMeshers_FaceSide(F, *edgeIt++, &aMesh, iSide < QUAD_TOP_SIDE,
-                                                     ignoreMediumNodes, myProxyMesh));
+        quad->side.push_back( StdMeshers_FaceSide::New( F, *edgeIt++, &aMesh, iSide < QUAD_TOP_SIDE,
+                                                        ignoreMediumNodes, myProxyMesh));
         ++iSide;
       }
       if ( quad->side.size() == 4 )
@@ -1155,36 +1250,12 @@ StdMeshers_Quadrangle_2D::CheckAnd2Dcompute (SMESH_Mesh &         aMesh,
   if ( quad )
   {
     // set normalized grid on unit square in parametric domain
-    if ( ! setNormalizedGrid( aMesh, TopoDS::Face( aShape ), quad))
+    if ( ! setNormalizedGrid( quad ))
       quad.reset();
   }
   return quad;
 }
 
-//=============================================================================
-/*!
- *
- */
-//=============================================================================
-
-faceQuadStruct::~faceQuadStruct()
-{
-  for (size_t i = 0; i < side.size(); i++) {
-    if (side[i]) {
-      delete side[i];
-      for (size_t j = i+1; j < side.size(); j++)
-        if ( side[i] == side[j] )
-          side[j] = 0;
-    }
-  }
-  side.clear();
-
-  if (uv_grid) {
-    delete [] uv_grid;
-    uv_grid = 0;
-  }
-}
-
 namespace
 {
   inline const vector<UVPtStruct>& getUVPtStructIn(FaceQuadStruct::Ptr& quad, int i, int nbSeg)
@@ -1192,9 +1263,9 @@ namespace
     bool   isXConst   = (i == QUAD_BOTTOM_SIDE || i == QUAD_TOP_SIDE);
     double constValue = (i == QUAD_BOTTOM_SIDE || i == QUAD_LEFT_SIDE) ? 0 : 1;
     return
-      quad->isEdgeOut[i] ?
-      quad->side[i]->SimulateUVPtStruct(nbSeg,isXConst,constValue) :
-      quad->side[i]->GetUVPtStruct(isXConst,constValue);
+      quad->nbNodeOut(i) ?
+      quad->side[i].grid->SimulateUVPtStruct(nbSeg,isXConst,constValue) :
+      quad->side[i].grid->GetUVPtStruct     (isXConst,constValue);
   }
   inline gp_UV calcUV(double x, double y,
                       const gp_UV& a0,const gp_UV& a1,const gp_UV& a2,const gp_UV& a3,
@@ -1212,10 +1283,11 @@ namespace
  */
 //=============================================================================
 
-bool StdMeshers_Quadrangle_2D::setNormalizedGrid (SMESH_Mesh &          aMesh,
-                                                  const TopoDS_Face&    aFace,
-                                                  FaceQuadStruct::Ptr & quad)
+bool StdMeshers_Quadrangle_2D::setNormalizedGrid (FaceQuadStruct::Ptr quad)
 {
+  if ( !quad->uv_grid.empty() )
+    return true;
+
   // Algorithme décrit dans "Génération automatique de maillages"
   // P.L. GEORGE, MASSON, Â§ 6.4.1 p. 84-85
   // traitement dans le domaine paramétrique 2d u,v
@@ -1233,81 +1305,133 @@ bool StdMeshers_Quadrangle_2D::setNormalizedGrid (SMESH_Mesh &          aMesh,
   //             =down
   //
 
-  int nbhoriz  = Min(quad->side[0]->NbPoints(), quad->side[2]->NbPoints());
-  int nbvertic = Min(quad->side[1]->NbPoints(), quad->side[3]->NbPoints());
-
-  quad->isEdgeOut[0] = (quad->side[0]->NbPoints() > quad->side[2]->NbPoints());
-  quad->isEdgeOut[1] = (quad->side[1]->NbPoints() > quad->side[3]->NbPoints());
-  quad->isEdgeOut[2] = (quad->side[2]->NbPoints() > quad->side[0]->NbPoints());
-  quad->isEdgeOut[3] = (quad->side[3]->NbPoints() > quad->side[1]->NbPoints());
-
-  UVPtStruct *uv_grid = quad->uv_grid = new UVPtStruct[nbvertic * nbhoriz];
+  int nbhoriz  = Min(quad->side[0].NbPoints(), quad->side[2].NbPoints());
+  int nbvertic = Min(quad->side[1].NbPoints(), quad->side[3].NbPoints());
 
-  const vector<UVPtStruct>& uv_e0 = getUVPtStructIn(quad, 0, nbhoriz - 1);
-  const vector<UVPtStruct>& uv_e1 = getUVPtStructIn(quad, 1, nbvertic - 1);
-  const vector<UVPtStruct>& uv_e2 = getUVPtStructIn(quad, 2, nbhoriz - 1);
-  const vector<UVPtStruct>& uv_e3 = getUVPtStructIn(quad, 3, nbvertic - 1);
+  if ( myQuadList.size() == 1 )
+  {
+    // all sub-quads must have NO sides with nbNodeOut > 0
+    quad->nbNodeOut(0) = Max( 0, quad->side[0].grid->NbPoints() - quad->side[2].grid->NbPoints());
+    quad->nbNodeOut(1) = Max( 0, quad->side[1].grid->NbPoints() - quad->side[3].grid->NbPoints());
+    quad->nbNodeOut(2) = Max( 0, quad->side[2].grid->NbPoints() - quad->side[0].grid->NbPoints());
+    quad->nbNodeOut(3) = Max( 0, quad->side[3].grid->NbPoints() - quad->side[1].grid->NbPoints());
+  }
+  int from[4] = {
+    quad->side[0].from,
+    quad->side[1].from,
+    quad->side[2].from,
+    quad->side[3].from
+  };
+  const vector<UVPtStruct>& uv_e0_vec = quad->side[ 0 ].GetUVPtStruct();
+  const vector<UVPtStruct>& uv_e1_vec = quad->side[ 1 ].GetUVPtStruct();
+  const vector<UVPtStruct>& uv_e2_vec = quad->side[ 2 ].GetUVPtStruct();
+  const vector<UVPtStruct>& uv_e3_vec = quad->side[ 3 ].GetUVPtStruct();
 
-  if (uv_e0.empty() || uv_e1.empty() || uv_e2.empty() || uv_e3.empty())
+  if (uv_e0_vec.empty() || uv_e1_vec.empty() || uv_e2_vec.empty() || uv_e3_vec.empty())
     //return error("Can't find nodes on sides");
     return error(COMPERR_BAD_INPUT_MESH);
 
+  UVPtStruct* uv_e0 = (UVPtStruct*) & uv_e0_vec[0] + from[0];
+  UVPtStruct* uv_e1 = (UVPtStruct*) & uv_e1_vec[0] + from[1];
+  UVPtStruct* uv_e2 = (UVPtStruct*) & uv_e2_vec[0] + from[2];
+  UVPtStruct* uv_e3 = (UVPtStruct*) & uv_e3_vec[0] + from[3];
+
+  quad->uv_grid.resize( nbvertic * nbhoriz );
+  quad->iSize = nbhoriz;
+  quad->jSize = nbvertic;
+  UVPtStruct *uv_grid = & quad->uv_grid[0];
+
+  quad->uv_box.Clear();
+
   // copy data of face boundary
-  {
+
+  { // BOTTOM
     const int j = 0;
-    for (int i = 0; i < nbhoriz; i++)       // down
+    const double x0 = uv_e0[ 0 ].normParam;
+    const double dx = uv_e0[ nbhoriz-1 ].normParam - uv_e0[ 0 ].normParam;
+    for (int i = 0; i < nbhoriz; i++) {      // down
+      uv_e0[i].x = ( uv_e0[i].normParam - x0 ) / dx;
+      uv_e0[i].y = 0.;
       uv_grid[ j * nbhoriz + i ] = uv_e0[i];
+      quad->uv_box.Add( uv_e0[i].UV() );
+    }
   }
-  {
+  { // RIGHT
     const int i = nbhoriz - 1;
-    for (int j = 0; j < nbvertic; j++)      // right
+    const double y0 = uv_e1[ 0 ].normParam;
+    const double dy = uv_e1[ nbvertic-1 ].normParam - uv_e1[ 0 ].normParam;
+    int j = 0, nb = nbvertic;
+    if ( quad->UVPt( i, j ).node ) ++j; // avoid copying from a split emulated side
+    for ( ; j < nb; j++) {      // right
+      uv_e1[j].x = 1.;
+      uv_e1[j].y = ( uv_e1[j].normParam - y0 ) / dy;
       uv_grid[ j * nbhoriz + i ] = uv_e1[j];
+      quad->uv_box.Add( uv_e1[j].UV() );
+    }
   }
-  {
+  { // TOP
     const int j = nbvertic - 1;
-    for (int i = 0; i < nbhoriz; i++)       // up
+    const double x0 = uv_e2[ 0 ].normParam;
+    const double dx = uv_e2[ nbhoriz-1 ].normParam - uv_e2[ 0 ].normParam;
+    int i = 0, nb = nbhoriz;
+    if ( quad->UVPt( nb-1, j ).node ) --nb; // avoid copying from a split emulated side
+    for (; i < nb; i++) {      // up
+      uv_e2[i].x = ( uv_e2[i].normParam - x0 ) / dx;
+      uv_e2[i].y = 1.;
       uv_grid[ j * nbhoriz + i ] = uv_e2[i];
+      quad->uv_box.Add( uv_e2[i].UV() );
+    }
   }
-  {
+  { // LEFT
     const int i = 0;
-    for (int j = 0; j < nbvertic; j++)      // left
+    const double y0 = uv_e3[ 0 ].normParam;
+    const double dy = uv_e3[ nbvertic-1 ].normParam - uv_e3[ 0 ].normParam;
+    int j = 0, nb = nbvertic;
+    if ( quad->UVPt( i, j    ).node ) ++j; // avoid copying from a split emulated side
+    if ( quad->UVPt( i, nb-1 ).node ) --nb;
+    for ( ; j < nb; j++) {     // left
+      uv_e3[j].x = 0.;
+      uv_e3[j].y = ( uv_e3[j].normParam - y0 ) / dy;
       uv_grid[ j * nbhoriz + i ] = uv_e3[j];
+      quad->uv_box.Add( uv_e3[j].UV() );
+    }
   }
 
   // normalized 2d parameters on grid
 
-  for (int i = 0; i < nbhoriz; i++) {
-    for (int j = 0; j < nbvertic; j++) {
-      int ij = j * nbhoriz + i;
-      // --- droite i cste : x = x0 + y(x1-x0)
-      double x0 = uv_e0[i].normParam;   // bas  - sud
-      double x1 = uv_e2[i].normParam;   // haut - nord
-      // --- droite j cste : y = y0 + x(y1-y0)
-      double y0 = uv_e3[j].normParam;   // gauche - ouest
-      double y1 = uv_e1[j].normParam;   // droite - est
+  for (int i = 1; i < nbhoriz-1; i++)
+  {
+    const double x0 = uv_e0[i].x;
+    const double x1 = uv_e2[i].x;
+    for (int j = 1; j < nbvertic-1; j++)
+    {
+      const double y0 = uv_e3[j].y;
+      const double y1 = uv_e1[j].y;
       // --- intersection : x=x0+(y0+x(y1-y0))(x1-x0)
       double x = (x0 + y0 * (x1 - x0)) / (1 - (y1 - y0) * (x1 - x0));
       double y = y0 + x * (y1 - y0);
+      int   ij = j * nbhoriz + i;
       uv_grid[ij].x = x;
       uv_grid[ij].y = y;
+      uv_grid[ij].node = NULL;
     }
   }
 
   // projection on 2d domain (u,v)
 
-  gp_UV a0 (uv_e0.front().u, uv_e0.front().v);
-  gp_UV a1 (uv_e0.back().u,  uv_e0.back().v );
-  gp_UV a2 (uv_e2.back().u,  uv_e2.back().v );
-  gp_UV a3 (uv_e2.front().u, uv_e2.front().v);
+  gp_UV a0 = uv_e0[0        ].UV();
+  gp_UV a1 = uv_e0[nbhoriz-1].UV();
+  gp_UV a2 = uv_e2[nbhoriz-1].UV();
+  gp_UV a3 = uv_e2[0        ].UV();
 
-  for (int i = 0; i < nbhoriz; i++)
+  for (int i = 1; i < nbhoriz-1; i++)
   {
-    gp_UV p0( uv_e0[i].u, uv_e0[i].v );
-    gp_UV p2( uv_e2[i].u, uv_e2[i].v );
-    for (int j = 0; j < nbvertic; j++)
+    gp_UV p0 = uv_e0[i].UV();
+    gp_UV p2 = uv_e2[i].UV();
+    for (int j = 1; j < nbvertic-1; j++)
     {
-      gp_UV p1( uv_e1[j].u, uv_e1[j].v );
-      gp_UV p3( uv_e3[j].u, uv_e3[j].v );
+      gp_UV p1 = uv_e1[j].UV();
+      gp_UV p3 = uv_e3[j].UV();
 
       int ij = j * nbhoriz + i;
       double x = uv_grid[ij].x;
@@ -1343,7 +1467,7 @@ static void shiftQuad(FaceQuadStruct::Ptr& quad, const int num)
 void FaceQuadStruct::shift( size_t nb, bool ori )
 {
   if ( nb == 0 ) return;
-  StdMeshers_FaceSide* sideArr[4] = { side[0], side[1], side[2], side[3] };
+  StdMeshers_FaceSidePtr sideArr[4] = { side[0], side[1], side[2], side[3] };
   for (int i = QUAD_BOTTOM_SIDE; i < NB_QUAD_SIDES; ++i) {
     int id = (i + nb) % NB_QUAD_SIDES;
     bool wasForward = (i  < QUAD_TOP_SIDE);
@@ -1367,10 +1491,10 @@ static gp_UV calcUV(double x0, double x1, double y0, double y1,
   double x = (x0 + y0 * (x1 - x0)) / (1 - (y1 - y0) * (x1 - x0));
   double y = y0 + x * (y1 - y0);
 
-  gp_UV p0 = quad->side[QUAD_BOTTOM_SIDE]->Value2d(x).XY();
-  gp_UV p1 = quad->side[QUAD_RIGHT_SIDE ]->Value2d(y).XY();
-  gp_UV p2 = quad->side[QUAD_TOP_SIDE   ]->Value2d(x).XY();
-  gp_UV p3 = quad->side[QUAD_LEFT_SIDE  ]->Value2d(y).XY();
+  gp_UV p0 = quad->side[QUAD_BOTTOM_SIDE].grid->Value2d(x).XY();
+  gp_UV p1 = quad->side[QUAD_RIGHT_SIDE ].grid->Value2d(y).XY();
+  gp_UV p2 = quad->side[QUAD_TOP_SIDE   ].grid->Value2d(x).XY();
+  gp_UV p3 = quad->side[QUAD_LEFT_SIDE  ].grid->Value2d(y).XY();
 
   gp_UV uv = calcUV(x,y, a0,a1,a2,a3, p0,p1,p2,p3);
 
@@ -1387,10 +1511,10 @@ static gp_UV calcUV2(double x, double y,
                      const gp_UV& a0, const gp_UV& a1,
                      const gp_UV& a2, const gp_UV& a3)
 {
-  gp_UV p0 = quad->side[QUAD_BOTTOM_SIDE]->Value2d(x).XY();
-  gp_UV p1 = quad->side[QUAD_RIGHT_SIDE ]->Value2d(y).XY();
-  gp_UV p2 = quad->side[QUAD_TOP_SIDE   ]->Value2d(x).XY();
-  gp_UV p3 = quad->side[QUAD_LEFT_SIDE  ]->Value2d(y).XY();
+  gp_UV p0 = quad->side[QUAD_BOTTOM_SIDE].grid->Value2d(x).XY();
+  gp_UV p1 = quad->side[QUAD_RIGHT_SIDE ].grid->Value2d(y).XY();
+  gp_UV p2 = quad->side[QUAD_TOP_SIDE   ].grid->Value2d(x).XY();
+  gp_UV p3 = quad->side[QUAD_LEFT_SIDE  ].grid->Value2d(y).XY();
 
   gp_UV uv = calcUV(x,y, a0,a1,a2,a3, p0,p1,p2,p3);
 
@@ -1418,24 +1542,37 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
   bool WisF = true;
   int i,j,geomFaceID = meshDS->ShapeToIndex(aFace);
 
-  int nb = quad->side[0]->NbPoints();
-  int nr = quad->side[1]->NbPoints();
-  int nt = quad->side[2]->NbPoints();
-  int nl = quad->side[3]->NbPoints();
+  int nb = quad->side[0].grid->NbPoints();
+  int nr = quad->side[1].grid->NbPoints();
+  int nt = quad->side[2].grid->NbPoints();
+  int nl = quad->side[3].grid->NbPoints();
   int dh = abs(nb-nt);
   int dv = abs(nr-nl);
 
-  // rotate sides to be as in the picture below and to have
-  // dh >= dv and nt > nb
-  if ( dh >= dv )
-    shiftQuad( quad, ( nt > nb ) ? 0 : 2 );
+  if ( myForcedPnts.empty() )
+  {
+    // rotate sides to be as in the picture below and to have
+    // dh >= dv and nt > nb
+    if ( dh >= dv )
+      shiftQuad( quad, ( nt > nb ) ? 0 : 2 );
+    else
+      shiftQuad( quad, ( nr > nl ) ? 1 : 3 );
+  }
   else
-    shiftQuad( quad, ( nr > nl ) ? 1 : 3 );
+  {
+    // rotate the quad to have nt > nb [and nr > nl]
+    if ( nb > nt )
+      quad->shift( nr > nl ? 1 : 2, true );
+    else if ( nr > nl )
+      quad->shift( nb == nt ? 1 : 0, true );
+    else if ( nl > nr )
+      quad->shift( 3, true );
+  }
 
-  nb = quad->side[0]->NbPoints();
-  nr = quad->side[1]->NbPoints();
-  nt = quad->side[2]->NbPoints();
-  nl = quad->side[3]->NbPoints();
+  nb = quad->side[0].grid->NbPoints();
+  nr = quad->side[1].grid->NbPoints();
+  nt = quad->side[2].grid->NbPoints();
+  nl = quad->side[3].grid->NbPoints();
   dh = abs(nb-nt);
   dv = abs(nr-nl);
   int nbh  = Max(nb,nt);
@@ -1470,6 +1607,302 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
   //      0------------0
   //       0  bottom  1
 
+  const vector<UVPtStruct>& uv_eb = quad->side[0].GetUVPtStruct(true,0);
+  const vector<UVPtStruct>& uv_er = quad->side[1].GetUVPtStruct(false,1);
+  const vector<UVPtStruct>& uv_et = quad->side[2].GetUVPtStruct(true,1);
+  const vector<UVPtStruct>& uv_el = quad->side[3].GetUVPtStruct(false,0);
+
+  if (uv_eb.size() != nb || uv_er.size() != nr || uv_et.size() != nt || uv_el.size() != nl)
+    return error(COMPERR_BAD_INPUT_MESH);
+
+  gp_UV a0,a1,a2,a3, p0,p1,p2,p3, uv;
+  double x,y;
+
+  a0 = uv_eb[ 0 ].UV();
+  a1 = uv_er[ 0 ].UV();
+  a2 = uv_er[ nr-1 ].UV();
+  a3 = uv_et[ 0 ].UV();
+
+  if ( !myForcedPnts.empty() )
+  {
+    if ( dv != 0 && dh != 0 )
+    {
+      const int dmin = Min( dv, dh );
+
+      // Make a side separating domains L and Cb
+      StdMeshers_FaceSidePtr sideLCb;
+      UVPtStruct p3dom; // a point where 3 domains meat
+      {                                                     //   dmin
+        vector<UVPtStruct> pointsLCb( dmin+1 );             // 1--------1
+        pointsLCb[0] = uv_eb[0];                            //  |   |  |
+        for ( int i = 1; i <= dmin; ++i )                   //  |   |Ct|
+        {                                                   //  | L |  |
+          x  = uv_et[ i ].normParam;                        //  |   |__|
+          y  = uv_er[ i ].normParam;                        //  |  /   |
+          p0 = quad->side[0].grid->Value2d( x ).XY();       //  | / Cb |dmin
+          p1 = uv_er[ i ].UV();                             //  |/     |
+          p2 = uv_et[ i ].UV();                             // 0--------0
+          p3 = quad->side[3].grid->Value2d( y ).XY();
+          uv = calcUV( x,y, a0,a1,a2,a3, p0,p1,p2,p3 );
+          pointsLCb[ i ].u = uv.X();
+          pointsLCb[ i ].v = uv.Y();
+        }
+        sideLCb = StdMeshers_FaceSide::New( pointsLCb, aFace );
+        p3dom   = pointsLCb.back();
+      }
+      // Make a side separating domains L and Ct
+      StdMeshers_FaceSidePtr sideLCt;
+      {
+        vector<UVPtStruct> pointsLCt( nl );
+        pointsLCt[0]     = p3dom;
+        pointsLCt.back() = uv_et[ dmin ];
+        x  = uv_et[ dmin ].normParam;
+        p0 = quad->side[0].grid->Value2d( x ).XY();
+        p2 = uv_et[ dmin ].UV();
+        for ( int i = 1; i < nl; ++i )
+        {
+          y  = uv_er[ i + dmin ].normParam;
+          p1 = uv_er[ i + dmin ].UV();
+          p3 = quad->side[3].grid->Value2d( y ).XY();
+          uv = calcUV( x,y, a0,a1,a2,a3, p0,p1,p2,p3 );
+          pointsLCt[ i ].u = uv.X();
+          pointsLCt[ i ].v = uv.Y();
+        }
+        sideLCt = StdMeshers_FaceSide::New( pointsLCt, aFace );
+      }
+      // Make a side separating domains Cb and Ct
+      StdMeshers_FaceSidePtr sideCbCt;
+      {
+        vector<UVPtStruct> pointsCbCt( nb );
+        pointsCbCt[0]     = p3dom;
+        pointsCbCt.back() = uv_er[ dmin ];
+        y  = uv_er[ dmin ].normParam;
+        p1 = uv_er[ dmin ].UV();
+        p3 = quad->side[3].grid->Value2d( y ).XY();
+        for ( int i = 1; i < nb-1; ++i )
+        {
+          x  = uv_et[ i + dmin ].normParam;
+          p2 = uv_et[ i + dmin ].UV();
+          p0 = quad->side[0].grid->Value2d( x ).XY();
+          uv = calcUV( x,y, a0,a1,a2,a3, p0,p1,p2,p3 );
+          pointsCbCt[ i ].u = uv.X();
+          pointsCbCt[ i ].v = uv.Y();
+        }
+        sideCbCt = StdMeshers_FaceSide::New( pointsCbCt, aFace );
+      }
+      // Make Cb quad
+      FaceQuadStruct* qCb = new FaceQuadStruct( quad->face );
+      myQuadList.push_back( FaceQuadStruct::Ptr( qCb ));
+      qCb->side.resize(4);
+      qCb->side[0] = quad->side[0];
+      qCb->side[1] = quad->side[1];
+      qCb->side[2] = sideCbCt;
+      qCb->side[3] = sideLCb;
+      qCb->side[1].to = dmin+1;
+      // Make L quad
+      FaceQuadStruct* qL = new FaceQuadStruct( quad->face );
+      myQuadList.push_back( FaceQuadStruct::Ptr( qL ));
+      qL->side.resize(4);
+      qL->side[0] = sideLCb;
+      qL->side[1] = sideLCt;
+      qL->side[2] = quad->side[2];
+      qL->side[3] = quad->side[3];
+      qL->side[2].to = dmin+1;
+      // Make Ct from the main quad
+      FaceQuadStruct::Ptr qCt = quad;
+      qCt->side[0] = sideCbCt;
+      qCt->side[3] = sideLCt;
+      qCt->side[1].from = dmin;
+      qCt->side[2].from = dmin;
+      qCt->uv_grid.clear();
+
+      // Connect sides
+      qCb->side[3].AddContact( dmin, & qCb->side[2], 0 );
+      qCb->side[3].AddContact( dmin, & qCt->side[3], 0 );
+      qCt->side[3].AddContact(    0, & qCt->side[0], 0 );
+      qCt->side[0].AddContact(    0, & qL ->side[0], dmin );
+      qL ->side[0].AddContact( dmin, & qL ->side[1], 0 );
+      qL ->side[0].AddContact( dmin, & qCb->side[2], 0 );
+
+      if ( dh == dv )
+        return computeQuadDominant( aMesh, aFace );
+      else
+        return computeQuadPref( aMesh, aFace, qCt );
+
+    } // if ( dv != 0 && dh != 0 )
+
+    // Case dv == 0
+    //
+    //     lw   nb  lw = dh/2
+    //    +------------+
+    //    |   |    |   |
+    //    |   | Ct |   |
+    //    | L |    | R |
+    //    |   |____|   |
+    //    |  /      \  |
+    //    | /   Cb   \ |
+    //    |/          \|
+    //    +------------+
+    const int lw = dh/2; // lateral width
+    const int bfrom = quad->side[0].from;
+    const int rfrom = quad->side[1].from;
+    const int tfrom = quad->side[2].from;
+    const int lfrom = quad->side[3].from;
+
+    const double   lL = quad->side[3].Length();
+    const double lLwL = quad->side[2].Length( tfrom, tfrom + lw + 1 );
+    const double yCbL = lLwL / ( lLwL + lL );
+
+    const double   lR = quad->side[1].Length();
+    const double lLwR = quad->side[2].Length( nt - lw - 1, nt );
+    const double yCbR = lLwR / ( lLwR + lR );
+
+    // Make sides separating domains Cb and L and R
+    StdMeshers_FaceSidePtr sideLCb, sideRCb;
+    UVPtStruct pTBL, pTBR; // points where 3 domains meat
+    {
+      vector<UVPtStruct> pointsLCb( lw+1 ), pointsRCb( lw+1 );
+      pointsLCb[0] = uv_eb[ 0  + bfrom ];
+      pointsRCb[0] = uv_eb[ nb + bfrom ];
+      for ( int i = 1, i2 = nt-2; i <= lw; ++i, --i2 )
+      {
+        x  = quad->side[2].Param( i );
+        y  = yCbL * i / lw;
+        p0 = quad->side[0].Value2d( x );
+        p1 = quad->side[1].Value2d( y );
+        p2 = uv_et[ i + tfrom ].UV();
+        p3 = quad->side[3].Value2d( y );
+        uv = calcUV( x,y, a0,a1,a2,a3, p0,p1,p2,p3 );
+        pointsLCb[ i ].u = uv.X();
+        pointsLCb[ i ].v = uv.Y();
+        pointsLCb[ i ].x = x;
+
+        x  = quad->side[2].Param( i2 );
+        y  = yCbR * i / lw;
+        p0 = quad->side[0].Value2d( x );
+        p2 = uv_et[ i2 + tfrom ].UV();
+        uv = calcUV( x,y, a0,a1,a2,a3, p0,p1,p2,p3 );
+        pointsRCb[ i ].u = uv.X();
+        pointsRCb[ i ].v = uv.Y();
+        pointsRCb[ i ].x = x;
+      }
+      sideLCb = StdMeshers_FaceSide::New( pointsLCb, aFace );
+      sideRCb = StdMeshers_FaceSide::New( pointsRCb, aFace );
+      pTBL    = pointsLCb.back();
+      pTBR    = pointsRCb.back();
+    }
+    // Make sides separating domains Ct and L and R
+    StdMeshers_FaceSidePtr sideLCt, sideRCt;
+    {
+      vector<UVPtStruct> pointsLCt( nl ), pointsRCt( nl );
+      pointsLCt[0]     = pTBL;
+      pointsLCt.back() = uv_et[ lw + tfrom ];
+      pointsRCt[0]     = pTBR;
+      pointsRCt.back() = uv_et[ lw + nb - 1 + tfrom ];
+      x  = pTBL.x;
+      p0 = quad->side[0].Value2d( x );
+      p2 = uv_et[ lw + tfrom ].UV();
+      int     iR = lw + nb - 1;
+      double  xR = pTBR.x;
+      gp_UV  p0R = quad->side[0].Value2d( xR );
+      gp_UV  p2R = uv_et[ iR + tfrom ].UV();
+      for ( int i = 1; i < nl; ++i )
+      {
+        y  = yCbL + ( 1. - yCbL ) * i / nl;
+        p1 = quad->side[1].Value2d( y );
+        p3 = quad->side[3].Value2d( y );
+        uv = calcUV( x,y, a0,a1,a2,a3, p0,p1,p2,p3 );
+        pointsLCt[ i ].u = uv.X();
+        pointsLCt[ i ].v = uv.Y();
+
+        y  = yCbR + ( 1. - yCbR ) * i / nl;
+        p1 = quad->side[1].Value2d( y );
+        p3 = quad->side[3].Value2d( y );
+        uv = calcUV( xR,y, a0,a1,a2,a3, p0,p1,p2,p3 );
+        pointsRCt[ i ].u = uv.X();
+        pointsRCt[ i ].v = uv.Y();
+      }
+      sideLCt = StdMeshers_FaceSide::New( pointsLCt, aFace );
+      sideRCt = StdMeshers_FaceSide::New( pointsRCt, aFace );
+    }
+    // Make a side separating domains Cb and Ct
+    StdMeshers_FaceSidePtr sideCbCt;
+    {
+      vector<UVPtStruct> pointsCbCt( nb );
+      pointsCbCt[0]     = pTBL;
+      pointsCbCt.back() = pTBR;
+      p1 = quad->side[1].Value2d( yCbR );
+      p3 = quad->side[3].Value2d( yCbL );
+      for ( int i = 1; i < nb-1; ++i )
+      {
+        x  = quad->side[2].Param( i + lw );
+        y  = yCbL + ( yCbR - yCbL ) * i / nb;
+        p2 = uv_et[ i + lw + tfrom ].UV();
+        p0 = quad->side[0].Value2d( x );
+        uv = calcUV( x,y, a0,a1,a2,a3, p0,p1,p2,p3 );
+        pointsCbCt[ i ].u = uv.X();
+        pointsCbCt[ i ].v = uv.Y();
+      }
+      sideCbCt = StdMeshers_FaceSide::New( pointsCbCt, aFace );
+    }
+    // Make Cb quad
+    FaceQuadStruct* qCb = new FaceQuadStruct( quad->face );
+    myQuadList.push_back( FaceQuadStruct::Ptr( qCb ));
+    qCb->side.resize(4);
+    qCb->side[0] = quad->side[0];
+    qCb->side[1] = sideRCb;
+    qCb->side[2] = sideCbCt;
+    qCb->side[3] = sideLCb;
+    // Make L quad
+    FaceQuadStruct* qL = new FaceQuadStruct( quad->face );
+    myQuadList.push_back( FaceQuadStruct::Ptr( qL ));
+    qL->side.resize(4);
+    qL->side[0] = sideLCb;
+    qL->side[1] = sideLCt;
+    qL->side[2] = quad->side[2];
+    qL->side[3] = quad->side[3];
+    qL->side[2].to = lw+1;
+    // Make R quad
+    FaceQuadStruct* qR = new FaceQuadStruct( quad->face );
+    myQuadList.push_back( FaceQuadStruct::Ptr( qR ));
+    qR->side.resize(4);
+    qR->side[0] = sideRCb;
+    qR->side[0].from = lw;
+    qR->side[0].to   = -1;
+    qR->side[1] = quad->side[1];
+    qR->side[2] = quad->side[2];
+    qR->side[2].from = nb + lw + tfrom;
+    qR->side[3] = sideRCt;
+    // Make Ct from the main quad
+    FaceQuadStruct::Ptr qCt = quad;
+    qCt->side[0] = sideCbCt;
+    qCt->side[1] = sideRCt;
+    qCt->side[2].from = lw + tfrom;
+    qCt->side[2].to   = nt - lw + tfrom;
+    qCt->side[3] = sideLCt;
+    qCt->uv_grid.clear();
+
+    // Connect sides
+    qCb->side[3].AddContact( lw, & qCb->side[2], 0 );
+    qCb->side[3].AddContact( lw, & qCt->side[3], 0 );
+    qCt->side[3].AddContact(  0, & qCt->side[0], 0 );
+    qCt->side[0].AddContact(  0, & qL ->side[0], lw );
+    qL ->side[0].AddContact( lw, & qL ->side[1], 0 );
+    qL ->side[0].AddContact( lw, & qCb->side[2], 0 );
+    //
+    qCb->side[1].AddContact( lw, & qCb->side[2], lw );
+    qCb->side[1].AddContact( lw, & qCt->side[1], 0 );
+    qCt->side[0].AddContact( lw, & qCt->side[1], 0 );
+    qCt->side[0].AddContact( lw, & qR ->side[0], lw );
+    qR ->side[3].AddContact( lw, & qR ->side[0], lw );
+    qR ->side[3].AddContact( lw, & qCb->side[2], lw );
+
+    if ( dh == dv )
+      return computeQuadDominant( aMesh, aFace );
+
+
+  }
+
   if ( dh > dv ) {
     addv = (dh-dv)/2;
     nbv  = nbv + addv;
@@ -1479,19 +1912,6 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
     nbh  = nbh + addh;
   }
 
-  const vector<UVPtStruct>& uv_eb = quad->side[0]->GetUVPtStruct(true,0);
-  const vector<UVPtStruct>& uv_er = quad->side[1]->GetUVPtStruct(false,1);
-  const vector<UVPtStruct>& uv_et = quad->side[2]->GetUVPtStruct(true,1);
-  const vector<UVPtStruct>& uv_el = quad->side[3]->GetUVPtStruct(false,0);
-
-  if (uv_eb.size() != nb || uv_er.size() != nr || uv_et.size() != nt || uv_el.size() != nl)
-    return error(COMPERR_BAD_INPUT_MESH);
-
-  if ( !OldVersion )
-  {
-    // dh/2, Min(nb,nt), dh - dh/2, dv
-  }
-
   // arrays for normalized params
   TColStd_SequenceOfReal npb, npr, npt, npl;
   for (i=0; i<nb; i++) {
@@ -1523,11 +1943,6 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
       npl.InsertAfter(1,npl.Value(2)-dpr);
     }
   }
-  
-  gp_XY a0(uv_eb.front().u, uv_eb.front().v);
-  gp_XY a1(uv_eb.back().u,  uv_eb.back().v);
-  gp_XY a2(uv_et.back().u,  uv_et.back().v);
-  gp_XY a3(uv_et.front().u, uv_et.front().v);
 
   int nnn = Min(nr,nl);
   // auxilary sequence of XY for creation nodes
@@ -1543,7 +1958,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
       NodesL.SetValue(1,j,uv_el[j-1].node);
     if (dl>0) {
       // add top nodes
-      for (i=1; i<=dl; i++) 
+      for (i=1; i<=dl; i++)
         NodesL.SetValue(i+1,nl,uv_et[i].node);
       // create and add needed nodes
       TColgp_SequenceOfXY UVtmp;
@@ -1580,13 +1995,13 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
           if (WisF) {
             SMDS_MeshFace* F =
               myHelper->AddFace(NodesL.Value(i,j), NodesL.Value(i+1,j),
-                              NodesL.Value(i+1,j+1), NodesL.Value(i,j+1));
+                                NodesL.Value(i+1,j+1), NodesL.Value(i,j+1));
             if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
           }
           else {
             SMDS_MeshFace* F =
               myHelper->AddFace(NodesL.Value(i,j), NodesL.Value(i,j+1),
-                              NodesL.Value(i+1,j+1), NodesL.Value(i+1,j));
+                                NodesL.Value(i+1,j+1), NodesL.Value(i+1,j));
             if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
           }
         }
@@ -1598,15 +2013,15 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
         UVL.Append(gp_UV (uv_el[i].u, uv_el[i].v));
       }
     }
-    
+
     // step2: create faces for right domain
     StdMeshers_Array2OfNode NodesR(1,dr+1,1,nr);
     // add right nodes
-    for (j=1; j<=nr; j++) 
+    for (j=1; j<=nr; j++)
       NodesR.SetValue(1,j,uv_er[nr-j].node);
     if (dr>0) {
       // add top nodes
-      for (i=1; i<=dr; i++) 
+      for (i=1; i<=dr; i++)
         NodesR.SetValue(i+1,1,uv_et[nt-1-i].node);
       // create and add needed nodes
       TColgp_SequenceOfXY UVtmp;
@@ -1643,13 +2058,13 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
           if (WisF) {
             SMDS_MeshFace* F =
               myHelper->AddFace(NodesR.Value(i,j), NodesR.Value(i+1,j),
-                              NodesR.Value(i+1,j+1), NodesR.Value(i,j+1));
+                                NodesR.Value(i+1,j+1), NodesR.Value(i,j+1));
             if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
           }
           else {
             SMDS_MeshFace* F =
               myHelper->AddFace(NodesR.Value(i,j), NodesR.Value(i,j+1),
-                              NodesR.Value(i+1,j+1), NodesR.Value(i+1,j));
+                                NodesR.Value(i+1,j+1), NodesR.Value(i+1,j));
             if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
           }
         }
@@ -1661,7 +2076,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
         UVR.Append(gp_UV(uv_er[i].u, uv_er[i].v));
       }
     }
-    
+
     // step3: create faces for central domain
     StdMeshers_Array2OfNode NodesC(1,nb,1,nbv);
     // add first line using NodesL
@@ -1675,12 +2090,12 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
     for (i=1; i<nr; i++)
       NodesC.SetValue(nb,dr+i+1,NodesR(dr+1,nr-i));
     // add top nodes (last columns)
-    for (i=dl+2; i<nbh-dr; i++) 
+    for (i=dl+2; i<nbh-dr; i++)
       NodesC.SetValue(i-dl,nbv,uv_et[i-1].node);
     // add bottom nodes (first columns)
     for (i=2; i<nb; i++)
       NodesC.SetValue(i,1,uv_eb[i-1].node);
-    
+
     // create and add needed nodes
     // add linear layers
     for (i=2; i<nb; i++) {
@@ -1722,13 +2137,13 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
         if (WisF) {
           SMDS_MeshFace* F =
             myHelper->AddFace(NodesC.Value(i,j), NodesC.Value(i+1,j),
-                            NodesC.Value(i+1,j+1), NodesC.Value(i,j+1));
+                              NodesC.Value(i+1,j+1), NodesC.Value(i,j+1));
           if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
         }
         else {
           SMDS_MeshFace* F =
             myHelper->AddFace(NodesC.Value(i,j), NodesC.Value(i,j+1),
-                            NodesC.Value(i+1,j+1), NodesC.Value(i+1,j));
+                              NodesC.Value(i+1,j+1), NodesC.Value(i+1,j));
           if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
         }
       }
@@ -1760,13 +2175,13 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
         if (WisF) {
           SMDS_MeshFace* F =
             myHelper->AddFace(NodesBRD.Value(i,j), NodesBRD.Value(i+1,j),
-                            NodesBRD.Value(i+1,j+1), NodesBRD.Value(i,j+1));
+                              NodesBRD.Value(i+1,j+1), NodesBRD.Value(i,j+1));
           if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
         }
         else {
           SMDS_MeshFace* F =
             myHelper->AddFace(NodesBRD.Value(i,j), NodesBRD.Value(i,j+1),
-                            NodesBRD.Value(i+1,j+1), NodesBRD.Value(i+1,j));
+                              NodesBRD.Value(i+1,j+1), NodesBRD.Value(i+1,j));
           if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
         }
       }
@@ -1812,7 +2227,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
           double yy1 = y1 + dy1*i;
           double dyy = yy1 - yy0;
           for (j=1; j<=nb; j++) {
-            double x = npt.Value(i+1+drl) + 
+            double x = npt.Value(i+1+drl) +
               npb.Value(j) * (npt.Value(nt-i) - npt.Value(i+1+drl));
             double y = yy0 + dyy*x;
             gp_UV UV = calcUV2(x, y, quad, a0, a1, a2, a3);
@@ -1855,7 +2270,7 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
           double yy1 = y1 + dy1*i;
           double dyy = yy1 - yy0;
           for (j=1; j<=nb; j++) {
-            double x = npt.Value(i+1) + 
+            double x = npt.Value(i+1) +
               npb.Value(j) * (npt.Value(nt-i-drl) - npt.Value(i+1));
             double y = yy0 + dyy*x;
             gp_UV UV = calcUV2(x, y, quad, a0, a1, a2, a3);
@@ -1872,13 +2287,13 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
           if (WisF) {
             SMDS_MeshFace* F =
               myHelper->AddFace(NodesC.Value(i,j), NodesC.Value(i+1,j),
-                              NodesC.Value(i+1,j+1), NodesC.Value(i,j+1));
+                                NodesC.Value(i+1,j+1), NodesC.Value(i,j+1));
             if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
           }
           else {
             SMDS_MeshFace* F =
               myHelper->AddFace(NodesC.Value(i,j), NodesC.Value(i,j+1),
-                              NodesC.Value(i+1,j+1), NodesC.Value(i+1,j));
+                                NodesC.Value(i+1,j+1), NodesC.Value(i+1,j));
             if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
           }
         }
@@ -1905,13 +2320,13 @@ bool StdMeshers_Quadrangle_2D::computeQuadPref (SMESH_Mesh &        aMesh,
         if (WisF) {
           SMDS_MeshFace* F =
             myHelper->AddFace(NodesLast.Value(i,1), NodesLast.Value(i+1,1),
-                            NodesLast.Value(i+1,2), NodesLast.Value(i,2));
+                              NodesLast.Value(i+1,2), NodesLast.Value(i,2));
           if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
         }
         else {
           SMDS_MeshFace* F =
             myHelper->AddFace(NodesLast.Value(i,1), NodesLast.Value(i,2),
-                            NodesLast.Value(i+1,2), NodesLast.Value(i+1,2));
+                              NodesLast.Value(i+1,2), NodesLast.Value(i+1,2));
           if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
         }
       }
@@ -2064,12 +2479,12 @@ bool StdMeshers_Quadrangle_2D::evaluateQuadPref(SMESH_Mesh &        aMesh,
  */
 //=============================================================================
 
-void StdMeshers_Quadrangle_2D::splitQuad(SMESHDS_Mesh *       theMeshDS,
-                                         int                  theFaceID,
-                                         const SMDS_MeshNode* theNode1,
-                                         const SMDS_MeshNode* theNode2,
-                                         const SMDS_MeshNode* theNode3,
-                                         const SMDS_MeshNode* theNode4)
+void StdMeshers_Quadrangle_2D::splitQuadFace(SMESHDS_Mesh *       theMeshDS,
+                                             int                  theFaceID,
+                                             const SMDS_MeshNode* theNode1,
+                                             const SMDS_MeshNode* theNode2,
+                                             const SMDS_MeshNode* theNode3,
+                                             const SMDS_MeshNode* theNode4)
 {
   SMDS_MeshFace* face;
   if ( SMESH_TNodeXYZ( theNode1 ).SquareDistance( theNode3 ) >
@@ -2100,8 +2515,8 @@ namespace
                                    SMESH_MesherHelper*  helper,
                                    Handle(Geom_Surface) S)
   {
-    const vector<UVPtStruct>& uv_eb = quad->side[QUAD_BOTTOM_SIDE]->GetUVPtStruct();
-    const vector<UVPtStruct>& uv_et = quad->side[QUAD_TOP_SIDE   ]->GetUVPtStruct();
+    const vector<UVPtStruct>& uv_eb = quad->side[QUAD_BOTTOM_SIDE].GetUVPtStruct();
+    const vector<UVPtStruct>& uv_et = quad->side[QUAD_TOP_SIDE   ].GetUVPtStruct();
     double rBot = ( uv_eb.size() - 1 ) * uvPt.normParam;
     double rTop = ( uv_et.size() - 1 ) * uvPt.normParam;
     int iBot = int( rBot );
@@ -2112,9 +2527,9 @@ namespace
     
     gp_UV uv = calcUV(/*x,y=*/x, y,
                       /*a0,...=*/UVs[UV_A0], UVs[UV_A1], UVs[UV_A2], UVs[UV_A3],
-                      /*p0=*/quad->side[QUAD_BOTTOM_SIDE]->Value2d( x ).XY(),
+                      /*p0=*/quad->side[QUAD_BOTTOM_SIDE].grid->Value2d( x ).XY(),
                       /*p1=*/UVs[ UV_R ],
-                      /*p2=*/quad->side[QUAD_TOP_SIDE   ]->Value2d( x ).XY(),
+                      /*p2=*/quad->side[QUAD_TOP_SIDE   ].grid->Value2d( x ).XY(),
                       /*p3=*/UVs[ UV_L ]);
     gp_Pnt P = S->Value( uv.X(), uv.Y() );
     uvPt.u = uv.X();
@@ -2280,10 +2695,10 @@ bool StdMeshers_Quadrangle_2D::computeReduced (SMESH_Mesh &        aMesh,
   Handle(Geom_Surface) S = BRep_Tool::Surface(aFace);
   int i,j,geomFaceID     = meshDS->ShapeToIndex(aFace);
 
-  int nb = quad->side[0]->NbPoints(); // bottom
-  int nr = quad->side[1]->NbPoints(); // right
-  int nt = quad->side[2]->NbPoints(); // top
-  int nl = quad->side[3]->NbPoints(); // left
+  int nb = quad->side[0].grid->NbPoints(); // bottom
+  int nr = quad->side[1].grid->NbPoints(); // right
+  int nt = quad->side[2].grid->NbPoints(); // top
+  int nl = quad->side[3].grid->NbPoints(); // left
 
   //  Simple Reduce 10->8->6->4 (3 steps)     Multiple Reduce 10->4 (1 step)
   //
@@ -2372,10 +2787,10 @@ bool StdMeshers_Quadrangle_2D::computeReduced (SMESH_Mesh &        aMesh,
       }
     }
 
-    nb = quad->side[0]->NbPoints();
-    nr = quad->side[1]->NbPoints();
-    nt = quad->side[2]->NbPoints();
-    nl = quad->side[3]->NbPoints();
+    nb = quad->side[0].grid->NbPoints();
+    nr = quad->side[1].grid->NbPoints();
+    nt = quad->side[2].grid->NbPoints();
+    nl = quad->side[3].grid->NbPoints();
     dh = abs(nb-nt);
     dv = abs(nr-nl);
     int nbh = Max(nb,nt);
@@ -2392,10 +2807,10 @@ bool StdMeshers_Quadrangle_2D::computeReduced (SMESH_Mesh &        aMesh,
       nbh = nbh + addh;
     }
 
-    const vector<UVPtStruct>& uv_eb = quad->side[0]->GetUVPtStruct(true,0);
-    const vector<UVPtStruct>& uv_er = quad->side[1]->GetUVPtStruct(false,1);
-    const vector<UVPtStruct>& uv_et = quad->side[2]->GetUVPtStruct(true,1);
-    const vector<UVPtStruct>& uv_el = quad->side[3]->GetUVPtStruct(false,0);
+    const vector<UVPtStruct>& uv_eb = quad->side[0].GetUVPtStruct(true,0);
+    const vector<UVPtStruct>& uv_er = quad->side[1].GetUVPtStruct(false,1);
+    const vector<UVPtStruct>& uv_et = quad->side[2].GetUVPtStruct(true,1);
+    const vector<UVPtStruct>& uv_el = quad->side[3].GetUVPtStruct(false,0);
 
     if (uv_eb.size() != nb || uv_er.size() != nr || uv_et.size() != nt || uv_el.size() != nl)
       return error(COMPERR_BAD_INPUT_MESH);
@@ -2646,10 +3061,10 @@ bool StdMeshers_Quadrangle_2D::computeReduced (SMESH_Mesh &        aMesh,
       }
     }
 
-    nb = quad->side[0]->NbPoints();
-    nr = quad->side[1]->NbPoints();
-    nt = quad->side[2]->NbPoints();
-    nl = quad->side[3]->NbPoints();
+    nb = quad->side[0].grid->NbPoints();
+    nr = quad->side[1].grid->NbPoints();
+    nt = quad->side[2].grid->NbPoints();
+    nl = quad->side[3].grid->NbPoints();
 
     // number of rows and columns
     int nrows = nr - 1; // and also == nl - 1
@@ -2711,10 +3126,10 @@ bool StdMeshers_Quadrangle_2D::computeReduced (SMESH_Mesh &        aMesh,
       }
     }
 
-    const vector<UVPtStruct>& uv_eb = quad->side[0]->GetUVPtStruct(true,0);
-    const vector<UVPtStruct>& uv_er = quad->side[1]->GetUVPtStruct(false,1);
-    const vector<UVPtStruct>& uv_et = quad->side[2]->GetUVPtStruct(true,1);
-    const vector<UVPtStruct>& uv_el = quad->side[3]->GetUVPtStruct(false,0);
+    const vector<UVPtStruct>& uv_eb = quad->side[0].GetUVPtStruct(true,0);
+    const vector<UVPtStruct>& uv_er = quad->side[1].GetUVPtStruct(false,1);
+    const vector<UVPtStruct>& uv_et = quad->side[2].GetUVPtStruct(true,1);
+    const vector<UVPtStruct>& uv_el = quad->side[3].GetUVPtStruct(false,0);
 
     if (uv_eb.size() != nb || uv_er.size() != nr || uv_et.size() != nt || uv_el.size() != nl)
       return error(COMPERR_BAD_INPUT_MESH);
@@ -3234,8 +3649,7 @@ void StdMeshers_Quadrangle_2D::updateDegenUV(FaceQuadStruct::Ptr quad)
     // --------------------------------------------------------------------------
     for ( unsigned i = 0; i < quad->side.size(); ++i )
     {
-      StdMeshers_FaceSide* side = quad->side[i];
-      const vector<UVPtStruct>& uvVec = side->GetUVPtStruct();
+      const vector<UVPtStruct>& uvVec = quad->side[i].GetUVPtStruct();
 
       // find which end of the side is on degenerated shape
       int degenInd = -1;
@@ -3251,10 +3665,9 @@ void StdMeshers_Quadrangle_2D::updateDegenUV(FaceQuadStruct::Ptr quad)
       if ( i >= QUAD_TOP_SIDE )
         isPrev = !isPrev;
       int i2 = ( isPrev ? ( i + 3 ) : ( i + 1 )) % 4;
-      StdMeshers_FaceSide* side2 = quad->side[ i2 ];
-      const vector<UVPtStruct>& uvVec2 = side2->GetUVPtStruct();
+      const vector<UVPtStruct>& uvVec2 = quad->side[ i2 ].GetUVPtStruct();
       int degenInd2 = -1;
-      if ( uvVec[ degenInd ].node == uvVec2[0].node )
+      if (      uvVec[ degenInd ].node == uvVec2.front().node )
         degenInd2 = 0;
       else if ( uvVec[ degenInd ].node == uvVec2.back().node )
         degenInd2 = uvVec2.size() - 1;
@@ -3274,10 +3687,10 @@ void StdMeshers_Quadrangle_2D::updateDegenUV(FaceQuadStruct::Ptr quad)
     // ----------------------------------------------------------------------------
     for ( unsigned i = 0; i < quad->side.size(); ++i )
     {
-      StdMeshers_FaceSide* degSide = quad->side[i];
+      StdMeshers_FaceSidePtr degSide = quad->side[i];
       if ( !myHelper->IsDegenShape( degSide->EdgeID(0) ))
         continue;
-      StdMeshers_FaceSide* oppSide = quad->side[( i+2 ) % quad->side.size() ];
+      StdMeshers_FaceSidePtr oppSide = quad->side[( i+2 ) % quad->side.size() ];
       if ( degSide->NbSegments() == oppSide->NbSegments() )
         continue;
 
@@ -3286,11 +3699,10 @@ void StdMeshers_Quadrangle_2D::updateDegenUV(FaceQuadStruct::Ptr quad)
       const SMDS_MeshNode*   n = uvVecDegOld[0].node;
       Handle(Geom2d_Curve) c2d = degSide->Curve2d(0);
       double f = degSide->FirstU(0), l = degSide->LastU(0);
-      gp_Pnt2d p1( uvVecDegOld.front().u, uvVecDegOld.front().v );
-      gp_Pnt2d p2( uvVecDegOld.back().u,  uvVecDegOld.back().v );
+      gp_Pnt2d p1 = uvVecDegOld.front().UV();
+      gp_Pnt2d p2 = uvVecDegOld.back().UV();
 
-      delete degSide;
-      quad->side[i] = new StdMeshers_FaceSide( oppSide, n, &p1, &p2, c2d, f, l );
+      quad->side[i] = StdMeshers_FaceSide::New( oppSide.get(), n, &p1, &p2, c2d, f, l );
     }
 }
 
@@ -3344,11 +3756,11 @@ void StdMeshers_Quadrangle_2D::smooth (FaceQuadStruct::Ptr quad)
   // set _uv of smooth nodes on FACE boundary
   for ( unsigned i = 0; i < quad->side.size(); ++i )
   {
-    const vector<UVPtStruct>& uvVec = quad->side[i]->GetUVPtStruct();
+    const vector<UVPtStruct>& uvVec = quad->side[i].GetUVPtStruct();
     for ( unsigned j = 0; j < uvVec.size(); ++j )
     {
       TSmoothNode & sNode = smooNoMap[ uvVec[j].node ];
-      sNode._uv.SetCoord( uvVec[j].u, uvVec[j].v );
+      sNode._uv  = uvVec[j].UV();
       sNode._xyz = SMESH_TNodeXYZ( uvVec[j].node );
     }
   }
@@ -3704,3 +4116,1004 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face&          theFace,
 
   return nbCorners;
 }
+
+//================================================================================
+/*!
+ * \brief Constructor of a side of quad
+ */
+//================================================================================
+
+FaceQuadStruct::Side::Side(StdMeshers_FaceSidePtr theGrid)
+  : grid(theGrid), nbNodeOut(0), from(0), to(theGrid ? theGrid->NbPoints() : 0 )
+{
+}
+
+//=============================================================================
+/*!
+ * \brief Constructor of a quad
+ */
+//=============================================================================
+
+FaceQuadStruct::FaceQuadStruct(const TopoDS_Face& F) : face( F )
+{
+  side.reserve(4);
+}
+
+//================================================================================
+/*!
+ * \brief Fills myForcedPnts
+ */
+//================================================================================
+
+bool StdMeshers_Quadrangle_2D::getEnforcedUV()
+{
+  myForcedPnts.clear();
+  if ( !myParams ) return true; // missing hypothesis
+
+  std::vector< TopoDS_Shape > shapes;
+  std::vector< gp_Pnt >       points;
+  myParams->GetEnforcedNodes( shapes, points );
+
+  TopTools_IndexedMapOfShape vMap;
+  for ( size_t i = 0; i < shapes.size(); ++i )
+    if ( !shapes[i].IsNull() )
+      TopExp::MapShapes( shapes[i], TopAbs_VERTEX, vMap );
+
+  size_t nbPoints = points.size();
+  for ( int i = 1; i <= vMap.Extent(); ++i )
+    points.push_back( BRep_Tool::Pnt( TopoDS::Vertex( vMap( i ))));
+
+  // find out if all points must be in the FACE, which is so if
+  // myParams is a local hypothesis on the FACE being meshed
+  bool isStrictCheck = false;
+  {
+    SMESH_HypoFilter paramFilter( SMESH_HypoFilter::Is( myParams ));
+    TopoDS_Shape assignedTo;
+    if ( myHelper->GetMesh()->GetHypothesis( myHelper->GetSubShape(),
+                                             paramFilter,
+                                             /*ancestors=*/true,
+                                             &assignedTo ))
+      isStrictCheck = ( assignedTo.IsSame( myHelper->GetSubShape() ));
+  }
+
+  multimap< double, ForcedPoint > sortedFP; // sort points by distance from EDGEs
+
+  Standard_Real u1,u2,v1,v2;
+  const TopoDS_Face&   face = TopoDS::Face( myHelper->GetSubShape() );
+  const double          tol = BRep_Tool::Tolerance( face );
+  Handle(Geom_Surface) surf = BRep_Tool::Surface( face );
+  surf->Bounds( u1,u2,v1,v2 );
+  GeomAPI_ProjectPointOnSurf project;
+  project.Init(surf, u1,u2, v1,v2, tol );
+
+  for ( size_t iP = 0; iP < points.size(); ++iP )
+  {
+    project.Perform( points[ iP ]);
+    if ( !project.IsDone() )
+    {
+      if ( isStrictCheck && iP < nbPoints )
+        return error
+          (TComm("Projection of an enforced point to the face failed - (")
+           << points[ iP ].X() << ", "<< points[ iP ].Y() << ", "<< points[ iP ].Z() << " )");
+      continue;
+    }
+    if ( project.LowerDistance() > tol*1000 )
+    {
+      if ( isStrictCheck && iP < nbPoints )
+        return error
+          (COMPERR_BAD_PARMETERS, TComm("An enforced point is too far from the face, dist = ")
+           << project.LowerDistance() << " - ("
+           << points[ iP ].X() << ", "<< points[ iP ].Y() << ", "<< points[ iP ].Z() << " )");
+      continue;
+    }
+    Quantity_Parameter u, v;
+    project.LowerDistanceParameters(u, v);
+    gp_Pnt2d uv( u, v );
+    BRepClass_FaceClassifier clsf ( face, uv, tol );
+    switch ( clsf.State() ) {
+    case TopAbs_IN:
+    {
+      double edgeDist =  ( Min( Abs( u - u1 ), Abs( u - u2 )) +
+                           Min( Abs( v - v1 ), Abs( v - v2 )));
+      ForcedPoint fp;
+      fp.uv  = uv.XY();
+      fp.xyz = points[ iP ].XYZ();
+      if ( iP >= nbPoints )
+        fp.vertex = TopoDS::Vertex( vMap( iP - nbPoints + 1 ));
+
+      sortedFP.insert( make_pair( edgeDist, fp ));
+      break;
+    }
+    case TopAbs_OUT:
+    {
+      if ( isStrictCheck && iP < nbPoints )
+        return error
+          (COMPERR_BAD_PARMETERS, TComm("An enforced point is out of the face boundary - ")
+           << points[ iP ].X() << ", "<< points[ iP ].Y() << ", "<< points[ iP ].Z() << " )");
+      break;
+    }
+    case TopAbs_ON:
+    {
+      if ( isStrictCheck && iP < nbPoints )
+        return error
+          (COMPERR_BAD_PARMETERS, TComm("An enforced point is on the face boundary - ")
+           << points[ iP ].X() << ", "<< points[ iP ].Y() << ", "<< points[ iP ].Z() << " )");
+      break;
+    }
+    default:
+    {
+      if ( isStrictCheck && iP < nbPoints )
+        return error
+          (TComm("Classification of an enforced point ralative to the face boundary failed - ")
+           << points[ iP ].X() << ", "<< points[ iP ].Y() << ", "<< points[ iP ].Z() << " )");
+    }
+    }
+  }
+
+  multimap< double, ForcedPoint >::iterator d2uv = sortedFP.begin();
+  for ( ; d2uv != sortedFP.end(); ++d2uv )
+    myForcedPnts.push_back( (*d2uv).second );
+
+  return true;
+}
+
+//================================================================================
+/*!
+ * \brief Splits quads by adding points of enforced nodes and create nodes on
+ *        the sides shared by quads
+ */
+//================================================================================
+
+bool StdMeshers_Quadrangle_2D::addEnforcedNodes()
+{
+  // if ( myForcedPnts.empty() )
+  //   return true;
+
+  // make a map of quads sharing a side
+  map< StdMeshers_FaceSidePtr, vector< FaceQuadStruct::Ptr > > quadsBySide;
+  list< FaceQuadStruct::Ptr >::iterator quadIt = myQuadList.begin();
+  for ( ; quadIt != myQuadList.end(); ++quadIt )
+    for ( size_t iSide = 0; iSide < (*quadIt)->side.size(); ++iSide )
+      quadsBySide[ (*quadIt)->side[iSide] ].push_back( *quadIt );
+
+  SMESH_Mesh*          mesh = myHelper->GetMesh();
+  SMESHDS_Mesh*      meshDS = myHelper->GetMeshDS();
+  const TopoDS_Face&   face = TopoDS::Face( myHelper->GetSubShape() );
+  Handle(Geom_Surface) surf = BRep_Tool::Surface( face );
+
+  for ( size_t iFP = 0; iFP < myForcedPnts.size(); ++iFP )
+  {
+    bool isNodeEnforced = false;
+
+    // look for a quad enclosing a enforced point
+    for ( quadIt = myQuadList.begin(); quadIt != myQuadList.end(); ++quadIt )
+    {
+      FaceQuadStruct::Ptr quad = *quadIt;
+      int i,j;
+      if ( !setNormalizedGrid( quad ))
+        return false;
+      if ( !quad->findCell( myForcedPnts[ iFP ], i, j ))
+        continue;
+
+      // a grid cell is found, select a node of the cell to move
+      // to the enforced point to and to split the quad at
+      multimap< double, pair< int, int > > ijByDist;
+      for ( int di = 0; di < 2; ++di )
+        for ( int dj = 0; dj < 2; ++dj )
+        {
+          double dist2 = ( myForcedPnts[ iFP ].uv - quad->UVPt( i+di,j+dj ).UV() ).SquareModulus();
+          ijByDist.insert( make_pair( dist2, make_pair( i+di,j+dj )));
+        }
+      // try all nodes starting from the closest one
+      set< FaceQuadStruct::Ptr > changedQuads;
+      multimap< double, pair< int, int > >::iterator d2ij = ijByDist.begin();
+      for ( ; !isNodeEnforced  &&  d2ij != ijByDist.end(); ++d2ij )
+      {
+        i = d2ij->second.first;
+        j = d2ij->second.second;
+
+        // check if a node is at a side
+        int iSide = -1;
+        if ( j == 0 )
+          iSide = QUAD_BOTTOM_SIDE;
+        else if ( j+1 == quad->jSize )
+          iSide = QUAD_TOP_SIDE;
+        else if ( i == 0 )
+          iSide = QUAD_LEFT_SIDE;
+        else if ( i+1 == quad->iSize )
+          iSide = QUAD_RIGHT_SIDE;
+
+        if ( iSide > -1 ) // ----- node is at a side
+        {
+          FaceQuadStruct::Side& side = quad->side[ iSide ];
+          // check if this node can be moved
+          if ( quadsBySide[ side ].size() < 2 )
+            continue; // its a face boundary -> can't move the node
+
+          int quadNodeIndex = ( iSide % 2 ) ? j : i;
+          int sideNodeIndex = side.ToSideIndex( quadNodeIndex );
+          if ( side.IsForced( sideNodeIndex ))
+          {
+            // the node is already moved to another enforced point
+            isNodeEnforced = quad->isEqual( myForcedPnts[ iFP ], i, j );
+            continue;
+          }
+          // make a node of a side forced
+          vector<UVPtStruct>& points = (vector<UVPtStruct>&) side.GetUVPtStruct();
+          points[ sideNodeIndex ].u = myForcedPnts[ iFP ].U();
+          points[ sideNodeIndex ].v = myForcedPnts[ iFP ].V();
+
+          updateSideUV( side, sideNodeIndex, quadsBySide );
+
+          // update adjacent sides
+          set< StdMeshers_FaceSidePtr > updatedSides;
+          updatedSides.insert( side );
+          for ( size_t i = 0; i < side.contacts.size(); ++i )
+            if ( side.contacts[i].point == sideNodeIndex )
+            {
+              const vector< FaceQuadStruct::Ptr >& adjQuads =
+                quadsBySide[ *side.contacts[i].other_side ];
+              if ( adjQuads.size() > 1 &&
+                   updatedSides.insert( * side.contacts[i].other_side ).second )
+              {
+                updateSideUV( *side.contacts[i].other_side,
+                              side.contacts[i].other_point,
+                              quadsBySide );
+              }
+              changedQuads.insert( adjQuads.begin(), adjQuads.end() );
+            }
+          const vector< FaceQuadStruct::Ptr >& adjQuads = quadsBySide[ side ];
+          changedQuads.insert( adjQuads.begin(), adjQuads.end() );
+
+          isNodeEnforced = true;
+        }
+        else // ------------------ node is inside the quad
+        {
+          // make a new side passing through IJ node and split the quad
+          int indForced, iNewSide;
+          if ( quad->iSize < quad->jSize ) // split vertically
+          {
+            quad->updateUV( myForcedPnts[ iFP ].uv, i, j, /*isVert=*/true );
+            indForced = i;
+            iNewSide  = splitQuad( quad, i, 0 );
+          }
+          else
+          {
+            quad->updateUV( myForcedPnts[ iFP ].uv, i, j, /*isVert=*/false );
+            indForced = j;
+            iNewSide  = splitQuad( quad, 0, j );
+          }
+          FaceQuadStruct::Ptr   newQuad = myQuadList.back();
+          FaceQuadStruct::Side& newSide = newQuad->side[ iNewSide ];
+
+          newSide.forced_nodes.insert( indForced );
+          quad->side[( iNewSide+2 ) % 4 ].forced_nodes.insert( indForced );
+
+          quadsBySide[ newSide ].push_back( quad );
+          quadsBySide[ newSide ].push_back( newQuad );
+
+          isNodeEnforced = true;
+
+        } // end of "node is inside the quad"
+
+      } // loop on nodes of the cell
+
+      // remove out-of-date uv grid of changedQuads
+      set< FaceQuadStruct::Ptr >::iterator qIt = changedQuads.begin();
+      for ( ; qIt != changedQuads.end(); ++qIt )
+        (*qIt)->uv_grid.clear();
+
+    } // loop on quads
+
+    if ( !isNodeEnforced )
+    {
+      if ( !myForcedPnts[ iFP ].vertex.IsNull() )
+        return error(TComm("Unable to move any node to vertex #")
+                     <<myHelper->GetMeshDS()->ShapeToIndex( myForcedPnts[ iFP ].vertex ));
+      else
+        return error(TComm("Unable to move any node to point ( ")
+                     << myForcedPnts[iFP].xyz.X() << ", "
+                     << myForcedPnts[iFP].xyz.Y() << ", "
+                     << myForcedPnts[iFP].xyz.Z() << " )");
+    }
+
+  } // loop on enforced points
+
+  // Compute nodes on all sides, where not yet present
+
+  for ( quadIt = myQuadList.begin(); quadIt != myQuadList.end(); ++quadIt )
+  {
+    FaceQuadStruct::Ptr quad = *quadIt;
+    for ( int iSide = 0; iSide < 4; ++iSide )
+    {
+      FaceQuadStruct::Side & side = quad->side[ iSide ];
+      if ( side.nbNodeOut > 0 )
+        continue; // emulated side
+      vector< FaceQuadStruct::Ptr >& quadVec = quadsBySide[ side ];
+      if ( quadVec.size() <= 1 )
+        continue; // outer side
+
+      bool missedNodesOnSide = false;
+      const vector<UVPtStruct>& points = side.grid->GetUVPtStruct();
+      for ( size_t iC = 0; iC < side.contacts.size(); ++iC )
+      {
+        const vector<UVPtStruct>& oGrid = side.contacts[iC].other_side->grid->GetUVPtStruct();
+        const UVPtStruct&         uvPt  = points[ side.contacts[iC].point ];
+        if ( side.contacts[iC].other_point >= oGrid.size()      ||
+             side.contacts[iC].point       >= points.size() )
+          throw SALOME_Exception( "StdMeshers_Quadrangle_2D::addEnforcedNodes(): wrong contact" );
+        if ( oGrid[ side.contacts[iC].other_point ].node )
+          (( UVPtStruct& ) uvPt).node = oGrid[ side.contacts[iC].other_point ].node;
+      }
+      for ( size_t iP = 0; iP < points.size(); ++iP )
+        if ( !points[ iP ].node )
+        {
+          UVPtStruct& uvPnt = ( UVPtStruct& ) points[ iP ];
+          gp_Pnt P = surf->Value( uvPnt.u, uvPnt.v );
+          uvPnt.node = meshDS->AddNode(P.X(), P.Y(), P.Z());
+          meshDS->SetNodeOnFace( uvPnt.node, myHelper->GetSubShapeID(), uvPnt.u, uvPnt.v );
+          missedNodesOnSide = true;
+        }
+      if ( missedNodesOnSide )
+      {
+        // clear uv_grid where nodes are missing
+        for ( size_t iQ = 0; iQ < quadVec.size(); ++iQ )
+          quadVec[ iQ ]->uv_grid.clear();
+      }
+    }
+  }
+
+  return true;
+}
+
+//================================================================================
+/*!
+ * \brief Splits a quad at I or J. Returns an index of a new side in the new quad
+ */
+//================================================================================
+
+int StdMeshers_Quadrangle_2D::splitQuad(FaceQuadStruct::Ptr quad, int I, int J)
+{
+  FaceQuadStruct* newQuad = new FaceQuadStruct( quad->face );
+  myQuadList.push_back( FaceQuadStruct::Ptr( newQuad ));
+
+  vector<UVPtStruct> points;
+  if ( I > 0 )
+  {
+    points.reserve( quad->jSize );
+    for ( int jP = 0; jP < quad->jSize; ++jP )
+      points.push_back( quad->UVPt( I, jP ));
+
+    newQuad->side.resize( 4 );
+    newQuad->side[ QUAD_BOTTOM_SIDE ] = quad->side[ QUAD_BOTTOM_SIDE ];
+    newQuad->side[ QUAD_RIGHT_SIDE  ] = quad->side[ QUAD_RIGHT_SIDE  ];
+    newQuad->side[ QUAD_TOP_SIDE    ] = quad->side[ QUAD_TOP_SIDE    ];
+    newQuad->side[ QUAD_LEFT_SIDE   ] = StdMeshers_FaceSide::New( points, quad->face );
+
+    FaceQuadStruct::Side& newSide  = newQuad->side[ QUAD_LEFT_SIDE ];
+    FaceQuadStruct::Side& newSide2 = quad->side   [ QUAD_RIGHT_SIDE ];
+
+    quad->side[ QUAD_RIGHT_SIDE  ] = newSide;
+
+    int iBot = quad->side[ QUAD_BOTTOM_SIDE ].ToSideIndex( I );
+    int iTop = quad->side[ QUAD_TOP_SIDE    ].ToSideIndex( I );
+
+    newSide.AddContact ( 0,               & quad->side[ QUAD_BOTTOM_SIDE ], iBot );
+    newSide2.AddContact( 0,               & quad->side[ QUAD_BOTTOM_SIDE ], iBot );
+    newSide.AddContact ( quad->jSize - 1, & quad->side[ QUAD_TOP_SIDE    ], iTop );
+    newSide2.AddContact( quad->jSize - 1, & quad->side[ QUAD_TOP_SIDE    ], iTop );
+    // cout << "Contact: L " << &newSide << " "<< newSide.NbPoints()
+    //      << " R " << &newSide2 << " "<< newSide2.NbPoints()
+    //      << " B " << &quad->side[ QUAD_BOTTOM_SIDE ] << " "<< quad->side[ QUAD_BOTTOM_SIDE].NbPoints()
+    //      << " T " << &quad->side[ QUAD_TOP_SIDE ]  << " "<< quad->side[ QUAD_TOP_SIDE].NbPoints()<< endl;
+
+    newQuad->side[ QUAD_BOTTOM_SIDE ].from = iBot;
+    newQuad->side[ QUAD_TOP_SIDE    ].from = iTop;
+
+    quad->side[ QUAD_BOTTOM_SIDE ].to = iBot + 1;
+    quad->side[ QUAD_TOP_SIDE    ].to = iTop + 1;
+    quad->uv_grid.clear();
+
+    return QUAD_LEFT_SIDE;
+  }
+  else if ( J > 0 ) //// split horizontally
+  {
+    points.reserve( quad->iSize );
+    for ( int iP = 0; iP < quad->iSize; ++iP )
+      points.push_back( quad->UVPt( iP, J ));
+
+    newQuad->side.resize( 4 );
+    newQuad->side[ QUAD_BOTTOM_SIDE ] = quad->side[ QUAD_BOTTOM_SIDE ];
+    newQuad->side[ QUAD_RIGHT_SIDE  ] = quad->side[ QUAD_RIGHT_SIDE  ];
+    newQuad->side[ QUAD_TOP_SIDE    ] = StdMeshers_FaceSide::New( points, quad->face );
+    newQuad->side[ QUAD_LEFT_SIDE   ] = quad->side[ QUAD_LEFT_SIDE   ];
+
+    FaceQuadStruct::Side& newSide  = newQuad->side[ QUAD_TOP_SIDE    ];
+    FaceQuadStruct::Side& newSide2 = quad->side   [ QUAD_BOTTOM_SIDE ];
+
+    quad->side[ QUAD_BOTTOM_SIDE ] = newSide;
+
+    int iLft = quad->side[ QUAD_LEFT_SIDE  ].ToSideIndex( J );
+    int iRgt = quad->side[ QUAD_RIGHT_SIDE ].ToSideIndex( J );
+
+    newSide.AddContact ( 0,               & quad->side[ QUAD_LEFT_SIDE  ], iLft );
+    newSide2.AddContact( 0,               & quad->side[ QUAD_LEFT_SIDE  ], iLft );
+    newSide.AddContact ( quad->iSize - 1, & quad->side[ QUAD_RIGHT_SIDE ], iRgt );
+    newSide2.AddContact( quad->iSize - 1, & quad->side[ QUAD_RIGHT_SIDE ], iRgt );
+    // cout << "Contact: T " << &newSide << " "<< newSide.NbPoints()
+    //      << " B " << &newSide2 << " "<< newSide2.NbPoints()
+    //      << " L " << &quad->side[ QUAD_LEFT_SIDE ] << " "<< quad->side[ QUAD_LEFT_SIDE].NbPoints()
+    //      << " R " << &quad->side[ QUAD_RIGHT_SIDE ]  << " "<< quad->side[ QUAD_RIGHT_SIDE].NbPoints()<< endl;
+
+    newQuad->side[ QUAD_RIGHT_SIDE ].to = iRgt+1;
+    newQuad->side[ QUAD_LEFT_SIDE  ].to = iLft+1;
+
+    quad->side[ QUAD_RIGHT_SIDE ].from = iRgt;
+    quad->side[ QUAD_LEFT_SIDE  ].from = iLft;
+    quad->uv_grid.clear();
+
+    return QUAD_TOP_SIDE;
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Updates UV of a side after moving its node
+ */
+//================================================================================
+
+void StdMeshers_Quadrangle_2D::updateSideUV( FaceQuadStruct::Side&  side,
+                                             int                    iForced,
+                                             const TQuadsBySide&    quadsBySide,
+                                             int *                  iNext)
+{
+  if ( !iNext )
+  {
+    side.forced_nodes.insert( iForced );
+
+    // update parts of the side before and after iForced
+
+    set<int>::iterator iIt = side.forced_nodes.upper_bound( iForced );
+    int iEnd = Min( side.NbPoints()-1, ( iIt == side.forced_nodes.end() ) ? int(1e7) : *iIt );
+    if ( iForced + 1 < iEnd )
+      updateSideUV( side, iForced, quadsBySide, &iEnd );
+
+    iIt = side.forced_nodes.lower_bound( iForced );
+    int iBeg = Max( 0, ( iIt == side.forced_nodes.begin() ) ? 0 : *--iIt );
+    if ( iForced - 1 > iBeg )
+      updateSideUV( side, iForced, quadsBySide, &iBeg );
+
+    return;
+  }
+
+  const int iFrom    = Min ( iForced, *iNext );
+  const int iTo      = Max ( iForced, *iNext ) + 1;
+  const int sideSize = iTo - iFrom;
+
+  vector<UVPtStruct> points[4];
+
+  // get from the quads grid points adjacent to the side
+  // to make two sides of another temporary quad
+  vector< FaceQuadStruct::Ptr > quads = quadsBySide.find( side )->second; // copy!
+  for ( int is2nd = 0; is2nd < 2; ++is2nd )
+  {
+    points[ is2nd ].reserve( sideSize );
+    int nbLoops = 0;
+    while ( points[is2nd].size() < sideSize )
+    {
+      int iCur = iFrom + points[is2nd].size() - int( !points[is2nd].empty() );
+
+      // look for a quad adjacent to iCur-th point of the side
+      for ( size_t iQ = 0; iQ < quads.size(); ++iQ )
+      {
+        FaceQuadStruct::Ptr q = quads[ iQ ];
+        if ( !q ) continue;
+        size_t iS;
+        for ( iS = 0; iS < q->side.size(); ++iS )
+          if ( side.grid == q->side[ iS ].grid )
+            break;
+        bool isOut;
+        if ( !q->side[ iS ].IsReversed() )
+          isOut = ( q->side[ iS ].from > iCur || q->side[ iS ].to-1 <= iCur );
+        else
+          isOut = ( q->side[ iS ].to  >= iCur || q->side[ iS ].from <= iCur );
+        if ( isOut )
+          continue;
+
+        // found - copy points
+        int i,j,di,dj,nb;
+        if ( iS % 2 ) // right ot left
+        {
+          i  = ( iS == QUAD_LEFT_SIDE ) ? 1 : q->iSize-2;
+          j  = q->side[ iS ].ToQuadIndex( iCur );
+          di = 0;
+          dj = ( q->side[ iS ].IsReversed() ) ? -1  : +1;
+          nb = ( q->side[ iS ].IsReversed() ) ? j+1 : q->jSize-j;
+        }
+        else // bottom or top
+        {
+          i  = q->side[ iS ].ToQuadIndex( iCur );
+          j  = ( iS == QUAD_BOTTOM_SIDE )  ?  1 : q->jSize-2;
+          di = ( q->side[ iS ].IsReversed() ) ? -1  : +1;
+          dj = 0;
+          nb = ( q->side[ iS ].IsReversed() ) ? i+1 : q->iSize-i;
+        }
+        if ( !points[is2nd].empty() )
+        {
+          gp_UV lastUV = points[is2nd].back().UV();
+          gp_UV quadUV = q->UVPt( i, j ).UV();
+          if ( ( lastUV - quadUV ).SquareModulus() > 1e-10 )
+            continue; // quad is on the other side of the side
+          i += di; j += dj; --nb;
+        }
+        for ( ; nb > 0 ; --nb )
+        {
+          points[ is2nd ].push_back( q->UVPt( i, j ));
+          if ( points[is2nd].size() >= sideSize )
+            break;
+          i += di; j += dj;
+        }
+        quads[ iQ ].reset(); // not to use this quad anymore
+
+        if ( points[is2nd].size() >= sideSize )
+          break;
+      } // loop on quads
+
+      if ( nbLoops++ > quads.size() )
+        throw SALOME_Exception( "StdMeshers_Quadrangle_2D::updateSideUV() bug: infinite loop" );
+
+    } // while ( points[is2nd].size() < sideSize )
+  } // two loops to fill points[0] and points[1]
+
+  // points for other pair of opposite sides of the temporary quad
+
+  enum { L,R,B,T }; // side index of points[]
+
+  points[B].push_back( points[L].front() );
+  points[B].push_back( side.GetUVPtStruct()[ iFrom ]);
+  points[B].push_back( points[R].front() );
+
+  points[T].push_back( points[L].back() );
+  points[T].push_back( side.GetUVPtStruct()[ iTo-1 ]);
+  points[T].push_back( points[R].back() );
+
+  // make the temporary quad
+  FaceQuadStruct::Ptr tmpQuad( new FaceQuadStruct( TopoDS::Face( myHelper->GetSubShape() )));
+  tmpQuad->side.push_back( StdMeshers_FaceSide::New( points[B] )); // bottom
+  tmpQuad->side.push_back( StdMeshers_FaceSide::New( points[R] )); // right
+  tmpQuad->side.push_back( StdMeshers_FaceSide::New( points[T] ));
+  tmpQuad->side.push_back( StdMeshers_FaceSide::New( points[L] ));
+
+  // compute new UV of the side
+  setNormalizedGrid( tmpQuad );
+  gp_UV uv = tmpQuad->UVPt(1,0).UV();
+  tmpQuad->updateUV( uv, 1,0, /*isVertical=*/true );
+
+  // update UV of the side
+  vector<UVPtStruct>& sidePoints = (vector<UVPtStruct>&) side.GetUVPtStruct();
+  for ( int i = iFrom; i < iTo; ++i )
+    sidePoints[ i ] = tmpQuad->UVPt( 1, i-iFrom );
+}
+
+//================================================================================
+/*!
+ * \brief Finds indices of a grid quad enclosing the given enforced UV
+ */
+//================================================================================
+
+bool FaceQuadStruct::findCell( const gp_XY& UV, int & I, int & J )
+{
+  // setNormalizedGrid() must be called before!
+  if ( uv_box.IsOut( UV ))
+    return false;
+
+  // find an approximate position
+  double x = 0.5, y = 0.5;
+  gp_XY t0 = UVPt( iSize - 1, 0 ).UV();
+  gp_XY t1 = UVPt( 0, jSize - 1 ).UV();
+  gp_XY t2 = UVPt( 0, 0         ).UV();
+  SMESH_MeshAlgos::GetBarycentricCoords( UV, t0, t1, t2, x, y );
+  x = Min( 1., Max( 0., x ));
+  y = Min( 1., Max( 0., y ));
+
+  // precise the position
+  //int i, j;
+  normPa2IJ( x,y, I,J );
+  if ( !isNear( UV, I,J ))
+  {
+    // look for the most close IJ by traversing uv_grid in the middle
+    double dist2, minDist2 = ( UV - UVPt( I,J ).UV() ).SquareModulus();
+    for ( int isU = 0; isU < 2; ++isU )
+    {
+      int ind1 = isU ? 0 : iSize / 2;
+      int ind2 = isU ? jSize / 2 : 0;
+      int di1  = isU ? Max( 2, iSize / 20 ) : 0;
+      int di2  = isU ? 0 : Max( 2, jSize / 20 );
+      int i,nb = isU ? iSize / di1 : jSize / di2;
+      for ( i = 0; i < nb; ++i, ind1 += di1, ind2 += di2 )
+        if (( dist2 = ( UV - UVPt( ind1,ind2 ).UV() ).SquareModulus() ) < minDist2 )
+        {
+          I = ind1;
+          J = ind2;
+          if ( isNear( UV, I,J ))
+            return true;
+          minDist2 = ( UV - UVPt( I,J ).UV() ).SquareModulus();
+        }
+    }
+    if ( !isNear( UV, I,J, Max( iSize, jSize ) /2 ))
+      return false;
+  }
+  return true;
+}
+
+//================================================================================
+/*!
+ * \brief Find indices (i,j) of a point in uv_grid by normalized parameters (x,y)
+ */
+//================================================================================
+
+void FaceQuadStruct::normPa2IJ(double X, double Y, int & I, int & J )
+{
+
+  I = Min( int ( iSize * X ), iSize - 2 );
+  J = Min( int ( jSize * Y ), jSize - 2 );
+
+  int oldI, oldJ;
+  do
+  {
+    oldI = I, oldJ = J;
+    while ( X <= UVPt( I,J ).x   && I != 0 )
+      --I;
+    while ( X >  UVPt( I+1,J ).x && I+1 < iSize )
+      ++I;
+    while ( Y <= UVPt( I,J ).y   && J != 0 )
+      --J;
+    while ( Y >  UVPt( I,J+1 ).y && J+1 < jSize )
+      ++J;
+  } while ( oldI != I || oldJ != J );
+}
+
+//================================================================================
+/*!
+ * \brief Looks for UV in quads around a given (I,J) and precise (I,J)
+ */
+//================================================================================
+
+bool FaceQuadStruct::isNear( const gp_XY& UV, int & I, int & J, int nbLoops )
+{
+  if ( I+1 >= iSize ) I = iSize - 2;
+  if ( J+1 >= jSize ) J = jSize - 2;
+
+  double bcI, bcJ;
+  gp_XY uvI, uvJ, uv0, uv1;
+  for ( int iLoop = 0; iLoop < nbLoops; ++iLoop )
+  {
+    int oldI = I, oldJ = J;
+
+    uvI = UVPt( I+1, J ).UV();
+    uvJ = UVPt( I, J+1 ).UV();
+    uv0 = UVPt( I, J   ).UV();
+    SMESH_MeshAlgos::GetBarycentricCoords( UV, uvI, uvJ, uv0, bcI, bcJ );
+    if ( bcI >= 0. && bcJ >= 0. && bcI + bcJ <= 1.)
+      return true;
+
+    if ( I > 0       && bcI < 0. ) --I;
+    if ( I+1 < iSize && bcI > 1. ) ++I;
+    if ( J > 0       && bcJ < 0. ) --J;
+    if ( J+1 < jSize && bcJ > 1. ) ++J;
+
+    uv1 = UVPt( I+1,J+1).UV();
+    if ( I != oldI || J != oldJ )
+    {
+      uvI = UVPt( I+1, J ).UV();
+      uvJ = UVPt( I, J+1 ).UV();
+    }
+    SMESH_MeshAlgos::GetBarycentricCoords( UV, uvI, uvJ, uv1, bcI, bcJ );
+    if ( bcI >= 0. && bcJ >= 0. && bcI + bcJ <= 1.)
+      return true;
+
+    if ( I > 0       && bcI > 1. ) --I;
+    if ( I+1 < iSize && bcI < 0. ) ++I;
+    if ( J > 0       && bcJ > 1. ) --J;
+    if ( J+1 < jSize && bcJ < 0. ) ++J;
+
+    if ( I == oldI && J == oldJ )
+      return false;
+
+    if ( iLoop+1 == nbLoops )
+    {
+      uvI = UVPt( I+1, J ).UV();
+      uvJ = UVPt( I, J+1 ).UV();
+      uv0 = UVPt( I, J   ).UV();
+      SMESH_MeshAlgos::GetBarycentricCoords( UV, uvI, uvJ, uv0, bcI, bcJ );
+      if ( bcI >= 0. && bcJ >= 0. && bcI + bcJ <= 1.)
+        return true;
+
+      uv1 = UVPt( I+1,J+1).UV();
+      SMESH_MeshAlgos::GetBarycentricCoords( UV, uvI, uvJ, uv1, bcI, bcJ );
+      if ( bcI >= 0. && bcJ >= 0. && bcI + bcJ <= 1.)
+        return true;
+    }
+  }
+  return false;
+}
+
+//================================================================================
+/*!
+ * \brief Checks if a given UV is equal to a given frid point
+ */
+//================================================================================
+
+bool FaceQuadStruct::isEqual( const gp_XY& UV, int I, int J )
+{
+  TopLoc_Location loc;
+  Handle(Geom_Surface) surf = BRep_Tool::Surface( face, loc );
+  gp_Pnt p1 = surf->Value( UV.X(), UV.Y() );
+  gp_Pnt p2 = surf->Value( UVPt( I,J ).u, UVPt( I,J ).v );
+
+  double dist2 = 1e100;
+  for ( int di = -1; di < 2; di += 2 )
+  {
+    int i = I + di;
+    if ( i < 0 || i+1 >= iSize ) continue;
+    for ( int dj = -1; dj < 2; dj += 2 )
+    {
+      int j = J + dj;
+      if ( j < 0 || j+1 >= jSize ) continue;
+
+      dist2 = Min( dist2,
+                   p2.SquareDistance( surf->Value( UVPt( i,j ).u, UVPt( i,j ).v )));
+    }
+  }
+  double tol2 = dist2 / 1000.;
+  return p1.SquareDistance( p2 ) < tol2;
+}
+
+//================================================================================
+/*!
+ * \brief Recompute UV of grid points around a moved point in one direction
+ */
+//================================================================================
+
+void FaceQuadStruct::updateUV( const gp_XY& UV, int I, int J, bool isVertical )
+{
+  UVPt( I, J ).u = UV.X();
+  UVPt( I, J ).v = UV.Y();
+
+  if ( isVertical )
+  {
+    // above J
+    if ( J+1 < jSize-1 )
+    {
+      gp_UV a0 = UVPt( 0,       J       ).UV();
+      gp_UV a1 = UVPt( iSize-1, J       ).UV();
+      gp_UV a2 = UVPt( iSize-1, jSize-1 ).UV();
+      gp_UV a3 = UVPt( 0,       jSize-1 ).UV();
+
+      gp_UV p0 = UVPt( I, J       ).UV();
+      gp_UV p2 = UVPt( I, jSize-1 ).UV();
+      const double y0 = UVPt( I, J ).y, dy = 1. - y0;
+      for (int j = J+1; j < jSize-1; j++)
+      {
+        gp_UV p1 = UVPt( iSize-1, j ).UV();
+        gp_UV p3 = UVPt( 0,       j ).UV();
+
+        UVPtStruct& uvPt = UVPt( I, j );
+        gp_UV uv = calcUV( uvPt.x, ( uvPt.y - y0 ) / dy, a0,a1,a2,a3, p0,p1,p2,p3);
+        uvPt.u = uv.X();
+        uvPt.v = uv.Y();
+      }
+    }
+    // under J
+    if ( J-1 > 0 )
+    {
+      gp_UV a0 = UVPt( 0,       0 ).UV();
+      gp_UV a1 = UVPt( iSize-1, 0 ).UV();
+      gp_UV a2 = UVPt( iSize-1, J ).UV();
+      gp_UV a3 = UVPt( 0,       J ).UV();
+
+      gp_UV p0 = UVPt( I, 0 ).UV();
+      gp_UV p2 = UVPt( I, J ).UV();
+      const double y0 = 0., dy = UVPt( I, J ).y - y0;
+      for (int j = 1; j < J; j++)
+      {
+        gp_UV p1 = UVPt( iSize-1, j ).UV();
+        gp_UV p3 = UVPt( 0,       j ).UV();
+
+        UVPtStruct& uvPt = UVPt( I, j );
+        gp_UV uv = calcUV( uvPt.x, ( uvPt.y - y0 ) / dy, a0,a1,a2,a3, p0,p1,p2,p3);
+        uvPt.u = uv.X();
+        uvPt.v = uv.Y();
+      }
+    }
+  }
+  else  // horizontally
+  {
+    // before I
+    if ( I-1 > 0 )
+    {
+      gp_UV a0 = UVPt( 0, 0 ).UV();
+      gp_UV a1 = UVPt( I, 0 ).UV();
+      gp_UV a2 = UVPt( I, jSize-1 ).UV();
+      gp_UV a3 = UVPt( 0, jSize-1 ).UV();
+
+      gp_UV p1 = UVPt( I, J ).UV();
+      gp_UV p3 = UVPt( 0, J ).UV();
+      const double x0 = 0., dx = UVPt( I, J ).x - x0;
+      for (int i = 1; i < I; i++)
+      {
+        gp_UV p0 = UVPt( i, 0       ).UV();
+        gp_UV p2 = UVPt( i, jSize-1 ).UV();
+
+        UVPtStruct& uvPt = UVPt( i, J );
+        gp_UV uv = calcUV(( uvPt.x - x0 ) / dx , uvPt.y, a0,a1,a2,a3, p0,p1,p2,p3);
+        uvPt.u = uv.X();
+        uvPt.v = uv.Y();
+      }
+    }
+    // after I
+    if ( I+1 < iSize-1 )
+    {
+      gp_UV a0 = UVPt( I,       0 ).UV();
+      gp_UV a1 = UVPt( iSize-1, 0 ).UV();
+      gp_UV a2 = UVPt( iSize-1, jSize-1 ).UV();
+      gp_UV a3 = UVPt( I,       jSize-1 ).UV();
+
+      gp_UV p1 = UVPt( iSize-1, J ).UV();
+      gp_UV p3 = UVPt( I,       J ).UV();
+      const double x0 = UVPt( I, J ).x, dx = 1. - x0;
+      for (int i = I+1; i < iSize-1; i++)
+      {
+        gp_UV p0 = UVPt( i, 0       ).UV();
+        gp_UV p2 = UVPt( i, jSize-1 ).UV();
+
+        UVPtStruct& uvPt = UVPt( i, J );
+        gp_UV uv = calcUV(( uvPt.x - x0 ) / dx , uvPt.y, a0,a1,a2,a3, p0,p1,p2,p3);
+        uvPt.u = uv.X();
+        uvPt.v = uv.Y();
+      }
+    }
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Side copying
+ */
+//================================================================================
+
+FaceQuadStruct::Side& FaceQuadStruct::Side::operator=(const Side& otherSide)
+{
+  grid = otherSide.grid;
+  from = otherSide.from;
+  to   = otherSide.to;
+  forced_nodes = otherSide.forced_nodes;
+  contacts     = otherSide.contacts;
+  nbNodeOut    = otherSide.nbNodeOut;
+
+  for ( size_t iC = 0; iC < contacts.size(); ++iC )
+  {
+    FaceQuadStruct::Side* oSide = contacts[iC].other_side;
+    for ( size_t iOC = 0; iOC < oSide->contacts.size(); ++iOC )
+      if ( oSide->contacts[iOC].other_side == & otherSide )
+      {
+        // cout << "SHIFT old " << &otherSide << " " << otherSide.NbPoints()
+        //      << " -> new " << this << " " << this->NbPoints() << endl;
+        oSide->contacts[iOC].other_side = this;
+      }
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Converts node index of a quad to node index of this side
+ */
+//================================================================================
+
+int FaceQuadStruct::Side::ToSideIndex( int quadNodeIndex ) const
+{
+  return ( from > to ) ? ( from - quadNodeIndex ) : ( quadNodeIndex + from );
+}
+
+//================================================================================
+/*!
+ * \brief Converts node index of this side to node index of a quad
+ */
+//================================================================================
+
+int FaceQuadStruct::Side::ToQuadIndex( int sideNodeIndex ) const
+{
+  return ( from > to ) ? ( from - sideNodeIndex ) : ( sideNodeIndex - from );
+}
+
+//================================================================================
+/*!
+ * \brief Checks if a node is enforced
+ *  \param [in] nodeIndex - an index of a node in a size
+ *  \return bool - \c true if the node is forced
+ */
+//================================================================================
+
+bool FaceQuadStruct::Side::IsForced( int nodeIndex ) const
+{
+  if ( nodeIndex < 0 || nodeIndex >= grid->NbPoints() )
+    throw SALOME_Exception( " FaceQuadStruct::Side::IsForced(): wrong index" );
+
+  if ( forced_nodes.count( nodeIndex ) )
+    return true;
+
+  for ( size_t i = 0; i < this->contacts.size(); ++i )
+    if ( contacts[ i ].point == nodeIndex &&
+         contacts[ i ].other_side->forced_nodes.count( contacts[ i ].other_point ))
+      return true;
+
+  return false;
+}
+
+//================================================================================
+/*!
+ * \brief Sets up a contact between this and another side
+ */
+//================================================================================
+
+void FaceQuadStruct::Side::AddContact( int ip, Side* side, int iop )
+{
+  if ( ip  >= GetUVPtStruct().size()      ||
+       iop >= side->GetUVPtStruct().size() )
+    throw SALOME_Exception( "FaceQuadStruct::Side::AddContact(): wrong point" );
+  {
+    contacts.resize( contacts.size() + 1 );
+    Contact&    c = contacts.back();
+    c.point       = ip;
+    c.other_side  = side;
+    c.other_point = iop;
+  }
+  {
+    side->contacts.resize( side->contacts.size() + 1 );
+    Contact&    c = side->contacts.back();
+    c.point       = iop;
+    c.other_side  = this;
+    c.other_point = ip;
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Returns a normalized parameter of a point indexed within a quadrangle
+ */
+//================================================================================
+
+double FaceQuadStruct::Side::Param( int i ) const
+{
+  const vector<UVPtStruct>& points = GetUVPtStruct();
+  return (( points[ from + i ].normParam - points[ from ].normParam ) /
+          ( points[ to   - 1 ].normParam - points[ from ].normParam ));
+}
+
+//================================================================================
+/*!
+ * \brief Returns UV by a parameter normalized within a quadrangle
+ */
+//================================================================================
+
+gp_XY FaceQuadStruct::Side::Value2d( double x ) const
+{
+  const vector<UVPtStruct>& points = GetUVPtStruct();
+  double u = ( points[ from ].normParam +
+               x * ( points[ to-1 ].normParam - points[ from ].normParam ));
+  return grid->Value2d( u ).XY();
+}
+
+//================================================================================
+/*!
+ * \brief Returns side length
+ */
+//================================================================================
+
+double FaceQuadStruct::Side::Length(int theFrom, int theTo) const
+{
+  const vector<UVPtStruct>& points = GetUVPtStruct();
+  double r = ( points[ Max( to,   theTo )-1 ].normParam -
+               points[ Max( from, theFrom ) ].normParam );
+  return r * grid->Length();
+}
index 54a2a066408b1961c11df8f09d302f767c60f39c..9fe6e120a9b659da4b54ae693e3e5ef6f6713a2a 100644 (file)
 #include "SMESH_Algo.hxx"
 #include "SMESH_ProxyMesh.hxx"
 #include "SMESH_StdMeshers.hxx"
+#include "StdMeshers_FaceSide.hxx"
 #include "StdMeshers_QuadrangleParams.hxx"
 
 #include <TopoDS_Face.hxx>
+#include <Bnd_B2d.hxx>
 
 class SMDS_MeshNode;
 class SMESH_Mesh;
 class SMESH_MesherHelper;
 class SMESH_ProxyMesh;
-class StdMeshers_FaceSide;
 struct uvPtStruct;
 
 
 enum TSideID { QUAD_BOTTOM_SIDE=0, QUAD_RIGHT_SIDE, QUAD_TOP_SIDE, QUAD_LEFT_SIDE, NB_QUAD_SIDES };
 
 typedef uvPtStruct UVPtStruct;
-typedef struct faceQuadStruct
+struct FaceQuadStruct
 {
-  std::vector< StdMeshers_FaceSide*> side;
-  bool isEdgeOut[4]; // true, if an EDGE has more nodes, than an opposite one
-  UVPtStruct* uv_grid;
-  TopoDS_Face face;
-  ~faceQuadStruct();
-  void shift( size_t nb, bool keepUnitOri );
-  typedef boost::shared_ptr<faceQuadStruct> Ptr;
-} FaceQuadStruct;
+  struct Side // a side of FaceQuadStruct
+  {
+    struct Contact // contact of two sides
+    {
+      int   point; // index of a grid point of this side where two sides meat
+      Side* other_side;
+      int   other_point;
+    };
+    StdMeshers_FaceSidePtr grid;
+    int                    from, to;     // indices of grid points used by the quad
+    std::set<int>          forced_nodes; // indices of forced grid points
+    std::vector<Contact>   contacts;     // contacts with sides of other quads
+    int                    nbNodeOut;    // nb of missing nodes on an opposite shorter side
+
+    Side(StdMeshers_FaceSidePtr theGrid = StdMeshers_FaceSidePtr());
+    Side& operator=(const Side& otherSide);
+    operator StdMeshers_FaceSidePtr() { return grid; }
+    operator const StdMeshers_FaceSidePtr() const { return grid; }
+    void AddContact( int ip, Side* side, int iop );
+    int  ToSideIndex( int quadNodeIndex ) const;
+    int  ToQuadIndex( int sideNodeIndex ) const;
+    bool IsForced( int nodeIndex ) const;
+    bool IsReversed() const { return nbNodeOut ? false : to < from; }
+    int  NbPoints() const { return Abs( to - from ); }
+    double Param( int nodeIndex ) const;
+    double Length( int from=-1, int to=-1) const;
+    gp_XY Value2d( double x ) const;
+    // some sortcuts
+    const vector<UVPtStruct>& GetUVPtStruct(bool isXConst=0, double constValue=0) const
+    { return nbNodeOut ?
+        grid->SimulateUVPtStruct( NbPoints()-nbNodeOut-1, isXConst, constValue ) :
+        grid->GetUVPtStruct( isXConst, constValue );
+    }
+  };
+
+  std::vector< Side >      side;
+  std::vector< UVPtStruct> uv_grid;
+  int                      iSize, jSize;
+  TopoDS_Face              face;
+  Bnd_B2d                  uv_box;
+
+  FaceQuadStruct ( const TopoDS_Face& F = TopoDS_Face() );
+  UVPtStruct& UVPt( int i, int j ) { return uv_grid[ i + j * iSize ]; }
+  void  shift    ( size_t nb, bool keepUnitOri );
+  int & nbNodeOut( int iSide ) { return side[ iSide ].nbNodeOut; }
+  bool  findCell ( const gp_XY& uv, int & i, int & j );
+  bool  isNear   ( const gp_XY& uv, int & i, int & j, int nbLoops=1 );
+  bool  isEqual  ( const gp_XY& uv, int   i, int   j );
+  void  normPa2IJ( double x, double y, int & i, int & j );
+  void  updateUV ( const gp_XY& uv, int   i, int   j, bool isVertical );
+
+  typedef boost::shared_ptr<FaceQuadStruct> Ptr;
+};
 
 class STDMESHERS_EXPORT StdMeshers_Quadrangle_2D: public SMESH_2D_Algo
 {
@@ -89,16 +135,17 @@ protected:
                                std::vector<int>& aNbNodes,
                                bool& IsQuadratic);
 
-  bool setNormalizedGrid(SMESH_Mesh&          aMesh,
-                         const TopoDS_Face&   aFace,
-                         FaceQuadStruct::Ptr& quad);
+  bool setNormalizedGrid(FaceQuadStruct::Ptr quad);
   
-  void splitQuad(SMESHDS_Mesh *theMeshDS,
-                 const int theFaceID,
-                 const SMDS_MeshNode* theNode1,
-                 const SMDS_MeshNode* theNode2,
-                 const SMDS_MeshNode* theNode3,
-                 const SMDS_MeshNode* theNode4);
+  void splitQuadFace(SMESHDS_Mesh *       theMeshDS,
+                     const int            theFaceID,
+                     const SMDS_MeshNode* theNode1,
+                     const SMDS_MeshNode* theNode2,
+                     const SMDS_MeshNode* theNode3,
+                     const SMDS_MeshNode* theNode4);
+
+  bool computeQuadDominant(SMESH_Mesh&         aMesh,
+                           const TopoDS_Face&  aFace);
 
   bool computeQuadDominant(SMESH_Mesh&         aMesh,
                            const TopoDS_Face&  aFace,
@@ -108,6 +155,10 @@ protected:
                        const TopoDS_Face&  aFace,
                        FaceQuadStruct::Ptr quad);
 
+  bool computeTriangles(SMESH_Mesh&         aMesh,
+                        const TopoDS_Face&  aFace,
+                        FaceQuadStruct::Ptr quad);
+
   bool evaluateQuadPref(SMESH_Mesh&         aMesh,
                         const TopoDS_Shape& aShape,
                         std::vector<int>&   aNbNodes,
@@ -129,20 +180,43 @@ protected:
                  int &                       theNbDegenEdges,
                  const bool                  considerMesh);
 
+  bool getEnforcedUV();
+
+  bool addEnforcedNodes();
+
+  int splitQuad(FaceQuadStruct::Ptr quad, int i, int j);
+
+  typedef std::map< StdMeshers_FaceSidePtr, std::vector< FaceQuadStruct::Ptr > > TQuadsBySide;
+  void updateSideUV( FaceQuadStruct::Side&  side,
+                     int                    iForced,
+                     const TQuadsBySide&    quads,
+                     int *                  iNext=NULL);
+
+
+  // Fields
 
-  // true if QuadranglePreference hypothesis is assigned that forces
-  // construction of quadrangles if the number of nodes on opposite edges
-  // is not the same in the case where the global number of nodes on edges
-  // is even
   bool myQuadranglePreference;
   bool myTrianglePreference;
   int  myTriaVertexID;
   bool myNeedSmooth;
-
-  StdMeshers_QuadType  myQuadType;
-  SMESH_MesherHelper*  myHelper; // tool for working with quadratic elements
-  SMESH_ProxyMesh::Ptr myProxyMesh;
-  FaceQuadStruct::Ptr  myQuadStruct;
+  const StdMeshers_QuadrangleParams* myParams;
+  StdMeshers_QuadType                myQuadType;
+
+  SMESH_MesherHelper*                myHelper;
+  SMESH_ProxyMesh::Ptr               myProxyMesh;
+  std::list< FaceQuadStruct::Ptr >   myQuadList;
+
+  struct ForcedPoint
+  {
+    gp_XY         uv;
+    gp_XYZ        xyz;
+    TopoDS_Vertex vertex;
+
+    double U() const { return uv.X(); }
+    double V() const { return uv.Y(); }
+    operator const gp_XY& () { return uv; }
+  };
+  std::vector< ForcedPoint >         myForcedPnts;
 };
 
 #endif
index 5377a6fa5d79d09cc40bc3800602f51524e3e2de..3470e50a2e9b44f27472bb97e85b76d533acf7e0 100644 (file)
@@ -37,6 +37,7 @@
 #include "SMESH_subMeshEventListener.hxx"
 #include "StdMeshers_Adaptive1D.hxx"
 #include "StdMeshers_Arithmetic1D.hxx"
+#include "StdMeshers_Geometric1D.hxx"
 #include "StdMeshers_AutomaticLength.hxx"
 #include "StdMeshers_Deflection1D.hxx"
 #include "StdMeshers_Distribution.hxx"
@@ -89,12 +90,14 @@ StdMeshers_Regular_1D::StdMeshers_Regular_1D(int hypId, int studyId,
   _compatibleHypothesis.push_back("StartEndLength");
   _compatibleHypothesis.push_back("Deflection1D");
   _compatibleHypothesis.push_back("Arithmetic1D");
+  _compatibleHypothesis.push_back("GeometricProgression");
   _compatibleHypothesis.push_back("FixedPoints1D");
   _compatibleHypothesis.push_back("AutomaticLength");
   _compatibleHypothesis.push_back("Adaptive1D");
-
-  _compatibleHypothesis.push_back("QuadraticMesh"); // auxiliary !!!
-  _compatibleHypothesis.push_back("Propagation"); // auxiliary !!!
+  // auxiliary:
+  _compatibleHypothesis.push_back("QuadraticMesh");
+  _compatibleHypothesis.push_back("Propagation");
+  _compatibleHypothesis.push_back("PropagOfDistribution");
 }
 
 //=============================================================================
@@ -223,6 +226,21 @@ bool StdMeshers_Regular_1D::CheckHypothesis( SMESH_Mesh&         aMesh,
     aStatus = SMESH_Hypothesis::HYP_OK;
   }
 
+  else if (hypName == "GeometricProgression")
+  {
+    const StdMeshers_Geometric1D * hyp =
+      dynamic_cast <const StdMeshers_Geometric1D * >(theHyp);
+    ASSERT(hyp);
+    _value[ BEG_LENGTH_IND ] = hyp->GetStartLength();
+    _value[ END_LENGTH_IND ] = hyp->GetCommonRatio();
+    ASSERT( _value[ BEG_LENGTH_IND ] > 0 && _value[ END_LENGTH_IND ] > 0 );
+    _hypType = GEOMETRIC_1D;
+
+    _revEdgesIDs = hyp->GetReversedEdges();
+
+    aStatus = SMESH_Hypothesis::HYP_OK;
+  }
+
   else if (hypName == "FixedPoints1D") {
     _fpHyp = dynamic_cast <const StdMeshers_FixedPoints1D*>(theHyp);
     ASSERT(_fpHyp);
@@ -616,6 +634,58 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh &     theMesh,
 
   double f = theFirstU, l = theLastU;
 
+  // Propagation Of Distribution
+  //
+  if ( !_mainEdge.IsNull() && _isPropagOfDistribution )
+  {
+    TopoDS_Edge mainEdge = TopoDS::Edge( _mainEdge ); // should not be a reference!
+    _gen->Compute( theMesh, mainEdge, /*aShapeOnly=*/true, /*anUpward=*/true);
+
+    SMESHDS_SubMesh* smDS = theMesh.GetMeshDS()->MeshElements( mainEdge );
+    if ( !smDS )
+      return error("No mesh on the source edge of Propagation Of Distribution");
+    if ( smDS->NbNodes() < 1 )
+      return true; // 1 segment
+
+    vector< double > mainEdgeParams;
+    if ( ! SMESH_Algo::GetNodeParamOnEdge( theMesh.GetMeshDS(), mainEdge, mainEdgeParams ))
+      return error("Bad node parameters on the source edge of Propagation Of Distribution");
+
+    vector< double > segLen( mainEdgeParams.size() - 1 );
+    double totalLen = 0;
+    BRepAdaptor_Curve mainEdgeCurve( mainEdge );
+    for ( size_t i = 1; i < mainEdgeParams.size(); ++i )
+    {
+      segLen[ i-1 ] = GCPnts_AbscissaPoint::Length( mainEdgeCurve,
+                                                    mainEdgeParams[i-1],
+                                                    mainEdgeParams[i]);
+      totalLen += segLen[ i-1 ];
+    }
+    for ( size_t i = 0; i < segLen.size(); ++i )
+      segLen[ i ] *= theLength / totalLen;
+
+    size_t iSeg = theReverse ? segLen.size()-1 : 0;
+    size_t dSeg = theReverse ? -1 : +1;
+    double param = theFirstU;
+    int nbParams = 0;
+    for ( int i = 0, nb = segLen.size()-1; i < nb; ++i, iSeg += dSeg )
+    {
+      GCPnts_AbscissaPoint Discret( theC3d, segLen[ iSeg ], param );
+      if ( !Discret.IsDone() ) break;
+      param = Discret.Parameter();
+      theParams.push_back( param );
+      ++nbParams;
+    }
+    if ( nbParams != segLen.size()-1 )
+      return error( SMESH_Comment("Can't divide into ") << segLen.size() << " segements");
+
+    compensateError( segLen[ theReverse ? segLen.size()-1 : 0 ],
+                     segLen[ theReverse ? 0 : segLen.size()-1 ],
+                     f, l, theLength, theC3d, theParams, true );
+    return true;
+  }
+
+
   switch( _hypType )
   {
   case LOCAL_LENGTH:
@@ -824,9 +894,54 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh &     theMesh,
     return true;
   }
 
+  case GEOMETRIC_1D: {
+
+    double a1 = _value[ BEG_LENGTH_IND ], an;
+    double q  = _value[ END_LENGTH_IND ];
+
+    double U1 = theReverse ? l : f;
+    double Un = theReverse ? f : l;
+    double param = U1;
+    double eltSize = a1;
+    if ( theReverse )
+      eltSize = -eltSize;
+
+    int nbParams = 0;
+    while ( true ) {
+      // computes a point on a curve <theC3d> at the distance <eltSize>
+      // from the point of parameter <param>.
+      GCPnts_AbscissaPoint Discret( theC3d, eltSize, param );
+      if ( !Discret.IsDone() ) break;
+      param = Discret.Parameter();
+      if ( f < param && param < l )
+        theParams.push_back( param );
+      else
+        break;
+      an = eltSize;
+      eltSize *= q;
+      ++nbParams;
+    }
+    if ( nbParams > 1 )
+    {
+      if ( Abs( param - Un ) < 0.2 * Abs( param - theParams.back() ))
+      {
+        compensateError( a1, eltSize, U1, Un, theLength, theC3d, theParams );
+      }
+      else if ( Abs( Un - theParams.back() ) <
+                0.2 * Abs( theParams.back() - *(--theParams.rbegin())))
+      {
+        theParams.pop_back();
+        compensateError( a1, an, U1, Un, theLength, theC3d, theParams );
+      }
+    }
+    if (theReverse) theParams.reverse(); // NPAL18025
+
+    return true;
+  }
+
   case FIXED_POINTS_1D: {
     const std::vector<double>& aPnts = _fpHyp->GetPoints();
-    const std::vector<int>& nbsegs = _fpHyp->GetNbSegments();
+    const std::vector<int>&   nbsegs = _fpHyp->GetNbSegments();
     int i = 0;
     TColStd_SequenceOfReal Params;
     for(; i<aPnts.size(); i++) {
@@ -1231,7 +1346,8 @@ StdMeshers_Regular_1D::GetUsedHypothesis(SMESH_Mesh &         aMesh,
   if (nbHyp == 0 && aShape.ShapeType() == TopAbs_EDGE)
   {
     // Check, if propagated from some other edge
-    _mainEdge = StdMeshers_Propagation::GetPropagationSource( aMesh, aShape );
+    _mainEdge = StdMeshers_Propagation::GetPropagationSource( aMesh, aShape,
+                                                              _isPropagOfDistribution );
     if ( !_mainEdge.IsNull() )
     {
       // Propagation of 1D hypothesis from <aMainEdge> on this edge;
index fbb9d0380628e70b8af7abd89b69cd6eb365467b..1298c80a675a20d601ab5e443f37e4d8e03020fc 100644 (file)
@@ -102,7 +102,7 @@ protected:
   StdMeshers_SegmentLengthAroundVertex* getVertexHyp(SMESH_Mesh &          theMesh,
                                                      const TopoDS_Vertex & theV);
 
-  enum HypothesisType { LOCAL_LENGTH, MAX_LENGTH, NB_SEGMENTS, BEG_END_LENGTH, DEFLECTION, ARITHMETIC_1D, FIXED_POINTS_1D, ADAPTIVE, NONE };
+  enum HypothesisType { LOCAL_LENGTH, MAX_LENGTH, NB_SEGMENTS, BEG_END_LENGTH, DEFLECTION, ARITHMETIC_1D, FIXED_POINTS_1D, ADAPTIVE, GEOMETRIC_1D, NONE };
 
   enum ValueIndex {
     SCALE_FACTOR_IND = 0,
@@ -140,6 +140,7 @@ protected:
   // a source of propagated hypothesis, is set by CheckHypothesis()
   // always called before Compute()
   TopoDS_Shape _mainEdge;
+  bool         _isPropagOfDistribution;
 };
 
 #endif
diff --git a/src/StdMeshers/StdMeshers_Reversible1D.cxx b/src/StdMeshers/StdMeshers_Reversible1D.cxx
new file mode 100644 (file)
index 0000000..05d25be
--- /dev/null
@@ -0,0 +1,99 @@
+// Copyright (C) 2007-2013  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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH SMESH : implementaion of SMESH idl descriptions
+//  File   : StdMeshers_Reversible1D.cxx
+//  Module : SMESH
+//
+
+#include "StdMeshers_Reversible1D.hxx"
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+StdMeshers_Reversible1D::StdMeshers_Reversible1D(int hypId, int studyId, SMESH_Gen * gen)
+  :SMESH_Hypothesis(hypId, studyId, gen)
+{
+  _param_algo_dim = 1; 
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+void StdMeshers_Reversible1D::SetReversedEdges( const std::vector<int>& ids )
+{
+  if ( ids != _edgeIDs )
+  {
+    _edgeIDs = ids;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+std::ostream & StdMeshers_Reversible1D::SaveTo(std::ostream & save)
+{
+  save << " " << _edgeIDs.size() << " ";
+
+  if ( !_edgeIDs.empty() )
+  {
+    for ( size_t i = 0; i < _edgeIDs.size(); i++)
+      save << " " << _edgeIDs[i];
+    save << " " << _objEntry << " ";
+  }
+
+  return save;
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+std::istream & StdMeshers_Reversible1D::LoadFrom(std::istream & load)
+{
+  bool isOK;
+  int intVal;
+
+  isOK = (load >> intVal);
+  if (isOK && intVal > 0) {
+    _edgeIDs.reserve( intVal );
+    for (int i = 0; i < _edgeIDs.capacity() && isOK; i++) {
+      isOK = (load >> intVal);
+      if ( isOK ) _edgeIDs.push_back( intVal );
+    }
+    isOK = (load >> _objEntry);
+  }
+
+  return load;
+}
diff --git a/src/StdMeshers/StdMeshers_Reversible1D.hxx b/src/StdMeshers/StdMeshers_Reversible1D.hxx
new file mode 100644 (file)
index 0000000..e393e20
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright (C) 2007-2013  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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH SMESH : implementaion of SMESH idl descriptions
+//  File   : StdMeshers_Reversible1D.hxx
+//  Module : SMESH
+//
+#ifndef _SMESH_Reversible1D_HXX_
+#define _SMESH_Reversible1D_HXX_
+
+#include "SMESH_StdMeshers.hxx"
+#include "SMESH_Hypothesis.hxx"
+
+#include <vector>
+
+/*!
+ * \brief A base of reversible 1D hypotheses
+ */
+class STDMESHERS_EXPORT StdMeshers_Reversible1D : public SMESH_Hypothesis
+{
+public:
+  StdMeshers_Reversible1D(int hypId, int studyId, SMESH_Gen* gen);
+
+  void SetReversedEdges( const std::vector<int>& ids);
+
+  void SetObjectEntry( const char* entry ) { _objEntry = entry; }
+
+  const char* GetObjectEntry() { return _objEntry.c_str(); }
+
+  const std::vector<int>& GetReversedEdges() const { return _edgeIDs; }
+
+  virtual std::ostream & SaveTo(std::ostream & save);
+  virtual std::istream & LoadFrom(std::istream & load);
+
+protected:
+  std::vector<int> _edgeIDs;
+  std::string      _objEntry;
+};
+
+#endif
index ee2eb57f6accd73f240b073025824e183a592ac1..53b58035c0ef0f91f6caee4089bc0ca05389dcae 100644 (file)
@@ -25,6 +25,9 @@
 //
 #include "StdMeshers_UseExisting_1D2D.hxx"
 
+#include "SMESH_Mesh.hxx"
+#include "SMESH_subMesh.hxx"
+
 //=======================================================================
 //function : StdMeshers_UseExisting_1D
 //purpose  : 
@@ -56,10 +59,11 @@ bool StdMeshers_UseExisting_1D::CheckHypothesis(SMESH_Mesh& ,
 //purpose  : 
 //=======================================================================
 
-bool StdMeshers_UseExisting_1D::Compute(SMESH_Mesh&, const TopoDS_Shape&)
+bool StdMeshers_UseExisting_1D::Compute(SMESH_Mesh& mesh, const TopoDS_Shape& edge)
 {
   // This algorithm exists to allow mesh generation by mesh
   // edition functions in TUI mode
+  mesh.GetSubMesh( edge )->SetIsAlwaysComputed( true );
   return true;
 }
 
@@ -110,10 +114,11 @@ bool StdMeshers_UseExisting_2D::CheckHypothesis(SMESH_Mesh& ,
 //purpose  : 
 //=======================================================================
 
-bool StdMeshers_UseExisting_2D::Compute(SMESH_Mesh&, const TopoDS_Shape&)
+bool StdMeshers_UseExisting_2D::Compute(SMESH_Mesh& mesh, const TopoDS_Shape& face)
 {
   // This algorithm exists to allow mesh generation by mesh edition
   // functions in TUI mode
+  mesh.GetSubMesh( face )->SetIsAlwaysComputed( true );
   return true;
 }
 
index e38c311ad027cea2b435f76df73843778ccf9ed1..c2a3c954b19c39410eb4105ca4160548b2cdd588 100644 (file)
@@ -35,6 +35,7 @@
 #include "SMESH_ControlsDef.hxx"
 #include "SMESH_Gen.hxx"
 #include "SMESH_Group.hxx"
+#include "SMESH_HypoFilter.hxx"
 #include "SMESH_Mesh.hxx"
 #include "SMESH_MeshAlgos.hxx"
 #include "SMESH_MesherHelper.hxx"
@@ -63,6 +64,7 @@
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
 #include <TopTools_IndexedMapOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
 #include <TopTools_MapOfShape.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Edge.hxx>
@@ -382,8 +384,10 @@ namespace VISCOUS_3D
   {
     TopoDS_Shape                    _solid;
     const StdMeshers_ViscousLayers* _hyp;
+    TopoDS_Shape                    _hypShape;
     _MeshOfSolid*                   _proxyMesh;
     set<TGeomID>                    _reversedFaceIds;
+    set<TGeomID>                    _ignoreFaceIds;
 
     double                          _stepSize, _stepSizeCoeff;
     const SMDS_MeshNode*            _stepSizeNodes[2];
@@ -393,10 +397,10 @@ namespace VISCOUS_3D
     // iteration over the map is 5 time longer than over the vector
     vector< _LayerEdge* >           _edges;
 
-    // key: an id of shape (EDGE or VERTEX) shared by a FACE with
-    // layers and a FACE w/o layers
+    // key:   an id of shape (EDGE or VERTEX) shared by a FACE with
+    //        layers and a FACE w/o layers
     // value: the shape (FACE or EDGE) to shrink mesh on.
-    // _LayerEdge's basing on nodes on key shape are inflated along the value shape
+    //       _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
@@ -414,7 +418,9 @@ namespace VISCOUS_3D
 
     _SolidData(const TopoDS_Shape&             s=TopoDS_Shape(),
                const StdMeshers_ViscousLayers* h=0,
-               _MeshOfSolid*                   m=0) :_solid(s), _hyp(h), _proxyMesh(m) {}
+               const TopoDS_Shape&             hs=TopoDS_Shape(),
+               _MeshOfSolid*                   m=0)
+      :_solid(s), _hyp(h), _hypShape(hs), _proxyMesh(m) {}
     ~_SolidData();
 
     Handle(Geom_Curve) CurveForSmooth( const TopoDS_Edge&    E,
@@ -517,7 +523,6 @@ namespace VISCOUS_3D
     SMESH_ComputeErrorPtr _error;
 
     vector< _SolidData >  _sdVec;
-    set<TGeomID>          _ignoreShapeIds;
     int                   _tmpFaceID;
   };
   //--------------------------------------------------------------------------------
@@ -617,7 +622,7 @@ namespace VISCOUS_3D
 //
 StdMeshers_ViscousLayers::StdMeshers_ViscousLayers(int hypId, int studyId, SMESH_Gen* gen)
   :SMESH_Hypothesis(hypId, studyId, gen),
-   _isToIgnoreShapes(18), _nbLayers(1), _thickness(1), _stretchFactor(1)
+   _isToIgnoreShapes(1), _nbLayers(1), _thickness(1), _stretchFactor(1)
 {
   _name = StdMeshers_ViscousLayers::GetHypType();
   _param_algo_dim = -3; // auxiliary hyp used by 3D algos
@@ -686,7 +691,7 @@ std::ostream & StdMeshers_ViscousLayers::SaveTo(std::ostream & save)
        << " " << _thickness
        << " " << _stretchFactor
        << " " << _shapeIds.size();
-  for ( unsigned i = 0; i < _shapeIds.size(); ++i )
+  for ( size_t i = 0; i < _shapeIds.size(); ++i )
     save << " " << _shapeIds[i];
   save << " " << !_isToIgnoreShapes; // negate to keep the behavior in old studies.
   return save;
@@ -788,7 +793,7 @@ namespace
     // get average dir of edges going fromV
     gp_XYZ edgeDir;
     //if ( edges.size() > 1 )
-      for ( unsigned i = 0; i < edges.size(); ++i )
+      for ( size_t i = 0; i < edges.size(); ++i )
       {
         edgeDir = getEdgeDir( edges[i], fromV );
         double size2 = edgeDir.SquareModulus();
@@ -909,9 +914,9 @@ namespace
       py = new ofstream(fname);
       *py << "import SMESH" << endl
           << "from salome.smesh import smeshBuilder" << endl
-          << "smesh = smeshBuilder.New(salome.myStudy)" << endl
+          << "smesh  = smeshBuilder.New(salome.myStudy)" << endl
           << "meshSO = smesh.GetCurrentStudy().FindObjectID('0:1:2:3')" << endl
-          << "mesh = smesh.Mesh( meshSO.GetObject() )"<<endl;
+          << "mesh   = smesh.Mesh( meshSO.GetObject() )"<<endl;
     }
     void Finish() {
       if (py)
@@ -1069,7 +1074,7 @@ SMESH_ComputeErrorPtr _ViscousBuilder::Compute(SMESH_Mesh&         theMesh,
   if ( !findFacesWithLayers() )
     return _error;
 
-  for ( unsigned i = 0; i < _sdVec.size(); ++i )
+  for ( size_t i = 0; i < _sdVec.size(); ++i )
   {
     if ( ! makeLayer(_sdVec[i]) )
       return _error;
@@ -1108,6 +1113,7 @@ bool _ViscousBuilder::findSolidsWithLayers()
   _sdVec.reserve( allSolids.Extent());
 
   SMESH_Gen* gen = _mesh->GetGen();
+  SMESH_HypoFilter filter;
   for ( int i = 1; i <= allSolids.Extent(); ++i )
   {
     // find StdMeshers_ViscousLayers hyp assigned to the i-th solid
@@ -1122,10 +1128,14 @@ bool _ViscousBuilder::findSolidsWithLayers()
       viscHyp = dynamic_cast<const StdMeshers_ViscousLayers*>( *hyp );
     if ( viscHyp )
     {
+      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, proxyMesh ));
+      _sdVec.push_back( _SolidData( allSolids(i), viscHyp, hypShape, proxyMesh ));
       _sdVec.back()._index = getMeshDS()->ShapeToIndex( allSolids(i));
     }
   }
@@ -1144,44 +1154,69 @@ bool _ViscousBuilder::findSolidsWithLayers()
 
 bool _ViscousBuilder::findFacesWithLayers()
 {
+  SMESH_MesherHelper helper( *_mesh );
+  TopExp_Explorer exp;
+  TopTools_IndexedMapOfShape solids;
+
   // collect all faces to ignore defined by hyp
-  vector<TopoDS_Shape> ignoreFaces;
-  for ( unsigned i = 0; i < _sdVec.size(); ++i )
+  for ( size_t i = 0; i < _sdVec.size(); ++i )
   {
+    solids.Add( _sdVec[i]._solid );
+
     vector<TGeomID> ids = _sdVec[i]._hyp->GetBndShapes();
-    for ( unsigned i = 0; i < ids.size(); ++i )
+    if ( _sdVec[i]._hyp->IsToIgnoreShapes() ) // FACEs to ignore are given
     {
-      const TopoDS_Shape& s = getMeshDS()->IndexToShape( ids[i] );
-      if ( !s.IsNull() && s.ShapeType() == TopAbs_FACE )
+      for ( size_t ii = 0; ii < ids.size(); ++ii )
       {
-        _ignoreShapeIds.insert( ids[i] );
-        ignoreFaces.push_back( s );
+        const TopoDS_Shape& s = getMeshDS()->IndexToShape( ids[ii] );
+        if ( !s.IsNull() && s.ShapeType() == TopAbs_FACE )
+          _sdVec[i]._ignoreFaceIds.insert( ids[ii] );
+      }
+    }
+    else // FACEs with layers are given
+    {
+      exp.Init( _sdVec[i]._solid, TopAbs_FACE );
+      for ( ; exp.More(); exp.Next() )
+      {
+        TGeomID faceInd = getMeshDS()->ShapeToIndex( exp.Current() );
+        if ( find( ids.begin(), ids.end(), faceInd ) == ids.end() )
+          _sdVec[i]._ignoreFaceIds.insert( faceInd );
       }
     }
-  }
 
-  // ignore internal faces
-  SMESH_MesherHelper helper( *_mesh );
-  TopExp_Explorer exp;
-  for ( unsigned i = 0; i < _sdVec.size(); ++i )
-  {
-    exp.Init( _sdVec[i]._solid.Oriented( TopAbs_FORWARD ), TopAbs_FACE );
-    for ( ; exp.More(); exp.Next() )
+    // ignore internal FACEs if inlets and outlets are specified
     {
-      TGeomID faceInd = getMeshDS()->ShapeToIndex( exp.Current() );
-      if ( helper.NbAncestors( exp.Current(), *_mesh, TopAbs_SOLID ) > 1 )
-      {     
-        _ignoreShapeIds.insert( faceInd );
-        ignoreFaces.push_back( exp.Current() );
-        if ( helper.IsReversedSubMesh( TopoDS::Face( exp.Current() )))
+      TopTools_IndexedDataMapOfShapeListOfShape solidsOfFace;
+      if ( _sdVec[i]._hyp->IsToIgnoreShapes() )
+        TopExp::MapShapesAndAncestors( _sdVec[i]._hypShape,
+                                       TopAbs_FACE, TopAbs_SOLID, solidsOfFace);
+
+      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 ))
+        {
           _sdVec[i]._reversedFaceIds.insert( faceInd );
+        }
       }
     }
   }
 
   // Find faces to shrink mesh on (solution 2 in issue 0020832);
   TopTools_IndexedMapOfShape shapes;
-  for ( unsigned i = 0; i < _sdVec.size(); ++i )
+  for ( size_t i = 0; i < _sdVec.size(); ++i )
   {
     shapes.Clear();
     TopExp::MapShapes(_sdVec[i]._solid, TopAbs_EDGE, shapes);
@@ -1201,18 +1236,35 @@ bool _ViscousBuilder::findFacesWithLayers()
       // check presence of layers on them
       int ignore[2];
       for ( int j = 0; j < 2; ++j )
-        ignore[j] = _ignoreShapeIds.count ( getMeshDS()->ShapeToIndex( FF[j] ));
-      if ( ignore[0] == ignore[1] ) continue; // nothing interesting
+        ignore[j] = _sdVec[i]._ignoreFaceIds.count ( getMeshDS()->ShapeToIndex( FF[j] ));
+      if ( ignore[0] == ignore[1] )
+        continue; // nothing interesting
       TopoDS_Shape fWOL = FF[ ignore[0] ? 0 : 1 ];
+      // check presence of layers on fWOL within an adjacent SOLID
+      PShapeIteratorPtr sIt = helper.GetAncestors( fWOL, *_mesh, TopAbs_SOLID );
+      while ( const TopoDS_Shape* solid = sIt->next() )
+        if ( !solid->IsSame( _sdVec[i]._solid ))
+        {
+          int iSolid = solids.FindIndex( *solid );
+          int  iFace = getMeshDS()->ShapeToIndex( fWOL );
+          if ( iSolid > 0 && !_sdVec[ iSolid-1 ]._ignoreFaceIds.count( iFace ))
+          {
+            _sdVec[i]._noShrinkFaces.insert( iFace );
+            fWOL.Nullify();
+          }
+        }
       // add edge to maps
-      TGeomID edgeInd = getMeshDS()->ShapeToIndex( edge );
-      _sdVec[i]._shrinkShape2Shape.insert( make_pair( edgeInd, fWOL ));
+      if ( !fWOL.IsNull())
+      {
+        TGeomID edgeInd = getMeshDS()->ShapeToIndex( edge );
+        _sdVec[i]._shrinkShape2Shape.insert( make_pair( edgeInd, fWOL ));
+      }
     }
   }
   // Exclude from _shrinkShape2Shape FACE's that can't be shrinked since
   // the algo of the SOLID sharing the FACE does not support it
   set< string > notSupportAlgos; notSupportAlgos.insert("Hexa_3D");
-  for ( unsigned i = 0; i < _sdVec.size(); ++i )
+  for ( size_t i = 0; i < _sdVec.size(); ++i )
   {
     TopTools_MapOfShape noShrinkVertices;
     map< TGeomID, TopoDS_Shape >::iterator e2f = _sdVec[i]._shrinkShape2Shape.begin();
@@ -1229,7 +1281,7 @@ bool _ViscousBuilder::findFacesWithLayers()
         SMESH_Algo* algo = _mesh->GetGen()->GetAlgo( *_mesh, *solid );
         if ( !algo || !notSupportAlgos.count( algo->GetName() )) continue;
         notShrinkFace = true;
-        for ( unsigned j = 0; j < _sdVec.size(); ++j )
+        for ( size_t j = 0; j < _sdVec.size(); ++j )
         {
           if ( _sdVec[j]._solid.IsSame( *solid ) )
             if ( _sdVec[j]._shrinkShape2Shape.count( edgeID ))
@@ -1262,10 +1314,10 @@ bool _ViscousBuilder::findFacesWithLayers()
       }
     }
   }
-      
+
   // Find the SHAPE along which to inflate _LayerEdge based on VERTEX
 
-  for ( unsigned i = 0; i < _sdVec.size(); ++i )
+  for ( size_t i = 0; i < _sdVec.size(); ++i )
   {
     shapes.Clear();
     TopExp::MapShapes(_sdVec[i]._solid, TopAbs_VERTEX, shapes);
@@ -1279,11 +1331,12 @@ bool _ViscousBuilder::findFacesWithLayers()
       while ( fIt->more())
       {
         const TopoDS_Shape* f = fIt->next();
-        const int         fID = getMeshDS()->ShapeToIndex( *f );
         if ( helper.IsSubShape( *f, _sdVec[i]._solid ) )
         {
           totalNbFaces++;
-          if ( _ignoreShapeIds.count ( fID ) && ! _sdVec[i]._noShrinkFaces.count( fID ))
+          const int fID = getMeshDS()->ShapeToIndex( *f );
+          if ( _sdVec[i]._ignoreFaceIds.count ( fID ) &&
+               !_sdVec[i]._noShrinkFaces.count( fID ))
             facesWOL.push_back( *f );
         }
       }
@@ -1293,42 +1346,42 @@ bool _ViscousBuilder::findFacesWithLayers()
       switch ( facesWOL.size() )
       {
       case 1:
+      {
+        helper.SetSubShape( facesWOL[0] );
+        if ( helper.IsRealSeam( vInd )) // inflate along a seam edge?
         {
-          helper.SetSubShape( facesWOL[0] );
-          if ( helper.IsRealSeam( vInd )) // inflate along a seam edge?
+          TopoDS_Shape seamEdge;
+          PShapeIteratorPtr eIt = helper.GetAncestors(vertex, *_mesh, TopAbs_EDGE);
+          while ( eIt->more() && seamEdge.IsNull() )
           {
-            TopoDS_Shape seamEdge;
-            PShapeIteratorPtr eIt = helper.GetAncestors(vertex, *_mesh, TopAbs_EDGE);
-            while ( eIt->more() && seamEdge.IsNull() )
-            {
-              const TopoDS_Shape* e = eIt->next();
-              if ( helper.IsRealSeam( *e ) )
-                seamEdge = *e;
-            }
-            if ( !seamEdge.IsNull() )
-            {
-              _sdVec[i]._shrinkShape2Shape.insert( make_pair( vInd, seamEdge ));
-              break;
-            }
+            const TopoDS_Shape* e = eIt->next();
+            if ( helper.IsRealSeam( *e ) )
+              seamEdge = *e;
+          }
+          if ( !seamEdge.IsNull() )
+          {
+            _sdVec[i]._shrinkShape2Shape.insert( make_pair( vInd, seamEdge ));
+            break;
           }
-          _sdVec[i]._shrinkShape2Shape.insert( make_pair( vInd, facesWOL[0] ));
-          break;
         }
+        _sdVec[i]._shrinkShape2Shape.insert( make_pair( vInd, facesWOL[0] ));
+        break;
+      }
       case 2:
+      {
+        // find an edge shared by 2 faces
+        PShapeIteratorPtr eIt = helper.GetAncestors(vertex, *_mesh, TopAbs_EDGE);
+        while ( eIt->more())
         {
-          // find an edge shared by 2 faces
-          PShapeIteratorPtr eIt = helper.GetAncestors(vertex, *_mesh, TopAbs_EDGE);
-          while ( eIt->more())
+          const TopoDS_Shape* e = eIt->next();
+          if ( helper.IsSubShape( *e, facesWOL[0]) &&
+               helper.IsSubShape( *e, facesWOL[1]))
           {
-            const TopoDS_Shape* e = eIt->next();
-            if ( helper.IsSubShape( *e, facesWOL[0]) &&
-                 helper.IsSubShape( *e, facesWOL[1]))
-            {
-              _sdVec[i]._shrinkShape2Shape.insert( make_pair( vInd, *e )); break;
-            }
+            _sdVec[i]._shrinkShape2Shape.insert( make_pair( vInd, *e )); break;
           }
-          break;
         }
+        break;
+      }
       default:
         return error("Not yet supported case", _sdVec[i]._index);
       }
@@ -1351,10 +1404,10 @@ bool _ViscousBuilder::makeLayer(_SolidData& data)
   subIds = data._noShrinkFaces;
   TopExp_Explorer exp( data._solid, TopAbs_FACE );
   for ( ; exp.More(); exp.Next() )
-    if ( ! _ignoreShapeIds.count( getMeshDS()->ShapeToIndex( exp.Current() )))
     {
       SMESH_subMesh* fSubM = _mesh->GetSubMesh( exp.Current() );
-      faceIds.insert( fSubM->GetId() );
+      if ( ! data._ignoreFaceIds.count( getMeshDS()->ShapeToIndex( exp.Current() )))
+        faceIds.insert( fSubM->GetId() );
       SMESH_subMeshIteratorPtr subIt =
         fSubM->getDependsOnIterator(/*includeSelf=*/true, /*complexShapeFirst=*/false);
       while ( subIt->more() )
@@ -1368,7 +1421,7 @@ bool _ViscousBuilder::makeLayer(_SolidData& data)
   for (; s2s != data._shrinkShape2Shape.end(); ++s2s )
   {
     TGeomID shapeInd = s2s->first;
-    for ( unsigned i = 0; i < _sdVec.size(); ++i )
+    for ( size_t i = 0; i < _sdVec.size(); ++i )
     {
       if ( _sdVec[i]._index == data._index ) continue;
       map< TGeomID, TopoDS_Shape >::iterator s2s2 = _sdVec[i]._shrinkShape2Shape.find( shapeInd );
@@ -1475,7 +1528,7 @@ bool _ViscousBuilder::makeLayer(_SolidData& data)
 
   // Set target nodes into _Simplex and _2NearEdges
   TNode2Edge::iterator n2e;
-  for ( unsigned i = 0; i < data._edges.size(); ++i )
+  for ( size_t i = 0; i < data._edges.size(); ++i )
   {
     if ( data._edges[i]->IsOnEdge())
       for ( int j = 0; j < 2; ++j )
@@ -1489,7 +1542,7 @@ bool _ViscousBuilder::makeLayer(_SolidData& data)
         data._edges[i]->_2neibors->_edges[j] = n2e->second;
       }
     else
-      for ( unsigned j = 0; j < data._edges[i]->_simplices.size(); ++j )
+      for ( size_t j = 0; j < data._edges[i]->_simplices.size(); ++j )
       {
         _Simplex& s = data._edges[i]->_simplices[j];
         s._nNext = data._n2eMap[ s._nNext ]->_nodes.back();
@@ -1573,7 +1626,7 @@ bool _ViscousBuilder::sortEdges( _SolidData&                    data,
   SMESH_MesherHelper helper( *_mesh );
   bool ok = true;
 
-  for ( unsigned iS = 0; iS < edgesByGeom.size(); ++iS )
+  for ( size_t iS = 0; iS < edgesByGeom.size(); ++iS )
   {
     vector<_LayerEdge*>& eS = edgesByGeom[iS];
     if ( eS.empty() ) continue;
@@ -1617,7 +1670,7 @@ bool _ViscousBuilder::sortEdges( _SolidData&                    data,
         if ( eE.empty() ) continue;
         if ( eE[0]->_sWOL.IsNull() )
         {
-          for ( unsigned i = 0; i < eE.size() && !needSmooth; ++i )
+          for ( size_t i = 0; i < eE.size() && !needSmooth; ++i )
             needSmooth = ( eE[i]->_cosin > 0.1 );
         }
         else
@@ -1625,7 +1678,7 @@ bool _ViscousBuilder::sortEdges( _SolidData&                    data,
           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 ( unsigned i = 0; i < eE.size() && !needSmooth; ++i )
+          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 );
@@ -1664,7 +1717,7 @@ bool _ViscousBuilder::sortEdges( _SolidData&                    data,
   }
 
   // then the rest _LayerEdge's
-  for ( unsigned iS = 0; iS < edgesByGeom.size(); ++iS )
+  for ( size_t iS = 0; iS < edgesByGeom.size(); ++iS )
   {
     vector<_LayerEdge*>& eVec = edgesByGeom[iS];
     data._edges.insert( data._edges.end(), eVec.begin(), eVec.end() );
@@ -1870,9 +1923,9 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge&         edge,
 
     if ( posType == SMDS_TOP_FACE )
     {
-      getSimplices( node, edge._simplices, _ignoreShapeIds, &data );
+      getSimplices( node, edge._simplices, data._ignoreFaceIds, &data );
       double avgNormProj = 0, avgLen = 0;
-      for ( unsigned i = 0; i < edge._simplices.size(); ++i )
+      for ( size_t i = 0; i < edge._simplices.size(); ++i )
       {
         gp_XYZ vec = edge._pos.back() - SMESH_TNodeXYZ( edge._simplices[i]._nPrev );
         avgNormProj += edge._normal * vec;
@@ -2103,7 +2156,7 @@ void _ViscousBuilder::getSimplices( const SMDS_MeshNode* node,
 void _ViscousBuilder::makeGroupOfLE()
 {
 #ifdef _DEBUG_
-  for ( unsigned i = 0 ; i < _sdVec.size(); ++i )
+  for ( size_t i = 0 ; i < _sdVec.size(); ++i )
   {
     if ( _sdVec[i]._edges.empty() ) continue;
 //     string name = SMESH_Comment("_LayerEdge's_") << i;
@@ -2113,10 +2166,10 @@ void _ViscousBuilder::makeGroupOfLE()
 //     SMESHDS_Mesh* mDS = _mesh->GetMeshDS();
 
     dumpFunction( SMESH_Comment("make_LayerEdge_") << i );
-    for ( unsigned j = 0 ; j < _sdVec[i]._edges.size(); ++j )
+    for ( size_t j = 0 ; j < _sdVec[i]._edges.size(); ++j )
     {
       _LayerEdge* le = _sdVec[i]._edges[j];
-      for ( unsigned iN = 1; iN < le->_nodes.size(); ++iN )
+      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]));
@@ -2124,7 +2177,7 @@ void _ViscousBuilder::makeGroupOfLE()
     dumpFunctionEnd();
 
     dumpFunction( SMESH_Comment("makeNormals") << i );
-    for ( unsigned j = 0 ; j < _sdVec[i]._edges.size(); ++j )
+    for ( size_t j = 0 ; j < _sdVec[i]._edges.size(); ++j )
     {
       _LayerEdge& edge = *_sdVec[i]._edges[j];
       SMESH_TNodeXYZ nXYZ( edge._nodes[0] );
@@ -2178,7 +2231,7 @@ bool _ViscousBuilder::inflate(_SolidData& data)
   auto_ptr<SMESH_ElementSearcher> searcher
     ( SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(),
                                            data._proxyMesh->GetFaces( data._solid )) );
-  for ( unsigned i = 0; i < data._edges.size(); ++i )
+  for ( size_t i = 0; i < data._edges.size(); ++i )
   {
     if ( data._edges[i]->IsOnEdge() ) continue;
     data._edges[i]->FindIntersection( *searcher, intersecDist, data._epsilon );
@@ -2213,7 +2266,7 @@ bool _ViscousBuilder::inflate(_SolidData& data)
 
     // Elongate _LayerEdge's
     dumpFunction(SMESH_Comment("inflate")<<data._index<<"_step"<<nbSteps); // debug
-    for ( unsigned i = 0; i < data._edges.size(); ++i )
+    for ( size_t i = 0; i < data._edges.size(); ++i )
     {
       data._edges[i]->SetNewLength( curThick, helper );
     }
@@ -2229,7 +2282,7 @@ bool _ViscousBuilder::inflate(_SolidData& data)
       if ( nbSteps > 0 )
       {
         dumpFunction(SMESH_Comment("invalidate")<<data._index<<"_step"<<nbSteps); // debug
-        for ( unsigned i = 0; i < data._edges.size(); ++i )
+        for ( size_t i = 0; i < data._edges.size(); ++i )
         {
           data._edges[i]->InvalidateStep( nbSteps+1 );
         }
@@ -2241,7 +2294,7 @@ bool _ViscousBuilder::inflate(_SolidData& data)
 
     // Evaluate achieved thickness
     avgThick = 0;
-    for ( unsigned i = 0; i < data._edges.size(); ++i )
+    for ( size_t i = 0; i < data._edges.size(); ++i )
       avgThick += data._edges[i]->_len;
     avgThick /= data._edges.size();
 #ifdef __myDEBUG
@@ -2289,7 +2342,7 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
   TopoDS_Face F;
 
   int iBeg, iEnd = 0;
-  for ( unsigned iS = 0; iS < data._endEdgeToSmooth.size(); ++iS )
+  for ( size_t iS = 0; iS < data._endEdgeToSmooth.size(); ++iS )
   {
     iBeg = iEnd;
     iEnd = data._endEdgeToSmooth[ iS ];
@@ -2355,7 +2408,7 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
         {
           _LayerEdge* edge = data._edges[i];
           SMESH_TNodeXYZ tgtXYZ( edge->_nodes.back() );
-          for ( unsigned j = 0; j < edge->_simplices.size(); ++j )
+          for ( size_t j = 0; j < edge->_simplices.size(); ++j )
             if ( !edge->_simplices[j].IsForward( edge->_nodes[0], &tgtXYZ ))
             {
               cout << "Bad simplex ( " << edge->_nodes[0]->GetID()<< " "<< tgtXYZ._node->GetID()
@@ -2384,7 +2437,7 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
   const SMDS_MeshElement* closestFace = 0;
   int iLE = 0;
 #endif
-  for ( unsigned i = 0; i < data._edges.size(); ++i )
+  for ( size_t i = 0; i < data._edges.size(); ++i )
   {
     if ( data._edges[i]->FindIntersection( *searcher, dist, data._epsilon, &intFace ))
       return false;
@@ -2695,7 +2748,7 @@ bool _ViscousBuilder::updateNormals( _SolidData&         data,
     vector< const SMDS_MeshNode*> nodes(4); // of a tmp mesh face
 
     dumpFunction(SMESH_Comment("makeTmpFacesOnEdges")<<data._index);
-    for ( unsigned i = 0; i < data._edges.size(); ++i )
+    for ( size_t i = 0; i < data._edges.size(); ++i )
     {
       _LayerEdge* edge = data._edges[i];
       if ( !edge->IsOnEdge() || !edge->_sWOL.IsNull() ) continue;
@@ -2712,7 +2765,7 @@ bool _ViscousBuilder::updateNormals( _SolidData&         data,
         }
         // look for a _LayerEdge containg tgt2
 //         _LayerEdge* neiborEdge = 0;
-//         unsigned di = 0; // check _edges[i+di] and _edges[i-di]
+//         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 )
@@ -2751,7 +2804,7 @@ bool _ViscousBuilder::updateNormals( _SolidData&         data,
   TLEdge2LEdgeSet edge2CloseEdge;
 
   const double eps = data._epsilon * data._epsilon;
-  for ( unsigned i = 0; i < data._edges.size(); ++i )
+  for ( size_t i = 0; i < data._edges.size(); ++i )
   {
     _LayerEdge* edge = data._edges[i];
     if ( !edge->IsOnEdge() || !edge->_sWOL.IsNull() ) continue;
@@ -2922,7 +2975,7 @@ bool _ViscousBuilder::updateNormals( _SolidData&         data,
   // 2) Check absence of intersections
   // TODO?
 
-  for ( unsigned i = 0 ; i < tmpFaces.size(); ++i )
+  for ( size_t i = 0 ; i < tmpFaces.size(); ++i )
     delete tmpFaces[i];
 
   return true;
@@ -2948,7 +3001,7 @@ bool _LayerEdge::FindIntersection( SMESH_ElementSearcher&   searcher,
   bool segmentIntersected = false;
   distance = Precision::Infinite();
   int iFace = -1; // intersected face
-  for ( unsigned 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 ||
@@ -3236,7 +3289,7 @@ bool _LayerEdge::Smooth(int& badNb)
 
   // compute new position for the last _pos
   gp_XYZ newPos (0,0,0);
-  for ( unsigned i = 0; i < _simplices.size(); ++i )
+  for ( size_t i = 0; i < _simplices.size(); ++i )
     newPos += SMESH_TNodeXYZ( _simplices[i]._nPrev );
   newPos /= _simplices.size();
 
@@ -3259,11 +3312,11 @@ bool _LayerEdge::Smooth(int& badNb)
   // count quality metrics (orientation) of tetras around _tgtNode
   int nbOkBefore = 0;
   SMESH_TNodeXYZ tgtXYZ( _nodes.back() );
-  for ( unsigned i = 0; i < _simplices.size(); ++i )
+  for ( size_t i = 0; i < _simplices.size(); ++i )
     nbOkBefore += _simplices[i].IsForward( _nodes[0], &tgtXYZ );
 
   int nbOkAfter = 0;
-  for ( unsigned i = 0; i < _simplices.size(); ++i )
+  for ( size_t i = 0; i < _simplices.size(); ++i )
     nbOkAfter += _simplices[i].IsForward( _nodes[0], &newPos );
 
   if ( nbOkAfter < nbOkBefore )
@@ -3389,14 +3442,14 @@ bool _ViscousBuilder::refine(_SolidData& data)
   gp_XY uv;
   bool isOnEdge;
 
-  for ( unsigned i = 0; i < data._edges.size(); ++i )
+  for ( size_t i = 0; i < data._edges.size(); ++i )
   {
     _LayerEdge& edge = *data._edges[i];
 
     // get accumulated length of segments
     vector< double > segLen( edge._pos.size() );
     segLen[0] = 0.0;
-    for ( unsigned j = 1; j < edge._pos.size(); ++j )
+    for ( size_t j = 1; j < edge._pos.size(); ++j )
       segLen[j] = segLen[j-1] + (edge._pos[j-1] - edge._pos[j] ).Modulus();
 
     // allocate memory for new nodes if it is not yet refined
@@ -3444,8 +3497,8 @@ bool _ViscousBuilder::refine(_SolidData& data)
 
     // create intermediate nodes
     double hSum = 0, hi = h0/f;
-    unsigned iSeg = 1;
-    for ( unsigned iStep = 1; iStep < edge._nodes.size(); ++iStep )
+    size_t iSeg = 1;
+    for ( size_t iStep = 1; iStep < edge._nodes.size(); ++iStep )
     {
       // compute an intermediate position
       hi *= f;
@@ -3512,7 +3565,7 @@ bool _ViscousBuilder::refine(_SolidData& data)
 
   if ( !getMeshDS()->IsEmbeddedMode() )
     // Log node movement
-    for ( unsigned i = 0; i < data._edges.size(); ++i )
+    for ( size_t i = 0; i < data._edges.size(); ++i )
     {
       _LayerEdge& edge = *data._edges[i];
       SMESH_TNodeXYZ p ( edge._nodes.back() );
@@ -3526,7 +3579,7 @@ bool _ViscousBuilder::refine(_SolidData& data)
   TopExp_Explorer exp( data._solid, TopAbs_FACE );
   for ( ; exp.More(); exp.Next() )
   {
-    if ( _ignoreShapeIds.count( getMeshDS()->ShapeToIndex( exp.Current() )))
+    if ( data._ignoreFaceIds.count( getMeshDS()->ShapeToIndex( exp.Current() )))
       continue;
     SMESHDS_SubMesh* fSubM = getMeshDS()->MeshElements( exp.Current() );
     SMDS_ElemIteratorPtr fIt = fSubM->GetElements();
@@ -3577,7 +3630,7 @@ bool _ViscousBuilder::shrink()
   // make map of (ids of FACEs to shrink mesh on) to (_SolidData containing _LayerEdge's
   // inflated along FACE or EDGE)
   map< TGeomID, _SolidData* > f2sdMap;
-  for ( unsigned i = 0 ; i < _sdVec.size(); ++i )
+  for ( size_t i = 0 ; i < _sdVec.size(); ++i )
   {
     _SolidData& data = _sdVec[i];
     TopTools_MapOfShape FFMap;
@@ -3684,7 +3737,7 @@ bool _ViscousBuilder::shrink()
 
     // Replace source nodes by target nodes in mesh faces to shrink
     const SMDS_MeshNode* nodes[20];
-    for ( unsigned i = 0; i < lEdges.size(); ++i )
+    for ( size_t i = 0; i < lEdges.size(); ++i )
     {
       _LayerEdge& edge = *lEdges[i];
       const SMDS_MeshNode* srcNode = edge._nodes[0];
@@ -3712,7 +3765,7 @@ bool _ViscousBuilder::shrink()
     vector< _SmoothNode > nodesToSmooth( smoothNodes.size() );
     {
       const bool sortSimplices = isConcaveFace;
-      for ( unsigned i = 0; i < smoothNodes.size(); ++i )
+      for ( size_t i = 0; i < smoothNodes.size(); ++i )
       {
         const SMDS_MeshNode* n = smoothNodes[i];
         nodesToSmooth[ i ]._node = n;
@@ -3728,7 +3781,7 @@ bool _ViscousBuilder::shrink()
     // Find EDGE's to shrink and set simpices to LayerEdge's
     set< _Shrinker1D* > eShri1D;
     {
-      for ( unsigned i = 0; i < lEdges.size(); ++i )
+      for ( size_t i = 0; i < lEdges.size(); ++i )
       {
         _LayerEdge* edge = lEdges[i];
         if ( edge->_sWOL.ShapeType() == TopAbs_EDGE )
@@ -3801,7 +3854,7 @@ bool _ViscousBuilder::shrink()
         int oldBadNb = badNb;
         badNb = 0;
         moved = false;
-        for ( unsigned i = 0; i < nodesToSmooth.size(); ++i )
+        for ( size_t i = 0; i < nodesToSmooth.size(); ++i )
         {
           moved |= nodesToSmooth[i].Smooth( badNb,surface,helper,refSign,
                                             smoothType, /*set3D=*/isConcaveFace);
@@ -3870,7 +3923,7 @@ bool _ViscousBuilder::shrink()
         case 3: smoothType = _SmoothNode::ANGULAR; break;
         }
         dumpFunction(SMESH_Comment("shrinkFace")<<f2sd->first<<"_st"<<++smooStep); // debug
-        for ( unsigned i = 0; i < nodesToSmooth.size(); ++i )
+        for ( size_t i = 0; i < nodesToSmooth.size(); ++i )
         {
           nodesToSmooth[i].Smooth( badNb,surface,helper,refSign,
                                    smoothType,/*set3D=*/st==1 );
@@ -3883,7 +3936,7 @@ bool _ViscousBuilder::shrink()
 
     if ( !getMeshDS()->IsEmbeddedMode() )
       // Log node movement
-      for ( unsigned i = 0; i < nodesToSmooth.size(); ++i )
+      for ( size_t i = 0; i < nodesToSmooth.size(); ++i )
       {
         SMESH_TNodeXYZ p ( nodesToSmooth[i]._node );
         getMeshDS()->MoveNode( nodesToSmooth[i]._node, p.X(), p.Y(), p.Z() );
@@ -3937,7 +3990,7 @@ bool _ViscousBuilder::prepareEdgeToShrink( _LayerEdge&            edge,
     //   if ( faceSubMesh->Contains( f ))
     //     faces.push_back( f );
     // }
-    // for ( unsigned i = 0; i < faces.size(); ++i )
+    // for ( size_t i = 0; i < faces.size(); ++i )
     // {
     //   const int nbNodes = faces[i]->NbCornerNodes();
     //   for ( int j = 0; j < nbNodes; ++j )
@@ -4397,11 +4450,11 @@ bool _SmoothNode::Smooth(int&                  badNb,
   // count quality metrics (orientation) of triangles around the node
   int nbOkBefore = 0;
   gp_XY tgtUV = helper.GetNodeUV( face, _node );
-  for ( unsigned i = 0; i < _simplices.size(); ++i )
+  for ( size_t i = 0; i < _simplices.size(); ++i )
     nbOkBefore += _simplices[i].IsForward( tgtUV, _node, face, helper, refSign );
 
   int nbOkAfter = 0;
-  for ( unsigned i = 0; i < _simplices.size(); ++i )
+  for ( size_t i = 0; i < _simplices.size(); ++i )
     nbOkAfter += _simplices[i].IsForward( newPos, _node, face, helper, refSign );
 
   if ( nbOkAfter < nbOkBefore )
@@ -4496,7 +4549,7 @@ gp_XY _SmoothNode::computeAngularPos(vector<gp_XY>& uv,
 
 _SolidData::~_SolidData()
 {
-  for ( unsigned i = 0; i < _edges.size(); ++i )
+  for ( size_t i = 0; i < _edges.size(); ++i )
   {
     if ( _edges[i] && _edges[i]->_2neibors )
       delete _edges[i]->_2neibors;
@@ -4569,7 +4622,7 @@ void _Shrinker1D::AddEdge( const _LayerEdge* e, SMESH_MesherHelper& helper )
   {
     // remove target node of the _LayerEdge from _nodes
     int nbFound = 0;
-    for ( unsigned i = 0; i < _nodes.size(); ++i )
+    for ( size_t i = 0; i < _nodes.size(); ++i )
       if ( !_nodes[i] || _nodes[i] == tgtNode0 || _nodes[i] == tgtNode1 )
         _nodes[i] = 0, nbFound++;
     if ( nbFound == _nodes.size() )
@@ -4607,7 +4660,7 @@ void _Shrinker1D::Compute(bool set3D, SMESH_MesherHelper& helper)
       l = helper.GetNodeU( E, _edges[1]->_nodes.back(), _nodes.back() );
     double totLen = GCPnts_AbscissaPoint::Length( aCurve, f, l );
 
-    for ( unsigned i = 0; i < _nodes.size(); ++i )
+    for ( size_t i = 0; i < _nodes.size(); ++i )
     {
       if ( !_nodes[i] ) continue;
       double len = totLen * _normPar[i];
@@ -4629,7 +4682,7 @@ void _Shrinker1D::Compute(bool set3D, SMESH_MesherHelper& helper)
     if ( _edges[1] )
       l = helper.GetNodeU( E, _edges[1]->_nodes.back(), _nodes.back() );
     
-    for ( unsigned i = 0; i < _nodes.size(); ++i )
+    for ( size_t i = 0; i < _nodes.size(); ++i )
     {
       if ( !_nodes[i] ) continue;
       double u = f * ( 1-_normPar[i] ) + l * _normPar[i];
@@ -4648,7 +4701,7 @@ void _Shrinker1D::Compute(bool set3D, SMESH_MesherHelper& helper)
 void _Shrinker1D::RestoreParams()
 {
   if ( _done )
-    for ( unsigned i = 0; i < _nodes.size(); ++i )
+    for ( size_t i = 0; i < _nodes.size(); ++i )
     {
       if ( !_nodes[i] ) continue;
       SMDS_EdgePosition* pos = static_cast<SMDS_EdgePosition*>( _nodes[i]->GetPosition() );
@@ -4701,7 +4754,7 @@ bool _ViscousBuilder::addBoundaryElements()
 {
   SMESH_MesherHelper helper( *_mesh );
 
-  for ( unsigned i = 0; i < _sdVec.size(); ++i )
+  for ( size_t i = 0; i < _sdVec.size(); ++i )
   {
     _SolidData& data = _sdVec[i];
     TopTools_IndexedMapOfShape geomEdges;
@@ -4772,7 +4825,7 @@ bool _ViscousBuilder::addBoundaryElements()
         {
           const TopoDS_Shape* pF = fIt->next();
           if ( helper.IsSubShape( *pF, data._solid) &&
-               !_ignoreShapeIds.count( e2f->first ))
+               !data._ignoreFaceIds.count( e2f->first ))
             F = *pF;
         }
       }
@@ -4788,7 +4841,7 @@ bool _ViscousBuilder::addBoundaryElements()
       // Make faces
       const int dj1 = reverse ? 0 : 1;
       const int dj2 = reverse ? 1 : 0;
-      for ( unsigned j = 1; j < ledges.size(); ++j )
+      for ( size_t j = 1; j < ledges.size(); ++j )
       {
         vector< const SMDS_MeshNode*>&  nn1 = ledges[j-dj1]->_nodes;
         vector< const SMDS_MeshNode*>&  nn2 = ledges[j-dj2]->_nodes;
index 937c79066efa46a064d6c65bce302e29f9b0912e..c2b58de8dabdcd40cd9f336bdb33b05b73a4d7ce 100644 (file)
@@ -42,6 +42,7 @@
 #include <QAbstractItemModel>
 #include <QApplication>
 #include <QButtonGroup>
+#include <QCheckBox>
 #include <QGridLayout>
 #include <QGroupBox>
 #include <QHBoxLayout>
 #include <QLineEdit>
 #include <QListWidget>
 #include <QModelIndex>
+#include <QPushButton>
 #include <QRadioButton>
 #include <QString>
 #include <QStyleOptionViewItem>
+#include <QTabWidget>
 #include <QTreeWidget>
 #include <QTreeWidgetItem>
 #include <QVBoxLayout>
-#include <QPushButton>
-#include <QTabWidget>
 
 #define SPACING 6
 #define MARGIN  11
@@ -162,7 +163,7 @@ namespace StdMeshersGUI
     myStepSpin->SetValue( myStep = 1. );
 
     // 3) Coodrinates/Spacing group
-    QFrame* csFrame = new QFrame( this );
+    QFrame*    csFrame = new QFrame( this );
     QVBoxLayout* scLay = new QVBoxLayout( csFrame );
     scLay->setMargin( 0 );
     scLay->setSpacing( SPACING );
@@ -610,7 +611,12 @@ QFrame* StdMeshersGUI_CartesianParamCreator::buildFrame()
   argGroupLayout->addWidget( myThreshold, row, 1 );
   row++;
   
-  // 2)  Grid definition
+  // 2)  "Implement edges"
+  myAddEdges = new QCheckBox( tr("ADD_EDGES"), GroupC1 );
+  argGroupLayout->addWidget( myAddEdges, row, 0, 1, 2 );
+  row++;
+
+  // 3)  Grid definition
   QTabWidget* tabWdg = new QTabWidget( fr );
   myAxisTabs[ 0 ] = new StdMeshersGUI::GridAxisTab( tabWdg, 0 );
   myAxisTabs[ 1 ] = new StdMeshersGUI::GridAxisTab( tabWdg, 1 );
@@ -637,6 +643,8 @@ void StdMeshersGUI_CartesianParamCreator::retrieveParams() const
   else
     myThreshold->setText( varName );
 
+  myAddEdges->setChecked( h->GetToAddEdges() );
+
   for ( int ax = 0; ax < 3; ++ax )
   {
     if ( h->IsGridBySpacing( ax ))
@@ -653,7 +661,8 @@ void StdMeshersGUI_CartesianParamCreator::retrieveParams() const
     }
   }
   if ( dlg() )
-    dlg()->setMinimumSize( dlg()->minimumSizeHint().width(), dlg()->minimumSizeHint().height() );
+    dlg()->setMinimumSize( dlg()->minimumSizeHint().width(),
+                           dlg()->minimumSizeHint().height() );
 }
 
 QString StdMeshersGUI_CartesianParamCreator::storeParams() const
@@ -668,6 +677,7 @@ QString StdMeshersGUI_CartesianParamCreator::storeParams() const
 
     h->SetVarParameter( myThreshold->text().toLatin1().constData(), "SetSizeThreshold" );
     h->SetSizeThreshold( myThreshold->text().toDouble() );
+    h->SetToAddEdges( myAddEdges->isChecked() );
 
     for ( int ax = 0; ax < 3; ++ax )
     {
index 5a02d5ca13bfcb1151ffed1e39c1e5e5e7593b30..1187bb90ba1aaff6622fd449135a7bd6734383dc 100644 (file)
 #include <QFrame>
 #include <QItemDelegate>
 
-class SMESHGUI_SpinBox;
-class QLineEdit;
+class QAbstractItemModel;
 class QButtonGroup;
-class QTreeWidgetItem;
-class QString;
-class QWidget;
-class QTreeWidget;
+class QCheckBox;
+class QLineEdit;
 class QListWidget;
-class QStyleOptionViewItem;
-class QModelIndex;
-class QAbstractItemModel;
 class QListWidgetItem;
+class QModelIndex;
+class QString;
+class QStyleOptionViewItem;
+class QTreeWidget;
+class QTreeWidgetItem;
+class QWidget;
+class SMESHGUI_SpinBox;
 
 namespace StdMeshersGUI
 {
@@ -136,6 +137,7 @@ protected:
 private:
   QLineEdit*                  myName;
   SMESHGUI_SpinBox*           myThreshold;
+  QCheckBox*                  myAddEdges;
   StdMeshersGUI::GridAxisTab* myAxisTabs[3];
 };
 
index ca774d105c118f684ab2517e567f0bf1952146a1..342f66fc418e775d9f7f94b9cb5b95d7c18b2917 100644 (file)
@@ -523,6 +523,23 @@ QString StdMeshersGUI_StdHypothesisCreator::storeParams() const
         h->SetObjectEntry( w->GetMainShapeEntry() );
       }
     }
+    else if( hypType()=="GeometricProgression" )
+    {
+      StdMeshers::StdMeshers_Geometric1D_var h =
+        StdMeshers::StdMeshers_Geometric1D::_narrow( hypothesis() );
+
+      StdMeshersGUI_SubShapeSelectorWdg* w = 
+        widget< StdMeshersGUI_SubShapeSelectorWdg >( 2 );
+
+      h->SetVarParameter( params[0].text(), "SetStartLength" );
+      h->SetStartLength( params[0].myValue.toDouble() );
+      h->SetVarParameter( params[1].text(), "SetCommonRatio" );
+      h->SetCommonRatio( params[1].myValue.toDouble() );
+      if (w) {
+        h->SetReversedEdges( w->GetListOfIDs() );
+        h->SetObjectEntry( w->GetMainShapeEntry() );
+      }
+    }
     else if( hypType()=="FixedPoints1D" )
     {
       StdMeshers::StdMeshers_FixedPoints1D_var h =
@@ -704,9 +721,9 @@ QString StdMeshersGUI_StdHypothesisCreator::storeParams() const
       h->SetStretchFactor ( params[2].myValue.toDouble() );
 
       if ( StdMeshersGUI_SubShapeSelectorWdg* idsWg = 
-           widget< StdMeshersGUI_SubShapeSelectorWdg >( 3 ))
+           widget< StdMeshersGUI_SubShapeSelectorWdg >( 4 ))
       {
-        h->SetIgnoreFaces( idsWg->GetListOfIDs() );
+        h->SetFaces( idsWg->GetListOfIDs(), params[3].myValue.toInt() );
       }
     }
     else if( hypType()=="ViscousLayers2D" )
@@ -878,6 +895,41 @@ bool StdMeshersGUI_StdHypothesisCreator::stdParams( ListOfStdParams& p ) const
     customWidgets()->append ( aDirectionWidget );
   }
 
+  else if( hypType()=="GeometricProgression" )
+  {
+    StdMeshers::StdMeshers_Geometric1D_var h =
+      StdMeshers::StdMeshers_Geometric1D::_narrow( hyp );
+
+    item.myName = tr( "SMESH_START_LENGTH_PARAM" );
+    if(!initVariableName( hyp, item, "SetStartLength" ))
+      item.myValue = h->GetStartLength();
+    p.append( item );
+
+    customWidgets()->append (0);
+
+    item.myName = tr( "SMESH_COMMON_RATIO" );
+    if(!initVariableName( hyp, item, "SetCommonRatio" ))
+      item.myValue = h->GetCommonRatio();
+    p.append( item );
+
+    customWidgets()->append (0);
+
+    item.myName = tr( "SMESH_REVERSED_EDGES" );
+    p.append( item );
+
+    StdMeshersGUI_SubShapeSelectorWdg* aDirectionWidget =
+      new StdMeshersGUI_SubShapeSelectorWdg();
+    QString aGeomEntry = SMESHGUI_GenericHypothesisCreator::getShapeEntry();
+    QString aMainEntry = SMESHGUI_GenericHypothesisCreator::getMainShapeEntry();
+    if ( aGeomEntry == "" )
+      aGeomEntry = h->GetObjectEntry();
+
+    aDirectionWidget->SetGeomShapeEntry( aGeomEntry );
+    aDirectionWidget->SetMainShapeEntry( aMainEntry );
+    aDirectionWidget->SetListOfIDs( h->GetReversedEdges() );
+    aDirectionWidget->showPreview( true );
+    customWidgets()->append ( aDirectionWidget );
+  }
 
   else if( hypType()=="FixedPoints1D" )
   {
@@ -1192,7 +1244,19 @@ bool StdMeshersGUI_StdHypothesisCreator::stdParams( ListOfStdParams& p ) const
     QString aMainEntry = SMESHGUI_GenericHypothesisCreator::getMainShapeEntry();
     if ( !aMainEntry.isEmpty() )
     {
-      item.myName = tr( "SMESH_FACES_WO_LAYERS" );
+      item.myName = tr( "TO_IGNORE_FACES_OR_NOT" );
+      p.append( item );
+
+      StdMeshersGUI_RadioButtonsGrpWdg* ignoreWdg = new StdMeshersGUI_RadioButtonsGrpWdg("");
+      ignoreWdg->setButtonLabels ( QStringList()
+                                   << tr("NOT_TO_IGNORE_FACES")
+                                   << tr("TO_IGNORE_FACES") );
+      ignoreWdg->setChecked( h->GetIsToIgnoreFaces() );
+      connect(ignoreWdg->getButtonGroup(),SIGNAL(buttonClicked(int)),this,SLOT(onValueChanged()));
+      customWidgets()->append( ignoreWdg );
+
+      item.myName =
+        tr( h->GetIsToIgnoreFaces() ? "SMESH_FACES_WO_LAYERS" : "SMESH_FACES_WITH_LAYERS" );
       p.append( item );
 
       StdMeshersGUI_SubShapeSelectorWdg* idsWg =
@@ -1200,7 +1264,7 @@ bool StdMeshersGUI_StdHypothesisCreator::stdParams( ListOfStdParams& p ) const
 
       idsWg->SetGeomShapeEntry( aMainEntry );
       idsWg->SetMainShapeEntry( aMainEntry );
-      idsWg->SetListOfIDs( h->GetIgnoreFaces() );
+      idsWg->SetListOfIDs( h->GetFaces() );
       idsWg->showPreview( true );
       customWidgets()->append ( idsWg );
     }
@@ -1325,6 +1389,13 @@ void StdMeshersGUI_StdHypothesisCreator::attuneStdWidget (QWidget* w, const int)
     {
       sb->RangeStepAndValidator( VALUE_SMALL, VALUE_MAX, 1.0, "parametric_precision" );
     }
+    else if( hypType()=="GeometricProgression" )
+    {
+      if (sb->objectName() == tr("SMESH_START_LENGTH_PARAM"))
+        sb->RangeStepAndValidator( VALUE_SMALL, VALUE_MAX, 1.0, "length_precision" );
+      else if (sb->objectName() == tr("SMESH_COMMON_RATIO"))
+        sb->RangeStepAndValidator( -VALUE_MAX, VALUE_MAX, 0.5, "len_tol_precision" );
+    }
     else if( hypType()=="MaxLength" )
     {
       sb->RangeStepAndValidator( VALUE_SMALL, VALUE_MAX, 1.0, "length_precision" );
@@ -1423,6 +1494,7 @@ QString StdMeshersGUI_StdHypothesisCreator::hypTypeName( const QString& t ) cons
     types.insert( "Deflection1D", "DEFLECTION1D" );
     types.insert( "Adaptive1D", "ADAPTIVE1D" );
     types.insert( "Arithmetic1D", "ARITHMETIC_1D" );
+    types.insert( "GeometricProgression", "GEOMETRIC_1D" );
     types.insert( "FixedPoints1D", "FIXED_POINTS_1D" );
     types.insert( "AutomaticLength", "AUTOMATIC_LENGTH" );
     types.insert( "ProjectionSource1D", "PROJECTION_SOURCE_1D" );
@@ -1596,12 +1668,15 @@ void StdMeshersGUI_StdHypothesisCreator::valueChanged( QWidget* paramWidget)
       toCopyGroups->setEnabled( true );
     }
   }
-  else if ( hypType() == "ViscousLayers2D" && paramWidget->inherits("QButtonGroup"))
+  else if ( hypType().startsWith( "ViscousLayers" ) && paramWidget->inherits("QButtonGroup"))
   {
     if ( QLabel* label = getLabel(4) )
     {
       bool toIgnore = widget< StdMeshersGUI_RadioButtonsGrpWdg >( 3 )->checkedId();
-      label->setText( tr( toIgnore ? "SMESH_EDGES_WO_LAYERS" : "SMESH_EDGES_WITH_LAYERS" ));
+      if ( hypType() == "ViscousLayers2D" )
+        label->setText( tr( toIgnore ? "SMESH_EDGES_WO_LAYERS" : "SMESH_EDGES_WITH_LAYERS" ));
+      else
+        label->setText( tr( toIgnore ? "SMESH_FACES_WO_LAYERS" : "SMESH_FACES_WITH_LAYERS" ));
     }
   }
 }
index a729340e2902e8852c3f8effc7ff6f85b1b39c87..537118cf5d75d3a393595ca145fa0a47897d8b15 100644 (file)
@@ -7,6 +7,10 @@
             <source>ICON_DLG_ARITHMETIC_1D</source>
             <translation>mesh_hypo_length.png</translation>
         </message>
+        <message>
+            <source>ICON_DLG_GEOMETRIC_1D</source>
+            <translation>mesh_hypo_length.png</translation>
+        </message>
         <message>
             <source>ICON_DLG_FIXED_POINTS_1D</source>
             <translation>mesh_hypo_length.png</translation>
             <source>ICON_DLG_ADAPTIVE1D</source>
             <translation>mesh_hypo_length.png</translation>
         </message>
-        <message>
-            <source>ICON_DLG_GEOMETRIC_1D</source>
-            <translation>mesh_hypo_length.png</translation>
-        </message>
         <message>
             <source>ICON_DLG_LAYER_DISTRIBUTION</source>
             <translation>mesh_hypo_layer_distribution.png</translation>
             <source>ICON_SMESH_TREE_HYPO_Arithmetic1D</source>
             <translation>mesh_tree_hypo_length.png</translation>
         </message>
+        <message>
+            <source>ICON_SMESH_TREE_HYPO_Geometric1D</source>
+            <translation>mesh_tree_hypo_length.png</translation>
+        </message>
         <message>
             <source>ICON_SMESH_TREE_HYPO_AutomaticLength</source>
             <translation>mesh_tree_hypo_length.png</translation>
             <source>ICON_SMESH_TREE_HYPO_Propagation</source>
             <translation>mesh_tree_hypo_length.png</translation>
         </message>
+        <message>
+            <source>ICON_SMESH_TREE_HYPO_PropagOfDistribution</source>
+            <translation>mesh_tree_hypo_length.png</translation>
+        </message>
         <message>
             <source>ICON_SMESH_TREE_HYPO_QuadranglePreference</source>
             <translation>mesh_tree_algo_quad.png</translation>
index c9982405eed93452836a1e3f84f8bc1fee9b19c1..f2ccb30f8cb57f12b93a9e309478a955acd5cb35 100644 (file)
         <source>TO_IGNORE_EDGES</source>
         <translation>Edges without layers (inlets and oulets)</translation>
     </message>
+    <message>
+        <source>TO_IGNORE_FACES_OR_NOT</source>
+        <translation>Specified faces are</translation>
+    </message>
+    <message>
+        <source>NOT_TO_IGNORE_FACES</source>
+        <translation>Faces with layers (walls)</translation>
+    </message>
+    <message>
+        <source>TO_IGNORE_FACES</source>
+        <translation>Faces without layers (inlets and oulets)</translation>
+    </message>
 </context>
 <context>
     <name>@default</name>
         <translation>Arithmetic 1D</translation>
     </message>
     <message>
-        <source>SMESH_ARITHMETIC_1D_PARAM</source>
-        <translation>Arithmetic Reason</translation>
+        <source>SMESH_ARITHMETIC_1D_TITLE</source>
+        <translation>Hypothesis Construction</translation>
     </message>
     <message>
-        <source>SMESH_ARITHMETIC_1D_TITLE</source>
+        <source>SMESH_GEOMETRIC_1D_HYPOTHESIS</source>
+        <translation>Geometric Progression</translation>
+    </message>
+    <message>
+        <source>SMESH_GEOMETRIC_1D_TITLE</source>
         <translation>Hypothesis Construction</translation>
     </message>
+    <message>
+        <source>SMESH_COMMON_RATIO</source>
+        <translation>Common Ratio</translation>
+    </message>
     <message>
         <source>SMESH_AUTOMATIC_LENGTH_HYPOTHESIS</source>
         <translation>Automatic Length</translation>
         <source>THRESHOLD</source>
         <translation>Threshold</translation>
     </message>
+    <message>
+        <source>ADD_EDGES</source>
+        <translation>Implement Edges</translation>
+    </message>
     <message>
         <source>AXIS_X</source>
         <translation>Axis X</translation>
index 4f3de78838b1c62b41e10a1404a8fc97a3e1b7b6..dba9000575ffa37e84de675b694369f42fc98198 100755 (executable)
@@ -3,6 +3,18 @@
 <TS version="2.0" language="fr_FR">
 <context>
     <name>@default</name>
+    <message>
+        <source>SMESH_COMMON_RATIO</source>
+        <translation type="unfinished">Common Ratio</translation>
+    </message>
+    <message>
+        <source>SMESH_GEOMETRIC_1D_TITLE</source>
+        <translation type="unfinished">Hypothesis Construction</translation>
+    </message>
+    <message>
+        <source>SMESH_GEOMETRIC_1D_HYPOTHESIS</source>
+        <translation type="unfinished">Geometric Progression</translation>
+    </message>
     <message>
         <source>SMESH_EDGES_WITH_LAYERS</source>
         <translation type="unfinished">Edges with layers</translation>
 </context>
 <context>
     <name>StdMeshersGUI_CartesianParamCreator</name>
+    <message>
+        <source>ADD_EDGES</source>
+        <translation type="unfinished">Implement Edges</translation>
+    </message>
     <message>
         <source>THRESHOLD</source>
         <translation>Seuil</translation>
index 51cbd0c0d14ce1b14409fb8cb0606e457e42d8fc..73bacce5c270d0453c9876375d96560edd8549ed 100644 (file)
@@ -129,8 +129,10 @@ ENDIF(SALOME_SMESH_ENABLE_MEFISTO)
 SET(StdMeshersEngine_SOURCES
   StdMeshers_i.cxx
   StdMeshers_LocalLength_i.cxx 
+  StdMeshers_Reversible1D_i.cxx
   StdMeshers_StartEndLength_i.cxx
   StdMeshers_Arithmetic1D_i.cxx
+  StdMeshers_Geometric1D_i.cxx
   StdMeshers_FixedPoints1D_i.cxx
   StdMeshers_NumberOfSegments_i.cxx
   StdMeshers_Deflection1D_i.cxx
index 5221f2cec47627d7763b27830095febfdde0bc0d..3db734054be4849eba401005c2bb11c28d8843fd 100644 (file)
@@ -224,6 +224,28 @@ void StdMeshers_CartesianParameters3D_i::GetGridSpacing(SMESH::string_array_out
   }
 }
 
+//=======================================================================
+//function : SetToAddEdges
+//purpose  : Enables implementation of geometrical edges into the mesh.
+//=======================================================================
+
+void StdMeshers_CartesianParameters3D_i::SetToAddEdges(CORBA::Boolean toAdd)
+{
+  GetImpl()->SetToAddEdges( toAdd );
+  SMESH::TPythonDump() << _this() << ".SetToAddEdges( " << toAdd << " )";
+}
+
+//=======================================================================
+//function : GetToAddEdges
+//purpose  : Returns true if implementation of geometrical edges into the
+//           mesh is enabled
+//=======================================================================
+
+CORBA::Boolean StdMeshers_CartesianParameters3D_i::GetToAddEdges()
+{
+  return GetImpl()->GetToAddEdges();
+}
+
 //=======================================================================
 //function : IsGridBySpacing
 //purpose  : Return true if the grid is defined by spacing functions and 
index a1f00f6059b24d160c9172d3f882bf835c9b6a75..abdda05f4f7f4aac8fd022aa9e54bda415d19ad5 100644 (file)
@@ -84,6 +84,14 @@ class STDMESHERS_I_EXPORT StdMeshers_CartesianParameters3D_i:
                       SMESH::double_array_out xInternalPoints,
                       CORBA::Short            axis) throw (SALOME::SALOME_Exception);
 
+  /*!
+   * \brief Enables implementation of geometrical edges into the mesh. If this feature
+   *        is disabled, sharp edges of the shape are lost ("smoothed") in the mesh if
+   *        they don't coincide with the grid lines
+   */
+  void SetToAddEdges(CORBA::Boolean toAdd);
+  CORBA::Boolean GetToAddEdges();
+
   /*!
    * \brief Return true if the grid is defined by spacing functions and 
    *        not by node coordinates
diff --git a/src/StdMeshers_I/StdMeshers_Geometric1D_i.cxx b/src/StdMeshers_I/StdMeshers_Geometric1D_i.cxx
new file mode 100644 (file)
index 0000000..b3183e8
--- /dev/null
@@ -0,0 +1,143 @@
+// Copyright (C) 2007-2013  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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
+//  File   : StdMeshers_Geometric1D_i.cxx
+//  Module : SMESH
+//
+#include "StdMeshers_Geometric1D_i.hxx"
+#include "SMESH_Gen_i.hxx"
+#include "SMESH_Gen.hxx"
+#include "SMESH_PythonDump.hxx"
+
+#include <Utils_CorbaException.hxx>
+#include <utilities.h>
+
+//=============================================================================
+/*!
+ *  StdMeshers_Geometric1D_i::StdMeshers_Geometric1D_i
+ *
+ *  Constructor
+ */
+//=============================================================================
+
+StdMeshers_Geometric1D_i::StdMeshers_Geometric1D_i( PortableServer::POA_ptr thePOA,
+                                                    int                     theStudyId,
+                                                    ::SMESH_Gen*            theGenImpl )
+  : SALOME::GenericObj_i( thePOA ), 
+    SMESH_Hypothesis_i( thePOA ),
+    StdMeshers_Reversible1D_i( this )
+{
+  myBaseImpl = new ::StdMeshers_Geometric1D( theGenImpl->GetANewId(),
+                                             theStudyId,
+                                             theGenImpl );
+}
+
+//=============================================================================
+/*!
+ * Sets <start segment length> parameter value
+ */
+//=============================================================================
+
+void StdMeshers_Geometric1D_i::SetStartLength( CORBA::Double theLength )
+  throw (SALOME::SALOME_Exception)
+{
+  try {
+    this->GetImpl()->SetStartLength( theLength );
+  }
+  catch ( SALOME_Exception& S_ex ) {
+    THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), SALOME::BAD_PARAM );
+  }
+  // Update Python script
+  SMESH::TPythonDump()
+    << _this() << ".SetStartLength( " << SMESH::TVar(theLength) << " )";
+}
+
+//=============================================================================
+/*!
+ * Sets <common ratio> parameter value
+ */
+//=============================================================================
+
+void StdMeshers_Geometric1D_i::SetCommonRatio( CORBA::Double factor )
+  throw (SALOME::SALOME_Exception)
+{
+  try {
+    this->GetImpl()->SetCommonRatio( factor );
+  }
+  catch ( SALOME_Exception& S_ex ) {
+    THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), SALOME::BAD_PARAM );
+  }
+  // Update Python script
+  SMESH::TPythonDump()
+    << _this() << ".SetCommonRatio( " << SMESH::TVar(factor) << " )";
+}
+
+//=============================================================================
+/*!
+ *  Returns length of the first segment 
+ */
+//=============================================================================
+
+CORBA::Double StdMeshers_Geometric1D_i::GetStartLength()
+{
+  return this->GetImpl()->GetStartLength();
+}
+
+//=============================================================================
+/*!
+ * Returns value of Common Ratio
+ */
+//=============================================================================
+
+CORBA::Double StdMeshers_Geometric1D_i::GetCommonRatio()
+{
+  return this->GetImpl()->GetCommonRatio();
+}
+
+//=============================================================================
+/*!
+ *  StdMeshers_Geometric1D_i::GetImpl
+ *
+ *  Get implementation
+ */
+//=============================================================================
+
+::StdMeshers_Geometric1D* StdMeshers_Geometric1D_i::GetImpl()
+{
+  return ( ::StdMeshers_Geometric1D* )myBaseImpl;
+}
+
+//================================================================================
+/*!
+ * \brief Verify whether hypothesis supports given entity type 
+  * \param type - dimension (see SMESH::Dimension enumeration)
+  * \retval CORBA::Boolean - TRUE if dimension is supported, FALSE otherwise
+ * 
+ * Verify whether hypothesis supports given entity type (see SMESH::Dimension enumeration)
+ */
+//================================================================================  
+
+CORBA::Boolean StdMeshers_Geometric1D_i::IsDimSupported(::SMESH::Dimension type)
+{
+  return type == SMESH::DIM_1D;
+}
diff --git a/src/StdMeshers_I/StdMeshers_Geometric1D_i.hxx b/src/StdMeshers_I/StdMeshers_Geometric1D_i.hxx
new file mode 100644 (file)
index 0000000..3786dd5
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright (C) 2007-2013  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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
+//  File   : StdMeshers_Geometric1D_i.hxx
+//  Module : SMESH
+//
+#ifndef _SMESH_Geometric1D_I_HXX_
+#define _SMESH_Geometric1D_I_HXX_
+
+#include "SMESH_StdMeshers_I.hxx"
+
+#include <SALOMEconfig.h>
+#include CORBA_SERVER_HEADER(SMESH_BasicHypothesis)
+
+#include "SMESH_Hypothesis_i.hxx"
+#include "StdMeshers_Geometric1D.hxx"
+#include "StdMeshers_Reversible1D_i.hxx"
+
+// ======================================================
+// Geometric 1D hypothesis
+// ======================================================
+class STDMESHERS_I_EXPORT StdMeshers_Geometric1D_i:
+  public virtual POA_StdMeshers::StdMeshers_Geometric1D,
+  public virtual SMESH_Hypothesis_i,
+  public virtual StdMeshers_Reversible1D_i
+{
+ public:
+  // Constructor
+  StdMeshers_Geometric1D_i( PortableServer::POA_ptr thePOA,
+                            int                     theStudyId,
+                            ::SMESH_Gen*            theGenImpl );
+
+  void SetStartLength(CORBA::Double length) throw(SALOME::SALOME_Exception);
+  void SetCommonRatio(CORBA::Double factor) throw(SALOME::SALOME_Exception);
+
+  CORBA::Double GetStartLength();
+  CORBA::Double GetCommonRatio();
+
+  virtual ::CORBA::Boolean IsDimSupported(::SMESH::Dimension type);
+
+  // Get implementation
+  ::StdMeshers_Geometric1D* GetImpl();
+};
+
+#endif
index 88a0163ec928dd52d1910b02deda913650f45ff0..6b92e8b2dfd2bc12547343aa53aafff113493f9d 100644 (file)
@@ -37,7 +37,7 @@ using namespace std;
 //purpose  : Return study entry of GEOM Object
 //=======================================================================
 
-std::string StdMeshers_ObjRefUlils::GeomObjectToEntry(GEOM::GEOM_Object_ptr theGeomObject)
+std::string StdMeshers_ObjRefUlils::GeomObjectToEntry(GEOM::GEOM_Object_ptr theGeomObject)
 {
   if ( CORBA::is_nil( theGeomObject ))
     return "NULL_OBJECT";
@@ -109,13 +109,16 @@ void StdMeshers_ObjRefUlils::SaveToStream( const TopoDS_Shape& theShape, ostream
    */
 //================================================================================
 
-TopoDS_Shape StdMeshers_ObjRefUlils::LoadFromStream( istream & stream)
+TopoDS_Shape StdMeshers_ObjRefUlils::LoadFromStream( istream &    stream,
+                                                     std::string* entry)
 {
-  if (SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen()) {
-    SALOMEDS::Study_var study = gen->GetCurrentStudy();
-    if ( ! study->_is_nil() ) {
-      string str;
-      if (stream >> str) {
+  string str;
+  if (stream >> str) {
+    if ( entry )
+      * entry = str;
+    if (SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen()) {
+      SALOMEDS::Study_var study = gen->GetCurrentStudy();
+      if ( ! study->_is_nil() ) {
         SALOMEDS::SObject_wrap sobj = study->FindObjectID( str.c_str() );
         CORBA::Object_var       obj = gen->SObjectToObject( sobj );
         GEOM::GEOM_Object_var  geom = GEOM::GEOM_Object::_narrow( obj );
@@ -123,6 +126,8 @@ TopoDS_Shape StdMeshers_ObjRefUlils::LoadFromStream( istream & stream)
       }
     }
   }
+  if ( entry )
+    entry->clear();
   return TopoDS_Shape();
 }
 
index c7d6ed86561270514a89d0bac39bb4c4f7fb1c0a..32ae9b3e3051d0e39b2daf621d851d0254d3ce23 100644 (file)
@@ -68,7 +68,7 @@ public:
   /*!
    * \brief Return study entry of GEOM Object
    */
-  static std::string GeomObjectToEntry(GEOM::GEOM_Object_ptr theGeomObject);
+  static std::string GeomObjectToEntry(GEOM::GEOM_Object_ptr theGeomObject);
 
   /*!
    * \brief Return GEOM Object by its study entry or TopoDS_Shape
@@ -89,7 +89,7 @@ public:
     * \param stream - the stream
     * \retval TopoDS_Shape - resulting shape
    */
-  static TopoDS_Shape LoadFromStream( std::istream & stream );
+  static TopoDS_Shape LoadFromStream( std::istream & stream, std::string* entry=NULL );
 
   /*!
    * \brief Store the CORBA object in the stream
index 919d2f698ef07705fdb5fa1911a3109820f78dd7..a468e81c8ea790fc3dd4f7e65a4d13136e9be423 100644 (file)
@@ -23,7 +23,6 @@
 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
 //  File   : StdMeshers_Propagation_i.cxx
 //  Module : SMESH
-//  $Header$
 //
 #include "StdMeshers_Propagation_i.hxx"
 #include "SMESH_Gen.hxx"
@@ -43,8 +42,8 @@ using namespace std;
 StdMeshers_Propagation_i::StdMeshers_Propagation_i (PortableServer::POA_ptr thePOA,
                                                     int                     theStudyId,
                                                     ::SMESH_Gen*            theGenImpl )
-     : SALOME::GenericObj_i( thePOA ), 
-       SMESH_Hypothesis_i( thePOA )
+  : SALOME::GenericObj_i( thePOA ),
+    SMESH_Hypothesis_i( thePOA )
 {
   MESSAGE( "StdMeshers_Propagation_i::StdMeshers_Propagation_i" );
   myBaseImpl = new ::StdMeshers_Propagation(theGenImpl->GetANewId(),
@@ -52,41 +51,49 @@ StdMeshers_Propagation_i::StdMeshers_Propagation_i (PortableServer::POA_ptr theP
                                             theGenImpl);
 }
 
-//=============================================================================
+//================================================================================
 /*!
- *  StdMeshers_Propagation_i::~StdMeshers_Propagation_i
+ * \brief Verify whether hypothesis supports given entity type
+ * \param type - dimension (see SMESH::Dimension enumeration)
+ * \retval CORBA::Boolean - TRUE if dimension is supported, FALSE otherwise
  *
- *  Destructor
+ * Verify whether hypothesis supports given entity type (see SMESH::Dimension enumeration)
  */
-//=============================================================================
-StdMeshers_Propagation_i::~StdMeshers_Propagation_i()
+//================================================================================
+CORBA::Boolean StdMeshers_Propagation_i::IsDimSupported( SMESH::Dimension type )
 {
-  MESSAGE( "StdMeshers_Propagation_i::~StdMeshers_Propagation_i" );
+  return type == SMESH::DIM_1D;
 }
 
 //=============================================================================
 /*!
- *  StdMeshers_Propagation_i::GetImpl
+ *  StdMeshers_PropagOfDistribution_i::StdMeshers_PropagOfDistribution_i
  *
- *  Get implementation
+ *  Constructor
  */
 //=============================================================================
-::StdMeshers_Propagation* StdMeshers_Propagation_i::GetImpl()
+StdMeshers_PropagOfDistribution_i::
+StdMeshers_PropagOfDistribution_i (PortableServer::POA_ptr thePOA,
+                                   int                     theStudyId,
+                                   ::SMESH_Gen*            theGenImpl )
+  : SALOME::GenericObj_i( thePOA ),
+    SMESH_Hypothesis_i( thePOA )
 {
-  MESSAGE( "StdMeshers_Propagation_i::GetImpl" );
-  return ( ::StdMeshers_Propagation* )myBaseImpl;
+  myBaseImpl = new ::StdMeshers_PropagOfDistribution(theGenImpl->GetANewId(),
+                                                     theStudyId,
+                                                     theGenImpl);
 }
 
 //================================================================================
 /*!
- * \brief Verify whether hypothesis supports given entity type 
 * \param type - dimension (see SMESH::Dimension enumeration)
 * \retval CORBA::Boolean - TRUE if dimension is supported, FALSE otherwise
- * 
+ * \brief Verify whether hypothesis supports given entity type
+ * \param type - dimension (see SMESH::Dimension enumeration)
+ * \retval CORBA::Boolean - TRUE if dimension is supported, FALSE otherwise
+ *
  * Verify whether hypothesis supports given entity type (see SMESH::Dimension enumeration)
  */
-//================================================================================  
-CORBA::Boolean StdMeshers_Propagation_i::IsDimSupported( SMESH::Dimension type )
+//================================================================================
+CORBA::Boolean StdMeshers_PropagOfDistribution_i::IsDimSupported( SMESH::Dimension type )
 {
   return type == SMESH::DIM_1D;
 }
index 0b303abfda90c1ad3304ea3c50376fde98be984b..19b35e9f9a46a54f4866ad394727444622e81fc5 100644 (file)
@@ -23,7 +23,6 @@
 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
 //  File   : StdMeshers_Propagation_i.hxx
 //  Module : SMESH
-//  $Header$
 //
 #ifndef _SMESH_PROPAGATION_I_HXX_
 #define _SMESH_PROPAGATION_I_HXX_
@@ -41,6 +40,7 @@ class SMESH_Gen;
 // ======================================================
 // Propagation hypothesis
 // ======================================================
+
 class STDMESHERS_I_EXPORT StdMeshers_Propagation_i:
   public virtual POA_StdMeshers::StdMeshers_Propagation,
   public virtual SMESH_Hypothesis_i
@@ -50,11 +50,24 @@ public:
   StdMeshers_Propagation_i (PortableServer::POA_ptr thePOA,
                             int                     theStudyId,
                             ::SMESH_Gen*            theGenImpl);
-  // Destructor
-  virtual ~StdMeshers_Propagation_i();
+  
+  // Verify whether hypothesis supports given entity type 
+  CORBA::Boolean IsDimSupported( SMESH::Dimension type );
+};
+
+// ======================================================
+// Propagation of Distribution hypothesis
+// ======================================================
 
-  // Get implementation
-  ::StdMeshers_Propagation* GetImpl();
+class STDMESHERS_I_EXPORT StdMeshers_PropagOfDistribution_i:
+  public virtual POA_StdMeshers::StdMeshers_PropagOfDistribution,
+  public virtual SMESH_Hypothesis_i
+{
+public:
+  // Constructor
+  StdMeshers_PropagOfDistribution_i (PortableServer::POA_ptr thePOA,
+                                     int                     theStudyId,
+                                     ::SMESH_Gen*            theGenImpl);
   
   // Verify whether hypothesis supports given entity type 
   CORBA::Boolean IsDimSupported( SMESH::Dimension type );
index ba32f927ae638baf9cb653b3e6f6594704cc5196..2c2c3ac5429fd3c38b2cd5f5ca4c45b7f8b63ec3 100644 (file)
 //  Module : SMESH
 
 #include "StdMeshers_QuadrangleParams_i.hxx"
-#include "SMESH_Gen_i.hxx"
+
 #include "SMESH_Gen.hxx"
+#include "SMESH_Gen_i.hxx"
 #include "SMESH_PythonDump.hxx"
+#include "StdMeshers_ObjRefUlils.hxx"
 
-#include "Utils_CorbaException.hxx"
-#include "utilities.h"
+#include <Utils_CorbaException.hxx>
+#include <utilities.h>
 
-#include <TCollection_AsciiString.hxx>
+#include <Standard_ErrorHandler.hxx>
+#include "SMESH_TryCatch.hxx"
 
 using namespace std;
 
@@ -82,13 +85,11 @@ void StdMeshers_QuadrangleParams_i::SetTriaVertex(CORBA::Long vertID)
     this->GetImpl()->SetTriaVertex( vertID );
   }
   catch ( SALOME_Exception& S_ex ) {
-    THROW_SALOME_CORBA_EXCEPTION( S_ex.what(),
-                                  SALOME::BAD_PARAM );
+    THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), SALOME::BAD_PARAM );
   }
 
   // Update Python script
-  SMESH::TPythonDump() << _this() << ".SetTriaVertex( "
-      << vertID << " )";
+  SMESH::TPythonDump() << _this() << ".SetTriaVertex( " << vertID << " )";
 }
 
 //=============================================================================
@@ -147,8 +148,7 @@ char* StdMeshers_QuadrangleParams_i::GetObjectEntry()
     entry = this->GetImpl()->GetObjectEntry();
   }
   catch ( SALOME_Exception& S_ex ) {
-    THROW_SALOME_CORBA_EXCEPTION( S_ex.what(),
-                                  SALOME::BAD_PARAM );
+    THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), SALOME::BAD_PARAM );
   }
   return CORBA::string_dup( entry );
 }
@@ -162,12 +162,6 @@ char* StdMeshers_QuadrangleParams_i::GetObjectEntry()
 //=============================================================================
 void StdMeshers_QuadrangleParams_i::SetQuadType(StdMeshers::QuadType type)
 {
-  //static char* quadTypes[5] = {"StdMeshers.QUAD_STANDARD",
-  //                             "StdMeshers.QUAD_TRIANGLE_PREF",
-  //                             "StdMeshers.QUAD_QUADRANGLE_PREF",
-  //                             "StdMeshers.QUAD_QUADRANGLE_PREF_REVERSED",
-  //                             "StdMeshers.QUAD_REDUCED"};
-
   MESSAGE("StdMeshers_QuadrangleParams_i::SetQuadType");
   ASSERT(myBaseImpl);
 
@@ -199,7 +193,6 @@ void StdMeshers_QuadrangleParams_i::SetQuadType(StdMeshers::QuadType type)
     quadType = "UNKNOWN";
   }
   SMESH::TPythonDump() << _this() << ".SetQuadType( " << quadType << " )";
-  //SMESH::TPythonDump() << _this() << ".SetQuadType( " << quadTypes[int(type)] << " )";
 }
 
 //=============================================================================
@@ -216,6 +209,100 @@ StdMeshers::QuadType StdMeshers_QuadrangleParams_i::GetQuadType()
   return StdMeshers::QuadType(int(this->GetImpl()->GetQuadType()));
 }
 
+//================================================================================
+/*!
+ * \brief Set positions of enforced nodes
+ */
+//================================================================================
+
+void StdMeshers_QuadrangleParams_i::SetEnforcedNodes(const GEOM::ListOfGO&     theVertices,
+                                                     const SMESH::nodes_array& thePoints)
+  throw ( SALOME::SALOME_Exception )
+{
+  try {
+    std::vector< TopoDS_Shape > shapes;
+    std::vector< gp_Pnt       > points;
+    shapes.reserve( theVertices.length() );
+    points.reserve( thePoints.length() );
+
+    myShapeEntries.clear();
+
+    for ( size_t i = 0; i < theVertices.length(); ++i )
+    {
+      if ( CORBA::is_nil( theVertices[i] ))
+        continue;
+      CORBA::String_var entry = theVertices[i]->GetStudyEntry();
+      if ( !entry.in() || !entry.in()[0] )
+        THROW_SALOME_CORBA_EXCEPTION( "Not published enforced vertex shape", SALOME::BAD_PARAM );
+
+      shapes.push_back( StdMeshers_ObjRefUlils::GeomObjectToShape( theVertices[i].in() ));
+      myShapeEntries.push_back( entry.in() );
+    }
+    for ( size_t i = 0; i < thePoints.length(); ++i )
+    {
+      points.push_back( gp_Pnt( thePoints[i].x, thePoints[i].y, thePoints[i].z ));
+    }
+    this->GetImpl()->SetEnforcedNodes( shapes, points );
+  }
+  catch ( SALOME_Exception& S_ex ) {
+    THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), SALOME::BAD_PARAM );
+  }
+  // Update Python script
+  SMESH::TPythonDump() << _this() << ".SetEnforcedNodes( "
+                       << theVertices << ", " << thePoints << " )";
+}
+  
+//================================================================================
+/*!
+ * \brief Returns positions of enforced nodes
+ */
+//================================================================================
+
+void StdMeshers_QuadrangleParams_i::GetEnforcedNodes(GEOM::ListOfGO_out     theVertices,
+                                                     SMESH::nodes_array_out thePoints)
+{
+  SMESH_TRY;
+
+  std::vector< TopoDS_Shape > shapes;
+  std::vector< gp_Pnt       > points;
+  this->GetImpl()->GetEnforcedNodes( shapes, points );
+
+  theVertices = new GEOM::ListOfGO;
+  thePoints   = new SMESH::nodes_array;
+
+  size_t i = 0;
+  theVertices->length( myShapeEntries.size() );
+  for ( i = 0; i < myShapeEntries.size(); ++i )
+    theVertices[i] =
+      StdMeshers_ObjRefUlils::EntryOrShapeToGeomObject( myShapeEntries[i], shapes[i] );
+
+  thePoints->length( points.size() );
+  for ( i = 0; i < points.size(); ++i )
+  {
+    thePoints[i].x = points[i].X();
+    thePoints[i].y = points[i].Y();
+    thePoints[i].z = points[i].Z();
+  }
+  SMESH_CATCH( SMESH::doNothing );
+}
+
+//================================================================================
+/*!
+ * \brief Returns study entries of shapes defining enforced nodes
+ */
+//================================================================================
+
+SMESH::string_array* StdMeshers_QuadrangleParams_i::GetEnfVertices()
+{
+  SMESH::string_array_var arr = new SMESH::string_array;
+  arr->length( myShapeEntries.size() );
+
+  for ( size_t i = 0; i < myShapeEntries.size(); ++i )
+    arr[ i ] = myShapeEntries[ i ].c_str();
+
+  return arr._retn();
+}
+
 //=============================================================================
 /*!
  *  StdMeshers_QuadrangleParams_i::GetImpl
@@ -243,3 +330,58 @@ CORBA::Boolean StdMeshers_QuadrangleParams_i::IsDimSupported( SMESH::Dimension t
 {
   return type == SMESH::DIM_2D;
 }
+
+//================================================================================
+/*!
+ * \brief Write parameters in a string
+  * \retval char* - resulting string
+ */
+//================================================================================
+
+char* StdMeshers_QuadrangleParams_i::SaveTo()
+{
+  ASSERT( myBaseImpl );
+  std::ostringstream os;
+
+  os << "ENTRIES: " << myShapeEntries.size();
+  for ( size_t i = 0; i < myShapeEntries.size(); ++i )
+    StdMeshers_ObjRefUlils::SaveToStream( myShapeEntries[ i ], os );
+  os << " ";
+
+  myBaseImpl->SaveTo( os );
+
+  return CORBA::string_dup( os.str().c_str() );
+}
+
+//================================================================================
+/*!
+ * \brief Retrieve parameters from the string
+  * \param theStream - the input string
+ */
+//================================================================================
+
+void StdMeshers_QuadrangleParams_i::LoadFrom( const char* theStream )
+{
+  ASSERT( myBaseImpl );
+
+  bool hasEntries = ( strncmp( "ENTRIES: ", theStream, 9 ) == 0 );
+  std::istringstream is( theStream + ( hasEntries ? 9 : 0 ));
+
+  if ( hasEntries )
+  {
+    int nb = 0;
+    if ( is >> nb && nb > 0 )
+    {
+      std::vector< TopoDS_Shape > shapes;
+      std::vector< gp_Pnt >       points;
+      myShapeEntries.resize( nb );
+
+      for ( int i = 0; i < nb; ++i )
+        shapes.push_back( StdMeshers_ObjRefUlils::LoadFromStream( is, & myShapeEntries[i] ));
+
+      GetImpl()->SetEnforcedNodes( shapes, points );
+    }
+  }
+
+  myBaseImpl->LoadFrom( is );
+}
index 4596712a0deda887074e0f92ac761f2056bf56bd..6a6e645d55dfb1615aa060910586d501b20d9c25 100644 (file)
@@ -19,7 +19,6 @@
 //  File   : StdMeshers_QuadrangleParams_i.hxx
 //  Author : Sergey KUUL, OCC
 //  Module : SMESH
-//  $Header$
 
 #ifndef _SMESH_QUADRANGLEPARAMS_I_HXX_
 #define _SMESH_QUADRANGLEPARAMS_I_HXX_
@@ -47,13 +46,6 @@ public:
   // Destructor
   virtual ~StdMeshers_QuadrangleParams_i();
 
-  // Set length
-  //void SetLength( CORBA::Double theLength, CORBA::Boolean theIsStart )
-  //  throw ( SALOME::SALOME_Exception );
-
-  // Get length
-  //CORBA::Double GetLength(CORBA::Boolean theIsStart);
-
   // Set base vertex for triangles
   void SetTriaVertex (CORBA::Long vertID);
 
@@ -72,11 +64,31 @@ public:
   // Get the type of quadrangulation
   StdMeshers::QuadType GetQuadType();
 
+  // Set positions of enforced nodes
+  void SetEnforcedNodes(const GEOM::ListOfGO&     vertices,
+                        const SMESH::nodes_array& points) throw ( SALOME::SALOME_Exception );
+  
+  // Returns positions of enforced nodes
+  void GetEnforcedNodes(GEOM::ListOfGO_out vertices, SMESH::nodes_array_out points);
+
+  // Returns entries of shapes defining enforced nodes
+  SMESH::string_array* GetEnfVertices();
+
+
   // Get implementation
   ::StdMeshers_QuadrangleParams* GetImpl();
   
   // Verify whether hypothesis supports given entity type 
   CORBA::Boolean IsDimSupported( SMESH::Dimension type );
+
+  // Redefined Persistence
+  virtual char* SaveTo();
+  virtual void  LoadFrom( const char* theStream );
+
+ protected:
+
+  std::vector<std::string> myShapeEntries;
+  
 };
 
 #endif
diff --git a/src/StdMeshers_I/StdMeshers_Reversible1D_i.cxx b/src/StdMeshers_I/StdMeshers_Reversible1D_i.cxx
new file mode 100644 (file)
index 0000000..20a8c9d
--- /dev/null
@@ -0,0 +1,143 @@
+// Copyright (C) 2007-2013  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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
+//  File   : StdMeshers_Reversible1D_i.cxx
+//  Module : SMESH
+//
+#include "StdMeshers_Reversible1D_i.hxx"
+#include "SMESH_PythonDump.hxx"
+
+#include <Utils_CorbaException.hxx>
+#include <utilities.h>
+
+#include CORBA_SERVER_HEADER(SMESH_Hypothesis)
+
+//================================================================================
+/*!
+ * \brief Constructor
+ */
+//================================================================================
+
+StdMeshers_Reversible1D_i::StdMeshers_Reversible1D_i( SMESH_Hypothesis_i* reversible )
+  : myHyp( reversible )
+{
+}
+
+//=============================================================================
+/*!
+ *  StdMeshers_Reversible1D_i::SetReversedEdges
+ *
+ *  Set edges to reverse
+ */
+//=============================================================================
+
+void StdMeshers_Reversible1D_i::SetReversedEdges( const SMESH::long_array& theIds )
+{
+  try {
+    std::vector<int> ids( theIds.length() );
+    CORBA::Long iEnd = theIds.length();
+    for ( CORBA::Long i = 0; i < iEnd; i++ )
+      ids[ i ] = theIds[ i ];
+
+    this->GetImpl()->SetReversedEdges( ids );
+  }
+  catch ( SALOME_Exception& S_ex ) {
+    THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), SALOME::BAD_PARAM );
+  }
+
+  // Update Python script
+  SMESH::TPythonDump() << myHyp->_this() << ".SetReversedEdges( " << theIds << " )";
+}
+
+//=============================================================================
+/*!
+ *  StdMeshers_Reversible1D_i::SetObjectEntry
+ *
+ *  Set the Entry for the Main Object
+ */
+//=============================================================================
+
+void StdMeshers_Reversible1D_i::SetObjectEntry( const char* theEntry )
+{
+  string entry(theEntry); // actually needed as theEntry is spoiled by moment of dumping
+  try {
+    this->GetImpl()->SetObjectEntry( entry.c_str() );
+    // Update Python script
+    SMESH::TPythonDump() << myHyp->_this() << ".SetObjectEntry( \"" << entry.c_str() << "\" )";
+  }
+  catch ( SALOME_Exception& S_ex ) {
+    THROW_SALOME_CORBA_EXCEPTION( S_ex.what(),SALOME::BAD_PARAM );
+  }
+}
+
+//=============================================================================
+/*!
+ *  StdMeshers_Reversible1D_i::GetObjectEntry
+ *
+ *  Set the Entry for the Main Object
+ */
+//=============================================================================
+
+char* StdMeshers_Reversible1D_i::GetObjectEntry()
+{
+  const char* entry;
+  try {
+    entry = this->GetImpl()->GetObjectEntry();
+  }
+  catch ( SALOME_Exception& S_ex ) {
+    THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), SALOME::BAD_PARAM );
+  }
+  return CORBA::string_dup( entry );
+}
+
+//=============================================================================
+/*!
+ *  StdMeshers_Reversible1D_i::GetReversedEdges
+ *
+ *  Get reversed edges
+ */
+//=============================================================================
+
+SMESH::long_array* StdMeshers_Reversible1D_i::GetReversedEdges()
+{
+  SMESH::long_array_var anArray = new SMESH::long_array;
+  std::vector<int> ids = this->GetImpl()->GetReversedEdges();
+  anArray->length( ids.size() );
+  for ( CORBA::Long i = 0; i < ids.size(); i++)
+    anArray [ i ] = ids [ i ];
+
+  return anArray._retn();
+}
+
+//=============================================================================
+/*!
+ *  StdMeshers_Reversible1D_i::GetImpl
+ *
+ *  Get implementation
+ */
+//=============================================================================
+
+::StdMeshers_Reversible1D* StdMeshers_Reversible1D_i::GetImpl()
+{
+  return ( ::StdMeshers_Reversible1D* )myHyp->GetImpl();
+}
diff --git a/src/StdMeshers_I/StdMeshers_Reversible1D_i.hxx b/src/StdMeshers_I/StdMeshers_Reversible1D_i.hxx
new file mode 100644 (file)
index 0000000..8d47a7c
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright (C) 2007-2013  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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
+//  File   : StdMeshers_Reversible1D_i.hxx
+//  Module : SMESH
+//
+#ifndef _SMESH_Reversible1D_I_HXX_
+#define _SMESH_Reversible1D_I_HXX_
+
+#include "SMESH_StdMeshers_I.hxx"
+
+#include <SALOMEconfig.h>
+#include CORBA_SERVER_HEADER(SMESH_BasicHypothesis)
+
+#include "SMESH_Hypothesis_i.hxx"
+#include "StdMeshers_Reversible1D.hxx"
+
+// ======================================================
+// Common metrhods of Reversible 1D hypotheses
+// ======================================================
+class STDMESHERS_I_EXPORT StdMeshers_Reversible1D_i:
+  public virtual POA_StdMeshers::Reversible1D
+{
+ public:
+  StdMeshers_Reversible1D_i( SMESH_Hypothesis_i* reversible );
+
+  //Set Reversed Edges
+  void SetReversedEdges( const SMESH::long_array& theIDs);
+
+  //Get Reversed Edges
+  SMESH::long_array*  GetReversedEdges();
+
+  //Set the Entry of the Object
+  void SetObjectEntry( const char* theEntry);
+
+  //Get Object Entry
+  char* GetObjectEntry();
+
+  // Get implementation
+  ::StdMeshers_Reversible1D* GetImpl();
+
+ private:
+  SMESH_Hypothesis_i* myHyp;
+};
+
+#endif
index 5ad82c7ecbb22ef1dd9b8a2c8d775b25ccc0f63c..8b3050421a82502b35e61b39fd961d553994721a 100644 (file)
@@ -78,15 +78,18 @@ StdMeshers_ViscousLayers_i::~StdMeshers_ViscousLayers_i()
  */
 //================================================================================
 
-void StdMeshers_ViscousLayers_i::SetIgnoreFaces(const ::SMESH::long_array& faceIDs)
-throw ( SALOME::SALOME_Exception )
+void StdMeshers_ViscousLayers_i::SetFaces(const ::SMESH::long_array& faceIDs,
+                                          CORBA::Boolean             toIgnore)
+  throw ( SALOME::SALOME_Exception )
 {
   vector<int> ids( faceIDs.length() );
   for ( unsigned i = 0; i < ids.size(); ++i )
     if (( ids[i] = faceIDs[i] ) < 1 )
       THROW_SALOME_CORBA_EXCEPTION( "Invalid face id", SALOME::BAD_PARAM );
-  GetImpl()->SetBndShapes( ids, /*toIgnore=*/true );
-  SMESH::TPythonDump() << _this() << ".SetIgnoreFaces( " << faceIDs << " )";
+
+  GetImpl()->SetBndShapes( ids, toIgnore );
+
+  SMESH::TPythonDump() << _this() << ".SetFaces( " << faceIDs << ", " << toIgnore << " )";
 }
 
 //================================================================================
@@ -95,16 +98,13 @@ throw ( SALOME::SALOME_Exception )
  */
 //================================================================================
 
-SMESH::long_array* StdMeshers_ViscousLayers_i::GetIgnoreFaces()
+SMESH::long_array* StdMeshers_ViscousLayers_i::GetFaces()
 {
+  vector<int> idsVec = GetImpl()->GetBndShapes();
   SMESH::long_array_var ids = new SMESH::long_array;
-  if ( GetImpl()->IsToIgnoreShapes() )
-  {
-    vector<int> idsVec = GetImpl()->GetBndShapes();
-    ids->length( idsVec.size() );
-    for ( unsigned i = 0; i < idsVec.size(); ++i )
-      ids[i] = idsVec[i];
-  }
+  ids->length( idsVec.size() );
+  for ( unsigned i = 0; i < idsVec.size(); ++i )
+    ids[i] = idsVec[i];
   return ids._retn();
 }
 
@@ -114,6 +114,47 @@ SMESH::long_array* StdMeshers_ViscousLayers_i::GetIgnoreFaces()
  */
 //================================================================================
 
+SMESH::long_array* StdMeshers_ViscousLayers_i::GetIgnoreFaces()
+{
+  if ( GetImpl()->IsToIgnoreShapes() )
+    return this->GetFaces();
+  return new SMESH::long_array;
+}
+
+//================================================================================
+/*!
+ * \brief 
+ */
+//================================================================================
+
+CORBA::Boolean StdMeshers_ViscousLayers_i::GetIsToIgnoreFaces()
+{
+  return GetImpl()->IsToIgnoreShapes();
+}
+
+//================================================================================
+/*!
+ * \brief 
+ */
+//================================================================================
+
+void StdMeshers_ViscousLayers_i::SetIgnoreFaces(const ::SMESH::long_array& faceIDs)
+throw ( SALOME::SALOME_Exception )
+{
+  vector<int> ids( faceIDs.length() );
+  for ( unsigned i = 0; i < ids.size(); ++i )
+    if (( ids[i] = faceIDs[i] ) < 1 )
+      THROW_SALOME_CORBA_EXCEPTION( "Invalid face id", SALOME::BAD_PARAM );
+  GetImpl()->SetBndShapes( ids, /*toIgnore=*/true );
+  SMESH::TPythonDump() << _this() << ".SetIgnoreFaces( " << faceIDs << " )";
+}
+
+//================================================================================
+/*!
+ * \brief 
+ */
+//================================================================================
+
 void StdMeshers_ViscousLayers_i::SetTotalThickness(::CORBA::Double thickness)
 throw ( SALOME::SALOME_Exception )
 {
index 59c8d324c2098c2d3c931d95368359127fc91b1a..9a6b760e35b18298d9481879659cfe854a327e35 100644 (file)
@@ -51,6 +51,11 @@ class STDMESHERS_I_EXPORT StdMeshers_ViscousLayers_i:
   void SetIgnoreFaces(const ::SMESH::long_array& faceIDs) throw ( SALOME::SALOME_Exception );
   SMESH::long_array* GetIgnoreFaces();
 
+  void SetFaces(const SMESH::long_array& faceIDs,
+                CORBA::Boolean           toIgnore) throw (SALOME::SALOME_Exception);
+  SMESH::long_array* GetFaces();
+  CORBA::Boolean     GetIsToIgnoreFaces();
+
   void SetTotalThickness(::CORBA::Double thickness) throw ( SALOME::SALOME_Exception );
   ::CORBA::Double GetTotalThickness();
 
index 3cc3ac0507f6d5c96828e1ffecb2753354937aec..2d98e11c4cd803aef245399b3c4ffe941f9cf502 100644 (file)
@@ -35,6 +35,7 @@
 #include "StdMeshers_AutomaticLength_i.hxx"
 #include "StdMeshers_StartEndLength_i.hxx"
 #include "StdMeshers_Arithmetic1D_i.hxx"
+#include "StdMeshers_Geometric1D_i.hxx"
 #include "StdMeshers_FixedPoints1D_i.hxx"
 #include "StdMeshers_NumberOfSegments_i.hxx"
 #include "StdMeshers_Deflection1D_i.hxx"
@@ -136,6 +137,8 @@ STDMESHERS_I_EXPORT
       aCreator = new StdHypothesisCreator_i<StdMeshers_NotConformAllowed_i>;
     else if (strcmp(aHypName, "Propagation") == 0)
       aCreator = new StdHypothesisCreator_i<StdMeshers_Propagation_i>;
+    else if (strcmp(aHypName, "PropagOfDistribution") == 0)
+      aCreator = new StdHypothesisCreator_i<StdMeshers_PropagOfDistribution_i>;
     else if (strcmp(aHypName, "MaxElementArea") == 0)
       aCreator = new StdHypothesisCreator_i<StdMeshers_MaxElementArea_i>;
     else if (strcmp(aHypName, "MaxElementVolume") == 0)
@@ -150,6 +153,8 @@ STDMESHERS_I_EXPORT
       aCreator = new StdHypothesisCreator_i<StdMeshers_FixedPoints1D_i>;
     else if (strcmp(aHypName, "Arithmetic1D") == 0)
       aCreator = new StdHypothesisCreator_i<StdMeshers_Arithmetic1D_i>;
+    else if (strcmp(aHypName, "GeometricProgression") == 0)
+      aCreator = new StdHypothesisCreator_i<StdMeshers_Geometric1D_i>;
     else if (strcmp(aHypName, "AutomaticLength") == 0)
       aCreator = new StdHypothesisCreator_i<StdMeshers_AutomaticLength_i>;
     else if (strcmp(aHypName, "QuadranglePreference") == 0)