Salome HOME
Merge from V6_3_BR 15/07/2011
authorvsr <vsr@opencascade.com>
Fri, 15 Jul 2011 11:19:53 +0000 (11:19 +0000)
committervsr <vsr@opencascade.com>
Fri, 15 Jul 2011 11:19:53 +0000 (11:19 +0000)
42 files changed:
configure.ac
doc/salome/gui/SMESH/doxyfile_py.in
doc/salome/gui/SMESH/images/2d_from_3d_dlg.png
doc/salome/gui/SMESH/input/additional_hypo.doc
doc/salome/gui/SMESH/input/blsurf_hypo.doc
doc/salome/gui/SMESH/input/constructing_meshes.doc
doc/salome/gui/SMESH/input/convert_to_from_quadratic_mesh.doc
doc/salome/gui/SMESH/input/cut_mesh_by_plane.doc
doc/salome/gui/SMESH/input/generate_flat_elements.doc
doc/salome/gui/SMESH/input/make_2dmesh_from_3d.doc
doc/salome/gui/SMESH/input/over_constrained_faces.doc
doc/salome/gui/SMESH/input/over_constrained_volumes.doc
doc/salome/gui/SMESH/input/smeshpy_interface.doc
doc/salome/gui/SMESH/input/tui_defining_ghs3d_hypotheses.doc
doc/salome/gui/SMESH/input/tui_generate_flat_elements.doc
doc/salome/gui/SMESH/static/header.html [deleted file]
doc/salome/gui/SMESH/static/header_py.html.in [new file with mode: 0644]
idl/SMESH_Mesh.idl
src/MEFISTO2/aptrte.cxx
src/MEFISTO2/trte.f
src/SMDS/Makefile.am
src/SMDS/SMDS_MeshElementIDFactory.cxx
src/SMDS/SMDS_MeshNode.hxx
src/SMDS/SMDS_VolumeTool.cxx
src/SMDS/SMDS_VolumeTool.hxx
src/SMESH/SMESH_Algo.cxx
src/SMESH/SMESH_MeshEditor.cxx
src/SMESH/SMESH_MesherHelper.cxx
src/SMESHGUI/SMESHGUI.cxx
src/SMESHGUI/SMESHGUI_Filter.cxx
src/SMESHGUI/SMESHGUI_Make2DFrom3DOp.cxx
src/SMESHGUI/SMESHGUI_Make2DFrom3DOp.h
src/SMESHGUI/SMESHGUI_MergeDlg.cxx
src/SMESHGUI/SMESH_msg_en.ts
src/SMESH_I/SMESH_Gen_i_1.cxx
src/SMESH_I/SMESH_Group_i.cxx
src/SMESH_I/SMESH_MeshEditor_i.cxx
src/SMESH_I/SMESH_subMesh_i.cxx
src/SMESH_SWIG/smeshDC.py
src/StdMeshers/StdMeshers_MEFISTO_2D.cxx
src/StdMeshers/StdMeshers_Quadrangle_2D.cxx
src/StdMeshers/StdMeshers_ViscousLayers.cxx

index 0548d07ca842cf03b57bfb91d54eebec9d12ecbc..22154ba84ee0abd6174a21a339f3905628fb967a 100644 (file)
@@ -24,7 +24,7 @@
 # Modified by : Alexander BORODIN (OCN) - autotools usage
 # Created from configure.in.base
 #
-AC_INIT([Salome2 Project SMESH module], [6.3.0], [webmaster.salome@opencascade.com], [SalomeSMESH])
+AC_INIT([Salome2 Project SMESH module], [6.3.1], [webmaster.salome@opencascade.com], [SalomeSMESH])
 AC_CONFIG_AUX_DIR(adm_local/unix/config_files)
 AC_CANONICAL_HOST
 AC_CANONICAL_TARGET
