Salome HOME
Merge from V5_1_5_BR branch 12/11/2010
authorvsr <vsr@opencascade.com>
Fri, 12 Nov 2010 14:22:21 +0000 (14:22 +0000)
committervsr <vsr@opencascade.com>
Fri, 12 Nov 2010 14:22:21 +0000 (14:22 +0000)
86 files changed:
configure.ac
doc/docutils/Makefile.am
doc/salome/gui/SMESH/Makefile.am
doc/salome/gui/SMESH/doxyfile_py.in
doc/salome/gui/SMESH/images/2d_from_3d_dlg.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/2d_from_3d_ico.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/2d_from_3d_menu.png
doc/salome/gui/SMESH/images/a-averagelength.png
doc/salome/gui/SMESH/images/hypo_quad_params_dialog.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/netgen3d_simple.png
doc/salome/gui/SMESH/input/1d_meshing_hypo.doc
doc/salome/gui/SMESH/input/2d_meshing_hypo.doc
doc/salome/gui/SMESH/input/about_filters.doc
doc/salome/gui/SMESH/input/about_hypo.doc
doc/salome/gui/SMESH/input/adding_nodes_and_elements.doc
doc/salome/gui/SMESH/input/adding_quadratic_elements.doc
doc/salome/gui/SMESH/input/additional_hypo.doc
doc/salome/gui/SMESH/input/creating_groups.doc
doc/salome/gui/SMESH/input/double_nodes_page.doc
doc/salome/gui/SMESH/input/index.doc
doc/salome/gui/SMESH/input/make_2dmesh_from_3d.doc
doc/salome/gui/SMESH/input/modifying_meshes.doc
doc/salome/gui/SMESH/input/netgen_2d_3d_hypo.doc
doc/salome/gui/SMESH/input/pattern_mapping.doc
doc/salome/gui/SMESH/input/removing_nodes_and_elements.doc
doc/salome/gui/SMESH/input/selection_filter_library.doc
doc/salome/gui/SMESH/input/tui_defining_hypotheses.doc
doc/salome/gui/SMESH/input/tui_filters.doc
doc/salome/gui/SMESH/input/tui_transforming_meshes.doc
idl/SMESH_BasicHypothesis.idl
idl/SMESH_Filter.idl
idl/SMESH_MeshEditor.idl
resources/Makefile.am
resources/SalomeApp.xml
resources/StdMeshers.xml
resources/mesh_quadrangle_quadpref.png [new file with mode: 0644]
resources/mesh_quadrangle_quadpref_reversed.png [new file with mode: 0644]
resources/mesh_quadrangle_reduced.png [new file with mode: 0644]
resources/mesh_quadrangle_standard.png [new file with mode: 0644]
resources/mesh_quadrangle_triapref.png [new file with mode: 0644]
src/Controls/SMESH_Controls.cxx
src/Controls/SMESH_ControlsDef.hxx
src/SMESH/SMESH_HypoFilter.cxx
src/SMESH/SMESH_HypoFilter.hxx
src/SMESH/SMESH_MeshEditor.cxx
src/SMESH/SMESH_MeshEditor.hxx
src/SMESH/SMESH_MesherHelper.cxx
src/SMESH/SMESH_MesherHelper.hxx
src/SMESHGUI/SMESHGUI.cxx
src/SMESHGUI/SMESHGUI.h
src/SMESHGUI/SMESHGUI_ComputeDlg.cxx
src/SMESHGUI/SMESHGUI_FilterDlg.cxx
src/SMESHGUI/SMESHGUI_GroupOnShapeDlg.cxx
src/SMESHGUI/SMESHGUI_Make2DFrom3DOp.cxx
src/SMESHGUI/SMESHGUI_Make2DFrom3DOp.h
src/SMESHGUI/SMESHGUI_MeshUtils.cxx
src/SMESHGUI/SMESHGUI_MeshUtils.h
src/SMESHGUI/SMESH_msg_en.ts
src/SMESHGUI/SMESH_msg_fr.ts
src/SMESH_I/SMESH_DumpPython.cxx
src/SMESH_I/SMESH_Filter_i.cxx
src/SMESH_I/SMESH_Filter_i.hxx
src/SMESH_I/SMESH_Gen_i.cxx
src/SMESH_I/SMESH_Group_i.cxx
src/SMESH_I/SMESH_MeshEditor_i.cxx
src/SMESH_I/SMESH_MeshEditor_i.hxx
src/SMESH_I/SMESH_Mesh_i.cxx
src/SMESH_I/SMESH_Pattern_i.cxx
src/SMESH_I/SMESH_subMesh_i.cxx
src/SMESH_SWIG/smeshDC.py
src/StdMeshers/StdMeshers_FaceSide.cxx
src/StdMeshers/StdMeshers_QuadToTriaAdaptor.cxx
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/StdMeshersGUI/Makefile.am
src/StdMeshersGUI/StdMeshersGUI_NbSegmentsCreator.h
src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.cxx [new file with mode: 0644]
src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.h [new file with mode: 0644]
src/StdMeshersGUI/StdMeshersGUI_StdHypothesisCreator.cxx
src/StdMeshersGUI/StdMeshers_images.ts
src/StdMeshersGUI/StdMeshers_msg_en.ts
src/StdMeshers_I/StdMeshers_QuadrangleParams_i.cxx
src/StdMeshers_I/StdMeshers_QuadrangleParams_i.hxx

index 6551e4b4fe6ad4d0bbf547b9a5e19a5af1e61cdd..c388519f273a9e5a7d674b79d325f9e571bfb441 100644 (file)
@@ -24,7 +24,7 @@
 # Modified by : Alexander BORODIN (OCN) - autotools usage
 # Created from configure.in.base
 #
-AC_INIT([Salome2 Project SMESH module], [5.1.4], [webmaster.salome@opencascade.com], [SalomeSMESH])
+AC_INIT([Salome2 Project SMESH module], [5.1.5], [webmaster.salome@opencascade.com], [SalomeSMESH])
 AC_CONFIG_AUX_DIR(adm_local/unix/config_files)
 AC_CANONICAL_HOST
 AC_CANONICAL_TARGET
@@ -434,6 +434,19 @@ echo
 #  chmod +x ./bin/salome/*; \
 #])
 
+AC_CONFIG_COMMANDS([hack_libtool],[
+sed -i "s%^CC=\"\(.*\)\"%hack_libtool (){ \n\
+  if test \"\$(echo \$[@] | grep -E '\\\-L/usr/lib(/../lib)?(64)? ')\" == \"\" \n\
+  then\n\
+    cmd=\"\1 \$[@]\"\n\
+  else\n\
+    cmd=\"\1 \"\`echo \$[@] | sed -r -e 's|(.*)-L/usr/lib(/../lib)?(64)? (.*)|\\\1\\\4 -L/usr/lib\\\3|g'\`\n\
+  fi\n\
+  \$cmd\n\
+}\n\
+CC=\"hack_libtool\"%g" libtool
+],[])
+
 # This list is initiated using autoscan and must be updated manually
 # when adding a new file <filename>.in to manage. When you execute
 # autoscan, the Makefile list is generated in the output file configure.scan.
@@ -485,5 +498,3 @@ AC_OUTPUT([ \
   idl/Makefile \
   Makefile
 ])
-
-AC_HACK_LIBTOOL
index e1698bb9e827ca407bb3d7a535ed29bd746bdc9e..a757dd6f74ced5a9ebf18df7a2d1adcd41f530ab 100644 (file)
@@ -39,7 +39,7 @@ SPHINXBUILD     = sphinx-build
 PAPEROPT_a4     = -D latex_paper_size=a4
 ALLSPHINXOPTS   = -d doctrees $(PAPEROPT_a4) $(SPHINXOPTS) $(SOURCEDIR)
 
-SPHINX_PYTHONPATH = $(prefix)/lib/python$(PYTHON_VERSION)/site-packages/salome:$(KERNEL_ROOT_DIR)/bin/salome:$(KERNEL_ROOT_DIR)/lib/python$(PYTHON_VERSION)/site-packages/salome:$(OMNIORB_ROOT)/lib/python$(PYTHON_VERSION)/site-packages
+SPHINX_PYTHONPATH = $(prefix)/lib/python$(PYTHON_VERSION)/site-packages/salome:$(prefix)/lib64/python$(PYTHON_VERSION)/site-packages/salome:$(KERNEL_ROOT_DIR)/bin/salome:$(KERNEL_ROOT_DIR)/lib/python$(PYTHON_VERSION)/site-packages/salome:$(KERNEL_ROOT_DIR)/lib64/python$(PYTHON_VERSION)/site-packages/salome:$(OMNIORB_ROOT)/lib/python$(PYTHON_VERSION)/site-packages:$(OMNIORB_ROOT)/lib64/python$(PYTHON_VERSION)/site-packages
 
 SPHINX_LD_LIBRARY_PATH = $(KERNEL_ROOT_DIR)/lib/salome:$(OMNIORB_ROOT)/lib
 
index 40503e04e4e18ab971de1119122c096cc438c968..1bb1e9beeb5951b492bb0ab8592dd14cb023bef6 100755 (executable)
@@ -31,23 +31,21 @@ guidoc_DATA = images/head.png
 
 
 usr_docs: doxyfile_py doxyfile 
-       echo "===========================================" ;            \
-       echo "Generating Python interface documentation";               \
-       echo "===========================================" ;            \
-       $(DOXYGEN) doxyfile_py ;                                        \
-       echo "===========================================" ;            \
-       echo "Replacing smeshDC by smesh" ;                             \
-       echo "===========================================" ;            \
-       files=`find smeshpy_doc -type f` ;                              \
-       for filen in $${files} ; do                                     \
-         sed -e "s/\<smeshDC\>/smesh/g" -e "s/smesh\.smesh/smesh/g"    \
-             -e "s/smesh::smesh/smesh/g" $${filen} > $${filen}_ ;      \
-         mv -f $${filen}_ $${filen} ;                                  \
-       done ;                                                          \
-       echo "===========================================" ;            \
-       echo "Generating GUI documentation" ;                           \
-       echo "===========================================" ;            \
-       $(DOXYGEN) doxyfile ;
+       echo "===========================================" ;                    \
+       echo "Replacing smeshDC by smesh" ;                                     \
+       echo "===========================================" ;                    \
+       sed -e "/class smeshDC/d" -e "s/^ *#/#/g" -e "s/^ *def /def /g"         \
+         -e "s/smeshDC/smesh/g" $(top_srcdir)/src/SMESH_SWIG/smeshDC.py >      \
+         $(top_builddir)/src/SMESH_SWIG/smesh.py ;                             \
+       echo "===========================================" ;                    \
+       echo "Generating Python interface documentation";                       \
+       echo "===========================================" ;                    \
+       $(DOXYGEN) doxyfile_py ;                                                \
+       echo "===========================================" ;                    \
+       echo "Generating GUI documentation" ;                                   \
+       echo "===========================================" ;                    \
+       $(DOXYGEN) doxyfile ;                                                   \
+       rm -f $(top_builddir)/src/SMESH_SWIG/smesh.py
 
 docs: usr_docs
 
index b381d08197d58c32870b43d6b6d084df511b07d5..6053cdfd0f171f9d2c523691534679f84264a48c 100755 (executable)
@@ -98,8 +98,8 @@ EXAMPLE_RECURSIVE      = NO
 #---------------------------------------------------------------------------
 #Input related options
 #---------------------------------------------------------------------------
-INPUT             = @top_srcdir@/src/SMESH_SWIG
-FILE_PATTERNS     = smeshDC.py
+INPUT             = @top_builddir@/src/SMESH_SWIG
+FILE_PATTERNS     = smesh.py
 IMAGE_PATH        = @srcdir@/images
 RECURSIVE         = NO
 EXAMPLE_PATH      = @top_srcdir@/src/SMESH_SWIG
diff --git a/doc/salome/gui/SMESH/images/2d_from_3d_dlg.png b/doc/salome/gui/SMESH/images/2d_from_3d_dlg.png
new file mode 100644 (file)
index 0000000..a035309
Binary files /dev/null and b/doc/salome/gui/SMESH/images/2d_from_3d_dlg.png differ
diff --git a/doc/salome/gui/SMESH/images/2d_from_3d_ico.png b/doc/salome/gui/SMESH/images/2d_from_3d_ico.png
new file mode 100644 (file)
index 0000000..b0842d3
Binary files /dev/null and b/doc/salome/gui/SMESH/images/2d_from_3d_ico.png differ
index ec5117214dacaa84c2c4ef4bfba338d141a7f344..acb7b349e3fb1c24bcbbf4fb695ed8bfebbb23fe 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/2d_from_3d_menu.png and b/doc/salome/gui/SMESH/images/2d_from_3d_menu.png differ
index 70e2afd26dd6ed299365193b2073c28946ed0695..c8ca5ac772651c15214eb8396d322187201641dc 100755 (executable)
Binary files a/doc/salome/gui/SMESH/images/a-averagelength.png and b/doc/salome/gui/SMESH/images/a-averagelength.png differ
diff --git a/doc/salome/gui/SMESH/images/hypo_quad_params_dialog.png b/doc/salome/gui/SMESH/images/hypo_quad_params_dialog.png
new file mode 100644 (file)
index 0000000..3cd442a
Binary files /dev/null and b/doc/salome/gui/SMESH/images/hypo_quad_params_dialog.png differ
index 959ec02c8996033167b16a39b068555607e3b503..e2fca5cd9123ff2005b8420339f91a193ea4024f 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/netgen3d_simple.png and b/doc/salome/gui/SMESH/images/netgen3d_simple.png differ
index aba2b65986184721dc951a633b2a2e3e97f1ca69..367a0d0b5abe489daf5be5ae49ab5bcd9c5da4cc 100644 (file)
@@ -5,7 +5,7 @@
 <br>
 <ul>
 <li>\ref arithmetic_1d_anchor "Arithmetic 1D"</li>
-<li>\ref average_length_anchor "Average Length"</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>
 <li>\ref number_of_segments_anchor "Number of segments"</li>
@@ -57,9 +57,9 @@ locations and 1D mesh elements are constructed on segments.
 
 <br>
 \anchor average_length_anchor
-<h2>Average Length hypothesis</h2>
+<h2>Local Length hypothesis</h2>
 
-<b>Average Length</b> hypothesis can be applied for meshing of edges
+<b>Local Length</b> hypothesis can be applied for meshing of edges
 composing your geometrical object. Definition of this hypothesis
 consists of setting the \b length of segments, which will split these
 edges, and the \b precision of rounding. The points on the edges
@@ -79,10 +79,10 @@ integer. Default value is 1e-07.
 
 \image html a-averagelength.png
 
-\image html b-erage_length.png "Average length hypothesis - all 1D mesh elements are roughly equal"
+\image html b-erage_length.png "Local Length hypothesis - all 1D mesh elements are roughly equal"
 
 <b>See Also</b> a sample TUI Script of a 
-\ref tui_average_length "Defining Average Length" hypothesis
+\ref tui_average_length "Defining Local Length" hypothesis
 operation.
 
 <br>\anchor max_length_anchor
@@ -157,7 +157,7 @@ operation.
 
 <b>Start and End Length</b> hypothesis allows to divide a geometrical edge
 into segments so that the first and the last segments have a specified
-length. The length medium segments changes with automatically chosen
+length. The length of medium segments changes with automatically chosen
 geometric progression. Then mesh nodes are
 constructed at segment ends location and 1D mesh elements are
 constructed on them.
index 892cc9f74e2800ac23164f43878795a0b1bcf205..d72e4d50459e39613ca3ac0bca641acd810f497a 100644 (file)
@@ -43,27 +43,58 @@ length calculated as an average edge length for a given wire.
 \anchor hypo_quad_params_anchor
 <h2>Quadrangle parameters</h2>
 
-<b>Quadrangle parameters</b> is a hypothesis for
-Quadrangle (Mapping), which allows using this algorithm for meshing of
-triangular faces.In this case it is necessary to select the <b>Base vertex</b> 
-used as a degenerated edge.
+\image html hypo_quad_params_dialog.png "Quadrangle parameters creation/edition dialog"
+
+<b>Quadrangle parameters</b> is a hypothesis for Quadrangle (Mapping).
+
+<b>Base vertex</b> parameter allows using Quadrangle (Mapping)
+algorithm for meshing of triangular faces. In this case it is
+necessary to select the vertex, which will be used as the fourth edge
+(degenerated).
 
 \image html hypo_quad_params_1.png "A face built from 3 edges"
 
 \image html hypo_quad_params_res.png "The resulting mesh"
 
-This hypothesis can be also used to mesh a segment of a circular face.
-Please, consider that there is a limitation on the selectiion of the degenerated
+This parameter can be also used to mesh a segment of a circular face.
+Please, consider that there is a limitation on the selection of the
 vertex for the faces built with the angle > 180 degrees (see the picture).
 
 \image html hypo_quad_params_2.png "3/4 of a circular face"
 
-In this case, selection of a wrong vertex for the <b>Quadrangle parameters</b>
-hypothesis will generate a wrong mesh. The picture below
+In this case, selection of a wrong vertex for the <b>Base vertex</b>
+parameter will generate a wrong mesh. The picture below
 shows the good (left) and the bad (right) results of meshing.
 
 \image html hypo_quad_params_res_2.png "The resulting meshes"
 
+<b>Type</b> parameter is used on faces with a different number of
+segments on opposite sides to define the algorithm of transition
+between them. The following types are available:
+
+<ul>
+<li><b>Standard</b> is the default case, when both triangles and quadrangles
+    are possible in the transition area along the finer meshed sides.</li>
+<li><b>Triangle preference</b> forces building only triangles in the
+    transition area along the finer meshed sides.
+    <i>This type corresponds to <b>Triangle Preference</b> additional
+    hypothesis, which is obsolete now.</i></li>
+<li><b>Quadrangle preference</b> forces building only quadrangles in the
+    transition area along the finer meshed sides. This hypothesis has a
+    restriction: the total quantity of segments on all
+    four sides of the face must be even (divisible by 2).</li>
+    <i>This type corresponds to <b>Quadrangle Preference</b>
+    additional hypothesis, which is obsolete now.</i></li>
+<li><b>Quadrangle preference (reversed)</b> works in the same way and
+with the same restriction as <b>Quadrangle preference</b>, but
+    the transition area is located along the coarser meshed sides.</li>
+<li><b>Reduced</b> type forces building only quadrangles and the transition
+    between the sides is made gradually, layer by layer. This type has
+    a limitation on the number of segments: one pair of opposite sides must have
+    the same number of segments, the other pair must have an even difference
+    between the numbers of segments on the sides.</li>
+</ul>
+
 <b>See Also</b> a sample TUI Script of a 
 \ref tui_quadrangle_parameters "Quadrangle Parameters" hypothesis.
 
index 98c74c424b940c3cffc49f98a1c3d0702ca9ec35..22d88635f7e3f2f95e3fd21adef34b7dc2f992a2 100644 (file)
@@ -2,8 +2,8 @@
 
 \page filters_page About filters
 
-\b Filters allows to pick only those mesh elements which satisfy to
-specific condition or set of conditions. Filters can be used to create
+\b Filters allow picking only the mesh elements satisfying to a
+specific condition or set of conditions. Filters can be used to create
 or edit mesh groups, remove elements from the mesh object, control
 mesh quality by different parameters, etc.
 
@@ -18,15 +18,14 @@ The functinality of mesh filters is available in both GUI and TUI
 modes:
 
 - In GUI, filters are available in some dialog boxes via an additional
-"Set Filters" button, clicking on which opens specific dialog box
+"Set Filters" button, clicking on which opens the dialog box
 allowing to specify the list of filter criterions to be applied to the
-current selection. Follow to the \subpage selection_filter_library_page page to learn more
+current selection. See \subpage selection_filter_library_page page to learn more
 about selection filters and their usage in GUI.
 
-- In Python scripts, filters can be used to choose only some of mesh
-  entities (nodes and/or elements) for the operations which require
-  list of the entities as input parameter (create/modify group, remove
+- In Python scripts, filters can be used to choose only some mesh
+  entities (nodes and/or elements) for the operations, which require the
+  list of entities as input parameter (create/modify group, remove
   nodes/elements, etc). The page \ref tui_filters_page provides
-  examples of the filters usage in the Python scripts.
-
+  examples of the filters usage in Python scripts.
 */
index bbce53d2c052865fcb6af119bca9f12bad12d63f..5f989ec3d671fd581b4d88448fa7ad89f0747e80 100644 (file)
@@ -17,7 +17,7 @@ them, you operate numerical values):
 <b>edges</b>):</li>
 <ul>
 <li>\ref arithmetic_1d_anchor "Arithmetic 1D"</li>
-<li>\ref average_length_anchor "Average Length"</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>
 <li>\ref number_of_segments_anchor "Number of segments"</li>
index 5c99e8e79e2ce9daa95cab88e33fef3d65787b93..c0168994b230585103cd8eb2a927b295c02becd7 100644 (file)
@@ -27,23 +27,23 @@ following associated submenu will appear:</li>
 
 From this submenu select the type of element which you would like to add to your mesh.
 
-\note All dialogs for adding new node or element to the mesh (except for
-the dialog for 0D elements) provide a possibility to add it
-automatically to the specified group or to create it anew using
-<b>Add to group</b> box, that allows to choose an existing group for
-the created node or element or to give the name to a new group. By
-default, the <b>Add to group</b> check box is switched off. If user
+\note All dialogs for new node or element adding to the mesh (except for
+the dialog for 0D elements) provide the possibility to automatically add
+a node or element to the specified group or to create the anew using
+<b>Add to group</b> box, that allows choosing an existing group for
+the created node or element or giving the name to a new group. By
+default, the <b>Add to group</b> check box is switched off. If the user
 swiches this check box on, the combo box listing all currently
 existing groups of the corresponding type becomes available. By
-default, no any group is selected. In such a case, when user presses
+default, no group is selected. In this case, when the user presses
 <b>Apply</b> or <b>Apply & Close</b> button, the warning message box
-informing the user about the necessity to input new group name is
-shown. The combo box lists both \ref standalone_group "standalone groups"
-and \ref group_on_geom "groups on geometry". If the user has 
-chosen the group on geometry, he is warned and proposed to
-\ref convert_to_standalone "convert this group to the standalone".
-If user refuses converting operation, an operation is cancelled and
-new node/element is not created!
+informs the user about the necessity to input new group name. The
+combo box lists both \ref standalone_group "standalone groups"
+and \ref group_on_geom "groups on geometry". If the user chooses a
+group on geometry, he is warned and proposed to
+\ref convert_to_standalone "convert this group to standalone".
+If the user rejects conversion operation, it is cancelled and
+new node/element is not created!
 
 </ol>
 
index 83736c85dc1e9047496344903ebb0b678ffa1deb..9219486302c70040bb417f7f6afd7e31a2d3d3f5 100644 (file)
@@ -18,23 +18,23 @@ one of the following:
 
 \image html image152.png
 
-\note All dialogs for adding quadratic element to the mesh
-provide a possibility to add new element
-automatically to the specified group or to create it anew using
-<b>Add to group</b> box, that allows to choose an existing group for
-the created node or element or to give the name to a new group. By
-default, the <b>Add to group</b> check box is switched off. If user
+\note All dialogs for quadratic element adding to the mesh
+provide the possibility to automatically add an element
+to the specified group or to create the group anew using
+<b>Add to group</b> box, that allows choosing an existing group for
+the created node or element or giving the name to a new group. By
+default, the <b>Add to group</b> check box is switched off. If the user
 swiches this check box on, the combo box listing all currently
 existing groups of the corresponding type becomes available. By
-default, no any group is selected. In such a case, when user presses
+default, no group is selected. In this case, when the user presses
 <b>Apply</b> or <b>Apply & Close</b> button, the warning message box
-informing the user about the necessity to input new group name is
-shown. The combo box lists both \ref standalone_group "standalone groups"
-and \ref group_on_geom "groups on geometry". If the user has 
-chosen the group on geometry, he is warned and proposed to
-\ref convert_to_standalone "convert this group to the standalone".
-If user refuses converting operation, an operation is cancelled and
-new node/element is not created!
+informs the user about the necessity to input a new group name. The
+combo box lists both \ref standalone_group "standalone groups"
+and \ref group_on_geom "groups on geometry". If the user chooses a
+group on geometry, he is warned and proposed to
+\ref convert_to_standalone "convert this group to standalone".
+If the user rejects conversion operation, it is cancelled and
+a new quadratic element is not created.
 
 
 To create any <b>Quadratic Element</b> specify the nodes which will form your
index 1205e19b0d5338f0dafe0a574b366ff2000df0fa..81eab0be8228ac10f0dd197eb4bf5e48692cdc67 100644 (file)
@@ -41,17 +41,20 @@ It allows Netgen 2D to build quadrangular meshes at any conditions.
 
 It allows Quadrangle (Mapping) to build quadrangular meshes even if the number
 of nodes at the opposite edges of a meshed face is not equal,
-otherwise this mesh will contain some triangular elements.
+otherwise this mesh will contain some triangular elements. <i>This use
+case is obsolete now. Use <b>Quadrangle Parameters</b> hypothesis with
+type <b>Quadrangle Preference</b> set instead.</i>
 <br>
 This hypothesis has one restriction on its work: the total quantity of
 segments on all four sides of the face must be even (divisible by 2).
 
-<h2>Triangle Preference</h2>
+<h2>Triangle Preference <i>(obsolete)</i></h2>
 
 This additional hypothesis can be used only together with Quadrangle (Mapping)
 algorithm. It allows to build triangular mesh faces in the refinement
 area if the number of nodes at the opposite edges of a meshed face is not equal,
 otherwise refinement area will contain some quadrangular elements.
+<i>This hypothesis is obsolete now. Use <b>Quadrangle Parameters</b>
+hypothesis with type <b>Triangle Preference</b> set instead.</i>
 
 */
index 1b00a6174d2b2765e5c0f40704d2b3f12f4ab6c0..85d633a22234080bce7e9977b990d579c1b15c5d 100644 (file)
@@ -26,7 +26,7 @@ SALOME Platform distinguishes between the two Group types:
 \anchor standalone_group <br><h2>"Standalone Group"</h2>
 
 <b>Standalone Group</b> consists of mesh elements, which you can define in
-the next possible ways:
+the following ways:
 <ul>
 <li>Choosing them manually with the mouse in the 3D Viewer. You can
 click on an element in the 3D viewer and it will be highlighted. After
@@ -37,9 +37,8 @@ definite filter to selection of the elements of your group. See more
 about filters on the
 \ref selection_filter_library_page "Selection filter library" page.</li>
 <li>By adding all existing entities of the chosen type to the
-group. For this purpose, it is necessary to turn on the <b>Select
-All</b> check box. In this mode, all controls which allow selection of
-the entities manually or by filters, are disabled.</li>
+group. For this turn on the <b>Select All</b> check box. In this
+mode all controls, which allow selecting the entities manually or by filters, are disabled.</li>
 </ul>
 To remove a selected element or elements from the list click the
 \b Remove button. The <b>Sort List</b> button allows to sort the list of IDs of
index eb41ee7473801eb424ff04188eed2edea4d2ed5c..063bcba5e0ff9dfffdfeccdee850cdf6e5d7048b 100644 (file)
@@ -1,8 +1,11 @@
 /*!
 
-\page double_nodes_page Duplicating Nodes
+\page double_nodes_page Duplicate Nodes
 
 \n This operation allows to duplicate nodes of your mesh.
+Duplication consists in replacement of an existing mesh element by another one.
+Lower level elements of the duplicated ones are cloned
+automatically. 
 
 <em>To duplicate nodes:</em>
 <ol>
@@ -34,13 +37,13 @@ In this mode the dialog looks like:
 \image html duplicate01.png
 
 Parameters to be defined in this mode:
-<ol>
+<ul>
 <li><b>Group of nodes to duplicate</b> (<em>mandatory</em>): these nodes will be duplicated.</li>
 <li><b>Group of elements to replace nodes with new ones</b> (<em>optional</em>): the duplicated nodes
  will be associated with these elements.</li>
 <li><b>Construct group with newly created nodes</b> option (<em>checked by default</em>): 
- if checked - the group with just created nodes will be builded.</li>
-</ol>
+ if checked - the group with just created nodes will be built.</li>
+</ul>
 
 <br>
 \anchor mode_with_elem_anchor
@@ -51,15 +54,15 @@ In this mode the dialog looks like:
 \image html duplicate02.png
 
 Parameters to be defined in this mode:
-<ol>
+<ul>
 <li><b>Group of elements to duplicate</b> (<em>mandatory</em>): these elements will be duplicated.</li>
 <li><b>Group of nodes at not to duplicate</b> (<em>optional</em>): group of nodes at crack bottom
  which will not be duplicated.</li>
 <li><b>Group of elements to replace nodes with new ones</b> (<em>mandatory</em>): the duplicated nodes
  will be associated with these elements.</li>
 <li><b>Construct group with newly created elements</b> option (<em>checked by default</em>): 
- if checked - the group with just created elements will be builded.</li>
-</ol>
+ if checked - the group with just created elements will be built.</li>
+</ul>
 
 
 <br><b>See Also</b> a sample TUI Script of a \ref tui_duplicate_nodes "Duplicate nodes" operation.  
index af0f76f16d5c0e427c4b4be40732b56e37ac4d23..0975842aece16b6c0d89fc93b9c54e15414ca7e7 100644 (file)
@@ -25,6 +25,10 @@ array of dedicated operations.</li>
 Almost all mesh module functionalities are accessible via
 \subpage smeshpy_interface_page "Mesh module Python interface".
 
+Also it can be useful to have a look at the
+\subpage smeshpypkg_page "documentation on SMESH python package". 
+
+
 \image html image7.jpg "Example of MESH module usage for engineering tasks"
 
 */
index f4b5b2ba5d37e8e37963133a432190abfd73764a..e520786296df0d79c4db9389dc38949abc82afb1 100644 (file)
@@ -1,22 +1,58 @@
 /*!
 
-\page make_2dmesh_from_3d_page Generate the skin elements (2D) of a mesh having 3D elements
+\page make_2dmesh_from_3d_page Generate boundary elements
 
-\n This functionality allows to generate 2D mesh elements as a skin
-on the existing 3D mesh elements.
+\n This functionality allows to generate mesh elements on the borders of
+elements of a higher dimension.
 
-<em>To generate 2D mesh:</em>
+<em>To generate border elements:</em>
 <ol>
-<li>From the Modification menu choose "Create 2D mesh from 3D"
-item, or choose from the popup menu.
+<li>From the Modification menu choose "Create boundary elements"
+item, or click "Create boundary elements" button in the toolbar
 
-\image html 2d_from_3d_menu.png
+\image html 2d_from_3d_ico.png "Create boundary elements icon"
 
-The algorithm detects boundary volume faces without connections to
-other volumes and creates 2D mesh elements on face nodes. If the mesh
-already contains 2D elements on the detected nodes, new elements are not
-created. The the resulting dialog shows mesh information statistics
-about the newly created 2D mesh elements.
+The following dialog box will appear:
+\image html 2d_from_3d_dlg.png "Create boundary elements dialog box".
+</li>
+<li>Check in the dialog box one of three radio buttons corresponding to
+the type of operation you would like to perform.</li>
+<li>Fill the other fields available in the dialog box.</li>
+<li>Click the \b Apply or <b>Apply and Close</b> button to perform the operation.</li>
 </ol>
 
+\n "Create boundary elements" dialog allows creation of boundary elements
+of three types.
+<ul>
+<li><b>2D from 3D</b> creates mesh faces on free facets of volume elements</li>
+<li><b>1D from 2D</b> creates mesh edges on free edges of mesh faces</li>
+<li><b>1D from 3D</b> creates mesh edges on all borders of free facets of volume elements</li>
+</ul>
+Here a <em>free facet</em> means a facet shared by only one volume, a <em>free edge</em>
+means an edge shared by only one mesh face.
+
+In this dialog:
+<ul>
+<li>specify the <b>Mesh, submesh or group</b>, the boundary which of
+will be analyzed.</li>
+<li>specify the <b>Target</b> mesh, where the boundary elements will
+  be created.
+  <ul>
+  <li><b>This mesh</b> adds elements in the selected mesh or the mesh
+  the selected submesh or group belongs to.</li>
+  <li><b>New mesh</b> adds elements to a new mesh. The new mesh appears
+  in the Object Browser with the name that you can change in the adjacent box. </li>
+  </ul></li>
+<li>activate <b>Copy source mesh</b> checkbox to copy 2D or 3D
+  elements (depending on the operation type), which belong to the analyzed 
+<b>Mesh, submesh or group</b> field, to the new mesh.</li>
+<li>deactivate <b>Copy missing elements only</b> checkbox to copy
+  boundary elements already present in the analyzed mesh to the
+  new mesh.</li>
+<li>activate <b>Create group</b> checkbox to create a group to which the
+  missing boundary elements are added. The new group appears
+  in the Object Browser with the name that you can change in the adjacent box. </li>
+</ul>
+<br><b>See Also</b> a sample TUI Script of a \ref tui_make_2dmesh_from_3d "Create boundary elements" operation.  
+
 */
index 8d5875a9c2fc2c6b18c5af487143e783b1dbaab2..45e746da4dd86923dffa259f06fbb92362d2663f 100644 (file)
@@ -18,7 +18,9 @@ elements of the mesh.</li>
 its elements.</li>
 <li>\subpage rotation_page "Rotate" by the indicated axis and angle
 the mesh or some of its elements.</li>
-<li>\subpage scale_page "Scale Transform" the mesh or some of its elements.</li>
+<li>\subpage scale_page "Scale Transform" the mesh or some of its
+elements.</li>
+<li>\subpage double_nodes_page "Duplicate nodes".</li>
 <li>Create a \subpage symmetry_page "symmetrical copy" of the mesh
 through a point or a vector of symmetry.</li>
 <li>Unite meshes by \subpage sewing_meshes_page "sewing" free borders,
@@ -45,8 +47,7 @@ of the selected node or edge.</li>
 <li>Apply \subpage pattern_mapping_page "pattern mapping".</li>
 <li>\subpage convert_to_from_quadratic_mesh_page "Convert regular mesh to quadratic", 
 or vice versa.</li>
-<li>Create \subpage double_nodes_page "double nodes".</li>
-<li>\subpage make_2dmesh_from_3d_page "Create 2D mesh from 3D".</li>
+<li>\subpage make_2dmesh_from_3d_page "Generate boundary elements".</li>
 
 </ul>
 
index bbb7c59ff4b8e92c59dc1af89eea92363e6aaaa9..7fd71550a29100a688afa8f18b5b67058874bc12 100644 (file)
@@ -42,8 +42,8 @@ dimension.
 - <b>Number of Segments</b> has the same sense as \ref
 number_of_segments_anchor "Number of segments" hypothesis with
 equidistant distribution.
-- <b>Average Length</b> has the same sense as \ref 
-average_length_anchor "Average Length" hypothesis.
+- <b>Local Length</b> has the same sense as \ref 
+average_length_anchor "Local Length" hypothesis.
 
 \b 2D group allows defining the size of 2D elements 
 - <b>Length from edges</b> if checked in, acts like \ref
index 1a48a4644bd640170c6d49e32cdd5a6f7e6960e5..ef7f8ba66a704be2910dfba199764ad1a3e4665f 100644 (file)
@@ -5,33 +5,31 @@
 <br><h2>About patterns</h2>
 
 The pattern describes a mesh to generate: positions of nodes within a
-geometrical domain and nodal connectivity of elements. As well, a
-pattern specifies the so-called key-points, i.e. nodes that will be
-located at geometrical vertices. Pattern description is stored in
+geometrical domain and nodal connectivity of elements. A
+pattern also specifies the so-called key-points, i.e. the nodes that will be
+located at geometrical vertices. The pattern description is stored in
 \<pattern_name\>.smp file.
 
 The smp file contains 4 sections:
 
--# The first line holds the total number of the pattern nodes (N).
--# The next N lines describe nodes coordinates. Each line holds 2
-coordinates of a node for 2D pattern or 3 cordinates for 3D pattern.
-Note, that for 3D pattern only relateive values in range [0;1] are
-valid for coordinates of the nodes.
--# A key-points line: indices of nodes to be mapped on geometrical
-vertices (for 2D pattern only). An index n refers to a node described 
-on an n-th line of section 2. The first node index is zero. For 3D 
-pattern key points are not specified.
--# The rest lines describe nodal connectivity of elements, one line
-for an element. A line holds indices of nodes forming an element. An
-index n refers to a node described on an n-th line of the section
-2. The first node index is zero. There must be 3 or 4 indices on a
-line for 2D pattern (only 2d elements are allowed) and 4, 5, 6 or 8
-indices for 3D pattern (only 3d elements are allowed).
-
-The 2D pattern must contain at least one element and at least one
-key-point. All key-points must lay on boundaries.
-
-The 3D pattern must contain at least one element.
+-# The first line indicates the total number of pattern nodes (N).
+-# The next N lines describe nodes coordinates. Each line contains 2
+node coordinates for a 2D pattern or 3 node cordinates for a 3D pattern.
+Note, that node coordinates of a 3D pattern can be defined only by relative values in range [0;1].
+-# The key-points line contains the indices of the nodes to be mapped on geometrical
+vertices (for a 2D pattern only). Index n refers to the node described 
+on the n-th line of section 2. The index of the first node zero. For a 3D pattern the key points are not specified.
+-# The remaining lines describe nodal connectivity of elements, one line
+for each element. Each line holds indices of nodes forming an element.
+Index n refers to the node described on the n-th line of section 2.
+The first node index is zero. There must be 3 or 4 indices on each
+line for a 2D pattern (only 2d elements are allowed) and 4, 5, 6 or 8
+indices for a 3D pattern (only 3d elements are allowed).
+
+A 2D pattern must contain at least one element and at least one
+key-point. All key-points must lie on boundaries.
+
+A 3D pattern must contain at least one element.
 
 An example of a simple 2D pattern smp file:
 
@@ -60,7 +58,7 @@ An example of a simple 2D pattern smp file:
  8 1 2
 \endcode
 
-The image below provides a preview of above described pattern:
+The image below provides a preview of the above pattern:
 
 \image html pattern2d.png
 
@@ -99,91 +97,120 @@ From the \b Modification menu choose the <b>Pattern Mapping</b> item or click
 \image html image98.png
 <center><em>"Pattern mapping" button</em></center>
 
-The following dialog box shall appear:
+The following dialog box will appear:
+
+\n For a <b>2D pattern</b>
 
 \image html patternmapping1.png
 
-<center><b> 2D Pattern Mapping dialog box</b></center>
+In this dialog you should specify:
+
+<ul>
+<li> \b Pattern, which can be loaded from .smp pattern file previously
+created manually or generated automatically from an existing mesh or submesh.</li>
+<li> \b Face with the number of vertices equal to the number of
+     key-points in the pattern; the number of key-points on internal
+     boundaries of the pattern must also be equal to the number of vertices
+     on internal boundaries of the face;</li>
+<li> \b Vertex to which the first key-point should be mapped;</li>
+Alternatively, it is possible to select <b>Refine selected mesh elements</b> 
+checkbox and apply the pattern to
+<li> <b>Mesh Face</b> instead of a geometric Face</li>
+<li> and select \b Node instead of vertex.</li>
+
+Additionally it is possible to:
+<li> <b>Reverse the order of key-points</b> By default, the vertices of
+     a face are ordered counterclockwise.<li>
+<li> Enable to <b> Create polygons near boundary</b> </li>
+<li> and <b>Create polyhedrons near boundary</b><li>  
+</ul>
+
+\n For a <b>3D pattern</b>
 
 \image html patternmapping2.png
 
-<center><b> 3D Pattern Mapping dialog box</b></center>
+In this dialog you should specify:
+<ul>
+<li> \b Pattern, which can be loaded from .smp pattern file previously
+created manually or generated automatically from an existing mesh or submesh.</li>
+   <li> A 3D block (Solid) object;</li>
+   <li> Two vertices that specify the order of nodes in the resulting mesh.</li>
+Alternatively, it is possible to select <b>Refine selected mesh elements</b> 
+checkbox and apply the pattern to
+<li> One or several <b>Mesh volumes</b> instead of a geometric 3D
+object</li>
+<li> and select two /b Nodes instead of vertices.</li> 
+Additionally it is possible to:
+<li> Enable to <b> Create polygons near boundary</b> </li>
+<li> and <b>Create polyhedrons near boundary</b><li>
+</ul>
+
+\n Automatic Generation 
+
+To generate a pattern automatically from an existing mesh or submesh,
+click \b New button.
+
+The following dialog box will appear:
 
-To apply a pattern to a geometrical object, you should specify:
+\image html a-patterntype1.png
 
--# For 2D pattern
-   - A face having the number of vertices equal to the number of
-     key-points in the pattern; the number of key-points on internal
-     boundaries of a pattern must also be equal to the number of vertices
-     on internal boundaries of a face;
-   - A vertex to which the first key-point should be mapped;
-   - Reverse or not the order of key-points. (The order of vertices of
-     a face is counterclockwise looking from outside).
--# For 3D pattern
-   - 3D block (Solid) object;
-   - Two vertices that specify the order of nodes in the resulting
-     mesh.
-
-Then you either load a .smp pattern file previously created manually
-by clicking on the <em>"Load pattern"</em> button, or click on the \b
-New button for automatic generation of the pattern.
-
-For an automatic generation you just specify a geometrical face (for
-2D) or solid (for 3d) having a mesh built on it. Mesh nodes lying on
-face vertices become key-points of 2D pattern. Additionally, for 2D
-pattern you may choose the way of getting nodes coordinates by
-<b>projecting nodes on the face</b> instead of using
-"positions on face" generated by mesher (if there is any). Faces
-having a seam edge can't be used for automatic pattern creation.
-
-When creating a pattern from an existing mesh, there are two possible
-cases:
-
-- A sub-mesh on face/solid is selected. A pattern is created from the 2d/3d
-elements bound to a face/solid by mesher. For 2D pattern, node coordinates are either
-"positions on face" computed by mesher, or coordinates got by node
-projection on a geometrical surface, according to the user choice. For
-3D pattern, nodes coordinates correspond to the nodes computed by mesher.
-- A mesh where the main shape is a face/solid, is selected. A pattern is
-created from all the 2d/3d elements in a mesh. In addition, for 2D
-pattern, if all mesh elements are build by mesher, the user can select
-the way of getting nodes coordinates, else all nodes are projected on
-a face surface.
+In this dialog you should specify:
 
-\image html a-patterntype.png
+<ul>
+<li> <b>Mesh or Submesh</b>, which is a meshed geometrical face (for a
+2D pattern) or a meshed solid (for a 3D pattern). Mesh nodes lying on
+the face vertices become key-points of the pattern. </li>
+<li> A custom <b>Pattern Name </b> </li>
+<li>Additionally, for a 2D pattern you may choose to 
+<b>Project nodes on the face</b> to get node coordinates instead of using
+"positions on face" generated by the mesher (if there is any). The faces
+having a seam edge cannot be used for automatic pattern creation.</li>
+</ul>
 
-<center><b> 2D Pattern Creation dialog box</b></center>
+When a pattern is created from an existing mesh, two cases are possible:
 
-\image html a-patterntype1.png
+- A sub-mesh on a face/solid is selected. The pattern is created from the 2d/3d
+elements bound to the face/solid by the mesher. For a 2D pattern, the node coordinates are either
+"positions on face" computed by the mesher, or coordinates got by node
+projection on a geometrical surface, according to the user choice. For
+a 3D pattern, the node coordinates correspond to the nodes computed by
+the mesher.
+- A mesh, where the main shape is a face/solid, is selected. The pattern is
+created from all 2d/3d elements in a mesh. In addition, if all mesh
+elements of a 2D pattern are built by the mesher, the user can select
+how to get node coordinates, otherwise all nodes are projected on
+a face surface.
 
-<center><b> 3D Pattern Creation dialog box</b></center>
 
 <br><h2>Mapping algorithm</h2>
 
-The mapping algorithm for 2D case is as follows:
-
-- Key-points are set in the order that they are encountered when
-  walking along a pattern boundary so that elements are on the left. The
-  first key-point is preserved.
-- Find geometrical vertices corresponding to key-points by vertices
-  order in a face boundary; here, "Reverse order of key-points" flag is
-  taken into account. \image html image95.gif
-- Boundary nodes of a pattern are mapped onto edges of a face: a
-  node located between certain key-points on a pattern boundary is
-  mapped on a geometrical edge limited by corresponding geometrical
-  vertices. Node position on an edge reflects its distance from two
-  key-points. \image html image96.gif
-- Coordinates of a non-boundary node in a parametric space of a face
- are defined as following. In a parametric space of a pattern, a node
- lays at the intersection of two iso-lines, each of which intersects a
- pattern boundary at least at two points. Knowing mapped positions of
- boundary nodes, we find where isoline-boundary intersection points are
- mapped to, and hence we can find mapped isolines direction and then,
- two node positions on two mapped isolines. The eventual mapped
- position of a node is found as an average of positions on mapped
- isolines. \image html image97.gif
-
-For 3D case the algorithm is similar.
+The mapping algorithm for a 2D case is as follows:
+
+- The key-points are set counterclockwise in the order corresponding
+  to their location on the pattern boundary. The first key-point is preserved.
+- The geometrical vertices corresponding to the key-points are found
+  on face boundary. Here, "Reverse order of key-points" flag is set. 
+\image html image95.gif
+- The boundary nodes of the pattern are mapped onto the edges of the face: a
+  node located between two key-points on the pattern boundary is
+  mapped on the geometrical edge limited by the corresponding geometrical
+  vertices. The node position on the edge depends on its distance from the
+  key-points. 
+\image html image96.gif
+- The cordinates of a non-boundary node in the parametric space of the face
+ are defined in the following way. In the parametric space of the
+  pattern, the  node lies at the intersection of two iso-lines. Both
+  of them intersect the pattern boundary at two
+  points at least. If the mapped positions of boundary nodes are known, it is
+  possible to find, where the points at the intersection of isolines
+  and boundaries are mapped. Then it is possible to find
+  the direction of mapped isolinesection and, filally, the poitions of
+  two nodes on two mapped isolines. The eventual mapped
+ position of the node is found as an average of the positions on mapped
+ isolines. 
+\image html image97.gif
+
+The 3D algorithm is similar.
 
 <b>See Also</b> a sample TUI Script of a 
 \ref tui_pattern_mapping "Pattern Mapping" operation.
index aef20c8add2fd24de7594d3905a358d666585fd6..0a48ee65e9f5b3c6d50504e6d41b3e133e98a4d9 100644 (file)
@@ -51,14 +51,14 @@ node of your mesh all adjacent elements will be also deleted.
 \anchor removing_orphan_nodes_anchor
 <h2>Removing orphan nodes</h2>
 
-There is a quick way to remove all the orphan (free) nodes.
+There is a quick way to remove all orphan (free) nodes.
 
-<em>To remove the orphan nodes:</em>
+<em>To remove orphan nodes:</em>
 <ol>
 <li>Select your mesh in the Object Browser or in the 3D viewer.</li>
 
 <li>From the <em>Modification</em> menu choose <em>Remove</em> and from the associated
-submenu select the <em>Orphan Nodes</em>, or just click <em>"Remove orphan nodes"</em>
+submenu select <em>Orphan Nodes</em>, or just click <em>"Remove orphan nodes"</em>
 button in the toolbar.
 
 \image html remove_orphan_nodes_icon.png
@@ -68,7 +68,7 @@ The following Warning message box will appear:
 
 \image html removeorphannodes.png
 
-Confirm removing nodes by pressing "Yes" button.
+Confirm nodes removal by pressing "Yes" button.
 </ol>
 
 <br>
index 94dd3844c4b6f3f87537a738b5d61abf0edd3665..c01dc0a54f6cf1848ee0be5bee16b0ce1a44c0f3 100644 (file)
@@ -156,6 +156,12 @@ See also a
 length, which is more, less or equal (within a given <b>Tolerance</b>) to the predefined
 <b>Threshold Value</b>. See also a
 \ref length_2d_page "Length 2D quality control".
+</li><li>
+<b>Coplanar faces</b> selects mesh faces neighboring the one selected
+by ID in <b>Threshold Value</b> field, if the angle between the
+normal to the neighboring face and the normal to the selected face is less then the
+angular tolerance (defined in degrees). Selection continues among all neighbor faces of already 
+selected ones.<br>
 </li>
 </ul>
 
index 1aa91d9d513a14841a1fb19ae7d1d3a24b3c9610..9932991f8c219134ddf32225d99142b1774efc41 100644 (file)
@@ -128,7 +128,7 @@ hexa.Compute()
 
 <br>
 \anchor tui_average_length
-<h3>Average Length</h3>
+<h3>Local Length</h3>
 
 \code
 from geompy import *
@@ -549,7 +549,7 @@ mesh.Compute()
 \endcode
 
 \anchor tui_quadrangle_parameters
-<h2>Quadrangle Parameters example </h2>
+<h2>Quadrangle Parameters example 1 (meshing a face with 3 edges) </h2>
 \code
 import geompy
 import smesh
@@ -570,7 +570,7 @@ Mesh_1 = smesh.Mesh(Common_1)
 Quadrangle_Parameters_1 = smesh.CreateHypothesis('QuadrangleParams')
 Quadrangle_Parameters_1.SetTriaVertex( 8 )
 
-# Define 1D hypothesis and cmpute the mesh
+# Define 1D hypothesis and compute the mesh
 Regular_1D = Mesh_1.Segment()
 Nb_Segments_1 = Regular_1D.NumberOfSegments(10)
 Nb_Segments_1.SetDistrType( 0 )
@@ -579,6 +579,56 @@ Quadrangle_2D = Mesh_1.Quadrangle()
 Mesh_1.Compute()
 \endcode
 
+<h2>Quadrangle Parameters example 2 (using different types) </h2>
+\code
+import geompy
+import smesh
+import StdMeshers
+
+# Make quadrangle face and explode it on edges.
+Vertex_1 = geompy.MakeVertex(0, 0, 0)
+Vertex_2 = geompy.MakeVertex(40, 0, 0)
+Vertex_3 = geompy.MakeVertex(40, 30, 0)
+Vertex_4 = geompy.MakeVertex(0, 30, 0)
+Quadrangle_Face_1 = geompy.MakeQuad4Vertices(Vertex_1, Vertex_4, Vertex_3, Vertex_2)
+[Edge_1,Edge_2,Edge_3,Edge_4] = geompy.SubShapeAllSorted(Quadrangle_Face_1, geompy.ShapeType["EDGE"])
+geompy.addToStudy( Vertex_1, "Vertex_1" )
+geompy.addToStudy( Vertex_2, "Vertex_2" )
+geompy.addToStudy( Vertex_3, "Vertex_3" )
+geompy.addToStudy( Vertex_4, "Vertex_4" )
+geompy.addToStudy( Quadrangle_Face_1, "Quadrangle Face_1" )
+geompy.addToStudyInFather( Quadrangle_Face_1, Edge_2, "Edge_2" )
+
+# Set the Geometry for meshing
+Mesh_1 = smesh.Mesh(Quadrangle_Face_1)
+
+# Create Quadrangle parameters and
+# define the Type as Quadrangle Preference
+Quadrangle_Parameters_1 = smesh.CreateHypothesis('QuadrangleParams')
+Quadrangle_Parameters_1.SetQuadType( StdMeshers.QUAD_QUADRANGLE_PREF )
+
+# Define other hypotheses and algorithms
+Regular_1D = Mesh_1.Segment()
+Nb_Segments_1 = Regular_1D.NumberOfSegments(4)
+Nb_Segments_1.SetDistrType( 0 )
+status = Mesh_1.AddHypothesis(Quadrangle_Parameters_1)
+Quadrangle_2D = Mesh_1.Quadrangle()
+
+# Define submesh on one edge to provide different number of segments
+Regular_1D_1 = Mesh_1.Segment(geom=Edge_2)
+Nb_Segments_2 = Regular_1D_1.NumberOfSegments(10)
+Nb_Segments_2.SetDistrType( 0 )
+SubMesh_1 = Regular_1D_1.GetSubMesh()
+
+# Compute mesh (with Quadrangle Preference type)
+isDone = Mesh_1.Compute()
+
+# Change type to Reduced and compute again
+Quadrangle_Parameters_1.SetQuadType( StdMeshers.QUAD_REDUCED )
+isDone = Mesh_1.Compute()
+\endcode
+
+
 \n Other meshing algorithms:
 
 <ul>
index ad6dd5929348854032739ab2051f0c6e923a0461..0a4fccd3bd2195e167f28d0c85d99234fbed0653 100755 (executable)
@@ -2,8 +2,8 @@
 
 \page tui_filters_page Filters usage
 
-Filters allows to pick only those mesh elements which satisfy to
-specific condition or set of conditions. Filters can be used to create
+Filters allow picking only the mesh elements satisfying to a
+specific condition or set of conditions. Filters can be used to create
 or edit mesh groups, remove elements from the mesh object, control
 mesh quality by different parameters, etc.
 
@@ -12,10 +12,10 @@ AND and \a OR. In addition, applied filter criterion can be reverted
 using logical operator \a NOT.
 
 Mesh filters use the functionality of mesh quality controls to filter
-mesh nodes / elements by specific characteristic (Area, Length, etc).
+mesh nodes / elements by specific characteristic (Area, Length, etc).
 
 This page provides a short description of the existing mesh filters,
-describing required parameters and gives simple examples of usage in
+describes required parameters and gives simple examples of usage in
 Python scripts.
 
 \sa \ref tui_quality_controls_page
index e50fcda36d46fb1384e8c4c29849db7f69cba760..22f11886f64f4cca29148358908f035cb43bbb45 100644 (file)
@@ -421,4 +421,167 @@ if salome.sg.hasDesktop():
     salome.sg.updateObjBrowser(0)
 \endcode
 
+<br>
+\anchor tui_make_2dmesh_from_3d
+<h3>Create boundary elements</h3>
+
+\code
+# The objective of these samples is to illustrate the following use cases:
+# 1) The mesh MESH1 with 3D cells has no or only a part of its skin (2D cells):
+#    1.1) Add the 2D skin (missing 2D cells) to MESH1 (what is done now by the algorithm).
+#    1.2) Create a new 3D Mesh MESH2 that consists of MESH1 and added 2D skin cells.
+#    1.3) Create a new 2D Mesh MESH3 that consists only of 2D skin cells.
+# 2) The mesh MESH1 with 3D cells has all its skin (2D cells):
+#    Create a new 2D Mesh MESH3 that consists only of 2D skin cells.
+#
+# In all cases an option to create a group containing these 2D skin cells is available.
+
+from smesh import *
+
+box = geompy.MakeBoxDXDYDZ(1,1,1)
+geompy.addToStudy(box,"box")
+boxFace = geompy.SubShapeAll(box, geompy.ShapeType["FACE"])[0]
+geompy.addToStudyInFather(box,boxFace,"boxFace")
+
+MESH1 = Mesh(box,"MESH1")
+MESH1.AutomaticHexahedralization()
+
+init_nb_edges = MESH1.NbEdges()
+init_nb_faces = MESH1.NbFaces()
+init_nb_volumes = MESH1.NbVolumes()
+
+# =========================================================================================
+# 1) The mesh MESH1 with 3D cells has no or only a part of its skin (2D cells)
+# =========================================================================================
+# remove some faces
+all_faces = MESH1.GetElementsByType(SMESH.FACE)
+rm_faces = all_faces[:init_nb_faces/5] + all_faces[4*init_nb_faces/5:]
+MESH1.RemoveElements(rm_faces)
+assert(MESH1.NbFaces() == init_nb_faces-len(rm_faces))
+
+# 1.1) Add the 2D skin (missing 2D cells) to MESH1
+# -------------------------------------------------
+# add missing faces
+# 1.1.1) to the whole mesh
+m,g = MESH1.MakeBoundaryMesh(MESH1)
+assert(init_nb_faces == MESH1.NbFaces())
+assert(init_nb_edges == MESH1.NbEdges())
+assert(m)
+assert(not g)
+
+# 1.1.2) to some elements
+MESH1.RemoveElements(rm_faces)
+MESH1.MakeBoundaryMesh([])
+assert(init_nb_faces != MESH1.NbFaces())
+volumes = MESH1.GetElementsByType(SMESH.VOLUME)
+for v in volumes:
+    MESH1.MakeBoundaryMesh([v])
+assert(init_nb_faces == MESH1.NbFaces())
+assert(init_nb_edges == MESH1.NbEdges())
+
+# 1.1.3) to a group of elements
+volGroup1 = MESH1.CreateEmptyGroup(SMESH.VOLUME, "volGroup1")
+volGroup1.Add( volumes[: init_nb_volumes/2])
+volGroup2 = MESH1.CreateEmptyGroup(SMESH.VOLUME, "volGroup2")
+volGroup1.Add( volumes[init_nb_volumes/2:])
+MESH1.RemoveElements(rm_faces)
+MESH1.MakeBoundaryMesh(volGroup1)
+MESH1.MakeBoundaryMesh(volGroup2)
+assert(init_nb_faces == MESH1.NbFaces())
+assert(init_nb_edges == MESH1.NbEdges())
+
+# 1.1.4) to a submesh.
+# The submesh has no volumes, so it is required to check if it passes without crash and does not create
+# missing faces
+faceSubmesh = MESH1.GetSubMesh( boxFace, "boxFace" )
+MESH1.RemoveElements(rm_faces)
+MESH1.MakeBoundaryMesh(faceSubmesh)
+assert(init_nb_faces != MESH1.NbFaces())
+
+# check group creation
+MESH1.RemoveElements(rm_faces)
+groupName = "added to mesh"
+m,group = MESH1.MakeBoundaryMesh(MESH1,groupName=groupName)
+assert(group)
+assert(group.GetName() == groupName)
+assert(group.Size() == len(rm_faces))
+
+
+# 1.2) Create a new 3D Mesh MESH2 that consists of MESH1 and added 2D skin cells.
+# ------------------------------------------------------------------------------
+MESH1.RemoveElements(rm_faces)
+meshName = "MESH2"
+MESH2,group = MESH1.MakeBoundaryMesh(MESH1,meshName=meshName,toCopyElements=True)
+assert(MESH2)
+assert(MESH2.GetName() == meshName)
+assert(MESH2.NbVolumes() == MESH1.NbVolumes())
+assert(MESH2.NbFaces() == len(rm_faces))
+
+# check group creation
+MESH1.RemoveElements(rm_faces)
+MESH2,group = MESH1.MakeBoundaryMesh(MESH1,meshName="MESH2_0",
+                                     groupName=groupName,toCopyElements=True)
+assert(group)
+assert(group.GetName() == groupName)
+assert(group.Size() == len(rm_faces))
+assert(group.GetMesh()._is_equivalent(MESH2.GetMesh()))
+
+# 1.3) Create a new 2D Mesh MESH3 that consists only of 2D skin cells.
+# -----------------------------------------------------------------------
+MESH1.RemoveElements(rm_faces)
+meshName = "MESH3"
+MESH3,group = MESH1.MakeBoundaryMesh(MESH1,meshName=meshName,toCopyExistingBondary=True)
+assert(MESH3)
+assert(not group)
+assert(MESH3.GetName() == meshName)
+assert(MESH3.NbVolumes() == 0)
+assert(MESH3.NbFaces() == init_nb_faces)
+
+# check group creation
+MESH1.RemoveElements(rm_faces)
+MESH3,group = MESH1.MakeBoundaryMesh(MESH1,meshName=meshName,
+                                     groupName=groupName, toCopyExistingBondary=True)
+assert(group)
+assert(group.GetName() == groupName)
+assert(group.Size() == len(rm_faces))
+assert(group.GetMesh()._is_equivalent(MESH3.GetMesh()))
+assert(MESH3.NbFaces() == init_nb_faces)
+
+# ==================================================================
+# 2) The mesh MESH1 with 3D cells has all its skin (2D cells)
+# Create a new 2D Mesh MESH3 that consists only of 2D skin cells.
+# ==================================================================
+MESH1.MakeBoundaryMesh(MESH1)
+MESH3,group = MESH1.MakeBoundaryMesh(MESH1,meshName=meshName,toCopyExistingBondary=True)
+assert(MESH3)
+assert(not group)
+assert(MESH3.NbVolumes() == 0)
+assert(MESH3.NbFaces() == init_nb_faces)
+
+# check group creation
+MESH3,group = MESH1.MakeBoundaryMesh(MESH1,meshName=meshName,
+                                     groupName=groupName, toCopyExistingBondary=True)
+assert(group)
+assert(group.GetName() == groupName)
+assert(group.Size() == 0)
+assert(group.GetMesh()._is_equivalent(MESH3.GetMesh()))
+assert(MESH3.NbFaces() == init_nb_faces)
+
+# ================
+# Make 1D from 2D
+# ================
+
+MESH1.Clear()
+MESH1.Compute()
+MESH1.RemoveElements( MESH1.GetElementsByType(SMESH.EDGE))
+
+rm_faces = faceSubmesh.GetIDs()[:2] # to remove few adjacent faces
+nb_missing_edges = 2 + 2*len(rm_faces)
+
+MESH1.RemoveElements(rm_faces)
+mesh,group = MESH1.MakeBoundaryMesh(MESH1, BND_1DFROM2D)
+assert( MESH1.NbEdges() == nb_missing_edges )
+
+
+\endcode
 */
index 871f077148b64e3e20c525831e1d355969c724d8..a5ecbcabf2e15f0af7eab40ff9cb6389964a6b55 100644 (file)
@@ -753,6 +753,16 @@ module StdMeshers
   /*!
    * StdMeshers_QuadrangleParams: interface of "Quadrangle Params" hypothesis
    */
+  enum QuadType
+  {
+    QUAD_STANDARD,
+    QUAD_TRIANGLE_PREF,
+    QUAD_QUADRANGLE_PREF,
+    QUAD_QUADRANGLE_PREF_REVERSED,
+    QUAD_REDUCED,
+    QUAD_NB_TYPES /* this is not a type of quadrangulation */
+  };
+
   interface StdMeshers_QuadrangleParams : SMESH::SMESH_Hypothesis
   {
     /*!
@@ -774,6 +784,16 @@ module StdMeshers
      * Get the entry of the main object
      */
     string GetObjectEntry();
+    
+    /*!
+     * Set the type of quadrangulation
+     */
+    void SetQuadType( in QuadType type );
+
+    /*!
+     * Get the type of quadrangulation
+     */
+    QuadType GetQuadType();
   };
 
   /*!
index 56f2cdce21ae47d30ac08f6cbfa82da0b6b7f265..3b478fec0d74235fcdd4ae63c15dca70ac0bf809 100644 (file)
@@ -65,6 +65,7 @@ module SMESH
     FT_LinearOrQuadratic,
     FT_GroupColor,
     FT_ElemGeomType,
+    FT_CoplanarFaces,
     FT_LessThan,
     FT_MoreThan,
     FT_EqualTo,
@@ -346,6 +347,16 @@ module SMESH
     void            SetGeometryType( in GeometryType theType );
   };
 
+  /*!
+  * Functor "Coplanar faces"
+  * Returns true if a mesh face is a coplanar neighbour to a given one. It checks
+  * if normal of a face has angle with the threshold face less than a tolerance.
+  */
+  interface CoplanarFaces : Predicate{
+    void            SetFace ( in long theFaceID );
+    void            SetTolerance( in double theToler );
+  };
+
   /*!
   *  Filter
   */
@@ -360,13 +371,13 @@ module SMESH
     *   BinaryOp      - binary logical operation FT_LogicalAND, FT_LogicalOR or
     *                   (FT_Undefined must be for the last criterion)
     *   ThresholdStr  - Threshold value defined as string. Used for:
-    *                   1. Diaposon of identifiers. Example: "1,2,3,5-10,12,27-29"
+    *                   1. Diapason of identifiers. Example: "1,2,3,5-10,12,27-29"
     *                   2. BelongToGeom predicate for storing name of shape
     *                   3. GroupColor predicate for storing group color "0.2;0;0.5"
     *   ThresholdID   - One more threshold value defined as string. Used for:
     *                   1. BelongToGeom predicate for storing id of shape
     *   Tolerance     - Tolerance is used for comparators (EqualTo comparision) and for
-    *                   "Belong to plane" and "Belong to cylinder" predicates
+    *                   "Belong to plane", "Belong to cylinder" etc predicates
     *   TypeOfElement - type of element SMESH::NODE, SMESH::FACE (used by BelongToGeom predicate only)
     *   Precision     - Precision of numerical functors
     */
@@ -477,6 +488,7 @@ module SMESH
 
     GroupColor        CreateGroupColor();
     ElemGeomType      CreateElemGeomType();
+    CoplanarFaces     CreateCoplanarFaces();
 
     /*!
     *  Create comparators ( predicates )
index 387091de33b13916fdb8ff3578186138d3f0ec65..c010980be7c1d91457cfe57f33a88a64a03fdbd1 100644 (file)
@@ -29,6 +29,8 @@
 
 module SMESH
 {
+  enum Bnd_Dimension { BND_2DFROM3D, BND_1DFROM3D, BND_1DFROM2D };
+  
   /*!
    * This interface makes modifications on the Mesh - removing elements and nodes etc.
    */
@@ -921,12 +923,34 @@ module SMESH
                                           in GEOM::GEOM_Object theShape );
 
     /*!
-     * \brief Generated skin mesh (containing 2D cells) from 3D mesh
+     * \brief Generates skin mesh (containing 2D cells) from 3D mesh
      * The created 2D mesh elements based on nodes of free faces of boundary volumes
      * \return TRUE if operation has been completed successfully, FALSE otherwise
      */
     boolean Make2DMeshFrom3D();
 
+    /*!
+     * \brief Creates missing boundary elements
+     *  \param elements - elements whose boundary is to be checked
+     *  \param dimension - defines type of boundary elements to create
+     *  \param groupName - a name of group to store created boundary elements in,
+     *                     "" means not to create the group
+     *  \param meshName - a name of new mesh to store created boundary elements in,
+     *                     "" means not to create the new mesh
+     *  \param toCopyElements - if true, the checked elements will be copied into the new mesh
+     *  \param toCopyExistingBondary - if true, not only new but also pre-existing 
+     *                                boundary elements will be copied into the new mesh
+     *  \param group - returns the create group, if any
+     *  \retval SMESH::SMESH_Mesh - the mesh where elements were added to
+     */
+    SMESH::SMESH_Mesh MakeBoundaryMesh(in SMESH_IDSource elements,
+                                       in Bnd_Dimension  dimension, 
+                                       in string         groupName,
+                                       in string         meshName,
+                                       in boolean        toCopyElements,
+                                       in boolean        toCopyExistingBondary,
+                                       out SMESH_Group   group);
+
   };
 };
 
index ed3f5aff7f32166ccacfab60e107025e13f5191f..9541a21336cbae3616e2787e71cf53f90e3a541d 100644 (file)
@@ -70,6 +70,11 @@ dist_salomeres_DATA = \
        mesh_pyramid.png \
        mesh_quad_n.png \
        mesh_quad.png \
+       mesh_quadrangle_quadpref.png \
+       mesh_quadrangle_quadpref_reversed.png \
+       mesh_quadrangle_reduced.png \
+       mesh_quadrangle_standard.png \
+       mesh_quadrangle_triapref.png \
        mesh_rem_element.png \
        mesh_rem_node.png \
        mesh_rem_orphan_nodes.png \
index a1806b5cd5b6e53bae2db01088519fb2850bfbba..b7993a340edf69ebd05615a84c3dd73a8a9d4d97 100644 (file)
@@ -67,6 +67,7 @@
     <parameter name="scalar_bar_vertical_y"        value="0.1" />
     <parameter name="DisplayMode"                  value="true" />
     <parameter name="auto_update"                  value="true" />
+    <parameter name="update_limit"                 value="500000" />
     <parameter name="display_mode"                 value="1"    />
     <parameter name="auto_groups"                  value="false"/>
     <parameter name="show_result_notification"     value="2"/>
index 37dda8a94f7fea4ee8af1500e841eec42f652f40..557cd9613f73d9731e27473808dfff9031e7e183 100644 (file)
     <hypothesis type="MaxElementVolume"
                 label-id="Max. Element Volume"
                 icon-id="mesh_hypo_volume.png"
-               need-geom = "false"
+               need-geom="false"
                 dim="3"/>
 
     <hypothesis type="ProjectionSource3D"
diff --git a/resources/mesh_quadrangle_quadpref.png b/resources/mesh_quadrangle_quadpref.png
new file mode 100644 (file)
index 0000000..429a610
Binary files /dev/null and b/resources/mesh_quadrangle_quadpref.png differ
diff --git a/resources/mesh_quadrangle_quadpref_reversed.png b/resources/mesh_quadrangle_quadpref_reversed.png
new file mode 100644 (file)
index 0000000..fb530ea
Binary files /dev/null and b/resources/mesh_quadrangle_quadpref_reversed.png differ
diff --git a/resources/mesh_quadrangle_reduced.png b/resources/mesh_quadrangle_reduced.png
new file mode 100644 (file)
index 0000000..985c236
Binary files /dev/null and b/resources/mesh_quadrangle_reduced.png differ
diff --git a/resources/mesh_quadrangle_standard.png b/resources/mesh_quadrangle_standard.png
new file mode 100644 (file)
index 0000000..957a0f2
Binary files /dev/null and b/resources/mesh_quadrangle_standard.png differ
diff --git a/resources/mesh_quadrangle_triapref.png b/resources/mesh_quadrangle_triapref.png
new file mode 100644 (file)
index 0000000..d14440d
Binary files /dev/null and b/resources/mesh_quadrangle_triapref.png differ
index 59a23c2388eb8649bbee7660016d925044bd7029..a8cf8c41925edf48730610cde8d1cc1f3c315ac3 100644 (file)
@@ -23,6 +23,7 @@
 #include "SMESH_ControlsDef.hxx"
 
 #include <set>
+#include <limits>
 
 #include <BRepAdaptor_Surface.hxx>
 #include <BRepClass_FaceClassifier.hxx>
 */
 
 namespace{
+
+  inline gp_XYZ gpXYZ(const SMDS_MeshNode* aNode )
+  {
+    return gp_XYZ(aNode->X(), aNode->Y(), aNode->Z() );
+  }
+
   inline double getAngle( const gp_XYZ& P1, const gp_XYZ& P2, const gp_XYZ& P3 )
   {
     gp_Vec v1( P1 - P2 ), v2( P3 - P2 );
@@ -171,6 +178,26 @@ namespace{
     return aResult;
   }
 
+  gp_XYZ getNormale( const SMDS_MeshFace* theFace, bool* ok=0 )
+  {
+    int aNbNode = theFace->NbNodes();
+
+    gp_XYZ q1 = gpXYZ( theFace->GetNode(1)) - gpXYZ( theFace->GetNode(0));
+    gp_XYZ q2 = gpXYZ( theFace->GetNode(2)) - gpXYZ( theFace->GetNode(0));
+    gp_XYZ n  = q1 ^ q2;
+    if ( aNbNode > 3 ) {
+      gp_XYZ q3 = gpXYZ( theFace->GetNode(3)) - gpXYZ( theFace->GetNode(0));
+      n += q2 ^ q3;
+    }
+    double len = n.Modulus();
+    bool zeroLen = ( len <= numeric_limits<double>::min());
+    if ( !zeroLen )
+      n /= len;
+
+    if (ok) *ok = !zeroLen;
+
+    return n;
+  }
 }
 
 
@@ -178,8 +205,8 @@ namespace{
 using namespace SMESH::Controls;
 
 /*
-                                FUNCTORS
-*/
*                               FUNCTORS
+ */
 
 /*
   Class       : NumericalFunctor
@@ -2002,13 +2029,71 @@ SMDSAbs_GeometryType ElemGeomType::GetGeomType() const
   return myGeomType;
 }
 
+//================================================================================
+/*!
+ * \brief Class CoplanarFaces
+ */
+//================================================================================
+
+CoplanarFaces::CoplanarFaces()
+  : myMesh(0), myFaceID(0), myToler(0)
+{
+}
+bool CoplanarFaces::IsSatisfy( long theElementId )
+{
+  if ( myCoplanarIDs.empty() )
+  {
+    // Build a set of coplanar face ids
+
+    if ( !myMesh || !myFaceID || !myToler )
+      return false;
+
+    const SMDS_MeshElement* face = myMesh->FindElement( myFaceID );
+    if ( !face || face->GetType() != SMDSAbs_Face )
+      return false;
+
+    bool normOK;
+    gp_Vec myNorm = getNormale( static_cast<const SMDS_MeshFace*>(face), &normOK );
+    if (!normOK)
+      return false;
+
+    const double radianTol = myToler * PI180;
+    typedef SMDS_StdIterator< const SMDS_MeshElement*, SMDS_ElemIteratorPtr > TFaceIt;
+    std::set<const SMDS_MeshElement*> checkedFaces, checkedNodes;
+    std::list<const SMDS_MeshElement*> faceQueue( 1, face );
+    while ( !faceQueue.empty() )
+    {
+      face = faceQueue.front();
+      if ( checkedFaces.insert( face ).second )
+      {
+        gp_Vec norm = getNormale( static_cast<const SMDS_MeshFace*>(face), &normOK );
+        if (!normOK || myNorm.Angle( norm ) <= radianTol)
+        {
+          myCoplanarIDs.insert( face->GetID() );
+          std::set<const SMDS_MeshElement*> neighborFaces;
+          for ( int i = 0; i < face->NbCornerNodes(); ++i )
+          {
+            const SMDS_MeshNode* n = face->GetNode( i );
+            if ( checkedNodes.insert( n ).second )
+              neighborFaces.insert( TFaceIt( n->GetInverseElementIterator(SMDSAbs_Face)),
+                                    TFaceIt());
+          }
+          faceQueue.insert( faceQueue.end(), neighborFaces.begin(), neighborFaces.end() );
+        }
+      }
+      faceQueue.pop_front();
+    }
+  }
+  return myCoplanarIDs.count( theElementId );
+}
+
 /*
-  Class       : RangeOfIds
-  Description : Predicate for Range of Ids.
-                Range may be specified with two ways.
-                1. Using AddToRange method
-                2. With SetRangeStr method. Parameter of this method is a string
-                   like as "1,2,3,50-60,63,67,70-"
+  *Class       : RangeOfIds
+  *Description : Predicate for Range of Ids.
+  *              Range may be specified with two ways.
+  *              1. Using AddToRange method
+  *              2. With SetRangeStr method. Parameter of this method is a string
+  *                 like as "1,2,3,50-60,63,67,70-"
 */
 
 //=======================================================================
@@ -2638,32 +2723,6 @@ static void getLinks( const SMDS_MeshFace* theFace,
   }
 }
 
-static gp_XYZ getNormale( const SMDS_MeshFace* theFace )
-{
-  gp_XYZ n;
-  int aNbNode = theFace->NbNodes();
-  TColgp_Array1OfXYZ anArrOfXYZ(1,4);
-  SMDS_ElemIteratorPtr aNodeItr = theFace->nodesIterator();
-  int i = 1;
-  for ( ; aNodeItr->more() && i <= 4; i++ ) {
-    SMDS_MeshNode* aNode = (SMDS_MeshNode*)aNodeItr->next();
-    anArrOfXYZ.SetValue(i, gp_XYZ( aNode->X(), aNode->Y(), aNode->Z() ) );
-  }
-
-  gp_XYZ q1 = anArrOfXYZ.Value(2) - anArrOfXYZ.Value(1);
-  gp_XYZ q2 = anArrOfXYZ.Value(3) - anArrOfXYZ.Value(1);
-  n  = q1 ^ q2;
-  if ( aNbNode > 3 ) {
-    gp_XYZ q3 = anArrOfXYZ.Value(4) - anArrOfXYZ.Value(1);
-    n += q2 ^ q3;
-  }
-  double len = n.Modulus();
-  if ( len > 0 )
-    n /= len;
-
-  return n;
-}
-
 bool ManifoldPart::findConnected
                  ( const ManifoldPart::TDataMapFacePtrInt& theAllFacePtrInt,
                   SMDS_MeshFace*                           theStartFace,
index 5849c1f83647b8c058fc40d28d9fa41b50dd6844..1fde3f281b60130be26003a0369dc5db1e4a4af8 100644 (file)
@@ -770,11 +770,11 @@ namespace SMESH{
     class SMESHCONTROLS_EXPORT ElemGeomType: public virtual Predicate{
     public:
       ElemGeomType();
-      virtual void        SetMesh( const SMDS_Mesh* theMesh );
-      virtual bool        IsSatisfy( long theElementId );
-      void                SetType( SMDSAbs_ElementType theType );
-      virtual             SMDSAbs_ElementType GetType() const;
-      void                SetGeomType( SMDSAbs_GeometryType theType );
+      virtual void         SetMesh( const SMDS_Mesh* theMesh );
+      virtual bool         IsSatisfy( long theElementId );
+      void                 SetType( SMDSAbs_ElementType theType );
+      virtual              SMDSAbs_ElementType GetType() const;
+      void                 SetGeomType( SMDSAbs_GeometryType theType );
       virtual SMDSAbs_GeometryType GetGeomType() const;
 
     private:
@@ -784,6 +784,31 @@ namespace SMESH{
     };
     typedef boost::shared_ptr<ElemGeomType> ElemGeomTypePtr;
 
+    /*
+      Class       : CoplanarFaces
+      Description : Predicate to check angle between faces
+    */
+    class SMESHCONTROLS_EXPORT CoplanarFaces: public virtual Predicate
+    {
+    public:
+      CoplanarFaces();
+      void                 SetFace( long theID )                   { myFaceID = theID; }
+      long                 GetFace() const                         { return myFaceID; }
+      void                 SetTolerance (const double theToler)    { myToler = theToler; }
+      double               GetTolerance () const                   { return myToler; }
+      virtual void         SetMesh( const SMDS_Mesh* theMesh )     { myMesh = theMesh; }
+      virtual              SMDSAbs_ElementType GetType() const     { return SMDSAbs_Face; }
+
+      virtual bool         IsSatisfy( long theElementId );
+
+    private:
+      const SMDS_Mesh*     myMesh;
+      long                 myFaceID;
+      double               myToler;
+      std::set< long >     myCoplanarIDs;
+    };
+    typedef boost::shared_ptr<CoplanarFaces> CoplanarFacesPtr;
+
     /*
       FILTER
     */
index dd99ac11a474597ad75afa3855eb4bc98b28c7d5..f60a122a965563f9229e1b341677100446950199 100644 (file)
@@ -27,7 +27,9 @@
 //
 #include "SMESH_HypoFilter.hxx"
 
+#include "SMESH_Gen.hxx"
 #include "SMESH_Hypothesis.hxx"
+#include "SMESH_MesherHelper.hxx"
 #include "SMESH_subMesh.hxx"
 
 #include <TopExp_Explorer.hxx>
@@ -115,7 +117,7 @@ bool SMESH_HypoFilter::InstancePredicate::IsOk(const SMESH_Hypothesis* aHyp,
 //=======================================================================
 
 bool SMESH_HypoFilter::IsAssignedToPredicate::IsOk(const SMESH_Hypothesis* aHyp,
-                                               const TopoDS_Shape&     aShape) const
+                                                   const TopoDS_Shape&     aShape) const
 {
   return ( !_mainShape.IsNull() && !aShape.IsNull() && _mainShape.IsSame( aShape ));
 }
@@ -128,14 +130,19 @@ bool SMESH_HypoFilter::IsAssignedToPredicate::IsOk(const SMESH_Hypothesis* aHyp,
 bool SMESH_HypoFilter::IsMoreLocalThanPredicate::IsOk(const SMESH_Hypothesis* aHyp,
                                                       const TopoDS_Shape&     aShape) const
 {
-  // issue 0020963
-  // if aShape is COMPOUND (i.e. most probably a GEOM group) then
-  // it is more local if it contains shapes of less dimension than _shapeType
-  if ( aShape.ShapeType() == TopAbs_COMPOUND )
-    for ( int moreLocalType = _shapeType+1; moreLocalType < int(TopAbs_SHAPE); ++moreLocalType )
-      if ( TopExp_Explorer( aShape, TopAbs_ShapeEnum(moreLocalType)).More())
-        return true;
-  return ( aShape.ShapeType() > _shapeType );
+  if ( SMESH_MesherHelper::IsSubShape( aShape, /*mainShape=*/_shape ))
+    return true;
+
+  if ( aShape.ShapeType() == TopAbs_COMPOUND && 
+       !SMESH_MesherHelper::IsSubShape( _shape, /*mainShape=*/aShape)) // issue 0020963
+  {
+    for ( int type = TopAbs_SOLID; type < TopAbs_SHAPE; ++type )
+      if ( aHyp->GetDim() == SMESH_Gen::GetShapeDim( TopAbs_ShapeEnum( type )))
+        for ( TopExp_Explorer exp( aShape, TopAbs_ShapeEnum( type )); exp.More(); exp.Next())
+          if ( SMESH_MesherHelper::IsSubShape( exp.Current(), /*mainShape=*/_shape ))
+            return true;
+  }
+  return false;
 }
 
 //=======================================================================
index 0fb043e57debecc43d06911a28a3afb488a8ea4e..c2ad8b75370c1e4f3515d4dd4769604d4ef0dbf6 100644 (file)
@@ -23,7 +23,6 @@
 //  SMESH SMESH : implementaion of SMESH idl descriptions
 //  File   : SMESH_HypoFilter.hxx
 //  Module : SMESH
-//  $Header$
 //
 #ifndef SMESH_HypoFilter_HeaderFile
 #define SMESH_HypoFilter_HeaderFile
@@ -168,8 +167,8 @@ class SMESH_EXPORT SMESH_HypoFilter: public SMESH_HypoPredicate
   };
         
   struct IsMoreLocalThanPredicate : public SMESH_HypoPredicate {
-    TopAbs_ShapeEnum _shapeType;
-    IsMoreLocalThanPredicate( const TopoDS_Shape& shape ):_shapeType(shape.ShapeType()){}
+    TopoDS_Shape _shape;
+    IsMoreLocalThanPredicate( const TopoDS_Shape& shape ):_shape(shape){}
     bool IsOk(const SMESH_Hypothesis* aHyp,
               const TopoDS_Shape&     aShape) const;
   };
index b802540f09405bf6c1902001f5da04a41d31a499..f26db9a0cbe68c21c6d7f6ac02667a37449a2fc2 100644 (file)
@@ -35,6 +35,7 @@
 #include "SMDS_SpacePosition.hxx"
 #include "SMDS_QuadraticFaceOfNodes.hxx"
 #include "SMDS_MeshGroup.hxx"
+#include "SMDS_SetIterator.hxx"
 
 #include "SMESHDS_Group.hxx"
 #include "SMESHDS_Mesh.hxx"
@@ -99,6 +100,8 @@ using namespace SMESH::Controls;
 typedef map<const SMDS_MeshElement*, list<const SMDS_MeshNode*> >    TElemOfNodeListMap;
 typedef map<const SMDS_MeshElement*, list<const SMDS_MeshElement*> > TElemOfElemListMap;
 
+typedef SMDS_SetIterator< SMDS_pElement, TIDSortedElemSet::const_iterator> TSetIterator;
+
 //=======================================================================
 //function : SMESH_MeshEditor
 //purpose  :
@@ -219,6 +222,7 @@ SMESH_MeshEditor::AddElement(const vector<const SMDS_MeshNode*> & node,
                                             node[16],node[17],node[18],node[19] );
     }
   }
+  if ( e ) myLastCreatedElems.Append( e );
   return e;
 }
 
@@ -5531,10 +5535,8 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
       }
     }
     else if ( theCopy ) {
-      if ( SMDS_MeshElement* copy = AddElement( nodes, elem->GetType(), elem->IsPoly() )) {
-        myLastCreatedElems.Append( copy );
+      if ( AddElement( nodes, elem->GetType(), elem->IsPoly() ))
         srcElems.Append( elem );
-      }
     }
     else {
       // reverse element as it was reversed by transformation
@@ -5871,7 +5873,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
   {
   public:
 
-    ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType);
+    ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType, double tolerance = NodeRadius );
     void getElementsNearPoint( const gp_Pnt& point, TIDSortedElemSet& foundElems);
     void getElementsNearLine ( const gp_Ax1& line, TIDSortedElemSet& foundElems);
     ~ElementBndBoxTree();
@@ -5887,7 +5889,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
     {
       const SMDS_MeshElement* _element;
       int                     _refCount; // an ElementBox can be included in several tree branches
-      ElementBox(const SMDS_MeshElement* elem);
+      ElementBox(const SMDS_MeshElement* elem, double tolerance);
     };
     vector< ElementBox* > _elements;
   };
@@ -5898,7 +5900,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
    */
   //================================================================================
 
-  ElementBndBoxTree::ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType)
+  ElementBndBoxTree::ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType, double tolerance)
     :SMESH_Octree( new SMESH_Octree::Limit( MaxLevel, /*minSize=*/0. ))
   {
     int nbElems = mesh.GetMeshInfo().NbElements( elemType );
@@ -5906,7 +5908,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
 
     SMDS_ElemIteratorPtr elemIt = mesh.elementsIterator( elemType );
     while ( elemIt->more() )
-      _elements.push_back( new ElementBox( elemIt->next() ));
+      _elements.push_back( new ElementBox( elemIt->next(),tolerance  ));
 
     if ( _elements.size() > MaxNbElemsInLeaf )
       compute();
@@ -6030,14 +6032,14 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
    */
   //================================================================================
 
-  ElementBndBoxTree::ElementBox::ElementBox(const SMDS_MeshElement* elem)
+  ElementBndBoxTree::ElementBox::ElementBox(const SMDS_MeshElement* elem, double tolerance)
   {
     _element  = elem;
     _refCount = 1;
     SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
     while ( nIt->more() )
       Add( SMESH_MeshEditor::TNodeXYZ( cast2Node( nIt->next() )));
-    Enlarge( NodeRadius );
+    Enlarge( tolerance );
   }
 
 } // namespace
@@ -6157,7 +6159,7 @@ double SMESH_ElementSearcherImpl::getTolerance()
           elemSize = max( dist, elemSize );
         }
       }
-      _tolerance = 1e-6 * elemSize;
+      _tolerance = 1e-4 * elemSize;
     }
   }
   return _tolerance;
@@ -6348,7 +6350,7 @@ FindElementsByPoint(const gp_Pnt&                      point,
     if ( !_ebbTree || _elementType != type )
     {
       if ( _ebbTree ) delete _ebbTree;
-      _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = type );
+      _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = type, tolerance );
     }
     TIDSortedElemSet suspectElems;
     _ebbTree->getElementsNearPoint( point, suspectElems );
@@ -9829,7 +9831,7 @@ bool SMESH_MeshEditor::doubleNodes( SMESHDS_Mesh*     theMeshDS,
       continue;
 
     if ( theIsDoubleElem )
-      myLastCreatedElems.Append( AddElement(newNodes, anElem->GetType(), anElem->IsPoly()) );
+      AddElement(newNodes, anElem->GetType(), anElem->IsPoly());
     else
       theMeshDS->ChangeElementNodes( anElem, &newNodes[ 0 ], anElem->NbNodes() );
 
@@ -10054,7 +10056,7 @@ bool SMESH_MeshEditor::DoubleNodesInRegion( const TIDSortedElemSet& theElems,
 
 //================================================================================
 /*!
- * \brief Generated skin mesh (containing 2D cells) from 3D mesh
+ * \brief Generates skin mesh (containing 2D cells) from 3D mesh
  * The created 2D mesh elements based on nodes of free faces of boundary volumes
  * \return TRUE if operation has been completed successfully, FALSE otherwise
  */
@@ -10096,9 +10098,195 @@ bool SMESH_MeshEditor::Make2DMeshFrom3D()
         nbExisted++;
         continue; // face already exsist
       }
-      myLastCreatedElems.Append( AddElement(nodes, SMDSAbs_Face, isPoly && iface == 1) );
+      AddElement(nodes, SMDSAbs_Face, isPoly && iface == 1);
       nbCreated++;
     }
   }
   return ( nbFree==(nbExisted+nbCreated) );
 }
+
+namespace
+{
+  inline const SMDS_MeshNode* getNodeWithSameID(SMESHDS_Mesh* mesh, const SMDS_MeshNode* node)
+  {
+    if ( const SMDS_MeshNode* n = mesh->FindNode( node->GetID() ))
+      return n;
+    return mesh->AddNodeWithID( node->X(),node->Y(),node->Z(), node->GetID() );
+  }
+}
+//================================================================================
+/*!
+ * \brief Creates missing boundary elements
+ *  \param elements - elements whose boundary is to be checked
+ *  \param dimension - defines type of boundary elements to create
+ *  \param group - a group to store created boundary elements in
+ *  \param targetMesh - a mesh to store created boundary elements in
+ *  \param toCopyElements - if true, the checked elements will be copied into the targetMesh
+ *  \param toCopyExistingBondary - if true, not only new but also pre-existing 
+ *                                boundary elements will be copied into the targetMesh
+ */
+//================================================================================
+
+void SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
+                                        Bnd_Dimension           dimension,
+                                        SMESH_Group*            group/*=0*/,
+                                        SMESH_Mesh*             targetMesh/*=0*/,
+                                        bool                    toCopyElements/*=false*/,
+                                        bool                    toCopyExistingBondary/*=false*/)
+{
+  SMDSAbs_ElementType missType = (dimension == BND_2DFROM3D) ? SMDSAbs_Face : SMDSAbs_Edge;
+  SMDSAbs_ElementType elemType = (dimension == BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
+  // hope that all elements are of the same type, do not check them all
+  if ( !elements.empty() && (*elements.begin())->GetType() != elemType )
+    throw SALOME_Exception(LOCALIZED("wrong element type"));
+
+  if ( !targetMesh )
+    toCopyElements = toCopyExistingBondary = false;
+
+  SMESH_MeshEditor tgtEditor( targetMesh ? targetMesh : myMesh );
+  SMESHDS_Mesh* aMesh = GetMeshDS(), *tgtMeshDS = tgtEditor.GetMeshDS();
+
+  SMDS_VolumeTool vTool;
+  TIDSortedElemSet emptySet, avoidSet;
+  int inode;
+
+  typedef vector<const SMDS_MeshNode*> TConnectivity;
+
+  SMDS_ElemIteratorPtr eIt;
+  if (elements.empty())
+    eIt = aMesh->elementsIterator(elemType);
+  else
+    eIt = SMDS_ElemIteratorPtr( new TSetIterator( elements.begin(), elements.end() ));
+
+  while (eIt->more())
+  {
+    const SMDS_MeshElement* elem = eIt->next();
+    const int iQuad = elem->IsQuadratic();
+
+    // 1. For an elem, get present bnd elements and connectivities of missing bnd elements
+    vector<const SMDS_MeshElement*> presentBndElems;
+    vector<TConnectivity>           missingBndElems;
+    TConnectivity nodes;
+    if ( vTool.Set(elem) ) // elem is a volume ------------------------------------------
+    { 
+      vTool.SetExternalNormal();
+      for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ )
+      {
+        if (!vTool.IsFreeFace(iface))
+          continue;
+        int nbFaceNodes = vTool.NbFaceNodes(iface);
+        const SMDS_MeshNode** nn = vTool.GetFaceNodes(iface);
+        if ( missType == SMDSAbs_Edge ) // boundary edges
+        {
+          nodes.resize( 2+iQuad );
+          for ( int i = 0; i < nbFaceNodes; i += 1+iQuad)
+          {
+            for ( int j = 0; j < nodes.size(); ++j )
+              nodes[j] =nn[i+j];
+            if ( const SMDS_MeshElement* edge =
+                 aMesh->FindElement(nodes,SMDSAbs_Edge,/*noMedium=*/0))
+              presentBndElems.push_back( edge );
+            else
+              missingBndElems.push_back( nodes );
+          }
+        }
+        else // boundary face
+        {
+          nodes.clear();
+          for ( inode = 0; inode < nbFaceNodes; inode += 1+iQuad)
+            nodes.push_back( nn[inode] );
+          if (iQuad)
+            for ( inode = 1; inode < nbFaceNodes; inode += 2)
+              nodes.push_back( nn[inode] );
+
+          if (const SMDS_MeshFace * f = aMesh->FindFace( nodes ) )
+            presentBndElems.push_back( f );
+          else
+            missingBndElems.push_back( nodes );
+        }
+      }
+    }
+    else                     // elem is a face ------------------------------------------
+    {
+      avoidSet.clear(), avoidSet.insert( elem );
+      int nbNodes = elem->NbCornerNodes();
+      nodes.resize( 2 /*+ iQuad*/);
+      for ( int i = 0; i < nbNodes; i++ )
+      {
+        nodes[0] = elem->GetNode(i);
+        nodes[1] = elem->GetNode((i+1)%nbNodes);
+        if ( FindFaceInSet( nodes[0], nodes[1], emptySet, avoidSet))
+          continue; // not free link
+
+        //if ( iQuad )
+        //nodes[2] = elem->GetNode( i + nbNodes );
+        if ( const SMDS_MeshElement* edge =
+             aMesh->FindElement(nodes,SMDSAbs_Edge,/*noMedium=*/true))
+          presentBndElems.push_back( edge );
+        else
+          missingBndElems.push_back( nodes );
+      }
+    }
+
+    // 2. Add missing boundary elements
+    if ( targetMesh != myMesh )
+      // instead of making a map of nodes in this mesh and targetMesh,
+      // we create nodes with same IDs. We can renumber them later, if needed
+      for ( int i = 0; i < missingBndElems.size(); ++i )
+      {
+        TConnectivity& srcNodes = missingBndElems[i];
+        TConnectivity  nodes( srcNodes.size() );
+        for ( inode = 0; inode < nodes.size(); ++inode )
+          nodes[inode] = getNodeWithSameID( tgtMeshDS, srcNodes[inode] );
+        tgtEditor.AddElement(nodes, missType, elem->IsPoly() && nodes.size()/(iQuad+1)>4);
+      }
+    else
+      for ( int i = 0; i < missingBndElems.size(); ++i )
+      {
+        TConnectivity&  nodes = missingBndElems[i];
+        tgtEditor.AddElement(nodes, missType, elem->IsPoly() && nodes.size()/(iQuad+1)>4);
+      }
+
+    // 3. Copy present boundary elements
+    if ( toCopyExistingBondary )
+      for ( int i = 0 ; i < presentBndElems.size(); ++i )
+      {
+        const SMDS_MeshElement* e = presentBndElems[i];
+        TConnectivity nodes( e->NbNodes() );
+        for ( inode = 0; inode < nodes.size(); ++inode )
+          nodes[inode] = getNodeWithSameID( tgtMeshDS, e->GetNode(inode) );
+        tgtEditor.AddElement(nodes, missType, e->IsPoly());
+        // leave only missing elements in tgtEditor.myLastCreatedElems
+        tgtEditor.myLastCreatedElems.Remove( tgtEditor.myLastCreatedElems.Size() );
+      }
+  } // loop on given elements
+
+  // 4. Fill group with missing boundary elements
+  if ( group )
+  {
+    if ( SMESHDS_Group* g = dynamic_cast<SMESHDS_Group*>( group->GetGroupDS() ))
+      for ( int i = 0; i < tgtEditor.myLastCreatedElems.Size(); ++i )
+        g->SMDSGroup().Add( tgtEditor.myLastCreatedElems( i+1 ));
+  }
+  tgtEditor.myLastCreatedElems.Clear();
+
+  // 5. Copy given elements
+  if ( toCopyElements )
+  {
+    if (elements.empty())
+      eIt = aMesh->elementsIterator(elemType);
+    else
+      eIt = SMDS_ElemIteratorPtr( new TSetIterator( elements.begin(), elements.end() ));
+    while (eIt->more())
+    {
+      const SMDS_MeshElement* elem = eIt->next();
+      TConnectivity nodes( elem->NbNodes() );
+      for ( inode = 0; inode < nodes.size(); ++inode )
+        nodes[inode] = getNodeWithSameID( tgtMeshDS, elem->GetNode(inode) );
+      tgtEditor.AddElement(nodes, elemType, elem->IsPoly());
+
+      tgtEditor.myLastCreatedElems.Clear();
+    }
+  }
+  return;
+}
index 80287eea379542e32a355f70ec423204d9c6abab..dabe3f8db851dacacfef236dd253a66484f117c3 100644 (file)
@@ -624,13 +624,17 @@ public:
                             const TIDSortedElemSet& theNodesNot,
                             const TopoDS_Shape&     theShape );
   
-  /*!
-   * \brief Generated skin mesh (containing 2D cells) from 3D mesh
-   * The created 2D mesh elements based on nodes of free faces of boundary volumes
-   * \return TRUE if operation has been completed successfully, FALSE otherwise
-   */
   bool Make2DMeshFrom3D();
-  
+
+  enum Bnd_Dimension { BND_2DFROM3D, BND_1DFROM3D, BND_1DFROM2D };
+
+  void MakeBoundaryMesh(const TIDSortedElemSet& elements,
+                        Bnd_Dimension           dimension,
+                        SMESH_Group*            group = 0,
+                        SMESH_Mesh*             targetMesh = 0,
+                        bool                    toCopyElements = false,
+                        bool                    toCopyExistingBondary = false);
+
 private:
 
   /*!
index 0a3887f702fd5eec16baeb1b22b1573390d3d2ba..b695e1276a5be8fc8310f060e75eaec3f694ba97 100644 (file)
@@ -356,7 +356,7 @@ gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face&   F,
       static_cast<const SMDS_FacePosition*>(n->GetPosition().get());
     uv.SetCoord(fpos->GetUParameter(),fpos->GetVParameter());
     if ( check )
-      uvOK = CheckNodeUV( F, n, uv.ChangeCoord(), 2*BRep_Tool::Tolerance( F ));
+      uvOK = CheckNodeUV( F, n, uv.ChangeCoord(), 10*MaxTolerance( F ));
   }
   else if(Pos->GetTypeOfPosition()==SMDS_TOP_EDGE)
   {
@@ -375,7 +375,7 @@ gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face&   F,
     else
       uv.SetCoord(0.,0.);
     if ( check || !validU )
-      uvOK = CheckNodeUV( F, n, uv.ChangeCoord(), 2*BRep_Tool::Tolerance( E ),/*force=*/ !validU );
+      uvOK = CheckNodeUV( F, n, uv.ChangeCoord(), 10*MaxTolerance( F ),/*force=*/ !validU );
 
     // for a node on a seam edge select one of UVs on 2 pcurves
     if ( n2 && IsSeamShape( edgeID ) )
@@ -1521,6 +1521,26 @@ bool SMESH_MesherHelper::IsSubShape( const TopoDS_Shape& shape, SMESH_Mesh* aMes
     shape.ShapeType() == TopAbs_COMPOUND && aMesh->GetMeshDS()->IsGroupOfSubShapes( shape );
 }
 
+//================================================================================
+/*!
+ * \brief Return maximal tolerance of shape
+ */
+//================================================================================
+
+double SMESH_MesherHelper::MaxTolerance( const TopoDS_Shape& shape )
+{
+  double tol = Precision::Confusion();
+  TopExp_Explorer exp;
+  for ( exp.Init( shape, TopAbs_FACE ); exp.More(); exp.Next() )
+    tol = Max( tol, BRep_Tool::Tolerance( TopoDS::Face( exp.Current())));
+  for ( exp.Init( shape, TopAbs_EDGE ); exp.More(); exp.Next() )
+    tol = Max( tol, BRep_Tool::Tolerance( TopoDS::Edge( exp.Current())));
+  for ( exp.Init( shape, TopAbs_VERTEX ); exp.More(); exp.Next() )
+    tol = Max( tol, BRep_Tool::Tolerance( TopoDS::Vertex( exp.Current())));
+
+  return tol;
+}
+
 //=======================================================================
 //function : IsQuadraticMesh
 //purpose  : Check mesh without geometry for: if all elements on this shape are quadratic,
index 14d9225e6535bc38f732c78be76b0968edcb897f..7af79e5cff44a38b306df7a39a29c73d614303d3 100644 (file)
@@ -140,6 +140,8 @@ public:
 
   static bool IsSubShape( const TopoDS_Shape& shape, SMESH_Mesh* aMesh );
 
+  static double MaxTolerance( const TopoDS_Shape& shape );
+
 
 public:
   // ---------- PUBLIC INSTANCE METHODS ----------
index 4867a2ca1fa7aef924b942d7a099aa645afe5a82..1efc41fd29c3cf65fb4d847210218ca61b121a10 100644 (file)
 
     SalomeApp_Application* anApp = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
     SUIT_ViewManager* vm = anApp->activeViewManager();
-    int nbSf = vm->getViewsCount();
+    int nbSf = vm ? vm->getViewsCount() : 0;
 
     SALOME_ListIteratorOfListIO It(selected);
 
           std::string anEntry = SO->GetID();
 
           /** Erase graphical object **/
-          if(SO->FindAttribute(anAttr, "AttributeIOR")){
+          if(SO->FindAttribute(anAttr, "AttributeIOR") && vm ){
             QVector<SUIT_ViewWindow*> aViews = vm->getViews();
             for(int i = 0; i < nbSf; i++){
               SUIT_ViewWindow *sf = aViews[i];
@@ -1330,13 +1330,22 @@ LightApp_SelectionMgr* SMESHGUI::selectionMgr()
     return 0;
 }
 
-bool SMESHGUI::automaticUpdate()
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+bool SMESHGUI::automaticUpdate(unsigned int requestedSize, bool* limitExceeded)
 {
   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
   if ( !resMgr )
     return false;
 
-  return resMgr->booleanValue( "SMESH", "auto_update", false );
+  bool autoUpdate  = resMgr->booleanValue( "SMESH", "auto_update",  false );
+  long updateLimit = resMgr->integerValue( "SMESH", "update_limit", 500000 );
+  bool exceeded = updateLimit > 0 && requestedSize > updateLimit;
+  if ( limitExceeded ) *limitExceeded = autoUpdate && exceeded;
+  return autoUpdate && !exceeded;
 }
 
 //=============================================================================
@@ -3821,8 +3830,12 @@ void SMESHGUI::createPreferences()
   // General tab ------------------------------------------------------------------------
   int genTab = addPreference( tr( "PREF_TAB_GENERAL" ) );
 
-  int updateGroup = addPreference( tr( "PREF_GROUP_UPDATE" ), genTab );
-  addPreference( tr( "PREF_AUTO_UPDATE" ), updateGroup, LightApp_Preferences::Bool, "SMESH", "auto_update" );
+  int autoUpdate = addPreference( tr( "PREF_AUTO_UPDATE" ), genTab, LightApp_Preferences::Auto, "SMESH", "auto_update" );
+  int lim = addPreference( tr( "PREF_UPDATE_LIMIT" ), autoUpdate, LightApp_Preferences::IntSpin, "SMESH", "update_limit" );
+  setPreferenceProperty( lim, "min",  0 );
+  setPreferenceProperty( lim, "max",  100000000 );
+  setPreferenceProperty( lim, "step", 1000 );
+  setPreferenceProperty( lim, "special", tr( "PREF_UPDATE_LIMIT_NOLIMIT" ) );
 
   int qaGroup = addPreference( tr( "PREF_GROUP_QUALITY" ), genTab );
   setPreferenceProperty( qaGroup, "columns", 2 );
index 4a82e5c1a8b0b08e430cc254965affb14b5ad741..bb2b29c043327e39d8300d011fbec3bb729b414a 100644 (file)
@@ -77,7 +77,7 @@ public :
   
   bool                            isActiveStudyLocked();
 
-  static bool                     automaticUpdate();
+  static bool                     automaticUpdate(unsigned int requestedSize = 0, bool* limitExceeded = 0);
 
   static void                     Modified( bool = true );
 
index ccd700190a6f67b26a9e24799aeee12d78270eaa..b31a1b8e9685f65a227f377bb0664455697bc335 100644 (file)
@@ -98,6 +98,7 @@
 
 #define COLONIZE(str)   (QString(str).contains(":") > 0 ? QString(str) : QString(str) + " :" )
 
+/* OBSOLETE
 static void addSeparator( QWidget* parent )
 {
   QGridLayout* l = qobject_cast<QGridLayout*>( parent->layout() );
@@ -109,6 +110,7 @@ static void addSeparator( QWidget* parent )
     l->addWidget( hline, row, i );
   }
 }
+*/
 
 enum TCol {
   COL_ALGO = 0, COL_SHAPE, COL_ERROR, COL_SHAPEID, COL_PUBLISHED, COL_BAD_MESH, NB_COLUMNS
@@ -734,25 +736,38 @@ void SMESHGUI_BaseComputeOp::computeMesh()
 
       // SHOW MESH
       // NPAL16631: if ( getSMESHGUI()->automaticUpdate() )
-      if ( !memoryLack && getSMESHGUI()->automaticUpdate() )
+      SUIT_ResourceMgr* resMgr = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() );
+      long newSize = myMesh->NbElements();
+      long limitSize = resMgr->integerValue( "SMESH", "update_limit", 500000 );
+      bool limitExceeded;
+      if ( !memoryLack )
       {
-        try {
+       if ( getSMESHGUI()->automaticUpdate( newSize, &limitExceeded ) )
+       {
+         try {
 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
-          OCC_CATCH_SIGNALS;
+           OCC_CATCH_SIGNALS;
 #endif
-          SMESH::Update(myIObject, true);
-        }
-        catch (...) {
+           SMESH::Update(myIObject, true);
+         }
+         catch (...) {
 #ifdef _DEBUG_
-          MESSAGE ( "Exception thrown during mesh visualization" );
+           MESSAGE ( "Exception thrown during mesh visualization" );
 #endif
-          if ( SMDS_Mesh::CheckMemory(true) ) { // has memory to show warning?
-            SMESH::OnVisuException();
-          }
-          else {
-            memoryLack = true;
-          }
+           if ( SMDS_Mesh::CheckMemory(true) ) { // has memory to show warning?
+             SMESH::OnVisuException();
+           }
+           else {
+             memoryLack = true;
+           }
+         }
         }
+       else if ( limitExceeded )
+       {
+         SUIT_MessageBox::warning( desktop(),
+                                   tr( "SMESH_WRN_WARNING" ),
+                                   tr( "SMESH_WRN_SIZE_LIMIT_EXCEEDED" ).arg( newSize ).arg( limitSize ) );
+       }
       }
       LightApp_SelectionMgr *Sel = selectionMgr();
       if ( Sel )
@@ -804,7 +819,7 @@ void SMESHGUI_BaseComputeOp::computeMesh()
 void SMESHGUI_BaseComputeOp::showComputeResult( const bool theMemoryLack,
                                                 const bool theNoCompError,
                                                 SMESH::compute_error_array_var& theCompErrors,
-                                                const bool     theNoHypoError,
+                                                const bool theNoHypoError,
                                                 const QString& theHypErrors )
 {
   bool hasShape = myMesh->HasShapeToMesh();
@@ -1562,6 +1577,7 @@ void SMESHGUI_PrecomputeOp::onPreview()
       
     SMESH::MeshPreviewStruct_var previewData =
       gen->Precompute(myMesh, myMainShape, (SMESH::Dimension)dim, aShapesId);
+
     SMESH::MeshPreviewStruct* previewRes = previewData._retn();
     if ( previewRes && previewRes->nodesXYZ.length() > 0 )
     {
index 2ae183e7423c203a949a7226d3ad15309ecc50fa..99da50cf28f01ba72cebbf27ec5770a2b05f4854 100755 (executable)
 #include "SMESHGUI_Filter.h"
 #include "SMESHGUI_FilterUtils.h"
 #include "SMESHGUI_FilterLibraryDlg.h"
+#include "SMESHGUI_SpinBox.h"
 
 #include <SMESH_Actor.h>
 #include <SMESH_NumberFilter.hxx>
 #include <SMESH_TypeFilter.hxx>
-#include <SMESHGUI_SpinBox.h>
 
 // SALOME GEOM includes
 #include <GEOMBase.h>
@@ -219,7 +219,7 @@ bool SMESHGUI_FilterTable::AdditionalWidget::IsValid (const bool theMsg) const
     }
     if (!valid && theMsg) {
       SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INSUFFICIENT_DATA"),
-                                  tr("SMESHGUI_INVALID_PARAMETERS"));
+                                   tr("SMESHGUI_INVALID_PARAMETERS"));
       return false;
     }
   }
@@ -317,7 +317,7 @@ void SMESHGUI_FilterTable::AdditionalWidget::SetPrecision(const int theId, const
     if ( qobject_cast<SMESHGUI_SpinBox*>( myWidgets[ theId ] ) ) {
       SMESHGUI_SpinBox* sb = qobject_cast<SMESHGUI_SpinBox*>( myWidgets[ theId ] );
       double val = sb->GetValue();
-      double min = pow(10, -(sb->decimals()));
+      double min = pow(10.0, -(sb->decimals()));
       sb->RangeStepAndValidator( 0., 1.e20, 0.1, precision ? precision : "len_tol_precision" );
       sb->SetValue( qMax( val, min ) );
     }
@@ -968,13 +968,16 @@ bool SMESHGUI_FilterTable::IsValid (const bool theMess, const int theEntityType)
       QtxColorButton* clrBtn = qobject_cast<QtxColorButton*>(aTable->cellWidget(i, 2));
       if (clrBtn && !clrBtn->color().isValid())
         errMsg = tr( "GROUPCOLOR_ERROR" );
-    } else if (aCriterion == SMESH::FT_RangeOfIds ||
-         aCriterion == SMESH::FT_BelongToGeom ||
-         aCriterion == SMESH::FT_BelongToPlane ||
-         aCriterion == SMESH::FT_BelongToCylinder ||
-         aCriterion == SMESH::FT_BelongToGenSurface ||
-         aCriterion == SMESH::FT_ElemGeomType ||
-         aCriterion == SMESH::FT_LyingOnGeom) {
+    }
+    else if (aCriterion == SMESH::FT_RangeOfIds ||
+             aCriterion == SMESH::FT_BelongToGeom ||
+             aCriterion == SMESH::FT_BelongToPlane ||
+             aCriterion == SMESH::FT_BelongToCylinder ||
+             aCriterion == SMESH::FT_BelongToGenSurface ||
+             aCriterion == SMESH::FT_ElemGeomType ||
+             aCriterion == SMESH::FT_CoplanarFaces ||
+             aCriterion == SMESH::FT_LyingOnGeom)
+    {
       if (aTable->text(i, 2).isEmpty())
         errMsg = tr( "ERROR" );
     }
@@ -988,8 +991,8 @@ bool SMESHGUI_FilterTable::IsValid (const bool theMess, const int theEntityType)
       if (!aRes && aTable->isEditable(i, 2))
         errMsg = tr( "ERROR" );
       else if (aType == SMESH::EDGE &&
-                GetCriterionType(i, aType) == SMESH::FT_MultiConnection &&
-                aThreshold == 1)
+               GetCriterionType(i, aType) == SMESH::FT_MultiConnection &&
+               aThreshold == 1)
         errMsg = tr( "MULTIEDGES_ERROR" );
     }
 
@@ -1088,12 +1091,14 @@ void SMESHGUI_FilterTable::GetCriterion (const int                 theRow,
   }
   else if ( aCriterionType == SMESH::FT_ElemGeomType )
     theCriterion.Threshold = (double)((ComboItem*)aTable->item(theRow, 2))->value();
+  else if ( aCriterionType == SMESH::FT_CoplanarFaces )
+    theCriterion.ThresholdID = aTable->text(theRow, 2).toLatin1().constData();
   else if ( aCriterionType != SMESH::FT_RangeOfIds &&
             aCriterionType != SMESH::FT_BelongToGeom &&
             aCriterionType != SMESH::FT_BelongToPlane &&
             aCriterionType != SMESH::FT_BelongToCylinder &&
             aCriterionType != SMESH::FT_BelongToGenSurface &&
-            aCriterionType != SMESH::FT_LyingOnGeom)
+            aCriterionType != SMESH::FT_LyingOnGeom )
   {
     theCriterion.Compare = ((ComboItem*)aTable->item(theRow, 1))->value();
     theCriterion.Threshold = aTable->item(theRow, 2)->text().toDouble();
@@ -1159,19 +1164,26 @@ void SMESHGUI_FilterTable::SetCriterion (const int                       theRow,
     ComboItem* typeBox = (ComboItem*)aTable->item(theRow, 2);
     typeBox->setValue( (int)(theCriterion.Threshold + 0.5) );
   }
+  else if (theCriterion.Type == SMESH::FT_CoplanarFaces )
+  {
+    aTable->item( theRow, 2 )->setText( QString( theCriterion.ThresholdID ) );
+  }
   else if (theCriterion.Type != SMESH::FT_RangeOfIds &&
-      theCriterion.Type != SMESH::FT_BelongToGeom &&
-      theCriterion.Type != SMESH::FT_BelongToPlane &&
-      theCriterion.Type != SMESH::FT_BelongToCylinder &&
-      theCriterion.Type != SMESH::FT_BelongToGenSurface &&
-      theCriterion.Type != SMESH::FT_LyingOnGeom &&
-      theCriterion.Type != SMESH::FT_FreeBorders &&
-      theCriterion.Type != SMESH::FT_FreeEdges &&
-      theCriterion.Type != SMESH::FT_FreeNodes &&
-      theCriterion.Type != SMESH::FT_FreeFaces &&
-      theCriterion.Type != SMESH::FT_BadOrientedVolume &&
-      theCriterion.Type != SMESH::FT_LinearOrQuadratic)
+           theCriterion.Type != SMESH::FT_BelongToGeom &&
+           theCriterion.Type != SMESH::FT_BelongToPlane &&
+           theCriterion.Type != SMESH::FT_BelongToCylinder &&
+           theCriterion.Type != SMESH::FT_BelongToGenSurface &&
+           theCriterion.Type != SMESH::FT_LyingOnGeom &&
+           theCriterion.Type != SMESH::FT_CoplanarFaces &&
+           theCriterion.Type != SMESH::FT_FreeBorders &&
+           theCriterion.Type != SMESH::FT_FreeEdges &&
+           theCriterion.Type != SMESH::FT_FreeNodes &&
+           theCriterion.Type != SMESH::FT_FreeFaces &&
+           theCriterion.Type != SMESH::FT_BadOrientedVolume &&
+           theCriterion.Type != SMESH::FT_LinearOrQuadratic)
+  {
     aTable->item( theRow, 2 )->setText(QString("%1").arg(theCriterion.Threshold, 0, 'g', 15));
+  }
   else
   {
     aTable->item( theRow, 2 )->setText(QString(theCriterion.ThresholdStr));
@@ -1179,24 +1191,25 @@ void SMESHGUI_FilterTable::SetCriterion (const int                       theRow,
       aTable->item( theRow, 5 )->setText( QString( theCriterion.ThresholdID ) );
   }
 
-  if (theCriterion.Compare  == SMESH::FT_EqualTo ||
-       theCriterion.Type    == SMESH::FT_BelongToPlane ||
-       theCriterion.Type    == SMESH::FT_BelongToCylinder ||
-       theCriterion.Type    == SMESH::FT_BelongToGenSurface ||
-       theCriterion.Type    == SMESH::FT_BelongToGeom ||
-       theCriterion.Type    == SMESH::FT_LyingOnGeom)
+  if (theCriterion.Compare == SMESH::FT_EqualTo ||
+      theCriterion.Type    == SMESH::FT_BelongToPlane ||
+      theCriterion.Type    == SMESH::FT_BelongToCylinder ||
+      theCriterion.Type    == SMESH::FT_BelongToGenSurface ||
+      theCriterion.Type    == SMESH::FT_BelongToGeom ||
+      theCriterion.Type    == SMESH::FT_LyingOnGeom ||
+      theCriterion.Type    == SMESH::FT_CoplanarFaces)
   {
     QTableWidgetItem* anItem = aTable->item(theRow, 0);
     if (!myAddWidgets.contains(anItem))
     {
       myAddWidgets[ anItem ] = new AdditionalWidget(myWgStack);
+      myAddWidgets[ anItem ]->SetPrecision( AdditionalWidget::Tolerance, getPrecision( theCriterion.Type ) );
       myWgStack->addWidget(myAddWidgets[ anItem ]);
     }
     myAddWidgets[ anItem ]->SetDouble(AdditionalWidget::Tolerance, theCriterion.Tolerance);
   }
 
   emit CriterionChanged(theRow, aType);
-
 }
 
 //=======================================================================
@@ -1324,11 +1337,13 @@ void SMESHGUI_FilterTable::updateAdditionalWidget()
 
   ComboItem* anItem = ((ComboItem*)aTable->item(aRow, 0));
   int aCriterion = GetCriterionType(aRow);
-  bool toEnable = ((ComboItem*)aTable->item(aRow, 1))->value() == SMESH::FT_EqualTo &&
-                  aCriterion != SMESH::FT_RangeOfIds &&
-                  aCriterion != SMESH::FT_FreeEdges &&
-                  aCriterion != SMESH::FT_FreeFaces &&
-                  aCriterion != SMESH::FT_BadOrientedVolume;
+  bool toEnable = ((((ComboItem*)aTable->item(aRow, 1))->value() == SMESH::FT_EqualTo &&
+                   aCriterion != SMESH::FT_RangeOfIds &&
+                   aCriterion != SMESH::FT_FreeEdges &&
+                   aCriterion != SMESH::FT_FreeFaces &&
+                   aCriterion != SMESH::FT_BadOrientedVolume)
+                   ||
+                   aCriterion == SMESH::FT_CoplanarFaces);
 
   if (!myAddWidgets.contains(anItem))
   {
@@ -1352,6 +1367,7 @@ const char* SMESHGUI_FilterTable::getPrecision( const int aType )
   case SMESH::FT_Warping:
   case SMESH::FT_MinimumAngle:
   case SMESH::FT_Skew:
+  case SMESH::FT_CoplanarFaces:
     retval = "angle_precision"; break;
   case SMESH::FT_Area:
     retval = "area_precision"; break;
@@ -1466,7 +1482,7 @@ void SMESHGUI_FilterTable::onCriterionChanged (const int row, const int col, con
   bool isComboItem = false;
   if (aTableItem) {
     int aTableType = aTable->item(row, 2)->type();
-    isComboItem = aTableType == aComboType ? true : false;
+    isComboItem = ( aTableType == aComboType );
   }
   
   if ( (aCriterionType != SMESH::FT_GroupColor && clrBtn) ||
@@ -1500,14 +1516,16 @@ void SMESHGUI_FilterTable::onCriterionChanged (const int row, const int col, con
     aTable->blockSignals( isSignalsBlocked );
   }
 
-  if (aType == SMESH::NODE && aCriterionType == SMESH::FT_FreeNodes ||
-      aType == SMESH::EDGE && aCriterionType == SMESH::FT_FreeBorders ||
-      aType == SMESH::FACE && (aCriterionType == SMESH::FT_FreeEdges ||
-                               aCriterionType == SMESH::FT_FreeFaces) ||
-      aType == SMESH::VOLUME && aCriterionType == SMESH::FT_BadOrientedVolume ||
+  if ((aType == SMESH::NODE && aCriterionType == SMESH::FT_FreeNodes ) ||
+      (aType == SMESH::EDGE && aCriterionType == SMESH::FT_FreeBorders ) ||
+      (aType == SMESH::FACE && (aCriterionType == SMESH::FT_FreeEdges ||
+                                aCriterionType == SMESH::FT_FreeFaces)) ||
+      (aType == SMESH::VOLUME && aCriterionType == SMESH::FT_BadOrientedVolume) ||
       aCriterionType == SMESH::FT_LinearOrQuadratic ||
       aCriterionType == SMESH::FT_GroupColor ||
-      aCriterionType == SMESH::FT_ElemGeomType)
+      aCriterionType == SMESH::FT_ElemGeomType ||
+      aCriterionType == SMESH::FT_CoplanarFaces
+      )
   {
     bool isSignalsBlocked = aTable->signalsBlocked();
     aTable->blockSignals( true );
@@ -1516,7 +1534,8 @@ void SMESHGUI_FilterTable::onCriterionChanged (const int row, const int col, con
       aCompareItem->clear();
     aTable->setEditable(false, row, 1);
     aTable->setEditable(aCriterionType == SMESH::FT_GroupColor ||
-                        aCriterionType == SMESH::FT_ElemGeomType, row, 2);
+                        aCriterionType == SMESH::FT_ElemGeomType ||
+                        aCriterionType == SMESH::FT_CoplanarFaces, row, 2);
     aTable->blockSignals( isSignalsBlocked );
   }
   else if (aCriterionType == SMESH::FT_RangeOfIds ||
@@ -1789,6 +1808,7 @@ const QMap<int, QString>& SMESHGUI_FilterTable::getCriteria (const int theType)
       aCriteria[ SMESH::FT_LinearOrQuadratic  ] = tr("LINEAR");
       aCriteria[ SMESH::FT_GroupColor         ] = tr("GROUP_COLOR");
       aCriteria[ SMESH::FT_ElemGeomType       ] = tr("GEOM_TYPE");
+      aCriteria[ SMESH::FT_CoplanarFaces      ] = tr("COPLANAR_FACES");
     }
     return aCriteria;
   }
@@ -2116,8 +2136,8 @@ bool SMESHGUI_FilterTable::GetThreshold (const int      theRow,
 // Purpose : Set text and internal value in cell of ID value 
 //=======================================================================
 void SMESHGUI_FilterTable::SetID( const int      theRow,
-                                 const QString& theText,
-                                 const int      theEntityType )
+                                  const QString& theText,
+                                  const int      theEntityType )
 {
   Table* aTable = myTables[ theEntityType == -1 ? GetType() : theEntityType ];
   aTable->item( theRow, 5 )->setText( theText );
@@ -2638,7 +2658,8 @@ bool SMESHGUI_FilterDlg::isValid() const
         aType == SMESH::FT_BelongToPlane ||
         aType == SMESH::FT_BelongToCylinder ||
         aType == SMESH::FT_BelongToGenSurface ||
-        aType == SMESH::FT_LyingOnGeom) {
+        aType == SMESH::FT_LyingOnGeom)
+    {
       QString aName;
       myTable->GetThreshold(i, aName);
 
@@ -2687,6 +2708,29 @@ bool SMESHGUI_FilterDlg::isValid() const
         }
       }
     }
+    else if (aType == SMESH::FT_CoplanarFaces)
+    {
+      QString faceID;
+      myTable->GetThreshold(i, faceID);
+      if ( faceID.isEmpty() )
+      {
+        SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INSUFFICIENT_DATA"),
+                                     tr("FACE_ID_NOT_SELECTED"));
+        return false;
+      }
+      if ( myMesh->_is_nil() )
+      {
+        SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INSUFFICIENT_DATA"),
+                                     tr("MESH_IS_NOT_SELECTED"));
+        return false;
+      }
+      if ( myMesh->GetElementType( faceID.toLong(), /*iselem=*/true) != SMESH::FACE )
+      {
+        SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INSUFFICIENT_DATA"),
+                                     tr("NOT_FACE_ID").arg(faceID));
+        return false;
+      }
+    }
   }
 
   return true;
@@ -2705,7 +2749,7 @@ void SMESHGUI_FilterDlg::SetSourceWg (QWidget* theWg,
 }
 
 //=======================================================================
-// name    : SMESHGUI_FilterDlg::SetGroupIds
+// name    : SMESHGUI_FilterDlg::SetMesh
 // Purpose : Set mesh
 //=======================================================================
 void SMESHGUI_FilterDlg::SetMesh (SMESH::SMESH_Mesh_var theMesh)
@@ -3067,19 +3111,30 @@ void SMESHGUI_FilterDlg::onSelectionDone()
   QList<int> types; 
   types << SMESH::FT_BelongToGeom     << SMESH::FT_BelongToPlane 
         << SMESH::FT_BelongToCylinder << SMESH::FT_BelongToGenSurface
-        << SMESH::FT_LyingOnGeom;
+        << SMESH::FT_LyingOnGeom      << SMESH::FT_CoplanarFaces;
   if (aList.Extent() != 1 || !myTable->CurrentCell(aRow, aCol) || 
       !types.contains(myTable->GetCriterionType(aRow)))
     return;
 
-  Handle(SALOME_InteractiveObject) anIO = aList.First();
-  GEOM::GEOM_Object_var anObj = SMESH::IObjectToInterface<GEOM::GEOM_Object>(anIO);
-  if (!anObj->_is_nil())
+  if ( myTable->GetCriterionType(aRow) == SMESH::FT_CoplanarFaces )
+  {
+    QString aString;
+    int nbElems = SMESH::GetNameOfSelectedElements(mySelector,//myViewWindow->GetSelector(),
+                                                   aList.First(), aString);
+    if (nbElems == 1)
+      myTable->SetThreshold(aRow, aString);
+  }
+  else
+  {
+    Handle(SALOME_InteractiveObject) anIO = aList.First();
+    GEOM::GEOM_Object_var anObj = SMESH::IObjectToInterface<GEOM::GEOM_Object>(anIO);
+    if (!anObj->_is_nil())
     {
       myTable->SetThreshold(aRow, GEOMBase::GetName(anObj));
       //myTable->SetID( aRow, GEOMBase::GetIORFromObject(anObj));
       myTable->SetID(aRow, anIO->getEntry());
     }
+  }
 }
 
 
@@ -3110,9 +3165,9 @@ void SMESHGUI_FilterDlg::updateSelection()
   if (mySelectionMgr == 0)
     return;
 
-  TColStd_MapOfInteger allTypes;
-  for( int i=0; i<10; i++ )
-    allTypes.Add( i );
+//   TColStd_MapOfInteger allTypes;
+//   for( int i=0; i<10; i++ )
+//     allTypes.Add( i );
   SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( mySMESHGUI->application()->activeStudy() );
   if( !aStudy )
     return;
@@ -3128,8 +3183,8 @@ void SMESHGUI_FilterDlg::updateSelection()
        aCriterionType == SMESH::FT_BelongToPlane ||
        aCriterionType == SMESH::FT_BelongToCylinder ||
        aCriterionType == SMESH::FT_BelongToGenSurface ||
-       aCriterionType == SMESH::FT_LyingOnGeom)) {
-
+       aCriterionType == SMESH::FT_LyingOnGeom))
+  {
     if (aCriterionType == SMESH::FT_BelongToGeom ||
         aCriterionType == SMESH::FT_BelongToGenSurface ||
         aCriterionType == SMESH::FT_LyingOnGeom) {
@@ -3144,9 +3199,12 @@ void SMESHGUI_FilterDlg::updateSelection()
     }
     myIsSelectionChanged = true;
 
-  } else {
+  }
+  else
+  {
     if (myIsSelectionChanged) {
-      mySelectionMgr->installFilter( new GEOM_TypeFilter( aStudy, -1 ) ); // This filter deactivates selection
+      // mySelectionMgr->installFilter( new GEOM_TypeFilter( aStudy, -1 ) ); // This filter deactivates selection
+      // Impossible to select any object in the OB on the second opening of FilterDlg
     }
   }
 }
index 9fefa98daf9d9e2f107bbb92186de7d3e7f5a67d..581aa53265474bc1eb8ae2a55150c67a504da002 100644 (file)
@@ -301,7 +301,7 @@ bool SMESHGUI_GroupOnShapeOp::onApply()
   if ( !aStudy ) return false;
 
   // mesh
-  _PTR(SObject)       meshSO = aStudy->FindObjectID( myMeshID.toLatin1().data() );
+  _PTR(SObject) meshSO = aStudy->FindObjectID( myMeshID.toLatin1().data() );
   SMESH::SMESH_Mesh_var mesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>( meshSO );
   if ( mesh->_is_nil() ) return false;
 
@@ -352,7 +352,15 @@ bool SMESHGUI_GroupOnShapeOp::onApply()
 
   update( UF_ObjBrowser | UF_Model );
 
-  init();
+  // Re-init controls to create the next group
+  myElemGeoIDs.clear();
+  myNodeGeoIDs.clear();
+  removeCustomFilters();
+  myDlg->myNodeGeomList->clear();
+  myDlg->myElemGeomList->clear();
+  myDlg->myElemGeomBtn->setChecked(false); 
+  myDlg->myNodeGeomBtn->setChecked(false);
+  myDlg->updateButtons();
 
   return !group->_is_nil();
 }
index ffbc3b80dd2f42c21a91f28872ef823aa829e395..4ffc3f09e4d30b02b8d701cd048eca79b95b0e7a 100644 (file)
 //
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
+// File   : SMESHGUI_Make2DFrom3D.cxx
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
 
-// File   : SMESHGUI_Make2DFrom3DOp.cxx
-// Author : Open CASCADE S.A.S.
-// SMESH includes
-//
 #include "SMESHGUI_Make2DFrom3DOp.h"
 
 #include "SMESHGUI.h"
 #include "SMESHGUI_Utils.h"
-#include "SMESHGUI_VTKUtils.h"
 #include "SMESHGUI_MeshUtils.h"
-#include "SMESHGUI_MeshInfosBox.h"
+#include "SMESH_TypeFilter.hxx"
+#include "SMESH_LogicalFilter.hxx"
 
 // SALOME GUI includes
-#include <LightApp_SelectionMgr.h>
-
+#include <LightApp_UpdateFlags.h>
+#include <SalomeApp_Tools.h>
+#include <SalomeApp_Study.h>
 #include <SUIT_Desktop.h>
 #include <SUIT_MessageBox.h>
-#include <SUIT_ResourceMgr.h>
 #include <SUIT_OverrideCursor.h>
 
-#include <SALOME_ListIO.hxx>
-
-// SALOME KERNEL includes
-#include <SALOMEDS_SObject.hxx>
-#include <SALOMEDSClient_SObject.hxx>
-
-// Qt includes
 // IDL includes
 #include <SALOMEconfig.h>
-#include CORBA_SERVER_HEADER(SMESH_Gen)
-#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
+#include CORBA_SERVER_HEADER(SMESH_Group)
 
-#include <QFrame>
-#include <QLabel>
-#include <QPixmap>
+// Qt includes
 #include <QGroupBox>
-#include <QPushButton>
-#include <QVBoxLayout>
-
-// MESH includes
-#include "SMDSAbs_ElementType.hxx"
-#include "SMDSAbs_ElementType.hxx"
-
+#include <QRadioButton>
+#include <QLineEdit>
+#include <QCheckBox>
+#include <QHBoxLayout>
+#include <QGridLayout>
 
 #define SPACING 6
 #define MARGIN  11
 
-// =========================================================================================
 /*!
- * \brief Dialog to show creted mesh statistic
- */
-//=======================================================================
+  \class SMESHGUI_Make2DFrom3DDlg
+  \brief Copy Mesh dialog box
+*/
 
 SMESHGUI_Make2DFrom3DDlg::SMESHGUI_Make2DFrom3DDlg( QWidget* parent )
- : SMESHGUI_Dialog( parent, false, true, Close/* | Help*/ )
+ : SMESHGUI_Dialog( parent, false, true, OK | Apply | Close | Help )
 {
+  // title
   setWindowTitle( tr("CAPTION") );
-  QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame());
+
+  // mesh
+  setObjectPixmap( "SMESH", tr( "ICON_SELECT" ) );
+  createObject( tr( "MESH" ), mainFrame(), Mesh );
+
+  // mode
+  QGroupBox* aModeGrp = new QGroupBox( tr( "MODE" ), mainFrame() );
+  QHBoxLayout* aModeGrpLayout = new QHBoxLayout( aModeGrp );
+  aModeGrpLayout->setMargin( MARGIN );
+  aModeGrpLayout->setSpacing( SPACING );
+  my2dFrom3dRB = new QRadioButton( tr( "2D_FROM_3D" ), aModeGrp );
+  my1dFrom2dRB = new QRadioButton( tr( "1D_FROM_2D" ), aModeGrp );
+  my1dFrom3dRB = new QRadioButton( tr( "1D_FROM_3D" ), aModeGrp );
+  aModeGrpLayout->addWidget( my2dFrom3dRB );
+  aModeGrpLayout->addWidget( my1dFrom2dRB );
+  aModeGrpLayout->addWidget( my1dFrom3dRB );
+
+  // target
+  QGroupBox* aTargetGrp = new QGroupBox( tr( "TARGET" ), mainFrame() );
+  QGridLayout* aTargetGrpLayout = new QGridLayout( aTargetGrp );
+  aTargetGrpLayout->setMargin( MARGIN );
+  aTargetGrpLayout->setSpacing( SPACING );
+  myThisMeshRB   = new QRadioButton( tr( "THIS_MESH" ), aTargetGrp );
+  myNewMeshRB    = new QRadioButton( tr( "NEW_MESH" ),  aTargetGrp );
+  myMeshName     = new QLineEdit( aTargetGrp );
+  myCopyCheck    = new QCheckBox( tr( "COPY_SRC" ),     aTargetGrp );
+  myMissingCheck = new QCheckBox( tr( "MISSING_ONLY" ), aTargetGrp );
+  aTargetGrpLayout->addWidget( myThisMeshRB,    0, 0 );
+  aTargetGrpLayout->addWidget( myNewMeshRB,     1, 0 );
+  aTargetGrpLayout->addWidget( myMeshName,     1, 1 );
+  aTargetGrpLayout->addWidget( myCopyCheck,    2, 0 );
+  aTargetGrpLayout->addWidget( myMissingCheck, 2, 1 );
+  myGroupCheck = new QCheckBox( tr( "CREATE_GROUP" ), mainFrame() );
+  myGroupName  = new QLineEdit( mainFrame() );
+
+  // layout
+  QGridLayout* aDlgLay = new QGridLayout( mainFrame() );
   aDlgLay->setMargin( 0 );
   aDlgLay->setSpacing( SPACING );
-  QFrame* aMainFrame = createMainFrame(mainFrame());
-  aDlgLay->addWidget(aMainFrame);
-  aDlgLay->setStretchFactor(aMainFrame, 1);
+  aDlgLay->addWidget( objectWg( Mesh,  Label ),   0, 0 );
+  aDlgLay->addWidget( objectWg( Mesh,  Btn ),     0, 1 );
+  aDlgLay->addWidget( objectWg( Mesh,  Control ), 0, 2 );
+  aDlgLay->addWidget( aModeGrp,     1, 0, 1, 3 );
+  aDlgLay->addWidget( aTargetGrp,   2, 0, 1, 3 );
+  aDlgLay->addWidget( myGroupCheck, 3, 0 );
+  aDlgLay->addWidget( myGroupName,  3, 1, 1, 2 );
+
+  // connect signals  
+  connect( myThisMeshRB, SIGNAL( clicked() ), this, SLOT( onTargetChanged() ) );
+  connect( myNewMeshRB,  SIGNAL( clicked() ), this, SLOT( onTargetChanged() ) );
+  connect( myGroupCheck, SIGNAL( clicked() ), this, SLOT( onGroupChecked() ) );
+
+  // init dlg
+  my2dFrom3dRB->setChecked( true );
+  myThisMeshRB->setChecked( true );
+  myMissingCheck->setChecked( true );
+  onTargetChanged();
+  onGroupChecked();
 }
 
-// =========================================================================================
-/*!
- * \brief Dialog destructor
- */
-//=======================================================================
-
 SMESHGUI_Make2DFrom3DDlg::~SMESHGUI_Make2DFrom3DDlg()
 {
 }
 
-//=======================================================================
-// function : createMainFrame()
-// purpose  : Create frame containing dialog's fields
-//=======================================================================
-
-QFrame* SMESHGUI_Make2DFrom3DDlg::createMainFrame (QWidget* theParent)
+SMESH::Bnd_Dimension SMESHGUI_Make2DFrom3DDlg::mode() const
 {
-  QFrame* aFrame = new QFrame(theParent);
+  if ( my2dFrom3dRB->isChecked() )
+    return SMESH::BND_2DFROM3D;
+  else if ( my1dFrom2dRB->isChecked() )
+    return SMESH::BND_1DFROM2D;
+  else
+    return SMESH::BND_1DFROM3D;
+}
 
-  SUIT_ResourceMgr* rm = resourceMgr();
-  QPixmap iconCompute (rm->loadPixmap("SMESH", tr("ICON_2D_FROM_3D")));
+bool SMESHGUI_Make2DFrom3DDlg::needNewMesh() const
+{
+  return myNewMeshRB->isChecked();
+}
 
-  // Mesh name
-  QGroupBox* nameBox = new QGroupBox(tr("SMESH_MESHINFO_NAME"), aFrame );
-  QHBoxLayout* nameBoxLayout = new QHBoxLayout(nameBox);
-  nameBoxLayout->setMargin(MARGIN); nameBoxLayout->setSpacing(SPACING);
-  myMeshName = new QLabel(nameBox);
-  nameBoxLayout->addWidget(myMeshName);
+QString SMESHGUI_Make2DFrom3DDlg::getNewMeshName() const
+{
+  return myMeshName->text().trimmed();
+}
 
-  // Mesh Info
+void SMESHGUI_Make2DFrom3DDlg::setNewMeshName( const QString& name )
+{
+  myMeshName->setText( name );
+}
 
-  myFullInfo = new SMESHGUI_MeshInfosBox(true,  aFrame);
+bool SMESHGUI_Make2DFrom3DDlg::needGroup() const
+{
+  return myGroupCheck->isChecked();
+}
 
-  // add all widgets to aFrame
-  QVBoxLayout* aLay = new QVBoxLayout(aFrame);
-  aLay->setMargin( 0 );
-  aLay->setSpacing( 0 );
-  aLay->addWidget( nameBox );
-  aLay->addWidget( myFullInfo );
+QString SMESHGUI_Make2DFrom3DDlg::getGroupName() const
+{
+  return myGroupName->text().trimmed();
+}
 
-  ((QPushButton*) button( OK ))->setDefault( true );
-  return aFrame;
+void SMESHGUI_Make2DFrom3DDlg::setGroupName( const QString& name )
+{
+  myGroupName->setText( name );
 }
 
-//================================================================================
-/*!
- * \brief set name of the mesh
-*/
-//================================================================================
+bool SMESHGUI_Make2DFrom3DDlg::copySource() const
+{
+  return myCopyCheck->isChecked();
+}
 
-void SMESHGUI_Make2DFrom3DDlg::SetMeshName(const QString& theName)
+bool SMESHGUI_Make2DFrom3DDlg::copyMissingOnly() const
 {
-  myMeshName->setText( theName );
+  return myMissingCheck->isChecked();
 }
 
-//================================================================================
-/*!
- * \brief set mesh info
-*/
-//================================================================================
+void SMESHGUI_Make2DFrom3DDlg::onTargetChanged()
+{
+  myMeshName->setEnabled( myNewMeshRB->isChecked() );
+  myCopyCheck->setEnabled( myNewMeshRB->isChecked() );
+  myMissingCheck->setEnabled( myNewMeshRB->isChecked() );
+}
 
-void SMESHGUI_Make2DFrom3DDlg::SetMeshInfo(const SMESH::long_array& theInfo)
+void SMESHGUI_Make2DFrom3DDlg::onGroupChecked()
 {
-  myFullInfo->SetMeshInfo( theInfo );
+  myGroupName->setEnabled( myGroupCheck->isChecked() );
 }
 
-//================================================================================
 /*!
- * \brief Constructor
+  \class SMESHGUI_Make2DFrom3DOp
+  \brief Copy Mesh operation class
 */
-//================================================================================
 
 SMESHGUI_Make2DFrom3DOp::SMESHGUI_Make2DFrom3DOp()
- : SMESHGUI_Operation()
+ : SMESHGUI_SelectionOp()
 {
-  myDlg = new SMESHGUI_Make2DFrom3DDlg(desktop());
 }
 
-//================================================================================
-/*!
- * \brief Desctructor
-*/
-//================================================================================
-
 SMESHGUI_Make2DFrom3DOp::~SMESHGUI_Make2DFrom3DOp()
 {
+  if ( myDlg )
+    delete myDlg;
 }
 
-//================================================================================
-/*!
- * \brief perform it's intention action: compute 2D mesh on 3D
- */
-//================================================================================
+LightApp_Dialog* SMESHGUI_Make2DFrom3DOp::dlg() const
+{
+  return myDlg;
+}
 
 void SMESHGUI_Make2DFrom3DOp::startOperation()
 {
-  myMesh = SMESH::SMESH_Mesh::_nil();
+  if( !myDlg )
+    myDlg = new SMESHGUI_Make2DFrom3DDlg( desktop() );
+
+  mySrc = SMESH::SMESH_IDSource::_nil();
   
-  // check selection
-  LightApp_SelectionMgr *Sel = selectionMgr();
-  SALOME_ListIO selected; Sel->selectedObjects( selected );
+  myHelpFileName = "make_2dmesh_from_3d_page.html";
 
-  int nbSel = selected.Extent();
-  if (nbSel != 1) {
-    SUIT_MessageBox::warning(desktop(),
-                             tr("SMESH_WRN_WARNING"),
-                             tr("SMESH_WRN_NO_AVAILABLE_DATA"));
-    onCancel();
-    return;
-  }
+  SMESHGUI_SelectionOp::startOperation();
+
+  myDlg->activateObject( SMESHGUI_Make2DFrom3DDlg::Mesh );
+  myDlg->setNewMeshName( SMESH::UniqueName( "Mesh_1" ) );
+  myDlg->setGroupName( SMESH::UniqueName( "Group" ) );
+  myDlg->show();
+
+  selectionDone();
+}
 
-  Handle(SALOME_InteractiveObject) anIO = selected.First();
-  myMesh = SMESH::GetMeshByIO(anIO);
-  if (myMesh->_is_nil()) {
-    SUIT_MessageBox::warning(desktop(),
-                             tr("SMESH_WRN_WARNING"),
-                             tr("SMESH_WRN_NO_AVAILABLE_DATA"));
-    onCancel();
-    return;
+void SMESHGUI_Make2DFrom3DOp::selectionDone()
+{
+  if ( !dlg() ) return;
+
+  if ( dlg()->isVisible() ) {
+    try {
+      QStringList names, ids;
+      LightApp_Dialog::TypesList types;
+      selected( names, types, ids );
+      if ( names.count() == 1 )
+        myDlg->selectObject( names, types, ids );
+      else
+        myDlg->clearSelection();
+    }
+    catch ( const SALOME::SALOME_Exception& S_ex ) {
+      SalomeApp_Tools::QtCatchCorbaException( S_ex );
+    }
+    catch ( ... ) {
+    }
   }
+}
 
-  SMESHGUI_Operation::startOperation();
+SUIT_SelectionFilter* SMESHGUI_Make2DFrom3DOp::createFilter( const int theId ) const
+{
+  SUIT_SelectionFilter* f = 0;
+  if ( theId == SMESHGUI_Make2DFrom3DDlg::Mesh ) {
+    QList<SUIT_SelectionFilter*> filters;
+    filters.append( new SMESH_TypeFilter( MESHorSUBMESH ) );
+    filters.append( new SMESH_TypeFilter( GROUP ) );
+    f = new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR );
+  }
+  return f;
+}
 
+bool SMESHGUI_Make2DFrom3DOp::isValid( QString& msg ) const
+{
+  if ( !dlg() ) return false;
+
+  // check if any source data is selected
+  QString entry = myDlg->selectedObject( SMESHGUI_Make2DFrom3DDlg::Mesh );
+  SMESH::SMESH_IDSource_var obj;
+  _PTR(SObject) sobj = SMESHGUI::activeStudy()->studyDS()->FindObjectID( entry.toLatin1().constData() );
+  if ( sobj )
+    obj = SMESH::SObjectToInterface<SMESH::SMESH_IDSource>( sobj );  
+
+  if ( obj->_is_nil() ) {
+    msg = tr( "SMESH_ERR_NO_INPUT_MESH" );
+    return false;
+  }
 
-  // backup mesh info before 2D mesh computation
-  SMESH::long_array_var anOldInfo = myMesh->GetMeshInfo();
+  // check if source contains elements of required type
+  SMESH::Bnd_Dimension mode = myDlg->mode();
+  SMESH::array_of_ElementType_var types = obj->GetTypes();
   
+  bool has3d = false;
+  bool has2d = false;
+  for ( int i = 0; i < types->length(); i++ ) {
+    if      ( types[i] == SMESH::VOLUME ) has3d = true;
+    else if ( types[i] == SMESH::FACE )   has2d = true;
+  }
 
-  if (!compute2DMesh()) {
-    SUIT_MessageBox::warning(desktop(),
-                             tr("SMESH_WRN_WARNING"),
-                             tr("SMESH_WRN_COMPUTE_FAILED"));
-    onCancel();
-    return;
-  }
-  // get new mesh statistic
-  SMESH::long_array_var aNewInfo = myMesh->GetMeshInfo();
-  // get difference in mesh statistic from old to new
-  for ( int i = SMDSEntity_Node; i < SMDSEntity_Last; i++ )
-    aNewInfo[i] -= anOldInfo[i];
-
-  // update presentation
-  SMESH::Update(anIO, SMESH::eDisplay);
-
-  // show computated result
-  _PTR(SObject) aMeshSObj = SMESH::FindSObject(myMesh);
-  if ( aMeshSObj )
-    myDlg->SetMeshName( aMeshSObj->GetName().c_str() );
-  myDlg->SetMeshInfo( aNewInfo );
-  myDlg->show(); /*exec();*/
-  commit();
-  SMESHGUI::Modified();
-}
-
-//================================================================================
-/*!
- * \brief compute 2D mesh on initial 3D
- */
-//================================================================================
+  if ( ( mode == SMESH::BND_2DFROM3D || mode == SMESH::BND_1DFROM3D ) && !has3d ) {
+    msg = tr( "SMESH_ERR_NO_3D_ELEMENTS" );
+    return false;
+  }
+  else if ( mode == SMESH::BND_1DFROM2D && !has2d ) {
+    msg = tr( "SMESH_ERR_NO_2D_ELEMENTS" );
+    return false;
+  }
+
+  // check if new mesh name is specified
+  if ( myDlg->needNewMesh() && myDlg->getNewMeshName().isEmpty() ) {
+    msg = tr( "SMESH_ERR_MESH_NAME_NOT_SPECIFIED" );
+    return false;
+  }
+
+  // check if group name is specified
+  if ( myDlg->needGroup() && myDlg->getGroupName().isEmpty() ) {
+    msg = tr( "SMESH_ERR_GRP_NAME_NOT_SPECIFIED" );
+    return false;
+  }
+    
+  return true;
+}
 
 bool SMESHGUI_Make2DFrom3DOp::compute2DMesh()
 {
   SUIT_OverrideCursor wc;
-  SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
-  return aMeshEditor->Make2DMeshFrom3D();
+
+  bool ok = false;
+  try {
+    QString entry = myDlg->selectedObject( SMESHGUI_Make2DFrom3DDlg::Mesh );
+    _PTR(SObject) sobj = SMESHGUI::activeStudy()->studyDS()->FindObjectID( entry.toLatin1().constData() );
+    SMESH::SMESH_IDSource_var obj = SMESH::SObjectToInterface<SMESH::SMESH_IDSource>( sobj );  
+    
+    SMESH::Bnd_Dimension mode = myDlg->mode();
+    QString meshName  = myDlg->needNewMesh() ? myDlg->getNewMeshName() : QString();
+    QString groupName = myDlg->needGroup()   ? myDlg->getGroupName()   : QString();
+    bool copySrc = myDlg->copySource();
+    bool copyAll = !myDlg->copyMissingOnly();
+
+    SMESH::SMESH_Mesh_var srcMesh = SMESH::SMESH_Mesh::_narrow( obj );
+    if ( CORBA::is_nil( srcMesh ) ) {
+      SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_narrow( obj );
+      if ( !CORBA::is_nil( subMesh ) )
+        srcMesh = subMesh->GetFather();
+    }
+    if ( CORBA::is_nil( srcMesh ) ) {
+      SMESH::SMESH_GroupBase_var grp = SMESH::SMESH_GroupBase::_narrow( obj );
+      if ( !CORBA::is_nil( grp ) )
+        srcMesh = grp->GetMesh();
+    }
+
+    if ( !CORBA::is_nil( srcMesh ) ) {
+      SMESH::SMESH_MeshEditor_var aMeshEditor = srcMesh->GetMeshEditor();
+      SMESH::SMESH_Group_var newGrp;
+      SMESH::SMESH_Mesh_var mesh = aMeshEditor->MakeBoundaryMesh( obj.in(), 
+                                                                  mode,
+                                                                  groupName.toLatin1().constData(),
+                                                                  meshName.toLatin1().constData(),
+                                                                  copySrc,
+                                                                  copyAll,
+                                                                  newGrp.out() );
+      if ( !mesh->_is_nil() ) {
+#ifdef WITHGENERICOBJ
+        mesh->Destroy();
+#endif
+      }
+      if ( !newGrp->_is_nil() ) {
+#ifdef WITHGENERICOBJ
+        newGrp->Destroy();
+#endif
+      }
+      ok = true;
+    }
+  }
+  catch ( ... ) {
+  }
+  return ok;
+}
+
+bool SMESHGUI_Make2DFrom3DOp::onApply()
+{
+  if ( isStudyLocked() )
+    return false;
+
+  QString msg;
+  if ( !isValid( msg ) ) {
+    dlg()->show();
+    if ( msg != "" )
+      SUIT_MessageBox::warning( myDlg, tr( "SMESH_ERROR" ), msg );
+    return false;
+  }
+
+  bool res = false;
+  try {
+    res = compute2DMesh();
+  }
+  catch ( const SALOME::SALOME_Exception& S_ex ) {
+    SalomeApp_Tools::QtCatchCorbaException( S_ex );
+  }
+  catch ( ... ) {
+  }
+
+  if ( res ) {
+    SMESHGUI::Modified();
+    update( UF_ObjBrowser | UF_Model );
+    myDlg->setNewMeshName( SMESH::UniqueName( "Mesh_1" ) );
+    myDlg->setGroupName( SMESH::UniqueName( "Group" ) );
+  }
+  else {
+    SUIT_MessageBox::warning( myDlg, tr( "SMESH_ERROR" ), tr( "SMESH_OPERATION_FAILED" ) );
+  }
+
+  return res;
 }
index f2ef2d9fd68b30160821b801c7bff7ab8ee0321f..23bab5e615cc0e362b42d684c5128558cc7613a4 100644 (file)
 //
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-
-// SMESH SMESHGUI : GUI for SMESH component
 // File   : SMESHGUI_Make2DFrom3D.h
-// Author : Open CASCADE S.A.S.
-//
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+
 #ifndef SMESHGUI_Make2DFrom3DOp_H
 #define SMESHGUI_Make2DFrom3DOp_H
 
 // SMESH includes
 #include "SMESH_SMESHGUI.hxx"
-
 #include "SMESHGUI_Dialog.h"
-#include "SMESHGUI_Operation.h"
+#include "SMESHGUI_SelectionOp.h"
 
-// IDL includes
 #include <SALOMEconfig.h>
-#include CORBA_SERVER_HEADER(SMESH_Mesh)
+#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
 
-class QFrame;
-class SMESHGUI_MeshInfosBox;
+class QCheckBox;
+class QLineEdit;
+class QRadioButton;
 
 /*!
  * \brief Dialog to show result mesh statistic
  */
 
-class SMESHGUI_Make2DFrom3DDlg :  public SMESHGUI_Dialog
+class SMESHGUI_EXPORT SMESHGUI_Make2DFrom3DDlg :  public SMESHGUI_Dialog
 {
   Q_OBJECT
 
- public:
+public:
+  enum { Mesh };
+
   SMESHGUI_Make2DFrom3DDlg( QWidget* );
   virtual ~SMESHGUI_Make2DFrom3DDlg();
 
-  void                   SetMeshName(const QString& theName);
-  void                   SetMeshInfo(const SMESH::long_array& theInfo);
-
- private:
-  QFrame*                createMainFrame( QWidget* );
-
- private:
-  QLabel*                myMeshName;
-  SMESHGUI_MeshInfosBox* myFullInfo;
+  SMESH::Bnd_Dimension mode() const;
+
+  bool                 needNewMesh() const;
+  QString              getNewMeshName() const;
+  void                 setNewMeshName( const QString& );
+
+  bool                 needGroup() const;
+  QString              getGroupName() const;
+  void                 setGroupName( const QString& );
+
+  bool                 copySource() const;
+  bool                 copyMissingOnly() const;
+
+private slots:
+  void                 onTargetChanged();
+  void                 onGroupChecked();
+
+private:
+  QRadioButton* my2dFrom3dRB;
+  QRadioButton* my1dFrom2dRB;
+  QRadioButton* my1dFrom3dRB;
+  QRadioButton* myThisMeshRB;
+  QRadioButton* myNewMeshRB;
+  QLineEdit*    myMeshName;
+  QCheckBox*    myCopyCheck;
+  QCheckBox*    myMissingCheck;
+  QCheckBox*    myGroupCheck;
+  QLineEdit*    myGroupName;
 };
 
-
 /*!
  * \brief Operation to compute 2D mesh on 3D
  */
 
-class SMESHGUI_Make2DFrom3DOp : public SMESHGUI_Operation
+class SMESHGUI_EXPORT SMESHGUI_Make2DFrom3DOp : public SMESHGUI_SelectionOp
 {
- public:
+  Q_OBJECT
+
+public:
   SMESHGUI_Make2DFrom3DOp();
   virtual ~SMESHGUI_Make2DFrom3DOp();
 
- protected:
+  virtual LightApp_Dialog*           dlg() const;
+
+protected:
   virtual void                       startOperation();
+  virtual void                       selectionDone();
+  virtual SUIT_SelectionFilter*      createFilter( const int ) const;
+  bool                               isValid( QString& ) const;
+
+protected slots:
+  virtual bool                       onApply();
 
- private:
+private:
   bool                               compute2DMesh();
 
- private:
-  SMESH::SMESH_Mesh_var              myMesh;
+private:
+  SMESH::SMESH_IDSource_var          mySrc;
   QPointer<SMESHGUI_Make2DFrom3DDlg> myDlg;
 };
 
index 0763be3ed52c27879096d76939e1e2eddde899af..bf53ecd7f45494486cf94181afc7e8a622650530 100644 (file)
@@ -82,4 +82,44 @@ namespace SMESH
     }
     return baseName;
   }
+
+  QString UniqueName(const QString& theBaseName, _PTR(SObject) theParent, const QString& thePostfix)
+  {
+    QString baseName = thePostfix.isEmpty() ? 
+      theBaseName : theBaseName + "_" + thePostfix;
+    QString name = baseName;
+    if ( _PTR(Study) aStudy = GetActiveStudyDocument() ) {
+      _PTR(SObject) p = theParent;
+      if ( !p ) p = aStudy->FindComponent( "SMESH" );
+      if ( p ) {
+       _PTR(ChildIterator) iter = aStudy->NewChildIterator( p );
+       int idx = 0;
+       while( true ) {
+         bool found = false;
+         for ( ; iter->More(); iter->Next() ) {
+           _PTR(SObject) so = iter->Value();
+           if ( !so ) continue; // skip bad objects
+           _PTR(SObject) ref;
+           if ( so->ReferencedObject( ref ) ) continue; // skip references
+           QString n = so->GetName().c_str();
+           if ( !n.isEmpty() && n == name ) {
+             QStringList names = name.split("_", QString::KeepEmptyParts);
+             if ( names.count() > 0 ) {
+               bool ok;
+               names.last().toInt( &ok );
+               if ( ok )
+                 names.removeLast();
+             }
+             names.append( QString::number( ++idx ) );
+             name = names.join( "_" );
+             found = true;
+             break;
+           }
+         }
+         if ( !found ) break;
+       }
+      }
+    }
+    return name;
+  }
 } // end of namespace SMESH
index 5edffe9f31512874dc84aeadffd24db5909f5656..5a959cb397d5e3f0981ad623cb30038560bb4972 100644 (file)
 // SALOME GUI includes
 #include <SALOME_InteractiveObject.hxx>
 
+// SALOME KERNEL includes
+#include <SALOMEDSClient_definitions.hxx>
+
 // IDL includes
 #include <SALOMEconfig.h>
 #include CORBA_SERVER_HEADER(SMESH_Mesh)
 
+class SALOMEDSClient_SObject;
+
 namespace SMESH
 {
   SMESHGUI_EXPORT
@@ -47,6 +52,8 @@ namespace SMESH
  
   SMESHGUI_EXPORT
     QString        UniqueMeshName( const QString&, const QString& = QString() );
+  SMESHGUI_EXPORT
+    QString        UniqueName( const QString&, _PTR(SObject) = _PTR(SObject)(), const QString& = QString() );
 }
 
 #endif // SMESHGUI_MESHUTILS_H
index 4a3a32e3ff95254ed5db14ed69d3f0779d54560c..a42af721797f2efc9b640ac9a15420001a3addb2 100644 (file)
     </message>
     <message>
         <source>MEN_2D_FROM_3D</source>
-        <translation>Create 2D mesh from 3D</translation>
+        <translation>Create boundary elements</translation>
     </message>
     <message>
         <source>MEN_MESH_ORDER</source>
@@ -2060,6 +2060,12 @@ Consider saving your work before application crash</translation>
         <source>SMESH_WRN_VIEWER_VTK</source>
         <translation>Study frame with VTK Viewer must be activated</translation>
     </message>
+    <message>
+        <source>SMESH_WRN_SIZE_LIMIT_EXCEEDED</source>
+        <translation>No automatic update of the presentation has been done: new mesh size (%1 elements) exceeds current size limit (%2 elements).
+Please check preferences of Mesh module.
+</translation>
+    </message>
     <message>
         <source>SMESH_WRN_WARNING</source>
         <translation>Warning</translation>
@@ -2174,7 +2180,7 @@ Consider saving your work before application crash</translation>
     </message>
     <message>
         <source>STB_2D_FROM_3D</source>
-        <translation>Create 2D mesh from 3D</translation>
+        <translation>Create boundary elements</translation>
     </message>
     <message>
         <source>STB_MESH_ORDER</source>
@@ -2694,7 +2700,7 @@ Consider saving your work before application crash</translation>
     </message>
     <message>
         <source>TOP_2D_FROM_3D</source>
-        <translation>Create 2D mesh from 3D</translation>
+        <translation>Create boundary elements</translation>
     </message>
     <message>
         <source>TOP_MESH_ORDER</source>
@@ -3246,6 +3252,14 @@ Please, create VTK viewer and try again</translation>
         <source>PREF_AUTO_UPDATE</source>
         <translation>Automatic update</translation>
     </message>
+    <message>
+        <source>PREF_UPDATE_LIMIT</source>
+        <translation>Size limit (elements)</translation>
+    </message>
+    <message>
+        <source>PREF_UPDATE_LIMIT_NOLIMIT</source>
+        <translation>No limit</translation>
+    </message>
     <message>
         <source>PREF_BACKFACE</source>
         <translation>Back face</translation>
@@ -3346,10 +3360,6 @@ Please, create VTK viewer and try again</translation>
         <source>PREF_GROUP_SELECTION</source>
         <translation>Selection</translation>
     </message>
-    <message>
-        <source>PREF_GROUP_UPDATE</source>
-        <translation>Update</translation>
-    </message>
     <message>
         <source>PREF_HIGHLIGHT_COLOR</source>
         <translation>Highlight color</translation>
@@ -3631,13 +3641,6 @@ Please specify it and try again</translation>
         <translation>No valid mesh object selected</translation>
     </message>
 </context>
-<context>
-    <name>SMESHGUI_Make2DFrom3DDlg</name>
-    <message>
-        <source>CAPTION</source>
-        <translation>Create 2D mesh from 3D</translation>
-    </message>
-</context>
 <context>
     <name>SMESHGUI_CreatePatternDlg</name>
     <message>
@@ -3923,6 +3926,16 @@ Please select a face and try again</translation>
         <source>SHAPE_IS_NOT_A_PLANE</source>
         <translation>&quot;%1&quot; is not a plane
 Please select a plane and try again</translation>
+    </message>
+    <message>
+        <source>FACE_ID_NOT_SELECTED</source>
+        <translation>Mesh face is not selected
+Please specify it and try again</translation>
+    </message>
+    <message>
+        <source>NOT_FACE_ID</source>
+        <translation>&quot;%1&quot; is not an ID of a mesh face.
+Please select a face and try again</translation>
     </message>
     <message>
         <source>SOURCE</source>
@@ -4131,6 +4144,10 @@ Please check input data and try again</translation>
         <source>COMPARE</source>
         <translation>Compare</translation>
     </message>
+    <message>
+        <source>COPLANAR_FACES</source>
+        <translation>Coplanar faces</translation>
+    </message>
     <message>
         <source>COPY_FROM</source>
         <translation>Copy from...</translation>
@@ -5248,4 +5265,78 @@ It is impossible to read point coordinates from file</translation>
         <translation>Construct group with newly created elements</translation>
     </message>
 </context>
+<context>
+    <name>SMESHGUI_Make2DFrom3DDlg</name>
+    <message>
+        <source>CAPTION</source>
+        <translation>Create boundary elements</translation>
+    </message>
+    <message>
+        <source>MESH</source>
+        <translation>Mesh, submesh or group</translation>
+    </message>
+    <message>
+        <source>MODE</source>
+        <translation>Mode</translation>
+    </message>
+    <message>
+        <source>2D_FROM_3D</source>
+        <translation>2D from 3D</translation>
+    </message>
+    <message>
+        <source>1D_FROM_3D</source>
+        <translation>1D from 3D</translation>
+    </message>
+    <message>
+        <source>1D_FROM_2D</source>
+        <translation>1D from 2D</translation>
+    </message>
+    <message>
+        <source>TARGET</source>
+        <translation>Target</translation>
+    </message>
+    <message>
+        <source>THIS_MESH</source>
+        <translation>This mesh</translation>
+    </message>
+    <message>
+        <source>NEW_MESH</source>
+        <translation>New mesh</translation>
+    </message>
+    <message>
+        <source>COPY_SRC</source>
+        <translation>Copy source mesh</translation>
+    </message>
+    <message>
+        <source>MISSING_ONLY</source>
+        <translation>Copy missing elements only</translation>
+    </message>
+    <message>
+        <source>CREATE_GROUP</source>
+        <translation>Create group</translation>
+    </message>
+</context>
+<context>
+    <name>SMESHGUI_Make2DFrom3DOp</name>
+    <message>
+        <source>SMESH_ERR_NO_INPUT_MESH</source>
+        <translation>Source mesh, sub-mesh or group is not specified</translation>
+    </message>
+    <message>
+        <source>SMESH_ERR_NO_3D_ELEMENTS</source>
+        <translation>The source object does not contain 3D elements</translation>
+    </message>
+    <message>
+        <source>SMESH_ERR_NO_2D_ELEMENTS</source>
+        <translation>The source object does not contain 2D elements</translation>
+    </message>
+    <message>
+        <source>SMESH_ERR_MESH_NAME_NOT_SPECIFIED</source>
+        <translation>New mesh name is not specified</translation>
+    </message>
+    <message>
+        <source>SMESH_ERR_GRP_NAME_NOT_SPECIFIED</source>
+        <translation>Group name is not specified</translation>
+    </message>
+</context>
 </TS>
index 4c267d36efce9a1e07c47e755fc88608e127046a..9c648f40ad1016cda65a1347aa16a379fea99b38 100755 (executable)
     </message>
     <message>
         <source>MEN_2D_FROM_3D</source>
-        <translation>Créer un maillage 2D Ã  partir de 3D</translation>
+        <translation>Créer les Ã©léments de frontière</translation>
     </message>
     <message>
         <source>MEN_MESH_ORDER</source>
@@ -2056,6 +2056,12 @@ Enregistrez votre progrès avant que l&apos;application se plante</translation>
         <source>SMESH_WRN_VIEWER_VTK</source>
         <translation>Il faut ouvrir la scène dans le visualisateur VTK</translation>
     </message>
+    <message>
+        <source>SMESH_WRN_SIZE_LIMIT_EXCEEDED</source>
+        <translation>La présentation n&apos;a pas Ã©té mise Ã  jour automatiquement: la taille nouvelle du maillage (%1 Ã©léments) dépasse la limite de taille actuelle (%2 Ã©léments).
+Il serait utile de changer la limite dans les préférences du module Mesh.
+</translation>
+    </message>
     <message>
         <source>SMESH_WRN_WARNING</source>
         <translation>Avertissement</translation>
@@ -2170,7 +2176,7 @@ Enregistrez votre progrès avant que l&apos;application se plante</translation>
     </message>
     <message>
         <source>STB_2D_FROM_3D</source>
-        <translation>Créer un maillage 2D Ã  partir de 3D</translation>
+        <translation>Créer les Ã©léments de frontière</translation>
     </message>
     <message>
         <source>STB_MESH_ORDER</source>
@@ -2690,7 +2696,7 @@ Enregistrez votre progrès avant que l&apos;application se plante</translation>
     </message>
     <message>
         <source>TOP_2D_FROM_3D</source>
-        <translation>Créer un Maillage 2D Ã  partir de 3D</translation>
+        <translation>Créer les Ã©léments de frontière</translation>
     </message>
     <message>
         <source>TOP_MESH_ORDER</source>
@@ -3240,6 +3246,14 @@ Ouvrez le visualisateur VTK et essayez de nouveau</translation>
         <source>PREF_AUTO_UPDATE</source>
         <translation>Mettre Ã  Jour Automatiquement</translation>
     </message>
+    <message>
+        <source>PREF_UPDATE_LIMIT</source>
+        <translation>Limite de taille (nombre d&apos;éléments)</translation>
+    </message>
+    <message>
+        <source>PREF_UPDATE_LIMIT_NOLIMIT</source>
+        <translation>Sans limite</translation>
+    </message>
     <message>
         <source>PREF_BACKFACE</source>
         <translation>Face Arrière</translation>
@@ -3340,10 +3354,6 @@ Ouvrez le visualisateur VTK et essayez de nouveau</translation>
         <source>PREF_GROUP_SELECTION</source>
         <translation>Sélection</translation>
     </message>
-    <message>
-        <source>PREF_GROUP_UPDATE</source>
-        <translation>Mettre Ã  jour</translation>
-    </message>
     <message>
         <source>PREF_HIGHLIGHT_COLOR</source>
         <translation>Couleur de sélection</translation>
@@ -3625,13 +3635,6 @@ Indiquez-le et essayez de nouveau</translation>
         <translation>Un maillage valide n&apos;est pas choisi</translation>
     </message>
 </context>
-<context>
-    <name>SMESHGUI_Make2DFrom3DDlg</name>
-    <message>
-        <source>CAPTION</source>
-        <translation>Créer un maillage 2D Ã  partir de 3D</translation>
-    </message>
-</context>
 <context>
     <name>SMESHGUI_CreatePatternDlg</name>
     <message>
@@ -3752,7 +3755,7 @@ Choisissez un groupe et essayez de nouveau</translation>
     </message>
 </context>
 <context>
-    <name>SMESHGUI_EditMeshDlg</name>
+    <name>SMESHGUI_MergeDlg</name>
     <message>
         <source>COINCIDENT_ELEMENTS</source>
         <translation>Eléments Coïncidents</translation>
@@ -3773,6 +3776,10 @@ Choisissez un groupe et essayez de nouveau</translation>
         <source>SELECT_ALL</source>
         <translation>Choisir Tous</translation>
     </message>
+    <message>
+        <source>EXCLUDE_GROUPS</source>
+        <translation>Exclure les Groupes</translation>
+    </message>
 </context>
 <context>
     <name>SMESHGUI_ExtrusionAlongPathDlg</name>
@@ -3913,6 +3920,16 @@ Choisissez une face et essayez de nouveau</translation>
         <source>SHAPE_IS_NOT_A_PLANE</source>
         <translation>&quot;%1&quot; n&apos;est pas un plan
 Choisissez un plan et essayez de nouveau</translation>
+    </message>
+    <message>
+        <source>FACE_ID_NOT_SELECTED</source>
+        <translation>La face de maillage n&apos;est pas choisie.
+Indiquez-la et essayez de nouveau.</translation>
+    </message>
+    <message>
+        <source>NOT_FACE_ID</source>
+        <translation>&quot;%1&quot; n&apos;est l&apos;ID valide d&apos;une face du maillage.
+Choisissez la face et essayez de nouveau.</translation>
     </message>
     <message>
         <source>SOURCE</source>
@@ -4121,6 +4138,10 @@ Vérifiez la validité de l&apos;information d&apos;entrée et essayez de nouvea
         <source>COMPARE</source>
         <translation>Comparer</translation>
     </message>
+    <message>
+        <source>COPLANAR_FACES</source>
+        <translation>Faces Coplanaires</translation>
+    </message>
     <message>
         <source>COPY_FROM</source>
         <translation>Copier de...</translation>
@@ -4845,6 +4866,10 @@ Il y a trop peu de points au fichier pour charger le circuit</translation>
         <source>SPLIT_HEX_TO_6_TETRA</source>
         <translation>En 6 tétraèdres</translation>
     </message>
+    <message>
+        <source>SPLIT_HEX_TO_24_TETRA</source>
+        <translation>En 24 tétraèdres</translation>
+    </message>
 </context>
 <context>
     <name>SMESHGUI_PrecisionDlg</name>
@@ -5234,4 +5259,78 @@ Il y a trop peu de points au fichier pour charger le circuit</translation>
         <translation>Construire un groupe avec les Ã©léments créés de nouveau</translation>
     </message>
 </context>
+<context>
+    <name>SMESHGUI_Make2DFrom3DDlg</name>
+    <message>
+        <source>CAPTION</source>
+        <translation>Créer les Ã©léments de frontière</translation>
+    </message>
+    <message>
+        <source>MESH</source>
+        <translation>Maillage, sous-maillage ou groupe</translation>
+    </message>
+    <message>
+        <source>MODE</source>
+        <translation>Mode</translation>
+    </message>
+    <message>
+        <source>2D_FROM_3D</source>
+        <translation>2D Ã  partir de 3D</translation>
+    </message>
+    <message>
+        <source>1D_FROM_3D</source>
+        <translation>1D Ã  partir de 3D</translation>
+    </message>
+    <message>
+        <source>1D_FROM_2D</source>
+        <translation>1D Ã  partir de 2D</translation>
+    </message>
+    <message>
+        <source>TARGET</source>
+        <translation>Cible</translation>
+    </message>
+    <message>
+        <source>THIS_MESH</source>
+        <translation>Ce maillage</translation>
+    </message>
+    <message>
+        <source>NEW_MESH</source>
+        <translation>Maillage nouveau</translation>
+    </message>
+    <message>
+        <source>COPY_SRC</source>
+        <translation>Copier le maillage source</translation>
+    </message>
+    <message>
+        <source>MISSING_ONLY</source>
+        <translation>Copier seulment les Ã©léments manquants</translation>
+    </message>
+    <message>
+        <source>CREATE_GROUP</source>
+        <translation>Créer un groupe</translation>
+    </message>
+</context>
+<context>
+    <name>SMESHGUI_Make2DFrom3DOp</name>
+    <message>
+        <source>SMESH_ERR_NO_INPUT_MESH</source>
+        <translation>Aucun maillage, sous-maillage ou groupe source n&apos;est indiqué</translation>
+    </message>
+    <message>
+        <source>SMESH_ERR_NO_3D_ELEMENTS</source>
+        <translation>L&apos;objet source ne contient pas d&apos;éléments 3D</translation>
+    </message>
+    <message>
+        <source>SMESH_ERR_NO_2D_ELEMENTS</source>
+        <translation>L&apos;objet source ne contient pas d&apos;éléments 2D</translation>
+    </message>
+    <message>
+        <source>SMESH_ERR_MESH_NAME_NOT_SPECIFIED</source>
+        <translation>Le nouveau nom du maillage n&apos;est pas indiqué</translation>
+    </message>
+    <message>
+        <source>SMESH_ERR_GRP_NAME_NOT_SPECIFIED</source>
+        <translation>Le nom du groupe n&apos;est pas indiqué</translation>
+    </message>
+</context>
 </TS>
index 91aaa656e9414d0034d367c3678243ad5a3e9879..4bc9f1aa21b83508a9877ff3048e81a59e56d891 100644 (file)
@@ -287,6 +287,7 @@ namespace SMESH
       case FT_BelongToCylinder: myStream<< "aBelongToCylinder"; break;
       case FT_BelongToGenSurface:myStream<<"aBelongToGenSurface";break;
       case FT_LyingOnGeom:      myStream<< "aLyingOnGeom";      break;
+      case FT_CoplanarFaces:    myStream<< "aCoplanarFaces";    break;
       case FT_RangeOfIds:       myStream<< "aRangeOfIds";       break;
       case FT_BadOrientedVolume:myStream<< "aBadOrientedVolume";break;
       case FT_LinearOrQuadratic:myStream<< "aLinearOrQuadratic";break;
index 67c0addd1bb35ff81dbbd4b3afc98d5e170d4297..477e92a1372ef2bb9bc50ff6c7b4c4ed0234331b 100644 (file)
@@ -1443,7 +1443,7 @@ void ElemGeomType_i::SetGeometryType(GeometryType theType)
 
 GeometryType ElemGeomType_i::GetGeometryType() const
 {
-  return (GeometryType)myElemGeomTypePtr->GetGeomType();;
+  return (GeometryType)myElemGeomTypePtr->GetGeomType();
 }
 
 FunctorType ElemGeomType_i::GetFunctorType()
@@ -1451,6 +1451,49 @@ FunctorType ElemGeomType_i::GetFunctorType()
   return SMESH::FT_ElemGeomType;
 }
 
+/*
+  Class       : CoplanarFaces_i
+  Description : Returns true if a mesh face is a coplanar neighbour to a given one
+*/
+CoplanarFaces_i::CoplanarFaces_i()
+{
+  myCoplanarFacesPtr.reset(new Controls::CoplanarFaces());
+  myFunctorPtr = myPredicatePtr = myCoplanarFacesPtr;
+}
+
+void CoplanarFaces_i::SetFace ( CORBA::Long theFaceID )
+{
+  myCoplanarFacesPtr->SetFace(theFaceID);
+  TPythonDump()<<this<<".SetFace("<<theFaceID<<")";
+}
+
+void CoplanarFaces_i::SetTolerance( CORBA::Double theToler )
+{
+  myCoplanarFacesPtr->SetTolerance(theToler);
+  TPythonDump()<<this<<".SetTolerance("<<theToler<<")";
+}
+
+CORBA::Long CoplanarFaces_i::GetFace () const
+{
+  return myCoplanarFacesPtr->GetFace();
+}
+
+char* CoplanarFaces_i::GetFaceAsString () const
+{
+  TCollection_AsciiString str(Standard_Integer(myCoplanarFacesPtr->GetFace()));
+  return CORBA::string_dup( str.ToCString() );
+}
+
+CORBA::Double CoplanarFaces_i::GetTolerance() const
+{
+  return myCoplanarFacesPtr->GetTolerance();
+}
+
+FunctorType CoplanarFaces_i::GetFunctorType()
+{
+  return SMESH::FT_CoplanarFaces;
+}
+
 /*
   Class       : Comparator_i
   Description : Base class for comparators
@@ -1867,6 +1910,14 @@ LyingOnGeom_ptr FilterManager_i::CreateLyingOnGeom()
   return anObj._retn();
 }
 
+CoplanarFaces_ptr FilterManager_i::CreateCoplanarFaces()
+{
+  SMESH::CoplanarFaces_i* aServant = new SMESH::CoplanarFaces_i();
+  SMESH::CoplanarFaces_var anObj = aServant->_this();
+  TPythonDump()<<aServant<<" = "<<this<<".CreateCoplanarFaces()";
+  return anObj._retn();
+}
+
 FreeBorders_ptr FilterManager_i::CreateFreeBorders()
 {
   SMESH::FreeBorders_i* aServant = new SMESH::FreeBorders_i();
@@ -2300,6 +2351,22 @@ static inline bool getCriteria( Predicate_i*                thePred,
       theCriteria[ i ].TypeOfElement = aPred->GetElementType();
       theCriteria[ i ].Tolerance     = aPred->GetTolerance();
 
+      return true;
+    }
+   case FT_CoplanarFaces:
+    {
+      CoplanarFaces_i* aPred = dynamic_cast<CoplanarFaces_i*>( thePred );
+
+      CORBA::ULong i = theCriteria->length();
+      theCriteria->length( i + 1 );
+
+      theCriteria[ i ] = createCriterion();
+      CORBA::String_var faceId = aPred->GetFaceAsString();
+
+      theCriteria[ i ].Type          = FT_CoplanarFaces;
+      theCriteria[ i ].ThresholdID   = faceId;
+      theCriteria[ i ].Tolerance     = aPred->GetTolerance();
+
       return true;
     }
   case FT_RangeOfIds:
@@ -2593,6 +2660,14 @@ CORBA::Boolean Filter_i::SetCriteria( const SMESH::Filter::Criteria& theCriteria
           aPredicate = tmpPred;
           break;
         }
+      case SMESH::FT_CoplanarFaces:
+        {
+          SMESH::CoplanarFaces_ptr tmpPred = aFilterMgr->CreateCoplanarFaces();
+          tmpPred->SetFace( atol (aThresholdID ));
+          tmpPred->SetTolerance( aTolerance );
+          aPredicate = tmpPred;
+          break;
+        }
 
       default:
         continue;
index 5451f821fe939a150352d8054fe8da9faef9d347..aefc71ef621b5ae1ef4e530b95b1714263274be1 100644 (file)
@@ -622,6 +622,26 @@ namespace SMESH
     Controls::ElemGeomTypePtr myElemGeomTypePtr;
   };
   
+  /*
+    Class       : CoplanarFaces_i
+    Description : Returns true if a mesh face is a coplanar neighbour to a given one
+  */
+  class SMESH_I_EXPORT CoplanarFaces_i: public virtual POA_SMESH::CoplanarFaces,
+                  public virtual Predicate_i
+  {
+  public:
+    CoplanarFaces_i();
+    FunctorType             GetFunctorType();
+
+    void                    SetFace ( CORBA::Long theFaceID );
+    void                    SetTolerance( CORBA::Double theToler );
+    char*                   GetFaceAsString () const;
+    CORBA::Long             GetFace () const;
+    CORBA::Double           GetTolerance () const;
+  private:
+    Controls::CoplanarFacesPtr myCoplanarFacesPtr;
+  };
+  
   /*
     Class       : Comparator_i
     Description : Base class for comparators
@@ -908,13 +928,11 @@ namespace SMESH
     FreeFaces_ptr             CreateFreeFaces();
     
     RangeOfIds_ptr            CreateRangeOfIds();
-    
     BadOrientedVolume_ptr     CreateBadOrientedVolume();
     LinearOrQuadratic_ptr     CreateLinearOrQuadratic();
-    
     GroupColor_ptr            CreateGroupColor();
-
     ElemGeomType_ptr          CreateElemGeomType();
+    CoplanarFaces_ptr         CreateCoplanarFaces();
 
     LessThan_ptr              CreateLessThan();
     MoreThan_ptr              CreateMoreThan();
index 96d566b5b494a0e0be9b85bdff7e7f4d4ca5dc3b..08ce77e368ad2765934599304aa5c5ef888df523 100644 (file)
@@ -3198,7 +3198,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::SaveASCII( SALOMEDS::SComponent_ptr theComponent
                                            bool                     isMultiFile ) {
   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::SaveASCII" );
   SALOMEDS::TMPFile_var aStreamFile = Save( theComponent, theURL, isMultiFile );
-  //return aStreamFile._retn();
+  return aStreamFile._retn();
 
   //after usual saving needs to encipher binary to text string
   //Any binary symbol will be represent as "|xx" () hexadecimal format number
@@ -4300,7 +4300,7 @@ bool SMESH_Gen_i::LoadASCII( SALOMEDS::SComponent_ptr theComponent,
                              const char*              theURL,
                              bool                     isMultiFile ) {
   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::LoadASCII" );
-  //return Load( theComponent, theStream, theURL, isMultiFile );
+  return Load( theComponent, theStream, theURL, isMultiFile );
 
   //before call main ::Load method it's need for decipher text format to
   //binary ( "|xx" => x' )
index e600c37f07a57dba8557f4b62299afc8813e8a54..592d172bacbdd4b61c8da769af0630132ab76541 100644 (file)
@@ -36,6 +36,8 @@
 #include "SMESH_Filter_i.hxx"
 #include "SMESH_PythonDump.hxx"
 
+#include CORBA_SERVER_HEADER(SMESH_Filter)
+
 #include "utilities.h"
 
 using namespace SMESH;
@@ -353,19 +355,20 @@ CORBA::Long SMESH_Group_i::AddFrom( SMESH::SMESH_IDSource_ptr theSource )
   SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>( GetGroupDS() );
   if (aGroupDS) {
     SMESH::long_array_var anIds;
-    if ( !CORBA::is_nil(SMESH::SMESH_GroupBase::_narrow(theSource)) &&
-         SMESH::SMESH_GroupBase::_narrow(theSource)->GetType() == GetType() ) {
+    SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theSource);
+    SMESH::SMESH_Mesh_var mesh       = SMESH::SMESH_Mesh::_narrow(theSource);
+    SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow(theSource);
+    SMESH::Filter_var filter         = SMESH::Filter::_narrow(theSource);
+    if ( !group->_is_nil())
+      anIds = group->GetType()==GetType() ? theSource->GetIDs() :  new SMESH::long_array();
+    else if ( !mesh->_is_nil() )
+      anIds = mesh->GetElementsByType( GetType() );
+    else if ( !submesh->_is_nil())
+      anIds = submesh->GetElementsByType( GetType() );
+    else if ( !filter->_is_nil() )
+      anIds = filter->GetElementType()==GetType() ? theSource->GetIDs() : new SMESH::long_array();
+    else 
       anIds = theSource->GetIDs();
-    }
-    else if ( !CORBA::is_nil(SMESH::SMESH_Mesh::_narrow(theSource)) ) {
-      anIds = SMESH::SMESH_Mesh::_narrow(theSource)->GetElementsByType( GetType() );
-    }
-    else if ( !CORBA::is_nil(SMESH::SMESH_subMesh::_narrow(theSource)) ) {
-      anIds = SMESH::SMESH_subMesh::_narrow(theSource)->GetElementsByType( GetType() );
-    }
-    else {
-      anIds->length( 0 );
-    }
     for ( int i = 0, total = anIds->length(); i < total; i++ ) {
       if ( aGroupDS->Add((int)anIds[i]) ) nbAdd++;
     }
index b88de2d3951e42016f5f55ea5b89f7b3a1b3a9e1..5da4f5cebf84549a7f8dfcf361ffd89957f9787e 100644 (file)
 //  Author : Nicolas REJNERI
 //  Module : SMESH
 //
+#ifdef WNT
+#define NOMINMAX
+#endif
+
 #include "SMESH_MeshEditor_i.hxx"
 
 #include "SMDS_Mesh0DElement.hxx"
@@ -5182,7 +5186,98 @@ CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
   ::SMESH_MeshEditor aMeshEditor( myMesh );
   bool aResult = aMeshEditor.Make2DMeshFrom3D();
   storeResult( aMeshEditor) ;
-  
+
   TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
   return aResult;
 }
+
+// issue 20749 ===================================================================
+/*!
+ * \brief Creates missing boundary elements
+ *  \param elements - elements whose boundary is to be checked
+ *  \param dimension - defines type of boundary elements to create
+ *  \param groupName - a name of group to store created boundary elements in,
+ *                     "" means not to create the group
+ *  \param meshName - a name of new mesh to store created boundary elements in,
+ *                     "" means not to create the new mesh
+ *  \param toCopyElements - if true, the checked elements will be copied into the new mesh
+ *  \param toCopyExistingBondary - if true, not only new but also pre-existing 
+ *                                boundary elements will be copied into the new mesh
+ *  \param group - returns the create group, if any
+ *  \retval SMESH::SMESH_Mesh - the mesh where elements were added to
+ */
+// ================================================================================
+
+SMESH::SMESH_Mesh_ptr
+SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
+                                     SMESH::Bnd_Dimension      dim,
+                                     const char*               groupName,
+                                     const char*               meshName,
+                                     CORBA::Boolean            toCopyElements,
+                                     CORBA::Boolean            toCopyExistingBondary,
+                                     SMESH::SMESH_Group_out    group)
+{
+  initData();
+
+  if ( dim > SMESH::BND_1DFROM2D )
+    THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
+
+  
+  SMESHDS_Mesh* aMeshDS = GetMeshDS();
+
+  SMESH::SMESH_Mesh_var mesh_var;
+  SMESH::SMESH_Group_var group_var;
+
+  TPythonDump pyDump;
+
+  TIDSortedElemSet elements;
+  SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
+  if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
+  {
+    // mesh to fill in
+    mesh_var =
+      strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
+    SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
+    // other mesh
+    SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
+
+    // group of new boundary elements
+    SMESH_Group* smesh_group = 0;
+    if ( strlen(groupName) )
+    {
+      group_var = mesh_i->CreateGroup( SMESH::ElementType(elemType),groupName);
+      if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
+        smesh_group = group_i->GetSmeshGroup();
+    }
+
+    // do it
+    ::SMESH_MeshEditor aMeshEditor( myMesh );
+    aMeshEditor.MakeBoundaryMesh( elements,
+                                  ::SMESH_MeshEditor::Bnd_Dimension(dim),
+                                  smesh_group,
+                                  smesh_mesh,
+                                  toCopyElements,
+                                  toCopyExistingBondary);
+    storeResult( aMeshEditor );
+  }
+
+  // result of MakeBoundaryMesh() is a tuple (mesh, group)
+  if ( mesh_var->_is_nil() )
+    pyDump << myMesh_i->_this() << ", ";
+  else
+    pyDump << mesh_var << ", ";
+  if ( group_var->_is_nil() )
+    pyDump << "_NoneGroup = "; // assignment to None is forbiden
+  else
+    pyDump << group_var << " = ";
+  pyDump << this << ".MakeBoundaryMesh( "
+         << idSource << ", "
+         << dim << ", "
+         << groupName << ", "
+         << meshName<< ", "
+         << toCopyElements << ", "
+         << toCopyExistingBondary << ")";
+
+  group = group_var._retn();
+  return mesh_var._retn();
+}
index 330a52faf47e20adde886d6a881ac1692e085fbe..3a96b87cdf8056c5afd8cbbe5704cbeed3327d3e 100644 (file)
@@ -671,14 +671,22 @@ public:
                                                const SMESH::ListOfGroups& theNodesNot,
                                                GEOM::GEOM_Object_ptr      theShape );
 
-    /*!
-     * \brief Generated skin mesh (containing 2D cells) from 3D mesh
-     * The created 2D mesh elements based on nodes of free faces of boundary volumes
-     * \return TRUE if operation has been completed successfully, FALSE otherwise
-    */
-    CORBA::Boolean Make2DMeshFrom3D();
-
- private: //!< private methods
+  /*!
+   * \brief Generated skin mesh (containing 2D cells) from 3D mesh
+   * The created 2D mesh elements based on nodes of free faces of boundary volumes
+   * \return TRUE if operation has been completed successfully, FALSE otherwise
+   */
+  CORBA::Boolean Make2DMeshFrom3D();
+
+  SMESH::SMESH_Mesh_ptr MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr elements,
+                                         SMESH::Bnd_Dimension      dimension,
+                                         const char*               groupName,
+                                         const char*               meshName,
+                                         CORBA::Boolean            toCopyElements,
+                                         CORBA::Boolean            toCopyMissingBondary,
+                                         SMESH::SMESH_Group_out    group);
+
+private: //!< private methods
 
   SMESHDS_Mesh * GetMeshDS() { return myMesh->GetMeshDS(); }
 
index bb8c8b4971c2b3dd79466ff4a500ca73d7717dd2..de07a09f7e89aa40c746e7bebefaa99e9853e59e 100644 (file)
@@ -2788,7 +2788,7 @@ SMESH::long_array* SMESH_Mesh_i::GetNodesId()
 
   long nbNodes = NbNodes();
   aResult->length( nbNodes );
-  SMDS_NodeIteratorPtr anIt = aSMESHDS_Mesh->nodesIterator();
+  SMDS_NodeIteratorPtr anIt = aSMESHDS_Mesh->nodesIterator(/*idInceasingOrder=*/true);
   for ( int i = 0, n = nbNodes; i < n && anIt->more(); i++ )
     aResult[i] = anIt->next()->GetID();
 
index 3d725b8fb6e47dcaf126d53c2573399668827e38..2a799a5b6d5cf5b23e434847a3e31e013f6c1eff 100644 (file)
@@ -387,7 +387,14 @@ CORBA::Boolean SMESH_Pattern_i::MakeMesh (SMESH::SMESH_Mesh_ptr theMesh,
                 << CreatePolygons << ", " << CreatePolyedrs << " )";
   addErrorCode( "MakeMesh" );
 
-  return myPattern.MakeMesh( aMesh, CreatePolygons, CreatePolyedrs );
+  int nb = aMesh->NbNodes() + aMesh->NbEdges() + aMesh->NbFaces() + aMesh->NbVolumes();
+
+  bool res = myPattern.MakeMesh( aMesh, CreatePolygons, CreatePolyedrs );
+
+  if ( nb > 0 && nb != aMesh->NbNodes() + aMesh->NbEdges() + aMesh->NbFaces() + aMesh->NbVolumes())
+    aMesh->SetIsModified(true);
+
+  return res;
 }
 
 //=======================================================================
index 8401ce7755da50a8c3ac59b5df82a7c6db6f079a..faa7aa1ca5230a80dce400abbf675ab7bb246ec0 100644 (file)
@@ -555,16 +555,26 @@ SMESH::long_array* SMESH_subMesh_i::GetMeshInfo()
 SMESH::array_of_ElementType* SMESH_subMesh_i::GetTypes()
 {
   SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
-  types->length( 1 );
+
   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
-  switch ( ::SMESH_Gen::GetShapeDim( aSubMesh->GetSubShape() ))
+  TopoDS_Shape shape = aSubMesh->GetSubShape();
+  while ( !shape.IsNull() && shape.ShapeType() == TopAbs_COMPOUND )
   {
-  case 0: types[0] = SMESH::ELEM0D; break;
-  case 1: types[0] = SMESH::EDGE; break;
-  case 2: types[0] = SMESH::FACE; break;
-  case 3: types[0] = SMESH::VOLUME; break;
-  default:
-    types->length(0);
+    TopoDS_Iterator it( shape );
+    shape = it.More() ? it.Value() : TopoDS_Shape();
+  }
+  if ( !shape.IsNull() )
+  {
+    types->length( 1 );
+    switch ( ::SMESH_Gen::GetShapeDim( shape ))
+    {
+    case 0: types[0] = SMESH::ELEM0D; break;
+    case 1: types[0] = SMESH::EDGE; break;
+    case 2: types[0] = SMESH::FACE; break;
+    case 3: types[0] = SMESH::VOLUME; break;
+    default:
+      types->length(0);
+    }
   }
   return types._retn();
 }
index 9a88f94a05746a093dcd557f532338ecf7bdcb4c..1e01d2ac014ea7f315723b319311921343f5106a 100644 (file)
@@ -50,6 +50,7 @@
 ##     @defgroup l3_hypos_ghs3dh GHS3D Parameters hypothesis
 ##     @defgroup l3_hypos_blsurf BLSURF Parameters hypothesis
 ##     @defgroup l3_hypos_hexotic Hexotic Parameters hypothesis
+##     @defgroup l3_hypos_quad Quadrangle Parameters hypothesis
 ##     @defgroup l3_hypos_additi Additional Hypotheses
 
 ##   @}
@@ -201,6 +202,9 @@ PrecisionConfusion = 1e-07
 # Methods of splitting a hexahedron into tetrahedra
 Hex_5Tet, Hex_6Tet, Hex_24Tet = 1, 2, 3
 
+# import items of enum QuadType
+for e in StdMeshers.QuadType._items: exec('%s = StdMeshers.%s'%(e,e))
+
 ## Converts an angle from degrees to radians
 def DegreesToRadians(AngleInDegrees):
     from math import pi
@@ -772,6 +776,18 @@ class smeshDC(SMESH._objref_SMESH_Gen):
             else:
                 print "Error: The treshold should be a string."
                 return None
+        elif CritType == FT_CoplanarFaces:
+            # Checks the treshold
+            if isinstance(aTreshold, int):
+                aCriterion.ThresholdID = "%s"%aTreshold
+            elif isinstance(aTreshold, str):
+                ID = int(aTreshold)
+                if ID < 1:
+                    raise ValueError, "Invalid ID of mesh face: '%s'"%aTreshold
+                aCriterion.ThresholdID = aTreshold
+            else:
+                raise ValueError,\
+                      "The treshold should be an ID of mesh face and not '%s'"%aTreshold
         elif CritType == FT_ElemGeomType:
             # Checks the treshold
             try:
@@ -1643,9 +1659,9 @@ class Mesh:
     #  @return SMESH_Group
     #  @ingroup l2_grps_create
     def MakeGroupByFilter(self, groupName, theFilter):
-        anIds = theFilter.GetElementsId(self.mesh)
-        anElemType = theFilter.GetElementType()
-        group = self.MakeGroupByIds(groupName, anElemType, anIds)
+        group = self.CreateEmptyGroup(theFilter.GetElementType(), groupName)
+        theFilter.SetMesh( self.mesh )
+        group.AddFrom( theFilter )
         return group
 
     ## Passes mesh elements through the given filter and return IDs of fitting elements
@@ -1653,7 +1669,8 @@ class Mesh:
     #  @return a list of ids
     #  @ingroup l1_controls
     def GetIdsFromFilter(self, theFilter):
-        return theFilter.GetElementsId(self.mesh)
+        theFilter.SetMesh( self.mesh )
+        return theFilter.GetIDs()
 
     ## Verifies whether a 2D mesh element has free edges (edges connected to one face only)\n
     #  Returns a list of special structures (borders).
@@ -2558,6 +2575,8 @@ class Mesh:
     def SplitVolumesIntoTetra(self, elemIDs, method=Hex_5Tet ):
         if isinstance( elemIDs, Mesh ):
             elemIDs = elemIDs.GetMesh()
+        if ( isinstance( elemIDs, list )):
+            elemIDs = self.editor.MakeIDSource(elemIDs, SMESH.VOLUME)
         self.editor.SplitVolumesIntoTetra(elemIDs, method)
 
     ## Splits quadrangle faces near triangular facets of volumes
@@ -2792,7 +2811,34 @@ class Mesh:
     #  @ingroup l2_modif_edit
     def  Make2DMeshFrom3D(self):
         return self.editor. Make2DMeshFrom3D()
-        
+
+    ## Creates missing boundary elements
+    #  @param elements - elements whose boundary is to be checked:
+    #                    mesh, group, sub-mesh or list of elements
+    #  @param dimension - defines type of boundary elements to create:
+    #                     SMESH.BND_2DFROM3D, SMESH.BND_1DFROM3D, SMESH.BND_1DFROM2D
+    #  @param groupName - a name of group to store created boundary elements in,
+    #                     "" means not to create the group
+    #  @param meshName - a name of new mesh to store created boundary elements in,
+    #                     "" means not to create the new mesh
+    #  @param toCopyElements - if true, the checked elements will be copied into the new mesh
+    #  @param toCopyExistingBondary - if true, not only new but also pre-existing 
+    #                                boundary elements will be copied into the new mesh
+    #  @return tuple (mesh, group) where bondary elements were added to
+    #  @ingroup l2_modif_edit
+    def MakeBoundaryMesh(self, elements, dimension=SMESH.BND_2DFROM3D, groupName="", meshName="",
+                         toCopyElements=False, toCopyExistingBondary=False):
+        if isinstance( elements, Mesh ):
+            elements = elements.GetMesh()
+        if ( isinstance( elements, list )):
+            elemType = SMESH.ALL
+            if elements: elemType = self.GetElementType( elements[0], iselem=True)
+            elements = self.editor.MakeIDSource(elements, elemType)
+        mesh, group = self.editor.MakeBoundaryMesh(elements,dimension,groupName,meshName,
+                                                   toCopyElements,toCopyExistingBondary)
+        if mesh: mesh = self.smeshpyD.Mesh(mesh)
+        return mesh, group
+
     ## Renumber mesh nodes
     #  @ingroup l2_modif_renumber
     def RenumberNodes(self):
@@ -3584,11 +3630,11 @@ class Mesh:
     def FindCoincidentNodesOnPart (self, SubMeshOrGroup, Tolerance, exceptNodes=[]):
         if (isinstance( SubMeshOrGroup, Mesh )):
             SubMeshOrGroup = SubMeshOrGroup.GetMesh()
-        if not isinstance( ExceptSubMeshOrGroups, list):
-            ExceptSubMeshOrGroups = [ ExceptSubMeshOrGroups ]
-        if ExceptSubMeshOrGroups and isinstance( ExceptSubMeshOrGroups[0], int):
-            ExceptSubMeshOrGroups = [ self.editor.MakeIDSource( ExceptSubMeshOrGroups, SMESH.NODE)]
-        return self.editor.FindCoincidentNodesOnPartBut(SubMeshOrGroup, Tolerance,ExceptSubMeshOrGroups)
+        if not isinstance( exceptNodes, list):
+            exceptNodes = [ exceptNodes ]
+        if exceptNodes and isinstance( exceptNodes[0], int):
+            exceptNodes = [ self.editor.MakeIDSource( exceptNodes, SMESH.NODE)]
+        return self.editor.FindCoincidentNodesOnPartBut(SubMeshOrGroup, Tolerance,exceptNodes)
 
     ## Merges nodes
     #  @param GroupsOfNodes the list of groups of nodes
@@ -3944,7 +3990,8 @@ class Mesh_Algorithm:
                 pass
             except:
                 name = mesh.geompyD.SubShapeName(geom, piece)
-                mesh.geompyD.addToStudyInFather(piece, geom, name)
+                if not name:
+                    name = "%s_%s"%(geom.GetShapeType(), id(geom%1000))
                 pass
             self.subm = mesh.mesh.GetSubMesh(geom, algo.GetName())
 
@@ -4649,48 +4696,96 @@ class Mesh_Triangle(Mesh_Algorithm):
 #  @ingroup l3_algos_basic
 class Mesh_Quadrangle(Mesh_Algorithm):
 
+    params=0
+
     ## Private constructor.
     def __init__(self, mesh, geom=0):
         Mesh_Algorithm.__init__(self)
         self.Create(mesh, geom, "Quadrangle_2D")
+        return
 
-    ## Defines "QuadranglePreference" hypothesis, forcing construction
-    #  of quadrangles if the number of nodes on the opposite edges is not the same
-    #  while the total number of nodes on edges is even
-    #
-    #  @ingroup l3_hypos_additi
-    def QuadranglePreference(self):
-        hyp = self.Hypothesis("QuadranglePreference", UseExisting=1,
-                              CompareMethod=self.CompareEqualHyp)
-        return hyp
+    ## Defines "QuadrangleParameters" hypothesis
+    #  @param quadType defines the algorithm of transition between differently descretized
+    #                  sides of a geometrical face:
+    #  - QUAD_STANDARD - both triangles and quadrangles are possible in the transition
+    #                    area along the finer meshed sides. 
+    #  - QUAD_TRIANGLE_PREF - only triangles are built in the transition area along the
+    #                    finer meshed sides.
+    #  - QUAD_QUADRANGLE_PREF - only quadrangles are built in the transition area along
+    #                    the finer meshed sides, iff the total quantity of segments on
+    #                    all four sides of the face is even (divisible by 2).
+    #  - QUAD_QUADRANGLE_PREF_REVERSED - same as QUAD_QUADRANGLE_PREF but the transition
+    #                    area is located along the coarser meshed sides. 
+    #  - QUAD_REDUCED - only quadrangles are built and the transition between the sides
+    #                    is made gradually, layer by layer. This type has a limitation on
+    #                    the number of segments: one pair of opposite sides must have the
+    #                    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
+    #  @ingroup l3_hypos_quad
+    def QuadrangleParameters(self, quadType=StdMeshers.QUAD_STANDARD, triangleVertex=0, UseExisting=0):
+        vertexID = triangleVertex
+        if isinstance( triangleVertex, geompyDC.GEOM._objref_GEOM_Object ):
+            vertexID = self.mesh.geompyD.GetSubShapeID( self.mesh.geom, triangleVertex )
+        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],
+                                          UseExisting = UseExisting, CompareMethod=compFun)
+            pass
+        if self.params.GetQuadType() != quadType:
+            self.params.SetQuadType(quadType)
+        if vertexID > 0:
+            self.params.SetTriaVertex( vertexID )
+        return self.params
 
-    ## Defines "TrianglePreference" hypothesis, forcing construction
-    #  of triangles in the refinement area if the number of nodes
-    #  on the opposite edges is not the same
-    #
-    #  @ingroup l3_hypos_additi
-    def TrianglePreference(self):
-        hyp = self.Hypothesis("TrianglePreference", UseExisting=1,
-                              CompareMethod=self.CompareEqualHyp)
-        return hyp
+    ## Defines "QuadrangleParams" hypothesis with a type of quadrangulation that only
+    #   quadrangles are built in the transition area along the finer meshed sides,
+    #   iff the total quantity of segments on all four sides of the face is even.
+    #  @param reversed if True, transition area is located along the coarser meshed sides.
+    #  @param UseExisting: if ==true - searches for the existing hypothesis created with
+    #                  the same parameters, else (default) - creates a new one
+    #  @ingroup l3_hypos_quad
+    def QuadranglePreference(self, reversed=False, UseExisting=0):
+        if reversed:
+            return self.QuadrangleParameters(QUAD_QUADRANGLE_PREF_REVERSED,UseExisting=UseExisting)
+        return self.QuadrangleParameters(QUAD_QUADRANGLE_PREF,UseExisting=UseExisting)
+
+    ## Defines "QuadrangleParams" hypothesis with a type of quadrangulation that only
+    #   triangles are built in the transition area along the finer meshed sides.
+    #  @param UseExisting: if ==true - searches for the existing hypothesis created with
+    #                  the same parameters, else (default) - creates a new one
+    #  @ingroup l3_hypos_quad
+    def TrianglePreference(self, UseExisting=0):
+        return self.QuadrangleParameters(QUAD_TRIANGLE_PREF,UseExisting=UseExisting)
+
+    ## Defines "QuadrangleParams" hypothesis with a type of quadrangulation that only
+    #   quadrangles are built and the transition between the sides is made gradually,
+    #   layer by layer. This type has a limitation on the number of segments: one pair
+    #   of opposite sides must have the same number of segments, the other pair must
+    #   have an even difference between the numbers of segments on the sides.
+    #  @param UseExisting: if ==true - searches for the existing hypothesis created with
+    #                  the same parameters, else (default) - creates a new one
+    #  @ingroup l3_hypos_quad
+    def Reduced(self, UseExisting=0):
+        return self.QuadrangleParameters(QUAD_REDUCED,UseExisting=UseExisting)
 
-    ## Defines "QuadrangleParams" hypothesis
+    ## Defines "QuadrangleParams" hypothesis with QUAD_STANDARD type of quadrangulation
     #  @param vertex: 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
-    #
-    #  @ingroup l3_hypos_additi
+    #  @ingroup l3_hypos_quad
     def TriangleVertex(self, vertex, UseExisting=0):
-        vertexID = vertex
-        if isinstance( vertexID, geompyDC.GEOM._objref_GEOM_Object ):
-            vertexID = self.mesh.geompyD.GetSubShapeID( self.mesh.geom, vertex )
-        hyp = self.Hypothesis("QuadrangleParams", [vertexID], UseExisting = UseExisting,
-                              CompareMethod=lambda hyp,args: hyp.GetTriaVertex()==args[0])
-        hyp.SetTriaVertex( vertexID )
-        return hyp
+        return self.QuadrangleParameters(QUAD_STANDARD,vertex,UseExisting)
 
 
 # Public class: Mesh_Tetrahedron
index 036da0ba9bbf4ac6488a46633395eab921ed42e2..f882f5c92c98a59b932147c5e588b577d1eba25a 100644 (file)
@@ -452,9 +452,12 @@ void StdMeshers_FaceSide::Reverse()
     reverse( myEdgeLength );
     reverse( myIsUniform );
   }
-  myNormPar[nbEdges-1]=1.;
-  myPoints.clear();
-  myFalsePoints.clear();
+  if ( nbEdges > 0 )
+  {
+    myNormPar[nbEdges-1]=1.;
+    myPoints.clear();
+    myFalsePoints.clear();
+  }
 }
 
 //================================================================================
index 3ae9552d9e0e4371b280b1a124781499abb3cc75..39dfd2e13f8bccd02922c79ef64e94c97e820676 100644 (file)
@@ -60,7 +60,7 @@ namespace
    */
   //================================================================================
 
-  class SMDS_EXPORT Q2TAdaptor_Triangle : public SMDS_MeshFace
+  class STDMESHERS_EXPORT Q2TAdaptor_Triangle : public SMDS_MeshFace
   {
     const SMDS_MeshNode* _nodes[3];
   public:
@@ -228,7 +228,7 @@ namespace
 
     // Check angle between normals
     double angle = nI.Angle( nJ );
-    bool tooClose = ( angle < 10 * PI180 );
+    bool tooClose = ( angle < 15 * PI180 );
 
     // Check if pyramids collide
     bool isOutI, isOutJ;
@@ -315,8 +315,14 @@ namespace
       }
     }
     if ( !mergedPyrams.empty() )
-      for (TIDSortedElemSet::iterator prm = mergedPyrams.begin(); prm != mergedPyrams.end(); ++prm)
+    {
+      TIDSortedElemSet::iterator prm;
+//       for (prm = mergedPyrams.begin(); prm != mergedPyrams.end(); ++prm)
+//         MergeAdjacent( *prm, mesh, nodesToMove );
+
+      for (prm = adjacentPyrams.begin(); prm != adjacentPyrams.end(); ++prm)
         MergeAdjacent( *prm, mesh, nodesToMove );
+    }
   }
 }
 
index 07cd7f6490082547f043684465691a301a93f193..c0e106364bfd9c4f44f25efd20ae83a2a9d590a3 100644 (file)
 //
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-
 //  SMESH SMESH : implementaion of SMESH idl descriptions
 //  File   : StdMeshers_QuadrangleParams.cxx
 //  Author : Sergey KUUL, OCC
 //  Module : SMESH
-//
+
 #include "StdMeshers_QuadrangleParams.hxx"
 
 #include "SMESH_Algo.hxx"
@@ -41,38 +40,36 @@ using namespace std;
 
 //=============================================================================
 /*!
- *  
+ *
  */
 //=============================================================================
-
 StdMeshers_QuadrangleParams::StdMeshers_QuadrangleParams(int hypId, int studyId,
                                                          SMESH_Gen * gen)
-  :SMESH_Hypothesis(hypId, studyId, gen)
+  : SMESH_Hypothesis(hypId, studyId, gen)
 {
   _name = "QuadrangleParams";
   _param_algo_dim = 2;
   _triaVertexID = -1;
+  _quadType = QUAD_STANDARD;
 }
 
 //=============================================================================
 /*!
- *  
+ *
  */
 //=============================================================================
-
 StdMeshers_QuadrangleParams::~StdMeshers_QuadrangleParams()
 {
 }
 
 //=============================================================================
 /*!
- *  
+ *
  */
 //=============================================================================
-
-void StdMeshers_QuadrangleParams::SetTriaVertex(int id)
+void StdMeshers_QuadrangleParams::SetTriaVertex (int id)
 {
-  if ( id != _triaVertexID ) {
+  if (id != _triaVertexID) {
     _triaVertexID = id;
     NotifySubMeshesHypothesisModification();
   }
@@ -80,22 +77,36 @@ void StdMeshers_QuadrangleParams::SetTriaVertex(int id)
 
 //=============================================================================
 /*!
- *  
+ *
  */
 //=============================================================================
+void StdMeshers_QuadrangleParams::SetQuadType (StdMeshers_QuadType type)
+{
+  if (type != _quadType) {
+    _quadType = type;
+    NotifySubMeshesHypothesisModification();
+  }
+}
 
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
 ostream & StdMeshers_QuadrangleParams::SaveTo(ostream & save)
 {
-  save << _triaVertexID << " " << _objEntry;
+  if (_objEntry.size() == 0)
+    save << _triaVertexID << " UNDEFINED " << int(_quadType);
+  else
+    save << _triaVertexID << " " << _objEntry << " " << int(_quadType);
   return save;
 }
 
 //=============================================================================
 /*!
- *  
+ *
  */
 //=============================================================================
-
 istream & StdMeshers_QuadrangleParams::LoadFrom(istream & load)
 {
   bool isOK = true;
@@ -104,16 +115,22 @@ istream & StdMeshers_QuadrangleParams::LoadFrom(istream & load)
     load.clear(ios::badbit | load.rdstate());
 
   isOK = (load >> _objEntry);
+  if (!isOK)
+    load.clear(ios::badbit | load.rdstate());
+
+  int type;
+  isOK = (load >> type);
+  if (isOK)
+    _quadType = StdMeshers_QuadType(type);
 
   return load;
 }
 
 //=============================================================================
 /*!
- *  
+ *
  */
 //=============================================================================
-
 ostream & operator <<(ostream & save, StdMeshers_QuadrangleParams & hyp)
 {
   return hyp.SaveTo( save );
@@ -121,10 +138,9 @@ ostream & operator <<(ostream & save, StdMeshers_QuadrangleParams & hyp)
 
 //=============================================================================
 /*!
- *  
+ *
  */
 //=============================================================================
-
 istream & operator >>(istream & load, StdMeshers_QuadrangleParams & hyp)
 {
   return hyp.LoadFrom( load );
@@ -138,7 +154,6 @@ istream & operator >>(istream & load, StdMeshers_QuadrangleParams & hyp)
  * \retval bool - true if parameter values have been successfully defined
  */
 //================================================================================
-
 bool StdMeshers_QuadrangleParams::SetParametersByMesh(const SMESH_Mesh* theMesh,
                                                       const TopoDS_Shape& theShape)
 {
@@ -154,10 +169,8 @@ bool StdMeshers_QuadrangleParams::SetParametersByMesh(const SMESH_Mesh* theMesh,
  *  \retval bool - true if parameter values have been successfully defined
  */
 //================================================================================
-
 bool StdMeshers_QuadrangleParams::SetParametersByDefaults(const TDefaults&  dflts,
                                                           const SMESH_Mesh* /*mesh*/)
 {
   return true;
 }
-
index da37f075558f96e9b9112996f9fcf0f4d6c63e06..d880c50081c5f9a7dcd368deb0c72873e837da46 100644 (file)
 //
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-
 //  SMESH SMESH : implementaion of SMESH idl descriptions
 //  File   : StdMeshers_QuadrangleParams.hxx
 //  Author : Sergey KUUL, OCC
 //  Module : SMESH
-//
+
 #ifndef _SMESH_QUADRANGLEPARAMS_HXX_
 #define _SMESH_QUADRANGLEPARAMS_HXX_
 
-
-
 #include "SMESH_StdMeshers.hxx"
 
 #include "SMESH_Hypothesis.hxx"
 #include "Utils_SALOME_Exception.hxx"
 
+enum StdMeshers_QuadType
+  {
+    QUAD_STANDARD,
+    QUAD_TRIANGLE_PREF,
+    QUAD_QUADRANGLE_PREF,
+    QUAD_QUADRANGLE_PREF_REVERSED,
+    QUAD_REDUCED,
+    QUAD_NB_TYPES
+  };
+
 class STDMESHERS_EXPORT StdMeshers_QuadrangleParams:
   public SMESH_Hypothesis
 {
@@ -39,13 +46,14 @@ public:
   StdMeshers_QuadrangleParams(int hypId, int studyId, SMESH_Gen* gen);
   virtual ~StdMeshers_QuadrangleParams();
 
-  void SetTriaVertex(int id);
-
-  void SetObjectEntry( const char* entry ) { _objEntry = entry; }
+  void SetTriaVertex (int id);
+  int GetTriaVertex() const { return _triaVertexID; }
 
+  void SetObjectEntry (const char* entry) { _objEntry = entry; }
   const char* GetObjectEntry() { return _objEntry.c_str(); }
 
-  int GetTriaVertex() const { return _triaVertexID; }
+  void SetQuadType (StdMeshers_QuadType type);
+  StdMeshers_QuadType GetQuadType() const { return _quadType; }
 
   virtual std::ostream & SaveTo(std::ostream & save);
   virtual std::istream & LoadFrom(std::istream & load);
@@ -71,8 +79,9 @@ public:
                                        const SMESH_Mesh* theMesh=0);
 
 protected:
-  int         _triaVertexID;
-  std::string _objEntry;
+  int                 _triaVertexID;
+  std::string         _objEntry;
+  StdMeshers_QuadType _quadType;
 };
 
 #endif
index c78c755d9f4cdfc738e69b55436e426fbebbce6b..1075db412219861a94ee8a70f3dce65c82c8814a 100644 (file)
 //  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_Quadrangle_2D.cxx
-//           Moved here from SMESH_Quadrangle_2D.cxx
 //  Author : Paul RASCLE, EDF
 //  Module : SMESH
-//
+
 #include "StdMeshers_Quadrangle_2D.hxx"
 
 #include "StdMeshers_FaceSide.hxx"
@@ -49,6 +46,7 @@
 #include <NCollection_DefineArray2.hxx>
 #include <Precision.hxx>
 #include <TColStd_SequenceOfReal.hxx>
+#include <TColStd_SequenceOfInteger.hxx>
 #include <TColgp_SequenceOfXY.hxx>
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
@@ -116,69 +114,75 @@ bool StdMeshers_Quadrangle_2D::CheckHypothesis
   bool isOk = true;
   aStatus = SMESH_Hypothesis::HYP_OK;
 
-  const list <const SMESHDS_Hypothesis * >&hyps =
+  const list <const SMESHDS_Hypothesis * >& hyps =
     GetUsedHypothesis(aMesh, aShape, false);
-  const SMESHDS_Hypothesis *theHyp = 0;
-  
-  if( hyps.size() == 1 ) {
-    myTriaVertexID = -1;
-    theHyp = hyps.front();
-    if(strcmp("QuadrangleParams", theHyp->GetName()) == 0) {
-      const StdMeshers_QuadrangleParams* theHyp1 = 
-        (const StdMeshers_QuadrangleParams*)theHyp;
-      myTriaVertexID = theHyp1->GetTriaVertex();
-      myQuadranglePreference= false;
-      myTrianglePreference= false; 
-    }
-    if(strcmp("QuadranglePreference", theHyp->GetName()) == 0) {
-      myQuadranglePreference= true;
-      myTrianglePreference= false; 
-      myTriaVertexID = -1;
-    }
-    else if(strcmp("TrianglePreference", theHyp->GetName()) == 0){
-      myQuadranglePreference= false;
-      myTrianglePreference= true; 
-      myTriaVertexID = -1;
+  const SMESHDS_Hypothesis * aHyp = 0;
+
+  myTriaVertexID = -1;
+  myQuadType = QUAD_STANDARD;
+  myQuadranglePreference = false;
+  myTrianglePreference = false;
+
+  bool isFirstParams = true;
+
+  // 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 (myQuadType == QUAD_QUADRANGLE_PREF ||
+          myQuadType == QUAD_QUADRANGLE_PREF_REVERSED)
+        myQuadranglePreference = true;
+      else if (myQuadType == QUAD_TRIANGLE_PREF)
+        myTrianglePreference = true;
+    }
+    else if (strcmp("QuadranglePreference", aHyp->GetName()) == 0) {
+      isFirstParams = false;
+      myQuadranglePreference = true;
+    }
+    else if (strcmp("TrianglePreference", aHyp->GetName()) == 0){
+      isFirstParams = false;
+      myTrianglePreference = true; 
+    }
+    else {
+      isFirstParams = false;
     }
   }
 
-  else if( hyps.size() > 1 ) {
-    theHyp = hyps.front();
-    if(strcmp("QuadrangleParams", theHyp->GetName()) == 0) {
-      const StdMeshers_QuadrangleParams* theHyp1 = 
-        (const StdMeshers_QuadrangleParams*)theHyp;
-      myTriaVertexID = theHyp1->GetTriaVertex();
-      theHyp = hyps.back();
-      if(strcmp("QuadranglePreference", theHyp->GetName()) == 0) {
-        myQuadranglePreference= true;
-        myTrianglePreference= false; 
+  // Second(last) assigned hypothesis (if any) is processed now
+  if (hyps.size() > 1) {
+    aHyp = hyps.back();
+    if (isFirstParams) {
+      if (strcmp("QuadranglePreference", aHyp->GetName()) == 0) {
+        myQuadranglePreference = true;
+        myTrianglePreference = false; 
+        myQuadType = QUAD_STANDARD;
       }
-      else if(strcmp("TrianglePreference", theHyp->GetName()) == 0){
-        myQuadranglePreference= false;
-        myTrianglePreference= true; 
+      else if (strcmp("TrianglePreference", aHyp->GetName()) == 0){
+        myQuadranglePreference = false;
+        myTrianglePreference = true; 
+        myQuadType = QUAD_STANDARD;
       }
     }
     else {
-      if(strcmp("QuadranglePreference", theHyp->GetName()) == 0) {
-        myQuadranglePreference= true;
-        myTrianglePreference= false; 
+      const StdMeshers_QuadrangleParams* aHyp2 = 
+        (const StdMeshers_QuadrangleParams*)aHyp;
+      myTriaVertexID = aHyp2->GetTriaVertex();
+
+      if (!myQuadranglePreference && !myTrianglePreference) { // priority of hypos
+        myQuadType = aHyp2->GetQuadType();
+        if (myQuadType == QUAD_QUADRANGLE_PREF ||
+            myQuadType == QUAD_QUADRANGLE_PREF_REVERSED)
+          myQuadranglePreference = true;
+        else if (myQuadType == QUAD_TRIANGLE_PREF)
+          myTrianglePreference = true;
       }
-      else if(strcmp("TrianglePreference", theHyp->GetName()) == 0){
-        myQuadranglePreference= false;
-        myTrianglePreference= true; 
-      }
-      const StdMeshers_QuadrangleParams* theHyp2 = 
-        (const StdMeshers_QuadrangleParams*)hyps.back();
-      myTriaVertexID = theHyp2->GetTriaVertex();
     }
   }
 
-  else {
-    myQuadranglePreference = false;
-    myTrianglePreference = false;
-    myTriaVertexID = -1;
-  }
-
   return isOk;
 }
 
@@ -197,17 +201,17 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
   SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
   aMesh.GetSubMesh(aShape);
 
-  SMESH_MesherHelper helper(aMesh);
+  SMESH_MesherHelper helper (aMesh);
   myTool = &helper;
 
   _quadraticMesh = myTool->IsQuadraticSubMesh(aShape);
 
-  FaceQuadStruct *quad = CheckNbEdges( aMesh, aShape );
-  std::auto_ptr<FaceQuadStruct> quadDeleter( quad ); // to delete quad at exit from Compute()
+  FaceQuadStruct *quad = CheckNbEdges(aMesh, aShape);
+  std::auto_ptr<FaceQuadStruct> quadDeleter (quad); // to delete quad at exit from Compute()
   if (!quad)
     return false;
 
-  if(myQuadranglePreference) {
+  if (myQuadranglePreference) {
     int n1 = quad->side[0]->NbPoints();
     int n2 = quad->side[1]->NbPoints();
     int n3 = quad->side[2]->NbPoints();
@@ -215,12 +219,27 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
     int nfull = n1+n2+n3+n4;
     int ntmp = nfull/2;
     ntmp = ntmp*2;
-    if( nfull==ntmp && ( (n1!=n3) || (n2!=n4) ) ) {
+    if (nfull == ntmp && ((n1 != n3) || (n2 != n4))) {
       // special path for using only quandrangle faces
       bool ok = ComputeQuadPref(aMesh, aShape, quad);
       return ok;
     }
   }
+  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;
+    int n24tmp = n24/2; n24tmp = n24tmp*2;
+    if ((n1 == n3 && n2 != n4 && n24tmp == n24) ||
+        (n2 == n4 && n1 != n3 && n13tmp == n13)) {
+      bool ok = ComputeReduced(aMesh, aShape, quad);
+      return ok;
+    }
+  }
 
   // set normalized grid on unit square in parametric domain
   
@@ -242,7 +261,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
   Handle(Geom_Surface) S = BRep_Tool::Surface(F);
 
   // internal mesh nodes
-  int i, j, geomFaceID = meshDS->ShapeToIndex( F );
+  int i, j, geomFaceID = meshDS->ShapeToIndex(F);
   for (i = 1; i < nbhoriz - 1; i++) {
     for (j = 1; j < nbvertic - 1; j++) {
       int ij = j * nbhoriz + i;
@@ -287,19 +306,19 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
       c = quad->uv_grid[(j + 1) * nbhoriz + i + 1].node;
       d = quad->uv_grid[(j + 1) * nbhoriz + i].node;
       SMDS_MeshFace* face = myTool->AddFace(a, b, c, d);
-      if(face) {
+      if (face) {
         meshDS->SetMeshElementOnShape(face, geomFaceID);
       }
     }
   }
 
-  const vector<UVPtStruct>& uv_e0 = quad->side[0]->GetUVPtStruct(true,0 );
+  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_e2 = quad->side[2]->GetUVPtStruct(true,1);
   const vector<UVPtStruct>& uv_e3 = quad->side[3]->GetUVPtStruct(false,0);
 
-  if ( uv_e0.empty() || uv_e1.empty() || uv_e2.empty() || uv_e3.empty() )
-    return error( COMPERR_BAD_INPUT_MESH );
+  if (uv_e0.empty() || uv_e1.empty() || uv_e2.empty() || uv_e3.empty())
+    return error(COMPERR_BAD_INPUT_MESH);
 
   double eps = Precision::Confusion();
 
@@ -364,7 +383,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
 
       if (near == g) { // make triangle
         SMDS_MeshFace* face = myTool->AddFace(a, b, c);
-        if(face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+        if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
       }
       else { // make quadrangle
         if (near - 1 < ilow)
@@ -373,9 +392,9 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
           d = quad->uv_grid[nbhoriz + near - 1].node;
         //SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
         
-        if(!myTrianglePreference){
+        if (!myTrianglePreference){
           SMDS_MeshFace* face = myTool->AddFace(a, b, c, d);
-          if(face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+          if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
         }
         else {
           SplitQuad(meshDS, geomFaceID, a, b, c, d);
@@ -390,7 +409,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
             else
               d = quad->uv_grid[nbhoriz + k - 1].node;
             SMDS_MeshFace* face = myTool->AddFace(a, c, d);
-            if(face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+            if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
           }
         }
         g = near;
@@ -452,7 +471,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
 
         if (near == g) { // make triangle
           SMDS_MeshFace* face = myTool->AddFace(a, b, c);
-          if(face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+          if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
         }
         else { // make quadrangle
           if (near + 1 > iup)
@@ -460,9 +479,9 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
           else
             d = quad->uv_grid[nbhoriz*(nbvertic - 2) + near + 1].node;
           //SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
-          if(!myTrianglePreference){
+          if (!myTrianglePreference){
             SMDS_MeshFace* face = myTool->AddFace(a, b, c, d);
-            if(face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+            if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
           }
           else {
             SplitQuad(meshDS, geomFaceID, a, b, c, d);
@@ -476,7 +495,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
               else
                 d = quad->uv_grid[nbhoriz*(nbvertic - 2) + k + 1].node;
               SMDS_MeshFace* face = myTool->AddFace(a, c, d);
-              if(face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+              if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
             }
           }
           g = near;
@@ -524,7 +543,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
 
       if (near == g) { // make triangle
         SMDS_MeshFace* face = myTool->AddFace(a, b, c);
-        if(face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+        if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
       }
       else { // make quadrangle
         if (near - 1 < jlow)
@@ -533,9 +552,9 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
           d = quad->uv_grid[nbhoriz*near - 2].node;
         //SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
 
-        if(!myTrianglePreference){
+        if (!myTrianglePreference){
           SMDS_MeshFace* face = myTool->AddFace(a, b, c, d);
-          if(face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+          if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
         }
         else {
           SplitQuad(meshDS, geomFaceID, a, b, c, d);
@@ -549,7 +568,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
             else
               d = quad->uv_grid[nbhoriz*k - 2].node;
             SMDS_MeshFace* face = myTool->AddFace(a, c, d);
-            if(face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+            if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
           }
         }
         g = near;
@@ -594,7 +613,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
 
         if (near == g) { // make triangle
           SMDS_MeshFace* face = myTool->AddFace(a, b, c);
-          if(face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+          if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
         }
         else { // make quadrangle
           if (near + 1 > jup)
@@ -602,9 +621,9 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
           else
             d = quad->uv_grid[nbhoriz*(near + 1) + 1].node;
           //SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
-          if(!myTrianglePreference){
+          if (!myTrianglePreference){
             SMDS_MeshFace* face = myTool->AddFace(a, b, c, d);
-            if(face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+            if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
           }
           else {
             SplitQuad(meshDS, geomFaceID, a, b, c, d);
@@ -618,7 +637,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
               else
                 d = quad->uv_grid[nbhoriz*(k + 1) + 1].node;
               SMDS_MeshFace* face = myTool->AddFace(a, c, d);
-              if(face) meshDS->SetMeshElementOnShape(face, geomFaceID);
+              if (face) meshDS->SetMeshElementOnShape(face, geomFaceID);
             }
           }
           g = near;
@@ -647,17 +666,17 @@ bool StdMeshers_Quadrangle_2D::Evaluate(SMESH_Mesh& aMesh,
 
   std::vector<int> aNbNodes(4);
   bool IsQuadratic = false;
-  if( !CheckNbEdgesForEvaluate( aMesh, aShape, aResMap, aNbNodes, IsQuadratic ) ) {
+  if (!CheckNbEdgesForEvaluate(aMesh, aShape, aResMap, aNbNodes, IsQuadratic)) {
     std::vector<int> aResVec(SMDSEntity_Last);
-    for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
+    for (int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
     SMESH_subMesh * sm = aMesh.GetSubMesh(aShape);
     aResMap.insert(std::make_pair(sm,aResVec));
     SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
-    smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this));
+    smError.reset(new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this));
     return false;
   }
 
-  if(myQuadranglePreference) {
+  if (myQuadranglePreference) {
     int n1 = aNbNodes[0];
     int n2 = aNbNodes[1];
     int n3 = aNbNodes[2];
@@ -665,7 +684,7 @@ bool StdMeshers_Quadrangle_2D::Evaluate(SMESH_Mesh& aMesh,
     int nfull = n1+n2+n3+n4;
     int ntmp = nfull/2;
     ntmp = ntmp*2;
-    if( nfull==ntmp && ( (n1!=n3) || (n2!=n4) ) ) {
+    if (nfull==ntmp && ((n1!=n3) || (n2!=n4))) {
       // special path for using only quandrangle faces
       return EvaluateQuadPref(aMesh, aShape, aNbNodes, aResMap, IsQuadratic);
       //return true;
@@ -685,27 +704,27 @@ bool StdMeshers_Quadrangle_2D::Evaluate(SMESH_Mesh& aMesh,
   int dv = Max(nbright, nbleft) - nbvertic;
 
   //int kdh = 0;
-  //if(dh>0) kdh = 1;
+  //if (dh>0) kdh = 1;
   //int kdv = 0;
-  //if(dv>0) kdv = 1;
+  //if (dv>0) kdv = 1;
 
   int nbNodes = (nbhoriz-2)*(nbvertic-2);
   //int nbFaces3 = dh + dv + kdh*(nbvertic-1)*2 + kdv*(nbhoriz-1)*2;
   int nbFaces3 = dh + dv;
-  //if( kdh==1 && kdv==1 ) nbFaces3 -= 2;
-  //if( dh>0 && dv>0 ) nbFaces3 -= 2;
+  //if (kdh==1 && kdv==1) nbFaces3 -= 2;
+  //if (dh>0 && dv>0) nbFaces3 -= 2;
   //int nbFaces4 = (nbhoriz-1-kdh)*(nbvertic-1-kdv);
   int nbFaces4 = (nbhoriz-1)*(nbvertic-1);
 
   std::vector<int> aVec(SMDSEntity_Last);
-  for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i] = 0;
-  if(IsQuadratic) {
+  for (int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i] = 0;
+  if (IsQuadratic) {
     aVec[SMDSEntity_Quad_Triangle] = nbFaces3;
     aVec[SMDSEntity_Quad_Quadrangle] = nbFaces4;
     int nbbndedges = nbdown + nbup + nbright + nbleft -4;
-    int nbintedges = ( nbFaces4*4 + nbFaces3*3 - nbbndedges ) / 2;
+    int nbintedges = (nbFaces4*4 + nbFaces3*3 - nbbndedges) / 2;
     aVec[SMDSEntity_Node] = nbNodes + nbintedges;
-    if( aNbNodes.size()==5 ) {
+    if (aNbNodes.size()==5) {
       aVec[SMDSEntity_Quad_Triangle] = nbFaces3 + aNbNodes[3] -1;
       aVec[SMDSEntity_Quad_Quadrangle] = nbFaces4 - aNbNodes[3] +1;
     }
@@ -714,7 +733,7 @@ bool StdMeshers_Quadrangle_2D::Evaluate(SMESH_Mesh& aMesh,
     aVec[SMDSEntity_Node] = nbNodes;
     aVec[SMDSEntity_Triangle] = nbFaces3;
     aVec[SMDSEntity_Quadrangle] = nbFaces4;
-    if( aNbNodes.size()==5 ) {
+    if (aNbNodes.size()==5) {
       aVec[SMDSEntity_Triangle] = nbFaces3 + aNbNodes[3] - 1;
       aVec[SMDSEntity_Quadrangle] = nbFaces4 - aNbNodes[3] + 1;
     }
@@ -737,12 +756,12 @@ static bool twoEdgesMeatAtVertex(const TopoDS_Edge& e1,
                                  SMESH_Mesh &       mesh)
 {
   TopoDS_Vertex v;
-  if ( !TopExp::CommonVertex( e1, e2, v ))
+  if (!TopExp::CommonVertex(e1, e2, v))
     return false;
-  TopTools_ListIteratorOfListOfShape ancestIt( mesh.GetAncestors( v ));
-  for ( ; ancestIt.More() ; ancestIt.Next() )
-    if ( ancestIt.Value().ShapeType() == TopAbs_EDGE )
-      if ( !e1.IsSame( ancestIt.Value() ) && !e2.IsSame( ancestIt.Value() ))
+  TopTools_ListIteratorOfListOfShape ancestIt(mesh.GetAncestors(v));
+  for (; ancestIt.More() ; ancestIt.Next())
+    if (ancestIt.Value().ShapeType() == TopAbs_EDGE)
+      if (!e1.IsSame(ancestIt.Value()) && !e2.IsSame(ancestIt.Value()))
         return false;
   return true;
 }
@@ -776,113 +795,113 @@ FaceQuadStruct* StdMeshers_Quadrangle_2D::CheckNbEdges(SMESH_Mesh &         aMes
 
   int nbSides = 0;
   list< TopoDS_Edge >::iterator edgeIt = edges.begin();
-  if ( nbEdgesInWire.front() == 3 ) // exactly 3 edges
+  if (nbEdgesInWire.front() == 3) // exactly 3 edges
   {
     SMESH_Comment comment;
     SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
-    if ( myTriaVertexID == -1)
+    if (myTriaVertexID == -1)
     {
       comment << "No Base vertex parameter provided for a trilateral geometrical face";
     }
     else
     {
       TopoDS_Vertex V = TopoDS::Vertex(meshDS->IndexToShape(myTriaVertexID));
-      if ( !V.IsNull() ) {
+      if (!V.IsNull()) {
         TopoDS_Edge E1,E2,E3;
-        for(; edgeIt != edges.end(); ++edgeIt) {
+        for (; edgeIt != edges.end(); ++edgeIt) {
           TopoDS_Edge E =  *edgeIt;
           TopoDS_Vertex VF, VL;
           TopExp::Vertices(E, VF, VL, true);
-          if( VF.IsSame(V) )
+          if (VF.IsSame(V))
             E1 = E;
-          else if( VL.IsSame(V) )
+          else if (VL.IsSame(V))
             E3 = E;
           else
             E2 = E;
         }
-        if ( !E1.IsNull() && !E2.IsNull() && !E3.IsNull() )
+        if (!E1.IsNull() && !E2.IsNull() && !E3.IsNull())
         {
-          quad->side.push_back( new StdMeshers_FaceSide(F, E1, &aMesh, true, ignoreMediumNodes));
-          quad->side.push_back( new StdMeshers_FaceSide(F, E2, &aMesh, true, ignoreMediumNodes));
-          quad->side.push_back( new StdMeshers_FaceSide(F, E3, &aMesh, false,ignoreMediumNodes));
+          quad->side.push_back(new StdMeshers_FaceSide(F, E1, &aMesh, true, ignoreMediumNodes));
+          quad->side.push_back(new StdMeshers_FaceSide(F, E2, &aMesh, true, ignoreMediumNodes));
+          quad->side.push_back(new StdMeshers_FaceSide(F, E3, &aMesh, false,ignoreMediumNodes));
           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(aNode, aPnt2d, quad->side[1]));
+          gp_Pnt2d aPnt2d(UVPSleft[0].u, UVPSleft[0].v);
+          quad->side.push_back(new StdMeshers_FaceSide(aNode, aPnt2d, quad->side[1]));
           return quad;
         }
       }
       comment << "Invalid Base vertex parameter: " << myTriaVertexID << " is not among [";
       TopTools_MapOfShape vMap;
-      for ( TopExp_Explorer v( aShape, TopAbs_VERTEX ); v.More(); v.Next())
-        if ( vMap.Add( v.Current() ))
-          comment << meshDS->ShapeToIndex( v.Current() ) << ( vMap.Extent()==3 ? "]" : ", ");
+      for (TopExp_Explorer v(aShape, TopAbs_VERTEX); v.More(); v.Next())
+        if (vMap.Add(v.Current()))
+          comment << meshDS->ShapeToIndex(v.Current()) << (vMap.Extent()==3 ? "]" : ", ");
     }
-    error( comment );
+    error(comment);
     delete quad;
     return quad = 0;
   }
-  else if ( nbEdgesInWire.front() == 4 ) { // exactly 4 edges
-    for ( ; edgeIt != edges.end(); ++edgeIt, nbSides++ )
-      quad->side.push_back( new StdMeshers_FaceSide(F, *edgeIt, &aMesh,
+  else if (nbEdgesInWire.front() == 4) { // exactly 4 edges
+    for (; edgeIt != edges.end(); ++edgeIt, nbSides++)
+      quad->side.push_back(new StdMeshers_FaceSide(F, *edgeIt, &aMesh,
                                                     nbSides<TOP_SIDE, ignoreMediumNodes));
   }
-  else if ( nbEdgesInWire.front() > 4 ) { // more than 4 edges - try to unite some
+  else if (nbEdgesInWire.front() > 4) { // more than 4 edges - try to unite some
     list< TopoDS_Edge > sideEdges;
-    while ( !edges.empty()) {
+    while (!edges.empty()) {
       sideEdges.clear();
-      sideEdges.splice( sideEdges.end(), edges, edges.begin()); // edges.front() -> sideEdges.end()
+      sideEdges.splice(sideEdges.end(), edges, edges.begin()); // edges.front() -> sideEdges.end()
       bool sameSide = true;
-      while ( !edges.empty() && sameSide ) {
-        sameSide = SMESH_Algo::IsContinuous( sideEdges.back(), edges.front() );
-        if ( sameSide )
-          sideEdges.splice( sideEdges.end(), edges, edges.begin());
+      while (!edges.empty() && sameSide) {
+        sameSide = SMESH_Algo::IsContinuous(sideEdges.back(), edges.front());
+        if (sameSide)
+          sideEdges.splice(sideEdges.end(), edges, edges.begin());
       }
-      if ( nbSides == 0 ) { // go backward from the first edge
+      if (nbSides == 0) { // go backward from the first edge
         sameSide = true;
-        while ( !edges.empty() && sameSide ) {
-          sameSide = SMESH_Algo::IsContinuous( sideEdges.front(), edges.back() );
-          if ( sameSide )
-            sideEdges.splice( sideEdges.begin(), edges, --edges.end());
+        while (!edges.empty() && sameSide) {
+          sameSide = SMESH_Algo::IsContinuous(sideEdges.front(), edges.back());
+          if (sameSide)
+            sideEdges.splice(sideEdges.begin(), edges, --edges.end());
         }
       }
-      quad->side.push_back( new StdMeshers_FaceSide(F, sideEdges, &aMesh,
+      quad->side.push_back(new StdMeshers_FaceSide(F, sideEdges, &aMesh,
                                                     nbSides<TOP_SIDE, ignoreMediumNodes));
       ++nbSides;
     }
     // issue 20222. Try to unite only edges shared by two same faces
     if (nbSides < 4) {
       // delete found sides
-      { FaceQuadStruct cleaner( *quad ); }
+      { FaceQuadStruct cleaner(*quad); }
       quad->side.clear();
       quad->side.reserve(nbEdgesInWire.front());
       nbSides = 0;
 
       SMESH_Block::GetOrderedEdges (F, V, edges, nbEdgesInWire);
-      while ( !edges.empty()) {
+      while (!edges.empty()) {
         sideEdges.clear();
-        sideEdges.splice( sideEdges.end(), edges, edges.begin());
+        sideEdges.splice(sideEdges.end(), edges, edges.begin());
         bool sameSide = true;
-        while ( !edges.empty() && sameSide ) {
+        while (!edges.empty() && sameSide) {
           sameSide =
-            SMESH_Algo::IsContinuous( sideEdges.back(), edges.front() ) &&
-            twoEdgesMeatAtVertex( sideEdges.back(), edges.front(), aMesh );
-          if ( sameSide )
-            sideEdges.splice( sideEdges.end(), edges, edges.begin());
+            SMESH_Algo::IsContinuous(sideEdges.back(), edges.front()) &&
+            twoEdgesMeatAtVertex(sideEdges.back(), edges.front(), aMesh);
+          if (sameSide)
+            sideEdges.splice(sideEdges.end(), edges, edges.begin());
         }
-        if ( nbSides == 0 ) { // go backward from the first edge
+        if (nbSides == 0) { // go backward from the first edge
           sameSide = true;
-          while ( !edges.empty() && sameSide ) {
+          while (!edges.empty() && sameSide) {
             sameSide =
-              SMESH_Algo::IsContinuous( sideEdges.front(), edges.back() ) &&
-              twoEdgesMeatAtVertex( sideEdges.front(), edges.back(), aMesh );
-            if ( sameSide )
-              sideEdges.splice( sideEdges.begin(), edges, --edges.end());
+              SMESH_Algo::IsContinuous(sideEdges.front(), edges.back()) &&
+              twoEdgesMeatAtVertex(sideEdges.front(), edges.back(), aMesh);
+            if (sameSide)
+              sideEdges.splice(sideEdges.begin(), edges, --edges.end());
           }
         }
-        quad->side.push_back( new StdMeshers_FaceSide(F, sideEdges, &aMesh,
+        quad->side.push_back(new StdMeshers_FaceSide(F, sideEdges, &aMesh,
                                                       nbSides<TOP_SIDE, ignoreMediumNodes));
         ++nbSides;
       }
@@ -890,16 +909,16 @@ FaceQuadStruct* StdMeshers_Quadrangle_2D::CheckNbEdges(SMESH_Mesh &         aMes
   }
   if (nbSides != 4) {
 #ifdef _DEBUG_
-    MESSAGE ( "StdMeshers_Quadrangle_2D. Edge IDs of " << nbSides << " sides:\n" );
-    for ( int i = 0; i < nbSides; ++i ) {
-      MESSAGE ( " ( " );
-      for ( int e = 0; e < quad->side[i]->NbEdges(); ++e )
-        MESSAGE ( myTool->GetMeshDS()->ShapeToIndex( quad->side[i]->Edge( e )) << " " );
-      MESSAGE ( ")\n" );
+    MESSAGE ("StdMeshers_Quadrangle_2D. Edge IDs of " << nbSides << " sides:\n");
+    for (int i = 0; i < nbSides; ++i) {
+      MESSAGE (" (");
+      for (int e = 0; e < quad->side[i]->NbEdges(); ++e)
+        MESSAGE (myTool->GetMeshDS()->ShapeToIndex(quad->side[i]->Edge(e)) << " ");
+      MESSAGE (")\n");
     }
     //cout << endl;
 #endif
-    if ( !nbSides )
+    if (!nbSides)
       nbSides = nbEdgesInWire.front();
     error(COMPERR_BAD_SHAPE, TComm("Face must have 4 sides but not ") << nbSides);
     delete quad;
@@ -938,51 +957,51 @@ bool StdMeshers_Quadrangle_2D::CheckNbEdgesForEvaluate(SMESH_Mesh& aMesh,
 
   int nbSides = 0;
   list< TopoDS_Edge >::iterator edgeIt = edges.begin();
-  SMESH_subMesh * sm = aMesh.GetSubMesh( *edgeIt );
+  SMESH_subMesh * sm = aMesh.GetSubMesh(*edgeIt);
   MapShapeNbElemsItr anIt = aResMap.find(sm);
-  if(anIt==aResMap.end()) {
+  if (anIt==aResMap.end()) {
     return false;
   }
   std::vector<int> aVec = (*anIt).second;
   IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]);
-  if ( nbEdgesInWire.front() == 3 ) { // exactly 3 edges
-    if(myTriaVertexID>0) {
+  if (nbEdgesInWire.front() == 3) { // exactly 3 edges
+    if (myTriaVertexID>0) {
       SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
       TopoDS_Vertex V = TopoDS::Vertex(meshDS->IndexToShape(myTriaVertexID));
-      if(!V.IsNull()) {
+      if (!V.IsNull()) {
         TopoDS_Edge E1,E2,E3;
-        for(; edgeIt != edges.end(); ++edgeIt) {
+        for (; edgeIt != edges.end(); ++edgeIt) {
           TopoDS_Edge E =  TopoDS::Edge(*edgeIt);
           TopoDS_Vertex VF, VL;
           TopExp::Vertices(E, VF, VL, true);
-          if( VF.IsSame(V) )
+          if (VF.IsSame(V))
             E1 = E;
-          else if( VL.IsSame(V) )
+          else if (VL.IsSame(V))
             E3 = E;
           else
             E2 = E;
         }
         SMESH_subMesh * sm = aMesh.GetSubMesh(E1);
         MapShapeNbElemsItr anIt = aResMap.find(sm);
-        if(anIt==aResMap.end()) return false;
+        if (anIt==aResMap.end()) return false;
         std::vector<int> aVec = (*anIt).second;
-        if(IsQuadratic)
+        if (IsQuadratic)
           aNbNodes[0] = (aVec[SMDSEntity_Node]-1)/2 + 2;
         else
           aNbNodes[0] = aVec[SMDSEntity_Node] + 2;
         sm = aMesh.GetSubMesh(E2);
         anIt = aResMap.find(sm);
-        if(anIt==aResMap.end()) return false;
+        if (anIt==aResMap.end()) return false;
         aVec = (*anIt).second;
-        if(IsQuadratic)
+        if (IsQuadratic)
           aNbNodes[1] = (aVec[SMDSEntity_Node]-1)/2 + 2;
         else
           aNbNodes[1] = aVec[SMDSEntity_Node] + 2;
         sm = aMesh.GetSubMesh(E3);
         anIt = aResMap.find(sm);
-        if(anIt==aResMap.end()) return false;
+        if (anIt==aResMap.end()) return false;
         aVec = (*anIt).second;
-        if(IsQuadratic)
+        if (IsQuadratic)
           aNbNodes[2] = (aVec[SMDSEntity_Node]-1)/2 + 2;
         else
           aNbNodes[2] = aVec[SMDSEntity_Node] + 2;
@@ -992,50 +1011,50 @@ bool StdMeshers_Quadrangle_2D::CheckNbEdgesForEvaluate(SMESH_Mesh& aMesh,
       }
     }
   }
-  if ( nbEdgesInWire.front() == 4 ) { // exactly 4 edges
-    for(; edgeIt != edges.end(); edgeIt++) {
-      SMESH_subMesh * sm = aMesh.GetSubMesh( *edgeIt );
+  if (nbEdgesInWire.front() == 4) { // exactly 4 edges
+    for (; edgeIt != edges.end(); edgeIt++) {
+      SMESH_subMesh * sm = aMesh.GetSubMesh(*edgeIt);
       MapShapeNbElemsItr anIt = aResMap.find(sm);
-      if(anIt==aResMap.end()) {
+      if (anIt==aResMap.end()) {
         return false;
       }
       std::vector<int> aVec = (*anIt).second;
-      if(IsQuadratic)
+      if (IsQuadratic)
         aNbNodes[nbSides] = (aVec[SMDSEntity_Node]-1)/2 + 2;
       else
         aNbNodes[nbSides] = aVec[SMDSEntity_Node] + 2;
       nbSides++;
     }
   }
-  else if ( nbEdgesInWire.front() > 4 ) { // more than 4 edges - try to unite some
+  else if (nbEdgesInWire.front() > 4) { // more than 4 edges - try to unite some
     list< TopoDS_Edge > sideEdges;
-    while ( !edges.empty()) {
+    while (!edges.empty()) {
       sideEdges.clear();
-      sideEdges.splice( sideEdges.end(), edges, edges.begin()); // edges.front() -> sideEdges.end()
+      sideEdges.splice(sideEdges.end(), edges, edges.begin()); // edges.front() -> sideEdges.end()
       bool sameSide = true;
-      while ( !edges.empty() && sameSide ) {
-        sameSide = SMESH_Algo::IsContinuous( sideEdges.back(), edges.front() );
-        if ( sameSide )
-          sideEdges.splice( sideEdges.end(), edges, edges.begin());
+      while (!edges.empty() && sameSide) {
+        sameSide = SMESH_Algo::IsContinuous(sideEdges.back(), edges.front());
+        if (sameSide)
+          sideEdges.splice(sideEdges.end(), edges, edges.begin());
       }
-      if ( nbSides == 0 ) { // go backward from the first edge
+      if (nbSides == 0) { // go backward from the first edge
         sameSide = true;
-        while ( !edges.empty() && sameSide ) {
-          sameSide = SMESH_Algo::IsContinuous( sideEdges.front(), edges.back() );
-          if ( sameSide )
-            sideEdges.splice( sideEdges.begin(), edges, --edges.end());
+        while (!edges.empty() && sameSide) {
+          sameSide = SMESH_Algo::IsContinuous(sideEdges.front(), edges.back());
+          if (sameSide)
+            sideEdges.splice(sideEdges.begin(), edges, --edges.end());
         }
       }
       list<TopoDS_Edge>::iterator ite = sideEdges.begin();
       aNbNodes[nbSides] = 1;
-      for(; ite!=sideEdges.end(); ite++) {
-        SMESH_subMesh * sm = aMesh.GetSubMesh( *ite );
+      for (; ite!=sideEdges.end(); ite++) {
+        SMESH_subMesh * sm = aMesh.GetSubMesh(*ite);
         MapShapeNbElemsItr anIt = aResMap.find(sm);
-        if(anIt==aResMap.end()) {
+        if (anIt==aResMap.end()) {
           return false;
         }
         std::vector<int> aVec = (*anIt).second;
-        if(IsQuadratic)
+        if (IsQuadratic)
           aNbNodes[nbSides] += (aVec[SMDSEntity_Node]-1)/2 + 1;
         else
           aNbNodes[nbSides] += aVec[SMDSEntity_Node] + 1;
@@ -1046,37 +1065,37 @@ bool StdMeshers_Quadrangle_2D::CheckNbEdgesForEvaluate(SMESH_Mesh& aMesh,
     if (nbSides < 4) {
       nbSides = 0;
       SMESH_Block::GetOrderedEdges (F, V, edges, nbEdgesInWire);
-      while ( !edges.empty()) {
+      while (!edges.empty()) {
         sideEdges.clear();
-        sideEdges.splice( sideEdges.end(), edges, edges.begin());
+        sideEdges.splice(sideEdges.end(), edges, edges.begin());
         bool sameSide = true;
-        while ( !edges.empty() && sameSide ) {
+        while (!edges.empty() && sameSide) {
           sameSide =
-            SMESH_Algo::IsContinuous( sideEdges.back(), edges.front() ) &&
-            twoEdgesMeatAtVertex( sideEdges.back(), edges.front(), aMesh );
-          if ( sameSide )
-            sideEdges.splice( sideEdges.end(), edges, edges.begin());
+            SMESH_Algo::IsContinuous(sideEdges.back(), edges.front()) &&
+            twoEdgesMeatAtVertex(sideEdges.back(), edges.front(), aMesh);
+          if (sameSide)
+            sideEdges.splice(sideEdges.end(), edges, edges.begin());
         }
-        if ( nbSides == 0 ) { // go backward from the first edge
+        if (nbSides == 0) { // go backward from the first edge
           sameSide = true;
-          while ( !edges.empty() && sameSide ) {
+          while (!edges.empty() && sameSide) {
             sameSide =
-              SMESH_Algo::IsContinuous( sideEdges.front(), edges.back() ) &&
-              twoEdgesMeatAtVertex( sideEdges.front(), edges.back(), aMesh );
-            if ( sameSide )
-              sideEdges.splice( sideEdges.begin(), edges, --edges.end());
+              SMESH_Algo::IsContinuous(sideEdges.front(), edges.back()) &&
+              twoEdgesMeatAtVertex(sideEdges.front(), edges.back(), aMesh);
+            if (sameSide)
+              sideEdges.splice(sideEdges.begin(), edges, --edges.end());
           }
         }
         list<TopoDS_Edge>::iterator ite = sideEdges.begin();
         aNbNodes[nbSides] = 1;
-        for(; ite!=sideEdges.end(); ite++) {
-          SMESH_subMesh * sm = aMesh.GetSubMesh( *ite );
+        for (; ite!=sideEdges.end(); ite++) {
+          SMESH_subMesh * sm = aMesh.GetSubMesh(*ite);
           MapShapeNbElemsItr anIt = aResMap.find(sm);
-          if(anIt==aResMap.end()) {
+          if (anIt==aResMap.end()) {
             return false;
           }
           std::vector<int> aVec = (*anIt).second;
-          if(IsQuadratic)
+          if (IsQuadratic)
             aNbNodes[nbSides] += (aVec[SMDSEntity_Node]-1)/2 + 1;
           else
             aNbNodes[nbSides] += aVec[SMDSEntity_Node] + 1;
@@ -1086,7 +1105,7 @@ bool StdMeshers_Quadrangle_2D::CheckNbEdgesForEvaluate(SMESH_Mesh& aMesh,
     }
   }
   if (nbSides != 4) {
-    if ( !nbSides )
+    if (!nbSides)
       nbSides = nbEdgesInWire.front();
     error(COMPERR_BAD_SHAPE, TComm("Face must have 4 sides but not ") << nbSides);
     return false;
@@ -1111,13 +1130,12 @@ FaceQuadStruct *StdMeshers_Quadrangle_2D::CheckAnd2Dcompute
 
   FaceQuadStruct *quad = CheckNbEdges(aMesh, aShape);
 
-  if(!quad) return 0;
+  if (!quad) return 0;
 
   // set normalized grid on unit square in parametric domain
   bool stat = SetNormalizedGrid(aMesh, aShape, quad);
-  if(!stat) {
-    if(!quad)
-      delete quad;
+  if (!stat) {
+    if (quad) delete quad;
     quad = 0;
   }
 
@@ -1141,13 +1159,21 @@ faceQuadStruct::~faceQuadStruct()
 namespace {
   inline const vector<UVPtStruct>& GetUVPtStructIn(FaceQuadStruct* quad, int i, int nbSeg)
   {
-    bool   isXConst   = ( i == BOTTOM_SIDE || i == TOP_SIDE );
-    double constValue = ( i == BOTTOM_SIDE || i == LEFT_SIDE ) ? 0 : 1;
+    bool   isXConst   = (i == BOTTOM_SIDE || i == TOP_SIDE);
+    double constValue = (i == BOTTOM_SIDE || i == LEFT_SIDE) ? 0 : 1;
     return
       quad->isEdgeOut[i] ?
       quad->side[i]->SimulateUVPtStruct(nbSeg,isXConst,constValue) :
       quad->side[i]->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,
+                      const gp_UV& p0,const gp_UV& p1,const gp_UV& p2,const gp_UV& p3)
+  {
+    return
+      ((1 - y) * p0 + x * p1 + y * p2 + (1 - x) * p3 ) -
+      ((1 - x) * (1 - y) * a0 + x * (1 - y) * a1 + x * y * a2 + (1 - x) * y * a3);
+  }
 }
 
 //=============================================================================
@@ -1194,14 +1220,14 @@ bool StdMeshers_Quadrangle_2D::SetNormalizedGrid (SMESH_Mesh & aMesh,
 
   UVPtStruct *uv_grid = quad->uv_grid = new UVPtStruct[nbvertic * nbhoriz];
 
-  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 );
+  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 ( uv_e0.empty() || uv_e1.empty() || uv_e2.empty() || uv_e3.empty() )
-    //return error( "Can't find nodes on sides");
-    return error( COMPERR_BAD_INPUT_MESH );
+  if (uv_e0.empty() || uv_e1.empty() || uv_e2.empty() || uv_e3.empty())
+    //return error("Can't find nodes on sides");
+    return error(COMPERR_BAD_INPUT_MESH);
 
   // nodes Id on "in" edges
   if (! quad->isEdgeOut[0]) {
@@ -1254,10 +1280,10 @@ bool StdMeshers_Quadrangle_2D::SetNormalizedGrid (SMESH_Mesh & aMesh,
   }
 
   // 4 --- 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.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);
 
   for (int i = 0; i < nbhoriz; i++) {
     for (int j = 0; j < nbvertic; j++) {
@@ -1275,8 +1301,7 @@ bool StdMeshers_Quadrangle_2D::SetNormalizedGrid (SMESH_Mesh & aMesh,
       gp_UV p2 = quad->side[2]->Value2d(param_2).XY();
       gp_UV p3 = quad->side[3]->Value2d(param_3).XY();
 
-      gp_UV uv = (1 - y) * p0 + x * p1 + y * p2 + (1 - x) * p3;
-      uv -= (1 - x) * (1 - y) * a0 + x * (1 - y) * a1 + x * y * a2 + (1 - x) * y * a3;
+      gp_UV uv = CalcUV(x,y, a0,a1,a2,a3, p0,p1,p2,p3);
 
       uv_grid[ij].u = uv.X();
       uv_grid[ij].v = uv.Y();
@@ -1293,11 +1318,11 @@ bool StdMeshers_Quadrangle_2D::SetNormalizedGrid (SMESH_Mesh & aMesh,
 static void ShiftQuad(FaceQuadStruct* quad, const int num, bool)
 {
   StdMeshers_FaceSide* side[4] = { quad->side[0], quad->side[1], quad->side[2], quad->side[3] };
-  for (int i = BOTTOM_SIDE; i < NB_SIDES; ++i ) {
-    int id = ( i + num ) % NB_SIDES;
-    bool wasForward = ( i < TOP_SIDE );
-    bool newForward = ( id < TOP_SIDE );
-    if ( wasForward != newForward )
+  for (int i = BOTTOM_SIDE; i < NB_SIDES; ++i) {
+    int id = (i + num) % NB_SIDES;
+    bool wasForward = (i < TOP_SIDE);
+    bool newForward = (id < TOP_SIDE);
+    if (wasForward != newForward)
       side[ i ]->Reverse();
     quad->side[ id ] = side[ i ];
   }
@@ -1313,9 +1338,9 @@ static gp_UV CalcUV(double x0, double x1, double y0, double y1,
                     const gp_UV& a0, const gp_UV& a1,
                     const gp_UV& a2, const gp_UV& a3)
 {
-  const vector<UVPtStruct>& uv_eb = quad->side[0]->GetUVPtStruct(true,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_et = quad->side[2]->GetUVPtStruct(true,1);
   const vector<UVPtStruct>& uv_el = quad->side[3]->GetUVPtStruct(false,0);
 
   double x = (x0 + y0 * (x1 - x0)) / (1 - (y1 - y0) * (x1 - x0));
@@ -1331,9 +1356,7 @@ static gp_UV CalcUV(double x0, double x1, double y0, double y1,
   gp_UV p2 = quad->side[TOP_SIDE   ]->Value2d(param_t).XY();
   gp_UV p3 = quad->side[LEFT_SIDE  ]->Value2d(param_l).XY();
 
-  gp_UV uv = p0 * (1 - y) + p1 * x + p2 * y + p3 * (1 - x);
-
-  uv -= (1 - x) * (1 - y) * a0 + x * (1 - y) * a1 + x * y * a2 + (1 - x) * y * a3;
+  gp_UV uv = CalcUV(x,y, a0,a1,a2,a3, p0,p1,p2,p3);
 
   return uv;
 }
@@ -1348,27 +1371,12 @@ static gp_UV CalcUV2(double x, double y,
                      const gp_UV& a0, const gp_UV& a1,
                      const gp_UV& a2, const gp_UV& a3)
 {
-  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);
-
-  //double x = (x0 + y0 * (x1 - x0)) / (1 - (y1 - y0) * (x1 - x0));
-  //double y = y0 + x * (y1 - y0);
-
-  double param_b = uv_eb[0].normParam + x * (uv_eb.back().normParam - uv_eb[0].normParam);
-  double param_t = uv_et[0].normParam + x * (uv_et.back().normParam - uv_et[0].normParam);
-  double param_r = uv_er[0].normParam + y * (uv_er.back().normParam - uv_er[0].normParam);
-  double param_l = uv_el[0].normParam + y * (uv_el.back().normParam - uv_el[0].normParam);
-
-  gp_UV p0 = quad->side[BOTTOM_SIDE]->Value2d(param_b).XY();
-  gp_UV p1 = quad->side[RIGHT_SIDE ]->Value2d(param_r).XY();
-  gp_UV p2 = quad->side[TOP_SIDE   ]->Value2d(param_t).XY();
-  gp_UV p3 = quad->side[LEFT_SIDE  ]->Value2d(param_l).XY();
-
-  gp_UV uv = p0 * (1 - y) + p1 * x + p2 * y + p3 * (1 - x);
+  gp_UV p0 = quad->side[BOTTOM_SIDE]->Value2d(x).XY();
+  gp_UV p1 = quad->side[RIGHT_SIDE ]->Value2d(y).XY();
+  gp_UV p2 = quad->side[TOP_SIDE   ]->Value2d(x).XY();
+  gp_UV p3 = quad->side[LEFT_SIDE  ]->Value2d(y).XY();
 
-  uv -= (1 - x) * (1 - y) * a0 + x * (1 - y) * a1 + x * y * a2 + (1 - x) * y * a3;
+  gp_UV uv = CalcUV(x,y, a0,a1,a2,a3, p0,p1,p2,p3);
 
   return uv;
 }
@@ -1388,20 +1396,14 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh &        aMesh,
   // of meshing after implementation new variant
   // for bug 0016220 from Mantis.
   bool OldVersion = false;
+  if (myQuadType == QUAD_QUADRANGLE_PREF_REVERSED)
+    OldVersion = true;
 
   SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
   const TopoDS_Face& F = TopoDS::Face(aShape);
   Handle(Geom_Surface) S = BRep_Tool::Surface(F);
-//  const TopoDS_Wire& W = BRepTools::OuterWire(F);
   bool WisF = true;
-//   if(W.Orientation()==TopAbs_FORWARD) 
-//     WisF = true;
-  //if(WisF) cout<<"W is FORWARD"<<endl;
-  //else cout<<"W is REVERSED"<<endl;
-//   bool FisF = (F.Orientation()==TopAbs_FORWARD);
-//   if(!FisF) WisF = !WisF;
-//  WisF = FisF;
-  int i,j,geomFaceID = meshDS->ShapeToIndex( F );
+  int i,j,geomFaceID = meshDS->ShapeToIndex(F);
 
   int nb = quad->side[0]->NbPoints();
   int nr = quad->side[1]->NbPoints();
@@ -1410,8 +1412,8 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh &        aMesh,
   int dh = abs(nb-nt);
   int dv = abs(nr-nl);
 
-  if( dh>=dv ) {
-    if( nt>nb ) {
+  if (dh>=dv) {
+    if (nt>nb) {
       // it is a base case => not shift quad but me be replacement is need
       ShiftQuad(quad,0,WisF);
     }
@@ -1421,7 +1423,7 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh &        aMesh,
     }
   }
   else {
-    if( nr>nl ) {
+    if (nr>nl) {
       // we have to shift quad on 1
       ShiftQuad(quad,1,WisF);
     }
@@ -1470,7 +1472,7 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh &        aMesh,
   //      0------------0
   //       0  bottom  1
 
-  if(dh>dv) {
+  if (dh>dv) {
     addv = (dh-dv)/2;
     nbv = nbv + addv;
   }
@@ -1479,82 +1481,81 @@ 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_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_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 (uv_eb.size() != nb || uv_er.size() != nr || uv_et.size() != nt || uv_el.size() != nl)
+    return error(COMPERR_BAD_INPUT_MESH);
 
   // arrays for normalized params
   //cout<<"Dump B:"<<endl;
   TColStd_SequenceOfReal npb, npr, npt, npl;
-  for(i=0; i<nb; i++) {
+  for (i=0; i<nb; i++) {
     npb.Append(uv_eb[i].normParam);
     //cout<<"i="<<i<<" par="<<uv_eb[i].normParam<<" npar="<<uv_eb[i].normParam;
     //const SMDS_MeshNode* N = uv_eb[i].node;
     //cout<<" node("<<N->X()<<","<<N->Y()<<","<<N->Z()<<")"<<endl;
   }
-  for(i=0; i<nr; i++) {
+  for (i=0; i<nr; i++) {
     npr.Append(uv_er[i].normParam);
   }
-  for(i=0; i<nt; i++) {
+  for (i=0; i<nt; i++) {
     npt.Append(uv_et[i].normParam);
   }
-  for(i=0; i<nl; i++) {
+  for (i=0; i<nl; i++) {
     npl.Append(uv_el[i].normParam);
   }
 
   int dl,dr;
-  if(OldVersion) {
+  if (OldVersion) {
     // add some params to right and left after the first param
     // insert to right
     dr = nbv - nr;
     double dpr = (npr.Value(2) - npr.Value(1))/(dr+1);
-    for(i=1; i<=dr; i++) {
+    for (i=1; i<=dr; i++) {
       npr.InsertAfter(1,npr.Value(2)-dpr);
     }
     // insert to left
     dl = nbv - nl;
     dpr = (npl.Value(2) - npl.Value(1))/(dl+1);
-    for(i=1; i<=dl; i++) {
+    for (i=1; i<=dl; i++) {
       npl.InsertAfter(1,npl.Value(2)-dpr);
     }
   }
   //cout<<"npb:";
-  //for(i=1; i<=npb.Length(); i++) {
+  //for (i=1; i<=npb.Length(); i++) {
   //  cout<<" "<<npb.Value(i);
   //}
   //cout<<endl;
   
-  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 );
+  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);
   //cout<<" a0("<<a0.X()<<","<<a0.Y()<<")"<<" a1("<<a1.X()<<","<<a1.Y()<<")"
   //    <<" a2("<<a2.X()<<","<<a2.Y()<<")"<<" a3("<<a3.X()<<","<<a3.Y()<<")"<<endl;
 
   int nnn = Min(nr,nl);
   // auxilary sequence of XY for creation nodes
   // in the bottom part of central domain
-  // it's length must be == nbv-nnn-1
-  TColgp_SequenceOfXY UVL;
-  TColgp_SequenceOfXY UVR;
+  // Length of UVL and UVR must be == nbv-nnn
+  TColgp_SequenceOfXY UVL, UVR, UVT;
 
-  if(OldVersion) {
+  if (OldVersion) {
     // step1: create faces for left domain
     StdMeshers_Array2OfNode NodesL(1,dl+1,1,nl);
     // add left nodes
-    for(j=1; j<=nl; j++)
+    for (j=1; j<=nl; j++)
       NodesL.SetValue(1,j,uv_el[j-1].node);
-    if(dl>0) {
+    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;
-      for(i=1; i<=dl; i++) {
+      for (i=1; i<=dl; i++) {
         double x0 = npt.Value(i+1);
         double x1 = x0;
         // diagonal node
@@ -1565,9 +1566,9 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh &        aMesh,
         SMDS_MeshNode * N = meshDS->AddNode(P.X(), P.Y(), P.Z());
         meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y());
         NodesL.SetValue(i+1,1,N);
-        if(UVL.Length()<nbv-nnn-1) UVL.Append(UV);
+        if (UVL.Length()<nbv-nnn) UVL.Append(UV);
         // internal nodes
-        for(j=2; j<nl; j++) {
+        for (j=2; j<nl; j++) {
           double y0 = npl.Value(dl+j);
           double y1 = npr.Value(dl+j);
           gp_UV UV = CalcUV(x0, x1, y0, y1, quad, a0, a1, a2, a3);
@@ -1575,57 +1576,57 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh &        aMesh,
           SMDS_MeshNode* N = meshDS->AddNode(P.X(), P.Y(), P.Z());
           meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y());
           NodesL.SetValue(i+1,j,N);
-          if( i==dl ) UVtmp.Append(UV);
+          if (i==dl) UVtmp.Append(UV);
         }
       }
-      for(i=1; i<=UVtmp.Length() && UVL.Length()<nbv-nnn-1; i++) {
+      for (i=1; i<=UVtmp.Length() && UVL.Length()<nbv-nnn; i++) {
         UVL.Append(UVtmp.Value(i));
       }
       //cout<<"Dump NodesL:"<<endl;
-      //for(i=1; i<=dl+1; i++) {
+      //for (i=1; i<=dl+1; i++) {
       //  cout<<"i="<<i;
-      //  for(j=1; j<=nl; j++) {
+      //  for (j=1; j<=nl; j++) {
       //    cout<<" ("<<NodesL.Value(i,j)->X()<<","<<NodesL.Value(i,j)->Y()<<","<<NodesL.Value(i,j)->Z()<<")";
       //  }
       //  cout<<endl;
       //}
       // create faces
-      for(i=1; i<=dl; i++) {
-        for(j=1; j<nl; j++) {
-          if(WisF) {
+      for (i=1; i<=dl; i++) {
+        for (j=1; j<nl; j++) {
+          if (WisF) {
             SMDS_MeshFace* F =
               myTool->AddFace(NodesL.Value(i,j), NodesL.Value(i+1,j),
                               NodesL.Value(i+1,j+1), NodesL.Value(i,j+1));
-            if(F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+            if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
           }
           else {
             SMDS_MeshFace* F =
               myTool->AddFace(NodesL.Value(i,j), NodesL.Value(i,j+1),
                               NodesL.Value(i+1,j+1), NodesL.Value(i+1,j));
-            if(F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+            if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
           }
         }
       }
     }
     else {
       // fill UVL using c2d
-      for(i=1; i<npl.Length() && UVL.Length()<nbv-nnn-1; i++) {
-        UVL.Append( gp_UV ( uv_el[i].u, uv_el[i].v ));
+      for (i=1; i<npl.Length() && UVL.Length()<nbv-nnn; i++) {
+        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) {
+    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;
-      for(i=1; i<=dr; i++) {
+      for (i=1; i<=dr; i++) {
         double x0 = npt.Value(nt-i);
         double x1 = x0;
         // diagonal node
@@ -1636,9 +1637,9 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh &        aMesh,
         SMDS_MeshNode * N = meshDS->AddNode(P.X(), P.Y(), P.Z());
         meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y());
         NodesR.SetValue(i+1,nr,N);
-        if(UVR.Length()<nbv-nnn-1) UVR.Append(UV);
+        if (UVR.Length()<nbv-nnn) UVR.Append(UV);
         // internal nodes
-        for(j=2; j<nr; j++) {
+        for (j=2; j<nr; j++) {
           double y0 = npl.Value(nbv-j+1);
           double y1 = npr.Value(nbv-j+1);
           gp_UV UV = CalcUV(x0, x1, y0, y1, quad, a0, a1, a2, a3);
@@ -1646,62 +1647,62 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh &        aMesh,
           SMDS_MeshNode* N = meshDS->AddNode(P.X(), P.Y(), P.Z());
           meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y());
           NodesR.SetValue(i+1,j,N);
-          if( i==dr ) UVtmp.Prepend(UV);
+          if (i==dr) UVtmp.Prepend(UV);
         }
       }
-      for(i=1; i<=UVtmp.Length() && UVR.Length()<nbv-nnn-1; i++) {
+      for (i=1; i<=UVtmp.Length() && UVR.Length()<nbv-nnn; i++) {
         UVR.Append(UVtmp.Value(i));
       }
       // create faces
-      for(i=1; i<=dr; i++) {
-        for(j=1; j<nr; j++) {
-          if(WisF) {
+      for (i=1; i<=dr; i++) {
+        for (j=1; j<nr; j++) {
+          if (WisF) {
             SMDS_MeshFace* F =
               myTool->AddFace(NodesR.Value(i,j), NodesR.Value(i+1,j),
                               NodesR.Value(i+1,j+1), NodesR.Value(i,j+1));
-            if(F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+            if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
           }
           else {
             SMDS_MeshFace* F =
               myTool->AddFace(NodesR.Value(i,j), NodesR.Value(i,j+1),
                               NodesR.Value(i+1,j+1), NodesR.Value(i+1,j));
-            if(F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+            if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
           }
         }
       }
     }
     else {
       // fill UVR using c2d
-      for(i=1; i<npr.Length() && UVR.Length()<nbv-nnn-1; i++) {
-        UVR.Append( gp_UV( uv_er[i].u, uv_er[i].v ));
+      for (i=1; i<npr.Length() && UVR.Length()<nbv-nnn; i++) {
+        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 string using NodesL
-    for(i=1; i<=dl+1; i++)
+    // add first line using NodesL
+    for (i=1; i<=dl+1; i++)
       NodesC.SetValue(1,i,NodesL(i,1));
-    for(i=2; i<=nl; i++)
+    for (i=2; i<=nl; i++)
       NodesC.SetValue(1,dl+i,NodesL(dl+1,i));
-    // add last string using NodesR
-    for(i=1; i<=dr+1; i++)
+    // add last line using NodesR
+    for (i=1; i<=dr+1; i++)
       NodesC.SetValue(nb,i,NodesR(i,nr));
-    for(i=1; i<nr; i++)
+    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++)
+    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++) {
+    for (i=2; i<nb; i++) {
       double x0 = npt.Value(dl+i);
       double x1 = x0;
-      for(j=1; j<nnn; j++) {
+      for (j=1; j<nnn; j++) {
         double y0 = npl.Value(nbv-nnn+j);
         double y1 = npr.Value(nbv-nnn+j);
         gp_UV UV = CalcUV(x0, x1, y0, y1, quad, a0, a1, a2, a3);
@@ -1709,41 +1710,48 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh &        aMesh,
         SMDS_MeshNode* N = meshDS->AddNode(P.X(), P.Y(), P.Z());
         meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y());
         NodesC.SetValue(i,nbv-nnn+j,N);
+        if ( j==1 )
+          UVT.Append( UV );
       }
     }
     // add diagonal layers
     //cout<<"UVL.Length()="<<UVL.Length()<<" UVR.Length()="<<UVR.Length()<<endl;
     //cout<<"Dump UVL:"<<endl;
-    //for(i=1; i<=UVL.Length(); i++) {
+    //for (i=1; i<=UVL.Length(); i++) {
     //  cout<<" ("<<UVL.Value(i).X()<<","<<UVL.Value(i).Y()<<")";
     //}
     //cout<<endl;
-    for(i=1; i<nbv-nnn; i++) {
-      double du = UVR.Value(i).X() - UVL.Value(i).X();
-      double dv = UVR.Value(i).Y() - UVL.Value(i).Y();
-      for(j=2; j<nb; j++) {
-        double u = UVL.Value(i).X() + du*npb.Value(j);
-        double v = UVL.Value(i).Y() + dv*npb.Value(j);
-        gp_Pnt P = S->Value(u,v);
+    gp_UV A2 = UVR.Value(nbv-nnn);
+    gp_UV A3 = UVL.Value(nbv-nnn);
+    for (i=1; i<nbv-nnn; i++) {
+      gp_UV p1 = UVR.Value(i);
+      gp_UV p3 = UVL.Value(i);
+      double y = i / double(nbv-nnn);
+      for (j=2; j<nb; j++) {
+        double x = npb.Value(j);
+        gp_UV p0( uv_eb[j-1].u, uv_eb[j-1].v );
+        gp_UV p2 = UVT.Value( j-1 );
+        gp_UV UV = CalcUV(x, y, a0, a1, A2, A3, p0,p1,p2,p3 );
+        gp_Pnt P = S->Value(UV.X(),UV.Y());
         SMDS_MeshNode* N = meshDS->AddNode(P.X(), P.Y(), P.Z());
-        meshDS->SetNodeOnFace(N, geomFaceID, u, v);
+        meshDS->SetNodeOnFace(N, geomFaceID, UV.X(),UV.Y());
         NodesC.SetValue(j,i+1,N);
       }
     }
     // create faces
-    for(i=1; i<nb; i++) {
-      for(j=1; j<nbv; j++) {
-        if(WisF) {
+    for (i=1; i<nb; i++) {
+      for (j=1; j<nbv; j++) {
+        if (WisF) {
           SMDS_MeshFace* F =
             myTool->AddFace(NodesC.Value(i,j), NodesC.Value(i+1,j),
                             NodesC.Value(i+1,j+1), NodesC.Value(i,j+1));
-          if(F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+          if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
         }
         else {
           SMDS_MeshFace* F =
             myTool->AddFace(NodesC.Value(i,j), NodesC.Value(i,j+1),
                             NodesC.Value(i+1,j+1), NodesC.Value(i+1,j));
-          if(F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+          if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
         }
       }
     }
@@ -1753,39 +1761,35 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh &        aMesh,
     // step1: create faces for bottom rectangle domain
     StdMeshers_Array2OfNode NodesBRD(1,nb,1,nnn-1);
     // fill UVL and UVR using c2d
-    for(j=0; j<nb; j++) {
+    for (j=0; j<nb; j++) {
       NodesBRD.SetValue(j+1,1,uv_eb[j].node);
     }
-    for(i=1; i<nnn-1; i++) {
+    for (i=1; i<nnn-1; i++) {
       NodesBRD.SetValue(1,i+1,uv_el[i].node);
       NodesBRD.SetValue(nb,i+1,uv_er[i].node);
-      double du = uv_er[i].u - uv_el[i].u;
-      double dv = uv_er[i].v - uv_el[i].v;
-      for(j=2; j<nb; j++) {
-        double u = uv_el[i].u + du*npb.Value(j);
-        double v = uv_el[i].v + dv*npb.Value(j);
-        gp_Pnt P = S->Value(u,v);
+      for (j=2; j<nb; j++) {
+        double x = npb.Value(j);
+        double y = (1-x) * npl.Value(i+1) + x * npr.Value(i+1);
+        gp_UV UV = CalcUV2(x, y, quad, a0, a1, a2, a3);
+        gp_Pnt P = S->Value(UV.X(),UV.Y());
         SMDS_MeshNode* N = meshDS->AddNode(P.X(), P.Y(), P.Z());
-        meshDS->SetNodeOnFace(N, geomFaceID, u, v);
+        meshDS->SetNodeOnFace(N, geomFaceID, UV.X(),UV.Y());
         NodesBRD.SetValue(j,i+1,N);
-
       }
     }
-    int nbf=0;
-    for(j=1; j<nnn-1; j++) {
-      for(i=1; i<nb; i++) {
-        nbf++;
-        if(WisF) {
+    for (j=1; j<nnn-1; j++) {
+      for (i=1; i<nb; i++) {
+        if (WisF) {
           SMDS_MeshFace* F =
             myTool->AddFace(NodesBRD.Value(i,j), NodesBRD.Value(i+1,j),
                             NodesBRD.Value(i+1,j+1), NodesBRD.Value(i,j+1));
-          if(F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+          if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
         }
         else {
           SMDS_MeshFace* F =
             myTool->AddFace(NodesBRD.Value(i,j), NodesBRD.Value(i,j+1),
                             NodesBRD.Value(i+1,j+1), NodesBRD.Value(i+1,j));
-          if(F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+          if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
         }
       }
     }
@@ -1793,19 +1797,19 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh &        aMesh,
     // create faces for region C
     StdMeshers_Array2OfNode NodesC(1,nb,1,drl+1+addv);
     // add nodes from previous region
-    for(j=1; j<=nb; j++) {
+    for (j=1; j<=nb; j++) {
       NodesC.SetValue(j,1,NodesBRD.Value(j,nnn-1));
     }
-    if( (drl+addv) > 0 ) {
+    if ((drl+addv) > 0) {
       int n1,n2;
-      if(nr>nl) {
+      if (nr>nl) {
         n1 = 1;
         n2 = drl + 1;
         TColgp_SequenceOfXY UVtmp;
         double drparam = npr.Value(nr) - npr.Value(nnn-1);
         double dlparam = npl.Value(nnn) - npl.Value(nnn-1);
         double y0,y1;
-        for(i=1; i<=drl; i++) {
+        for (i=1; i<=drl; i++) {
           // add existed nodes from right edge
           NodesC.SetValue(nb,i+1,uv_er[nnn+i-2].node);
           //double dtparam = npt.Value(i+1);
@@ -1813,7 +1817,7 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh &        aMesh,
           double dpar = (y1 - npr.Value(nnn-1))/drparam;
           y0 = npl.Value(nnn-1) + dpar*dlparam; // param on left edge
           double dy = y1 - y0;
-          for(j=1; j<nb; j++) {
+          for (j=1; j<nb; j++) {
             double x = npt.Value(i+1) + npb.Value(j)*(1-npt.Value(i+1));
             double y = y0 + dy*x;
             gp_UV UV = CalcUV2(x, y, quad, a0, a1, a2, a3);
@@ -1825,13 +1829,13 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh &        aMesh,
         }
         double dy0 = (1-y0)/(addv+1);
         double dy1 = (1-y1)/(addv+1);
-        for(i=1; i<=addv; i++) {
+        for (i=1; i<=addv; i++) {
           double yy0 = y0 + dy0*i;
           double yy1 = y1 + dy1*i;
           double dyy = yy1 - yy0;
-          for(j=1; j<=nb; j++) {
+          for (j=1; j<=nb; j++) {
             double x = npt.Value(i+1+drl) + 
-              npb.Value(j) * ( npt.Value(nt-i) - 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);
             gp_Pnt P = S->Value(UV.X(),UV.Y());
@@ -1849,14 +1853,14 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh &        aMesh,
         double drparam = npr.Value(nnn) - npr.Value(nnn-1);
         double y0 = npl.Value(nnn-1);
         double y1 = npr.Value(nnn-1);
-        for(i=1; i<=drl; i++) {
+        for (i=1; i<=drl; i++) {
           // add existed nodes from right edge
           NodesC.SetValue(1,i+1,uv_el[nnn+i-2].node);
           y0 = npl.Value(nnn+i-1); // param on left edge
           double dpar = (y0 - npl.Value(nnn-1))/dlparam;
           y1 = npr.Value(nnn-1) + dpar*drparam; // param on right edge
           double dy = y1 - y0;
-          for(j=2; j<=nb; j++) {
+          for (j=2; j<=nb; j++) {
             double x = npb.Value(j)*npt.Value(nt-i);
             double y = y0 + dy*x;
             gp_UV UV = CalcUV2(x, y, quad, a0, a1, a2, a3);
@@ -1868,13 +1872,13 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh &        aMesh,
         }
         double dy0 = (1-y0)/(addv+1);
         double dy1 = (1-y1)/(addv+1);
-        for(i=1; i<=addv; i++) {
+        for (i=1; i<=addv; i++) {
           double yy0 = y0 + dy0*i;
           double yy1 = y1 + dy1*i;
           double dyy = yy1 - yy0;
-          for(j=1; j<=nb; j++) {
+          for (j=1; j<=nb; j++) {
             double x = npt.Value(i+1) + 
-              npb.Value(j) * ( npt.Value(nt-i-drl) - 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);
             gp_Pnt P = S->Value(UV.X(),UV.Y());
@@ -1885,57 +1889,55 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh &        aMesh,
         }
       }
       // create faces
-      for(j=1; j<=drl+addv; j++) {
-        for(i=1; i<nb; i++) {
-          nbf++;
-          if(WisF) {
+      for (j=1; j<=drl+addv; j++) {
+        for (i=1; i<nb; i++) {
+          if (WisF) {
             SMDS_MeshFace* F =
               myTool->AddFace(NodesC.Value(i,j), NodesC.Value(i+1,j),
                               NodesC.Value(i+1,j+1), NodesC.Value(i,j+1));
-            if(F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+            if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
           }
           else {
             SMDS_MeshFace* F =
               myTool->AddFace(NodesC.Value(i,j), NodesC.Value(i,j+1),
                               NodesC.Value(i+1,j+1), NodesC.Value(i+1,j));
-            if(F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+            if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
           }
         }
       } // end nr<nl
 
       StdMeshers_Array2OfNode NodesLast(1,nt,1,2);
-      for(i=1; i<=nt; i++) {
+      for (i=1; i<=nt; i++) {
         NodesLast.SetValue(i,2,uv_et[i-1].node);
       }
       int nnn=0;
-      for(i=n1; i<drl+addv+1; i++) {
+      for (i=n1; i<drl+addv+1; i++) {
         nnn++;
         NodesLast.SetValue(nnn,1,NodesC.Value(1,i));
       }
-      for(i=1; i<=nb; i++) {
+      for (i=1; i<=nb; i++) {
         nnn++;
         NodesLast.SetValue(nnn,1,NodesC.Value(i,drl+addv+1));
       }
-      for(i=drl+addv; i>=n2; i--) {
+      for (i=drl+addv; i>=n2; i--) {
         nnn++;
         NodesLast.SetValue(nnn,1,NodesC.Value(nb,i));
       }
-      for(i=1; i<nt; i++) {
-        nbf++;
-        if(WisF) {
+      for (i=1; i<nt; i++) {
+        if (WisF) {
           SMDS_MeshFace* F =
             myTool->AddFace(NodesLast.Value(i,1), NodesLast.Value(i+1,1),
                             NodesLast.Value(i+1,2), NodesLast.Value(i,2));
-          if(F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+          if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
         }
         else {
           SMDS_MeshFace* F =
             myTool->AddFace(NodesLast.Value(i,1), NodesLast.Value(i,2),
                             NodesLast.Value(i+1,2), NodesLast.Value(i+1,2));
-          if(F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+          if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
         }
       }
-    } // if( (drl+addv) > 0 )
+    } // if ((drl+addv) > 0)
 
   } // end new version implementation
 
@@ -1960,6 +1962,8 @@ bool StdMeshers_Quadrangle_2D::EvaluateQuadPref(SMESH_Mesh &        aMesh,
   // of meshing after implementation new variant
   // for bug 0016220 from Mantis.
   bool OldVersion = false;
+  if (myQuadType == QUAD_QUADRANGLE_PREF_REVERSED)
+    OldVersion = true;
 
   const TopoDS_Face& F = TopoDS::Face(aShape);
   Handle(Geom_Surface) S = BRep_Tool::Surface(F);
@@ -1971,8 +1975,8 @@ bool StdMeshers_Quadrangle_2D::EvaluateQuadPref(SMESH_Mesh &        aMesh,
   int dh = abs(nb-nt);
   int dv = abs(nr-nl);
 
-  if( dh>=dv ) {
-    if( nt>nb ) {
+  if (dh>=dv) {
+    if (nt>nb) {
       // it is a base case => not shift 
     }
     else {
@@ -1984,7 +1988,7 @@ bool StdMeshers_Quadrangle_2D::EvaluateQuadPref(SMESH_Mesh &        aMesh,
     }
   }
   else {
-    if( nr>nl ) {
+    if (nr>nl) {
       // we have to shift quad on 1
       nb = aNbNodes[3];
       nr = aNbNodes[0];
@@ -2007,7 +2011,7 @@ bool StdMeshers_Quadrangle_2D::EvaluateQuadPref(SMESH_Mesh &        aMesh,
   int addh = 0;
   int addv = 0;
 
-  if(dh>dv) {
+  if (dh>dv) {
     addv = (dh-dv)/2;
     nbv = nbv + addv;
   }
@@ -2017,7 +2021,7 @@ bool StdMeshers_Quadrangle_2D::EvaluateQuadPref(SMESH_Mesh &        aMesh,
   }
 
   int dl,dr;
-  if(OldVersion) {
+  if (OldVersion) {
     // add some params to right and left after the first param
     // insert to right
     dr = nbv - nr;
@@ -2029,14 +2033,14 @@ bool StdMeshers_Quadrangle_2D::EvaluateQuadPref(SMESH_Mesh &        aMesh,
 
   int nbNodes = 0;
   int nbFaces = 0;
-  if(OldVersion) {
+  if (OldVersion) {
     // step1: create faces for left domain
-    if(dl>0) {
+    if (dl>0) {
       nbNodes += dl*(nl-1);
       nbFaces += dl*(nl-1);
     }
     // step2: create faces for right domain
-    if(dr>0) {
+    if (dr>0) {
       nbNodes += dr*(nr-1);
       nbFaces += dr*(nr-1);
     }
@@ -2053,11 +2057,11 @@ bool StdMeshers_Quadrangle_2D::EvaluateQuadPref(SMESH_Mesh &        aMesh,
   } // end new version implementation
 
   std::vector<int> aVec(SMDSEntity_Last);
-  for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i] = 0;
-  if(IsQuadratic) {
+  for (int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i] = 0;
+  if (IsQuadratic) {
     aVec[SMDSEntity_Quad_Quadrangle] = nbFaces;
     aVec[SMDSEntity_Node] = nbNodes + nbFaces*4;
-    if( aNbNodes.size()==5 ) {
+    if (aNbNodes.size()==5) {
       aVec[SMDSEntity_Quad_Triangle] = aNbNodes[3] - 1;
       aVec[SMDSEntity_Quad_Quadrangle] = nbFaces - aNbNodes[3] + 1;
     }
@@ -2065,7 +2069,7 @@ bool StdMeshers_Quadrangle_2D::EvaluateQuadPref(SMESH_Mesh &        aMesh,
   else {
     aVec[SMDSEntity_Node] = nbNodes;
     aVec[SMDSEntity_Quadrangle] = nbFaces;
-    if( aNbNodes.size()==5 ) {
+    if (aNbNodes.size()==5) {
       aVec[SMDSEntity_Triangle] = aNbNodes[3] - 1;
       aVec[SMDSEntity_Quadrangle] = nbFaces - aNbNodes[3] + 1;
     }
@@ -2094,19 +2098,1102 @@ void StdMeshers_Quadrangle_2D::SplitQuad(SMESHDS_Mesh *theMeshDS,
   gp_Pnt c(theNode3->X(),theNode3->Y(),theNode3->Z());
   gp_Pnt d(theNode4->X(),theNode4->Y(),theNode4->Z());
   SMDS_MeshFace* face;
-  if(a.Distance(c) > b.Distance(d)){
+  if (a.Distance(c) > b.Distance(d)){
     face = myTool->AddFace(theNode2, theNode4 , theNode1);
-    if(face) theMeshDS->SetMeshElementOnShape(face, theFaceID );
+    if (face) theMeshDS->SetMeshElementOnShape(face, theFaceID);
     face = myTool->AddFace(theNode2, theNode3, theNode4);
-    if(face) theMeshDS->SetMeshElementOnShape(face, theFaceID );
+    if (face) theMeshDS->SetMeshElementOnShape(face, theFaceID);
 
   }
   else{
     face = myTool->AddFace(theNode1, theNode2 ,theNode3);
-    if(face) theMeshDS->SetMeshElementOnShape(face, theFaceID );
+    if (face) theMeshDS->SetMeshElementOnShape(face, theFaceID);
     face = myTool->AddFace(theNode1, theNode3, theNode4);
-    if(face) theMeshDS->SetMeshElementOnShape(face, theFaceID );
+    if (face) theMeshDS->SetMeshElementOnShape(face, theFaceID);
   }
 }
 
+//=======================================================================
+/*!
+ *  Implementation of Reduced algorithm (meshing with quadrangles only)
+ */
+//=======================================================================
+bool StdMeshers_Quadrangle_2D::ComputeReduced (SMESH_Mesh &        aMesh,
+                                               const TopoDS_Shape& aShape,
+                                               FaceQuadStruct*     quad)
+{
+  SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
+  const TopoDS_Face& F = TopoDS::Face(aShape);
+  Handle(Geom_Surface) S = BRep_Tool::Surface(F);
+  int i,j,geomFaceID = meshDS->ShapeToIndex(F);
+
+  int nb = quad->side[0]->NbPoints();
+  int nr = quad->side[1]->NbPoints();
+  int nt = quad->side[2]->NbPoints();
+  int nl = quad->side[3]->NbPoints();
+
+  //  Simple Reduce 8->6->4->2 (3 steps)      Multiple Reduce 8->2 (1 step)
+  //
+  //  .-----.-----.-----.-----.               .-----.-----.-----.-----.
+  //  |    / \    |    / \    |               |    / \    |    / \    |
+  //  |   /    .--.--.    \   |               |    / \    |    / \    |
+  //  |   /   /   |   \   \   |               |   /  .----.----.  \   |
+  //  .---.---.---.---.---.---.               |   / / \   |   / \ \   |
+  //  |   /  / \  |  / \  \   |               |   / / \   |   / \ \   |
+  //  |  /  /   .-.-.   \  \  |               |  / /  .---.---.  \ \  |
+  //  |  /  /  /  |  \  \  \  |               |  / / / \  |  / \ \ \  |
+  //  .--.--.--.--.--.--.--.--.               |  / / /  \ | /  \ \ \  |
+  //  |  / /  / \ | / \  \ \  |               | / / /   .-.-.   \ \ \ |
+  //  | / /  /  .-.-.  \  \ \ |               | / / /  /  |  \  \ \ \ |
+  //  | / / /  /  |  \  \ \ \ |               | / / /  /  |  \  \ \ \ |
+  //  .-.-.-.--.--.--.--.-.-.-.               .-.-.-.--.--.--.--.-.-.-.
+
+  bool MultipleReduce = false;
+  {
+    int nb1 = nb;
+    int nr1 = nr;
+    int nt1 = nt;
+    int nl1 = nl;
+
+    if (nr == nl) {
+      if (nb < nt) {
+        nt1 = nb;
+        nb1 = nt;
+      }
+    }
+    else if (nb == nt) {
+      nl1 = nb; // and == nt
+      nr1 = nb; // and == nt
+      if (nl < nr) {
+        nt1 = nl;
+        nb1 = nr;
+      }
+      else {
+        nt1 = nr;
+        nb1 = nl;
+      }
+    }
+    else {
+      return false;
+    }
+
+    // number of rows and columns
+    int nrows = nr1 - 1; // and also == nl1 - 1
+    int ncol_top = nt1 - 1;
+    int ncol_bot = nb1 - 1;
+    int npair_top = ncol_top / 2;
+    // maximum number of bottom elements for "linear" simple reduce
+    //int max_lin = ncol_top + npair_top * 2 * nrows;
+    // maximum number of bottom elements for "tree" simple reduce
+    int max_tree = npair_top * pow(2.0, nrows + 1);
+    if (ncol_top > npair_top * 2) {
+      int delta = ncol_bot - max_tree;
+      for (int irow = 1; irow < nrows; irow++) {
+        int nfour = delta / 4;
+        delta -= nfour*2;
+      }
+      if (delta <= (ncol_top - npair_top * 2))
+        max_tree = ncol_bot;
+    }
+
+    if (ncol_bot > max_tree)
+      MultipleReduce = true;
+  }
+
+  if (MultipleReduce) { // == ComputeQuadPref QUAD_QUADRANGLE_PREF_REVERSED
+    //==================================================
+    int dh = abs(nb-nt);
+    int dv = abs(nr-nl);
 
+    if (dh >= dv) {
+      if (nt > nb) {
+        // it is a base case => not shift quad but may be replacement is need
+        ShiftQuad(quad,0,true);
+      }
+      else {
+        // we have to shift quad on 2
+        ShiftQuad(quad,2,true);
+      }
+    }
+    else {
+      if (nr > nl) {
+        // we have to shift quad on 1
+        ShiftQuad(quad,1,true);
+      }
+      else {
+        // we have to shift quad on 3
+        ShiftQuad(quad,3,true);
+      }
+    }
+
+    nb = quad->side[0]->NbPoints();
+    nr = quad->side[1]->NbPoints();
+    nt = quad->side[2]->NbPoints();
+    nl = quad->side[3]->NbPoints();
+    dh = abs(nb-nt);
+    dv = abs(nr-nl);
+    int nbh  = Max(nb,nt);
+    int nbv = Max(nr,nl);
+    int addh = 0;
+    int addv = 0;
+
+    if (dh>dv) {
+      addv = (dh-dv)/2;
+      nbv = nbv + addv;
+    }
+    else { // dv>=dh
+      addh = (dv-dh)/2;
+      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);
+
+    // arrays for normalized params
+    TColStd_SequenceOfReal npb, npr, npt, npl;
+    for (j = 0; j < nb; j++) {
+      npb.Append(uv_eb[j].normParam);
+    }
+    for (i = 0; i < nr; i++) {
+      npr.Append(uv_er[i].normParam);
+    }
+    for (j = 0; j < nt; j++) {
+      npt.Append(uv_et[j].normParam);
+    }
+    for (i = 0; i < nl; i++) {
+      npl.Append(uv_el[i].normParam);
+    }
+
+    int dl,dr;
+    // orientation of face and 3 main domain for future faces
+    //       0   top    1
+    //      1------------1
+    //       |   |  |   |
+    //       |   |  |   |
+    //       | L |  | R |
+    //  left |   |  |   | rigth
+    //       |  /    \  |
+    //       | /  C   \ |
+    //       |/        \|
+    //      0------------0
+    //       0  bottom  1
+
+    // add some params to right and left after the first param
+    // insert to right
+    dr = nbv - nr;
+    double dpr = (npr.Value(2) - npr.Value(1))/(dr+1);
+    for (i=1; i<=dr; i++) {
+      npr.InsertAfter(1,npr.Value(2)-dpr);
+    }
+    // insert to left
+    dl = nbv - nl;
+    dpr = (npl.Value(2) - npl.Value(1))/(dl+1);
+    for (i=1; i<=dl; i++) {
+      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
+    // in the bottom part of central domain
+    // it's length must be == nbv-nnn-1
+    TColgp_SequenceOfXY UVL;
+    TColgp_SequenceOfXY UVR;
+    //==================================================
+
+    // step1: create faces for left domain
+    StdMeshers_Array2OfNode NodesL(1,dl+1,1,nl);
+    // add left nodes
+    for (j=1; j<=nl; j++)
+      NodesL.SetValue(1,j,uv_el[j-1].node);
+    if (dl>0) {
+      // add top nodes
+      for (i=1; i<=dl; i++) 
+        NodesL.SetValue(i+1,nl,uv_et[i].node);
+      // create and add needed nodes
+      TColgp_SequenceOfXY UVtmp;
+      for (i=1; i<=dl; i++) {
+        double x0 = npt.Value(i+1);
+        double x1 = x0;
+        // diagonal node
+        double y0 = npl.Value(i+1);
+        double y1 = npr.Value(i+1);
+        gp_UV UV = CalcUV(x0, x1, y0, y1, quad, a0, a1, a2, a3);
+        gp_Pnt P = S->Value(UV.X(),UV.Y());
+        SMDS_MeshNode * N = meshDS->AddNode(P.X(), P.Y(), P.Z());
+        meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y());
+        NodesL.SetValue(i+1,1,N);
+        if (UVL.Length()<nbv-nnn-1) UVL.Append(UV);
+        // internal nodes
+        for (j=2; j<nl; j++) {
+          double y0 = npl.Value(dl+j);
+          double y1 = npr.Value(dl+j);
+          gp_UV UV = CalcUV(x0, x1, y0, y1, quad, a0, a1, a2, a3);
+          gp_Pnt P = S->Value(UV.X(),UV.Y());
+          SMDS_MeshNode* N = meshDS->AddNode(P.X(), P.Y(), P.Z());
+          meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y());
+          NodesL.SetValue(i+1,j,N);
+          if (i==dl) UVtmp.Append(UV);
+        }
+      }
+      for (i=1; i<=UVtmp.Length() && UVL.Length()<nbv-nnn-1; i++) {
+        UVL.Append(UVtmp.Value(i));
+      }
+      // create faces
+      for (i=1; i<=dl; i++) {
+        for (j=1; j<nl; j++) {
+            SMDS_MeshFace* F =
+              myTool->AddFace(NodesL.Value(i,j), NodesL.Value(i+1,j),
+                              NodesL.Value(i+1,j+1), NodesL.Value(i,j+1));
+            if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+        }
+      }
+    }
+    else {
+      // fill UVL using c2d
+      for (i=1; i<npl.Length() && UVL.Length()<nbv-nnn-1; i++) {
+        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++) 
+      NodesR.SetValue(1,j,uv_er[nr-j].node);
+    if (dr>0) {
+      // add top nodes
+      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;
+      for (i=1; i<=dr; i++) {
+        double x0 = npt.Value(nt-i);
+        double x1 = x0;
+        // diagonal node
+        double y0 = npl.Value(i+1);
+        double y1 = npr.Value(i+1);
+        gp_UV UV = CalcUV(x0, x1, y0, y1, quad, a0, a1, a2, a3);
+        gp_Pnt P = S->Value(UV.X(),UV.Y());
+        SMDS_MeshNode * N = meshDS->AddNode(P.X(), P.Y(), P.Z());
+        meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y());
+        NodesR.SetValue(i+1,nr,N);
+        if (UVR.Length()<nbv-nnn-1) UVR.Append(UV);
+        // internal nodes
+        for (j=2; j<nr; j++) {
+          double y0 = npl.Value(nbv-j+1);
+          double y1 = npr.Value(nbv-j+1);
+          gp_UV UV = CalcUV(x0, x1, y0, y1, quad, a0, a1, a2, a3);
+          gp_Pnt P = S->Value(UV.X(),UV.Y());
+          SMDS_MeshNode* N = meshDS->AddNode(P.X(), P.Y(), P.Z());
+          meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y());
+          NodesR.SetValue(i+1,j,N);
+          if (i==dr) UVtmp.Prepend(UV);
+        }
+      }
+      for (i=1; i<=UVtmp.Length() && UVR.Length()<nbv-nnn-1; i++) {
+        UVR.Append(UVtmp.Value(i));
+      }
+      // create faces
+      for (i=1; i<=dr; i++) {
+        for (j=1; j<nr; j++) {
+            SMDS_MeshFace* F =
+              myTool->AddFace(NodesR.Value(i,j), NodesR.Value(i+1,j),
+                              NodesR.Value(i+1,j+1), NodesR.Value(i,j+1));
+            if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+        }
+      }
+    }
+    else {
+      // fill UVR using c2d
+      for (i=1; i<npr.Length() && UVR.Length()<nbv-nnn-1; i++) {
+        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
+    for (i=1; i<=dl+1; i++)
+      NodesC.SetValue(1,i,NodesL(i,1));
+    for (i=2; i<=nl; i++)
+      NodesC.SetValue(1,dl+i,NodesL(dl+1,i));
+    // add last line using NodesR
+    for (i=1; i<=dr+1; i++)
+      NodesC.SetValue(nb,i,NodesR(i,nr));
+    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++) 
+      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++) {
+      double x0 = npt.Value(dl+i);
+      double x1 = x0;
+      for (j=1; j<nnn; j++) {
+        double y0 = npl.Value(nbv-nnn+j);
+        double y1 = npr.Value(nbv-nnn+j);
+        gp_UV UV = CalcUV(x0, x1, y0, y1, quad, a0, a1, a2, a3);
+        gp_Pnt P = S->Value(UV.X(),UV.Y());
+        SMDS_MeshNode* N = meshDS->AddNode(P.X(), P.Y(), P.Z());
+        meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y());
+        NodesC.SetValue(i,nbv-nnn+j,N);
+      }
+    }
+    // add diagonal layers
+    for (i=1; i<nbv-nnn; i++) {
+      double du = UVR.Value(i).X() - UVL.Value(i).X();
+      double dv = UVR.Value(i).Y() - UVL.Value(i).Y();
+      for (j=2; j<nb; j++) {
+        double u = UVL.Value(i).X() + du*npb.Value(j);
+        double v = UVL.Value(i).Y() + dv*npb.Value(j);
+        gp_Pnt P = S->Value(u,v);
+        SMDS_MeshNode* N = meshDS->AddNode(P.X(), P.Y(), P.Z());
+        meshDS->SetNodeOnFace(N, geomFaceID, u, v);
+        NodesC.SetValue(j,i+1,N);
+      }
+    }
+    // create faces
+    for (i=1; i<nb; i++) {
+      for (j=1; j<nbv; j++) {
+          SMDS_MeshFace* F =
+            myTool->AddFace(NodesC.Value(i,j), NodesC.Value(i+1,j),
+                            NodesC.Value(i+1,j+1), NodesC.Value(i,j+1));
+          if (F) meshDS->SetMeshElementOnShape(F, geomFaceID);
+      }
+    }
+    // TODO ???
+  } // end Multiple Reduce implementation
+  else { // Simple Reduce (!MultipleReduce)
+    //=========================================================
+    if (nr == nl) {
+      if (nt < nb) {
+        // it is a base case => not shift quad
+        //ShiftQuad(quad,0,true);
+      }
+      else {
+        // we have to shift quad on 2
+        ShiftQuad(quad,2,true);
+      }
+    }
+    else {
+      if (nl > nr) {
+        // we have to shift quad on 1
+        ShiftQuad(quad,1,true);
+      }
+      else {
+        // we have to shift quad on 3
+        ShiftQuad(quad,3,true);
+      }
+    }
+
+    nb = quad->side[0]->NbPoints();
+    nr = quad->side[1]->NbPoints();
+    nt = quad->side[2]->NbPoints();
+    nl = quad->side[3]->NbPoints();
+    // number of rows and columns
+    int nrows = nr - 1; // and also == nl - 1
+    int ncol_top = nt - 1;
+    int ncol_bot = nb - 1;
+    int npair_top = ncol_top / 2;
+    // maximum number of bottom elements for "linear" simple reduce
+    int max_lin = ncol_top + npair_top * 2 * nrows;
+    // maximum number of bottom elements for "tree" simple reduce
+    //int max_tree = npair_top * pow(2, nrows + 1);
+
+    //if (ncol_bot > max_tree)
+    //  MultipleReduce = true;
+
+    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);
+
+    // arrays for normalized params
+    TColStd_SequenceOfReal npb, npr, npt, npl;
+    for (j = 0; j < nb; j++) {
+      npb.Append(uv_eb[j].normParam);
+    }
+    for (i = 0; i < nr; i++) {
+      npr.Append(uv_er[i].normParam);
+    }
+    for (j = 0; j < nt; j++) {
+      npt.Append(uv_et[j].normParam);
+    }
+    for (i = 0; i < nl; i++) {
+      npl.Append(uv_el[i].normParam);
+    }
+
+    // We will ajust new points to this grid
+    if (!SetNormalizedGrid(aMesh, aShape, quad))
+      return false;
+
+    // TODO ???
+    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);
+    //=========================================================
+
+    TColStd_SequenceOfInteger curr_base, next_base;
+    TColStd_SequenceOfReal curr_par_u, curr_par_v;
+    TColStd_SequenceOfReal next_par_u, next_par_v;
+    StdMeshers_Array2OfNode NodesBRD (1,nb, 1,nr);
+    for (j = 1; j <= nb; j++) {
+      NodesBRD.SetValue(j, 1, uv_eb[j - 1].node); // bottom
+      curr_base.Append(j);
+      next_base.Append(-1);
+      curr_par_u.Append(uv_eb[j-1].u);
+      curr_par_v.Append(uv_eb[j-1].v);
+      next_par_u.Append(0.);
+      next_par_v.Append(0.);
+    }
+    for (j = 1; j <= nt; j++) {
+      NodesBRD.SetValue(j, nr, uv_et[j - 1].node); // top
+    }
+
+    int curr_base_len = nb;
+    int next_base_len = 0;
+
+    if (ncol_bot > max_lin) {
+      // "tree" simple reduce 2->4->8->16->32->...
+      //
+      //  .---------------.---------------.---------------.---------------. nr
+      //  | \             |             / | \             |             / |
+      //  |     \ .-------.-------. /     |     \ .-------.-------. /     |
+      //  |       |       |       |       |       |       |       |       |
+      //  .-------.-------.-------.-------.-------.-------.-------.-------.
+      //  |\      |      /|\      |      /|\      |      /|\      |      /|
+      //  |  \.---.---./  |  \.---.---./  |  \.---.---./  |  \.---.---./  | i
+      //  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
+      //  .---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.
+      //  |\  |  /|\  |  /|\  |  /|\  |  /|\  |  /|\  |  /|\  |  /|\  |  /|
+      //  | .-.-. | .-.-. | .-.-. | .-.-. | .-.-. | .-.-. | .-.-. | .-.-. |
+      //  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+      //  .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. 1
+      //  1                               j                               nb
+
+      for (i = 1; i < nr; i++) { // layer by layer
+        // left
+        NodesBRD.SetValue(1, i+1, uv_el[i].node);
+        next_base.SetValue(++next_base_len, 1);
+        // right
+        NodesBRD.SetValue(nb, i+1, uv_er[i].node);
+
+        next_par_u.SetValue(next_base_len, uv_el[i].u);
+        next_par_v.SetValue(next_base_len, uv_el[i].v);
+
+        // to stop reducing, if number of nodes reaches nt
+        int delta = curr_base_len - nt;
+
+        //double du = uv_er[i].u - uv_el[i].u;
+        //double dv = uv_er[i].v - uv_el[i].v;
+
+        // to calculate normalized parameter, we must know number of points in next layer
+        int nb_four = (curr_base_len - 1) / 4;
+        int nb_next = nb_four*2 + (curr_base_len - nb_four*4);
+        if (nb_next < nt) nb_next = nt;
+
+        for (j = 1; j + 4 <= curr_base_len && delta > 0; j += 4, delta -= 2) {
+          // add one "HH": nodes a,b,c,d,e and faces 1,2,3,4,5,6
+          //
+          //  .-----a-----b i + 1
+          //  |\ 5  | 6  /|
+          //  | \   |   / |
+          //  |  c--d--e  |
+          //  |1 |2 |3 |4 |
+          //  |  |  |  |  |
+          //  .--.--.--.--. i
+          //
+          //  j     j+2   j+4
+
+          double u,v;
+
+          // a (i + 1, j + 2)
+          const SMDS_MeshNode* Na;
+          next_base_len++;
+          next_base.SetValue(next_base_len, curr_base.Value(j + 2));
+          if (i + 1 == nr) { // top
+            Na = uv_et[next_base_len - 1].node;
+            NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Na);
+            u = uv_et[next_base_len - 1].u;
+            v = uv_et[next_base_len - 1].v;
+          }
+          else {
+            //double norm_par = double(next_base_len - 1)/double(nb_next - 1);
+            //u = uv_el[i].u + du * norm_par;
+            //v = uv_el[i].v + dv * norm_par;
+            {
+              double rel = double(next_base_len - 1) * double(nt - 1) / double(nb_next - 1) + 1;
+              int nearest_node_j = (int)rel;
+              rel -= nearest_node_j;
+              int ij = (i + 1 - 1) * nt + (nearest_node_j - 1);
+              double u1 = quad->uv_grid[ij].u;
+              double v1 = quad->uv_grid[ij].v;
+              double u2 = quad->uv_grid[ij + 1].u;
+              double v2 = quad->uv_grid[ij + 1].v;
+              double duj = (u2 - u1) * rel;
+              double dvj = (v2 - v1) * rel;
+              u = u1 + duj;
+              v = v1 + dvj;
+            }
+            //u = uv_el[i].u + du*npb.Value(curr_base.Value(j + 2));
+            //v = uv_el[i].v + dv*npb.Value(curr_base.Value(j + 2));
+            gp_Pnt P = S->Value(u,v);
+            SMDS_MeshNode* Na1 = meshDS->AddNode(P.X(), P.Y(), P.Z());
+            meshDS->SetNodeOnFace(Na1, geomFaceID, u, v);
+            NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Na1);
+            Na = Na1;
+          }
+          next_par_u.SetValue(next_base_len, u);
+          next_par_v.SetValue(next_base_len, v);
+
+          // b (i + 1, j + 4)
+          const SMDS_MeshNode* Nb;
+          next_base_len++;
+          next_base.SetValue(next_base_len, curr_base.Value(j + 4));
+          if (i + 1 == nr) { // top
+            Nb = uv_et[next_base_len - 1].node;
+            NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nb);
+            u = uv_et[next_base_len - 1].u;
+            v = uv_et[next_base_len - 1].v;
+          }
+          else if (j + 4 == curr_base_len) { // right
+            Nb = NodesBRD.Value(next_base.Value(next_base_len), i + 1);
+            u = uv_er[i].u;
+            v = uv_er[i].v;
+          }
+          else {
+            //double norm_par = double(next_base_len - 1)/double(nb_next - 1);
+            //u = uv_el[i].u + du * norm_par;
+            //v = uv_el[i].v + dv * norm_par;
+            {
+              double rel = double(next_base_len - 1) * double(nt - 1) / double(nb_next - 1) + 1;
+              int nearest_node_j = (int)rel;
+              rel -= nearest_node_j;
+              int ij = (i + 1 - 1) * nt + (nearest_node_j - 1);
+              double u1 = quad->uv_grid[ij].u;
+              double v1 = quad->uv_grid[ij].v;
+              double u2 = quad->uv_grid[ij + 1].u;
+              double v2 = quad->uv_grid[ij + 1].v;
+              double duj = (u2 - u1) * rel;
+              double dvj = (v2 - v1) * rel;
+              u = u1 + duj;
+              v = v1 + dvj;
+            }
+            //u = uv_el[i].u + du*npb.Value(curr_base.Value(j + 4));
+            //v = uv_el[i].v + dv*npb.Value(curr_base.Value(j + 4));
+            gp_Pnt P = S->Value(u,v);
+            SMDS_MeshNode* Nb1 = meshDS->AddNode(P.X(), P.Y(), P.Z());
+            meshDS->SetNodeOnFace(Nb1, geomFaceID, u, v);
+            NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nb1);
+            Nb = Nb1;
+          }
+          next_par_u.SetValue(next_base_len, u);
+          next_par_v.SetValue(next_base_len, v);
+
+          // c
+          u = (curr_par_u.Value(j + 2) + next_par_u.Value(next_base_len - 2)) / 2.0;
+          v = (curr_par_v.Value(j + 2) + next_par_v.Value(next_base_len - 2)) / 2.0;
+          gp_Pnt P = S->Value(u,v);
+          SMDS_MeshNode* Nc = meshDS->AddNode(P.X(), P.Y(), P.Z());
+          meshDS->SetNodeOnFace(Nc, geomFaceID, u, v);
+
+          // d
+          u = (curr_par_u.Value(j + 2) + next_par_u.Value(next_base_len - 1)) / 2.0;
+          v = (curr_par_v.Value(j + 2) + next_par_v.Value(next_base_len - 1)) / 2.0;
+          P = S->Value(u,v);
+          SMDS_MeshNode* Nd = meshDS->AddNode(P.X(), P.Y(), P.Z());
+          meshDS->SetNodeOnFace(Nd, geomFaceID, u, v);
+
+          // e
+          u = (curr_par_u.Value(j + 2) + next_par_u.Value(next_base_len)) / 2.0;
+          v = (curr_par_v.Value(j + 2) + next_par_v.Value(next_base_len)) / 2.0;
+          P = S->Value(u,v);
+          SMDS_MeshNode* Ne = meshDS->AddNode(P.X(), P.Y(), P.Z());
+          meshDS->SetNodeOnFace(Ne, geomFaceID, u, v);
+
+          // Faces
+          SMDS_MeshFace* F1 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j + 0), i),
+                                              NodesBRD.Value(curr_base.Value(j + 1), i),
+                                              Nc,
+                                              NodesBRD.Value(next_base.Value(next_base_len - 2), i + 1));
+          if (F1) meshDS->SetMeshElementOnShape(F1, geomFaceID);
+
+          SMDS_MeshFace* F2 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j + 1), i),
+                                              NodesBRD.Value(curr_base.Value(j + 2), i),
+                                              Nd, Nc);
+          if (F2) meshDS->SetMeshElementOnShape(F2, geomFaceID);
+
+          SMDS_MeshFace* F3 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j + 2), i),
+                                              NodesBRD.Value(curr_base.Value(j + 3), i),
+                                              Ne, Nd);
+          if (F3) meshDS->SetMeshElementOnShape(F3, geomFaceID);
+
+          SMDS_MeshFace* F4 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j + 3), i),
+                                              NodesBRD.Value(curr_base.Value(j + 4), i),
+                                              Nb, Ne);
+          if (F4) meshDS->SetMeshElementOnShape(F4, geomFaceID);
+
+          SMDS_MeshFace* F5 = myTool->AddFace(Nc, Nd, Na,
+                                              NodesBRD.Value(next_base.Value(next_base_len - 2), i + 1));
+          if (F5) meshDS->SetMeshElementOnShape(F5, geomFaceID);
+
+          SMDS_MeshFace* F6 = myTool->AddFace(Nd, Ne, Nb, Na);
+          if (F6) meshDS->SetMeshElementOnShape(F6, geomFaceID);
+        }
+
+        // not reduced side elements (if any)
+        for (; j < curr_base_len; j++) {
+          // f (i + 1, j + 1)
+          const SMDS_MeshNode* Nf;
+          double u,v;
+          next_base.SetValue(++next_base_len, curr_base.Value(j + 1));
+          if (i + 1 == nr) { // top
+            Nf = uv_et[next_base_len - 1].node;
+            NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nf);
+            u = uv_et[next_base_len - 1].u;
+            v = uv_et[next_base_len - 1].v;
+          }
+          else if (j + 1 == curr_base_len) { // right
+            Nf = NodesBRD.Value(next_base.Value(next_base_len), i + 1);
+            u = uv_er[i].u;
+            v = uv_er[i].v;
+          }
+          else {
+            //double norm_par = double(next_base_len - 1)/double(nb_next - 1);
+            //u = uv_el[i].u + du * norm_par;
+            //v = uv_el[i].v + dv * norm_par;
+            {
+              double rel = double(next_base_len - 1) * double(nt - 1) / double(nb_next - 1) + 1;
+              int nearest_node_j = (int)rel;
+              rel -= nearest_node_j;
+              int ij = (i + 1 - 1) * nt + (nearest_node_j - 1);
+              double u1 = quad->uv_grid[ij].u;
+              double v1 = quad->uv_grid[ij].v;
+              double u2 = quad->uv_grid[ij + 1].u;
+              double v2 = quad->uv_grid[ij + 1].v;
+              double duj = (u2 - u1) * rel;
+              double dvj = (v2 - v1) * rel;
+              u = u1 + duj;
+              v = v1 + dvj;
+            }
+            //u = uv_el[i].u + du*npb.Value(curr_base.Value(j + 1));
+            //v = uv_el[i].v + dv*npb.Value(curr_base.Value(j + 1));
+            gp_Pnt P = S->Value(u,v);
+            SMDS_MeshNode* Nf1 = meshDS->AddNode(P.X(), P.Y(), P.Z());
+            meshDS->SetNodeOnFace(Nf1, geomFaceID, u, v);
+            NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nf1);
+            Nf = Nf1;
+          }
+          next_par_u.SetValue(next_base_len, u);
+          next_par_v.SetValue(next_base_len, v);
+          SMDS_MeshFace* F1 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j), i),
+                                              NodesBRD.Value(curr_base.Value(j + 1), i),
+                                              NodesBRD.Value(next_base.Value(next_base_len), i + 1),
+                                              NodesBRD.Value(next_base.Value(next_base_len - 1), i + 1));
+          if (F1) meshDS->SetMeshElementOnShape(F1, geomFaceID);
+        }
+
+        curr_base_len = next_base_len;
+        curr_base = next_base;
+        curr_par_u = next_par_u;
+        curr_par_v = next_par_v;
+        next_base_len = 0;
+      }
+    } // end "tree" simple reduce
+    else {
+      // "linear" simple reduce 4->8->12->16 (3 steps)
+      //
+      //  .---------------.---------------.---------------.---------------. nr
+      //  | \             |             / | \             |             / |
+      //  |     \ .-------.-------. /     |     \ .-------.-------. /     |
+      //  |       |       |       |       |       |       |       |       |
+      //  .-------.-------.-------.-------.-------.-------.-------.-------.
+      //  |      / \      |      / \      |      / \      |      / \      |
+      //  |     /   \.----.----./   \     |     /   \.----.----./   \     | i
+      //  |     /    |    |    |    \     |     /    |    |    |    \     |
+      //  .-----.----.----.----.----.-----.-----.----.----.----.----.-----.
+      //  |     /   / \   |  /  \   \     |     /   / \   |  /  \   \     |
+      //  |    /   /    .-.-.    \   \    |    /   /    .-.-.    \   \    |
+      //  |   /   /    /  |  \    \   \   |   /   /    /  |  \    \   \   |
+      //  .---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---. 1
+      //  1                               j                               nb
+
+      // nt = 5, nb = 7, nr = 4
+      //int delta_all = 2;
+      //int delta_one_col = 6;
+      //int nb_col = 0;
+      //int remainder = 2;
+      //if (remainder > 0) nb_col++;
+      //nb_col = 1;
+      //int free_left = 1;
+      //free_left += 2;
+      //int free_middle = 4;
+
+      int delta_all = nb - nt;
+      int delta_one_col = (nr - 1) * 2;
+      int nb_col = delta_all / delta_one_col;
+      int remainder = delta_all - nb_col * delta_one_col;
+      if (remainder > 0) {
+        nb_col++;
+      }
+      int free_left = ((nt - 1) - nb_col * 2) / 2;
+      free_left += nr - 2;
+      int free_middle = (nr - 2) * 2;
+      if (remainder > 0 && nb_col == 1) {
+        int nb_rows_short_col = remainder / 2;
+        int nb_rows_thrown = (nr - 1) - nb_rows_short_col;
+        free_left -= nb_rows_thrown;
+      }
+
+      // nt = 5, nb = 17, nr = 4
+      //int delta_all = 12;
+      //int delta_one_col = 6;
+      //int nb_col = 2;
+      //int remainder = 0;
+      //int free_left = 2;
+      //int free_middle = 4;
+
+      for (i = 1; i < nr; i++, free_middle -= 2, free_left -= 1) { // layer by layer
+        // left
+        NodesBRD.SetValue(1, i+1, uv_el[i].node);
+        next_base.SetValue(++next_base_len, 1);
+        // right
+        NodesBRD.SetValue(nb, i+1, uv_er[i].node);
+
+        // left
+        next_par_u.SetValue(next_base_len, uv_el[i].u);
+        next_par_v.SetValue(next_base_len, uv_el[i].v);
+
+        // to calculate normalized parameter, we must know number of points in next layer
+        int nb_next = curr_base_len - nb_col * 2;
+        if (remainder > 0 && i > remainder / 2)
+          // take into account short "column"
+          nb_next += 2;
+        if (nb_next < nt) nb_next = nt;
+
+        // not reduced left elements
+        for (j = 1; j <= free_left; j++) {
+          // f (i + 1, j + 1)
+          const SMDS_MeshNode* Nf;
+          double u,v;
+          next_base.SetValue(++next_base_len, curr_base.Value(j + 1));
+          if (i + 1 == nr) { // top
+            Nf = uv_et[next_base_len - 1].node;
+            NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nf);
+            u = uv_et[next_base_len - 1].u;
+            v = uv_et[next_base_len - 1].v;
+          }
+          else {
+            {
+              double rel = double(next_base_len - 1) * double(nt - 1) / double(nb_next - 1) + 1;
+              int nearest_node_j = (int)rel;
+              rel -= nearest_node_j;
+              int ij = (i + 1 - 1) * nt + (nearest_node_j - 1);
+              double u1 = quad->uv_grid[ij].u;
+              double v1 = quad->uv_grid[ij].v;
+              double u2 = quad->uv_grid[ij + 1].u;
+              double v2 = quad->uv_grid[ij + 1].v;
+              double duj = (u2 - u1) * rel;
+              double dvj = (v2 - v1) * rel;
+              u = u1 + duj;
+              v = v1 + dvj;
+            }
+            gp_Pnt P = S->Value(u,v);
+            SMDS_MeshNode* Nf1 = meshDS->AddNode(P.X(), P.Y(), P.Z());
+            meshDS->SetNodeOnFace(Nf1, geomFaceID, u, v);
+            NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nf1);
+            Nf = Nf1;
+          }
+          next_par_u.SetValue(next_base_len, u);
+          next_par_v.SetValue(next_base_len, v);
+          SMDS_MeshFace* F1 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j), i),
+                                              NodesBRD.Value(curr_base.Value(j + 1), i),
+                                              NodesBRD.Value(next_base.Value(next_base_len), i + 1),
+                                              NodesBRD.Value(next_base.Value(next_base_len - 1), i + 1));
+          if (F1) meshDS->SetMeshElementOnShape(F1, geomFaceID);
+        }
+
+        for (int icol = 1; icol <= nb_col; icol++) {
+
+          if (remainder > 0 && icol == nb_col && i > remainder / 2)
+            // stop short "column"
+            break;
+
+          // add one "HH": nodes a,b,c,d,e and faces 1,2,3,4,5,6
+          //
+          //  .-----a-----b i + 1
+          //  |\ 5  | 6  /|
+          //  | \   |   / |
+          //  |  c--d--e  |
+          //  |1 |2 |3 |4 |
+          //  |  |  |  |  |
+          //  .--.--.--.--. i
+          //
+          //  j     j+2   j+4
+
+          double u,v;
+
+          // a (i + 1, j + 2)
+          const SMDS_MeshNode* Na;
+          next_base_len++;
+          next_base.SetValue(next_base_len, curr_base.Value(j + 2));
+          if (i + 1 == nr) { // top
+            Na = uv_et[next_base_len - 1].node;
+            NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Na);
+            u = uv_et[next_base_len - 1].u;
+            v = uv_et[next_base_len - 1].v;
+          }
+          else {
+            {
+              double rel = double(next_base_len - 1) * double(nt - 1) / double(nb_next - 1) + 1;
+              int nearest_node_j = (int)rel;
+              rel -= nearest_node_j;
+              int ij = (i + 1 - 1) * nt + (nearest_node_j - 1);
+              double u1 = quad->uv_grid[ij].u;
+              double v1 = quad->uv_grid[ij].v;
+              double u2 = quad->uv_grid[ij + 1].u;
+              double v2 = quad->uv_grid[ij + 1].v;
+              double duj = (u2 - u1) * rel;
+              double dvj = (v2 - v1) * rel;
+              u = u1 + duj;
+              v = v1 + dvj;
+            }
+            gp_Pnt P = S->Value(u,v);
+            SMDS_MeshNode* Na1 = meshDS->AddNode(P.X(), P.Y(), P.Z());
+            meshDS->SetNodeOnFace(Na1, geomFaceID, u, v);
+            NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Na1);
+            Na = Na1;
+          }
+          next_par_u.SetValue(next_base_len, u);
+          next_par_v.SetValue(next_base_len, v);
+
+          // b (i + 1, j + 4)
+          const SMDS_MeshNode* Nb;
+          next_base_len++;
+          next_base.SetValue(next_base_len, curr_base.Value(j + 4));
+          if (i + 1 == nr) { // top
+            Nb = uv_et[next_base_len - 1].node;
+            NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nb);
+            u = uv_et[next_base_len - 1].u;
+            v = uv_et[next_base_len - 1].v;
+          }
+          else if (j + 4 == curr_base_len) { // right
+            Nb = NodesBRD.Value(next_base.Value(next_base_len), i + 1);
+            u = uv_er[i].u;
+            v = uv_er[i].v;
+          }
+          else {
+            {
+              double rel = double(next_base_len - 1) * double(nt - 1) / double(nb_next - 1) + 1;
+              int nearest_node_j = (int)rel;
+              rel -= nearest_node_j;
+              int ij = (i + 1 - 1) * nt + (nearest_node_j - 1);
+              double u1 = quad->uv_grid[ij].u;
+              double v1 = quad->uv_grid[ij].v;
+              double u2 = quad->uv_grid[ij + 1].u;
+              double v2 = quad->uv_grid[ij + 1].v;
+              double duj = (u2 - u1) * rel;
+              double dvj = (v2 - v1) * rel;
+              u = u1 + duj;
+              v = v1 + dvj;
+            }
+            gp_Pnt P = S->Value(u,v);
+            SMDS_MeshNode* Nb1 = meshDS->AddNode(P.X(), P.Y(), P.Z());
+            meshDS->SetNodeOnFace(Nb1, geomFaceID, u, v);
+            NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nb1);
+            Nb = Nb1;
+          }
+          next_par_u.SetValue(next_base_len, u);
+          next_par_v.SetValue(next_base_len, v);
+
+          // c
+          u = (curr_par_u.Value(j + 2) + next_par_u.Value(next_base_len - 2)) / 2.0;
+          v = (curr_par_v.Value(j + 2) + next_par_v.Value(next_base_len - 2)) / 2.0;
+          gp_Pnt P = S->Value(u,v);
+          SMDS_MeshNode* Nc = meshDS->AddNode(P.X(), P.Y(), P.Z());
+          meshDS->SetNodeOnFace(Nc, geomFaceID, u, v);
+
+          // d
+          u = (curr_par_u.Value(j + 2) + next_par_u.Value(next_base_len - 1)) / 2.0;
+          v = (curr_par_v.Value(j + 2) + next_par_v.Value(next_base_len - 1)) / 2.0;
+          P = S->Value(u,v);
+          SMDS_MeshNode* Nd = meshDS->AddNode(P.X(), P.Y(), P.Z());
+          meshDS->SetNodeOnFace(Nd, geomFaceID, u, v);
+
+          // e
+          u = (curr_par_u.Value(j + 2) + next_par_u.Value(next_base_len)) / 2.0;
+          v = (curr_par_v.Value(j + 2) + next_par_v.Value(next_base_len)) / 2.0;
+          P = S->Value(u,v);
+          SMDS_MeshNode* Ne = meshDS->AddNode(P.X(), P.Y(), P.Z());
+          meshDS->SetNodeOnFace(Ne, geomFaceID, u, v);
+
+          // Faces
+          SMDS_MeshFace* F1 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j + 0), i),
+                                              NodesBRD.Value(curr_base.Value(j + 1), i),
+                                              Nc,
+                                              NodesBRD.Value(next_base.Value(next_base_len - 2), i + 1));
+          if (F1) meshDS->SetMeshElementOnShape(F1, geomFaceID);
+
+          SMDS_MeshFace* F2 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j + 1), i),
+                                              NodesBRD.Value(curr_base.Value(j + 2), i),
+                                              Nd, Nc);
+          if (F2) meshDS->SetMeshElementOnShape(F2, geomFaceID);
+
+          SMDS_MeshFace* F3 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j + 2), i),
+                                              NodesBRD.Value(curr_base.Value(j + 3), i),
+                                              Ne, Nd);
+          if (F3) meshDS->SetMeshElementOnShape(F3, geomFaceID);
+
+          SMDS_MeshFace* F4 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j + 3), i),
+                                              NodesBRD.Value(curr_base.Value(j + 4), i),
+                                              Nb, Ne);
+          if (F4) meshDS->SetMeshElementOnShape(F4, geomFaceID);
+
+          SMDS_MeshFace* F5 = myTool->AddFace(Nc, Nd, Na,
+                                              NodesBRD.Value(next_base.Value(next_base_len - 2), i + 1));
+          if (F5) meshDS->SetMeshElementOnShape(F5, geomFaceID);
+
+          SMDS_MeshFace* F6 = myTool->AddFace(Nd, Ne, Nb, Na);
+          if (F6) meshDS->SetMeshElementOnShape(F6, geomFaceID);
+
+          j += 4;
+
+          // not reduced middle elements
+          if (icol < nb_col) {
+            if (remainder > 0 && icol == nb_col - 1 && i > remainder / 2)
+              // pass middle elements before stopped short "column"
+              break;
+
+            int free_add = free_middle;
+            if (remainder > 0 && icol == nb_col - 1)
+              // next "column" is short
+              free_add -= (nr - 1) - (remainder / 2);
+
+            for (int imiddle = 1; imiddle <= free_add; imiddle++) {
+              // f (i + 1, j + imiddle)
+              const SMDS_MeshNode* Nf;
+              double u,v;
+              next_base.SetValue(++next_base_len, curr_base.Value(j + imiddle));
+              if (i + 1 == nr) { // top
+                Nf = uv_et[next_base_len - 1].node;
+                NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nf);
+                u = uv_et[next_base_len - 1].u;
+                v = uv_et[next_base_len - 1].v;
+              }
+              else if (j + imiddle == curr_base_len) { // right
+                Nf = NodesBRD.Value(next_base.Value(next_base_len), i + 1);
+                u = uv_er[i].u;
+                v = uv_er[i].v;
+              }
+              else {
+                {
+                  double rel = double(next_base_len - 1) * double(nt - 1) / double(nb_next - 1) + 1;
+                  int nearest_node_j = (int)rel;
+                  rel -= nearest_node_j;
+                  int ij = (i + 1 - 1) * nt + (nearest_node_j - 1);
+                  double u1 = quad->uv_grid[ij].u;
+                  double v1 = quad->uv_grid[ij].v;
+                  double u2 = quad->uv_grid[ij + 1].u;
+                  double v2 = quad->uv_grid[ij + 1].v;
+                  double duj = (u2 - u1) * rel;
+                  double dvj = (v2 - v1) * rel;
+                  u = u1 + duj;
+                  v = v1 + dvj;
+                }
+                gp_Pnt P = S->Value(u,v);
+                SMDS_MeshNode* Nf1 = meshDS->AddNode(P.X(), P.Y(), P.Z());
+                meshDS->SetNodeOnFace(Nf1, geomFaceID, u, v);
+                NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nf1);
+                Nf = Nf1;
+              }
+              next_par_u.SetValue(next_base_len, u);
+              next_par_v.SetValue(next_base_len, v);
+              SMDS_MeshFace* F1 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j - 1 + imiddle), i),
+                                                  NodesBRD.Value(curr_base.Value(j + imiddle), i),
+                                                  NodesBRD.Value(next_base.Value(next_base_len), i + 1),
+                                                  NodesBRD.Value(next_base.Value(next_base_len - 1), i + 1));
+              if (F1) meshDS->SetMeshElementOnShape(F1, geomFaceID);
+            }
+            j += free_add;
+          }
+        }
+
+        // not reduced right elements
+        for (; j < curr_base_len; j++) {
+          // f (i + 1, j + 1)
+          const SMDS_MeshNode* Nf;
+          double u,v;
+          next_base.SetValue(++next_base_len, curr_base.Value(j + 1));
+          if (i + 1 == nr) { // top
+            Nf = uv_et[next_base_len - 1].node;
+            NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nf);
+            u = uv_et[next_base_len - 1].u;
+            v = uv_et[next_base_len - 1].v;
+          }
+          else if (j + 1 == curr_base_len) { // right
+            Nf = NodesBRD.Value(next_base.Value(next_base_len), i + 1);
+            u = uv_er[i].u;
+            v = uv_er[i].v;
+          }
+          else {
+            {
+              double rel = double(next_base_len - 1) * double(nt - 1) / double(nb_next - 1) + 1;
+              int nearest_node_j = (int)rel;
+              rel -= nearest_node_j;
+              int ij = (i + 1 - 1) * nt + (nearest_node_j - 1);
+              double u1 = quad->uv_grid[ij].u;
+              double v1 = quad->uv_grid[ij].v;
+              double u2 = quad->uv_grid[ij + 1].u;
+              double v2 = quad->uv_grid[ij + 1].v;
+              double duj = (u2 - u1) * rel;
+              double dvj = (v2 - v1) * rel;
+              u = u1 + duj;
+              v = v1 + dvj;
+            }
+            gp_Pnt P = S->Value(u,v);
+            SMDS_MeshNode* Nf1 = meshDS->AddNode(P.X(), P.Y(), P.Z());
+            meshDS->SetNodeOnFace(Nf1, geomFaceID, u, v);
+            NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nf1);
+            Nf = Nf1;
+          }
+          next_par_u.SetValue(next_base_len, u);
+          next_par_v.SetValue(next_base_len, v);
+          SMDS_MeshFace* F1 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j), i),
+                                              NodesBRD.Value(curr_base.Value(j + 1), i),
+                                              NodesBRD.Value(next_base.Value(next_base_len), i + 1),
+                                              NodesBRD.Value(next_base.Value(next_base_len - 1), i + 1));
+          if (F1) meshDS->SetMeshElementOnShape(F1, geomFaceID);
+        }
+
+        curr_base_len = next_base_len;
+        curr_base = next_base;
+        curr_par_u = next_par_u;
+        curr_par_v = next_par_v;
+        next_base_len = 0;
+      }
+    } // end "linear" simple reduce
+  } // end Simple Reduce implementation
+
+  bool isOk = true;
+  return isOk;
+}
index 74c64f6f087e2aa3c09de93c4f2f93103e013f78..56741ec764f008fdaea8731d81e083a5a9035355 100644 (file)
 //
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-
 //  SMESH SMESH : implementaion of SMESH idl descriptions
 //  File   : StdMeshers_Quadrangle_2D.hxx
 //           Moved here from SMESH_Quadrangle_2D.hxx
 //  Author : Paul RASCLE, EDF
 //  Module : SMESH
 //  $Header$
-//
+
 #ifndef _SMESH_QUADRANGLE_2D_HXX_
 #define _SMESH_QUADRANGLE_2D_HXX_
 
 #include "SMESH_StdMeshers.hxx"
 
+#include "StdMeshers_QuadrangleParams.hxx"
+
 #include "SMESH_2D_Algo.hxx"
 #include "Utils_SALOME_Exception.hxx"
 
@@ -120,6 +121,10 @@ protected:
                              const TopoDS_Face& F, const TopoDS_Edge& E,
                              double first, double last, int nb_segm);
 
+  bool ComputeReduced (SMESH_Mesh& aMesh,
+                       const TopoDS_Shape& aShape,
+                       FaceQuadStruct* quad);
+
   // 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
@@ -130,6 +135,8 @@ protected:
 
   int myTriaVertexID;
 
+  StdMeshers_QuadType myQuadType;
+
   SMESH_MesherHelper* myTool; // tool for working with quadratic elements
 };
 
index 8273990301c52a873bf4ec4360b8aa5fac8dc166..6771e53edc90f14dbdcba2d5e0d7ca8b2dd159be 100644 (file)
@@ -731,6 +731,9 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh &     theMesh,
     double a1 = _value[ BEG_LENGTH_IND ];
     double an = _value[ END_LENGTH_IND ];
     double q  = ( theLength - a1 ) / ( theLength - an );
+    if ( q < theLength/1e6 || 1.01*theLength < a1 + an)
+      return error ( SMESH_Comment("Invalid segment lengths (")<<a1<<" and "<<an<<") "<<
+                     "for an edge of length "<<theLength);
 
     double U1 = theReverse ? l : f;
     double Un = theReverse ? f : l;
@@ -759,6 +762,9 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh &     theMesh,
 
     double a1 = _value[ BEG_LENGTH_IND ];
     double an = _value[ END_LENGTH_IND ];
+    if ( 1.01*theLength < a1 + an)
+      return error ( SMESH_Comment("Invalid segment lengths (")<<a1<<" and "<<an<<") "<<
+                     "for an edge of length "<<theLength);
 
     double  q = ( an - a1 ) / ( 2 *theLength/( a1 + an ) - 1 );
     int n = int(fabs(q) > numeric_limits<double>::min() ? ( 1+( an-a1 )/q ) : ( 1+theLength/a1 ));
@@ -941,6 +947,25 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & t
   if (!idFirst || !idLast)
     return error( COMPERR_BAD_INPUT_MESH, "No node on vertex");
 
+  // remove elements created by e.g. patern mapping (PAL21999)
+  // CLEAN event is incorrectly ptopagated seemingly due to Propagation hyp
+  // so TEMPORARY solution is to clean the submesh manually
+  //theMesh.GetSubMesh(theShape)->ComputeStateEngine( SMESH_subMesh::CLEAN );
+  if (SMESHDS_SubMesh * subMeshDS = meshDS->MeshElements(theShape))
+  {
+    SMDS_ElemIteratorPtr ite = subMeshDS->GetElements();
+    while (ite->more())
+      meshDS->RemoveFreeElement(ite->next(), subMeshDS);
+    SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes();
+    while (itn->more()) {
+      const SMDS_MeshNode * node = itn->next();
+      if ( node->NbInverseElements() == 0 )
+        meshDS->RemoveFreeNode(node, subMeshDS);
+      else
+        meshDS->RemoveNode(node);
+    }
+  }
+
   if (!Curve.IsNull())
   {
     list< double > params;
@@ -982,7 +1007,6 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & t
       parLast = f;
     }
     */
-
     for (list<double>::iterator itU = params.begin(); itU != params.end(); itU++) {
       double param = *itU;
       gp_Pnt P = Curve->Value(param);
index e47134592ee392b86a7ad3a3c0aa3431704fa141..9d9875d14c5759d7a08e6c19ad7d4eea69c8313f 100644 (file)
 #
 #  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 #
-
 #  SMESH StdMeshersGUI : GUI for StdMeshers plugin
 #  File   : Makefile.in
 #  Author : Julia DOROVSKIKH
 #  Modified by : Alexander BORODIN (OCN) - autotools usage
 #  Module : SMESH
-#
+
 include $(top_srcdir)/adm_local/unix/make_common_starter.am
 
 # header files 
@@ -33,12 +32,14 @@ salomeinclude_HEADERS = \
        StdMeshersGUI_DistrTable.h \
        StdMeshersGUI_NbSegmentsCreator.h \
        StdMeshersGUI_ObjectReferenceParamWdg.h \
+       StdMeshersGUI_QuadrangleParamWdg.h \
        StdMeshersGUI_LayerDistributionParamWdg.h \
        StdMeshersGUI_FixedPointsParamWdg.h \
        StdMeshersGUI_SubShapeSelectorWdg.h
 
 # Libraries targets
 lib_LTLIBRARIES = libStdMeshersGUI.la
+
 dist_libStdMeshersGUI_la_SOURCES = \
        StdMeshersGUI.cxx \
        StdMeshersGUI_StdHypothesisCreator.cxx \
@@ -46,6 +47,7 @@ dist_libStdMeshersGUI_la_SOURCES = \
        StdMeshersGUI_DistrTable.cxx \
        StdMeshersGUI_NbSegmentsCreator.cxx \
        StdMeshersGUI_ObjectReferenceParamWdg.cxx \
+       StdMeshersGUI_QuadrangleParamWdg.cxx \
        StdMeshersGUI_LayerDistributionParamWdg.cxx \
        StdMeshersGUI_FixedPointsParamWdg.cxx \
        StdMeshersGUI_SubShapeSelectorWdg.cxx
@@ -56,6 +58,7 @@ MOC_FILES = \
        StdMeshersGUI_DistrTable_moc.cxx \
        StdMeshersGUI_NbSegmentsCreator_moc.cxx \
        StdMeshersGUI_ObjectReferenceParamWdg_moc.cxx \
+       StdMeshersGUI_QuadrangleParamWdg_moc.cxx \
        StdMeshersGUI_LayerDistributionParamWdg_moc.cxx \
        StdMeshersGUI_FixedPointsParamWdg_moc.cxx \
        StdMeshersGUI_SubShapeSelectorWdg_moc.cxx
index f50b1943335a0f686fa876794b07cfe8d43524e6..a66a825524ca86e85e356be78bf2db984ecc1913 100644 (file)
@@ -92,7 +92,7 @@ private:
   QLabel          *myLScale, *myLTable, *myLExpr, *myInfo;
   QGridLayout*     myGroupLayout;
   int              myTableRow, myPreviewRow;
-  QRadioButton*    myCutNeg;
+  //QRadioButton*    myCutNeg;
   QGroupBox*       myReversedEdgesBox;
 
   StdMeshersGUI_SubShapeSelectorWdg*    myDirectionWidget;
diff --git a/src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.cxx b/src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.cxx
new file mode 100644 (file)
index 0000000..ccb38c6
--- /dev/null
@@ -0,0 +1,100 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+//  File   : StdMeshersGUI_QuadrangleParamWdg.cxx
+//  Author : Open CASCADE S.A.S. (jfa)
+//  SMESH includes
+
+#include "StdMeshersGUI_QuadrangleParamWdg.h"
+
+#include "SMESHGUI.h"
+
+#include "SUIT_ResourceMgr.h"
+
+// Qt includes
+#include <QButtonGroup>
+#include <QRadioButton>
+#include <QLabel>
+#include <QGridLayout>
+
+// IDL includes
+#include <SALOMEconfig.h>
+#include CORBA_CLIENT_HEADER(SMESH_BasicHypothesis)
+
+#define SPACING 6
+#define MARGIN 0
+
+//================================================================================
+// function : Constructor
+// purpose  :
+//================================================================================
+StdMeshersGUI_QuadrangleParamWdg::StdMeshersGUI_QuadrangleParamWdg (QWidget * parent)
+  : QWidget(parent),
+    myType(0)
+{
+  myType = new QButtonGroup (this);
+
+  QGridLayout* typeLay = new QGridLayout( this );
+
+  typeLay->setMargin(MARGIN);
+  typeLay->setSpacing(SPACING);
+
+  QString aTypeKey ("SMESH_QUAD_TYPE_%1");
+  QString aPictKey ("ICON_StdMeshers_Quadrangle_Params_%1");
+
+  int itype = 0;
+  for (; itype < int(StdMeshers::QUAD_NB_TYPES); itype++) {
+    QRadioButton* rbi = new QRadioButton (tr(aTypeKey.arg(itype).toLatin1()), this);
+    QPixmap pmi (SMESHGUI::resourceMgr()->loadPixmap("SMESH", tr(aPictKey.arg(itype).toLatin1())));
+    QLabel* pli = new QLabel (this);
+    pli->setPixmap(pmi);
+    typeLay->addWidget(rbi, itype, 0, 1, 1);
+    typeLay->addWidget(pli, itype, 1, 1, 1);
+    myType->addButton(rbi, itype);
+  }
+  myType->button(0)->setChecked(true);
+
+  setLayout(typeLay);
+  setMinimumWidth(300);
+}
+
+//================================================================================
+// function : Destructor
+// purpose  :
+//================================================================================
+StdMeshersGUI_QuadrangleParamWdg::~StdMeshersGUI_QuadrangleParamWdg()
+{
+}
+
+//=================================================================================
+// function : SetType
+// purpose  :
+//=================================================================================
+void StdMeshersGUI_QuadrangleParamWdg::SetType (int theType)
+{
+  myType->button(theType)->setChecked(true);
+}
+
+//=================================================================================
+// function : GetType
+// purpose  :
+//=================================================================================
+int StdMeshersGUI_QuadrangleParamWdg::GetType()
+{
+  return myType->checkedId();
+}
diff --git a/src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.h b/src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.h
new file mode 100644 (file)
index 0000000..2d5abdc
--- /dev/null
@@ -0,0 +1,49 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+//  File   : StdMeshersGUI_QuadrangleParamWdg.h
+//  Author : Open CASCADE S.A.S. (jfa)
+
+#ifndef STDMESHERSGUI_QUADRANGLEPARAMWDG_H
+#define STDMESHERSGUI_QUADRANGLEPARAMWDG_H
+
+// SMESH includes
+#include "SMESH_StdMeshersGUI.hxx"
+
+// Qt includes
+#include <QWidget>
+
+class QButtonGroup;
+
+class STDMESHERSGUI_EXPORT StdMeshersGUI_QuadrangleParamWdg : public QWidget
+{
+  Q_OBJECT
+
+public:
+  StdMeshersGUI_QuadrangleParamWdg (QWidget* parent = 0);
+  ~StdMeshersGUI_QuadrangleParamWdg();
+
+  void SetType (int theType);
+  int  GetType ();
+
+private:
+  // Quadranle preference, Triangle preference, Reduced
+  QButtonGroup* myType;
+};
+
+#endif // STDMESHERSGUI_QUADRANGLEPARAMWDG_H
index 156f2133ea157f7a38718c95842632dfad00e951..3e8d13ee2d34aced898364f3030df63b56c1a9b4 100644 (file)
 //
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
+//  File   : StdMeshersGUI_StdHypothesisCreator.cxx
+//  Author : Alexander SOLOVYOV, Open CASCADE S.A.S.
+//  SMESH includes
 
-// File   : StdMeshersGUI_StdHypothesisCreator.cxx
-// Author : Alexander SOLOVYOV, Open CASCADE S.A.S.
-// SMESH includes
-//
 #include "StdMeshersGUI_StdHypothesisCreator.h"
 
 #include <SMESHGUI.h>
 #include <SMESHGUI_SpinBox.h>
 #include <SMESHGUI_HypothesesUtils.h>
 #include <SMESHGUI_Utils.h>
+
 #include <SMESH_TypeFilter.hxx>
 #include <SMESH_NumberFilter.hxx>
-#include "StdMeshersGUI_ObjectReferenceParamWdg.h"
+
+#include "StdMeshersGUI_FixedPointsParamWdg.h"
 #include "StdMeshersGUI_LayerDistributionParamWdg.h"
+#include "StdMeshersGUI_ObjectReferenceParamWdg.h"
+#include "StdMeshersGUI_QuadrangleParamWdg.h"
 #include "StdMeshersGUI_SubShapeSelectorWdg.h"
-#include "StdMeshersGUI_FixedPointsParamWdg.h"
+
 #include <SALOMEDSClient_Study.hxx>
 
 // SALOME GUI includes
@@ -387,9 +390,11 @@ bool StdMeshersGUI_StdHypothesisCreator::checkParams( QString& msg ) const
   }
   else if ( hypType() == "QuadrangleParams" )
   {
-    StdMeshersGUI_SubShapeSelectorWdg* w = 
-      widget< StdMeshersGUI_SubShapeSelectorWdg >( 0 );
-    ok = ( w->GetListSize() > 0 );
+    //StdMeshersGUI_SubShapeSelectorWdg* w =
+    //  widget< StdMeshersGUI_SubShapeSelectorWdg >( 0 );
+    //ok = ( w->GetListSize() > 0 );
+    //StdMeshersGUI_QuadrangleParamWdg* w =
+    //  widget< StdMeshersGUI_QuadrangleParamWdg >( 1 );
   }
   return ok;
 }
@@ -608,14 +613,17 @@ QString StdMeshersGUI_StdHypothesisCreator::storeParams() const
     {
       StdMeshers::StdMeshers_QuadrangleParams_var h =
         StdMeshers::StdMeshers_QuadrangleParams::_narrow( hypothesis() );
-      StdMeshersGUI_SubShapeSelectorWdg* w = 
+      StdMeshersGUI_SubShapeSelectorWdg* w1 =
         widget< StdMeshersGUI_SubShapeSelectorWdg >( 0 );
-      if (w) {
-        if( w->GetListSize() > 0 ) {
-          h->SetTriaVertex( w->GetListOfIDs()[0] ); // getlist must be called once
-          const char * entry = w->GetMainShapeEntry();
-          h->SetObjectEntry( entry );
+      StdMeshersGUI_QuadrangleParamWdg* w2 =
+        widget< StdMeshersGUI_QuadrangleParamWdg >( 1 );
+      if (w1 && w2) {
+        if (w1->GetListSize() > 0) {
+          h->SetTriaVertex(w1->GetListOfIDs()[0]); // getlist must be called once
+          const char * entry = w1->GetMainShapeEntry();
+          h->SetObjectEntry(entry);
         }
+        h->SetQuadType(StdMeshers::QuadType(w2->GetType()));
       }
     }
   }
@@ -984,13 +992,13 @@ bool StdMeshersGUI_StdHypothesisCreator::stdParams( ListOfStdParams& p ) const
     customWidgets()->append( newObjRefParamWdg( filterForShapeOfDim( 0 ),
                                                h->GetTargetVertex( 2 )));
   }
-  else if( hypType()=="QuadrangleParams" )
+  else if (hypType() == "QuadrangleParams")
   {
     StdMeshers::StdMeshers_QuadrangleParams_var h =
-      StdMeshers::StdMeshers_QuadrangleParams::_narrow( hyp );
+      StdMeshers::StdMeshers_QuadrangleParams::_narrow(hyp);
 
-    item.myName = tr( "SMESH_BASE_VERTEX" );
-    p.append( item );
+    item.myName = tr("SMESH_BASE_VERTEX");
+    p.append(item);
 
     StdMeshersGUI_SubShapeSelectorWdg* aDirectionWidget =
       new StdMeshersGUI_SubShapeSelectorWdg();
@@ -998,21 +1006,32 @@ bool StdMeshersGUI_StdHypothesisCreator::stdParams( ListOfStdParams& p ) const
     aDirectionWidget->SetSubShType(TopAbs_VERTEX);
     QString anEntry = SMESHGUI_GenericHypothesisCreator::getShapeEntry();
     QString aMainEntry = SMESHGUI_GenericHypothesisCreator::getMainShapeEntry();
-    if ( anEntry == "" )
+    if (anEntry == "")
       anEntry = h->GetObjectEntry();
-    aDirectionWidget->SetGeomShapeEntry( anEntry );
-    aDirectionWidget->SetMainShapeEntry( aMainEntry );
-    if ( !isCreation() ) {
+    aDirectionWidget->SetGeomShapeEntry(anEntry);
+    aDirectionWidget->SetMainShapeEntry(aMainEntry);
+    if (!isCreation()) {
       SMESH::long_array_var aVec = new SMESH::long_array;
       int vertID = h->GetTriaVertex();
-      if(vertID>0) {
+      if (vertID > 0) {
         aVec->length(1);
         aVec[0] = vertID;
-        aDirectionWidget->SetListOfIDs( aVec );
+        aDirectionWidget->SetListOfIDs(aVec);
       }
     }
-    aDirectionWidget->showPreview( true );
-    customWidgets()->append ( aDirectionWidget );
+    aDirectionWidget->showPreview(true);
+
+    item.myName = tr("SMESH_QUAD_TYPE");
+    p.append(item);
+
+    StdMeshersGUI_QuadrangleParamWdg* aTypeWidget =
+      new StdMeshersGUI_QuadrangleParamWdg();
+    if (!isCreation()) {
+      aTypeWidget->SetType(int(h->GetQuadType()));
+    }
+
+    customWidgets()->append(aDirectionWidget);
+    customWidgets()->append(aTypeWidget);
   }
   else
     res = false;
@@ -1217,6 +1236,13 @@ bool StdMeshersGUI_StdHypothesisCreator::getParamFromCustomWidget( StdParam & pa
     param.myValue = w->GetValue();
     return true;
   }
+  if ( widget->inherits( "StdMeshersGUI_QuadrangleParamWdg" ))
+  {
+    //const StdMeshersGUI_QuadrangleParamWdg * w =
+    //  static_cast<const StdMeshersGUI_QuadrangleParamWdg*>( widget );
+    param.myValue = "QuadType";
+    return true;
+  }
   if ( widget->inherits( "StdMeshersGUI_FixedPointsParamWdg" ))
   {
     const StdMeshersGUI_FixedPointsParamWdg * w =
index da9130846c431ea9119f200bdbe814dd2cd95cb6..927a4c09bb48a0363cafed5185084f61186d028c 100644 (file)
             <source>ICON_DLG_PROJECTION_SOURCE_3D</source>
             <translation>mesh_hypo_source_3d.png</translation>
         </message>
+        <message>
+            <source>ICON_DLG_QUADRANGLE_PARAMS</source>
+            <translation>mesh_hypo_length.png</translation>
+        </message>
         <message>
             <source>ICON_DLG_SEGMENT_LENGTH_AROUND_VERTEX</source>
             <translation>mesh_hypo_length.png</translation>
             <source>ICON_SMESH_TREE_HYPO_StartEndLength</source>
             <translation>mesh_tree_hypo_length.png</translation>
         </message>
+    </context>
+    <context>
+        <name>StdMeshersGUI_QuadrangleParamWdg</name>
         <message>
-            <source>ICON_DLG_QUADRANGLE_PARAMS</source>
-            <translation>mesh_hypo_length.png</translation>
+            <source>ICON_StdMeshers_Quadrangle_Params_0</source>
+            <translation>mesh_quadrangle_standard.png</translation>
+        </message>
+        <message>
+            <source>ICON_StdMeshers_Quadrangle_Params_1</source>
+            <translation>mesh_quadrangle_triapref.png</translation>
+        </message>
+        <message>
+            <source>ICON_StdMeshers_Quadrangle_Params_2</source>
+            <translation>mesh_quadrangle_quadpref.png</translation>
+        </message>
+        <message>
+            <source>ICON_StdMeshers_Quadrangle_Params_3</source>
+            <translation>mesh_quadrangle_quadpref_reversed.png</translation>
+        </message>
+        <message>
+            <source>ICON_StdMeshers_Quadrangle_Params_4</source>
+            <translation>mesh_quadrangle_reduced.png</translation>
         </message>
     </context>
 </TS>
index 228cc7a58ace7efe997ad91b673b42749a6df842..c04916750f3d1a12bf4d4d23cf1320948fc717a8 100644 (file)
         <source>SMESH_QUADRANGLE_PARAMS_TITLE</source>
         <translation>Hypothesis Construction</translation>
     </message>
+    <message>
+        <source>SMESH_QUAD_TYPE</source>
+        <translation>Type</translation>
+    </message>
+</context>
+<context>
+    <name>StdMeshersGUI_QuadrangleParamWdg</name>
+    <message>
+        <source>SMESH_QUAD_TYPE_0</source>
+        <translation>Standard</translation>
+    </message>
+    <message>
+        <source>SMESH_QUAD_TYPE_1</source>
+        <translation>Triangle preference</translation>
+    </message>
+    <message>
+        <source>SMESH_QUAD_TYPE_2</source>
+        <translation>Quadrangle preference</translation>
+    </message>
+    <message>
+        <source>SMESH_QUAD_TYPE_3</source>
+        <translation>Quadrangle preference (reversed)</translation>
+    </message>
+    <message>
+        <source>SMESH_QUAD_TYPE_4</source>
+        <translation>Reduced</translation>
+    </message>
 </context>
 <context>
     <name>StdMeshersGUI_LayerDistributionParamWdg</name>
index 612ccc9eefd0166ce97dd84fc856e42f7a738c15..85295c055e8b763193b07299da118087e30c7af1 100644 (file)
 //
 //  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_QuadrangleParams_i.cxx
 //  Author : Sergey KUUL, OCC
 //  Module : SMESH
-//  $Header$
-//
+
 #include "StdMeshers_QuadrangleParams_i.hxx"
 #include "SMESH_Gen_i.hxx"
 #include "SMESH_Gen.hxx"
@@ -94,6 +92,21 @@ void StdMeshers_QuadrangleParams_i::SetTriaVertex(CORBA::Long vertID)
       << vertID << " )";
 }
 
+//=============================================================================
+/*!
+ *  StdMeshers_QuadrangleParams_i::GetTriaVertex
+ *
+ *  Get base vertex for triangles
+ */
+//=============================================================================
+
+CORBA::Long StdMeshers_QuadrangleParams_i::GetTriaVertex()
+{
+  MESSAGE( "StdMeshers_QuadrangleParams_i::GetTriaVertex" );
+  ASSERT( myBaseImpl );
+  return this->GetImpl()->GetTriaVertex();
+}
+
 //=============================================================================
 /*!
  *  StdMeshers_QuadrangleParams_i::SetObjectEntry
@@ -143,17 +156,65 @@ char* StdMeshers_QuadrangleParams_i::GetObjectEntry()
 
 //=============================================================================
 /*!
- *  StdMeshers_QuadrangleParams_i::GetTriaVertex
+ *  StdMeshers_QuadrangleParams_i::SetQuadType
  *
- *  Get base vertex for triangles
+ *  Set the type of quadrangulation
  */
 //=============================================================================
+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"};
 
-CORBA::Long StdMeshers_QuadrangleParams_i::GetTriaVertex()
+  MESSAGE("StdMeshers_QuadrangleParams_i::SetQuadType");
+  ASSERT(myBaseImpl);
+
+  if (int(type) >= int(StdMeshers::QUAD_NB_TYPES)) {
+    THROW_SALOME_CORBA_EXCEPTION("Bad type of quadrangulation", SALOME::BAD_PARAM);
+  }
+
+  try {
+    this->GetImpl()->SetQuadType(StdMeshers_QuadType(int(type)));
+  }
+  catch (SALOME_Exception& S_ex) {
+    THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
+  }
+
+  // Update Python script
+  const char* quadType;
+  switch (type) {
+  case StdMeshers::QUAD_STANDARD:
+    quadType = "StdMeshers.QUAD_STANDARD"; break;
+  case StdMeshers::QUAD_TRIANGLE_PREF:
+    quadType = "StdMeshers.QUAD_TRIANGLE_PREF"; break;
+  case StdMeshers::QUAD_QUADRANGLE_PREF:
+    quadType = "StdMeshers.QUAD_QUADRANGLE_PREF"; break;
+  case StdMeshers::QUAD_QUADRANGLE_PREF_REVERSED:
+    quadType = "StdMeshers.QUAD_QUADRANGLE_PREF_REVERSED"; break;
+  case StdMeshers::QUAD_REDUCED:
+    quadType = "StdMeshers.QUAD_REDUCED"; break;
+  default:
+    quadType = "UNKNOWN";
+  }
+  SMESH::TPythonDump() << _this() << ".SetQuadType( " << quadType << " )";
+  //SMESH::TPythonDump() << _this() << ".SetQuadType( " << quadTypes[int(type)] << " )";
+}
+
+//=============================================================================
+/*!
+ *  StdMeshers_QuadrangleParams_i::GetQuadType
+ *
+ *  Get the type of quadrangulation
+ */
+//=============================================================================
+StdMeshers::QuadType StdMeshers_QuadrangleParams_i::GetQuadType()
 {
-  MESSAGE( "StdMeshers_QuadrangleParams_i::GetTriaVertex" );
-  ASSERT( myBaseImpl );
-  return this->GetImpl()->GetTriaVertex();
+  MESSAGE("StdMeshers_QuadrangleParams_i::GetQuadType");
+  ASSERT(myBaseImpl);
+  return StdMeshers::QuadType(int(this->GetImpl()->GetQuadType()));
 }
 
 //=============================================================================
@@ -183,4 +244,3 @@ CORBA::Boolean StdMeshers_QuadrangleParams_i::IsDimSupported( SMESH::Dimension t
 {
   return type == SMESH::DIM_2D;
 }
-
index fa695107deb513945fe01eac85f2733dc63d32b8..062af680d0f7f85cfaa4059ac3fefc4f5759405e 100644 (file)
 //
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-
-//  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
+//  SMESH SMESH_I : idl implementation based on 'SMESH' unit's classes
 //  File   : StdMeshers_QuadrangleParams_i.hxx
 //  Author : Sergey KUUL, OCC
 //  Module : SMESH
 //  $Header$
-//
+
 #ifndef _SMESH_QUADRANGLEPARAMS_I_HXX_
 #define _SMESH_QUADRANGLEPARAMS_I_HXX_
 
@@ -43,9 +42,9 @@ class STDMESHERS_I_EXPORT StdMeshers_QuadrangleParams_i:
 {
 public:
   // Constructor
-  StdMeshers_QuadrangleParams_iPortableServer::POA_ptr thePOA,
+  StdMeshers_QuadrangleParams_i (PortableServer::POA_ptr thePOA,
                                  int                     theStudyId,
-                                 ::SMESH_Gen*            theGenImpl );
+                                 ::SMESH_Gen*            theGenImpl);
   // Destructor
   virtual ~StdMeshers_QuadrangleParams_i();
 
@@ -56,18 +55,24 @@ public:
   // Get length
   //CORBA::Double GetLength(CORBA::Boolean theIsStart);
 
-  //Set base vertex for triangles
-  void SetTriaVertex(CORBA::Long vertID);
+  // Set base vertex for triangles
+  void SetTriaVertex (CORBA::Long vertID);
 
-  //Get base vertex for triangles
+  // Get base vertex for triangles
   CORBA::Long GetTriaVertex();
   
-  //Set the Entry of the Object
-  void SetObjectEntry(const char* theEntry);
+  // Set the Entry of the Object
+  void SetObjectEntry (const char* theEntry);
 
-  //Get Object Entry
+  // Get Object Entry
   char* GetObjectEntry();
 
+  // Set the type of quadrangulation
+  void SetQuadType (StdMeshers::QuadType type);
+
+  // Get the type of quadrangulation
+  StdMeshers::QuadType GetQuadType();
+
   // Get implementation
   ::StdMeshers_QuadrangleParams* GetImpl();