Merge from V6_3_BR 15/07/2011

This commit is contained in:
vsr 2011-07-15 11:19:53 +00:00
parent 244cad68dd
commit 91c92cb543
42 changed files with 917 additions and 449 deletions

View File

@ -24,7 +24,7 @@
# Modified by : Alexander BORODIN (OCN) - autotools usage # Modified by : Alexander BORODIN (OCN) - autotools usage
# Created from configure.in.base # 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_CONFIG_AUX_DIR(adm_local/unix/config_files)
AC_CANONICAL_HOST AC_CANONICAL_HOST
AC_CANONICAL_TARGET AC_CANONICAL_TARGET
@ -481,6 +481,7 @@ AC_OUTPUT([ \
doc/salome/gui/SMESH/doxyfile \ doc/salome/gui/SMESH/doxyfile \
doc/salome/gui/SMESH/doxyfile_py \ doc/salome/gui/SMESH/doxyfile_py \
doc/salome/gui/SMESH/static/header.html \ doc/salome/gui/SMESH/static/header.html \
doc/salome/gui/SMESH/static/header_py.html \
doc/salome/tui/Makefile \ doc/salome/tui/Makefile \
doc/salome/tui/doxyfile \ doc/salome/tui/doxyfile \
doc/salome/tui/static/header.html \ doc/salome/tui/static/header.html \

View File

@ -110,7 +110,7 @@ EXAMPLE_PATH = @top_srcdir@/src/SMESH_SWIG
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
GENERATE_HTML = YES GENERATE_HTML = YES
HTML_OUTPUT = smeshpy_doc HTML_OUTPUT = smeshpy_doc
HTML_HEADER = @builddir@/static/header.html HTML_HEADER = @builddir@/static/header_py.html
HTML_FOOTER = @srcdir@/static/footer.html HTML_FOOTER = @srcdir@/static/footer.html
HTML_STYLESHEET = @srcdir@/static/doxygen.css HTML_STYLESHEET = @srcdir@/static/doxygen.css
TOC_EXPAND = YES TOC_EXPAND = YES

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -44,7 +44,7 @@ segments on all four sides of the face must be even (divisible by 2).
\anchor viscous_layers_anchor \anchor viscous_layers_anchor
<h2>Viscous Layers</h2> <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 several 3D algorithms: NETGEN 3D, GHS3D and Hexahedron(i,j,k). This
hypothesis allows creation of layers of highly stretched prisms near hypothesis allows creation of layers of highly stretched prisms near
mesh boundary, which is beneficial for high quality viscous mesh boundary, which is beneficial for high quality viscous
@ -56,13 +56,13 @@ actually the hexahedrons.
<ul> <ul>
<li><b>Name</b> - allows to define the name of the hypothesis.</li> <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>Total thicknes</b> - gives the total thickness of prism layers.</li>
<li><b>Number of layers</b> - defines number of layers of prisms.</li> <li><b>Number of layers</b> - defines the number of prism layers.</li>
<li><b>Stretch factor</b> - defines factor of growth of height of <li><b>Stretch factor</b> - defines the growth factor of prism height
prisms from the mesh boundary towards inside of mesh.</li> from the mesh boundary inwards.</li>
<li><b>Faces without layers</b> - defines geometrical faces on which <li><b>Faces without layers</b> - defines geometrical faces on which
layers of prisms should not be constructed. By default the layers of prism layers should not be constructed. By default the prism layers
prisms are not constructed on geometrical faces shared by solids.</li> are not constructed on geometrical faces shared by solids.</li>
</ul> </ul>
\image html viscous_layers_mesh.png A group containing viscous layer prisms. \image html viscous_layers_mesh.png A group containing viscous layer prisms.

View 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. More specific size maps can be defined on faces.
<ul> <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> <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 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. to its maximum (2.5) in the <i>arguments</i> tab.
</ul> </ul>
\n \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> <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> If the two options are combined the size will remain constant
<li> Else the growing is only controled by the standard arguments of BLSURF (gradation ...).</li> 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>
</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 \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 \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. <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 \anchor blsurf_attractor_computation
<h2>Computation of attractors</h2> <h2>Computation of attractors</h2>
\n \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 \n
Where : Where :
<ul> <ul>
<li>h_start is the desired size on the given attractor shape</li> <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> <li>R is called the distance of influence and allows controlling the growth rate of the mesh </li>
</ul> </ul>

View 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 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 that the choice of hypotheses depends on the algorithm. There must be
one Algorithm and zero or several Hypotheses for each dimension of your 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), hypotheses using some default parameters),
otherwise you will not get any mesh at all. Of course, if you 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 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 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 clicking <b>Assign a set of hypotheses</b> button and selecting among
pre-defined sets of hypotheses. In addition to the standard 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 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 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). tags).
\image html hypo_sets.png \image html hypo_sets.png
<center>List of sets of hypotheses: <em>[custom]</em> is automatically added to the sets defined <center>List of sets of hypotheses: <em>[custom]</em> is automatically added to the sets defined

View File

@ -2,11 +2,11 @@
\page convert_to_from_quadratic_mesh_page Convert to/from Quadratic Mesh \page convert_to_from_quadratic_mesh_page Convert to/from Quadratic Mesh
\n This functionality allows you to transtorm standard meshes (or \n This functionality allows transforming standard meshes (or
sum-mesh) to quadratic and vice versa. sub-meshes) to quadratic and vice versa.
See \ref adding_quadratic_elements_page "Adding quadratic elements" See \ref adding_quadratic_elements_page "Adding quadratic elements"
for more information about quadratic meshes. 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 produce a non-conformal mesh. Elements on the boundary between
quadratic and linear sub-meshes become (or remain) quadratic. quadratic and linear sub-meshes become (or remain) quadratic.
@ -14,8 +14,8 @@ quadratic and linear sub-meshes become (or remain) quadratic.
<ol> <ol>
<li>Select a mesh or a sub-mesh in the Object Browser or in the <li>Select a mesh or a sub-mesh in the Object Browser or in the
Viewer.</li> Viewer.</li>
<li>From the Modification menu choose the Convert to/from Quadratic <li>From the Modification menu choose <b> Convert to/from Quadratic
Mesh item, or click <em>"Convert to/from quadratic"</em> button in the Mesh item </b>, or click <em>"Convert to/from quadratic"</em> button in the
toolbar. toolbar.
\image html image154.png \image html image154.png
@ -26,18 +26,17 @@ The following dialog box will appear:
\image html convert.png \image html convert.png
</li> </li>
<li>In this dialog box you should specify: <li>In this dialog box specify:
<ul> <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 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 (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 <li>if it is necessary to place medium nodes of the quadratic mesh on the
geometry (meshed object). This option is active at convertion to geometry (meshed object). This option is relevant for conversion to
qudratic mesh only and provided that the mesh is based on some quadratic provided that the mesh is based on a geometry (not imported from file).</li>
geometry (not imported from the file).</li>
</ul> </ul>
\image html image156.gif \image html image156.gif

View File

@ -2,8 +2,8 @@
\page cut_mesh_by_plane_page Cut a tetrahedron mesh by a plane \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. \n MeshCut works only with 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, 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. 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. \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 nx ny nz = vector normal to the cut plane
\n px py pz = a point of 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 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 \n where L is the mean edge size of the tetrahedron
<br> <br>
\anchor meshcut_plugin \anchor meshcut_plugin
<h2>Using MeshCut inside SALOME</h2> <h2>Using MeshCut inside SALOME</h2>
When the MeshCut plugin is installed, you will find it in the Mesh menu, sub-menu SMESH_plugins. 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, look for a file named meshcut_plugin.py in your SMESH installation. \n If the plugin is not installed, the file meshcut_plugin.py is in
The file is normally in the subdirectory bin/salome/meshcut_plugin.py. 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. \n If there are already plugins defined in a smesh_plugins.py file,
if not, copy this file as ${HOME}/Plugins/smesh_plugins.py or ${APPLI}/Plugins/smesh_plugins.py this file should be added at the end.
or in your ${PLUGINPATH} Directory. 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 <li>From the Mesh menu, sub-menu SMESH_plugins, choose "MeshCut" item
The following dialog box will appear: The following dialog box will appear:

View 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. of groups of volumes, or on a list of groups of faces.
\n These functionalities are only available in python scripts. \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.
*/ */

View File

@ -7,7 +7,7 @@ elements of a higher dimension.
<em>To generate border elements:</em> <em>To generate border elements:</em>
<ol> <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" <li>From the Modification menu choose "Create boundary elements"
item, or click "Create boundary elements" button in the toolbar 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: The following dialog box will appear:
\image html 2d_from_3d_dlg.png "Create boundary elements dialog box". \image html 2d_from_3d_dlg.png "Create boundary elements dialog box".
</li> </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> the type of operation you would like to perform.</li>
<li>Fill the other fields available in the dialog box.</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> <li>Click the \b Apply or <b>Apply and Close</b> button to perform the operation.</li>
</ol> </ol>
\n "Create boundary elements" dialog allows creation of boundary elements \n "Create boundary elements" dialog allows creation of boundary elements
of three types. of two types.
<ul> <ul>
<li><b>2D from 3D</b> creates mesh faces on free facets of volume elements</li> <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</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> </ul>
Here a <em>free facet</em> means a facet shared by only one volume, a <em>free edge</em> 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. means an edge shared by only one mesh face.
In this dialog: In this dialog:
<ul> <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 <li>specify the <b>Target</b> mesh, where the boundary elements will
be created. be created.
<ul> <ul>

View File

@ -2,7 +2,10 @@
\page over_constrained_faces_page Over-constrained faces \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 \image html over_constrained_faces.png

View File

@ -3,6 +3,10 @@
\page over_constrained_volumes_page Over-constrained volumes \page over_constrained_volumes_page Over-constrained volumes
\n This mesh quality control highlights volumes sharing only one of its borders with other 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 \image html over_constrained_volumes.png

View File

@ -139,5 +139,6 @@ the following links:
- \subpage tui_transforming_meshes_page - \subpage tui_transforming_meshes_page
- \subpage tui_notebook_smesh_page - \subpage tui_notebook_smesh_page
- \subpage tui_measurements_page - \subpage tui_measurements_page
- \subpage tui_generate_flat_elements_page
*/ */

View File

@ -38,11 +38,11 @@ ghs3dMesh.Compute()
# - the coordinates x,y,z # - the coordinates x,y,z
# - a GEOM vertex or compound (No geometry, TUI only) # - 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). # a group (No geometry, TUI only).
# Ex1: Add 1 enforced vertices by coords at (50,50,100) # Ex1: Add one enforced vertex with coordinates (50,50,100)
# with a physical size of 2 # and physical size 2.
import geompy import geompy
import smesh import smesh
@ -73,10 +73,10 @@ GHS3D_Parameters.SetEnforcedVertex( 50, 50, 100, 2) # no group
ghs3dMesh.Compute() ghs3dMesh.Compute()
# Ex2: Add 1 enforced vertices by GEOM vertex at (50,50,100) # Ex2: Add one vertex enforced by a GEOM vertex at (50,50,100)
# with a physical size of 5 and add it to a group called "My special nodes" # 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') GHS3D_Parameters_wo_geometry = smesh.CreateHypothesis('GHS3D_Parameters', 'GHS3DEngine')
ghs3dMesh_wo_geometry.AddHypothesis( GHS3D ) ghs3dMesh_wo_geometry.AddHypothesis( GHS3D )
ghs3dMesh_wo_geometry.AddHypothesis( GHS3D_Parameters_wo_geometry ) ghs3dMesh_wo_geometry.AddHypothesis( GHS3D_Parameters_wo_geometry )
@ -104,8 +104,8 @@ GHS3D_Parameters.ClearEnforcedVertices()
\code \code
# It is possible to constraint GHS3D with another mesh or group. # It is possible to constrain GHS3D with another mesh or group.
# The constraint can be the nodes, edges or faces. # The constraint can refer to the nodes, edges or faces.
# This feature is available only in TUI, on meshes without geometry. # This feature is available only in TUI, on meshes without geometry.
# The constraining elements are called enforced elements for the mesh. # The constraining elements are called enforced elements for the mesh.
# They can be recovered using groups if necessary. # They can be recovered using groups if necessary.
@ -133,7 +133,7 @@ geompy.addToStudy( p1, "p1" )
geompy.addToStudy( p2, "p2" ) geompy.addToStudy( p2, "p2" )
geompy.addToStudy( c, "c" ) geompy.addToStudy( c, "c" )
# Create the 2D algo and hypothesis # Create the 2D algorithm and hypothesis
BLSURF = smesh.CreateHypothesis('BLSURF', 'BLSURFEngine') BLSURF = smesh.CreateHypothesis('BLSURF', 'BLSURFEngine')
# For the box # For the box
BLSURF_Parameters = smesh.CreateHypothesis('BLSURF_Parameters', 'BLSURFEngine') BLSURF_Parameters = smesh.CreateHypothesis('BLSURF_Parameters', 'BLSURFEngine')
@ -143,7 +143,7 @@ BLSURF_Parameters.SetPhySize( 200 )
BLSURF_Parameters2 = smesh.CreateHypothesis('BLSURF_Parameters', 'BLSURFEngine') BLSURF_Parameters2 = smesh.CreateHypothesis('BLSURF_Parameters', 'BLSURFEngine')
BLSURF_Parameters2.SetGeometricMesh( 1 ) BLSURF_Parameters2.SetGeometricMesh( 1 )
# Create the 3D algo and hypothesis # Create the 3D algorithm and hypothesis
GHS3D = smesh.CreateHypothesis('GHS3D_3D', 'GHS3DEngine') GHS3D = smesh.CreateHypothesis('GHS3D_3D', 'GHS3DEngine')
GHS3D_Parameters_node = smesh.CreateHypothesis('GHS3D_Parameters', 'GHS3DEngine') GHS3D_Parameters_node = smesh.CreateHypothesis('GHS3D_Parameters', 'GHS3DEngine')
#GHS3D_Parameters_node.SetToMeshHoles( 1 ) #GHS3D_Parameters_node.SetToMeshHoles( 1 )
@ -173,7 +173,7 @@ Mesh_box_tri.AddHypothesis( BLSURF_Parameters )
Mesh_box_tri.Compute() Mesh_box_tri.Compute()
# Create 4 copies of the 2D mesh to test the 3 types of contraints (NODE, EDGE, FACE) # 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. # Then the 3D algo and hypothesis are assigned to them.
mesh_mesh = smesh.CopyMesh( Mesh_box_tri, 'Enforced by faces of mesh', 0, 0) mesh_mesh = smesh.CopyMesh( Mesh_box_tri, 'Enforced by faces of mesh', 0, 0)

View File

@ -8,9 +8,9 @@
\n Double nodes on shared faces between groups of volumes and create flat elements on demand. \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 \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 faces at the boundaries of the groups are doubled. Optionally, the internal faces are replaced
by flat elements. 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 The flat elements are stored in groups of volumes.
\n \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]) [Solid_1,Solid_2,Solid_3] = geompy.SubShapes(Partition_1, [53, 2, 30])
[Face_1,Face_2] = geompy.SubShapes(Partition_1, [37, 20]) [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) Mesh_1 = smesh.Mesh(Partition_1)
BLSURF = Mesh_1.Triangle(algo=smesh.BLSURF) 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. \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. 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. the flat elements are built, otherwise, there is only a duplication of the nodes.
\code \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]) Mesh_1.CreateFlatElementsOnFacesGroups([Face_1_1, Face_2_1])
\endcode \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.
*/ */