@@ -481,6 +481,7 @@ AC_OUTPUT([ \
   doc/salome/gui/SMESH/doxyfile \
   doc/salome/gui/SMESH/doxyfile_py \
   doc/salome/gui/SMESH/static/header.html \
+  doc/salome/gui/SMESH/static/header_py.html \
   doc/salome/tui/Makefile \
   doc/salome/tui/doxyfile \
   doc/salome/tui/static/header.html \
index 24803a00a3f3bd325c5c48f51bc724ad3746bc98..94359dfd57727d36aab4740f0b776eec89f31faa 100755 (executable)
@@ -110,7 +110,7 @@ EXAMPLE_PATH      = @top_srcdir@/src/SMESH_SWIG
 #---------------------------------------------------------------------------
 GENERATE_HTML     = YES
 HTML_OUTPUT       = smeshpy_doc
-HTML_HEADER       = @builddir@/static/header.html
+HTML_HEADER       = @builddir@/static/header_py.html
 HTML_FOOTER       = @srcdir@/static/footer.html
 HTML_STYLESHEET   = @srcdir@/static/doxygen.css
 TOC_EXPAND        = YES
index 4a839e89e23143881a7dd6eb1ed0137add1b8459..e0c8ca5cfd9f6b67a4112e5ab440357a2f09579d 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/2d_from_3d_dlg.png and b/doc/salome/gui/SMESH/images/2d_from_3d_dlg.png differ
index 12aa8a261bf0912e004b4222490c1b4954277fa5..0ad7382309ed0dfdacf224254e19e96c6994ab60 100644 (file)
@@ -44,7 +44,7 @@ segments on all four sides of the face must be even (divisible by 2).
 \anchor viscous_layers_anchor
 <h2>Viscous Layers</h2>
 
-<b>Viscous Layers</b> additional hypotheses can be used together with
+<b>Viscous Layers</b> additional hypothesis can be used together with
 several 3D algorithms: NETGEN 3D, GHS3D and Hexahedron(i,j,k). This
 hypothesis allows creation of layers of highly stretched prisms near
 mesh boundary, which is beneficial for high quality viscous
@@ -56,13 +56,13 @@ actually the hexahedrons.
 
 <ul>
 <li><b>Name</b> - allows to define the name of the hypothesis.</li>
-<li><b>Total thicknes</b> - gives total thickness of layers of prisms.</li>
-<li><b>Number of layers</b> - defines number of layers of prisms.</li>
-<li><b>Stretch factor</b> - defines factor of growth of height of
-prisms from the mesh boundary towards inside of mesh.</li>
+<li><b>Total thicknes</b> - gives the total thickness of prism layers.</li>
+<li><b>Number of layers</b> - defines the number of prism layers.</li>
+<li><b>Stretch factor</b> - defines the growth factor of prism height
+from the mesh boundary inwards.</li>
 <li><b>Faces without layers</b> - defines geometrical faces on which
-layers of prisms should not be constructed. By default the layers of
-prisms are not constructed on geometrical faces shared by solids.</li>
+prism layers should not be constructed. By default the prism layers
+are not constructed on geometrical faces shared by solids.</li>
 </ul>
 
 \image html viscous_layers_mesh.png A group containing viscous layer prisms.
index 99ea78e09c328f14ada65d97573148db1449c876..795fbb974a594ebdf9049720f982da84e52f1daa 100644 (file)
@@ -247,38 +247,56 @@ In order to compute the mean of several values, the arithmetic mean is used by d
 More specific size maps can be defined on faces. 
 
 <ul>
-<li> <i> Attractors </i> allow to define the size of the mesh elements on a face so that the mesh is the finest on the attractor shape and becomes coarser when getting far from this shape.
+<li> <i> Attractors </i> allow to define the size of the mesh elements
+on a face so that the mesh is the finest on the attractor shape and
+becomes coarser when getting far from this shape.
 <ul> 
-<li> The selected attractor can be a Vertex, an Edge, a Wire or a Compound mixing several entities of those types.</li>
+<li> The selected attractor can be a Vertex, an Edge, a Wire or a
+Compound mixing several entities of those types.</li>
 <li> The attractor doesn't have to be a sub-shape of the shape to mesh.</li>
-<li> The size will grow exponentially (see formula below) but is bounded by gradation, \n so if you want the formula to be strictly respected, you should set the <i>gradation</i> 
+<li> The size will grow exponentially (see the formula below) but is
+bounded by gradation, \n so if you want the formula to be strictly
+respected, you should set the <i>gradation</i> 
 to its maximum (2.5) in the <i>arguments</i> tab. 
 </ul>
 \n
-<li> Furthermore you can choose to <i> keep the size constant </i> until a certain distance from a shape. This option can be combined or not with an <i>attractor</i> size map described above. 
+<li> Furthermore you can choose to <i> keep the size constant </i>
+until a certain distance from a shape. This option can be combined or
+not with an <i>attractor</i> size map described above. 
 <ul>
-<li> If the two options are combined the size will remain constant until the distant specified in "constant over" and grow then as prescribed by the attractor function.</li>
-<li> Else the growing is only controled by the standard arguments of BLSURF (gradation ...).</li>
+<li> If the two options are combined the size will remain constant
+until the distance specified in "constant over" and grow then as
+prescribed by the attractor function.</li>
+<li> Else the growing is only controled by the standard arguments of
+BLSURF (gradation ...).</li>
 </ul>
 </ul>
 
-\image html blsurf_attractors2.png "Example of mesh created using attractors, the attractors here are the side edges and the size grow from the side of the surface towards the apex"
+\image html blsurf_attractors2.png "Example of mesh created using
+attractors, the attractors here are the side edges and the size grows
+from the side of the surface towards the apex"
 \n
-\image html blsurf_const_size_near_shape2.png "Example of size map with constant size option, the size is kept constant on the left side of the surface until a certain distance"
+\image html blsurf_const_size_near_shape2.png "Example of size map
+with constant size option, the size is kept constant on the left side
+of the surface until a certain distance"
 \n
-Remark : The validation of the hypothesis might take a few seconds if attractors are defined or the "constant size" option is used because a map of distances has to be built on the whole surface for each face where such an hypothesis has been defined.
+Remark : The validation of the hypothesis might take a few seconds if
+attractors are defined or the "constant size" option is used because a
+map of distances has to be built on the whole surface for each face
+where such a hypothesis has been defined.
 
 <br><b>See Also</b> a sample TUI Script of the \ref tui_blsurf "creation of a BLSurf hypothesis", including size map.
 
 \anchor blsurf_attractor_computation
 <h2>Computation of attractors</h2>
 \n
-The size grow exponentially following the equation : h(d) = User size + (h_start - User Size) * exp( -(d / R)^2  ).
+The size grows exponentially following the equation : h(d) = User size + (h_start - User Size) * exp( -(d / R)^2  ).
 \n
 Where :
 <ul>
 <li>h_start is the desired size on the given attractor shape</li>
-<li>d is the distance of the current point from the attractor shape. The distance is the geodesic distance (i.e. calculated by following the surface to be meshed) </li>
+<li>d is the distance of the current point from the attractor
+shape. The distance is the geodesic distance (i.e. calculated by following the surface to be meshed) </li>
 <li>R is called the distance of influence and allows controlling the growth rate of the mesh </li>
 </ul>
 
index 6ceaba3ac0504c6cbde28c6ec045be0168cadd6c..5f746699822df6efa4e1f687fa52731c551effde 100644 (file)
@@ -52,7 +52,7 @@ The use of additional hypotheses is optional (i.e. you may leave
 Proceed in the same way with 2d and 3d Algorithms and Hypotheses, note
 that the choice of hypotheses depends on the algorithm. There must be
 one Algorithm and zero or several Hypotheses for each dimension of your
-object (most of the standard 2D and 3D algorithms can work without
+object (most standard 2D and 3D algorithms can work without
 hypotheses using some default parameters), 
 otherwise you will not get any mesh at all. Of course, if you
 wish to mesh a face, which is a 2d object, you don't need to define 3d
@@ -74,11 +74,11 @@ algorithms applied to the construction of the mesh.</li>
 There is an alternative way to create a mesh on an object simply by
 clicking <b>Assign a set of hypotheses</b> button and selecting among
 pre-defined sets of hypotheses. In addition to the standard
-sets of hypotheses, one can create his own sets by creating
+sets of hypotheses, it is possible to create custom sets by editing
 CustomMeshers.xml file located in the home directory. CustomMeshers.xml
-file must describe sets of hypotheses the
+file must describe sets of hypotheses in the
 same way as ${SMESH_ROOT_DIR}/share/salome/resources/smesh/StdMeshers.xml 
-file does (hypotheses sets are enclosed between <hypotheses-set-group>
+file does (sets of hypotheses are enclosed between <hypotheses-set-group>
 tags).
 \image html hypo_sets.png
 <center>List of sets of hypotheses: <em>[custom]</em> is automatically added to the sets defined
index dd1b71e44699214d0e3576af959f851b288494d7..66f850664e8625b54b175f16f303844b25d9d7c3 100644 (file)
@@ -2,11 +2,11 @@
 
 \page convert_to_from_quadratic_mesh_page Convert to/from Quadratic Mesh
 
-\n This functionality allows you to transtorm standard meshes (or
-sum-mesh) to quadratic and vice versa. 
+\n This functionality allows transforming standard meshes (or
+sub-meshes) to quadratic and vice versa. 
 See \ref adding_quadratic_elements_page "Adding quadratic elements" 
 for more information about quadratic meshes.
-Note that conversion of the sub-mesh most probably will
+Note that conversion of a sub-mesh most probably will
 produce a non-conformal mesh. Elements on the boundary between
 quadratic and linear sub-meshes become (or remain) quadratic.
 
@@ -14,8 +14,8 @@ quadratic and linear sub-meshes become (or remain) quadratic.
 <ol>
 <li>Select a mesh or a sub-mesh in the Object Browser or in the
 Viewer.</li>
-<li>From the Modification menu choose the Convert to/from Quadratic
-Mesh item, or click <em>"Convert to/from quadratic"</em> button in the
+<li>From the Modification menu choose <b> Convert to/from Quadratic
+Mesh item </b>, or click <em>"Convert to/from quadratic"</em> button in the
 toolbar.
 
 \image html image154.png
@@ -26,18 +26,17 @@ The following dialog box will appear:
 \image html convert.png
 
 </li>
-<li>In this dialog box you should specify:
+<li>In this dialog box specify:
 
 <ul>
-<li>if you wish to convert a standard mesh to quadratic or a quadratic
+<li>if it is necessary to convert a standard mesh to quadratic or a quadratic
 mesh to standard. Note that the choice is available only if the selected mesh
 (or sub-mesh) contains both quadratic and linear elements, else the
-sole direction of convertion is automatically selected.</li>
+direction of conversion is selected automatically.</li>
 
-<li>if you wish to place medium nodes of the quadratic mesh on the
-geometry (meshed object). This option is active at convertion to
-qudratic mesh only and provided that the mesh is based on some
-geometry (not imported from the file).</li>
+<li>if it is necessary to place medium nodes of the quadratic mesh on the
+geometry (meshed object). This option is relevant for conversion to
+quadratic provided that the mesh is based on a geometry (not imported from file).</li>
 </ul>
 
 \image html image156.gif
index d089144986907e782162c9e8a24af6be305823ad..0b9500b4effdd8630420e662b034c5404f318104 100644 (file)
@@ -2,8 +2,8 @@
 
 \page cut_mesh_by_plane_page Cut a tetrahedron mesh by a plane
 
-\n MeshCut works only on Med files and produces Med files, and is a standalone program.
-It can be used either directly on a shell command outside SALOME, or with a GUI interface in SMESH,
+\n MeshCut works only with MED files and produces MED files, and is a standalone program.
+It can be used either directly from a command shell outside SALOME, or with a GUI interface in SMESH,
 provided in a python plugin that needs to be installed in your SALOME application.
 
 \n MeshCut allows to cut a mesh constituted of linear tetrahedrons by a plane.
@@ -31,20 +31,21 @@ MeshCut input.med output.med resuMeshName aboveGroup belowGroup nx ny nz px py p
 \n  nx ny nz     = vector normal to the cut plane
 \n  px py pz     = a point of the cut plane
 \n  T            = 0 < T < 1 : vertices of a tetrahedron are considered as belonging to
-\n                 the cut plane if their distance to the plane is inferior to L*T
+\n                 the cut plane if their distance from the plane is inferior to L*T,
 \n                 where L is the mean edge size of the tetrahedron
 
 <br>
 \anchor meshcut_plugin
 <h2>Using MeshCut inside SALOME</h2>
 
-When the MeshCut plugin is installed, you will find it in the Mesh menu, sub-menu SMESH_plugins.
-\n If the plugin is not installed, look for a file named meshcut_plugin.py in your SMESH installation.
-The file is normally in the subdirectory bin/salome/meshcut_plugin.py.
+When the MeshCut plugin is installed, it can be found in the Mesh menu, sub-menu SMESH_plugins.
+\n If the plugin is not installed, the file meshcut_plugin.py is in
+SMESH installation in  subdirectory bin/salome/meshcut_plugin.py.
 
-\n If you already have plugins defined in a smesh_plugins.py file, add this file at the end.
- if not, copy this file as ${HOME}/Plugins/smesh_plugins.py or ${APPLI}/Plugins/smesh_plugins.py
- or in your ${PLUGINPATH} Directory.
+\n If there are already plugins defined in a smesh_plugins.py file,
+ this file should be added at the end.
+ if not, copied as ${HOME}/Plugins/smesh_plugins.py or ${APPLI}/Plugins/smesh_plugins.py
+ or in ${PLUGINPATH} Directory.
  
 <li>From the Mesh menu, sub-menu SMESH_plugins, choose "MeshCut" item
 The following dialog box will appear:
index 36ecea7b8cec54a4b8e402ed2720a9910e89b31b..7cfdbf90b3fde42071defc828bd7fd490be44d3a 100644 (file)
@@ -7,6 +7,6 @@ allow to generate flat volume elements on the boundaries of a list
 of groups of volumes, or on a list of groups of faces.
 \n These functionalities are only available in python scripts.
 
-<br><b>See </b> a sample TUI Script of a \ref tui_double_nodes_on_group_boundaries "Generate flat elements" operations.  
+<br><b>See </b> a sample TUI Script of \ref tui_double_nodes_on_group_boundaries "Generate flat elements" operation.  
 
 */
index fe8f31b665b0a0a18365b5c0c3ad8e72f2cb64cc..0ab41a24df44a6cb6ec0d9041d4021bac569657e 100644 (file)
@@ -7,7 +7,7 @@ elements of a higher dimension.
 
 <em>To generate border elements:</em>
 <ol>
-<li>Select a mesh in the Object Browser or in the 3D Viewer</li>
+<li>Select a mesh or groups in the Object Browser or in the 3D Viewer</li>
 <li>From the Modification menu choose "Create boundary elements"
 item, or click "Create boundary elements" button in the toolbar
 
@@ -16,26 +16,23 @@ item, or click "Create boundary elements" button in the toolbar
 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
+<li>Check in the dialog box one of two 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.
+of two 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 2D groups</b> creates mesh edges on borders of groups of faces</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>2D groups</b> on borders of which the edges will be
-generated (if <b>1D from 2D groups</b> is selected).</li>
 <li>specify the <b>Target</b> mesh, where the boundary elements will
   be created.
   <ul>
index 26ad944f7a7ec6c9139f14a1396ffb07d06768c4..ca00dbd1a04538926e9be44b889d6a8f7d39d260 100644 (file)
@@ -2,7 +2,10 @@
 
 \page over_constrained_faces_page Over-constrained faces
 
-\n This mesh quality control highlights faces sharing only one of its borders with other faces.
+\n This mesh quality control highlights faces sharing only one of its borders with other faces. In other words the faces having all there nodes on the external border of the mesh are highlighted.
+
+\note The highlighted faces are actually over constrained only if, at the computation time, 
+the boundary conditions on the borders where the nodes are located are all Dirichlet boundary conditions.
 
 \image html over_constrained_faces.png
 
index 1519e0ae658adc983d797c0c22bfa7b04c389ddd..9c11ebb0c6ae01eb467080a105c669e7bf763524 100644 (file)
@@ -3,6 +3,10 @@
 \page over_constrained_volumes_page Over-constrained volumes
 
 \n This mesh quality control highlights volumes sharing only one of its borders with other volumes.
+In other words the volumes having all there nodes on the external border of the mesh are highlighted.
+
+\note The highlighted volumes are actually over constrained only if, at the computation time, 
+the boundary conditions on the borders where the nodes are located are all Dirichlet boundary conditions.
 
 \image html over_constrained_volumes.png
 
index 8b63ddfa335a9d9fbc3b388552e6f64b47134f19..a677107cffeab97a17127d6319daa1667c3d08de 100644 (file)
@@ -139,5 +139,6 @@ the following links:
 - \subpage tui_transforming_meshes_page
 - \subpage tui_notebook_smesh_page
 - \subpage tui_measurements_page
+- \subpage tui_generate_flat_elements_page 
 
 */
index 0146e81e3ff7aa0e26fdc24e5b7852a983c65f21..0051faada94aa88e69dcc7e1012f17882becbc3e 100644 (file)
@@ -38,11 +38,11 @@ ghs3dMesh.Compute()
 # - the coordinates x,y,z
 # - a GEOM vertex or compound (No geometry, TUI only)
 #
-# The enforced nodes created can also be stored in
+# The created enforced nodes can also be stored in
 # a group (No geometry, TUI only).
 
-# Ex1: Add 1 enforced vertices by coords at (50,50,100) 
-#      with a physical size of 2
+# Ex1: Add one enforced vertex with coordinates (50,50,100) 
+#      and physical size 2.
 
 import geompy
 import smesh
@@ -73,10 +73,10 @@ GHS3D_Parameters.SetEnforcedVertex( 50, 50, 100, 2) # no group
 ghs3dMesh.Compute()
 
 
-# Ex2: Add 1 enforced vertices by GEOM vertex at (50,50,100) 
-#      with a physical size of 5 and add it to a group called "My special nodes"
+# Ex2: Add one vertex enforced by a GEOM vertex at (50,50,100) 
+#      with physical size 5 and add it to a group called "My special nodes"
 
-# Create another GHS3D hypothesis and assign it to the mesh wo geometry
+# Create another GHS3D hypothesis and assign it to the mesh without geometry
 GHS3D_Parameters_wo_geometry = smesh.CreateHypothesis('GHS3D_Parameters', 'GHS3DEngine')
 ghs3dMesh_wo_geometry.AddHypothesis( GHS3D )
 ghs3dMesh_wo_geometry.AddHypothesis( GHS3D_Parameters_wo_geometry )
@@ -104,8 +104,8 @@ GHS3D_Parameters.ClearEnforcedVertices()
 
 \code
 
-# It is possible to constraint GHS3D with another mesh or group.
-# The constraint can be the nodes, edges or faces.
+# It is possible to constrain GHS3D with another mesh or group.
+# The constraint can refer to the nodes, edges or faces.
 # This feature is available only in TUI, on meshes without geometry.
 # The constraining elements are called enforced elements for the mesh.
 # They can be recovered using groups if necessary.
@@ -133,7 +133,7 @@ geompy.addToStudy( p1, "p1" )
 geompy.addToStudy( p2, "p2" )
 geompy.addToStudy( c, "c" )
 
-# Create the 2D algo and hypothesis
+# Create the 2D algorithm and hypothesis
 BLSURF = smesh.CreateHypothesis('BLSURF', 'BLSURFEngine')
 # For the box
 BLSURF_Parameters = smesh.CreateHypothesis('BLSURF_Parameters', 'BLSURFEngine')
@@ -143,7 +143,7 @@ BLSURF_Parameters.SetPhySize( 200 )
 BLSURF_Parameters2 = smesh.CreateHypothesis('BLSURF_Parameters', 'BLSURFEngine')
 BLSURF_Parameters2.SetGeometricMesh( 1 )
 
-# Create the 3D algo and hypothesis
+# Create the 3D algorithm and hypothesis
 GHS3D = smesh.CreateHypothesis('GHS3D_3D', 'GHS3DEngine')
 GHS3D_Parameters_node = smesh.CreateHypothesis('GHS3D_Parameters', 'GHS3DEngine')
 #GHS3D_Parameters_node.SetToMeshHoles( 1 )
@@ -173,7 +173,7 @@ Mesh_box_tri.AddHypothesis( BLSURF_Parameters )
 Mesh_box_tri.Compute()
 
 # Create 4 copies of the 2D mesh to test the 3 types of contraints (NODE, EDGE, FACE)
-# from a whole mesh and from groups of elements.
+# from the whole mesh and from groups of elements.
 # Then the 3D algo and hypothesis are assigned to them.
 
 mesh_mesh = smesh.CopyMesh( Mesh_box_tri, 'Enforced by faces of mesh', 0, 0)
@@ -213,4 +213,4 @@ mesh_mesh.Compute()
 \image html ghs3d_screenshot_enf5.png
 \image html ghs3d_screenshot_enf6.png
 
-*/
\ No newline at end of file
+*/
index eb336888f530f58d44a63c44f7cba6f35c3f70d4..45806adbbc482196fc298e0af16d67e23e7bb1d0 100644 (file)
@@ -7,10 +7,10 @@
 <h2>Double nodes on groups boundaries</h2>
 
 \n Double nodes on shared faces between groups of volumes and create flat elements on demand.
-\n The list of groups must describe a partition of the mesh volumes.The nodes of the internal
-faces at the boundaries of the groups are doubled. In option, the internal faces are replaced
+\n The list of groups must describe a partition of the mesh volumes. The nodes of the internal
+faces at the boundaries of the groups are doubled. Optionally, the internal faces are replaced
 by flat elements.
-\n Triangles are transformed in prisms, and quadrangles in hexahedrons.
+\n Triangles are transformed into prisms, and quadrangles into hexahedrons.
 \n The flat elements are stored in groups of volumes.
 
 \n
@@ -37,7 +37,7 @@ Partition_1 = geompy.MakePartition([Fuse_1], [Cylinder_1], [], [], geompy.ShapeT
 [Solid_1,Solid_2,Solid_3] = geompy.SubShapes(Partition_1, [53, 2, 30])
 [Face_1,Face_2] = geompy.SubShapes(Partition_1, [37, 20])
 
-# meshing (linear tetrahedrons here, but other elements are OK)
+# meshing (linear tetrahedrons are here, but other elements are OK)
 
 Mesh_1 = smesh.Mesh(Partition_1)
 BLSURF = Mesh_1.Triangle(algo=smesh.BLSURF)
@@ -61,7 +61,7 @@ Face_2_1 = Mesh_1.GroupOnGeom(Face_2,'Face_2',SMESH.FACE)
 
 \n Here, the 3 groups of volumes [Solid_1_1, Solid_2_1, Solid_3_1] constitute a partition of the mesh.
 The flat elements on group boundaries and on faces are built with the following code.
-\n If the last argument (boolean) in DoubleNodesOnGroupBoundaries is set to 1,
+\n If the last argument (Boolean) in DoubleNodesOnGroupBoundaries is set to 1,
 the flat elements are built, otherwise, there is only a duplication of the nodes.
 
 \code
@@ -70,6 +70,6 @@ Mesh_1.DoubleNodesOnGroupBoundaries([Solid_1_1, Solid_2_1, Solid_3_1], 1)
 Mesh_1.CreateFlatElementsOnFacesGroups([Face_1_1, Face_2_1])
 \endcode
 
-\n To observe the flat element groups, save the resulting mesh on a Med file and reload it.
+\n To observe flat element groups, save the resulting mesh on a MED file and reload it.
 
 */
diff --git a/doc/salome/gui/SMESH/static/header.html b/doc/salome/gui/SMESH/static/header.html
deleted file mode 100755 (executable)
index a70a95e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
-<html>
-<head>
-   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-   <title>$title</title>
-   <link href="doxygen.css" rel="stylesheet" type="text/css">
-</head>
-<hr>
-<center>
-SALOME documentation central
-</center>
-<hr>
diff --git a/doc/salome/gui/SMESH/static/header_py.html.in b/doc/salome/gui/SMESH/static/header_py.html.in
new file mode 100644 (file)
index 0000000..36e6a0c
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<title>$title</title>
+<link href="$relpath$tabs.css" rel="stylesheet" type="text/css"/>
+<link href="$relpath$search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="$relpath$search/search.js"></script>
+<link href="$relpath$navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="$relpath$jquery.js"></script>
+<script type="text/javascript" src="$relpath$navtree.js"></script>
+<script type="text/javascript" src="$relpath$resize.js"></script>
+<script type="text/javascript">
+$(document).ready(initResizable);
+</script>
+<link href="$relpath$doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body onload='searchBox.OnSelectItem(0);'>
+<div id="top"><!-- do not remove this div! -->
+<div id="titlearea"><div align="right"><div class="version">Version: @VERSION@</div></div></div>
+<div align="bottom-left"><a href=../index.html>Home</a></div>
+
+</div>
index 71e2cca69856e3d4677eae7423d64ed745861e38..4b710727b619a216bc86378b3475b611c82d50d5 100644 (file)
@@ -264,7 +264,8 @@ module SMESH
     long_array GetMeshInfo();
 
     /*!
-     * Returns types of elements it contains
+     * Returns types of elements it contains.
+     * It's empty if the SMESH_IDSource contains no IDs
      */
     array_of_ElementType GetTypes();
 
index 4fe87ed698c7afeccd5b788a15dcf3db7cfac069..9d02fc14ef17edca248fa3503db79b39e28e2dd2 100755 (executable)
@@ -415,6 +415,8 @@ void  aptrte( Z   nutysu, R      aretmx,
   if( mntree==NULL ) goto ERREUR;
 
   //initialisation du tableau letree et ajout dans letree des sommets 1 a nbsomm
+  comxmi[0].x = comxmi[1].x = uvslf[0].x;
+  comxmi[0].y = comxmi[1].y = uvslf[0].y;
   teajte( mxsomm, nbsomm, mnpxyd, comxmi, aretmx, mxtree, mntree, ierr );
   comxmi[0].z=0;
   comxmi[1].z=0;
index 273569def1c20288d24bbaea4f7f0567688b56b4..5b562b8efe630dbc3cd6d60cb391688679e29df5 100755 (executable)
@@ -1294,7 +1294,7 @@ c        la direction pour le calcul de la longueur (inactif ici!)
          xyzd(2) = 0d0
          xyzd(3) = 0d0
 
-         longai = areteideale()
+         longai = areteideale(xyz,xyzd)
 c         (xyz,xyzd)
          if( longai .lt. 0d0 ) then
             write(imprim,10000) xyz
index 34e8f9c01db8fb441670a1406304ea7bae061c8e..c5fe45fdc30f01a8b956dc5313ecb0b254510535 100644 (file)
@@ -122,21 +122,16 @@ dist_libSMDS_la_SOURCES = \
 # additionnal information to compil and link file
 libSMDS_la_CPPFLAGS = \
        $(KERNEL_CXXFLAGS) \
-       $(CAS_CPPFLAGS) \
         $(VTK_INCLUDES) \
        $(BOOST_CPPFLAGS)
 
 libSMDS_la_LDFLAGS  = \
        $(VTK_LIBS) \
-       $(KERNEL_LDFLAGS) -lSALOMELocalTrace \
-       $(CAS_KERNEL)
+       $(KERNEL_LDFLAGS) -lSALOMELocalTrace
 
 # Executables targets
 bin_PROGRAMS = SMDS_MemoryLimit
 dist_SMDS_MemoryLimit_SOURCES = \
        SMDS_MemoryLimit.cxx
 
-SMDS_MemoryLimit_LDADD = \
-       $(KERNEL_LDFLAGS) -lSALOMELocalTrace
-
 #libSMDS_la_LDFLAGS += -L/data/eap/S5_MV/INSTALL/SMESH/lib/salome -lPerfmeter
index 7a656c195871464b8a31de2697b44b6c14a41f78..6c86e6f28b5137f7bb650ea52f7b5a06ae65a0e4 100644 (file)
@@ -38,6 +38,8 @@
 #include "SMDS_UnstructuredGrid.hxx"
 #include <vtkCellType.h>
 
+#include <climits>
+
 using namespace std;
 
 //=======================================================================
@@ -173,7 +175,7 @@ void SMDS_MeshElementIDFactory::ReleaseID(int ID, int vtkId)
 
 void SMDS_MeshElementIDFactory::updateMinMax() const
 {
-  myMin = IntegerLast();
+  myMin = INT_MAX;
   myMax = 0;
   for (int i = 0; i < myMesh->myCells.size(); i++)
     {
@@ -186,7 +188,7 @@ void SMDS_MeshElementIDFactory::updateMinMax() const
             myMin = id;
         }
     }
-  if (myMin == IntegerLast())
+  if (myMin == INT_MAX)
     myMin = 0;
 }
 
index 560fef0df3ea233ca28456a7f8409f96ad7cad01..107402393561529ef0c310d063ae8e69224ab547 100644 (file)
@@ -32,7 +32,6 @@
 #include "SMDS_MeshElement.hxx"
 #include "SMDS_Position.hxx"
 #include "ObjectPool.hxx"
-#include <NCollection_List.hxx>
 
 class SMDS_EXPORT SMDS_MeshNode:public SMDS_MeshElement
 {
index ef7c8422265399d952b3ececf608d44585a31cf8..904e585d2eb88011d6993eff78724499ebfa9af0 100644 (file)
@@ -1355,20 +1355,23 @@ int SMDS_VolumeTool::GetAllExistingEdges(vector<const SMDS_MeshElement*> & edges
   return edges.size();
 }
 
-//=======================================================================
-//function : IsFreeFace
-//purpose  : check that only one volume is build on the face nodes
-//=======================================================================
+//================================================================================
+/*!
+ * \brief check that only one volume is build on the face nodes
+ *
+ * If a face is shared by one of <ignoreVolumes>, it is considered free
+ */
+//================================================================================
 
-bool SMDS_VolumeTool::IsFreeFace( int faceIndex )
+bool SMDS_VolumeTool::IsFreeFace( int faceIndex, const SMDS_MeshElement** otherVol/*=0*/ )
 {
-  const int free = true;
+  const bool isFree = true;
 
   if (!setFace( faceIndex ))
-    return !free;
+    return !isFree;
 
   const SMDS_MeshNode** nodes = GetFaceNodes( faceIndex );
-  int nbFaceNodes = myFaceNbNodes;
+  const int nbFaceNodes = myFaceNbNodes;
 
   // evaluate nb of face nodes shared by other volume
   int maxNbShared = -1;
@@ -1377,25 +1380,19 @@ bool SMDS_VolumeTool::IsFreeFace( int faceIndex )
   TElemIntMap::iterator vNbIt;
   for ( int iNode = 0; iNode < nbFaceNodes; iNode++ ) {
     const SMDS_MeshNode* n = nodes[ iNode ];
-    SMDS_ElemIteratorPtr eIt = n->GetInverseElementIterator();
+    SMDS_ElemIteratorPtr eIt = n->GetInverseElementIterator( SMDSAbs_Volume );
     while ( eIt->more() ) {
       const SMDS_MeshElement* elem = eIt->next();
-      if ( elem != myVolume && elem->GetType() == SMDSAbs_Volume ) {
-        int nbShared = 1;
-        vNbIt = volNbShared.find( elem );
-        if ( vNbIt == volNbShared.end() ) {
-          volNbShared.insert ( TElemIntMap::value_type( elem, nbShared ));
-        }
-        else {
-          nbShared = ++(*vNbIt).second;
-        }
-        if ( nbShared > maxNbShared )
-          maxNbShared = nbShared;
+      if ( elem != myVolume ) {
+        vNbIt = volNbShared.insert( make_pair( elem, 0 )).first;
+        (*vNbIt).second++;
+        if ( vNbIt->second > maxNbShared )
+          maxNbShared = vNbIt->second;
       }
     }
   }
   if ( maxNbShared < 3 )
-    return free; // is free
+    return isFree; // is free
 
   // find volumes laying on the opposite side of the face
   // and sharing all nodes
@@ -1404,55 +1401,81 @@ bool SMDS_VolumeTool::IsFreeFace( int faceIndex )
   if ( IsFaceExternal( faceIndex ))
     intNormal = XYZ( -intNormal.x, -intNormal.y, -intNormal.z );
   XYZ p0 ( nodes[0] ), baryCenter;
-  for ( vNbIt = volNbShared.begin(); vNbIt != volNbShared.end(); vNbIt++ ) {
-    int nbShared = (*vNbIt).second;
+  for ( vNbIt = volNbShared.begin(); vNbIt != volNbShared.end();  ) {
+    const int& nbShared = (*vNbIt).second;
     if ( nbShared >= 3 ) {
       SMDS_VolumeTool volume( (*vNbIt).first );
       volume.GetBaryCenter( baryCenter.x, baryCenter.y, baryCenter.z );
       XYZ intNormal2( baryCenter - p0 );
-      if ( intNormal.Dot( intNormal2 ) < 0 )
-        continue; // opposite side
+      if ( intNormal.Dot( intNormal2 ) < 0 ) {
+        // opposite side
+        if ( nbShared >= nbFaceNodes )
+        {
+          // a volume shares the whole facet
+          if ( otherVol ) *otherVol = vNbIt->first;
+          return !isFree; 
+        }
+        ++vNbIt;
+        continue;
+      }
     }
     // remove a volume from volNbShared map
-    volNbShared.erase( vNbIt-- );
+    volNbShared.erase( vNbIt++ );
   }
 
-  // here volNbShared contains only volumes laying on the
-  // opposite side of the face
-  if ( volNbShared.empty() ) {
-    return free; // is free
+  // here volNbShared contains only volumes laying on the opposite side of
+  // the face and sharing 3 or more but not all face nodes with myVolume
+  if ( volNbShared.size() < 2 ) {
+    return isFree; // is free
   }
 
   // check if the whole area of a face is shared
-  bool isShared[] = { false, false, false, false }; // 4 triangle parts of a quadrangle
-  for ( vNbIt = volNbShared.begin(); vNbIt != volNbShared.end(); vNbIt++ ) {
-    SMDS_VolumeTool volume( (*vNbIt).first );
-    bool prevLinkShared = false;
-    int nbSharedLinks = 0;
-    for ( int iNode = 0; iNode < nbFaceNodes; iNode++ ) {
-      bool linkShared = volume.IsLinked( nodes[ iNode ], nodes[ iNode + 1] );
-      if ( linkShared )
-        nbSharedLinks++;
-      if ( linkShared && prevLinkShared &&
-          volume.IsLinked( nodes[ iNode - 1 ], nodes[ iNode + 1] ))
-        isShared[ iNode ] = true;
-      prevLinkShared = linkShared;
-    }
-    if ( nbSharedLinks == nbFaceNodes )
-      return !free; // is not free
-    if ( nbFaceNodes == 4 ) {
-      // check traingle parts 1 & 3
-      if ( isShared[1] && isShared[3] )
-        return !free; // is not free
-      // check triangle parts 0 & 2;
-      // 0 part could not be checked in the loop; check it here
-      if ( isShared[2] && prevLinkShared &&
-          volume.IsLinked( nodes[ 0 ], nodes[ 1 ] ) &&
-          volume.IsLinked( nodes[ 1 ], nodes[ 3 ] ) )
-        return !free; // is not free
-    }
+  for ( int iNode = 0; iNode < nbFaceNodes; iNode++ )
+  {
+    const SMDS_MeshNode* n = nodes[ iNode ];
+    // check if n is shared by one of volumes of volNbShared
+    bool isShared = false;
+    SMDS_ElemIteratorPtr eIt = n->GetInverseElementIterator( SMDSAbs_Volume );
+    while ( eIt->more() && !isShared )
+      isShared = volNbShared.count( eIt->next() );
+    if ( !isShared )
+      return isFree;
   }
-  return free;
+  if ( otherVol ) *otherVol = volNbShared.begin()->first;
+  return !isFree;
+
+//   if ( !myVolume->IsPoly() )
+//   {
+//     bool isShared[] = { false, false, false, false }; // 4 triangle parts of a quadrangle
+//     for ( vNbIt = volNbShared.begin(); vNbIt != volNbShared.end(); vNbIt++ ) {
+//       SMDS_VolumeTool volume( (*vNbIt).first );
+//       bool prevLinkShared = false;
+//       int nbSharedLinks = 0;
+//       for ( int iNode = 0; iNode < nbFaceNodes; iNode++ ) {
+//         bool linkShared = volume.IsLinked( nodes[ iNode ], nodes[ iNode + 1] );
+//         if ( linkShared )
+//           nbSharedLinks++;
+//         if ( linkShared && prevLinkShared &&
+//              volume.IsLinked( nodes[ iNode - 1 ], nodes[ iNode + 1] ))
+//           isShared[ iNode ] = true;
+//         prevLinkShared = linkShared;
+//       }
+//       if ( nbSharedLinks == nbFaceNodes )
+//         return !free; // is not free
+//       if ( nbFaceNodes == 4 ) {
+//         // check traingle parts 1 & 3
+//         if ( isShared[1] && isShared[3] )
+//           return !free; // is not free
+//         // check triangle parts 0 & 2;
+//         // 0 part could not be checked in the loop; check it here
+//         if ( isShared[2] && prevLinkShared &&
+//              volume.IsLinked( nodes[ 0 ], nodes[ 1 ] ) &&
+//              volume.IsLinked( nodes[ 1 ], nodes[ 3 ] ) )
+//           return !free; // is not free
+//       }
+//     }
+//   }
+//  return free;
 }
 
 //=======================================================================
index 9cc0ae829eec00b44abbc09abd1966b72f3e5691..f21a47209384978a7016b7ca28499dc4c9a58a88 100644 (file)
@@ -160,8 +160,9 @@ class SMDS_EXPORT SMDS_VolumeTool
   // Check normal orientation of a face.
   // SetExternalNormal() is taken into account.
 
-  bool IsFreeFace(  int faceIndex );
+  bool IsFreeFace(  int faceIndex, const SMDS_MeshElement** otherVol=0 );
   // Check that all volumes built on the face nodes lays on one side
+  // otherVol returns another volume sharing the given facet
 
   bool GetFaceNormal (int faceIndex, double & X, double & Y, double & Z);
   // Return a normal to a face
index bbe59e92804deace295eb1f96f6e14b5b4d8b0dd..e509dd1b9fbe52afabc4d779c685b967b413d1ae 100644 (file)
@@ -174,7 +174,7 @@ double SMESH_Algo::EdgeLength(const TopoDS_Edge & E)
     return 0;
   TopLoc_Location L;
   Handle(Geom_Curve) C = BRep_Tool::Curve(E, L, UMin, UMax);
-  GeomAdaptor_Curve AdaptCurve(C);
+  GeomAdaptor_Curve AdaptCurve(C, UMin, UMax); //range is important for periodic curves
   double length = GCPnts_AbscissaPoint::Length(AdaptCurve, UMin, UMax);
   return length;
 }
index d47fcc0ad4a7ce06f9b563bd516bfbc5d8d6744e..76432855fe476d48e366cff1bc5fa5211dad0628 100644 (file)
@@ -1615,6 +1615,7 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
       helper.SetIsQuadratic( false );
     }
     vector<const SMDS_MeshNode*> nodes( (*elem)->begin_nodes(), (*elem)->end_nodes() );
+    helper.SetElementsOnShape( true );
     if ( splitMethod._baryNode )
     {
       // make a node at barycenter
@@ -1642,7 +1643,6 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
     }
 
     // make tetras
-    helper.SetElementsOnShape( true );
     vector<const SMDS_MeshElement* > tetras( splitMethod._nbTetra ); // splits of a volume
     const int* tetConn = splitMethod._connectivity;
     for ( int i = 0; i < splitMethod._nbTetra; ++i, tetConn += 4 )
@@ -1670,6 +1670,12 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
         helper.SetElementsOnShape( false );
         vector< const SMDS_MeshElement* > triangles;
 
+        // find submesh to add new triangles in
+        if ( !fSubMesh || !fSubMesh->Contains( face ))
+        {
+          int shapeID = FindShape( face );
+          fSubMesh = GetMeshDS()->MeshElements( shapeID );
+        }
         map<int, const SMDS_MeshNode*>::iterator iF_n = splitMethod._faceBaryNode.find(iF);
         if ( iF_n != splitMethod._faceBaryNode.end() )
         {
@@ -1681,6 +1687,9 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
             if ( !volTool.IsFaceExternal( iF ))
               swap( n2, n3 );
             triangles.push_back( helper.AddFace( n1,n2,n3 ));
+
+            if ( fSubMesh && n3->getshapeId() < 1 )
+              fSubMesh->AddNode( n3 );
           }
         }
         else
@@ -1719,12 +1728,6 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
                                                  volNodes[ facet->_n3 ]));
           }
         }
-        // find submesh to add new triangles in
-        if ( !fSubMesh || !fSubMesh->Contains( face ))
-        {
-          int shapeID = FindShape( face );
-          fSubMesh = GetMeshDS()->MeshElements( shapeID );
-        }
         for ( int i = 0; i < triangles.size(); ++i )
         {
           if ( !triangles[i] ) continue;
@@ -3088,35 +3091,27 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet &          theElems,
     // fix nodes on mesh boundary
 
     if ( checkBoundaryNodes ) {
-      map< NLink, int > linkNbMap; // how many times a link encounters in elemsOnFace
-      map< NLink, int >::iterator link_nb;
+      map< SMESH_TLink, int > linkNbMap; // how many times a link encounters in elemsOnFace
+      map< SMESH_TLink, int >::iterator link_nb;
       // put all elements links to linkNbMap
       list< const SMDS_MeshElement* >::iterator elemIt = elemsOnFace.begin();
       for ( ; elemIt != elemsOnFace.end(); ++elemIt ) {
         const SMDS_MeshElement* elem = (*elemIt);
-        int nbn =  elem->NbNodes();
-        if(elem->IsQuadratic())
-          nbn = nbn/2;
+        int nbn =  elem->NbCornerNodes();
         // loop on elem links: insert them in linkNbMap
-        const SMDS_MeshNode* curNode, *prevNode = elem->GetNodeWrap( nbn );
         for ( int iN = 0; iN < nbn; ++iN ) {
-          curNode = elem->GetNode( iN );
-          NLink link;
-          if ( curNode < prevNode ) link = make_pair( curNode , prevNode );
-          else                      link = make_pair( prevNode , curNode );
-          prevNode = curNode;
-          link_nb = linkNbMap.find( link );
-          if ( link_nb == linkNbMap.end() )
-            linkNbMap.insert( make_pair ( link, 1 ));
-          else
-            link_nb->second++;
+          const SMDS_MeshNode* n1 = elem->GetNode( iN );
+          const SMDS_MeshNode* n2 = elem->GetNode(( iN+1 ) % nbn);
+          SMESH_TLink link( n1, n2 );
+          link_nb = linkNbMap.insert( make_pair( link, 0 )).first;
+          link_nb->second++;
         }
       }
       // remove nodes that are in links encountered only once from setMovableNodes
       for ( link_nb = linkNbMap.begin(); link_nb != linkNbMap.end(); ++link_nb ) {
         if ( link_nb->second == 1 ) {
-          setMovableNodes.erase( link_nb->first.first );
-          setMovableNodes.erase( link_nb->first.second );
+          setMovableNodes.erase( link_nb->first.node1() );
+          setMovableNodes.erase( link_nb->first.node2() );
         }
       }
     }
@@ -4120,7 +4115,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
                 if ( f )
                   aMesh->ChangeElementNodes( f, &polygon_nodes[0], nbn );
                 else
-                  myLastCreatedElems.Append(aMesh->AddPolygonalFace(polygon_nodes));
+                  AddElement(polygon_nodes, SMDSAbs_Face, polygon_nodes.size()>4);
               }
             }
 
@@ -11578,13 +11573,12 @@ namespace
  *  \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
+ *  \param toCopyExistingBoundary - if true, not only new but also pre-existing
  *                                boundary elements will be copied into the targetMesh
  *  \param toAddExistingBondary - if true, not only new but also pre-existing
  *                                boundary elements will be added into the new group
  *  \param aroundElements - if true, elements will be created on boundary of given
- *                          elements else, on boundary of the whole mesh. This
- *                          option works for 2D elements only.
+ *                          elements else, on boundary of the whole mesh.
  * \return nb of added boundary elements
  */
 //================================================================================
@@ -11594,7 +11588,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
                                        SMESH_Group*            group/*=0*/,
                                        SMESH_Mesh*             targetMesh/*=0*/,
                                        bool                    toCopyElements/*=false*/,
-                                       bool                    toCopyExistingBondary/*=false*/,
+                                       bool                    toCopyExistingBoundary/*=false*/,
                                        bool                    toAddExistingBondary/*= false*/,
                                        bool                    aroundElements/*= false*/)
 {
@@ -11604,11 +11598,8 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
   if ( !elements.empty() && (*elements.begin())->GetType() != elemType )
     throw SALOME_Exception(LOCALIZED("wrong element type"));
 
-  if ( aroundElements && elemType == SMDSAbs_Volume )
-    throw SALOME_Exception(LOCALIZED("wrong element type for aroundElements==true"));
-
   if ( !targetMesh )
-    toCopyElements = toCopyExistingBondary = false;
+    toCopyElements = toCopyExistingBoundary = false;
 
   SMESH_MeshEditor tgtEditor( targetMesh ? targetMesh : myMesh );
   SMESHDS_Mesh* aMesh = GetMeshDS(), *tgtMeshDS = tgtEditor.GetMeshDS();
@@ -11646,11 +11637,13 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
     if ( vTool.Set(elem) ) // elem is a volume ------------------------------------------
     {
       vTool.SetExternalNormal();
+      const SMDS_MeshElement* otherVol = 0;
       for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ )
       {
-        if (!vTool.IsFreeFace(iface))
+        if ( !vTool.IsFreeFace(iface, &otherVol) &&
+             ( !aroundElements || elements.count( otherVol )))
           continue;
-        int nbFaceNodes = vTool.NbFaceNodes(iface);
+        const int nbFaceNodes = vTool.NbFaceNodes(iface);
         const SMDS_MeshNode** nn = vTool.GetFaceNodes(iface);
         if ( missType == SMDSAbs_Edge ) // boundary edges
         {
@@ -11679,6 +11672,21 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
             presentBndElems.push_back( f );
           else
             missingBndElems.push_back( nodes );
+
+          if ( targetMesh != myMesh )
+          {
+            // add 1D elements on face boundary to be added to a new mesh
+            const SMDS_MeshElement* edge;
+            for ( inode = 0; inode < nbFaceNodes; inode += 1+iQuad)
+            {
+              if ( iQuad )
+                edge = aMesh->FindEdge( nn[inode], nn[inode+1], nn[inode+2]);
+              else
+                edge = aMesh->FindEdge( nn[inode], nn[inode+1]);
+              if ( edge && avoidSet.insert( edge ).second )
+                presentBndElems.push_back( edge );
+            }
+          }
         }
       }
     }
@@ -11709,7 +11717,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
     // ---------------------------------
     if ( targetMesh != myMesh )
       // instead of making a map of nodes in this mesh and targetMesh,
-      // we create nodes with same IDs. We can renumber them later, if needed
+      // we create nodes with same IDs.
       for ( int i = 0; i < missingBndElems.size(); ++i )
       {
         TConnectivity& srcNodes = missingBndElems[i];
@@ -11738,14 +11746,14 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
     // ----------------------------------
     // 3. Copy present boundary elements
     // ----------------------------------
-    if ( toCopyExistingBondary )
+    if ( toCopyExistingBoundary )
       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) );
-        presentEditor->AddElement(nodes, missType, e->IsPoly());
+        presentEditor->AddElement(nodes, e->GetType(), e->IsPoly());
       }
     else // store present elements to add them to a group
       for ( int i = 0 ; i < presentBndElems.size(); ++i )
index 698446b5c53268c5c592ee118fce14bbd3a95dee..dd79438606bbf89049efc3740d35e5a8456aa865 100644 (file)
@@ -194,7 +194,7 @@ void SMESH_MesherHelper::SetSubShape(const int aShID)
 {
   if ( aShID == myShapeID )
     return;
-  if ( aShID > 1 )
+  if ( aShID > 0 )
     SetSubShape( GetMeshDS()->IndexToShape( aShID ));
   else
     SetSubShape( TopoDS_Shape() );
index eda45d9b9cf44eaae292cc166c4619a5522c6de0..7d608fae577e7905c59391cad7b1b3c7ebb5c473 100644 (file)
@@ -3742,8 +3742,9 @@ void SMESHGUI::initialize( CAM_Application* app )
   popupMgr()->insert( separator(), -1, 0 );
   createPopupItem( 4043, OB, mesh );                       // CLEAR_MESH
   popupMgr()->insert( separator(), -1, 0 );
-  createPopupItem( 417, OB, mesh + " " + subMesh );         // convert to quadratic
-  createPopupItem( 418, OB, mesh/*, "&& " + hasVolumes*/);  // create 2D mesh on 3D
+  createPopupItem( 417, OB, mesh + " " + subMesh );        // convert to quadratic
+  createPopupItem( 418, OB, mesh + " " + group,            // create 2D mesh from 3D
+                   "&& dim>=2"); 
   popupMgr()->insert( separator(), -1, 0 );
 
   QString only_one_non_empty = QString( " && %1=1 && numberOfNodes>0" ).arg( dc );
index 6c057090365849d9ad90e1e9a4f27f0b36d9110b..4cf3f91b031812d103d39617b40b847e0eeb27ab 100755 (executable)
@@ -107,8 +107,8 @@ bool SMESHGUI_PredicateFilter::IsObjValid( const int theObjId ) const
   if ( myActor == 0 || myPred->_is_nil() )
     return false;
 
-  SMESH_Actor* anActor = ( SMESH_Actor* )myActor;
-  if ( anActor->GetObject() == 0 )
+  SMESH_Actor* anActor = dynamic_cast< SMESH_Actor* >( myActor );
+  if ( !anActor || anActor->GetObject() == 0 )
     return false;
 
   SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
@@ -211,8 +211,8 @@ bool SMESHGUI_QuadrangleFilter::IsValid( const int theCellId ) const
   if ( myActor == 0 )
     return false;
 
-  SMESH_Actor* anActor = ( SMESH_Actor* )myActor;
-  if ( anActor->GetObject() == 0 )
+  SMESH_Actor* anActor = dynamic_cast< SMESH_Actor* >( myActor );
+  if ( !anActor || anActor->GetObject() == 0 )
     return false;
 
   SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
@@ -231,8 +231,8 @@ bool SMESHGUI_QuadrangleFilter::IsObjValid( const int theObjId ) const
   if ( myActor == 0 )
     return false;
 
-  SMESH_Actor* anActor = ( SMESH_Actor* )myActor;
-  if ( anActor->GetObject() == 0 )
+  SMESH_Actor* anActor = dynamic_cast< SMESH_Actor* >( myActor );
+  if ( !anActor || anActor->GetObject() == 0 )
     return false;
 
   SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
@@ -290,8 +290,8 @@ bool SMESHGUI_TriangleFilter::IsValid( const int theCellId ) const
   if ( myActor == 0 )
     return false;
 
-  SMESH_Actor* anActor = ( SMESH_Actor* )myActor;
-  if ( anActor->GetObject() == 0 )
+  SMESH_Actor* anActor = dynamic_cast< SMESH_Actor* >( myActor );
+  if ( !anActor || anActor->GetObject() == 0 )
     return false;
 
   SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
@@ -310,8 +310,8 @@ bool SMESHGUI_TriangleFilter::IsObjValid( const int theObjId ) const
   if ( myActor == 0 )
     return false;
 
-  SMESH_Actor* anActor = ( SMESH_Actor* )myActor;
-  if ( anActor->GetObject() == 0 )
+  SMESH_Actor* anActor = dynamic_cast< SMESH_Actor* >( myActor );
+  if ( !anActor || anActor->GetObject() == 0 )
     return false;
 
   SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
@@ -368,8 +368,8 @@ bool SMESHGUI_FacesFilter::IsValid( const int theCellId ) const
   if ( myActor == 0 )
     return false;
 
-  SMESH_Actor* anActor = ( SMESH_Actor* )myActor;
-  if ( anActor->GetObject() == 0 )
+  SMESH_Actor* anActor = dynamic_cast< SMESH_Actor* >( myActor );
+  if ( !anActor || anActor->GetObject() == 0 )
     return false;
 
   SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
@@ -387,8 +387,8 @@ bool SMESHGUI_FacesFilter::IsObjValid( const int theObjId ) const
   if ( myActor == 0 )
     return false;
 
-  SMESH_Actor* anActor = ( SMESH_Actor* )myActor;
-  if ( anActor->GetObject() == 0 )
+  SMESH_Actor* anActor = dynamic_cast< SMESH_Actor* >( myActor );
+  if ( !anActor || anActor->GetObject() == 0 )
     return false;
 
   SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
@@ -442,11 +442,11 @@ SMESHGUI_VolumesFilter::~SMESHGUI_VolumesFilter()
 //=======================================================================
 bool SMESHGUI_VolumesFilter::IsValid( const int theCellId ) const
 {
-  if ( myActor == 0 )
+  if ( myActor == 0 || theCellId < 1 )
     return false;
 
-  SMESH_Actor* anActor = ( SMESH_Actor* )myActor;
-  if ( anActor->GetObject() == 0 )
+  SMESH_Actor* anActor = dynamic_cast< SMESH_Actor* >( myActor );
+  if ( !anActor || anActor->GetObject() == 0 )
     return false;
 
   SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
@@ -464,8 +464,8 @@ bool SMESHGUI_VolumesFilter::IsObjValid( const int theObjId ) const
   if ( myActor == 0 )
     return false;
 
-  SMESH_Actor* anActor = ( SMESH_Actor* )myActor;
-  if ( anActor->GetObject() == 0 )
+  SMESH_Actor* anActor = dynamic_cast< SMESH_Actor* >( myActor );
+  if ( !anActor || anActor->GetObject() == 0 )
     return false;
 
   SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
index afc81d19acf1246e680932d387ba0022c5156fb9..746cc5afdd0c94fb5f1fd4e2d1bf8636fcdbde73 100644 (file)
@@ -26,6 +26,8 @@
 #include "SMESHGUI_MeshUtils.h"
 #include "SMESH_TypeFilter.hxx"
 #include "SMESH_LogicalFilter.hxx"
+#include "SMESHGUI_VTKUtils.h"
+#include "SMESH_Actor.h"
 
 // SALOME GUI includes
 #include <LightApp_Application.h>
@@ -37,6 +39,7 @@
 #include <SUIT_OverrideCursor.h>
 #include <SUIT_Session.h>
 #include <SVTK_ViewModel.h>
+//#include <SVTK_ViewWindow.h>
 #include <SalomeApp_Study.h>
 #include <SalomeApp_Tools.h>
 
@@ -53,6 +56,8 @@
 #include <QGridLayout>
 #include <QToolButton>
 
+#include <Standard_ErrorHandler.hxx>
+
 #define SPACING 6
 #define MARGIN  11
 
@@ -74,16 +79,22 @@ SMESHGUI_Make2DFrom3DDlg::SMESHGUI_Make2DFrom3DDlg( QWidget* parent )
   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 );
+  //my1dFrom3dRB = new QRadioButton( tr( "1D_FROM_3D" ), aModeGrp );
   aModeGrpLayout->addWidget( my2dFrom3dRB );
   aModeGrpLayout->addWidget( my1dFrom2dRB );
-  aModeGrpLayout->addWidget( my1dFrom3dRB );
+  //aModeGrpLayout->addWidget( my1dFrom3dRB );
+
+//   // Groups of mesh faces
+//   setObjectPixmap( "SMESH", tr( "ICON_SELECT" ) );
+//   createObject( tr( "Groups" ), mainFrame(), Groups );
+//   setNameIndication( Groups, ListOfNames );
+//   objectWg( Groups, Btn )->hide();
 
-  // Groups of mesh faces
-  setObjectPixmap( "SMESH", tr( "ICON_SELECT" ) );
-  createObject( tr( "Groups" ), mainFrame(), Groups );
-  setNameIndication( Groups, ListOfNames );
-  objectWg( Groups, Btn )->hide();
+  // Mesh or Groups
+  //setObjectPixmap( "SMESH", tr( "ICON_SELECT" ) );
+  createObject( tr( "Groups" ), mainFrame(), MeshOrGroups );
+  setNameIndication( MeshOrGroups, ListOfNames );
+  objectWg( MeshOrGroups, Btn )->hide();
 
   // target
   QGroupBox* aTargetGrp = new QGroupBox( tr( "TARGET" ), mainFrame() );
@@ -106,8 +117,8 @@ SMESHGUI_Make2DFrom3DDlg::SMESHGUI_Make2DFrom3DDlg( QWidget* parent )
   aDlgLay->setMargin( 0 );
   aDlgLay->setSpacing( SPACING );
   aDlgLay->addWidget( aModeGrp,     0, 0, 1, 3 );
-  aDlgLay->addWidget( objectWg( Groups,  Label ),   1, 0 );
-  aDlgLay->addWidget( objectWg( Groups,  Control ), 1, 1 );
+  aDlgLay->addWidget( objectWg( MeshOrGroups,  Label ),   1, 0 );
+  aDlgLay->addWidget( objectWg( MeshOrGroups,  Control ), 1, 1 );
   aDlgLay->addWidget( aTargetGrp,   2, 0, 1, 3 );
   aDlgLay->addWidget( myGroupCheck, 3, 0 );
   aDlgLay->addWidget( myGroupName,  3, 1, 1, 2 );
@@ -153,6 +164,21 @@ void SMESHGUI_Make2DFrom3DDlg::setNewMeshName( const QString& name )
   myMeshName->setText( name );
 }
 