View File

@ -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>

View File

@ -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>

View File

@ -264,7 +264,8 @@ module SMESH
long_array GetMeshInfo(); 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(); array_of_ElementType GetTypes();

View File

@ -415,6 +415,8 @@ void aptrte( Z nutysu, R aretmx,
if( mntree==NULL ) goto ERREUR; if( mntree==NULL ) goto ERREUR;
//initialisation du tableau letree et ajout dans letree des sommets 1 a nbsomm //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 ); teajte( mxsomm, nbsomm, mnpxyd, comxmi, aretmx, mxtree, mntree, ierr );
comxmi[0].z=0; comxmi[0].z=0;
comxmi[1].z=0; comxmi[1].z=0;

View File

@ -1294,7 +1294,7 @@ c la direction pour le calcul de la longueur (inactif ici!)
xyzd(2) = 0d0 xyzd(2) = 0d0
xyzd(3) = 0d0 xyzd(3) = 0d0
longai = areteideale() longai = areteideale(xyz,xyzd)
c (xyz,xyzd) c (xyz,xyzd)
if( longai .lt. 0d0 ) then if( longai .lt. 0d0 ) then
write(imprim,10000) xyz write(imprim,10000) xyz

View File

@ -122,21 +122,16 @@ dist_libSMDS_la_SOURCES = \
# additionnal information to compil and link file # additionnal information to compil and link file
libSMDS_la_CPPFLAGS = \ libSMDS_la_CPPFLAGS = \
$(KERNEL_CXXFLAGS) \ $(KERNEL_CXXFLAGS) \
$(CAS_CPPFLAGS) \
$(VTK_INCLUDES) \ $(VTK_INCLUDES) \
$(BOOST_CPPFLAGS) $(BOOST_CPPFLAGS)
libSMDS_la_LDFLAGS = \ libSMDS_la_LDFLAGS = \
$(VTK_LIBS) \ $(VTK_LIBS) \
$(KERNEL_LDFLAGS) -lSALOMELocalTrace \ $(KERNEL_LDFLAGS) -lSALOMELocalTrace
$(CAS_KERNEL)
# Executables targets # Executables targets
bin_PROGRAMS = SMDS_MemoryLimit bin_PROGRAMS = SMDS_MemoryLimit
dist_SMDS_MemoryLimit_SOURCES = \ dist_SMDS_MemoryLimit_SOURCES = \
SMDS_MemoryLimit.cxx SMDS_MemoryLimit.cxx
SMDS_MemoryLimit_LDADD = \
$(KERNEL_LDFLAGS) -lSALOMELocalTrace
#libSMDS_la_LDFLAGS += -L/data/eap/S5_MV/INSTALL/SMESH/lib/salome -lPerfmeter #libSMDS_la_LDFLAGS += -L/data/eap/S5_MV/INSTALL/SMESH/lib/salome -lPerfmeter

View File

@ -38,6 +38,8 @@
#include "SMDS_UnstructuredGrid.hxx" #include "SMDS_UnstructuredGrid.hxx"
#include <vtkCellType.h> #include <vtkCellType.h>
#include <climits>
using namespace std; using namespace std;
//======================================================================= //=======================================================================
@ -173,7 +175,7 @@ void SMDS_MeshElementIDFactory::ReleaseID(int ID, int vtkId)
void SMDS_MeshElementIDFactory::updateMinMax() const void SMDS_MeshElementIDFactory::updateMinMax() const
{ {
myMin = IntegerLast(); myMin = INT_MAX;
myMax = 0; myMax = 0;
for (int i = 0; i < myMesh->myCells.size(); i++) for (int i = 0; i < myMesh->myCells.size(); i++)
{ {
@ -186,7 +188,7 @@ void SMDS_MeshElementIDFactory::updateMinMax() const
myMin = id; myMin = id;
} }
} }
if (myMin == IntegerLast()) if (myMin == INT_MAX)
myMin = 0; myMin = 0;
} }

View File