+void SMESHGUI_Make2DFrom3DDlg::setNewMeshEnabled( bool enable )
+{
+  if ( !enable )
+    myThisMeshRB->setChecked( true );
+
+  myNewMeshRB->setEnabled( enable );
+
+  onTargetChanged();
+}
+
+bool SMESHGUI_Make2DFrom3DDlg::getNewMeshEnabled() const
+{
+  return myNewMeshRB->isEnabled();
+}
+
 bool SMESHGUI_Make2DFrom3DDlg::needGroup() const
 {
   return myGroupCheck->isChecked();
@@ -190,7 +216,9 @@ void SMESHGUI_Make2DFrom3DDlg::onGroupChecked()
 */
 
 SMESHGUI_Make2DFrom3DOp::SMESHGUI_Make2DFrom3DOp()
- : SMESHGUI_SelectionOp()
+  : SMESHGUI_SelectionOp(),
+    myMeshFilter(MESH),
+    myGroupFilter(GROUP)
 {
 }
 
@@ -220,33 +248,43 @@ void SMESHGUI_Make2DFrom3DOp::startOperation()
 
   connect( myDlg->my2dFrom3dRB, SIGNAL( toggled(bool) ), this, SLOT( onModeChanged() ) );
   connect( myDlg->my1dFrom2dRB, SIGNAL( toggled(bool) ), this, SLOT( onModeChanged() ) );
-  connect( myDlg->my1dFrom3dRB, SIGNAL( toggled(bool) ), this, SLOT( onModeChanged() ) );
+  //connect( myDlg->my1dFrom3dRB, SIGNAL( toggled(bool) ), this, SLOT( onModeChanged() ) );
+
+  //onModeChanged();
 
-  onModeChanged();
+  myDlg->activateObject( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups );
+  selectionDone();
 }
 
+//================================================================================
+/*!
+ * \brief Set filter corresponding to dimension
+ */
+//================================================================================
+
 void SMESHGUI_Make2DFrom3DOp::onModeChanged()
 {
-  QRadioButton* b = dynamic_cast<QRadioButton*>( sender());
-  if ( b && !b->isChecked() )
-    return;
-
-  // enable "2D groups" field
-  bool enableGroups = ( myDlg->mode() == SMESH::BND_1DFROM3D );
-  myDlg->setObjectEnabled( SMESHGUI_Make2DFrom3DDlg::Groups, enableGroups );
-  ((QToolButton*) myDlg->objectWg( SMESHGUI_Make2DFrom3DDlg::Groups,
-                                   SMESHGUI_Make2DFrom3DDlg::Btn ))->setChecked( enableGroups );
+//   QRadioButton* b = dynamic_cast<QRadioButton*>( sender());
+//   if ( b && !b->isChecked() )
+//     return;
+
+//   // enable "2D groups" field
+//   bool enableGroups = ( myDlg->mode() == SMESH::BND_1DFROM3D );
+//   myDlg->setObjectEnabled( SMESHGUI_Make2DFrom3DDlg::Groups, enableGroups );
+//   ((QToolButton*) myDlg->objectWg( SMESHGUI_Make2DFrom3DDlg::Groups,
+//                                    SMESHGUI_Make2DFrom3DDlg::Btn ))->setChecked( enableGroups );
   
-  // install filter
-  int id =  enableGroups ? SMESHGUI_Make2DFrom3DDlg::Groups : SMESHGUI_Make2DFrom3DDlg::Mesh;
-  onDeactivateObject( id );
-  onActivateObject( id );
+//   // install filter
+//   int id =  enableGroups ? SMESHGUI_Make2DFrom3DDlg::Groups : SMESHGUI_Make2DFrom3DDlg::Mesh;
+//   onDeactivateObject( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups );
+//   onActivateObject  ( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups );
+//   selectionDone();
 }
 
 void SMESHGUI_Make2DFrom3DOp::selectionDone()
 {
+  myDlg->clearSelection( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups );
   mySrcMesh = SMESH::SMESH_Mesh::_nil();
-  myDlg->clearSelection( SMESHGUI_Make2DFrom3DDlg::Groups );
 
   if ( !dlg() ) return;
 
@@ -258,13 +296,16 @@ void SMESHGUI_Make2DFrom3DOp::selectionDone()
       selected( names, types, ids );
       myDlg->selectObject( names, types, ids );
 
-      SALOME_ListIO sel; selectionMgr()->selectedObjects( sel, SVTK_Viewer::Type() );
-      if ( !sel.IsEmpty() )
+      // enable/desable "new mesh" button
+      bool isMesh = true;
+      for ( int i = 0; i < ids.count() && isMesh; ++i )
       {
-        SMESH::SMESH_IDSource_var IS = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>(sel.First());
-        if(!CORBA::is_nil(IS))
-          mySrcMesh = IS->GetMesh();
+        _PTR(SObject) sobj =
+          SMESHGUI::activeStudy()->studyDS()->FindObjectID( ids[i].toLatin1().constData() );
+        mySrcMesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>( sobj );  
+        isMesh = !mySrcMesh->_is_nil();
       }
+      myDlg->setNewMeshEnabled( isMesh );
     }
     catch ( const SALOME::SALOME_Exception& S_ex ) {
       SalomeApp_Tools::QtCatchCorbaException( S_ex );
@@ -276,8 +317,13 @@ void SMESHGUI_Make2DFrom3DOp::selectionDone()
 
 SUIT_SelectionFilter* SMESHGUI_Make2DFrom3DOp::createFilter( const int theId ) const
 {
-  MeshObjectType type = ( theId == SMESHGUI_Make2DFrom3DDlg::Groups ? GROUP_FACE : MESH );
-  SUIT_SelectionFilter* f = new SMESH_TypeFilter( type );
+  SMESHGUI_Make2DFrom3DOp* me = (SMESHGUI_Make2DFrom3DOp*) this;
+
+  QList<SUIT_SelectionFilter*> subFilters;
+  subFilters.append( & me->myMeshFilter );
+  subFilters.append( & me->myGroupFilter );
+
+  SUIT_SelectionFilter* f = new SMESH_LogicalFilter( subFilters, SMESH_LogicalFilter::LO_OR );
   return f;
 }
 
@@ -286,43 +332,61 @@ bool SMESHGUI_Make2DFrom3DOp::isValid( QString& msg ) const
   if ( !dlg() ) return false;
 
   // check if a mesh is selected
-  if ( mySrcMesh->_is_nil() )
+  if ( !myDlg->hasSelection( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups ))
   {
     msg = tr( "SMESH_ERR_NO_INPUT_MESH" );
     return false;
   }
-  // check if groups are selected
-  SMESH::Bnd_Dimension mode = myDlg->mode();
-  if ( mode == SMESH::BND_1DFROM3D )
+  QStringList entries;
+  dlg()->selectedObject( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups, entries );
+  const bool isMeshSelected = ( !mySrcMesh->_is_nil() );
+  if ( isMeshSelected )
   {
-    SMESH::SMESH_GroupBase_var grp;
-    QStringList entries;
-    dlg()->selectedObject( SMESHGUI_Make2DFrom3DDlg::Groups, entries );
-    if ( !entries.isEmpty() )
-    {
-      _PTR(SObject) sobj = SMESHGUI::activeStudy()->studyDS()->FindObjectID( entries[0].toLatin1().constData() );
-      if ( sobj )
-        grp = SMESH::SObjectToInterface<SMESH::SMESH_GroupBase>( sobj );
-    }
-    if ( grp->_is_nil() ) {
-      msg = tr( "SMESH_ERR_NO_INPUT_GROUP" );
+    // only one mesh is allowed
+    if ( entries.size() > 1 ) {
+      msg = tr( "SMESH_TOO_MANY_MESHES" );
       return false;
     }
   }
   else
   {
-    // check if mesh contains elements of required type
-    SMESH::Bnd_Dimension mode = myDlg->mode();
-
-    if ( mode == SMESH::BND_2DFROM3D && mySrcMesh->NbVolumes() == 0 ) {
-      msg = tr( "SMESH_ERR_NO_3D_ELEMENTS" );
-      return false;
+    // check if only groups are selected
+    for ( int i = 0; i < entries.count(); ++i )
+    {
+      SMESH::SMESH_GroupBase_var grp;
+      if ( _PTR(SObject) sobj = SMESHGUI::activeStudy()->studyDS()->FindObjectID( entries[i].toLatin1().constData() ))
+        grp = SMESH::SObjectToInterface<SMESH::SMESH_GroupBase>( sobj );
+      if ( grp->_is_nil() ) {
+        msg = tr( "SMESH_NOT_ONLY_GROUPS" );
+        return false;
+      }
     }
-    else if ( mode == SMESH::BND_1DFROM2D && mySrcMesh->NbFaces() == 0  ) {
-      msg = tr( "SMESH_ERR_NO_2D_ELEMENTS" );
-      return false;
+  }
+  // check if the selected objects contains elements of required type
+  bool hasFaces = false, hasVolumes = false;
+  SMESH::Bnd_Dimension mode = myDlg->mode();
+  for ( int i = 0; i < entries.count(); ++i )
+  {
+    SMESH::SMESH_IDSource_var idSource;
+    if ( _PTR(SObject) sobj = SMESHGUI::activeStudy()->studyDS()->FindObjectID( entries[i].toLatin1().constData() ))
+      idSource = SMESH::SObjectToInterface<SMESH::SMESH_IDSource>( sobj );
+    if ( !idSource->_is_nil() ) {
+      SMESH::array_of_ElementType_var types = idSource->GetTypes();
+      for ( int j = 0; j < types->length(); ++j )
+        if ( types[j] == SMESH::VOLUME )
+          hasVolumes = true;
+        else if ( types[j] == SMESH::FACE )
+          hasFaces = true;
     }
   }
+  if ( mode == SMESH::BND_2DFROM3D && !hasVolumes ) {
+    msg = tr( "SMESH_ERR_NO_3D_ELEMENTS" );
+    return false;
+  }
+  else if ( mode == SMESH::BND_1DFROM2D && !hasFaces  ) {
+    msg = tr( "SMESH_ERR_NO_2D_ELEMENTS" );
+    return false;
+  }
 
   // check if new mesh name is specified
   if ( myDlg->needNewMesh() && myDlg->getNewMeshName().isEmpty() ) {
@@ -335,7 +399,7 @@ bool SMESHGUI_Make2DFrom3DOp::isValid( QString& msg ) const
     msg = tr( "SMESH_ERR_GRP_NAME_NOT_SPECIFIED" );
     return false;
   }
-    
+
   return true;
 }
 
@@ -345,20 +409,41 @@ bool SMESHGUI_Make2DFrom3DOp::compute2DMesh( QStringList& theEntryList )
 
   bool ok = false;
   try {
+    SMESH::Bnd_Dimension mode = myDlg->mode();
+    QString meshName          = myDlg->needNewMesh() ? myDlg->getNewMeshName() : QString();
+    QString groupName         = myDlg->needGroup()   ? myDlg->getGroupName()   : QString();
+    bool copyAll              = myDlg->copySource();
+
     QStringList entries;
-    dlg()->selectedObject( SMESHGUI_Make2DFrom3DDlg::Groups, entries );
+    dlg()->selectedObject( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups, entries );
     SMESH::ListOfIDSources_var groups = new SMESH::ListOfIDSources;
-    groups->length( entries.count() );
-    for ( int i = 0; i < entries.count(); ++i )
+    QString wrongGroups = "";
+
+    if ( mySrcMesh->_is_nil() ) // get selected groups, find groups of wrong type
     {
-      _PTR(SObject) sobj = SMESHGUI::activeStudy()->studyDS()->FindObjectID( entries[i].toLatin1().constData() );
-      SMESH::SMESH_IDSource_var grp = SMESH::SObjectToInterface<SMESH::SMESH_IDSource>( sobj );  
-      groups[i] = grp;
+      int nbGroups = 0;
+      int goodType = ( mode == SMESH::BND_2DFROM3D ? SMESH::VOLUME : SMESH::FACE );
+      groups->length( entries.count() );
+      for ( int i = 0; i < entries.count(); ++i )
+      {
+        _PTR(SObject) sobj =
+          SMESHGUI::activeStudy()->studyDS()->FindObjectID( entries[i].toLatin1().constData() );
+        SMESH::SMESH_IDSource_var grp = SMESH::SObjectToInterface<SMESH::SMESH_IDSource>( sobj );  
+        SMESH::array_of_ElementType_var types = grp->GetTypes();
+        if ( types->length() < 1 || types[0] != goodType )
+        {
+          if ( !wrongGroups.isEmpty() )
+            wrongGroups += ", ";
+          wrongGroups += sobj->GetName().c_str();
+        }
+        else
+        {
+          groups[ nbGroups++ ] = grp;
+        }
+      }
+      groups->length( nbGroups );
+      mySrcMesh = groups[0]->GetMesh();
     }
-    SMESH::Bnd_Dimension mode = myDlg->mode();
-    QString meshName  = myDlg->needNewMesh() ? myDlg->getNewMeshName() : QString();
-    QString groupName = myDlg->needGroup()   ? myDlg->getGroupName()   : QString();
-    bool copyAll = myDlg->copySource();
 
     if ( !CORBA::is_nil( mySrcMesh ) ) {
       SMESH::SMESH_MeshEditor_var aMeshEditor = mySrcMesh->GetMeshEditor();
@@ -371,9 +456,11 @@ bool SMESHGUI_Make2DFrom3DOp::compute2DMesh( QStringList& theEntryList )
                                                                groups,
                                                                newMesh.out(),
                                                                newGrp.out() );
-      SUIT_MessageBox::information( myDlg,
-                                    tr("SMESH_INFORMATION"),
-                                    tr("NB_ADDED").arg( nbAdded ));
+      QString msg = tr("NB_ADDED").arg( nbAdded );
+      if ( !wrongGroups.isEmpty() )
+        msg += ".\n" + tr("WRONG_GROUPS").arg( wrongGroups );
+      SUIT_MessageBox::information( myDlg, tr("SMESH_INFORMATION"), msg);
+
       if ( !newMesh->_is_nil() ) {
         if( _PTR(SObject) aSObject = SMESH::ObjectToSObject( newMesh ) )
           theEntryList.append( aSObject->GetID().c_str() );
@@ -387,6 +474,11 @@ bool SMESHGUI_Make2DFrom3DOp::compute2DMesh( QStringList& theEntryList )
 #endif
       }
       ok = true;
+
+      for ( int i = 0; i < entries.count(); ++i )
+        if ( SMESH_Actor* actor = SMESH::FindActorByEntry( entries[i].toLatin1().constData() ))
+          SMESH::Update(actor->getIO(),actor->GetVisibility());
+      SMESH::RepaintCurrentView();
     }
   }
   catch ( ... ) {
index 272e7e09b7c544c380361af7e69156ecab462c9c..e0372955ac8aa025e551a73257b20594f4088b08 100644 (file)
@@ -26,6 +26,7 @@
 #include "SMESH_SMESHGUI.hxx"
 #include "SMESHGUI_Dialog.h"
 #include "SMESHGUI_SelectionOp.h"
+#include "SMESH_TypeFilter.hxx"
 
 #include <SALOMEconfig.h>
 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
@@ -45,7 +46,7 @@ class SMESHGUI_EXPORT SMESHGUI_Make2DFrom3DDlg :  public SMESHGUI_Dialog
   Q_OBJECT
 
 public:
-  enum { MeshGroups };
+  enum { MeshOrGroups };
 
   SMESHGUI_Make2DFrom3DDlg( QWidget* );
   virtual ~SMESHGUI_Make2DFrom3DDlg();
@@ -55,6 +56,8 @@ public:
   bool                 needNewMesh() const;
   QString              getNewMeshName() const;
   void                 setNewMeshName( const QString& );
+  void                 setNewMeshEnabled( bool );
+  bool                 getNewMeshEnabled() const;
 
   bool                 needGroup() const;
   QString              getGroupName() const;
@@ -110,6 +113,9 @@ private:
 private:
   SMESH::SMESH_Mesh_var              mySrcMesh;
   QPointer<SMESHGUI_Make2DFrom3DDlg> myDlg;
+
+  SMESH_TypeFilter                   myMeshFilter;
+  SMESH_TypeFilter                   myGroupFilter;
 };
 
 #endif // SMESHGUI_Make2DFrom3DOp_H
index 7a7b0fa9ee4716b61838fe9c2040686ccac1243b..9f5a486f8074ca375998ed4660d2732c54aa122f 100644 (file)
@@ -682,6 +682,8 @@ bool SMESHGUI_MergeDlg::ClickOnApply()
   } catch(...) {
   }
   
+  ListCoincident->clear();
+  
   SMESH::UpdateView();
   SMESHGUI::Modified();
   
index b5c337db28125905b11dc7689d01d762b36439c2..5bbd260f57baf52bcb1bcc8d0f5b6b3987c72a06 100644 (file)
@@ -5617,7 +5617,7 @@ It is impossible to read point coordinates from file</translation>
     </message>
     <message>
         <source>Groups</source>
-        <translation>2D groups</translation>
+        <translation>Mesh or groups</translation>
     </message>
     <message>
         <source>MODE</source>
@@ -5666,21 +5666,31 @@ It is impossible to read point coordinates from file</translation>
         <source>NB_ADDED</source>
         <translation>%1 boundary elements have been added</translation>
     </message>
+    <message>
+        <source>WRONG_GROUPS</source>
+        <translation>The following groups have not been processed
+as they are of improper type:
+%1</translation>
+    </message>
     <message>
         <source>SMESH_ERR_NO_INPUT_MESH</source>
         <translation>Source mesh is not specified</translation>
     </message>
     <message>
-        <source>SMESH_ERR_NO_INPUT_GROUP</source>
-        <translation>2D group is not specified</translation>
+        <source>SMESH_TOO_MANY_MESHES</source>
+        <translation>Only one mesh can be processed at once</translation>
+    </message>
+    <message>
+        <source>SMESH_NOT_ONLY_GROUPS</source>
+        <translation>Can't process meshes and groups at once</translation>
     </message>
     <message>
         <source>SMESH_ERR_NO_3D_ELEMENTS</source>
-        <translation>The source object does not contain 3D elements</translation>
+        <translation>The source objects do not contain 3D elements</translation>
     </message>
     <message>
         <source>SMESH_ERR_NO_2D_ELEMENTS</source>
-        <translation>The source object does not contain 2D elements</translation>
+        <translation>The source objects do not contain 2D elements</translation>
     </message>
     <message>
         <source>SMESH_ERR_MESH_NAME_NOT_SPECIFIED</source>
index ef41b4c6f2311154c60ac85e38ec29c393929952..1fd5f54150aee1b9d616deaae8175d1d567d6a25 100644 (file)
@@ -632,7 +632,10 @@ SALOMEDS::SObject_ptr SMESH_Gen_i::PublishSubMesh (SALOMEDS::Study_ptr      theS
     SetName( aRootSO, aRootName );
 
     // Add new submesh to corresponding sub-tree
-    aSubMeshSO = publish (theStudy, theSubMesh, aRootSO, 0, "ICON_SMESH_TREE_MESH_WARN");
+    SMESH::array_of_ElementType_var elemTypes = theSubMesh->GetTypes();
+    const int isEmpty = ( elemTypes->length() == 0 );
+    const char* pm[2] = { "ICON_SMESH_TREE_MESH", "ICON_SMESH_TREE_MESH_WARN" };
+    aSubMeshSO = publish (theStudy, theSubMesh, aRootSO, 0, pm[isEmpty] );
     if ( aSubMeshSO->_is_nil() )
       return aSubMeshSO._retn();
   }
index 20eb9798a9a4e397bc4d87faf7d19c4701d70b0b..2473b8c4ca641c732b49220f3df809d456180d70 100644 (file)
@@ -592,8 +592,12 @@ SMESH::long_array* SMESH_GroupBase_i::GetIDs()
 SMESH::array_of_ElementType* SMESH_GroupBase_i::GetTypes()
 {
   SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
-  types->length( 1 );
-  types[0] = GetType();
+  if ( SMESHDS_GroupBase* ds = GetGroupDS() )
+    if ( !ds->IsEmpty() )
+    {
+      types->length( 1 );
+      types[0] = GetType();
+    }
   return types._retn();
 }
 
index 9eb4ebdfd017e9e46b338055a4c87cf287a73d5c..94273a2e07a485b3160ea4c9124cd11fe6b16c6d 100644 (file)
@@ -432,8 +432,10 @@ struct _IDSource : public POA_SMESH::SMESH_IDSource
   SMESH::array_of_ElementType* GetTypes()
   {
     SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
-    types->length( 1 );
-    types[0] = _type;
+    if ( _ids.length() > 0 ) {
+      types->length( 1 );
+      types[0] = _type;
+    }
     return types._retn();
   }
 };