@ -32,7 +32,6 @@
#include "SMDS_MeshElement.hxx" #include "SMDS_MeshElement.hxx"
#include "SMDS_Position.hxx" #include "SMDS_Position.hxx"
#include "ObjectPool.hxx" #include "ObjectPool.hxx"
#include <NCollection_List.hxx>
class SMDS_EXPORT SMDS_MeshNode:public SMDS_MeshElement class SMDS_EXPORT SMDS_MeshNode:public SMDS_MeshElement
{ {

View File

@ -1355,20 +1355,23 @@ int SMDS_VolumeTool::GetAllExistingEdges(vector<const SMDS_MeshElement*> & edges
return edges.size(); 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 )) if (!setFace( faceIndex ))
return !free; return !isFree;
const SMDS_MeshNode** nodes = GetFaceNodes( faceIndex ); const SMDS_MeshNode** nodes = GetFaceNodes( faceIndex );
int nbFaceNodes = myFaceNbNodes; const int nbFaceNodes = myFaceNbNodes;
// evaluate nb of face nodes shared by other volume // evaluate nb of face nodes shared by other volume
int maxNbShared = -1; int maxNbShared = -1;
@ -1377,25 +1380,19 @@ bool SMDS_VolumeTool::IsFreeFace( int faceIndex )
TElemIntMap::iterator vNbIt; TElemIntMap::iterator vNbIt;
for ( int iNode = 0; iNode < nbFaceNodes; iNode++ ) { for ( int iNode = 0; iNode < nbFaceNodes; iNode++ ) {
const SMDS_MeshNode* n = nodes[ iNode ]; const SMDS_MeshNode* n = nodes[ iNode ];
SMDS_ElemIteratorPtr eIt = n->GetInverseElementIterator(); SMDS_ElemIteratorPtr eIt = n->GetInverseElementIterator( SMDSAbs_Volume );
while ( eIt->more() ) { while ( eIt->more() ) {
const SMDS_MeshElement* elem = eIt->next(); const SMDS_MeshElement* elem = eIt->next();
if ( elem != myVolume && elem->GetType() == SMDSAbs_Volume ) { if ( elem != myVolume ) {
int nbShared = 1; vNbIt = volNbShared.insert( make_pair( elem, 0 )).first;
vNbIt = volNbShared.find( elem ); (*vNbIt).second++;
if ( vNbIt == volNbShared.end() ) { if ( vNbIt->second > maxNbShared )
volNbShared.insert ( TElemIntMap::value_type( elem, nbShared )); maxNbShared = vNbIt->second;
}
else {
nbShared = ++(*vNbIt).second;
}
if ( nbShared > maxNbShared )
maxNbShared = nbShared;
} }
} }
} }
if ( maxNbShared < 3 ) if ( maxNbShared < 3 )
return free; // is free return isFree; // is free
// find volumes laying on the opposite side of the face // find volumes laying on the opposite side of the face
// and sharing all nodes // and sharing all nodes
@ -1404,55 +1401,81 @@ bool SMDS_VolumeTool::IsFreeFace( int faceIndex )
if ( IsFaceExternal( faceIndex )) if ( IsFaceExternal( faceIndex ))
intNormal = XYZ( -intNormal.x, -intNormal.y, -intNormal.z ); intNormal = XYZ( -intNormal.x, -intNormal.y, -intNormal.z );
XYZ p0 ( nodes[0] ), baryCenter; XYZ p0 ( nodes[0] ), baryCenter;
for ( vNbIt = volNbShared.begin(); vNbIt != volNbShared.end(); vNbIt++ ) { for ( vNbIt = volNbShared.begin(); vNbIt != volNbShared.end(); ) {
int nbShared = (*vNbIt).second; const int& nbShared = (*vNbIt).second;
if ( nbShared >= 3 ) { if ( nbShared >= 3 ) {
SMDS_VolumeTool volume( (*vNbIt).first ); SMDS_VolumeTool volume( (*vNbIt).first );
volume.GetBaryCenter( baryCenter.x, baryCenter.y, baryCenter.z ); volume.GetBaryCenter( baryCenter.x, baryCenter.y, baryCenter.z );
XYZ intNormal2( baryCenter - p0 ); XYZ intNormal2( baryCenter - p0 );
if ( intNormal.Dot( intNormal2 ) < 0 ) if ( intNormal.Dot( intNormal2 ) < 0 ) {
continue; // opposite side // 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 // remove a volume from volNbShared map
volNbShared.erase( vNbIt-- ); volNbShared.erase( vNbIt++ );
} }
// here volNbShared contains only volumes laying on the // here volNbShared contains only volumes laying on the opposite side of
// opposite side of the face // the face and sharing 3 or more but not all face nodes with myVolume
if ( volNbShared.empty() ) { if ( volNbShared.size() < 2 ) {
return free; // is free return isFree; // is free
} }
// check if the whole area of a face is shared // check if the whole area of a face is shared
bool isShared[] = { false, false, false, false }; // 4 triangle parts of a quadrangle for ( int iNode = 0; iNode < nbFaceNodes; iNode++ )
for ( vNbIt = volNbShared.begin(); vNbIt != volNbShared.end(); vNbIt++ ) { {
SMDS_VolumeTool volume( (*vNbIt).first ); const SMDS_MeshNode* n = nodes[ iNode ];
bool prevLinkShared = false; // check if n is shared by one of volumes of volNbShared
int nbSharedLinks = 0; bool isShared = false;
for ( int iNode = 0; iNode < nbFaceNodes; iNode++ ) { SMDS_ElemIteratorPtr eIt = n->GetInverseElementIterator( SMDSAbs_Volume );
bool linkShared = volume.IsLinked( nodes[ iNode ], nodes[ iNode + 1] ); while ( eIt->more() && !isShared )
if ( linkShared ) isShared = volNbShared.count( eIt->next() );
nbSharedLinks++; if ( !isShared )
if ( linkShared && prevLinkShared && return isFree;
volume.IsLinked( nodes[ iNode - 1 ], nodes[ iNode + 1] ))
isShared[ iNode ] = true;
prevLinkShared = linkShared;
} }
if ( nbSharedLinks == nbFaceNodes ) if ( otherVol ) *otherVol = volNbShared.begin()->first;
return !free; // is not free return !isFree;
if ( nbFaceNodes == 4 ) {
// check traingle parts 1 & 3 // if ( !myVolume->IsPoly() )
if ( isShared[1] && isShared[3] ) // {
return !free; // is not free // bool isShared[] = { false, false, false, false }; // 4 triangle parts of a quadrangle
// check triangle parts 0 & 2; // for ( vNbIt = volNbShared.begin(); vNbIt != volNbShared.end(); vNbIt++ ) {
// 0 part could not be checked in the loop; check it here // SMDS_VolumeTool volume( (*vNbIt).first );
if ( isShared[2] && prevLinkShared && // bool prevLinkShared = false;
volume.IsLinked( nodes[ 0 ], nodes[ 1 ] ) && // int nbSharedLinks = 0;
volume.IsLinked( nodes[ 1 ], nodes[ 3 ] ) ) // for ( int iNode = 0; iNode < nbFaceNodes; iNode++ ) {
return !free; // is not free // bool linkShared = volume.IsLinked( nodes[ iNode ], nodes[ iNode + 1] );
} // if ( linkShared )
} // nbSharedLinks++;
return free; // 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;
} }
//======================================================================= //=======================================================================

View File

@ -160,8 +160,9 @@ class SMDS_EXPORT SMDS_VolumeTool
// Check normal orientation of a face. // Check normal orientation of a face.
// SetExternalNormal() is taken into account. // 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 // 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); bool GetFaceNormal (int faceIndex, double & X, double & Y, double & Z);
// Return a normal to a face // Return a normal to a face

View File

@ -174,7 +174,7 @@ double SMESH_Algo::EdgeLength(const TopoDS_Edge & E)
return 0; return 0;
TopLoc_Location L; TopLoc_Location L;
Handle(Geom_Curve) C = BRep_Tool::Curve(E, L, UMin, UMax); 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); double length = GCPnts_AbscissaPoint::Length(AdaptCurve, UMin, UMax);
return length; return length;
} }

View File