@@ -5881,20 +5883,37 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
   if ( dim > SMESH::BND_1DFROM2D )
     THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
 
-  // check that groups belongs to to this mesh and is not this mesh
-  const int nbGroups = groups.length();
-  for ( int i = 0; i < nbGroups; ++i )
+  // separate groups belonging to this and other mesh
+  SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
+  SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
+  groupsOfThisMesh->length( groups.length() );
+  groupsOfOtherMesh->length( groups.length() );
+  int nbGroups = 0, nbGroupsOfOtherMesh = 0;
+  for ( int i = 0; i < groups.length(); ++i )
   {
     SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
     if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
-      THROW_SALOME_CORBA_EXCEPTION("group does not belong to this mesh", SALOME::BAD_PARAM);
+      groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
+    else
+      groupsOfThisMesh[ nbGroups++ ] = groups[i];
     if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
       THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
   }
+  groupsOfThisMesh->length( nbGroups );
+  groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
 
+  int nbAdded = 0;
   TPythonDump pyDump;
 
-  int nbAdded = 0;
+  if ( nbGroupsOfOtherMesh > 0 )
+  {
+    // process groups belonging to another mesh
+    SMESH::SMESH_Mesh_var    otherMesh = groupsOfOtherMesh[0]->GetMesh();
+    SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
+    nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
+                                             groupsOfOtherMesh, mesh, group );
+  }
+
   SMESH::SMESH_Mesh_var mesh_var;
   SMESH::SMESH_Group_var group_var;
 
@@ -5931,12 +5950,12 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
 
   TIDSortedElemSet elements;
 
-  if ( nbGroups > 0 )
+  if ( groups.length() > 0 )
   {
     for ( int i = 0; i < nbGroups; ++i )
     {
       elements.clear();
-      if ( idSourceToSet( groups[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/false ))
+      if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
       {
         SMESH::Bnd_Dimension bdim = 
           ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
index 9ccc8bc8ce8ec378e8b4b4eb64fa99a0544372d9..475254f7c43408dc328116cd1120d08185e23b54 100644 (file)
@@ -557,23 +557,27 @@ SMESH::array_of_ElementType* SMESH_subMesh_i::GetTypes()
   SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
 
   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
-  TopoDS_Shape shape = aSubMesh->GetSubShape();
-  while ( !shape.IsNull() && shape.ShapeType() == TopAbs_COMPOUND )
+  if ( SMESHDS_SubMesh* smDS = aSubMesh->GetSubMeshDS() )
   {
-    TopoDS_Iterator it( shape );
-    shape = it.More() ? it.Value() : TopoDS_Shape();
-  }
-  if ( !shape.IsNull() )
-  {
-    types->length( 1 );
-    switch ( ::SMESH_Gen::GetShapeDim( shape ))
+    SMDS_ElemIteratorPtr eIt = smDS->GetElements();
+    if ( eIt->more() )
+    {
+      types->length( 1 );
+      types[0] = SMESH::ElementType( eIt->next()->GetType());
+    }
+    else if ( smDS->GetNodes()->more() )
     {
-    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_Shape shape = aSubMesh->GetSubShape();
+      while ( !shape.IsNull() && shape.ShapeType() == TopAbs_COMPOUND )
+      {
+        TopoDS_Iterator it( shape );
+        shape = it.More() ? it.Value() : TopoDS_Shape();
+      }
+      if ( !shape.IsNull() && shape.ShapeType() == TopAbs_VERTEX )
+      {
+        types->length( 1 );
+        types[0] = SMESH::NODE;
+      }
     }
   }
   return types._retn();
index 60dd74951291d186919ee81ea4461185d778d8f4..5f3bfd6c4755eb03e7dae16f9b0c4e97f3f0e04c 100644 (file)
@@ -490,6 +490,25 @@ def CheckPlugin(plugin):
         return False
     return True
 
+## Private method. Add geom (sub-shape of the main shape) into the study if not yet there
+def AssureGeomPublished(mesh, geom, name=''):
+    if not isinstance( geom, geompyDC.GEOM._objref_GEOM_Object ):
+        return
+    if not geom.IsSame( mesh.geom ) and not geom.GetStudyEntry():
+        ## set the study
+        studyID = mesh.smeshpyD.GetCurrentStudy()._get_StudyId()
+        if studyID != mesh.geompyD.myStudyId:
+            mesh.geompyD.init_geom( mesh.smeshpyD.GetCurrentStudy())
+        ## get a name
+        if not name and geom.GetShapeType() != geompyDC.GEOM.COMPOUND:
+            # for all groups SubShapeName() returns "Compound_-1"
+            name = mesh.geompyD.SubShapeName(geom, mesh.geom)
+        if not name:
+            name = "%s_%s"%(geom.GetShapeType(), id(geom)%10000)
+        ## publish
+        mesh.geompyD.addToStudyInFather( mesh.geom, geom, name )
+    return
+
 # end of l1_auxiliary
 ## @}
 
@@ -1164,19 +1183,7 @@ class Mesh:
     #  @return an object of type SMESH_SubMesh, representing a part of mesh, which lies on the given shape
     #  @ingroup l2_submeshes
     def GetSubMesh(self, geom, name):
-        if not geom.IsSame( self.geom ) and not geom.GetStudyEntry():
-            ## set the study
-            studyID = self.smeshpyD.GetCurrentStudy()._get_StudyId()
-            if studyID != self.geompyD.myStudyId:
-                self.geompyD.init_geom( self.smeshpyD.GetCurrentStudy())
-            ## get a name
-            if not name and geom.GetShapeType() != geompyDC.GEOM.COMPOUND:
-                # for all groups SubShapeName() returns "Compound_-1"
-                name = self.geompyD.SubShapeName(geom, self.geom)
-            if not name:
-                name = "%s_%s"%(geom.GetShapeType(), id(geom)%10000)
-            ## publish
-            self.geompyD.addToStudyInFather( self.geom, geom, name )
+        AssureGeomPublished( self, geom, name )
         submesh = self.mesh.GetSubMesh( geom, name )
         return submesh
 
@@ -1580,7 +1587,7 @@ class Mesh:
             salome.sg.updateObjBrowser(1)
 
     ## Computes a tetrahedral mesh using AutomaticLength + MEFISTO + NETGEN
-    #  @param fineness [0,-1] defines mesh fineness
+    #  @param fineness [0.0,1.0] defines mesh fineness
     #  @return True or False
     #  @ingroup l3_algos_basic
     def AutomaticTetrahedralization(self, fineness=0):
@@ -1597,7 +1604,7 @@ class Mesh:
         return self.Compute()
 
     ## Computes an hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
-    #  @param fineness [0,-1] defines mesh fineness
+    #  @param fineness [0.0, 1.0] defines mesh fineness
     #  @return True or False
     #  @ingroup l3_algos_basic
     def AutomaticHexahedralization(self, fineness=0):
@@ -1667,8 +1674,8 @@ class Mesh:
             pass
         pass
 
-    ## Deprecated, used only for compatibility! Please, use ExportMED() method instead.
-    ## Exports the mesh in a file in MED format and chooses the \a version of MED format
+    ## Deprecated, used only for compatibility! Please, use ExportToMEDX() method instead.
+    #  Exports the mesh in a file in MED format and chooses the \a version of MED format
     ## allowing to overwrite the file if it exists or add the exported data to its contents
     #  @param f the file name
     #  @param version values are SMESH.MED_V2_1, SMESH.MED_V2_2
@@ -1767,58 +1774,33 @@ class Mesh:
     #  @return SMESH_GroupOnGeom
     #  @ingroup l2_grps_create
     def GroupOnGeom(self, grp, name="", typ=None):
+        AssureGeomPublished( self, grp, name )
         if name == "":
             name = grp.GetName()
-
-        if typ == None:
-            tgeo = str(grp.GetShapeType())
-            if tgeo == "VERTEX":
-                typ = NODE
-            elif tgeo == "EDGE":
-                typ = EDGE
-            elif tgeo == "FACE":
-                typ = FACE
-            elif tgeo == "SOLID":
-                typ = VOLUME
-            elif tgeo == "SHELL":
-                typ = VOLUME
-            elif tgeo == "COMPOUND":
-                try: # it raises on a compound of compounds
-                    if len( self.geompyD.GetObjectIDs( grp )) == 0:
-                        print "Mesh.Group: empty geometric group", GetName( grp )
-                        return 0
-                    pass
-                except:
-                    pass
-                if grp.GetType() == 37: # GEOMImpl_Types.hxx: #define GEOM_GROUP 37
-                    # group
-                    tgeo = self.geompyD.GetType(grp)
-                    if tgeo == geompyDC.ShapeType["VERTEX"]:
-                        typ = NODE
-                    elif tgeo == geompyDC.ShapeType["EDGE"]:
-                        typ = EDGE
-                    elif tgeo == geompyDC.ShapeType["FACE"]:
-                        typ = FACE
-                    elif tgeo == geompyDC.ShapeType["SOLID"]:
-                        typ = VOLUME
-                        pass
-                    pass
-                else:
-                    # just a compound
-                    for elemType, shapeType in [[VOLUME,"SOLID"],[FACE,"FACE"],
-                                                [EDGE,"EDGE"],[NODE,"VERTEX"]]:
-                        if self.geompyD.SubShapeAll(grp,geompyDC.ShapeType[shapeType]):
-                            typ = elemType
-                            break
-                        pass
-                    pass
-                pass
-            pass
-        if typ == None:
-            print "Mesh.Group: bad first argument: expected a group, a vertex, an edge, a face or a solid"
-            return 0
+        if not typ:
+            typ = self._groupTypeFromShape( grp )
+        return self.mesh.CreateGroupFromGEOM(typ, name, grp)
+
+    ## Pivate method to get a type of group on geometry
+    def _groupTypeFromShape( self, shape ):
+        tgeo = str(shape.GetShapeType())
+        if tgeo == "VERTEX":
+            typ = NODE
+        elif tgeo == "EDGE":
+            typ = EDGE
+        elif tgeo == "FACE" or tgeo == "SHELL":
+            typ = FACE
+        elif tgeo == "SOLID" or tgeo == "COMPSOLID":
+            typ = VOLUME
+        elif tgeo == "COMPOUND":
+            sub = self.geompyD.SubShapeAll( shape, geompyDC.ShapeType["SHAPE"])
+            if not sub:
+                raise ValueError,"_groupTypeFromShape(): empty geometric group or compound '%s'" % GetName(shape)
+            return self._groupTypeFromShape( sub[0] )
         else:
-            return self.mesh.CreateGroupFromGEOM(typ, name, grp)
+            raise ValueError, \
+                  "_groupTypeFromShape(): invalid geometry '%s'" % GetName(shape)
+        return typ
 
     ## Creates a mesh group with given \a name based on the \a filter which
     ## is a special type of group dynamically updating it's contents during
@@ -4480,7 +4462,7 @@ class Mesh_Algorithm:
             self.geom = mesh.geom
         else:
             self.geom = geom
-            self.AssureGeomPublished( geom )
+            AssureGeomPublished( mesh, geom )
             try:
                 name = GetName(geom)
                 pass
@@ -4492,25 +4474,6 @@ class Mesh_Algorithm:
         TreatHypoStatus( status, algo.GetName(), name, True )
         return
 
-    ## Private method. Add geom into the study if not yet there
-    def AssureGeomPublished(self, geom, name=''):
-        if not isinstance( geom, geompyDC.GEOM._objref_GEOM_Object ):
-            return
-        if not geom.IsSame( self.mesh.geom ) and not geom.GetStudyEntry():
-            ## set the study
-            studyID = self.mesh.smeshpyD.GetCurrentStudy()._get_StudyId()
-            if studyID != self.mesh.geompyD.myStudyId:
-                self.mesh.geompyD.init_geom( self.mesh.smeshpyD.GetCurrentStudy())
-            ## get a name
-            if not name and geom.GetShapeType() != geompyDC.GEOM.COMPOUND:
-                # for all groups SubShapeName() returns "Compound_-1"
-                name = self.mesh.geompyD.SubShapeName(geom, self.mesh.geom)
-            if not name:
-                name = "%s_%s"%(geom.GetShapeType(), id(geom)%10000)
-            ## publish
-            self.mesh.geompyD.addToStudyInFather( self.mesh.geom, geom, name )
-        return
-
     def CompareHyp (self, hyp, args):
         print "CompareHyp is not implemented for ", self.__class__.__name__, ":", hyp.GetName()
         return False
@@ -4860,7 +4823,7 @@ class Mesh_Segment(Mesh_Algorithm):
         ### 0D algorithm
         if self.geom is None:
             raise RuntimeError, "Attemp to create SegmentAroundVertex_0D algoritm on None shape"
-        self.AssureGeomPublished( self.geom )
+        AssureGeomPublished( self.mesh, self.geom )
         name = GetName(self.geom)
 
         algo = self.FindAlgorithm("SegmentAroundVertex_0D", self.mesh.smeshpyD)
@@ -5112,8 +5075,8 @@ class Mesh_Triangle(Mesh_Algorithm):
     #  @param theConstantSizeDistance : distance until which the mesh size will be kept constant on theFace                                                      
     #  @ingroup l3_hypos_blsurf
     def SetAttractorGeom(self, theFace, theAttractor, theStartSize, theEndSize, theInfluenceDistance, theConstantSizeDistance):
-        self.AssureGeomPublished( theFace )
-        self.AssureGeomPublished( theAttractor )
+        AssureGeomPublished( self.mesh, theFace )
+        AssureGeomPublished( self.mesh, theAttractor )
         #  Parameter of BLSURF algo
         self.Parameters().SetAttractorGeom(theFace, theAttractor, theStartSize, theEndSize, theInfluenceDistance, theConstantSizeDistance)
         
@@ -5121,7 +5084,7 @@ class Mesh_Triangle(Mesh_Algorithm):
     #  @param theFace      : face on which the attractor has to be removed                               
     #  @ingroup l3_hypos_blsurf
     def UnsetAttractorGeom(self, theFace):
-        self.AssureGeomPublished( theFace )
+        AssureGeomPublished( self.mesh, theFace )
         #  Parameter of BLSURF algo
         self.Parameters().SetAttractorGeom(theFace)
 
@@ -5620,7 +5583,7 @@ class Mesh_Tetrahedron(Mesh_Algorithm):
     ## To set an enforced vertex given a GEOM vertex, group or compound.
     #  @ingroup l3_hypos_ghs3dh
     def SetEnforcedVertexGeom(self, theVertex, size):
-        self.AssureGeomPublished( theVertex )
+        AssureGeomPublished( self.mesh, theVertex )
         #  Advanced parameter of GHS3D
         return self.Parameters().SetEnforcedVertexGeom(theVertex, size)
 
@@ -5629,14 +5592,14 @@ class Mesh_Tetrahedron(Mesh_Algorithm):
     #  Only on meshes w/o geometry
     #  @ingroup l3_hypos_ghs3dh
     def SetEnforcedVertexGeomWithGroup(self, theVertex, size, groupName):
-        self.AssureGeomPublished( theVertex )
+        AssureGeomPublished( self.mesh, theVertex )
         #  Advanced parameter of GHS3D
         return self.Parameters().SetEnforcedVertexGeomWithGroup(theVertex, size,groupName)
 
     ## To remove an enforced vertex given a GEOM vertex, group or compound.
     #  @ingroup l3_hypos_ghs3dh
     def RemoveEnforcedVertexGeom(self, theVertex):
-        self.AssureGeomPublished( theVertex )
+        AssureGeomPublished( self.mesh, theVertex )
         #  Advanced parameter of GHS3D
         return self.Parameters().RemoveEnforcedVertexGeom(theVertex)
 
@@ -5782,9 +5745,9 @@ class Mesh_Projection1D(Mesh_Algorithm):
     #  @param UseExisting if ==true - searches for the existing hypothesis created with
     #                     the same parameters, else (default) - creates a new one
     def SourceEdge(self, edge, mesh=None, srcV=None, tgtV=None, UseExisting=0):
-        self.AssureGeomPublished( edge )
-        self.AssureGeomPublished( srcV )
-        self.AssureGeomPublished( tgtV )
+        AssureGeomPublished( self.mesh, edge )
+        AssureGeomPublished( self.mesh, srcV )
+        AssureGeomPublished( self.mesh, tgtV )
         hyp = self.Hypothesis("ProjectionSource1D", [edge,mesh,srcV,tgtV],
                               UseExisting=0)
                               #UseExisting=UseExisting, CompareMethod=self.CompareSourceEdge)
@@ -5832,7 +5795,7 @@ class Mesh_Projection2D(Mesh_Algorithm):
     def SourceFace(self, face, mesh=None, srcV1=None, tgtV1=None,
                    srcV2=None, tgtV2=None, UseExisting=0):
         for geom in [ face, srcV1, tgtV1, srcV2, tgtV2 ]:
-            self.AssureGeomPublished( geom )
+            AssureGeomPublished( self.mesh, geom )
         hyp = self.Hypothesis("ProjectionSource2D", [face,mesh,srcV1,tgtV1,srcV2,tgtV2],
                               UseExisting=0)
                               #UseExisting=UseExisting, CompareMethod=self.CompareSourceFace)
@@ -5879,7 +5842,7 @@ class Mesh_Projection3D(Mesh_Algorithm):
     def SourceShape3D(self, solid, mesh=0, srcV1=0, tgtV1=0,
                       srcV2=0, tgtV2=0, UseExisting=0):
         for geom in [ solid, srcV1, tgtV1, srcV2, tgtV2 ]:
-            self.AssureGeomPublished( geom )
+            AssureGeomPublished( self.mesh, geom )
         hyp = self.Hypothesis("ProjectionSource3D",
                               [solid,mesh,srcV1,tgtV1,srcV2,tgtV2],
                               UseExisting=0)
@@ -6141,7 +6104,7 @@ class Mesh_UseExistingElements(Mesh_Algorithm):
         if self.algo.GetName() == "Import_2D":
             raise ValueError, "algoritm dimension mismatch"
         for group in groups:
-            self.AssureGeomPublished( group )
+            AssureGeomPublished( self.mesh, group )
         hyp = self.Hypothesis("ImportSource1D", [groups, toCopyMesh, toCopyGroups],
                               UseExisting=UseExisting, CompareMethod=self._compareHyp)
         hyp.SetSourceEdges(groups)
@@ -6158,7 +6121,7 @@ class Mesh_UseExistingElements(Mesh_Algorithm):
         if self.algo.GetName() == "Import_1D":
             raise ValueError, "algoritm dimension mismatch"
         for group in groups:
-            self.AssureGeomPublished( group )
+            AssureGeomPublished( self.mesh, group )
         hyp = self.Hypothesis("ImportSource2D", [groups, toCopyMesh, toCopyGroups],
                               UseExisting=UseExisting, CompareMethod=self._compareHyp)
         hyp.SetSourceFaces(groups)
index ffc906a62bdadcaad6be5ac264eebc2a077cc025..f9aa827012987e95b9f596f1b283ef66aa797f19 100644 (file)
@@ -237,6 +237,8 @@ bool StdMeshers_MEFISTO_2D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh
   Z nutysu = 1;           // 1: il existe un fonction areteideale_()
   // Z  nutysu=0;         // 0: on utilise aretmx
   R aretmx = _edgeLength; // longueur max aretes future triangulation
+  if ( _hypMaxElementArea )
+    aretmx *= 1.5;
   
   nblf = nbWires;
   
index 8aa83e935233528e0cc0528b82ebcc0446b34302..3589a7870609db0a94ccff51a622ac9595b32ff5 100644 (file)
@@ -2218,9 +2218,9 @@ bool StdMeshers_Quadrangle_2D::ComputeReduced (SMESH_Mesh &        aMesh,
     int nrows = nr1 - 1;
     int ncol_top = nt1 - 1;
     int ncol_bot = nb1 - 1;
-    // maximum number of bottom elements for "tree" simple reduce 3->1
-    int max_tree31 = ncol_top * pow(3.0, nrows);
-    if (ncol_bot > max_tree31)
+    // number of rows needed to reduce ncol_bot to ncol_top using simple 3->1 "tree" (see below)
+    int nrows_tree31 = int( log( ncol_bot / ncol_top ) / log( 3 )); // = log x base 3
+    if ( nrows < nrows_tree31 )
       MultipleReduce = true;
   }
 
@@ -2543,9 +2543,12 @@ bool StdMeshers_Quadrangle_2D::ComputeReduced (SMESH_Mesh &        aMesh,
     // maximum number of bottom elements for "linear" simple reduce 4->2
     int max_lin31 = ncol_top + ncol_top * 2 * nrows;
     // maximum number of bottom elements for "tree" simple reduce 4->2
-    int max_tree42 = npair_top * pow(2.0, nrows + 1);
-    if (ncol_top > npair_top * 2) {
-      int delta = ncol_bot - max_tree42;
+    int max_tree42 = 0;
+    // number of rows needed to reduce ncol_bot to ncol_top using simple 4->2 "tree"
+    int nrows_tree42 = int( log2( ncol_bot / ncol_top )); // needed to avoid overflow at pow(2)
+    if (ncol_top > npair_top * 2 && nrows_tree42 < nrows) {
+      max_tree42 = npair_top * pow(2.0, nrows + 1);
+      int delta = ncol_bot - int( max_tree42 );
       for (int irow = 1; irow < nrows; irow++) {
         int nfour = delta / 4;
         delta -= nfour * 2;
index 9487a6148b003600eb140c0fdc2178a5b975f21e..6fd8738add3d8db70dc9baca30e5d19bc9cde2a6 100644 (file)
 #include "utilities.h"
 
 #include <BRep_Tool.hxx>
+#include <Bnd_B2d.hxx>
+#include <Bnd_B3d.hxx>
+#include <ElCLib.hxx>
 #include <GCPnts_AbscissaPoint.hxx>
+#include <Geom2d_Circle.hxx>
+#include <Geom2d_Line.hxx>
+#include <Geom2d_TrimmedCurve.hxx>
 #include <GeomAdaptor_Curve.hxx>
+#include <Geom_Circle.hxx>
 #include <Geom_Curve.hxx>
+#include <Geom_Line.hxx>
+#include <Geom_TrimmedCurve.hxx>
 #include <Precision.hxx>
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
@@ -268,6 +277,10 @@ namespace VISCOUS
     gp_XYZ*              _plnNorm;
 
     _2NearEdges() { _nodes[0]=_nodes[1]=0; _plnNorm = 0; }
+    void reverse() {
+      std::swap( _nodes[0], _nodes[1] );
+      std::swap( _wgt[0], _wgt[1] );
+    }
   };
   //--------------------------------------------------------------------------------
   /*!
@@ -362,9 +375,8 @@ namespace VISCOUS
     // FACE's WOL, srink on which is forbiden due to algo on the adjacent SOLID
     set< TGeomID >                   _noShrinkFaces;
 
-    // end index in _edges of _LayerEdge's based on EDGE (map key) to
-    // FACE (maybe NULL) they are inflated along
-    //map< int, TopoDS_Face >          _endEdge2Face;
+    // <EDGE to smooth on> to <it's curve>
+    map< TGeomID,Handle(Geom_Curve)> _edge2curve;
 
     // end indices in _edges of _LayerEdge on one shape to smooth
     vector< int >                    _endEdgeToSmooth;
@@ -377,6 +389,13 @@ namespace VISCOUS
                const StdMeshers_ViscousLayers* h=0,
                _MeshOfSolid*                   m=0) :_solid(s), _hyp(h), _proxyMesh(m) {}
     ~_SolidData();
+
+    Handle(Geom_Curve) CurveForSmooth( const TopoDS_Edge&    E,
+                                       const int             iFrom,
+                                       const int             iTo,
+                                       Handle(Geom_Surface)& surface,
+                                       const TopoDS_Face&    F,
+                                       SMESH_MesherHelper&   helper);
   };
   //--------------------------------------------------------------------------------
   /*!
@@ -433,7 +452,13 @@ namespace VISCOUS
                         const double            cosin);
     void limitStepSize( _SolidData& data, const double minSize);
     bool inflate(_SolidData& data);
-    bool smoothAndCheck(_SolidData& data, int nbSteps, double & distToIntersection);
+    bool smoothAndCheck(_SolidData& data, const int nbSteps, double & distToIntersection);
+    bool smoothAnalyticEdge( _SolidData&           data,
+                             const int             iFrom,
+                             const int             iTo,
+                             Handle(Geom_Surface)& surface,
+                             const TopoDS_Face&    F,
+                             SMESH_MesherHelper&   helper);
     bool updateNormals( _SolidData& data, SMESH_MesherHelper& helper );
     bool refine(_SolidData& data);
     bool shrink();
@@ -1994,7 +2019,7 @@ bool _ViscousBuilder::inflate(_SolidData& data)
 //================================================================================
 
 bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
-                                     int         nbSteps,
+                                     const int   nbSteps,
                                      double &    distToIntersection)
 {
   if ( data._endEdgeToSmooth.empty() )
@@ -2028,21 +2053,25 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
     TGeomID sInd = data._edges[ iBeg ]->_nodes[0]->getshapeId();
 
     if ( data._edges[ iBeg ]->IsOnEdge() )
-    {
-      dumpFunction(SMESH_Comment("smooth")<<data._index << "_Ed"<<sInd <<"_InfStep"<<nbSteps);
-      // smooth on EDGE's
-      int step = 0;
-      do {
-        moved = false;
-        for ( int i = iBeg; i < iEnd; ++i )
-        {
-          moved |= data._edges[i]->SmoothOnEdge(surface, F, helper);
+    { // try a simple solution on an analytic EDGE
+      if ( !smoothAnalyticEdge( data, iBeg, iEnd, surface, F, helper ))
+      {
+        dumpFunction(SMESH_Comment("smooth")<<data._index << "_Ed"<<sInd <<"_InfStep"<<nbSteps);
+        // smooth on EDGE's
+        int step = 0;
+        do {
+          moved = false;
+          for ( int i = iBeg; i < iEnd; ++i )
+          {
+            moved |= data._edges[i]->SmoothOnEdge(surface, F, helper);
+          }
+          dumpCmd( SMESH_Comment("# end step ")<<step);
         }
-        dumpCmd( SMESH_Comment("# end step ")<<step);
-      }
-      while ( moved && step++ < 5 );
+        while ( moved && step++ < 5 );
+        //cout << " NB STEPS: " << step << endl;
 
-      dumpFunctionEnd();
+        dumpFunctionEnd();
+      }
     }
     else
     {
@@ -2094,7 +2123,7 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
   double dist;
   const SMDS_MeshElement* intFace = 0;
 #ifdef __myDEBUG
-  const SMDS_MeshElement* *closestFace = 0;
+  const SMDS_MeshElement* closestFace = 0;
   int iLE = 0;
 #endif
   for ( unsigned i = 0; i < data._edges.size(); ++i )
@@ -2124,6 +2153,253 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
   return true;
 }
 
+//================================================================================
+/*!
+ * \brief Return a curve of the EDGE to be used for smoothing and arrange
+ *        _LayerEdge's to be in a consequent order
+ */
+//================================================================================
+
+Handle(Geom_Curve) _SolidData::CurveForSmooth( const TopoDS_Edge&    E,
+                                               const int             iFrom,
+                                               const int             iTo,
+                                               Handle(Geom_Surface)& surface,
+                                               const TopoDS_Face&    F,
+                                               SMESH_MesherHelper&   helper)
+{
+  TGeomID eIndex = helper.GetMeshDS()->ShapeToIndex( E );
+
+  map< TGeomID, Handle(Geom_Curve)>::iterator i2curve = _edge2curve.find( eIndex );
+
+  if ( i2curve == _edge2curve.end() )
+  {
+    // sort _LayerEdge's by position on the EDGE
+    {
+      map< double, _LayerEdge* > u2edge;
+      for ( int i = iFrom; i < iTo; ++i )
+        u2edge.insert( make_pair( helper.GetNodeU( E, _edges[i]->_nodes[0] ), _edges[i] ));
+
+      ASSERT( u2edge.size() == iTo - iFrom );
+      map< double, _LayerEdge* >::iterator u2e = u2edge.begin();
+      for ( int i = iFrom; i < iTo; ++i, ++u2e )
+        _edges[i] = u2e->second;
+
+      // set _2neibors according to the new order
+      for ( int i = iFrom; i < iTo-1; ++i )
+        if ( _edges[i]->_2neibors->_nodes[1] != _edges[i+1]->_nodes.back() )
+          _edges[i]->_2neibors->reverse();
+      if ( u2edge.size() > 1 &&
+           _edges[iTo-1]->_2neibors->_nodes[0] != _edges[iTo-2]->_nodes.back() )
+        _edges[iTo-1]->_2neibors->reverse();
+    }
+
+    SMESHDS_SubMesh* smDS = helper.GetMeshDS()->MeshElements( eIndex );
+
+    TopLoc_Location loc; double f,l;
+
+    Handle(Geom_Line)   line;
+    Handle(Geom_Circle) circle;
+    bool isLine, isCirc;
+    if ( F.IsNull() ) // 3D case
+    {
+      // check if the EDGE is a line
+      Handle(Geom_Curve) curve = BRep_Tool::Curve( E, loc, f, l);
+      if ( curve->IsKind( STANDARD_TYPE( Geom_TrimmedCurve )))
+        curve = Handle(Geom_TrimmedCurve)::DownCast( curve )->BasisCurve();
+
+      line   = Handle(Geom_Line)::DownCast( curve );
+      circle = Handle(Geom_Circle)::DownCast( curve );
+      isLine = (!line.IsNull());
+      isCirc = (!circle.IsNull());
+
+      if ( !isLine && !isCirc ) // Check if the EDGE is close to a line
+      {
+        Bnd_B3d bndBox;
+        SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
+        while ( nIt->more() )
+          bndBox.Add( SMESH_TNodeXYZ( nIt->next() ));
+        gp_XYZ size = bndBox.CornerMax() - bndBox.CornerMin();
+
+        SMESH_TNodeXYZ p0( _edges[iFrom]->_2neibors->_nodes[0] );
+        SMESH_TNodeXYZ p1( _edges[iFrom]->_2neibors->_nodes[1] );
+        const double lineTol = 1e-2 * ( p0 - p1 ).Modulus();
+        for ( int i = 0; i < 3 && !isLine; ++i )
+          isLine = ( size.Coord( i+1 ) <= lineTol );
+      }
+      if ( !isLine && !isCirc && iTo-iFrom > 2) // Check if the EDGE is close to a circle
+      {
+        // TODO
+      }
+    }
+    else // 2D case
+    {
+      // check if the EDGE is a line
+      Handle(Geom2d_Curve) curve = BRep_Tool::CurveOnSurface( E, F, f, l);
+      if ( curve->IsKind( STANDARD_TYPE( Geom2d_TrimmedCurve )))
+        curve = Handle(Geom2d_TrimmedCurve)::DownCast( curve )->BasisCurve();
+
+      Handle(Geom2d_Line)   line2d   = Handle(Geom2d_Line)::DownCast( curve );
+      Handle(Geom2d_Circle) circle2d = Handle(Geom2d_Circle)::DownCast( curve );
+      isLine = (!line2d.IsNull());
+      isCirc = (!circle2d.IsNull());
+
+      if ( !isLine && !isCirc) // Check if the EDGE is close to a line
+      {
+        Bnd_B2d bndBox;
+        SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
+        while ( nIt->more() )
+          bndBox.Add( helper.GetNodeUV( F, nIt->next() ));
+        gp_XY size = bndBox.CornerMax() - bndBox.CornerMin();
+
+        const double lineTol = 1e-2 * sqrt( bndBox.SquareExtent() );
+        for ( int i = 0; i < 2 && !isLine; ++i )
+          isLine = ( size.Coord( i+1 ) <= lineTol );
+      }
+      if ( !isLine && !isCirc && iTo-iFrom > 2) // Check if the EDGE is close to a circle
+      {
+        // TODO
+      }
+      if ( isLine )
+      {
+        line = new Geom_Line( gp::OX() ); // only type does matter
+      }
+      else if ( isCirc )
+      {
+        gp_Pnt2d p = circle2d->Location();
+        gp_Ax2 ax( gp_Pnt( p.X(), p.Y(), 0), gp::DX());
+        circle = new Geom_Circle( ax, 1.); // only center position does matter
+      }
+    }
+
+    Handle(Geom_Curve)& res = _edge2curve[ eIndex ];
+    if ( isLine )
+      res = line;
+    else if ( isCirc )
+      res = circle;
+
+    return res;
+  }
+  return i2curve->second;
+}
+
+//================================================================================
+/*!
+ * \brief smooth _LayerEdge's on a staight EDGE or circular EDGE
+ */
+//================================================================================
+
+bool _ViscousBuilder::smoothAnalyticEdge( _SolidData&           data,
+                                          const int             iFrom,
+                                          const int             iTo,
+                                          Handle(Geom_Surface)& surface,
+                                          const TopoDS_Face&    F,
+                                          SMESH_MesherHelper&   helper)
+{
+  TopoDS_Shape S = helper.GetSubShapeByNode( data._edges[ iFrom ]->_nodes[0],
+                                             helper.GetMeshDS());
+  TopoDS_Edge E = TopoDS::Edge( S );
+
+  Handle(Geom_Curve) curve = data.CurveForSmooth( E, iFrom, iTo, surface, F, helper );
+  if ( curve.IsNull() ) return false;
+
+  // compute a relative length of segments
+  vector< double > len( iTo-iFrom+1 );
+  {
+    double curLen, prevLen = len[0] = 1.0;
+    for ( int i = iFrom; i < iTo; ++i )
+    {
+      curLen = prevLen * data._edges[i]->_2neibors->_wgt[0] / data._edges[i]->_2neibors->_wgt[1];
+      len[i-iFrom+1] = len[i-iFrom] + curLen;
+      prevLen = curLen;
+    }
+  }
+
+  if ( curve->IsKind( STANDARD_TYPE( Geom_Line )))
+  {
+    if ( F.IsNull() ) // 3D
+    {
+      SMESH_TNodeXYZ p0( data._edges[iFrom]->_2neibors->_nodes[0]);
+      SMESH_TNodeXYZ p1( data._edges[iTo-1]->_2neibors->_nodes[1]);
+      for ( int i = iFrom; i < iTo; ++i )
+      {
+        double r = len[i-iFrom] / len.back();
+        gp_XYZ newPos = p0 * ( 1. - r ) + p1 * r;
+        data._edges[i]->_pos.back() = newPos;
+        SMDS_MeshNode* tgtNode = const_cast<SMDS_MeshNode*>( data._edges[i]->_nodes.back() );
+        tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() );
+      }
+    }
+    else
+    {
+      gp_XY uv0 = helper.GetNodeUV( F, data._edges[iFrom]->_2neibors->_nodes[0]);
+      gp_XY uv1 = helper.GetNodeUV( F, data._edges[iTo-1]->_2neibors->_nodes[1]);
+      for ( int i = iFrom; i < iTo; ++i )
+      {
+        double r = len[i-iFrom] / len.back();
+        gp_XY  newUV = uv0 * ( 1. - r ) + uv1 * r;
+        data._edges[i]->_pos.back().SetCoord( newUV.X(), newUV.Y(), 0 );
+
+        gp_Pnt newPos = surface->Value( newUV.X(), newUV.Y() );
+        SMDS_MeshNode* tgtNode = const_cast<SMDS_MeshNode*>( data._edges[i]->_nodes.back() );
+        tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() );
+
+        SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() );
+        pos->SetUParameter( newUV.X() );
+        pos->SetVParameter( newUV.Y() );
+      }
+    }
+    return true;
+  }
+
+  if ( curve->IsKind( STANDARD_TYPE( Geom_Circle )))
+  {
+    Handle(Geom_Circle) circle = Handle(Geom_Circle)::DownCast( curve );
+    gp_Pnt center3D = circle->Location();
+
+    if ( F.IsNull() ) // 3D
+    {
+      return false; // TODO ???
+    }
+    else // 2D
+    {
+      const gp_XY center( center3D.X(), center3D.Y() );
+      
+      gp_XY uv0 = helper.GetNodeUV( F, data._edges[iFrom]->_2neibors->_nodes[0]);
+      gp_XY uvM = helper.GetNodeUV( F, data._edges[iFrom]->_nodes.back());
+      gp_XY uv1 = helper.GetNodeUV( F, data._edges[iTo-1]->_2neibors->_nodes[1]);
+      gp_Vec2d vec0( center, uv0 );
+      gp_Vec2d vecM( center, uvM);
+      gp_Vec2d vec1( center, uv1 );
+      double uLast = vec0.Angle( vec1 ); // -PI - +PI
+      double uMidl = vec0.Angle( vecM );
+      if ( uLast < 0 ) uLast += 2*PI; // 0.0 - 2*PI
+      if ( uMidl < 0 ) uMidl += 2*PI;
+      const bool sense = ( uMidl < uLast );
+      const double radius = 0.5 * ( vec0.Magnitude() + vec1.Magnitude() );
+
+      gp_Ax2d axis( center, vec0 );
+      gp_Circ2d circ ( axis, radius, sense );
+      for ( int i = iFrom; i < iTo; ++i )
+      {
+        double    newU = uLast * len[i-iFrom] / len.back();
+        gp_Pnt2d newUV = ElCLib::Value( newU, circ );
+        data._edges[i]->_pos.back().SetCoord( newUV.X(), newUV.Y(), 0 );
+
+        gp_Pnt newPos = surface->Value( newUV.X(), newUV.Y() );
+        SMDS_MeshNode* tgtNode = const_cast<SMDS_MeshNode*>( data._edges[i]->_nodes.back() );
+        tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() );
+
+        SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() );
+        pos->SetUParameter( newUV.X() );
+        pos->SetVParameter( newUV.Y() );
+      }
+    }
+    return true;
+  }
+
+  return false;
+}
+
 //================================================================================
 /*!
  * \brief Modify normals of _LayerEdge's on EDGE's to avoid intersection with
@@ -3219,15 +3495,32 @@ bool _ViscousBuilder::shrink()
       if ( badNb > 0 )
         return error(SMESH_Comment("Can't shrink 2D mesh on face ") << f2sd->first );
     }
-    // No wrongly shaped faces remain; final smooth. Set node XYZ
-    for ( int st = 3; st; --st )
+    // No wrongly shaped faces remain; final smooth. Set node XYZ.
+    // First, find out a needed quality of smoothing (high for quadrangles only)
+    bool highQuality;
+    {
+      const bool hasTria = _mesh->NbTriangles(), hasQuad = _mesh->NbQuadrangles();
+      if ( hasTria != hasQuad )
+      {
+        highQuality = hasQuad;
+      }
+      else
+      {
+        set<int> nbNodesSet;
+        SMDS_ElemIteratorPtr fIt = smDS->GetElements();
+        while ( fIt->more() && nbNodesSet.size() < 2 )
+          nbNodesSet.insert( fIt->next()->NbCornerNodes() );
+        highQuality = ( *nbNodesSet.begin() == 4 );
+      }
+    }
+    for ( int st = highQuality ? 8 : 3; st; --st )
     {
       dumpFunction(SMESH_Comment("shrinkFace")<<f2sd->first<<"_st"<<++smooStep); // debug
       for ( unsigned i = 0; i < nodesToSmooth.size(); ++i )
         nodesToSmooth[i].Smooth( badNb,surface,helper,refSign,/*set3D=*/st==1 );
       dumpFunctionEnd();
     }
-    // Set event listener to clear FACE sub-mesh together with SOLID sub-mesh
+    // Set an event listener to clear FACE sub-mesh together with SOLID sub-mesh
     _SrinkShapeListener::ToClearSubMeshWithSolid( sm, data._solid );
 
   }// loop on FACES to srink mesh on