@ -1615,6 +1615,7 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
helper.SetIsQuadratic( false ); helper.SetIsQuadratic( false );
} }
vector<const SMDS_MeshNode*> nodes( (*elem)->begin_nodes(), (*elem)->end_nodes() ); vector<const SMDS_MeshNode*> nodes( (*elem)->begin_nodes(), (*elem)->end_nodes() );
helper.SetElementsOnShape( true );
if ( splitMethod._baryNode ) if ( splitMethod._baryNode )
{ {
// make a node at barycenter // make a node at barycenter
@ -1642,7 +1643,6 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
} }
// make tetras // make tetras
helper.SetElementsOnShape( true );
vector<const SMDS_MeshElement* > tetras( splitMethod._nbTetra ); // splits of a volume vector<const SMDS_MeshElement* > tetras( splitMethod._nbTetra ); // splits of a volume
const int* tetConn = splitMethod._connectivity; const int* tetConn = splitMethod._connectivity;
for ( int i = 0; i < splitMethod._nbTetra; ++i, tetConn += 4 ) for ( int i = 0; i < splitMethod._nbTetra; ++i, tetConn += 4 )
@ -1670,6 +1670,12 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
helper.SetElementsOnShape( false ); helper.SetElementsOnShape( false );
vector< const SMDS_MeshElement* > triangles; 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); map<int, const SMDS_MeshNode*>::iterator iF_n = splitMethod._faceBaryNode.find(iF);
if ( iF_n != splitMethod._faceBaryNode.end() ) if ( iF_n != splitMethod._faceBaryNode.end() )
{ {
@ -1681,6 +1687,9 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
if ( !volTool.IsFaceExternal( iF )) if ( !volTool.IsFaceExternal( iF ))
swap( n2, n3 ); swap( n2, n3 );
triangles.push_back( helper.AddFace( n1,n2,n3 )); triangles.push_back( helper.AddFace( n1,n2,n3 ));
if ( fSubMesh && n3->getshapeId() < 1 )
fSubMesh->AddNode( n3 );
} }
} }
else else
@ -1719,12 +1728,6 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
volNodes[ facet->_n3 ])); 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 ) for ( int i = 0; i < triangles.size(); ++i )
{ {
if ( !triangles[i] ) continue; if ( !triangles[i] ) continue;
@ -3088,35 +3091,27 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet & theElems,
// fix nodes on mesh boundary // fix nodes on mesh boundary
if ( checkBoundaryNodes ) { if ( checkBoundaryNodes ) {
map< NLink, int > linkNbMap; // how many times a link encounters in elemsOnFace map< SMESH_TLink, int > linkNbMap; // how many times a link encounters in elemsOnFace
map< NLink, int >::iterator link_nb; map< SMESH_TLink, int >::iterator link_nb;
// put all elements links to linkNbMap // put all elements links to linkNbMap
list< const SMDS_MeshElement* >::iterator elemIt = elemsOnFace.begin(); list< const SMDS_MeshElement* >::iterator elemIt = elemsOnFace.begin();
for ( ; elemIt != elemsOnFace.end(); ++elemIt ) { for ( ; elemIt != elemsOnFace.end(); ++elemIt ) {
const SMDS_MeshElement* elem = (*elemIt); const SMDS_MeshElement* elem = (*elemIt);
int nbn = elem->NbNodes(); int nbn = elem->NbCornerNodes();
if(elem->IsQuadratic())
nbn = nbn/2;
// loop on elem links: insert them in linkNbMap // loop on elem links: insert them in linkNbMap
const SMDS_MeshNode* curNode, *prevNode = elem->GetNodeWrap( nbn );
for ( int iN = 0; iN < nbn; ++iN ) { for ( int iN = 0; iN < nbn; ++iN ) {
curNode = elem->GetNode( iN ); const SMDS_MeshNode* n1 = elem->GetNode( iN );
NLink link; const SMDS_MeshNode* n2 = elem->GetNode(( iN+1 ) % nbn);
if ( curNode < prevNode ) link = make_pair( curNode , prevNode ); SMESH_TLink link( n1, n2 );
else link = make_pair( prevNode , curNode ); link_nb = linkNbMap.insert( make_pair( link, 0 )).first;
prevNode = curNode;
link_nb = linkNbMap.find( link );
if ( link_nb == linkNbMap.end() )
linkNbMap.insert( make_pair ( link, 1 ));
else
link_nb->second++; link_nb->second++;
} }
} }
// remove nodes that are in links encountered only once from setMovableNodes // remove nodes that are in links encountered only once from setMovableNodes
for ( link_nb = linkNbMap.begin(); link_nb != linkNbMap.end(); ++link_nb ) { for ( link_nb = linkNbMap.begin(); link_nb != linkNbMap.end(); ++link_nb ) {
if ( link_nb->second == 1 ) { if ( link_nb->second == 1 ) {
setMovableNodes.erase( link_nb->first.first ); setMovableNodes.erase( link_nb->first.node1() );
setMovableNodes.erase( link_nb->first.second ); setMovableNodes.erase( link_nb->first.node2() );
} }
} }
} }
@ -4120,7 +4115,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes,
if ( f ) if ( f )
aMesh->ChangeElementNodes( f, &polygon_nodes[0], nbn ); aMesh->ChangeElementNodes( f, &polygon_nodes[0], nbn );
else 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 group - a group to store created boundary elements in
* \param targetMesh - a mesh 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 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 * boundary elements will be copied into the targetMesh
* \param toAddExistingBondary - if true, not only new but also pre-existing * \param toAddExistingBondary - if true, not only new but also pre-existing
* boundary elements will be added into the new group * boundary elements will be added into the new group
* \param aroundElements - if true, elements will be created on boundary of given * \param aroundElements - if true, elements will be created on boundary of given
* elements else, on boundary of the whole mesh. This * elements else, on boundary of the whole mesh.
* option works for 2D elements only.
* \return nb of added boundary elements * \return nb of added boundary elements
*/ */
//================================================================================ //================================================================================
@ -11594,7 +11588,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
SMESH_Group* group/*=0*/, SMESH_Group* group/*=0*/,
SMESH_Mesh* targetMesh/*=0*/, SMESH_Mesh* targetMesh/*=0*/,
bool toCopyElements/*=false*/, bool toCopyElements/*=false*/,
bool toCopyExistingBondary/*=false*/, bool toCopyExistingBoundary/*=false*/,
bool toAddExistingBondary/*= false*/, bool toAddExistingBondary/*= false*/,
bool aroundElements/*= false*/) bool aroundElements/*= false*/)
{ {
@ -11604,11 +11598,8 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
if ( !elements.empty() && (*elements.begin())->GetType() != elemType ) if ( !elements.empty() && (*elements.begin())->GetType() != elemType )
throw SALOME_Exception(LOCALIZED("wrong element type")); throw SALOME_Exception(LOCALIZED("wrong element type"));
if ( aroundElements && elemType == SMDSAbs_Volume )
throw SALOME_Exception(LOCALIZED("wrong element type for aroundElements==true"));
if ( !targetMesh ) if ( !targetMesh )
toCopyElements = toCopyExistingBondary = false; toCopyElements = toCopyExistingBoundary = false;
SMESH_MeshEditor tgtEditor( targetMesh ? targetMesh : myMesh ); SMESH_MeshEditor tgtEditor( targetMesh ? targetMesh : myMesh );
SMESHDS_Mesh* aMesh = GetMeshDS(), *tgtMeshDS = tgtEditor.GetMeshDS(); 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 ------------------------------------------ if ( vTool.Set(elem) ) // elem is a volume ------------------------------------------
{ {
vTool.SetExternalNormal(); vTool.SetExternalNormal();
const SMDS_MeshElement* otherVol = 0;
for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ ) for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ )
{ {
if (!vTool.IsFreeFace(iface)) if ( !vTool.IsFreeFace(iface, &otherVol) &&
( !aroundElements || elements.count( otherVol )))
continue; continue;
int nbFaceNodes = vTool.NbFaceNodes(iface); const int nbFaceNodes = vTool.NbFaceNodes(iface);
const SMDS_MeshNode** nn = vTool.GetFaceNodes(iface); const SMDS_MeshNode** nn = vTool.GetFaceNodes(iface);
if ( missType == SMDSAbs_Edge ) // boundary edges if ( missType == SMDSAbs_Edge ) // boundary edges
{ {
@ -11679,6 +11672,21 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
presentBndElems.push_back( f ); presentBndElems.push_back( f );
else else
missingBndElems.push_back( nodes ); 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 ) if ( targetMesh != myMesh )
// instead of making a map of nodes in this mesh and targetMesh, // 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 ) for ( int i = 0; i < missingBndElems.size(); ++i )
{ {
TConnectivity& srcNodes = missingBndElems[i]; TConnectivity& srcNodes = missingBndElems[i];
@ -11738,14 +11746,14 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
// ---------------------------------- // ----------------------------------
// 3. Copy present boundary elements // 3. Copy present boundary elements
// ---------------------------------- // ----------------------------------
if ( toCopyExistingBondary ) if ( toCopyExistingBoundary )
for ( int i = 0 ; i < presentBndElems.size(); ++i ) for ( int i = 0 ; i < presentBndElems.size(); ++i )
{ {
const SMDS_MeshElement* e = presentBndElems[i]; const SMDS_MeshElement* e = presentBndElems[i];
TConnectivity nodes( e->NbNodes() ); TConnectivity nodes( e->NbNodes() );
for ( inode = 0; inode < nodes.size(); ++inode ) for ( inode = 0; inode < nodes.size(); ++inode )
nodes[inode] = getNodeWithSameID( tgtMeshDS, e->GetNode(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 else // store present elements to add them to a group
for ( int i = 0 ; i < presentBndElems.size(); ++i ) for ( int i = 0 ; i < presentBndElems.size(); ++i )

View File

@ -194,7 +194,7 @@ void SMESH_MesherHelper::SetSubShape(const int aShID)
{ {
if ( aShID == myShapeID ) if ( aShID == myShapeID )
return; return;
if ( aShID > 1 ) if ( aShID > 0 )
SetSubShape( GetMeshDS()->IndexToShape( aShID )); SetSubShape( GetMeshDS()->IndexToShape( aShID ));
else else
SetSubShape( TopoDS_Shape() ); SetSubShape( TopoDS_Shape() );

View File

@ -3743,7 +3743,8 @@ void SMESHGUI::initialize( CAM_Application* app )
createPopupItem( 4043, OB, mesh ); // CLEAR_MESH createPopupItem( 4043, OB, mesh ); // CLEAR_MESH
popupMgr()->insert( separator(), -1, 0 ); popupMgr()->insert( separator(), -1, 0 );
createPopupItem( 417, OB, mesh + " " + subMesh ); // convert to quadratic createPopupItem( 417, OB, mesh + " " + subMesh ); // convert to quadratic
createPopupItem( 418, OB, mesh/*, "&& " + hasVolumes*/); // create 2D mesh on 3D createPopupItem( 418, OB, mesh + " " + group, // create 2D mesh from 3D
"&& dim>=2");
popupMgr()->insert( separator(), -1, 0 ); popupMgr()->insert( separator(), -1, 0 );
QString only_one_non_empty = QString( " && %1=1 && numberOfNodes>0" ).arg( dc ); QString only_one_non_empty = QString( " && %1=1 && numberOfNodes>0" ).arg( dc );

View File

@ -107,8 +107,8 @@ bool SMESHGUI_PredicateFilter::IsObjValid( const int theObjId ) const
if ( myActor == 0 || myPred->_is_nil() ) if ( myActor == 0 || myPred->_is_nil() )
return false; return false;
SMESH_Actor* anActor = ( SMESH_Actor* )myActor; SMESH_Actor* anActor = dynamic_cast< SMESH_Actor* >( myActor );
if ( anActor->GetObject() == 0 ) if ( !anActor || anActor->GetObject() == 0 )
return false; return false;
SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh(); SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
@ -211,8 +211,8 @@ bool SMESHGUI_QuadrangleFilter::IsValid( const int theCellId ) const
if ( myActor == 0 ) if ( myActor == 0 )
return false; return false;
SMESH_Actor* anActor = ( SMESH_Actor* )myActor; SMESH_Actor* anActor = dynamic_cast< SMESH_Actor* >( myActor );
if ( anActor->GetObject() == 0 ) if ( !anActor || anActor->GetObject() == 0 )
return false; return false;
SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh(); SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
@ -231,8 +231,8 @@ bool SMESHGUI_QuadrangleFilter::IsObjValid( const int theObjId ) const
if ( myActor == 0 ) if ( myActor == 0 )
return false; return false;
SMESH_Actor* anActor = ( SMESH_Actor* )myActor; SMESH_Actor* anActor = dynamic_cast< SMESH_Actor* >( myActor );
if ( anActor->GetObject() == 0 ) if ( !anActor || anActor->GetObject() == 0 )
return false; return false;
SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh(); SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
@ -290,8 +290,8 @@ bool SMESHGUI_TriangleFilter::IsValid( const int theCellId ) const
if ( myActor == 0 ) if ( myActor == 0 )
return false; return false;
SMESH_Actor* anActor = ( SMESH_Actor* )myActor; SMESH_Actor* anActor = dynamic_cast< SMESH_Actor* >( myActor );
if ( anActor->GetObject() == 0 ) if ( !anActor || anActor->GetObject() == 0 )
return false; return false;
SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh(); SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
@ -310,8 +310,8 @@ bool SMESHGUI_TriangleFilter::IsObjValid( const int theObjId ) const
if ( myActor == 0 ) if ( myActor == 0 )
return false; return false;
SMESH_Actor* anActor = ( SMESH_Actor* )myActor; SMESH_Actor* anActor = dynamic_cast< SMESH_Actor* >( myActor );
if ( anActor->GetObject() == 0 ) if ( !anActor || anActor->GetObject() == 0 )
return false; return false;
SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh(); SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
@ -368,8 +368,8 @@ bool SMESHGUI_FacesFilter::IsValid( const int theCellId ) const
if ( myActor == 0 ) if ( myActor == 0 )
return false; return false;
SMESH_Actor* anActor = ( SMESH_Actor* )myActor; SMESH_Actor* anActor = dynamic_cast< SMESH_Actor* >( myActor );
if ( anActor->GetObject() == 0 ) if ( !anActor || anActor->GetObject() == 0 )
return false; return false;
SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh(); SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
@ -387,8 +387,8 @@ bool SMESHGUI_FacesFilter::IsObjValid( const int theObjId ) const
if ( myActor == 0 ) if ( myActor == 0 )
return false; return false;
SMESH_Actor* anActor = ( SMESH_Actor* )myActor; SMESH_Actor* anActor = dynamic_cast< SMESH_Actor* >( myActor );
if ( anActor->GetObject() == 0 ) if ( !anActor || anActor->GetObject() == 0 )
return false; return false;
SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh(); SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
@ -442,11 +442,11 @@ SMESHGUI_VolumesFilter::~SMESHGUI_VolumesFilter()
//======================================================================= //=======================================================================
bool SMESHGUI_VolumesFilter::IsValid( const int theCellId ) const bool SMESHGUI_VolumesFilter::IsValid( const int theCellId ) const
{ {
if ( myActor == 0 ) if ( myActor == 0 || theCellId < 1 )
return false; return false;
SMESH_Actor* anActor = ( SMESH_Actor* )myActor; SMESH_Actor* anActor = dynamic_cast< SMESH_Actor* >( myActor );
if ( anActor->GetObject() == 0 ) if ( !anActor || anActor->GetObject() == 0 )
return false; return false;
SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh(); SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
@ -464,8 +464,8 @@ bool SMESHGUI_VolumesFilter::IsObjValid( const int theObjId ) const
if ( myActor == 0 ) if ( myActor == 0 )
return false; return false;
SMESH_Actor* anActor = ( SMESH_Actor* )myActor; SMESH_Actor* anActor = dynamic_cast< SMESH_Actor* >( myActor );
if ( anActor->GetObject() == 0 ) if ( !anActor || anActor->GetObject() == 0 )
return false; return false;
SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh(); SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();

View File

@ -26,6 +26,8 @@
#include "SMESHGUI_MeshUtils.h" #include "SMESHGUI_MeshUtils.h"
#include "SMESH_TypeFilter.hxx" #include "SMESH_TypeFilter.hxx"
#include "SMESH_LogicalFilter.hxx" #include "SMESH_LogicalFilter.hxx"
#include "SMESHGUI_VTKUtils.h"
#include "SMESH_Actor.h"
// SALOME GUI includes // SALOME GUI includes
#include <LightApp_Application.h> #include <LightApp_Application.h>
@ -37,6 +39,7 @@
#include <SUIT_OverrideCursor.h> #include <SUIT_OverrideCursor.h>
#include <SUIT_Session.h> #include <SUIT_Session.h>
#include <SVTK_ViewModel.h> #include <SVTK_ViewModel.h>
//#include <SVTK_ViewWindow.h>
#include <SalomeApp_Study.h> #include <SalomeApp_Study.h>
#include <SalomeApp_Tools.h> #include <SalomeApp_Tools.h>
@ -53,6 +56,8 @@
#include <QGridLayout> #include <QGridLayout>
#include <QToolButton> #include <QToolButton>
#include <Standard_ErrorHandler.hxx>
#define SPACING 6 #define SPACING 6
#define MARGIN 11 #define MARGIN 11
@ -74,16 +79,22 @@ SMESHGUI_Make2DFrom3DDlg::SMESHGUI_Make2DFrom3DDlg( QWidget* parent )
aModeGrpLayout->setSpacing( SPACING ); aModeGrpLayout->setSpacing( SPACING );
my2dFrom3dRB = new QRadioButton( tr( "2D_FROM_3D" ), aModeGrp ); my2dFrom3dRB = new QRadioButton( tr( "2D_FROM_3D" ), aModeGrp );
my1dFrom2dRB = new QRadioButton( tr( "1D_FROM_2D" ), 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( my2dFrom3dRB );
aModeGrpLayout->addWidget( my1dFrom2dRB ); aModeGrpLayout->addWidget( my1dFrom2dRB );
aModeGrpLayout->addWidget( my1dFrom3dRB ); //aModeGrpLayout->addWidget( my1dFrom3dRB );
// Groups of mesh faces // // Groups of mesh faces
setObjectPixmap( "SMESH", tr( "ICON_SELECT" ) ); // setObjectPixmap( "SMESH", tr( "ICON_SELECT" ) );
createObject( tr( "Groups" ), mainFrame(), Groups ); // createObject( tr( "Groups" ), mainFrame(), Groups );
setNameIndication( Groups, ListOfNames ); // setNameIndication( Groups, ListOfNames );
objectWg( Groups, Btn )->hide(); // 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 // target
QGroupBox* aTargetGrp = new QGroupBox( tr( "TARGET" ), mainFrame() ); QGroupBox* aTargetGrp = new QGroupBox( tr( "TARGET" ), mainFrame() );
@ -106,8 +117,8 @@ SMESHGUI_Make2DFrom3DDlg::SMESHGUI_Make2DFrom3DDlg( QWidget* parent )
aDlgLay->setMargin( 0 ); aDlgLay->setMargin( 0 );
aDlgLay->setSpacing( SPACING ); aDlgLay->setSpacing( SPACING );
aDlgLay->addWidget( aModeGrp, 0, 0, 1, 3 ); aDlgLay->addWidget( aModeGrp, 0, 0, 1, 3 );
aDlgLay->addWidget( objectWg( Groups, Label ), 1, 0 ); aDlgLay->addWidget( objectWg( MeshOrGroups, Label ), 1, 0 );
aDlgLay->addWidget( objectWg( Groups, Control ), 1, 1 ); aDlgLay->addWidget( objectWg( MeshOrGroups, Control ), 1, 1 );
aDlgLay->addWidget( aTargetGrp, 2, 0, 1, 3 ); aDlgLay->addWidget( aTargetGrp, 2, 0, 1, 3 );
aDlgLay->addWidget( myGroupCheck, 3, 0 ); aDlgLay->addWidget( myGroupCheck, 3, 0 );
aDlgLay->addWidget( myGroupName, 3, 1, 1, 2 ); aDlgLay->addWidget( myGroupName, 3, 1, 1, 2 );
@ -153,6 +164,21 @@ void SMESHGUI_Make2DFrom3DDlg::setNewMeshName( const QString& name )
myMeshName->setText( 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 bool SMESHGUI_Make2DFrom3DDlg::needGroup() const
{ {
return myGroupCheck->isChecked(); return myGroupCheck->isChecked();
@ -190,7 +216,9 @@ void SMESHGUI_Make2DFrom3DDlg::onGroupChecked()
*/ */
SMESHGUI_Make2DFrom3DOp::SMESHGUI_Make2DFrom3DOp() 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->my2dFrom3dRB, SIGNAL( toggled(bool) ), this, SLOT( onModeChanged() ) );
connect( myDlg->my1dFrom2dRB, 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() void SMESHGUI_Make2DFrom3DOp::onModeChanged()
{ {
QRadioButton* b = dynamic_cast<QRadioButton*>( sender()); // QRadioButton* b = dynamic_cast<QRadioButton*>( sender());
if ( b && !b->isChecked() ) // if ( b && !b->isChecked() )
return; // return;
// enable "2D groups" field // // enable "2D groups" field
bool enableGroups = ( myDlg->mode() == SMESH::BND_1DFROM3D ); // bool enableGroups = ( myDlg->mode() == SMESH::BND_1DFROM3D );
myDlg->setObjectEnabled( SMESHGUI_Make2DFrom3DDlg::Groups, enableGroups ); // myDlg->setObjectEnabled( SMESHGUI_Make2DFrom3DDlg::Groups, enableGroups );
((QToolButton*) myDlg->objectWg( SMESHGUI_Make2DFrom3DDlg::Groups, // ((QToolButton*) myDlg->objectWg( SMESHGUI_Make2DFrom3DDlg::Groups,
SMESHGUI_Make2DFrom3DDlg::Btn ))->setChecked( enableGroups ); // SMESHGUI_Make2DFrom3DDlg::Btn ))->setChecked( enableGroups );
// install filter // // install filter
int id = enableGroups ? SMESHGUI_Make2DFrom3DDlg::Groups : SMESHGUI_Make2DFrom3DDlg::Mesh; // int id = enableGroups ? SMESHGUI_Make2DFrom3DDlg::Groups : SMESHGUI_Make2DFrom3DDlg::Mesh;
onDeactivateObject( id ); // onDeactivateObject( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups );
onActivateObject( id ); // onActivateObject ( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups );
// selectionDone();
} }
void SMESHGUI_Make2DFrom3DOp::selectionDone() void SMESHGUI_Make2DFrom3DOp::selectionDone()
{ {
myDlg->clearSelection( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups );
mySrcMesh = SMESH::SMESH_Mesh::_nil(); mySrcMesh = SMESH::SMESH_Mesh::_nil();
myDlg->clearSelection( SMESHGUI_Make2DFrom3DDlg::Groups );
if ( !dlg() ) return; if ( !dlg() ) return;
@ -258,13 +296,16 @@ void SMESHGUI_Make2DFrom3DOp::selectionDone()
selected( names, types, ids ); selected( names, types, ids );
myDlg->selectObject( names, types, ids ); myDlg->selectObject( names, types, ids );
SALOME_ListIO sel; selectionMgr()->selectedObjects( sel, SVTK_Viewer::Type() ); // enable/desable "new mesh" button
if ( !sel.IsEmpty() ) bool isMesh = true;
for ( int i = 0; i < ids.count() && isMesh; ++i )
{ {
SMESH::SMESH_IDSource_var IS = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>(sel.First()); _PTR(SObject) sobj =
if(!CORBA::is_nil(IS)) SMESHGUI::activeStudy()->studyDS()->FindObjectID( ids[i].toLatin1().constData() );
mySrcMesh = IS->GetMesh(); mySrcMesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>( sobj );
isMesh = !mySrcMesh->_is_nil();
} }
myDlg->setNewMeshEnabled( isMesh );
} }
catch ( const SALOME::SALOME_Exception& S_ex ) { catch ( const SALOME::SALOME_Exception& S_ex ) {
SalomeApp_Tools::QtCatchCorbaException( S_ex ); SalomeApp_Tools::QtCatchCorbaException( S_ex );
@ -276,8 +317,13 @@ void SMESHGUI_Make2DFrom3DOp::selectionDone()
SUIT_SelectionFilter* SMESHGUI_Make2DFrom3DOp::createFilter( const int theId ) const SUIT_SelectionFilter* SMESHGUI_Make2DFrom3DOp::createFilter( const int theId ) const
{ {
MeshObjectType type = ( theId == SMESHGUI_Make2DFrom3DDlg::Groups ? GROUP_FACE : MESH ); SMESHGUI_Make2DFrom3DOp* me = (SMESHGUI_Make2DFrom3DOp*) this;
SUIT_SelectionFilter* f = new SMESH_TypeFilter( type );
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; return f;
} }
@ -286,43 +332,61 @@ bool SMESHGUI_Make2DFrom3DOp::isValid( QString& msg ) const
if ( !dlg() ) return false; if ( !dlg() ) return false;
// check if a mesh is selected // check if a mesh is selected
if ( mySrcMesh->_is_nil() ) if ( !myDlg->hasSelection( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups ))
{ {
msg = tr( "SMESH_ERR_NO_INPUT_MESH" ); msg = tr( "SMESH_ERR_NO_INPUT_MESH" );
return false; return false;
} }
// check if groups are selected
SMESH::Bnd_Dimension mode = myDlg->mode();
if ( mode == SMESH::BND_1DFROM3D )
{
SMESH::SMESH_GroupBase_var grp;
QStringList entries; QStringList entries;
dlg()->selectedObject( SMESHGUI_Make2DFrom3DDlg::Groups, entries ); dlg()->selectedObject( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups, entries );
if ( !entries.isEmpty() ) const bool isMeshSelected = ( !mySrcMesh->_is_nil() );
if ( isMeshSelected )
{ {
_PTR(SObject) sobj = SMESHGUI::activeStudy()->studyDS()->FindObjectID( entries[0].toLatin1().constData() ); // only one mesh is allowed
if ( sobj ) if ( entries.size() > 1 ) {
grp = SMESH::SObjectToInterface<SMESH::SMESH_GroupBase>( sobj ); msg = tr( "SMESH_TOO_MANY_MESHES" );
}
if ( grp->_is_nil() ) {
msg = tr( "SMESH_ERR_NO_INPUT_GROUP" );
return false; return false;
} }
} }
else else
{ {
// check if mesh contains elements of required type // 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;
}
}
}
// check if the selected objects contains elements of required type
bool hasFaces = false, hasVolumes = false;
SMESH::Bnd_Dimension mode = myDlg->mode(); SMESH::Bnd_Dimension mode = myDlg->mode();
for ( int i = 0; i < entries.count(); ++i )
if ( mode == SMESH::BND_2DFROM3D && mySrcMesh->NbVolumes() == 0 ) { {
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" ); msg = tr( "SMESH_ERR_NO_3D_ELEMENTS" );
return false; return false;
} }
else if ( mode == SMESH::BND_1DFROM2D && mySrcMesh->NbFaces() == 0 ) { else if ( mode == SMESH::BND_1DFROM2D && !hasFaces ) {
msg = tr( "SMESH_ERR_NO_2D_ELEMENTS" ); msg = tr( "SMESH_ERR_NO_2D_ELEMENTS" );
return false; return false;
} }
}
// check if new mesh name is specified // check if new mesh name is specified
if ( myDlg->needNewMesh() && myDlg->getNewMeshName().isEmpty() ) { if ( myDlg->needNewMesh() && myDlg->getNewMeshName().isEmpty() ) {
@ -345,21 +409,42 @@ bool SMESHGUI_Make2DFrom3DOp::compute2DMesh( QStringList& theEntryList )
bool ok = false; bool ok = false;
try { try {
QStringList entries;
dlg()->selectedObject( SMESHGUI_Make2DFrom3DDlg::Groups, entries );
SMESH::ListOfIDSources_var groups = new SMESH::ListOfIDSources;
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 );
groups[i] = grp;
}
SMESH::Bnd_Dimension mode = myDlg->mode(); SMESH::Bnd_Dimension mode = myDlg->mode();
QString meshName = myDlg->needNewMesh() ? myDlg->getNewMeshName() : QString(); QString meshName = myDlg->needNewMesh() ? myDlg->getNewMeshName() : QString();
QString groupName = myDlg->needGroup() ? myDlg->getGroupName() : QString(); QString groupName = myDlg->needGroup() ? myDlg->getGroupName() : QString();
bool copyAll = myDlg->copySource(); bool copyAll = myDlg->copySource();
QStringList entries;
dlg()->selectedObject( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups, entries );
SMESH::ListOfIDSources_var groups = new SMESH::ListOfIDSources;
QString wrongGroups = "";
if ( mySrcMesh->_is_nil() ) // get selected groups, find groups of wrong type
{
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();
}
if ( !CORBA::is_nil( mySrcMesh ) ) { if ( !CORBA::is_nil( mySrcMesh ) ) {
SMESH::SMESH_MeshEditor_var aMeshEditor = mySrcMesh->GetMeshEditor(); SMESH::SMESH_MeshEditor_var aMeshEditor = mySrcMesh->GetMeshEditor();
SMESH::SMESH_Group_var newGrp; SMESH::SMESH_Group_var newGrp;
@ -371,9 +456,11 @@ bool SMESHGUI_Make2DFrom3DOp::compute2DMesh( QStringList& theEntryList )
groups, groups,
newMesh.out(), newMesh.out(),
newGrp.out() ); newGrp.out() );
SUIT_MessageBox::information( myDlg, QString msg = tr("NB_ADDED").arg( nbAdded );
tr("SMESH_INFORMATION"), if ( !wrongGroups.isEmpty() )
tr("NB_ADDED").arg( nbAdded )); msg += ".\n" + tr("WRONG_GROUPS").arg( wrongGroups );
SUIT_MessageBox::information( myDlg, tr("SMESH_INFORMATION"), msg);
if ( !newMesh->_is_nil() ) { if ( !newMesh->_is_nil() ) {
if( _PTR(SObject) aSObject = SMESH::ObjectToSObject( newMesh ) ) if( _PTR(SObject) aSObject = SMESH::ObjectToSObject( newMesh ) )
theEntryList.append( aSObject->GetID().c_str() ); theEntryList.append( aSObject->GetID().c_str() );
@ -387,6 +474,11 @@ bool SMESHGUI_Make2DFrom3DOp::compute2DMesh( QStringList& theEntryList )
#endif #endif
} }
ok = true; 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 ( ... ) { catch ( ... ) {

View File

@ -26,6 +26,7 @@
#include "SMESH_SMESHGUI.hxx" #include "SMESH_SMESHGUI.hxx"
#include "SMESHGUI_Dialog.h" #include "SMESHGUI_Dialog.h"
#include "SMESHGUI_SelectionOp.h" #include "SMESHGUI_SelectionOp.h"
#include "SMESH_TypeFilter.hxx"
#include <SALOMEconfig.h> #include <SALOMEconfig.h>
#include CORBA_SERVER_HEADER(SMESH_MeshEditor) #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
@ -45,7 +46,7 @@ class SMESHGUI_EXPORT SMESHGUI_Make2DFrom3DDlg : public SMESHGUI_Dialog
Q_OBJECT Q_OBJECT
public: public:
enum { Mesh, Groups }; enum { MeshOrGroups };
SMESHGUI_Make2DFrom3DDlg( QWidget* ); SMESHGUI_Make2DFrom3DDlg( QWidget* );
virtual ~SMESHGUI_Make2DFrom3DDlg(); virtual ~SMESHGUI_Make2DFrom3DDlg();
@ -55,6 +56,8 @@ public:
bool needNewMesh() const; bool needNewMesh() const;
QString getNewMeshName() const; QString getNewMeshName() const;
void setNewMeshName( const QString& ); void setNewMeshName( const QString& );
void setNewMeshEnabled( bool );
bool getNewMeshEnabled() const;
bool needGroup() const; bool needGroup() const;
QString getGroupName() const; QString getGroupName() const;
@ -110,6 +113,9 @@ private:
private: private:
SMESH::SMESH_Mesh_var mySrcMesh; SMESH::SMESH_Mesh_var mySrcMesh;
QPointer<SMESHGUI_Make2DFrom3DDlg> myDlg; QPointer<SMESHGUI_Make2DFrom3DDlg> myDlg;
SMESH_TypeFilter myMeshFilter;
SMESH_TypeFilter myGroupFilter;
}; };
#endif // SMESHGUI_Make2DFrom3DOp_H #endif // SMESHGUI_Make2DFrom3DOp_H

View File

@ -682,6 +682,8 @@ bool SMESHGUI_MergeDlg::ClickOnApply()
} catch(...) { } catch(...) {
} }
ListCoincident->clear();
SMESH::UpdateView(); SMESH::UpdateView();
SMESHGUI::Modified(); SMESHGUI::Modified();

View File

@ -5617,7 +5617,7 @@ It is impossible to read point coordinates from file</translation>
</message> </message>
<message> <message>
<source>Groups</source> <source>Groups</source>
<translation>2D groups</translation> <translation>Mesh or groups</translation>
</message> </message>
<message> <message>
<source>MODE</source> <source>MODE</source>
@ -5666,21 +5666,31 @@ It is impossible to read point coordinates from file</translation>
<source>NB_ADDED</source> <source>NB_ADDED</source>
<translation>%1 boundary elements have been added</translation> <translation>%1 boundary elements have been added</translation>
</message> </message>
<message>
<source>WRONG_GROUPS</source>
<translation>The following groups have not been processed
as they are of improper type:
%1</translation>
</message>
<message> <message>
<source>SMESH_ERR_NO_INPUT_MESH</source> <source>SMESH_ERR_NO_INPUT_MESH</source>
<translation>Source mesh is not specified</translation> <translation>Source mesh is not specified</translation>
</message> </message>
<message> <message>
<source>SMESH_ERR_NO_INPUT_GROUP</source> <source>SMESH_TOO_MANY_MESHES</source>
<translation>2D group is not specified</translation> <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>
<message> <message>
<source>SMESH_ERR_NO_3D_ELEMENTS</source> <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>
<message> <message>
<source>SMESH_ERR_NO_2D_ELEMENTS</source> <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>
<message> <message>
<source>SMESH_ERR_MESH_NAME_NOT_SPECIFIED</source> <source>SMESH_ERR_MESH_NAME_NOT_SPECIFIED</source>

View File

@ -632,7 +632,10 @@ SALOMEDS::SObject_ptr SMESH_Gen_i::PublishSubMesh (SALOMEDS::Study_ptr theS
SetName( aRootSO, aRootName ); SetName( aRootSO, aRootName );
// Add new submesh to corresponding sub-tree // 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() ) if ( aSubMeshSO->_is_nil() )
return aSubMeshSO._retn(); return aSubMeshSO._retn();
} }

View File

@ -592,8 +592,12 @@ SMESH::long_array* SMESH_GroupBase_i::GetIDs()
SMESH::array_of_ElementType* SMESH_GroupBase_i::GetTypes() SMESH::array_of_ElementType* SMESH_GroupBase_i::GetTypes()
{ {
SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType; SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
if ( SMESHDS_GroupBase* ds = GetGroupDS() )
if ( !ds->IsEmpty() )
{
types->length( 1 ); types->length( 1 );
types[0] = GetType(); types[0] = GetType();
}
return types._retn(); return types._retn();
} }

View File

@ -432,8 +432,10 @@ struct _IDSource : public POA_SMESH::SMESH_IDSource
SMESH::array_of_ElementType* GetTypes() SMESH::array_of_ElementType* GetTypes()
{ {
SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType; SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
if ( _ids.length() > 0 ) {
types->length( 1 ); types->length( 1 );
types[0] = _type; types[0] = _type;
}
return types._retn(); return types._retn();
} }
}; };
@ -5881,20 +5883,37 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
if ( dim > SMESH::BND_1DFROM2D ) if ( dim > SMESH::BND_1DFROM2D )
THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM); THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
// check that groups belongs to to this mesh and is not this mesh // separate groups belonging to this and other mesh
const int nbGroups = groups.length(); SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
for ( int i = 0; i < nbGroups; ++i ) 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(); SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m )) 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] )) if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM); THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
} }
groupsOfThisMesh->length( nbGroups );
TPythonDump pyDump; groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
int nbAdded = 0; int nbAdded = 0;
TPythonDump pyDump;
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_Mesh_var mesh_var;
SMESH::SMESH_Group_var group_var; SMESH::SMESH_Group_var group_var;
@ -5931,12 +5950,12 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
TIDSortedElemSet elements; TIDSortedElemSet elements;
if ( nbGroups > 0 ) if ( groups.length() > 0 )
{ {
for ( int i = 0; i < nbGroups; ++i ) for ( int i = 0; i < nbGroups; ++i )
{ {
elements.clear(); elements.clear();
if ( idSourceToSet( groups[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/false )) if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
{ {
SMESH::Bnd_Dimension bdim = SMESH::Bnd_Dimension bdim =
( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D; ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;

View 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::array_of_ElementType_var types = new SMESH::array_of_ElementType;
::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId]; ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
if ( SMESHDS_SubMesh* smDS = aSubMesh->GetSubMeshDS() )
{
SMDS_ElemIteratorPtr eIt = smDS->GetElements();
if ( eIt->more() )
{
types->length( 1 );
types[0] = SMESH::ElementType( eIt->next()->GetType());
}
else if ( smDS->GetNodes()->more() )
{
TopoDS_Shape shape = aSubMesh->GetSubShape(); TopoDS_Shape shape = aSubMesh->GetSubShape();
while ( !shape.IsNull() && shape.ShapeType() == TopAbs_COMPOUND ) while ( !shape.IsNull() && shape.ShapeType() == TopAbs_COMPOUND )
{ {
TopoDS_Iterator it( shape ); TopoDS_Iterator it( shape );
shape = it.More() ? it.Value() : TopoDS_Shape(); shape = it.More() ? it.Value() : TopoDS_Shape();
} }
if ( !shape.IsNull() ) if ( !shape.IsNull() && shape.ShapeType() == TopAbs_VERTEX )
{ {
types->length( 1 ); types->length( 1 );
switch ( ::SMESH_Gen::GetShapeDim( shape )) types[0] = SMESH::NODE;
{ }
case 0: types[0] = SMESH::ELEM0D; break;
case 1: types[0] = SMESH::EDGE; break;
case 2: types[0] = SMESH::FACE; break;
case 3: types[0] = SMESH::VOLUME; break;
default:
types->length(0);
} }
} }
return types._retn(); return types._retn();

View File

@ -490,6 +490,25 @@ def CheckPlugin(plugin):
return False return False
return True 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 # 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 # @return an object of type SMESH_SubMesh, representing a part of mesh, which lies on the given shape
# @ingroup l2_submeshes # @ingroup l2_submeshes
def GetSubMesh(self, geom, name): def GetSubMesh(self, geom, name):
if not geom.IsSame( self.geom ) and not geom.GetStudyEntry(): AssureGeomPublished( self, geom, name )
## 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 )
submesh = self.mesh.GetSubMesh( geom, name ) submesh = self.mesh.GetSubMesh( geom, name )
return submesh return submesh
@ -1580,7 +1587,7 @@ class Mesh:
salome.sg.updateObjBrowser(1) salome.sg.updateObjBrowser(1)
## Computes a tetrahedral mesh using AutomaticLength + MEFISTO + NETGEN ## 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 # @return True or False
# @ingroup l3_algos_basic # @ingroup l3_algos_basic
def AutomaticTetrahedralization(self, fineness=0): def AutomaticTetrahedralization(self, fineness=0):
@ -1597,7 +1604,7 @@ class Mesh:
return self.Compute() return self.Compute()
## Computes an hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron ## 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 # @return True or False
# @ingroup l3_algos_basic # @ingroup l3_algos_basic
def AutomaticHexahedralization(self, fineness=0): def AutomaticHexahedralization(self, fineness=0):
@ -1667,8 +1674,8 @@ class Mesh:
pass pass
pass pass
## Deprecated, used only for compatibility! Please, use ExportMED() method instead. ## 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 # 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 ## allowing to overwrite the file if it exists or add the exported data to its contents
# @param f the file name # @param f the file name
# @param version values are SMESH.MED_V2_1, SMESH.MED_V2_2 # @param version values are SMESH.MED_V2_1, SMESH.MED_V2_2
@ -1767,58 +1774,33 @@ class Mesh:
# @return SMESH_GroupOnGeom # @return SMESH_GroupOnGeom
# @ingroup l2_grps_create # @ingroup l2_grps_create
def GroupOnGeom(self, grp, name="", typ=None): def GroupOnGeom(self, grp, name="", typ=None):
AssureGeomPublished( self, grp, name )
if name == "": if name == "":
name = grp.GetName() name = grp.GetName()
if not typ:
typ = self._groupTypeFromShape( grp )
return self.mesh.CreateGroupFromGEOM(typ, name, grp)
if typ == None: ## Pivate method to get a type of group on geometry
tgeo = str(grp.GetShapeType()) def _groupTypeFromShape( self, shape ):
tgeo = str(shape.GetShapeType())
if tgeo == "VERTEX": if tgeo == "VERTEX":
typ = NODE typ = NODE
elif tgeo == "EDGE": elif tgeo == "EDGE":
typ = EDGE typ = EDGE
elif tgeo == "FACE": elif tgeo == "FACE" or tgeo == "SHELL":
typ = FACE typ = FACE
elif tgeo == "SOLID": elif tgeo == "SOLID" or tgeo == "COMPSOLID":
typ = VOLUME
elif tgeo == "SHELL":
typ = VOLUME typ = VOLUME
elif tgeo == "COMPOUND": elif tgeo == "COMPOUND":
try: # it raises on a compound of compounds sub = self.geompyD.SubShapeAll( shape, geompyDC.ShapeType["SHAPE"])
if len( self.geompyD.GetObjectIDs( grp )) == 0: if not sub:
print "Mesh.Group: empty geometric group", GetName( grp ) raise ValueError,"_groupTypeFromShape(): empty geometric group or compound '%s'" % GetName(shape)
return 0 return self._groupTypeFromShape( sub[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: else:
# just a compound raise ValueError, \
for elemType, shapeType in [[VOLUME,"SOLID"],[FACE,"FACE"], "_groupTypeFromShape(): invalid geometry '%s'" % GetName(shape)
[EDGE,"EDGE"],[NODE,"VERTEX"]]: return typ
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
else:
return self.mesh.CreateGroupFromGEOM(typ, name, grp)
## Creates a mesh group with given \a name based on the \a filter which ## 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 ## is a special type of group dynamically updating it's contents during
@ -4480,7 +4462,7 @@ class Mesh_Algorithm:
self.geom = mesh.geom self.geom = mesh.geom
else: else:
self.geom = geom self.geom = geom
self.AssureGeomPublished( geom ) AssureGeomPublished( mesh, geom )
try: try:
name = GetName(geom) name = GetName(geom)
pass pass
@ -4492,25 +4474,6 @@ class Mesh_Algorithm:
TreatHypoStatus( status, algo.GetName(), name, True ) TreatHypoStatus( status, algo.GetName(), name, True )
return 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): def CompareHyp (self, hyp, args):
print "CompareHyp is not implemented for ", self.__class__.__name__, ":", hyp.GetName() print "CompareHyp is not implemented for ", self.__class__.__name__, ":", hyp.GetName()
return False return False
@ -4860,7 +4823,7 @@ class Mesh_Segment(Mesh_Algorithm):
### 0D algorithm ### 0D algorithm
if self.geom is None: if self.geom is None:
raise RuntimeError, "Attemp to create SegmentAroundVertex_0D algoritm on None shape" raise RuntimeError, "Attemp to create SegmentAroundVertex_0D algoritm on None shape"
self.AssureGeomPublished( self.geom ) AssureGeomPublished( self.mesh, self.geom )
name = GetName(self.geom) name = GetName(self.geom)
algo = self.FindAlgorithm("SegmentAroundVertex_0D", self.mesh.smeshpyD) 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 # @param theConstantSizeDistance : distance until which the mesh size will be kept constant on theFace
# @ingroup l3_hypos_blsurf # @ingroup l3_hypos_blsurf
def SetAttractorGeom(self, theFace, theAttractor, theStartSize, theEndSize, theInfluenceDistance, theConstantSizeDistance): def SetAttractorGeom(self, theFace, theAttractor, theStartSize, theEndSize, theInfluenceDistance, theConstantSizeDistance):
self.AssureGeomPublished( theFace ) AssureGeomPublished( self.mesh, theFace )
self.AssureGeomPublished( theAttractor ) AssureGeomPublished( self.mesh, theAttractor )
# Parameter of BLSURF algo # Parameter of BLSURF algo
self.Parameters().SetAttractorGeom(theFace, theAttractor, theStartSize, theEndSize, theInfluenceDistance, theConstantSizeDistance) 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 # @param theFace : face on which the attractor has to be removed
# @ingroup l3_hypos_blsurf # @ingroup l3_hypos_blsurf
def UnsetAttractorGeom(self, theFace): def UnsetAttractorGeom(self, theFace):
self.AssureGeomPublished( theFace ) AssureGeomPublished( self.mesh, theFace )
# Parameter of BLSURF algo # Parameter of BLSURF algo
self.Parameters().SetAttractorGeom(theFace) 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. ## To set an enforced vertex given a GEOM vertex, group or compound.
# @ingroup l3_hypos_ghs3dh # @ingroup l3_hypos_ghs3dh
def SetEnforcedVertexGeom(self, theVertex, size): def SetEnforcedVertexGeom(self, theVertex, size):
self.AssureGeomPublished( theVertex ) AssureGeomPublished( self.mesh, theVertex )
# Advanced parameter of GHS3D # Advanced parameter of GHS3D
return self.Parameters().SetEnforcedVertexGeom(theVertex, size) return self.Parameters().SetEnforcedVertexGeom(theVertex, size)
@ -5629,14 +5592,14 @@ class Mesh_Tetrahedron(Mesh_Algorithm):
# Only on meshes w/o geometry # Only on meshes w/o geometry
# @ingroup l3_hypos_ghs3dh # @ingroup l3_hypos_ghs3dh
def SetEnforcedVertexGeomWithGroup(self, theVertex, size, groupName): def SetEnforcedVertexGeomWithGroup(self, theVertex, size, groupName):
self.AssureGeomPublished( theVertex ) AssureGeomPublished( self.mesh, theVertex )
# Advanced parameter of GHS3D # Advanced parameter of GHS3D
return self.Parameters().SetEnforcedVertexGeomWithGroup(theVertex, size,groupName) return self.Parameters().SetEnforcedVertexGeomWithGroup(theVertex, size,groupName)
## To remove an enforced vertex given a GEOM vertex, group or compound. ## To remove an enforced vertex given a GEOM vertex, group or compound.
# @ingroup l3_hypos_ghs3dh # @ingroup l3_hypos_ghs3dh
def RemoveEnforcedVertexGeom(self, theVertex): def RemoveEnforcedVertexGeom(self, theVertex):
self.AssureGeomPublished( theVertex ) AssureGeomPublished( self.mesh, theVertex )
# Advanced parameter of GHS3D # Advanced parameter of GHS3D
return self.Parameters().RemoveEnforcedVertexGeom(theVertex) 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 # @param UseExisting if ==true - searches for the existing hypothesis created with
# the same parameters, else (default) - creates a new one # the same parameters, else (default) - creates a new one
def SourceEdge(self, edge, mesh=None, srcV=None, tgtV=None, UseExisting=0): def SourceEdge(self, edge, mesh=None, srcV=None, tgtV=None, UseExisting=0):
self.AssureGeomPublished( edge ) AssureGeomPublished( self.mesh, edge )
self.AssureGeomPublished( srcV ) AssureGeomPublished( self.mesh, srcV )
self.AssureGeomPublished( tgtV ) AssureGeomPublished( self.mesh, tgtV )
hyp = self.Hypothesis("ProjectionSource1D", [edge,mesh,srcV,tgtV], hyp = self.Hypothesis("ProjectionSource1D", [edge,mesh,srcV,tgtV],
UseExisting=0) UseExisting=0)
#UseExisting=UseExisting, CompareMethod=self.CompareSourceEdge) #UseExisting=UseExisting, CompareMethod=self.CompareSourceEdge)
@ -5832,7 +5795,7 @@ class Mesh_Projection2D(Mesh_Algorithm):
def SourceFace(self, face, mesh=None, srcV1=None, tgtV1=None, def SourceFace(self, face, mesh=None, srcV1=None, tgtV1=None,
srcV2=None, tgtV2=None, UseExisting=0): srcV2=None, tgtV2=None, UseExisting=0):
for geom in [ face, srcV1, tgtV1, srcV2, tgtV2 ]: 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], hyp = self.Hypothesis("ProjectionSource2D", [face,mesh,srcV1,tgtV1,srcV2,tgtV2],
UseExisting=0) UseExisting=0)
#UseExisting=UseExisting, CompareMethod=self.CompareSourceFace) #UseExisting=UseExisting, CompareMethod=self.CompareSourceFace)
@ -5879,7 +5842,7 @@ class Mesh_Projection3D(Mesh_Algorithm):
def SourceShape3D(self, solid, mesh=0, srcV1=0, tgtV1=0, def SourceShape3D(self, solid, mesh=0, srcV1=0, tgtV1=0,
srcV2=0, tgtV2=0, UseExisting=0): srcV2=0, tgtV2=0, UseExisting=0):
for geom in [ solid, srcV1, tgtV1, srcV2, tgtV2 ]: for geom in [ solid, srcV1, tgtV1, srcV2, tgtV2 ]:
self.AssureGeomPublished( geom ) AssureGeomPublished( self.mesh, geom )
hyp = self.Hypothesis("ProjectionSource3D", hyp = self.Hypothesis("ProjectionSource3D",
[solid,mesh,srcV1,tgtV1,srcV2,tgtV2], [solid,mesh,srcV1,tgtV1,srcV2,tgtV2],
UseExisting=0) UseExisting=0)
@ -6141,7 +6104,7 @@ class Mesh_UseExistingElements(Mesh_Algorithm):
if self.algo.GetName() == "Import_2D": if self.algo.GetName() == "Import_2D":
raise ValueError, "algoritm dimension mismatch" raise ValueError, "algoritm dimension mismatch"
for group in groups: for group in groups:
self.AssureGeomPublished( group ) AssureGeomPublished( self.mesh, group )
hyp = self.Hypothesis("ImportSource1D", [groups, toCopyMesh, toCopyGroups], hyp = self.Hypothesis("ImportSource1D", [groups, toCopyMesh, toCopyGroups],
UseExisting=UseExisting, CompareMethod=self._compareHyp) UseExisting=UseExisting, CompareMethod=self._compareHyp)
hyp.SetSourceEdges(groups) hyp.SetSourceEdges(groups)
@ -6158,7 +6121,7 @@ class Mesh_UseExistingElements(Mesh_Algorithm):
if self.algo.GetName() == "Import_1D": if self.algo.GetName() == "Import_1D":
raise ValueError, "algoritm dimension mismatch" raise ValueError, "algoritm dimension mismatch"
for group in groups: for group in groups:
self.AssureGeomPublished( group ) AssureGeomPublished( self.mesh, group )
hyp = self.Hypothesis("ImportSource2D", [groups, toCopyMesh, toCopyGroups], hyp = self.Hypothesis("ImportSource2D", [groups, toCopyMesh, toCopyGroups],
UseExisting=UseExisting, CompareMethod=self._compareHyp) UseExisting=UseExisting, CompareMethod=self._compareHyp)
hyp.SetSourceFaces(groups) hyp.SetSourceFaces(groups)

View 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 = 1; // 1: il existe un fonction areteideale_()
// Z nutysu=0; // 0: on utilise aretmx // Z nutysu=0; // 0: on utilise aretmx
R aretmx = _edgeLength; // longueur max aretes future triangulation R aretmx = _edgeLength; // longueur max aretes future triangulation
if ( _hypMaxElementArea )
aretmx *= 1.5;
nblf = nbWires; nblf = nbWires;

View File

@ -2218,9 +2218,9 @@ bool StdMeshers_Quadrangle_2D::ComputeReduced (SMESH_Mesh & aMesh,
int nrows = nr1 - 1; int nrows = nr1 - 1;
int ncol_top = nt1 - 1; int ncol_top = nt1 - 1;
int ncol_bot = nb1 - 1; int ncol_bot = nb1 - 1;
// maximum number of bottom elements for "tree" simple reduce 3->1 // number of rows needed to reduce ncol_bot to ncol_top using simple 3->1 "tree" (see below)
int max_tree31 = ncol_top * pow(3.0, nrows); int nrows_tree31 = int( log( ncol_bot / ncol_top ) / log( 3 )); // = log x base 3
if (ncol_bot > max_tree31) if ( nrows < nrows_tree31 )
MultipleReduce = true; 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 // maximum number of bottom elements for "linear" simple reduce 4->2
int max_lin31 = ncol_top + ncol_top * 2 * nrows; int max_lin31 = ncol_top + ncol_top * 2 * nrows;
// maximum number of bottom elements for "tree" simple reduce 4->2 // maximum number of bottom elements for "tree" simple reduce 4->2
int max_tree42 = npair_top * pow(2.0, nrows + 1); int max_tree42 = 0;
if (ncol_top > npair_top * 2) { // number of rows needed to reduce ncol_bot to ncol_top using simple 4->2 "tree"
int delta = ncol_bot - max_tree42; 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++) { for (int irow = 1; irow < nrows; irow++) {
int nfour = delta / 4; int nfour = delta / 4;
delta -= nfour * 2; delta -= nfour * 2;

View File

@ -43,9 +43,18 @@
#include "utilities.h" #include "utilities.h"
#include <BRep_Tool.hxx> #include <BRep_Tool.hxx>
#include <Bnd_B2d.hxx>
#include <Bnd_B3d.hxx>
#include <ElCLib.hxx>
#include <GCPnts_AbscissaPoint.hxx> #include <GCPnts_AbscissaPoint.hxx>
#include <Geom2d_Circle.hxx>
#include <Geom2d_Line.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <GeomAdaptor_Curve.hxx> #include <GeomAdaptor_Curve.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Curve.hxx> #include <Geom_Curve.hxx>
#include <Geom_Line.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <Precision.hxx> #include <Precision.hxx>
#include <TopExp.hxx> #include <TopExp.hxx>
#include <TopExp_Explorer.hxx> #include <TopExp_Explorer.hxx>
@ -268,6 +277,10 @@ namespace VISCOUS
gp_XYZ* _plnNorm; gp_XYZ* _plnNorm;
_2NearEdges() { _nodes[0]=_nodes[1]=0; _plnNorm = 0; } _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 // FACE's WOL, srink on which is forbiden due to algo on the adjacent SOLID
set< TGeomID > _noShrinkFaces; set< TGeomID > _noShrinkFaces;
// end index in _edges of _LayerEdge's based on EDGE (map key) to // <EDGE to smooth on> to <it's curve>
// FACE (maybe NULL) they are inflated along map< TGeomID,Handle(Geom_Curve)> _edge2curve;
//map< int, TopoDS_Face > _endEdge2Face;
// end indices in _edges of _LayerEdge on one shape to smooth // end indices in _edges of _LayerEdge on one shape to smooth
vector< int > _endEdgeToSmooth; vector< int > _endEdgeToSmooth;
@ -377,6 +389,13 @@ namespace VISCOUS
const StdMeshers_ViscousLayers* h=0, const StdMeshers_ViscousLayers* h=0,
_MeshOfSolid* m=0) :_solid(s), _hyp(h), _proxyMesh(m) {} _MeshOfSolid* m=0) :_solid(s), _hyp(h), _proxyMesh(m) {}
~_SolidData(); ~_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); const double cosin);
void limitStepSize( _SolidData& data, const double minSize); void limitStepSize( _SolidData& data, const double minSize);
bool inflate(_SolidData& data); 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 updateNormals( _SolidData& data, SMESH_MesherHelper& helper );
bool refine(_SolidData& data); bool refine(_SolidData& data);
bool shrink(); bool shrink();
@ -1994,7 +2019,7 @@ bool _ViscousBuilder::inflate(_SolidData& data)
//================================================================================ //================================================================================
bool _ViscousBuilder::smoothAndCheck(_SolidData& data, bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
int nbSteps, const int nbSteps,
double & distToIntersection) double & distToIntersection)
{ {
if ( data._endEdgeToSmooth.empty() ) if ( data._endEdgeToSmooth.empty() )
@ -2028,6 +2053,8 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
TGeomID sInd = data._edges[ iBeg ]->_nodes[0]->getshapeId(); TGeomID sInd = data._edges[ iBeg ]->_nodes[0]->getshapeId();
if ( data._edges[ iBeg ]->IsOnEdge() ) if ( data._edges[ iBeg ]->IsOnEdge() )
{ // 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); dumpFunction(SMESH_Comment("smooth")<<data._index << "_Ed"<<sInd <<"_InfStep"<<nbSteps);
// smooth on EDGE's // smooth on EDGE's
@ -2041,9 +2068,11 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
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 else
{ {
// smooth on FACE's // smooth on FACE's
@ -2094,7 +2123,7 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
double dist; double dist;
const SMDS_MeshElement* intFace = 0; const SMDS_MeshElement* intFace = 0;
#ifdef __myDEBUG #ifdef __myDEBUG
const SMDS_MeshElement* *closestFace = 0; const SMDS_MeshElement* closestFace = 0;
int iLE = 0; int iLE = 0;
#endif #endif
for ( unsigned i = 0; i < data._edges.size(); ++i ) for ( unsigned i = 0; i < data._edges.size(); ++i )
@ -2124,6 +2153,253 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
return true; 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 * \brief Modify normals of _LayerEdge's on EDGE's to avoid intersection with
@ -3219,15 +3495,32 @@ bool _ViscousBuilder::shrink()
if ( badNb > 0 ) if ( badNb > 0 )
return error(SMESH_Comment("Can't shrink 2D mesh on face ") << f2sd->first ); return error(SMESH_Comment("Can't shrink 2D mesh on face ") << f2sd->first );
} }
// No wrongly shaped faces remain; final smooth. Set node XYZ // No wrongly shaped faces remain; final smooth. Set node XYZ.
for ( int st = 3; st; --st ) // 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 dumpFunction(SMESH_Comment("shrinkFace")<<f2sd->first<<"_st"<<++smooStep); // debug
for ( unsigned i = 0; i < nodesToSmooth.size(); ++i ) for ( unsigned i = 0; i < nodesToSmooth.size(); ++i )
nodesToSmooth[i].Smooth( badNb,surface,helper,refSign,/*set3D=*/st==1 ); nodesToSmooth[i].Smooth( badNb,surface,helper,refSign,/*set3D=*/st==1 );
dumpFunctionEnd(); 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 ); _SrinkShapeListener::ToClearSubMeshWithSolid( sm, data._solid );
}// loop on FACES to srink mesh on }// loop on FACES to srink mesh on