diff --git a/CMakeLists.txt b/CMakeLists.txt
index 249c3c09d..a88f8c23a 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -29,10 +29,10 @@ STRING(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UC)
SET(${PROJECT_NAME_UC}_MAJOR_VERSION 7)
SET(${PROJECT_NAME_UC}_MINOR_VERSION 4)
-SET(${PROJECT_NAME_UC}_PATCH_VERSION 0)
+SET(${PROJECT_NAME_UC}_PATCH_VERSION 1)
SET(${PROJECT_NAME_UC}_VERSION
${${PROJECT_NAME_UC}_MAJOR_VERSION}.${${PROJECT_NAME_UC}_MINOR_VERSION}.${${PROJECT_NAME_UC}_PATCH_VERSION})
-SET(${PROJECT_NAME_UC}_VERSION_DEV 0)
+SET(${PROJECT_NAME_UC}_VERSION_DEV 1)
# Find KERNEL
# ===========
@@ -162,7 +162,7 @@ ENDIF(EXISTS ${GEOM_ROOT_DIR})
##
# VTK is obligatiry for the SMESH
-FIND_PACKAGE(SalomeVTK 6.1 REQUIRED)
+FIND_PACKAGE(SalomeVTK REQUIRED)
FIND_PACKAGE(SalomeCAS REQUIRED)
diff --git a/doc/salome/examples/CMakeLists.txt b/doc/salome/examples/CMakeLists.txt
index 227764998..7aa063689 100644
--- a/doc/salome/examples/CMakeLists.txt
+++ b/doc/salome/examples/CMakeLists.txt
@@ -17,8 +17,10 @@
# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
#
+# examples that cant be used for testing because they use external mesher plug-ins
SET(BAD_TESTS
3dmesh.py
+ a3DmeshOnModified2Dmesh.py
creating_meshes_ex01.py
creating_meshes_ex03.py
creating_meshes_ex05.py
@@ -39,14 +41,14 @@ SET(BAD_TESTS
quality_controls_ex20.py
quality_controls_ex21.py
quality_controls_ex22.py
- viewing_meshes_ex01.py
-)
+ viewing_meshes_ex01.py
+ )
SET(GOOD_TESTS
- cartesian_algo.py
- creating_meshes_ex02.py
- creating_meshes_ex04.py
- creating_meshes_ex06.py
+ cartesian_algo.py
+ creating_meshes_ex02.py
+ creating_meshes_ex04.py
+ creating_meshes_ex06.py
creating_meshes_ex07.py
creating_meshes_ex08.py
defining_hypotheses_ex01.py
diff --git a/doc/salome/examples/a3DmeshOnModified2Dmesh.py b/doc/salome/examples/a3DmeshOnModified2Dmesh.py
new file mode 100644
index 000000000..7fcdcaca8
--- /dev/null
+++ b/doc/salome/examples/a3DmeshOnModified2Dmesh.py
@@ -0,0 +1,62 @@
+import salome
+salome.salome_init()
+
+from salome.geom import geomBuilder
+geompy = geomBuilder.New(salome.myStudy)
+
+# This script demonstrates generation of 3D mesh basing on a modified 2D mesh
+#
+# Purpose is to get a tetrahedral mesh in a sphere cut by a cube.
+# The requirement is to have a surface mesh on the cube comprised of
+# triangles of exactly the same size arranged in a grid pattern.
+#
+# To fulfill this requirement we mesh the box using Quadrangle (Mapping)
+# meshing algorithm, split quadrangles into triangles and then generate
+# tetrahedrons.
+
+
+# Make the geometry
+
+Box_1 = geompy.MakeBox(-100,-100,-100, 100, 100, 100)
+Sphere_1 = geompy.MakeSphereR( 300 )
+Cut_1 = geompy.MakeCut(Sphere_1, Box_1, theName="Cut_1")
+# get a spherical face
+Sph_Face = geompy.ExtractShapes( Sphere_1, geompy.ShapeType["FACE"] )[0]
+
+# get the shape Sph_Face turned into during MakeCut()
+Sph_Face = geompy.GetInPlace(Cut_1, Sph_Face, isNewImplementation=True, theName="Sphere_1")
+
+
+# 1) Define a mesh with 1D and 2D meshers
+
+import SMESH
+from salome.smesh import smeshBuilder
+smesh = smeshBuilder.New(salome.myStudy)
+
+Mesh_1 = smesh.Mesh(Cut_1)
+
+# "global" meshers (assigned to Cut_1) that will be used for the box
+Regular_1D = Mesh_1.Segment()
+Local_Length_1 = Regular_1D.LocalLength(20)
+Quadrangle_2D = Mesh_1.Quadrangle()
+
+# a "local" mesher (assigned to a sub-mesh on Sphere_1) to mesh the sphere
+algo_2D = Mesh_1.Triangle( smeshBuilder.NETGEN_1D2D, Sph_Face )
+algo_2D.SetMaxSize( 70. )
+algo_2D.SetFineness( smeshBuilder.Moderate )
+algo_2D.SetMinSize( 7. )
+
+# 2) Compute 2D mesh
+isDone = Mesh_1.Compute()
+
+# 3) Split quadrangles into triangles
+isDone = Mesh_1.SplitQuadObject( Mesh_1, Diag13=True )
+
+# 4) Define a 3D mesher
+Mesh_1.Tetrahedron()
+
+# 5) Compute 3D mesh
+Mesh_1.Compute()
+
+if salome.sg.hasDesktop():
+ salome.sg.updateObjBrowser(1)
diff --git a/doc/salome/examples/creating_meshes_ex08.py b/doc/salome/examples/creating_meshes_ex08.py
index 18f9dad01..e8f43eee6 100644
--- a/doc/salome/examples/creating_meshes_ex08.py
+++ b/doc/salome/examples/creating_meshes_ex08.py
@@ -32,8 +32,8 @@ newMesh = smesh.CopyMesh( mesh, "whole mesh copy")
# 2. copy a group of 2D elements along with groups
newMesh = smesh.CopyMesh( fGroup, "face group copy with groups",toCopyGroups=True)
-# 3. copy a group of nodes with preseving their ids
-newMesh = smesh.CopyMesh( nGroup, "node group copy", toKeepIDs=True)
+# 3. copy a group of nodes
+newMesh = smesh.CopyMesh( nGroup, "node group copy")
# 4. copy some faces
faceIds = fGroup.GetIDs()[-10:]
diff --git a/doc/salome/examples/prism_3d_algo.py b/doc/salome/examples/prism_3d_algo.py
index df18d0fcb..7be0a29d3 100644
--- a/doc/salome/examples/prism_3d_algo.py
+++ b/doc/salome/examples/prism_3d_algo.py
@@ -1,9 +1,14 @@
# Use 3D extrusion meshing algorithm
-import salome, smesh, SMESH, geompy
-
+import salome
salome.salome_init()
-smesh.SetCurrentStudy( salome.myStudy )
+
+from salome.geom import geomBuilder
+geompy = geomBuilder.New(salome.myStudy)
+
+import SMESH
+from salome.smesh import smeshBuilder
+smesh = smeshBuilder.New(salome.myStudy)
OX = geompy.MakeVectorDXDYDZ(1,0,0)
OY = geompy.MakeVectorDXDYDZ(0,1,0)
diff --git a/doc/salome/gui/SMESH/images/copy_mesh_dlg.png b/doc/salome/gui/SMESH/images/copy_mesh_dlg.png
index db9c929b5..c959e680f 100644
Binary files a/doc/salome/gui/SMESH/images/copy_mesh_dlg.png and b/doc/salome/gui/SMESH/images/copy_mesh_dlg.png differ
diff --git a/doc/salome/gui/SMESH/images/display_entity_choose_item.png b/doc/salome/gui/SMESH/images/display_entity_choose_item.png
new file mode 100644
index 000000000..d09961822
Binary files /dev/null and b/doc/salome/gui/SMESH/images/display_entity_choose_item.png differ
diff --git a/doc/salome/gui/SMESH/images/display_entity_dlg.png b/doc/salome/gui/SMESH/images/display_entity_dlg.png
new file mode 100644
index 000000000..d0f4fa0ca
Binary files /dev/null and b/doc/salome/gui/SMESH/images/display_entity_dlg.png differ
diff --git a/doc/salome/gui/SMESH/images/extrusionalongaline1.png b/doc/salome/gui/SMESH/images/extrusionalongaline1.png
old mode 100755
new mode 100644
index 95a26ca90..0cc13d518
Binary files a/doc/salome/gui/SMESH/images/extrusionalongaline1.png and b/doc/salome/gui/SMESH/images/extrusionalongaline1.png differ
diff --git a/doc/salome/gui/SMESH/images/extrusionalongaline2.png b/doc/salome/gui/SMESH/images/extrusionalongaline2.png
old mode 100755
new mode 100644
index 8c1662396..987a66c61
Binary files a/doc/salome/gui/SMESH/images/extrusionalongaline2.png and b/doc/salome/gui/SMESH/images/extrusionalongaline2.png differ
diff --git a/doc/salome/gui/SMESH/input/1d_meshing_hypo.doc b/doc/salome/gui/SMESH/input/1d_meshing_hypo.doc
index 7a9228b68..8c38c8ddf 100644
--- a/doc/salome/gui/SMESH/input/1d_meshing_hypo.doc
+++ b/doc/salome/gui/SMESH/input/1d_meshing_hypo.doc
@@ -257,15 +257,14 @@ hypothesis operation.
\anchor automatic_length_anchor
Automatic Length
-This hypothesis is automatically applied when you select Assign a
-set of hypotheses option in Create Mesh menu.
-
-\image html automaticlength.png
-
The dialog box prompts you to define the quality of the future mesh by
only one parameter, which is \b Fineness, ranging from 0 (coarse mesh,
low number of elements) to 1 (extremely fine mesh, great number of
-elements). Compare one and the same object (sphere) meshed with
+elements).
+
+\image html automaticlength.png
+
+Compare one and the same object (sphere) meshed with
minimum and maximum value of this parameter.
\image html image147.gif "Example of a very rough mesh. Automatic Length works for 0."
diff --git a/doc/salome/gui/SMESH/input/2d_meshing_hypo.doc b/doc/salome/gui/SMESH/input/2d_meshing_hypo.doc
index 0ccb902e0..05b8d5a39 100644
--- a/doc/salome/gui/SMESH/input/2d_meshing_hypo.doc
+++ b/doc/salome/gui/SMESH/input/2d_meshing_hypo.doc
@@ -113,10 +113,9 @@ of the enforced nodes.
projected to the meshed face and located close enough to the
meshed face will be used to create the enforced nodes.
+\note Enforced nodes can't be created at \b Reduced transition type.
Let us see how the algorithm works:
-
-
Initially positions of nodes are computed without taking into
account the enforced vertex (yellow point).
diff --git a/doc/salome/gui/SMESH/input/about_meshes.doc b/doc/salome/gui/SMESH/input/about_meshes.doc
index 870e5c182..65201ac64 100644
--- a/doc/salome/gui/SMESH/input/about_meshes.doc
+++ b/doc/salome/gui/SMESH/input/about_meshes.doc
@@ -7,10 +7,12 @@ a set of entities with a simple topology.
It is possible to \subpage constructing_meshes_page "construct meshes"
on the basis of geometrical shapes produced in the GEOM module.
-It is also possible to
-\subpage constructing_submeshes_page "construct mesh on a part of the geometrical object",
-for example, a face, with different meshing parameters or using
-another meshing algorithm.
+Construction of \subpage constructing_submeshes_page "sub-meshes"
+allows to mesh parts of the geometrical object, for example a face,
+with different meshing parameters or using another meshing algorithm
+than other parts.
+
+3D mesh can be generated basing on a 2D closed mesh.
Several created meshes can be \subpage building_compounds_page "combined into another mesh".
@@ -62,44 +64,4 @@ described in the following way:
coordinates of the corresponding vertex.
-Connections
-
-Each mesh entity bounds 0 or more mesh entities of higher
-dimension. In the same way each mesh entity is bounded by 0 or more
-mesh entities of lower dimension:
-
-
-A node bounds edges, faces and volumes
-An edge bounds faces, and volumes
-A face bounds volumes
-A volume is bounded by faces, edges and nodes
-A face is bounded by edges, and nodes
-An edge is bounded by nodes
-
-
-You can notice that there are two types of connections: \b inverse and
-\b direct connections.
-
-Inverse connections
-
-This relationship has a particularity that the order of bounded
-entities has not a direct meaning. Also the number of bounded entities
-is not fixed.
-
-\b Example: The edges surrounding a node. The 3rd edge has no more
-sense that the 5th one.
-
-Direct connections
-
-This relationship has a particularity that the order of bounding
-entities is meaningful. The number of bounding entities is fixed and
-depends on the type of the entity (hexahedron, tetrahedron,?).
-
-\b Example: An edge is composed of two nodes. A face is composed of 3
-or 4 edges depending if we are dealing with triangles or quadrangles.
-
-The connections are not only restricted to entities of one dimension
-higher or lower. For example some algorithms may be interested to
-retrieve all the faces surrounding a node.
-
*/
diff --git a/doc/salome/gui/SMESH/input/basic_meshing_algos.doc b/doc/salome/gui/SMESH/input/basic_meshing_algos.doc
index ee632b282..977b505db 100644
--- a/doc/salome/gui/SMESH/input/basic_meshing_algos.doc
+++ b/doc/salome/gui/SMESH/input/basic_meshing_algos.doc
@@ -52,15 +52,15 @@ geometrical objects.
There is also a number of more specific algorithms:
+\subpage prism_3d_algo_page "for meshing prismatic shapes"
\subpage projection_algos_page "for meshing by projection of another mesh"
\subpage import_algos_page "for meshing by importing elements from another mesh"
\subpage radial_prism_algo_page "for meshing geometrical objects with cavities"
-\subpage segments_around_vertex_algo_page "for defining the local size of elements around a certain node"
-\subpage prism_3d_algo_page "for meshing prismatic shapes"
\subpage radial_quadrangle_1D2D_algo_page "for meshing special 2d faces (circles and part of circles)"
\subpage use_existing_page "Use Edges to be Created Manually" and
\ref use_existing_page "Use Faces to be Created Manually" algorithms can be
used to create a 1D or a 2D mesh in a python script.
+\subpage segments_around_vertex_algo_page "for defining the local size of elements around a certain node"
\ref constructing_meshes_page "Constructing meshes" page describes in
diff --git a/doc/salome/gui/SMESH/input/constructing_meshes.doc b/doc/salome/gui/SMESH/input/constructing_meshes.doc
index 232d4f524..5d26cae6c 100644
--- a/doc/salome/gui/SMESH/input/constructing_meshes.doc
+++ b/doc/salome/gui/SMESH/input/constructing_meshes.doc
@@ -9,6 +9,7 @@
\ref preview_anchor "Previewing the mesh" (optional)
\ref submesh_order_anchor "Changing sub-mesh priority" (optional)
\ref compute_anchor "Computing the mesh"
+ \ref edit_anchor "Editing the mesh" (optional)
\anchor create_mesh_anchor
@@ -357,8 +358,29 @@ computation reporting. There are the following possibilities: always
show the information box, show only if an error occurs or never.
By default, the information box is always shown after mesh computation operation.
-
+
+\anchor edit_anchor
+
Editing the mesh
+It is possible to \ref modifying_meshes_page "edit the mesh" of
+lower dimension before generation of mesh of higher dimension.
+For example you can generate 2D mesh, modify it using e.g.
+\ref pattern_mapping_page, and then generate 3D mesh basing on the
+modified 2D mesh. The workflow is following:
+- Define 1D and 2D meshing algorithms.
+- Compute the mesh. 2D mesh is generated.
+- Apply \ref pattern_mapping_page.
+- Define 3D meshing algorithms without modifying 1D and 2D algorithms
+and hypotheses.
+- Compute the mesh. 3D mesh is generated.
+
+\note Nodes and elements added \ref adding_nodes_and_elements_page
+"manually" can't be used in this workflow because the manually created
+entities are not attached to any geometry and thus (usually) can't be
+found by a mesher paving some geometry.
+
+See Also a sample TUI Script demonstrates the possibility of
+\ref tui_editing_while_meshing "Intermediate edition while meshing"
*/
diff --git a/doc/salome/gui/SMESH/input/constructing_submeshes.doc b/doc/salome/gui/SMESH/input/constructing_submeshes.doc
index 230903449..782b5662e 100644
--- a/doc/salome/gui/SMESH/input/constructing_submeshes.doc
+++ b/doc/salome/gui/SMESH/input/constructing_submeshes.doc
@@ -2,9 +2,21 @@
\page constructing_submeshes_page Constructing sub-meshes
-Sub-mesh is a mesh on a geometrical sub-object created with meshing algorithms
-and/or hypotheses other than the algorithms and hypotheses assigned to
-the parent mesh on the parent geometrical object.
+Sub-mesh is a mesh on a geometrical sub-object (sub-shape) used to assign
+different meshing algorithms and/or hypotheses than the algorithms and
+hypotheses assigned to the parent mesh on the parent geometrical
+object, that allows getting a local mesh refinement.
+
+A sub-shape to create a sub-mesh on should be retrieved from the shape
+of the parent mesh one of the following ways:
+ In Geometry module, via New Entity > Explode menu.
+ In Geometry module, by creation of a group (New Entity >
+ Group > Create Group menu).
+ In Mesh module, by
+ \ref subshape_by_mesh_elem "selecting a mesh element" generated on a
+ sub-shape of interest. This way is accessible if the mesh is
+ already computed.
+
If a geometrical sub-object belongs to several geometrical objects
having different meshes or sub-meshes, it will be meshed with the
@@ -56,6 +68,7 @@ sub-mesh. You can select meshing algorithms and hypotheses in the same way as
in \ref constructing_meshes_page "Create mesh" menu.
\par
+\anchor subshape_by_mesh_elem
If the parent mesh is already computed, then you can define the
\b Geometry by picking mesh elements computed on a sub-shape of interest
in the 3D Viewer, i.e. you do not have to extract this sub-shape
@@ -77,12 +90,13 @@ Browser.
\image html find_geom_by_mesh_elem.png
\par
-In this dialog, Element Type defines kind of element to pick in the
-Viewer.
+In this dialog, Element Type defines a kind of element to pick in the
+Viewer.
Instead of picking an element in the Viewer, you can type its
ID in Element ID field.
- Geometry name field allows defining a name of the sub-shape.
-
+ Geometry name field allows defining a name of the sub-shape
+with which the sub-shape will appear in the Object Browser (if not yet
+there).
\par
In the Object Browser the structure of the new sub-mesh will be
diff --git a/doc/salome/gui/SMESH/input/copy_mesh.doc b/doc/salome/gui/SMESH/input/copy_mesh.doc
index 2c65ab8d0..15bf2d129 100644
--- a/doc/salome/gui/SMESH/input/copy_mesh.doc
+++ b/doc/salome/gui/SMESH/input/copy_mesh.doc
@@ -42,9 +42,6 @@ selection_filter_library_page "Selection filter library" page.
activate Generate groups checkbox to copy the groups of
elements of the source mesh to the newly created mesh.
-activate Preserve IDs of elements checkbox to keep
-the IDs of new nodes and elements the same as the IDs of source nodes
-and elements.
diff --git a/doc/salome/gui/SMESH/input/display_entity.doc b/doc/salome/gui/SMESH/input/display_entity.doc
index 570674017..ccd0043ef 100644
--- a/doc/salome/gui/SMESH/input/display_entity.doc
+++ b/doc/salome/gui/SMESH/input/display_entity.doc
@@ -9,4 +9,13 @@ edges or combine them.
\image html image58.gif Only Edges
+If the mesh contains a lot of elements, select Choose... item,
+
+\image html display_entity_choose_item.png Item to call 'Display Entity' dialog box
+
+and Display Entity dialog box will provide a way to display only some entities at first display instead of displaying all entities long time.
+
+\image html display_entity_dlg.png 'Display Entity' dialog allows to select entities before displaying
+
+\note This menu item is available from popup menu in both Object browser and 3D viewer.
*/
\ No newline at end of file
diff --git a/doc/salome/gui/SMESH/input/extrusion.doc b/doc/salome/gui/SMESH/input/extrusion.doc
index 4813eee5c..a28af48d4 100644
--- a/doc/salome/gui/SMESH/input/extrusion.doc
+++ b/doc/salome/gui/SMESH/input/extrusion.doc
@@ -6,12 +6,12 @@
dimension than the input ones. Any node, segment or 2D element can be
extruded. Each type of elements has a corresponding type of extruded elements:
-Extruded element Result elements
-Node Segments
-Segment Quadrilaterals
-Triangle Pentahedrons
-Quadrilateral Hexahedrons
-Polygon Polyhedrons
+Extruded element Result element
+Node Segment
+Segment Quadrilateral
+Triangle Pentahedron
+Quadrilateral Hexahedron
+Polygon Polyhedron
Hexagonal polygon Hexagonal prism
@@ -35,7 +35,8 @@ The following dialog common for line and planar elements will appear:
In this dialog:
- Select the type of elements which will be extruded (0D, 1D or 2D).
+ Select the type of elements which will be extruded (nodes, 1D or
+ 2D elements).
Specify the IDs of the elements which will be extruded by one
following means:
@@ -62,9 +63,15 @@ The following dialog common for line and planar elements will appear:
specify the distance of extrusion along the vector.
Specify the number of steps.
- If you activate Generate Groups check-box, the created
- elements contained in groups will be included into new groups named
- by pattern "_extruded" and "_top".
+ If you activate Generate Groups check-box, the result elements
+ created from extruded elements contained in groups will be
+ included into new groups named by pattern "_extruded" and "_top". For example if an
+ extruded quadrangle is included in \a Group_1 group then result
+ hexahedra will be included in \a Group_1_extruded group and a
+ quadrangle created at the "top" of extruded mesh will
+ be included in \a Group_1_top group. This check-box is active
+ only if there are some groups in the mesh.
Click \b Apply or Apply and Close button to confirm the operation.
diff --git a/doc/salome/gui/SMESH/input/modifying_meshes.doc b/doc/salome/gui/SMESH/input/modifying_meshes.doc
index 9006ddcd0..f09ab21d4 100755
--- a/doc/salome/gui/SMESH/input/modifying_meshes.doc
+++ b/doc/salome/gui/SMESH/input/modifying_meshes.doc
@@ -12,8 +12,6 @@ nodes to polyhedrons at an arbitrary place in the mesh.
elements (used in quadratic meshes) from quadratic nodes to quadratic polyhedrons at an arbitrary place in the mesh.
\subpage removing_nodes_and_elements_page "Remove" any existing
mesh elements.
-\subpage renumbering_nodes_and_elements_page "Renumber" nodes and
-elements of the mesh.
\subpage translation_page "Translate" in the indicated direction the mesh or some of
its elements.
\subpage rotation_page "Rotate" by the indicated axis and angle
@@ -53,6 +51,11 @@ or vice versa.
\subpage cut_mesh_by_plane_page "Cut a tetrahedron mesh by a plane".
+It is possible to \ref edit_anchor "modify the mesh" of lower
+dimension before generation of mesh of higher dimension.
+
+
+
\note It is possible to use the variables defined in the SALOME \b NoteBook
to specify the numerical parameters used for modification of any object.
diff --git a/doc/salome/gui/SMESH/input/pattern_mapping.doc b/doc/salome/gui/SMESH/input/pattern_mapping.doc
index ef7f8ba66..969b9fc5e 100644
--- a/doc/salome/gui/SMESH/input/pattern_mapping.doc
+++ b/doc/salome/gui/SMESH/input/pattern_mapping.doc
@@ -14,7 +14,7 @@ The smp file contains 4 sections:
-# The first line indicates the total number of pattern nodes (N).
-# The next N lines describe nodes coordinates. Each line contains 2
-node coordinates for a 2D pattern or 3 node cordinates for a 3D pattern.
+node coordinates for a 2D pattern or 3 node coordinates for a 3D pattern.
Note, that node coordinates of a 3D pattern can be defined only by relative values in range [0;1].
-# The key-points line contains the indices of the nodes to be mapped on geometrical
vertices (for a 2D pattern only). Index n refers to the node described
@@ -89,7 +89,7 @@ An example of a simple 3D pattern smp file:
Application of pattern mapping
-To apply pattern mapping to a geometrical object:
+To apply pattern mapping to a geometrical object or mesh elements:
From the \b Modification menu choose the Pattern Mapping item or click
"Pattern mapping" button in the toolbar.
@@ -113,16 +113,17 @@ created manually or generated automatically from an existing mesh or submesh.
\b Vertex to which the first key-point should be mapped;
+
Alternatively, it is possible to select Refine selected mesh elements
-checkbox and apply the pattern to
+check-box and apply the pattern to
Mesh Face instead of a geometric Face
and select \b Node instead of vertex.
-
-Additionally it is possible to:
- Reverse the order of key-points By default, the vertices of
- a face are ordered counterclockwise.
+
+Additionally it is possible to:
+ Reverse the order of key-points . By default, the vertices of
+ a face are ordered counterclockwise.
Enable to Create polygons near boundary
- and Create polyhedrons near boundary
+ and Create polyhedrons near boundary
\n For a 3D pattern
@@ -133,21 +134,27 @@ In this dialog you should specify:
\b Pattern, which can be loaded from .smp pattern file previously
created manually or generated automatically from an existing mesh or submesh.
- A 3D block (Solid) object;
- Two vertices that specify the order of nodes in the resulting mesh.
+ A 3D block (Solid) object.
+ Two vertices that specify the order of nodes in the resulting
+ mesh.
+
Alternatively, it is possible to select Refine selected mesh elements
checkbox and apply the pattern to
+
One or several Mesh volumes instead of a geometric 3D
object
and select two /b Nodes instead of vertices.
+
Additionally it is possible to:
+
Enable to Create polygons near boundary
- and Create polyhedrons near boundary
+ and Create polyhedrons near boundary
-\n Automatic Generation
+
+ Automatic Generation
-To generate a pattern automatically from an existing mesh or submesh,
+To generate a pattern automatically from an existing mesh or sub-mesh,
click \b New button.
The following dialog box will appear:
diff --git a/doc/salome/gui/SMESH/input/selection_filter_library.doc b/doc/salome/gui/SMESH/input/selection_filter_library.doc
index c06fb6ec5..02d39a541 100644
--- a/doc/salome/gui/SMESH/input/selection_filter_library.doc
+++ b/doc/salome/gui/SMESH/input/selection_filter_library.doc
@@ -237,7 +237,7 @@ See also \ref filter_double_elements "Double Elements quality control".
Bad oriented volume selects mesh volumes, which are incorrectly oriented from
the point of view of MED convention.
-Over-constrained volumes selects mesh volumes having only one border shared
+Over-constrained volumes selects mesh volumes having only one facet shared
with other volumes.
See also \ref over_constrained_volumes_page "Over-constrained volumes quality control".
diff --git a/doc/salome/gui/SMESH/input/tui_creating_meshes.doc b/doc/salome/gui/SMESH/input/tui_creating_meshes.doc
index f1b12e4c4..984616457 100644
--- a/doc/salome/gui/SMESH/input/tui_creating_meshes.doc
+++ b/doc/salome/gui/SMESH/input/tui_creating_meshes.doc
@@ -18,6 +18,11 @@
Change priority of submeshes in Mesh
\tui_script{creating_meshes_ex03.py}
+
+\anchor tui_editing_while_meshing
+Intermediate edition while meshing
+\tui_script{a3DmeshOnModified2Dmesh.py}
+
\anchor tui_editing_mesh
Editing a mesh
diff --git a/doc/salome/gui/SMESH/input/viewing_meshes_overview.doc b/doc/salome/gui/SMESH/input/viewing_meshes_overview.doc
index 376da99b0..248685579 100644
--- a/doc/salome/gui/SMESH/input/viewing_meshes_overview.doc
+++ b/doc/salome/gui/SMESH/input/viewing_meshes_overview.doc
@@ -33,7 +33,7 @@ viewer.
\subpage display_mode_page "Display Mode" - allows to select between
Wireframe, Shading and Nodes presentation.
\subpage display_entity_page "Display Entity" - allows to display
-Faces, Edges or both.
+entities by types (Faces, Edges, Volumes etc.).
2D Quadratic - allows to select between the representation
of quadratic edges as broken lines or as arcs
Orientation of faces - shows vectors of orientation of
diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt
index 4ffa049b7..46ca05a36 100755
--- a/resources/CMakeLists.txt
+++ b/resources/CMakeLists.txt
@@ -34,6 +34,8 @@ SET(SMESH_RESOURCES_FILES
mesh_aspect_3d.png
mesh_biquad_quadrangle.png
mesh_biquad_triangle.png
+ mesh_choose.png
+ mesh_choose_all.png
mesh_clear.png
mesh_compute.png
mesh_diagonal.png
diff --git a/resources/SalomeApp.xml.in b/resources/SalomeApp.xml.in
index 618692c76..c49059d3a 100644
--- a/resources/SalomeApp.xml.in
+++ b/resources/SalomeApp.xml.in
@@ -130,9 +130,9 @@
diff --git a/resources/mesh_choose.png b/resources/mesh_choose.png
new file mode 100644
index 000000000..b5a40bacb
Binary files /dev/null and b/resources/mesh_choose.png differ
diff --git a/resources/mesh_choose_all.png b/resources/mesh_choose_all.png
new file mode 100644
index 000000000..5387c8416
Binary files /dev/null and b/resources/mesh_choose_all.png differ
diff --git a/src/Controls/SMESH_Controls.cxx b/src/Controls/SMESH_Controls.cxx
index 213dc236d..6311da713 100644
--- a/src/Controls/SMESH_Controls.cxx
+++ b/src/Controls/SMESH_Controls.cxx
@@ -1954,6 +1954,7 @@ bool MultiConnection2D::Value::operator<(const MultiConnection2D::Value& x) cons
}
void MultiConnection2D::GetValues(MValues& theValues){
+ if ( !myMesh ) return;
SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
for(; anIter->more(); ){
const SMDS_MeshFace* anElem = anIter->next();
@@ -3134,11 +3135,14 @@ bool RangeOfIds::SetRangeStr( const TCollection_AsciiString& theStr )
myIds.Clear();
TCollection_AsciiString aStr = theStr;
- aStr.RemoveAll( ' ' );
- aStr.RemoveAll( '\t' );
+ //aStr.RemoveAll( ' ' );
+ //aStr.RemoveAll( '\t' );
+ for ( int i = 1; i <= aStr.Length(); ++i )
+ if ( isspace( aStr.Value( i )))
+ aStr.SetValue( i, ',');
for ( int aPos = aStr.Search( ",," ); aPos != -1; aPos = aStr.Search( ",," ) )
- aStr.Remove( aPos, 2 );
+ aStr.Remove( aPos, 1 );
TCollection_AsciiString tmpStr = aStr.Token( ",", 1 );
int i = 1;
@@ -4247,11 +4251,11 @@ void BelongToGeom::init()
myIsSubshape = IsSubShape(aMap, myShape);
}
- if (!myIsSubshape)
+ //if (!myIsSubshape) // to be always ready to check an element not bound to geometry
{
myElementsOnShapePtr.reset(new ElementsOnShape());
myElementsOnShapePtr->SetTolerance(myTolerance);
- myElementsOnShapePtr->SetAllNodes(true); // belong, while false means "lays on"
+ myElementsOnShapePtr->SetAllNodes(true); // "belong", while false means "lays on"
myElementsOnShapePtr->SetMesh(myMeshDS);
myElementsOnShapePtr->SetShape(myShape, myType);
}
@@ -4292,36 +4296,43 @@ bool BelongToGeom::IsSatisfy (long theId)
{
if( const SMDS_MeshNode* aNode = myMeshDS->FindNode( theId ) )
{
+ if ( aNode->getshapeId() < 1 )
+ return myElementsOnShapePtr->IsSatisfy(theId);
+
const SMDS_PositionPtr& aPosition = aNode->GetPosition();
SMDS_TypeOfPosition aTypeOfPosition = aPosition->GetTypeOfPosition();
switch( aTypeOfPosition )
{
- case SMDS_TOP_VERTEX : return IsContains( myMeshDS,myShape,aNode,TopAbs_VERTEX );
- case SMDS_TOP_EDGE : return IsContains( myMeshDS,myShape,aNode,TopAbs_EDGE );
- case SMDS_TOP_FACE : return IsContains( myMeshDS,myShape,aNode,TopAbs_FACE );
- case SMDS_TOP_3DSPACE: return IsContains( myMeshDS,myShape,aNode,TopAbs_SHELL );
+ case SMDS_TOP_VERTEX : return ( IsContains( myMeshDS,myShape,aNode,TopAbs_VERTEX ));
+ case SMDS_TOP_EDGE : return ( IsContains( myMeshDS,myShape,aNode,TopAbs_EDGE ));
+ case SMDS_TOP_FACE : return ( IsContains( myMeshDS,myShape,aNode,TopAbs_FACE ));
+ case SMDS_TOP_3DSPACE: return ( IsContains( myMeshDS,myShape,aNode,TopAbs_SOLID ) ||
+ IsContains( myMeshDS,myShape,aNode,TopAbs_SHELL ));
}
}
}
else
{
- if( const SMDS_MeshElement* anElem = myMeshDS->FindElement( theId ) )
+ if ( const SMDS_MeshElement* anElem = myMeshDS->FindElement( theId ))
{
+ if ( anElem->getshapeId() < 1 )
+ return myElementsOnShapePtr->IsSatisfy(theId);
+
if( myType == SMDSAbs_All )
{
- return IsContains( myMeshDS,myShape,anElem,TopAbs_EDGE ) ||
- IsContains( myMeshDS,myShape,anElem,TopAbs_FACE ) ||
- IsContains( myMeshDS,myShape,anElem,TopAbs_SHELL )||
- IsContains( myMeshDS,myShape,anElem,TopAbs_SOLID );
+ return ( IsContains( myMeshDS,myShape,anElem,TopAbs_EDGE ) ||
+ IsContains( myMeshDS,myShape,anElem,TopAbs_FACE ) ||
+ IsContains( myMeshDS,myShape,anElem,TopAbs_SOLID )||
+ IsContains( myMeshDS,myShape,anElem,TopAbs_SHELL ));
}
else if( myType == anElem->GetType() )
{
switch( myType )
{
- case SMDSAbs_Edge : return IsContains( myMeshDS,myShape,anElem,TopAbs_EDGE );
- case SMDSAbs_Face : return IsContains( myMeshDS,myShape,anElem,TopAbs_FACE );
- case SMDSAbs_Volume: return IsContains( myMeshDS,myShape,anElem,TopAbs_SHELL )||
- IsContains( myMeshDS,myShape,anElem,TopAbs_SOLID );
+ case SMDSAbs_Edge : return ( IsContains( myMeshDS,myShape,anElem,TopAbs_EDGE ));
+ case SMDSAbs_Face : return ( IsContains( myMeshDS,myShape,anElem,TopAbs_FACE ));
+ case SMDSAbs_Volume: return ( IsContains( myMeshDS,myShape,anElem,TopAbs_SOLID )||
+ IsContains( myMeshDS,myShape,anElem,TopAbs_SHELL ));
}
}
}
diff --git a/src/PluginUtils/GeomSelectionTools.cxx b/src/PluginUtils/GeomSelectionTools.cxx
index d57f2a210..c248771a4 100644
--- a/src/PluginUtils/GeomSelectionTools.cxx
+++ b/src/PluginUtils/GeomSelectionTools.cxx
@@ -28,7 +28,7 @@
#include
#include
-#include
+#include
#include
#include
#include
@@ -96,7 +96,7 @@ LightApp_SelectionMgr* GeomSelectionTools::selectionMgr()
*/
SALOME_ListIO* GeomSelectionTools::getSelectedSalomeObjects()
{
- SALOME_ListIO* selected;
+ SALOME_ListIO* selected = new SALOME_ListIO;
LightApp_SelectionMgr* aSel = selectionMgr();
aSel->selectedObjects( *selected, NULL, false );
return selected;
diff --git a/src/SMESH/CMakeLists.txt b/src/SMESH/CMakeLists.txt
index 17e8d7b9c..a23c8c468 100644
--- a/src/SMESH/CMakeLists.txt
+++ b/src/SMESH/CMakeLists.txt
@@ -58,6 +58,7 @@ SET(_link_LIBRARIES
${CAS_TKG2d}
${CAS_TKCDF}
${GEOM_NMTTools}
+ ${GEOM_GEOMUtils}
${Boost_LIBRARIES}
SMESHDS
SMESHControls
diff --git a/src/SMESH/SMESH_Algo.cxx b/src/SMESH/SMESH_Algo.cxx
index 732c3e64a..5ec1240b0 100644
--- a/src/SMESH/SMESH_Algo.cxx
+++ b/src/SMESH/SMESH_Algo.cxx
@@ -522,9 +522,7 @@ GeomAbs_Shape SMESH_Algo::Continuity(TopoDS_Edge E1,
Standard_Real tol = BRep_Tool::Tolerance( V );
Standard_Real angTol = 2e-3;
try {
-#if OCC_VERSION_LARGE > 0x06010000
OCC_CATCH_SIGNALS;
-#endif
return BRepLProp::Continuity(C1, C2, u1, u2, tol, angTol);
}
catch (Standard_Failure) {
diff --git a/src/SMESH/SMESH_HypoFilter.cxx b/src/SMESH/SMESH_HypoFilter.cxx
index e5d167064..d0125d1e5 100644
--- a/src/SMESH/SMESH_HypoFilter.cxx
+++ b/src/SMESH/SMESH_HypoFilter.cxx
@@ -157,8 +157,9 @@ void SMESH_HypoFilter::IsMoreLocalThanPredicate::findPreferable()
bool SMESH_HypoFilter::IsMoreLocalThanPredicate::IsOk(const SMESH_Hypothesis* aHyp,
const TopoDS_Shape& aShape) const
{
- if ( aShape.IsSame( _mesh.GetShapeToMesh() ))
- return false; // aHyp is global
+ if ( aShape.IsSame( _mesh.GetShapeToMesh() ) || // aHyp is global
+ aShape.IsSame( _shape ))
+ return false;
if ( SMESH_MesherHelper::IsSubShape( aShape, /*mainShape=*/_shape ))
return true;
diff --git a/src/SMESH/SMESH_Mesh.cxx b/src/SMESH/SMESH_Mesh.cxx
index 7692f9f0e..72d7ef193 100644
--- a/src/SMESH/SMESH_Mesh.cxx
+++ b/src/SMESH/SMESH_Mesh.cxx
@@ -55,8 +55,10 @@
#include "DriverCGNS_Write.hxx"
#endif
+#include
+
#undef _Precision_HeaderFile
-#include
+//#include
#include
#include
#include
@@ -226,7 +228,7 @@ SMESH_Mesh::~SMESH_Mesh()
bool SMESH_Mesh::MeshExists( int meshId ) const
{
- return _myDocument ? _myDocument->GetMesh( meshId ) : false;
+ return _myDocument ? bool( _myDocument->GetMesh( meshId )) : false;
}
//=============================================================================
@@ -327,8 +329,9 @@ double SMESH_Mesh::GetShapeDiagonalSize(const TopoDS_Shape & aShape)
{
if ( !aShape.IsNull() ) {
Bnd_Box Box;
- BRepBndLib::Add(aShape, Box);
- return sqrt( Box.SquareExtent() );
+ GEOMUtils::PreciseBoundingBox(aShape, Box);
+ if ( !Box.IsVoid() )
+ return sqrt( Box.SquareExtent() );
}
return 0;
}
diff --git a/src/SMESH/SMESH_Mesh.hxx b/src/SMESH/SMESH_Mesh.hxx
index 0cf3e0949..c603c6a41 100644
--- a/src/SMESH/SMESH_Mesh.hxx
+++ b/src/SMESH/SMESH_Mesh.hxx
@@ -63,15 +63,15 @@ typedef std::list TListOfListOfInt;
class SMESH_EXPORT SMESH_Mesh
{
-public:
- SMESH_Mesh(int theLocalId,
- int theStudyId,
+ public:
+ SMESH_Mesh(int theLocalId,
+ int theStudyId,
SMESH_Gen* theGen,
bool theIsEmbeddedMode,
SMESHDS_Document* theDocument);
-
+
virtual ~SMESH_Mesh();
-
+
/*!
* \brief Set geometry to be meshed
*/
diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx
index e216b2e74..08cc1d9c2 100644
--- a/src/SMESH/SMESH_MeshEditor.cxx
+++ b/src/SMESH/SMESH_MeshEditor.cxx
@@ -3701,13 +3701,8 @@ static bool getClosestUV (Extrema_GenExtPS& projector,
if ( projector.IsDone() ) {
double u, v, minVal = DBL_MAX;
for ( int i = projector.NbExt(); i > 0; i-- )
-#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
if ( projector.SquareDistance( i ) < minVal ) {
minVal = projector.SquareDistance( i );
-#else
- if ( projector.Value( i ) < minVal ) {
- minVal = projector.Value( i );
-#endif
projector.Point( i ).Parameter( u, v );
}
result.SetCoord( u, v );
@@ -10397,15 +10392,12 @@ namespace {
}
void Perform(const gp_Pnt& aPnt, double theTol)
{
+ theTol *= theTol;
_state = TopAbs_OUT;
_extremum.Perform(aPnt);
if ( _extremum.IsDone() )
for ( int iSol = 1; iSol <= _extremum.NbExt() && _state == TopAbs_OUT; ++iSol)
-#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
_state = ( _extremum.SquareDistance(iSol) <= theTol ? TopAbs_IN : TopAbs_OUT );
-#else
- _state = ( _extremum.Value(iSol) <= theTol ? TopAbs_IN : TopAbs_OUT );
-#endif
}
TopAbs_State State() const
{
diff --git a/src/SMESH/SMESH_MesherHelper.cxx b/src/SMESH/SMESH_MesherHelper.cxx
index bdd358451..c6c51ab37 100644
--- a/src/SMESH/SMESH_MesherHelper.cxx
+++ b/src/SMESH/SMESH_MesherHelper.cxx
@@ -242,40 +242,68 @@ void SMESH_MesherHelper::SetSubShape(const TopoDS_Shape& aSh)
for ( TopExp_Explorer eF( aSh, TopAbs_FACE ); eF.More(); eF.Next() )
{
const TopoDS_Face& face = TopoDS::Face( eF.Current() );
+ BRepAdaptor_Surface surf( face, false );
+ if ( surf.IsUPeriodic() || surf.IsUClosed() ) {
+ myParIndex |= U_periodic;
+ myPar1[0] = surf.FirstUParameter();
+ myPar2[0] = surf.LastUParameter();
+ }
+ if ( surf.IsVPeriodic() || surf.IsVClosed() ) {
+ myParIndex |= V_periodic;
+ myPar1[1] = surf.FirstVParameter();
+ myPar2[1] = surf.LastVParameter();
+ }
- // if ( surface->IsUPeriodic() || surface->IsVPeriodic() ||
- // surface->IsUClosed() || surface->IsVClosed() )
+ gp_Pnt2d uv1, uv2;
+ for (TopExp_Explorer exp( face, TopAbs_EDGE ); exp.More(); exp.Next())
{
- //while ( surface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface )))
- //surface = Handle(Geom_RectangularTrimmedSurface)::DownCast( surface )->BasisSurface();
-
- for (TopExp_Explorer exp( face, TopAbs_EDGE ); exp.More(); exp.Next())
+ // look for a "seam" edge, a real seam or an edge on period boundary
+ TopoDS_Edge edge = TopoDS::Edge( exp.Current() );
+ if ( myParIndex )
{
- // look for a seam edge
- TopoDS_Edge edge = TopoDS::Edge( exp.Current() );
- if ( BRep_Tool::IsClosed( edge, face )) {
- // initialize myPar1, myPar2 and myParIndex
- gp_Pnt2d uv1, uv2;
- BRep_Tool::UVPoints( edge, face, uv1, uv2 );
- if ( Abs( uv1.Coord(1) - uv2.Coord(1) ) < Abs( uv1.Coord(2) - uv2.Coord(2) ))
+ BRep_Tool::UVPoints( edge, face, uv1, uv2 );
+ const double du = Abs( uv1.Coord(1) - uv2.Coord(1) );
+ const double dv = Abs( uv1.Coord(2) - uv2.Coord(2) );
+
+ bool isSeam = BRep_Tool::IsClosed( edge, face );
+ if ( isSeam ) // real seam - having two pcurves on face
+ {
+ // pcurve can lie not on pediod boundary (22582, mesh_Quadratic_01/C9)
+ if ( du < dv )
{
double u1 = uv1.Coord(1);
edge.Reverse();
BRep_Tool::UVPoints( edge, face, uv1, uv2 );
double u2 = uv1.Coord(1);
- myParIndex |= U_periodic;
myPar1[0] = Min( u1, u2 );
myPar2[0] = Max( u1, u2 );
}
- else {
+ else
+ {
double v1 = uv1.Coord(2);
edge.Reverse();
BRep_Tool::UVPoints( edge, face, uv1, uv2 );
double v2 = uv1.Coord(2);
- myParIndex |= V_periodic;
myPar1[1] = Min( v1, v2 );
myPar2[1] = Max( v1, v2 );
}
+ }
+ else //if ( !isSeam )
+ {
+ // one pcurve but on period boundary (22772, mesh_Quadratic_01/D1)
+ if (( myParIndex & U_periodic ) && du < Precision::PConfusion() )
+ {
+ isSeam = ( Abs( uv1.Coord(1) - myPar1[0] ) < Precision::PConfusion() ||
+ Abs( uv1.Coord(1) - myPar2[0] ) < Precision::PConfusion() );
+ }
+ else if (( myParIndex & V_periodic ) && dv < Precision::PConfusion() )
+ {
+ isSeam = ( Abs( uv1.Coord(2) - myPar1[1] ) < Precision::PConfusion() ||
+ Abs( uv1.Coord(2) - myPar2[1] ) < Precision::PConfusion() );
+ }
+ }
+ if ( isSeam )
+ {
// store seam shape indices, negative if shape encounters twice
int edgeID = meshDS->ShapeToIndex( edge );
mySeamShapeIds.insert( IsSeamShape( edgeID ) ? -edgeID : edgeID );
@@ -284,27 +312,12 @@ void SMESH_MesherHelper::SetSubShape(const TopoDS_Shape& aSh)
mySeamShapeIds.insert( IsSeamShape( vertexID ) ? -vertexID : vertexID );
}
}
-
- // look for a degenerated edge
- if ( SMESH_Algo::isDegenerated( edge )) {
- myDegenShapeIds.insert( meshDS->ShapeToIndex( edge ));
- for ( TopExp_Explorer v( edge, TopAbs_VERTEX ); v.More(); v.Next() )
- myDegenShapeIds.insert( meshDS->ShapeToIndex( v.Current() ));
- }
}
- if ( !myDegenShapeIds.empty() && !myParIndex )
- {
- BRepAdaptor_Surface surf( face, false );
- if ( surf.IsUPeriodic() || surf.IsUClosed() ) {
- myParIndex |= U_periodic;
- myPar1[0] = surf.FirstUParameter();
- myPar2[0] = surf.LastUParameter();
- }
- else if ( surf.IsVPeriodic() || surf.IsVClosed() ) {
- myParIndex |= V_periodic;
- myPar1[1] = surf.FirstVParameter();
- myPar2[1] = surf.LastVParameter();
- }
+ // look for a degenerated edge
+ if ( SMESH_Algo::isDegenerated( edge )) {
+ myDegenShapeIds.insert( meshDS->ShapeToIndex( edge ));
+ for ( TopExp_Explorer v( edge, TopAbs_VERTEX ); v.More(); v.Next() )
+ myDegenShapeIds.insert( meshDS->ShapeToIndex( v.Current() ));
}
}
}
@@ -380,10 +393,13 @@ void SMESH_MesherHelper::AddTLinkNode(const SMDS_MeshNode* n1,
*/
//================================================================================
-void SMESH_MesherHelper::AddTLinks(const SMDS_MeshEdge* edge)
+bool SMESH_MesherHelper::AddTLinks(const SMDS_MeshEdge* edge)
{
- if ( edge->IsQuadratic() )
+ if ( edge && edge->IsQuadratic() )
AddTLinkNode(edge->GetNode(0), edge->GetNode(1), edge->GetNode(2));
+ else
+ return false;
+ return true;
}
//================================================================================
@@ -392,8 +408,9 @@ void SMESH_MesherHelper::AddTLinks(const SMDS_MeshEdge* edge)
*/
//================================================================================
-void SMESH_MesherHelper::AddTLinks(const SMDS_MeshFace* f)
+bool SMESH_MesherHelper::AddTLinks(const SMDS_MeshFace* f)
{
+ bool isQuad = true;
if ( !f->IsPoly() )
switch ( f->NbNodes() ) {
case 7:
@@ -417,7 +434,9 @@ void SMESH_MesherHelper::AddTLinks(const SMDS_MeshFace* f)
AddTLinkNode(f->GetNode(2),f->GetNode(3),f->GetNode(6));
AddTLinkNode(f->GetNode(3),f->GetNode(0),f->GetNode(7)); break;
default:;
+ isQuad = false;
}
+ return isQuad;
}
//================================================================================
@@ -426,7 +445,7 @@ void SMESH_MesherHelper::AddTLinks(const SMDS_MeshFace* f)
*/
//================================================================================
-void SMESH_MesherHelper::AddTLinks(const SMDS_MeshVolume* volume)
+bool SMESH_MesherHelper::AddTLinks(const SMDS_MeshVolume* volume)
{
if ( volume->IsQuadratic() )
{
@@ -460,7 +479,9 @@ void SMESH_MesherHelper::AddTLinks(const SMDS_MeshVolume* volume)
nFCenter ));
}
}
+ return true;
}
+ return false;
}
//================================================================================
@@ -586,14 +607,24 @@ gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face& F,
Handle(Geom_Surface) S = BRep_Tool::Surface(F,loc);
Standard_Boolean isUPeriodic = S->IsUPeriodic();
Standard_Boolean isVPeriodic = S->IsVPeriodic();
+ gp_Pnt2d newUV = uv;
if ( isUPeriodic || isVPeriodic ) {
Standard_Real UF,UL,VF,VL;
S->Bounds(UF,UL,VF,VL);
- if(isUPeriodic)
- uv.SetX( uv.X() + ShapeAnalysis::AdjustToPeriod(uv.X(),UF,UL));
- if(isVPeriodic)
- uv.SetY( uv.Y() + ShapeAnalysis::AdjustToPeriod(uv.Y(),VF,VL));
+ if ( isUPeriodic )
+ newUV.SetX( uv.X() + ShapeAnalysis::AdjustToPeriod(uv.X(),UF,UL));
+ if ( isVPeriodic )
+ newUV.SetY( uv.Y() + ShapeAnalysis::AdjustToPeriod(uv.Y(),VF,VL));
}
+ if ( n2 )
+ {
+ gp_Pnt2d uv2 = GetNodeUV( F, n2, 0, check );
+ if ( isUPeriodic && Abs( uv.X()-uv2.X() ) < Abs( newUV.X()-uv2.X() ))
+ newUV.SetX( uv.X() );
+ if ( isVPeriodic && Abs( uv.Y()-uv2.Y() ) < Abs( newUV.Y()-uv2.Y() ))
+ newUV.SetY( uv.Y() );
+ }
+ uv = newUV;
}
}
else if(Pos->GetTypeOfPosition()==SMDS_TOP_VERTEX)
@@ -910,7 +941,7 @@ bool SMESH_MesherHelper::CheckNodeU(const TopoDS_Edge& E,
int shapeID = n->getshapeId();
bool infinit = Precision::IsInfinite( u );
bool zero = ( u == 0. );
- if ( force || toCheckPosOnShape( shapeID ) || infinit || zero )
+ if ( force || infinit || zero || toCheckPosOnShape( shapeID ))
{
TopLoc_Location loc; double f,l;
Handle(Geom_Curve) curve = BRep_Tool::Curve( E,loc,f,l );
@@ -927,7 +958,7 @@ bool SMESH_MesherHelper::CheckNodeU(const TopoDS_Edge& E,
gp_Pnt nodePnt = SMESH_TNodeXYZ( n );
if ( !loc.IsIdentity() ) nodePnt.Transform( loc.Transformation().Inverted() );
gp_Pnt curvPnt;
- double dist = u;
+ double dist = 2*tol;
if ( !infinit )
{
curvPnt = curve->Value( u );
@@ -2433,7 +2464,7 @@ namespace
//=======================================================================
//function : IsStructured
-//purpose : Return true if 2D mesh on FACE is structured
+//purpose : Return true if 2D mesh on FACE is a structured rectangle
//=======================================================================
bool SMESH_MesherHelper::IsStructured( SMESH_subMesh* faceSM )
@@ -2523,6 +2554,79 @@ bool SMESH_MesherHelper::IsStructured( SMESH_subMesh* faceSM )
return true;
}
+//=======================================================================
+//function : IsDistorted2D
+//purpose : Return true if 2D mesh on FACE is ditorted
+//=======================================================================
+
+bool SMESH_MesherHelper::IsDistorted2D( SMESH_subMesh* faceSM,
+ bool checkUV)
+{
+ if ( !faceSM || faceSM->GetSubShape().ShapeType() != TopAbs_FACE )
+ return false;
+
+ bool haveBadFaces = false;
+
+ SMESH_MesherHelper helper( *faceSM->GetFather() );
+ helper.SetSubShape( faceSM->GetSubShape() );
+
+ const TopoDS_Face& F = TopoDS::Face( faceSM->GetSubShape() );
+ SMESHDS_SubMesh* smDS = helper.GetMeshDS()->MeshElements( F );
+ if ( !smDS || smDS->NbElements() == 0 ) return false;
+
+ SMDS_ElemIteratorPtr faceIt = smDS->GetElements();
+ double prevArea = 0;
+ vector< const SMDS_MeshNode* > nodes;
+ vector< gp_XY > uv;
+ bool* toCheckUV = checkUV ? & checkUV : 0;
+ while ( faceIt->more() && !haveBadFaces )
+ {
+ const SMDS_MeshElement* face = faceIt->next();
+
+ // get nodes
+ nodes.resize( face->NbCornerNodes() );
+ SMDS_MeshElement::iterator n = face->begin_nodes();
+ for ( size_t i = 0; i < nodes.size(); ++n, ++i )
+ nodes[ i ] = *n;
+
+ // avoid elems on degenarate shapes as UV on them can be wrong
+ if ( helper.HasDegeneratedEdges() )
+ {
+ bool isOnDegen = false;
+ for ( size_t i = 0; ( i < nodes.size() && !isOnDegen ); ++i )
+ isOnDegen = helper.IsDegenShape( nodes[ i ]->getshapeId() );
+ if ( isOnDegen )
+ continue;
+ }
+ // prepare to getting UVs
+ const SMDS_MeshNode* inFaceNode = 0;
+ if ( helper.HasSeam() ) {
+ for ( size_t i = 0; ( i < nodes.size() && !inFaceNode ); ++i )
+ if ( !helper.IsSeamShape( nodes[ i ]->getshapeId() ))
+ inFaceNode = nodes[ i ];
+ if ( !inFaceNode )
+ continue;
+ }
+ // get UVs
+ uv.resize( nodes.size() );
+ for ( size_t i = 0; i < nodes.size(); ++i )
+ uv[ i ] = helper.GetNodeUV( F, nodes[ i ], inFaceNode, toCheckUV );
+
+ // compare orientation of triangles
+ double faceArea = 0;
+ for ( int iT = 0, nbT = nodes.size()-2; iT < nbT; ++iT )
+ {
+ gp_XY v1 = uv[ iT+1 ] - uv[ 0 ];
+ gp_XY v2 = uv[ iT+2 ] - uv[ 0 ];
+ faceArea += v2 ^ v1;
+ }
+ haveBadFaces = ( faceArea * prevArea < 0 );
+ prevArea = faceArea;
+ }
+
+ return haveBadFaces;
+}
+
//================================================================================
/*!
* \brief Find out elements orientation on a geometrical face
@@ -2702,6 +2806,28 @@ bool SMESH_MesherHelper::IsSubShape( const TopoDS_Shape& shape, SMESH_Mesh* aMes
(shape.ShapeType() == TopAbs_COMPOUND && aMesh->GetMeshDS()->IsGroupOfSubShapes( shape ));
}
+//=======================================================================
+//function : IsBlock
+//purpose :
+//=======================================================================
+
+bool SMESH_MesherHelper::IsBlock( const TopoDS_Shape& shape )
+{
+ if ( shape.IsNull() )
+ return false;
+
+ TopoDS_Shell shell;
+ TopExp_Explorer exp( shape, TopAbs_SHELL );
+ if ( !exp.More() ) return false;
+ shell = TopoDS::Shell( exp.Current() );
+ if ( exp.Next(), exp.More() ) return false;
+
+ TopoDS_Vertex v;
+ TopTools_IndexedMapOfOrientedShape map;
+ return SMESH_Block::FindBlockShapes( shell, v, v, map );
+}
+
+
//================================================================================
/*!
* \brief Return maximal tolerance of shape
diff --git a/src/SMESH/SMESH_MesherHelper.hxx b/src/SMESH/SMESH_MesherHelper.hxx
index 51ea719de..164861c32 100644
--- a/src/SMESH/SMESH_MesherHelper.hxx
+++ b/src/SMESH/SMESH_MesherHelper.hxx
@@ -117,6 +117,11 @@ class SMESH_EXPORT SMESH_MesherHelper
*/
static bool IsStructured( SMESH_subMesh* faceSM );
+ /*!
+ * \brief Return true if 2D mesh on FACE is distored
+ */
+ static bool IsDistorted2D( SMESH_subMesh* faceSM, bool checkUV=false );
+
/*!
* \brief Returns true if given node is medium
* \param n - node to check
@@ -167,15 +172,15 @@ class SMESH_EXPORT SMESH_MesherHelper
* a0 p0 a1
*/
inline static gp_XY calcTFI(double x, double y,
- const gp_XY a0,const gp_XY a1,const gp_XY a2,const gp_XY a3,
- const gp_XY p0,const gp_XY p1,const gp_XY p2,const gp_XY p3);
+ const gp_XY& a0,const gp_XY& a1,const gp_XY& a2,const gp_XY& a3,
+ const gp_XY& p0,const gp_XY& p1,const gp_XY& p2,const gp_XY& p3);
/*!
* \brief Same as "gp_XY calcTFI(...)" but in 3D
*/
inline static gp_XYZ calcTFI(double x, double y,
- const gp_XYZ a0,const gp_XYZ a1,const gp_XYZ a2,const gp_XYZ a3,
- const gp_XYZ p0,const gp_XYZ p1,const gp_XYZ p2,const gp_XYZ p3);
+ const gp_XYZ& a0,const gp_XYZ& a1,const gp_XYZ& a2,const gp_XYZ& a3,
+ const gp_XYZ& p0,const gp_XYZ& p1,const gp_XYZ& p2,const gp_XYZ& p3);
/*!
* \brief Count nb of sub-shapes
* \param shape - the shape
@@ -216,6 +221,8 @@ class SMESH_EXPORT SMESH_MesherHelper
static bool IsSubShape( const TopoDS_Shape& shape, SMESH_Mesh* aMesh );
+ static bool IsBlock( const TopoDS_Shape& shape );
+
static double MaxTolerance( const TopoDS_Shape& shape );
static double GetAngle( const TopoDS_Edge & E1, const TopoDS_Edge & E2,
@@ -637,9 +644,9 @@ public:
void AddTLinkNodeMap(const TLinkNodeMap& aMap)
{ myTLinkNodeMap.insert(aMap.begin(), aMap.end()); }
- void AddTLinks(const SMDS_MeshEdge* edge);
- void AddTLinks(const SMDS_MeshFace* face);
- void AddTLinks(const SMDS_MeshVolume* vol);
+ bool AddTLinks(const SMDS_MeshEdge* edge);
+ bool AddTLinks(const SMDS_MeshFace* face);
+ bool AddTLinks(const SMDS_MeshVolume* vol);
/**
* Returns myTLinkNodeMap
@@ -725,8 +732,8 @@ public:
//=======================================================================
inline gp_XY
SMESH_MesherHelper::calcTFI(double x, double y,
- const gp_XY a0,const gp_XY a1,const gp_XY a2,const gp_XY a3,
- const gp_XY p0,const gp_XY p1,const gp_XY p2,const gp_XY p3)
+ const gp_XY& a0,const gp_XY& a1,const gp_XY& a2,const gp_XY& a3,
+ const gp_XY& p0,const gp_XY& p1,const gp_XY& p2,const gp_XY& p3)
{
return
((1 - y) * p0 + x * p1 + y * p2 + (1 - x) * p3 ) -
@@ -735,8 +742,8 @@ SMESH_MesherHelper::calcTFI(double x, double y,
//=======================================================================
inline gp_XYZ
SMESH_MesherHelper::calcTFI(double x, double y,
- const gp_XYZ a0,const gp_XYZ a1,const gp_XYZ a2,const gp_XYZ a3,
- const gp_XYZ p0,const gp_XYZ p1,const gp_XYZ p2,const gp_XYZ p3)
+ const gp_XYZ& a0,const gp_XYZ& a1,const gp_XYZ& a2,const gp_XYZ& a3,
+ const gp_XYZ& p0,const gp_XYZ& p1,const gp_XYZ& p2,const gp_XYZ& p3)
{
return
((1 - y) * p0 + x * p1 + y * p2 + (1 - x) * p3 ) -
diff --git a/src/SMESH/SMESH_Pattern.cxx b/src/SMESH/SMESH_Pattern.cxx
index 75d26244d..2264ba3d1 100644
--- a/src/SMESH/SMESH_Pattern.cxx
+++ b/src/SMESH/SMESH_Pattern.cxx
@@ -501,13 +501,8 @@ static gp_XY project (const SMDS_MeshNode* theNode,
}
double u, v, minVal = DBL_MAX;
for ( int i = theProjectorPS.NbExt(); i > 0; i-- )
-#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
if ( theProjectorPS.SquareDistance( i ) < minVal ) {
minVal = theProjectorPS.SquareDistance( i );
-#else
- if ( theProjectorPS.Value( i ) < minVal ) {
- minVal = theProjectorPS.Value( i );
-#endif
theProjectorPS.Point( i ).Parameter( u, v );
}
return gp_XY( u, v );
diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx
index 59294a54c..0d4e2d120 100644
--- a/src/SMESH/SMESH_subMesh.cxx
+++ b/src/SMESH/SMESH_subMesh.cxx
@@ -2148,9 +2148,9 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen,
if ( mainShape.IsSame( _subShape ))
return _subShape;
- const bool ignoreAuxiliaryHyps = false;
+ const bool skipAuxHyps = false;
list aUsedHyp =
- theAlgo->GetUsedHypothesis( *_father, _subShape, ignoreAuxiliaryHyps ); // copy
+ theAlgo->GetUsedHypothesis( *_father, _subShape, skipAuxHyps ); // copy
// put in a compound all shapes with the same hypothesis assigned
// and a good ComputeState
@@ -2161,11 +2161,13 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen,
theSubs.clear();
- TopExp_Explorer anExplorer( mainShape, _subShape.ShapeType() );
- for ( ; anExplorer.More(); anExplorer.Next() )
+ SMESH_subMeshIteratorPtr smIt = _father->GetSubMesh( mainShape )->getDependsOnIterator(false);
+ while ( smIt->more() )
{
- const TopoDS_Shape& S = anExplorer.Current();
- SMESH_subMesh* subMesh = _father->GetSubMesh( S );
+ SMESH_subMesh* subMesh = smIt->next();
+ const TopoDS_Shape& S = subMesh->_subShape;
+ if ( S.ShapeType() != this->_subShape.ShapeType() )
+ continue;
theSubs.push_back( subMesh );
if ( subMesh == this )
{
@@ -2173,12 +2175,14 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen,
}
else if ( subMesh->GetComputeState() == READY_TO_COMPUTE )
{
- SMESH_Algo* anAlgo = theGen->GetAlgo( subMesh );
- if (strcmp( anAlgo->GetName(), theAlgo->GetName()) == 0 && // same algo
- anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp) // same hyps
+ SMESH_Algo* anAlgo = subMesh->GetAlgo();
+ if (( anAlgo->IsSameName( *theAlgo )) && // same algo
+ ( anAlgo->GetUsedHypothesis( *_father, S, skipAuxHyps ) == aUsedHyp )) // same hyps
+ {
aBuilder.Add( aCompound, S );
- if ( !subMesh->SubMeshesComputed() )
- theSubComputed = false;
+ if ( !subMesh->SubMeshesComputed() )
+ theSubComputed = false;
+ }
}
}
diff --git a/src/SMESHGUI/CMakeLists.txt b/src/SMESHGUI/CMakeLists.txt
index d92818942..59a99865b 100644
--- a/src/SMESHGUI/CMakeLists.txt
+++ b/src/SMESHGUI/CMakeLists.txt
@@ -142,6 +142,7 @@ SET(_moc_HEADERS
SMESHGUI_PropertiesDlg.h
SMESHGUI_Add0DElemsOnAllNodesDlg.h
SMESHGUI_FieldSelectorWdg.h
+ SMESHGUI_DisplayEntitiesDlg.h
)
# header files / no moc processing
@@ -249,6 +250,7 @@ SET(_other_SOURCES
SMESHGUI_MeshEditPreview.cxx
SMESHGUI_FileValidator.cxx
SMESHGUI_FieldSelectorWdg.cxx
+ SMESHGUI_DisplayEntitiesDlg.cxx
)
# sources / to compile
diff --git a/src/SMESHGUI/SMESHGUI.cxx b/src/SMESHGUI/SMESHGUI.cxx
index 71ccf611d..7908b4f49 100644
--- a/src/SMESHGUI/SMESHGUI.cxx
+++ b/src/SMESHGUI/SMESHGUI.cxx
@@ -81,6 +81,7 @@
#include "SMESHGUI_SymmetryDlg.h"
#include "SMESHGUI_TranslationDlg.h"
#include "SMESHGUI_TransparencyDlg.h"
+#include "SMESHGUI_DisplayEntitiesDlg.h"
#include "SMESHGUI_FilterUtils.h"
#include "SMESHGUI_GEOMGenUtils.h"
@@ -91,14 +92,14 @@
#include "SMESHGUI_Utils.h"
#include "SMESHGUI_VTKUtils.h"
-#include
+#include "SMESH_version.h"
#include "SMESH_ControlsDef.hxx"
-#include
-#include
-#include
-#include
-#include
+#include "SMESH_Actor.h"
+#include "SMESH_ActorUtils.h"
+#include "SMESH_Client.hxx"
+#include "SMESH_ScalarBarActor.h"
+#include "SMESH_TypeFilter.hxx"
// SALOME GUI includes
#include
@@ -132,7 +133,6 @@
#include
#include
-#include
#ifndef DISABLE_PLOT2DVIEWER
#include
@@ -1566,111 +1566,124 @@ namespace
void Control( int theCommandID )
{
+ SMESH_Actor::eControl aControl = SMESH_Actor::eNone;
+ switch ( theCommandID ){
+ case SMESHOp::OpFreeNode:
+ aControl = SMESH_Actor::eFreeNodes;
+ break;
+ case SMESHOp::OpEqualNode:
+ aControl = SMESH_Actor::eCoincidentNodes;
+ break;
+ case SMESHOp::OpFreeEdge:
+ aControl = SMESH_Actor::eFreeEdges;
+ break;
+ case SMESHOp::OpFreeBorder:
+ aControl = SMESH_Actor::eFreeBorders;
+ break;
+ case SMESHOp::OpLength:
+ aControl = SMESH_Actor::eLength;
+ break;
+ case SMESHOp::OpConnection:
+ aControl = SMESH_Actor::eMultiConnection;
+ break;
+ case SMESHOp::OpEqualEdge:
+ aControl = SMESH_Actor::eCoincidentElems1D;
+ break;
+ case SMESHOp::OpFreeFace:
+ aControl = SMESH_Actor::eFreeFaces;
+ break;
+ case SMESHOp::OpBareBorderFace:
+ aControl = SMESH_Actor::eBareBorderFace;
+ break;
+ case SMESHOp::OpOverConstrainedFace:
+ aControl = SMESH_Actor::eOverConstrainedFace;
+ break;
+ case SMESHOp::OpLength2D:
+ aControl = SMESH_Actor::eLength2D;
+ break;
+ case SMESHOp::OpConnection2D:
+ aControl = SMESH_Actor::eMultiConnection2D;
+ break;
+ case SMESHOp::OpArea:
+ aControl = SMESH_Actor::eArea;
+ break;
+ case SMESHOp::OpTaper:
+ aControl = SMESH_Actor::eTaper;
+ break;
+ case SMESHOp::OpAspectRatio:
+ aControl = SMESH_Actor::eAspectRatio;
+ break;
+ case SMESHOp::OpMinimumAngle:
+ aControl = SMESH_Actor::eMinimumAngle;
+ break;
+ case SMESHOp::OpWarpingAngle:
+ aControl = SMESH_Actor::eWarping;
+ break;
+ case SMESHOp::OpSkew:
+ aControl = SMESH_Actor::eSkew;
+ break;
+ case SMESHOp::OpMaxElementLength2D:
+ aControl = SMESH_Actor::eMaxElementLength2D;
+ break;
+ case SMESHOp::OpEqualFace:
+ aControl = SMESH_Actor:: eCoincidentElems2D;
+ break;
+ case SMESHOp::OpAspectRatio3D:
+ aControl = SMESH_Actor::eAspectRatio3D;
+ break;
+ case SMESHOp::OpVolume:
+ aControl = SMESH_Actor::eVolume3D;
+ break;
+ case SMESHOp::OpMaxElementLength3D:
+ aControl = SMESH_Actor::eMaxElementLength3D;
+ break;
+ case SMESHOp::OpBareBorderVolume:
+ aControl = SMESH_Actor::eBareBorderVolume;
+ break;
+ case SMESHOp::OpOverConstrainedVolume:
+ aControl = SMESH_Actor::eOverConstrainedVolume;
+ break;
+ case SMESHOp::OpEqualVolume:
+ aControl = SMESH_Actor::eCoincidentElems3D;
+ break;
+ }
+ _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
LightApp_SelectionMgr *aSel = SMESHGUI::selectionMgr();
SALOME_ListIO selected;
if( aSel )
aSel->selectedObjects( selected );
if( !selected.IsEmpty() ){
- Handle(SALOME_InteractiveObject) anIO = selected.First();
- if(!anIO.IsNull()){
- SMESH_Actor::eControl aControl = SMESH_Actor::eNone;
- if(SMESH_Actor *anActor = SMESH::FindActorByEntry(anIO->getEntry())) {
- switch ( theCommandID ){
- case SMESHOp::OpFreeNode:
- aControl = SMESH_Actor::eFreeNodes;
- break;
- case SMESHOp::OpEqualNode:
- aControl = SMESH_Actor::eCoincidentNodes;
- break;
- case SMESHOp::OpFreeEdge:
- aControl = SMESH_Actor::eFreeEdges;
- break;
- case SMESHOp::OpFreeBorder:
- aControl = SMESH_Actor::eFreeBorders;
- break;
- case SMESHOp::OpLength:
- aControl = SMESH_Actor::eLength;
- break;
- case SMESHOp::OpConnection:
- aControl = SMESH_Actor::eMultiConnection;
- break;
- case SMESHOp::OpEqualEdge:
- aControl = SMESH_Actor::eCoincidentElems1D;
- break;
- case SMESHOp::OpFreeFace:
- aControl = SMESH_Actor::eFreeFaces;
- break;
- case SMESHOp::OpBareBorderFace:
- aControl = SMESH_Actor::eBareBorderFace;
- break;
- case SMESHOp::OpOverConstrainedFace:
- aControl = SMESH_Actor::eOverConstrainedFace;
- break;
- case SMESHOp::OpLength2D:
- aControl = SMESH_Actor::eLength2D;
- break;
- case SMESHOp::OpConnection2D:
- aControl = SMESH_Actor::eMultiConnection2D;
- break;
- case SMESHOp::OpArea:
- aControl = SMESH_Actor::eArea;
- break;
- case SMESHOp::OpTaper:
- aControl = SMESH_Actor::eTaper;
- break;
- case SMESHOp::OpAspectRatio:
- aControl = SMESH_Actor::eAspectRatio;
- break;
- case SMESHOp::OpMinimumAngle:
- aControl = SMESH_Actor::eMinimumAngle;
- break;
- case SMESHOp::OpWarpingAngle:
- aControl = SMESH_Actor::eWarping;
- break;
- case SMESHOp::OpSkew:
- aControl = SMESH_Actor::eSkew;
- break;
- case SMESHOp::OpMaxElementLength2D:
- aControl = SMESH_Actor::eMaxElementLength2D;
- break;
- case SMESHOp::OpEqualFace:
- aControl = SMESH_Actor:: eCoincidentElems2D;
- break;
- case SMESHOp::OpAspectRatio3D:
- aControl = SMESH_Actor::eAspectRatio3D;
- break;
- case SMESHOp::OpVolume:
- aControl = SMESH_Actor::eVolume3D;
- break;
- case SMESHOp::OpMaxElementLength3D:
- aControl = SMESH_Actor::eMaxElementLength3D;
- break;
- case SMESHOp::OpBareBorderVolume:
- aControl = SMESH_Actor::eBareBorderVolume;
- break;
- case SMESHOp::OpOverConstrainedVolume:
- aControl = SMESH_Actor::eOverConstrainedVolume;
- break;
- case SMESHOp::OpEqualVolume:
- aControl = SMESH_Actor::eCoincidentElems3D;
- break;
- }
-
- anActor->SetControlMode(aControl);
- anActor->GetScalarBarActor()->SetTitle( functorToString( anActor->GetFunctor() ).toLatin1().constData() );
- SMESH::RepaintCurrentView();
+ SALOME_ListIteratorOfListIO It(selected);
+ for ( ; It.More(); It.Next())
+ {
+ Handle(SALOME_InteractiveObject) anIO = It.Value();
+ if(!anIO.IsNull()){
+ _PTR(SObject) SO = aStudy->FindObjectID( It.Value()->getEntry() );
+ if ( SO ) {
+ CORBA::Object_var aObject = SMESH::SObjectToObject( SO );
+ SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow( aObject );
+ SMESH::SMESH_subMesh_var aSubMesh = SMESH::SMESH_subMesh::_narrow( aObject );
+ SMESH::SMESH_GroupBase_var aGroup = SMESH::SMESH_GroupBase::_narrow( aObject );
+ if ( !aMesh->_is_nil() || !aSubMesh->_is_nil() || !aGroup->_is_nil() ) {
+ if(SMESH_Actor *anActor = SMESH::FindActorByEntry(anIO->getEntry())) {
+ anActor->SetControlMode(aControl);
+ anActor->GetScalarBarActor()->SetTitle( functorToString( anActor->GetFunctor() ).toLatin1().constData() );
+ SMESH::RepaintCurrentView();
#ifndef DISABLE_PLOT2DVIEWER
- if(anActor->GetPlot2Histogram()) {
- SPlot2d_Histogram* aHistogram = anActor->UpdatePlot2Histogram();
- QString functorName = functorToString( anActor->GetFunctor());
- QString aHistogramName("%1 : %2");
- aHistogramName = aHistogramName.arg(anIO->getName()).arg(functorName);
- aHistogram->setName(aHistogramName);
- aHistogram->setHorTitle(functorName);
- SMESH::ProcessIn2DViewers(anActor);
- }
+ if(anActor->GetPlot2Histogram()) {
+ SPlot2d_Histogram* aHistogram = anActor->UpdatePlot2Histogram();
+ QString functorName = functorToString( anActor->GetFunctor());
+ QString aHistogramName("%1 : %2");
+ aHistogramName = aHistogramName.arg(anIO->getName()).arg(functorName);
+ aHistogram->setName(aHistogramName);
+ aHistogram->setHorTitle(functorName);
+ SMESH::ProcessIn2DViewers(anActor);
+ }
#endif
+ }
+ }
+ }
}
}
}
@@ -1743,6 +1756,19 @@ namespace
return RefType;
}
+ uint randomize( uint size )
+ {
+ static bool initialized = false;
+ if ( !initialized ) {
+ qsrand( QDateTime::currentDateTime().toTime_t() );
+ initialized = true;
+ }
+ uint v = qrand();
+ v = uint( (double)( v ) / RAND_MAX * size );
+ v = qMax( uint(0), qMin ( v, size-1 ) );
+ return v;
+ }
+
} //namespace
void SMESHGUI::OnEditDelete()
@@ -2503,6 +2529,13 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
::SetDisplayEntity(theCommandID);
break;
+ // Choose entities to be displayed
+ case SMESHOp::OpDEChoose:
+ {
+ ( new SMESHGUI_DisplayEntitiesDlg( SMESHGUI::desktop() ) )->exec();
+ break;
+ }
+
case SMESHOp::OpOrientationOnFaces:
{
LightApp_SelectionMgr* mgr = selectionMgr();
@@ -3530,19 +3563,10 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
LightApp_SelectionMgr* mgr = selectionMgr();
SALOME_ListIO selected; mgr->selectedObjects( selected );
- if ( selected.Extent() == 1 && selected.First()->hasEntry() ) {
- _PTR(SObject) SO = aStudy->FindObjectID( selected.First()->getEntry() );
- if ( SO ) {
- CORBA::Object_var aObject = SMESH::SObjectToObject( SO );
- SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow( aObject );
- SMESH::SMESH_subMesh_var aSubMesh = SMESH::SMESH_subMesh::_narrow( aObject );
- SMESH::SMESH_GroupBase_var aGroup = SMESH::SMESH_GroupBase::_narrow( aObject );
- if ( !aMesh->_is_nil() || !aSubMesh->_is_nil() || !aGroup->_is_nil() ) {
- SUIT_OverrideCursor wc;
- ::Control( theCommandID );
- break;
- }
- }
+ if( !selected.IsEmpty() ) {
+ SUIT_OverrideCursor wc;
+ ::Control( theCommandID );
+ break;
}
SUIT_MessageBox::warning(desktop(),
tr( "SMESH_WRN_WARNING" ),
@@ -3855,8 +3879,8 @@ void SMESHGUI::initialize( CAM_Application* app )
createSMESHAction( SMESHOp::OpRemoveOrphanNodes, "REMOVE_ORPHAN_NODES", "ICON_DLG_REM_ORPHAN_NODES" );
createSMESHAction( SMESHOp::OpClearMesh, "CLEAR_MESH", "ICON_CLEAR_MESH" );
- createSMESHAction( SMESHOp::OpRenumberingNodes, "RENUM_NODES", "ICON_DLG_RENUMBERING_NODES" );
- createSMESHAction( SMESHOp::OpRenumberingElements, "RENUM_ELEMENTS", "ICON_DLG_RENUMBERING_ELEMENTS" );
+ //createSMESHAction( SMESHOp::OpRenumberingNodes, "RENUM_NODES", "ICON_DLG_RENUMBERING_NODES" );
+ //createSMESHAction( SMESHOp::OpRenumberingElements, "RENUM_ELEMENTS", "ICON_DLG_RENUMBERING_ELEMENTS" );
createSMESHAction( SMESHOp::OpTranslation, "TRANS", "ICON_SMESH_TRANSLATION_VECTOR" );
createSMESHAction( SMESHOp::OpRotation, "ROT", "ICON_DLG_MESH_ROTATION" );
@@ -3899,7 +3923,8 @@ void SMESHGUI::initialize( CAM_Application* app )
createSMESHAction( SMESHOp::OpDEFaces, "FACES", "ICON_DLG_TRIANGLE", 0, true );
createSMESHAction( SMESHOp::OpDEVolumes, "VOLUMES", "ICON_DLG_TETRAS", 0, true );
createSMESHAction( SMESHOp::OpDEBalls, "BALLS", "ICON_DLG_BALL", 0, true );
- createSMESHAction( SMESHOp::OpDEAllEntity, "ALL" );
+ createSMESHAction( SMESHOp::OpDEChoose, "CHOOSE", "ICON_DLG_CHOOSE", 0, false );
+ createSMESHAction( SMESHOp::OpDEAllEntity, "ALL", "ICON_DLG_CHOOSE_ALL", 0, false );
createSMESHAction( SMESHOp::OpOrientationOnFaces, "FACE_ORIENTATION", "", 0, true );
createSMESHAction( SMESHOp::OpRepresentationLines, "LINE_REPRESENTATION", "", 0, true );
@@ -3927,6 +3952,23 @@ void SMESHGUI::initialize( CAM_Application* app )
createSMESHAction( SMESHOp::OpSortChild, "SORT_CHILD_ITEMS" );
+ QList aCtrlActions;
+ aCtrlActions << SMESHOp::OpFreeNode << SMESHOp::OpEqualNode // node controls
+ << SMESHOp::OpFreeEdge << SMESHOp::OpFreeBorder
+ << SMESHOp::OpLength << SMESHOp::OpConnection << SMESHOp::OpEqualEdge // edge controls
+ << SMESHOp::OpFreeFace << SMESHOp::OpLength2D << SMESHOp::OpConnection2D
+ << SMESHOp::OpArea << SMESHOp::OpTaper << SMESHOp::OpAspectRatio
+ << SMESHOp::OpMinimumAngle << SMESHOp::OpWarpingAngle << SMESHOp::OpSkew
+ << SMESHOp::OpMaxElementLength2D << SMESHOp::OpBareBorderFace
+ << SMESHOp::OpOverConstrainedFace << SMESHOp::OpEqualFace // face controls
+ << SMESHOp::OpAspectRatio3D << SMESHOp::OpVolume
+ << SMESHOp::OpMaxElementLength3D << SMESHOp::OpBareBorderVolume
+ << SMESHOp::OpOverConstrainedVolume << SMESHOp::OpEqualVolume; // volume controls
+ QActionGroup* aCtrlGroup = new QActionGroup( application()->desktop() );
+ aCtrlGroup->setExclusive( true );
+ for( int i = 0; i < aCtrlActions.size(); i++ )
+ aCtrlGroup->addAction( action( aCtrlActions[i] ) );
+
// ----- create menu --------------
int fileId = createMenu( tr( "MEN_FILE" ), -1, 1 ),
editId = createMenu( tr( "MEN_EDIT" ), -1, 3 ),
@@ -3947,7 +3989,7 @@ void SMESHGUI::initialize( CAM_Application* app )
volumeId = createMenu( tr( "MEN_VOLUME_CTRL" ), ctrlId, -1, 10 ),
addId = createMenu( tr( "MEN_ADD" ), modifyId, 402 ),
removeId = createMenu( tr( "MEN_REMOVE" ), modifyId, 403 ),
- renumId = createMenu( tr( "MEN_RENUM" ), modifyId, 404 ),
+ //renumId = createMenu( tr( "MEN_RENUM" ), modifyId, 404 ),
transfId = createMenu( tr( "MEN_TRANSF" ), modifyId, 405 ),
basicPropId = createMenu( tr( "MEN_BASIC_PROPERTIES" ), measureId, -1, 10 );
@@ -4031,6 +4073,8 @@ void SMESHGUI::initialize( CAM_Application* app )
createMenu( SMESHOp::OpOverConstrainedVolume, volumeId, -1 );
createMenu( SMESHOp::OpEqualVolume, volumeId, -1 );
createMenu( separator(), ctrlId, -1 );
+ createMenu( SMESHOp::OpReset, ctrlId, -1 );
+ createMenu( separator(), ctrlId, -1 );
createMenu( SMESHOp::OpOverallMeshQuality, ctrlId, -1 );
createMenu( SMESHOp::OpNode, addId, -1 );
@@ -4067,8 +4111,8 @@ void SMESHGUI::initialize( CAM_Application* app )
createMenu( separator(), removeId, -1 );
createMenu( SMESHOp::OpClearMesh, removeId, -1 );
- createMenu( SMESHOp::OpRenumberingNodes, renumId, -1 );
- createMenu( SMESHOp::OpRenumberingElements, renumId, -1 );
+ //createMenu( SMESHOp::OpRenumberingNodes, renumId, -1 );
+ //createMenu( SMESHOp::OpRenumberingElements, renumId, -1 );
createMenu( SMESHOp::OpTranslation, transfId, -1 );
createMenu( SMESHOp::OpRotation, transfId, -1 );
@@ -4103,21 +4147,21 @@ void SMESHGUI::initialize( CAM_Application* app )
createMenu( SMESHOp::OpUpdate, viewId, -1 );
// ----- create toolbars --------------
- int meshTb = createTool( tr( "TB_MESH" ) ),
- info = createTool( tr( "TB_INFO" ) ),
- groupTb = createTool( tr( "TB_GROUP" ) ),
- ctrl0dTb = createTool( tr( "TB_CTRL0D" ) ),
- ctrl1dTb = createTool( tr( "TB_CTRL1D" ) ),
- ctrl2dTb = createTool( tr( "TB_CTRL2D" ) ),
- ctrl3dTb = createTool( tr( "TB_CTRL3D" ) ),
- addElemTb = createTool( tr( "TB_ADD" ) ),
- addNonElemTb = createTool( tr( "TB_ADDNON" ) ),
- remTb = createTool( tr( "TB_REM" ) ),
- renumbTb = createTool( tr( "TB_RENUMBER" ) ),
- transformTb = createTool( tr( "TB_TRANSFORM" ) ),
- modifyTb = createTool( tr( "TB_MODIFY" ) ),
- measuremTb = createTool( tr( "TB_MEASUREM" ) ),
- dispModeTb = createTool( tr( "TB_DISP_MODE" ) );
+ int meshTb = createTool( tr( "TB_MESH" ), QString( "SMESHMeshToolbar" ) ),
+ info = createTool( tr( "TB_INFO" ), QString( "SMESHInformationToolbar" ) ),
+ groupTb = createTool( tr( "TB_GROUP" ), QString( "SMESHGroupToolbar" ) ),
+ ctrl0dTb = createTool( tr( "TB_CTRL0D" ), QString( "SMESHNodeControlsToolbar" ) ),
+ ctrl1dTb = createTool( tr( "TB_CTRL1D" ), QString( "SMESHEdgeControlsToolbar" ) ),
+ ctrl2dTb = createTool( tr( "TB_CTRL2D" ), QString( "SMESHFaceControlsToolbar" ) ),
+ ctrl3dTb = createTool( tr( "TB_CTRL3D" ), QString( "SMESHVolumeControlsToolbar" ) ),
+ addElemTb = createTool( tr( "TB_ADD" ), QString( "SMESHAddElementToolbar" ) ),
+ addNonElemTb = createTool( tr( "TB_ADDNON" ), QString( "SMESHAddElementToolbar" ) ),
+ remTb = createTool( tr( "TB_REM" ), QString( "SMESHRemoveToolbar" ) ),
+ //renumbTb = createTool( tr( "TB_RENUMBER" ), QString( "SMESHRenumberingToolbar" ) ),
+ transformTb = createTool( tr( "TB_TRANSFORM" ), QString( "SMESHTransformationToolbar" ) ),
+ modifyTb = createTool( tr( "TB_MODIFY" ), QString( "SMESHModificationToolbar" ) ),
+ measuremTb = createTool( tr( "TB_MEASUREM" ), QString( "SMESHMeasurementsToolbar" ) ),
+ dispModeTb = createTool( tr( "TB_DISP_MODE" ), QString( "SMESHDisplayModeToolbar" ) );
createTool( SMESHOp::OpCreateMesh, meshTb );
createTool( SMESHOp::OpCreateSubMesh, meshTb );
@@ -4201,8 +4245,8 @@ void SMESHGUI::initialize( CAM_Application* app )
createTool( SMESHOp::OpRemoveOrphanNodes, remTb );
createTool( SMESHOp::OpClearMesh, remTb );
- createTool( SMESHOp::OpRenumberingNodes, renumbTb );
- createTool( SMESHOp::OpRenumberingElements, renumbTb );
+ //createTool( SMESHOp::OpRenumberingNodes, renumbTb );
+ //createTool( SMESHOp::OpRenumberingElements, renumbTb );
createTool( SMESHOp::OpTranslation, transformTb );
createTool( SMESHOp::OpRotation, transformTb );
@@ -4413,6 +4457,11 @@ void SMESHGUI::initialize( CAM_Application* app )
popupMgr()->insert( separator(), anId, -1 );
+ popupMgr()->insert( action( SMESHOp::OpDEChoose ), anId, -1 );
+ popupMgr()->setRule( action( SMESHOp::OpDEChoose ), aClient + "&&" + aType + "&&" + isNotEmpty, QtxPopupMgr::VisibleRule );
+
+ popupMgr()->insert( separator(), anId, -1 );
+
popupMgr()->insert( action( SMESHOp::OpDEAllEntity ), anId, -1 );
popupMgr()->setRule( action( SMESHOp::OpDEAllEntity ), aDiffElemsInVTK + "&& isVisible && not( elemTypes in entityMode )", QtxPopupMgr::VisibleRule );
@@ -4731,6 +4780,8 @@ bool SMESHGUI::deactivateModule( SUIT_Study* study )
void SMESHGUI::studyClosed( SUIT_Study* s )
{
+ if( !s )
+ return;
SMESH::RemoveVisuData( s->id() );
SalomeApp_Module::studyClosed( s );
}
@@ -4879,7 +4930,7 @@ void SMESHGUI::createPreferences()
addPreference( tr( "PREF_PRECISION_USE" ), qaGroup, LightApp_Preferences::Bool, "SMESH", "use_precision" );
int prec = addPreference( tr( "PREF_PRECISION_VALUE" ), qaGroup, LightApp_Preferences::IntSpin, "SMESH", "controls_precision" );
setPreferenceProperty( prec, "min", 0 );
- setPreferenceProperty( prec, "max", 16 );
+ setPreferenceProperty( prec, "max", 100 );
int doubleNodesTol = addPreference( tr( "PREF_EQUAL_NODES_TOL" ), qaGroup, LightApp_Preferences::DblSpin, "SMESH", "equal_nodes_tolerance" );
setPreferenceProperty( doubleNodesTol, "precision", 10 );
setPreferenceProperty( doubleNodesTol, "min", 0.0000000001 );
@@ -6901,7 +6952,7 @@ SALOMEDS::Color SMESHGUI::getPredefinedUniqueColor()
}
}
}
- static int currentColor = 0;
+ static int currentColor = randomize( colors.size() );
SALOMEDS::Color color;
color.R = (double)colors[currentColor].red() / 255.0;
diff --git a/src/SMESHGUI/SMESHGUI_Add0DElemsOnAllNodesDlg.cxx b/src/SMESHGUI/SMESHGUI_Add0DElemsOnAllNodesDlg.cxx
index 9cbad861c..b053c6099 100644
--- a/src/SMESHGUI/SMESHGUI_Add0DElemsOnAllNodesDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_Add0DElemsOnAllNodesDlg.cxx
@@ -463,9 +463,7 @@ void SMESHGUI_Add0DElemsOnAllNodesOp::onSelTypeChange(int selType)
//================================================================================
/*!
- * \brief Install
- *
- *
+ * \brief Install filters
*/
//================================================================================
diff --git a/src/SMESHGUI/SMESHGUI_AddMeshElementDlg.cxx b/src/SMESHGUI/SMESHGUI_AddMeshElementDlg.cxx
index 79588047c..cbc584da5 100644
--- a/src/SMESHGUI/SMESHGUI_AddMeshElementDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_AddMeshElementDlg.cxx
@@ -586,6 +586,7 @@ void SMESHGUI_AddMeshElementDlg::ClickOnApply()
SMESH::long_array_var anIdList = new SMESH::long_array;
anIdList->length( 1 );
anIdList[0] = -1;
+ const bool onlyNodesInMesh = ( myMesh->NbElements() == 0 );
switch (myElementType) {
case SMDSAbs_0DElement:
@@ -645,8 +646,10 @@ void SMESHGUI_AddMeshElementDlg::ClickOnApply()
mySelectionMgr->setSelectedObjects( aList, false );
mySimulation->SetVisibility(false);
+ if ( onlyNodesInMesh )
+ myActor->SetRepresentation( SMESH_Actor::eEdge ); // wireframe
SMESH::UpdateView();
-
+
buttonOk->setEnabled(false);
buttonApply->setEnabled(false);
diff --git a/src/SMESHGUI/SMESHGUI_CopyMeshDlg.cxx b/src/SMESHGUI/SMESHGUI_CopyMeshDlg.cxx
index 39665f3a5..8a02ddd03 100644
--- a/src/SMESHGUI/SMESHGUI_CopyMeshDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_CopyMeshDlg.cxx
@@ -166,9 +166,10 @@ SMESHGUI_CopyMeshDlg::SMESHGUI_CopyMeshDlg( SMESHGUI* theModule )
myCopyGroupsCheck = new QCheckBox(tr("SMESH_MAKE_GROUPS"), GroupArguments);
myCopyGroupsCheck->setChecked(false);
- // CheckBox for keeping ids
+ // CheckBox for keeping ids ( OBSOLETE )
myKeepIdsCheck = new QCheckBox(tr("SMESH_KEEP_IDS"), GroupArguments);
myKeepIdsCheck->setChecked(true);
+ myKeepIdsCheck->hide();
// layout
GroupArgumentsLayout->addWidget(myTextLabelElements, 0, 0);
@@ -178,7 +179,7 @@ SMESHGUI_CopyMeshDlg::SMESHGUI_CopyMeshDlg( SMESHGUI* theModule )
GroupArgumentsLayout->addWidget(meshNameLabel, 2, 0);
GroupArgumentsLayout->addWidget(myMeshNameEdit, 2, 1, 1, 5);
GroupArgumentsLayout->addWidget(myCopyGroupsCheck, 3, 0, 1, 6);
- GroupArgumentsLayout->addWidget(myKeepIdsCheck, 4, 0, 1, 6);
+ // GroupArgumentsLayout->addWidget(myKeepIdsCheck, 4, 0, 1, 6);
/***************************************************************/
GroupButtons = new QGroupBox(this);
diff --git a/src/SMESHGUI/SMESHGUI_DeleteGroupDlg.cxx b/src/SMESHGUI/SMESHGUI_DeleteGroupDlg.cxx
index 5d0a1ee7d..f106c0b66 100644
--- a/src/SMESHGUI/SMESHGUI_DeleteGroupDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_DeleteGroupDlg.cxx
@@ -43,7 +43,6 @@
#include
#include
-#include
#include
#include
diff --git a/src/SMESHGUI/SMESHGUI_DisplayEntitiesDlg.cxx b/src/SMESHGUI/SMESHGUI_DisplayEntitiesDlg.cxx
new file mode 100644
index 000000000..1e0a288d5
--- /dev/null
+++ b/src/SMESHGUI/SMESHGUI_DisplayEntitiesDlg.cxx
@@ -0,0 +1,247 @@
+// Copyright (C) 2014 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File : SMESHGUI_DisplayEntitiesDlg.cxx
+// Author : Alexander KOVALEV, Open CASCADE S.A.S. (alexander.kovalev@opencascade.com)
+
+#include "SMESHGUI_DisplayEntitiesDlg.h"
+
+#include "SMESHGUI.h"
+#include "SMESHGUI_Utils.h"
+#include "SMESHGUI_VTKUtils.h"
+#include "SMESHGUI_MeshUtils.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+const int MARGIN = 9;
+const int SPACING = 6;
+
+/*!
+ \class SMESHGUI_DisplayEntitiesDlg
+ \brief Dialog box to select entities to be displayed in viewer
+*/
+
+/*
+ \brief Constructor
+ \param parent parent widget
+*/
+SMESHGUI_DisplayEntitiesDlg::SMESHGUI_DisplayEntitiesDlg( QWidget* parent )
+ : SMESHGUI_Dialog( parent, true, false, Standard )
+{
+ SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
+
+ LightApp_SelectionMgr* mgr = SMESHGUI::selectionMgr();
+ SALOME_ListIO selected;
+ mgr->selectedObjects( selected );
+ SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_nil();
+ myActor = 0;
+ myNbCheckedButtons = 0;
+
+ SALOME_ListIteratorOfListIO it( selected );
+ myIObject = selected.First();
+ if ( myIObject->hasEntry() ) {
+ myActor = SMESH::FindActorByEntry( myIObject->getEntry() );
+ }
+ myEntityMode = myActor ? myActor->GetEntityMode() : 0;
+
+ aMesh = SMESH::GetMeshByIO( myIObject );
+
+ // set title
+ setWindowTitle( tr( "MEN_DISP_ENT" ) );
+
+ // create widgets
+ QGroupBox* anEntitiesGrp = new QGroupBox( tr( "SMESH_MESHINFO_ENTITIES" ), mainFrame() );
+ QGridLayout* hl = new QGridLayout( anEntitiesGrp );
+ hl->setMargin( MARGIN );
+ hl->setSpacing( SPACING );
+ int nbElements;
+
+ // 0DElements
+ nbElements = myActor ? myActor->GetObject()->GetNbEntities( SMDSAbs_0DElement ) : aMesh->Nb0DElements();
+ my0DElemsTB = new QCheckBox( tr("SMESH_ELEMS0D"), anEntitiesGrp );
+ my0DElemsTB->setIcon( QIcon( aResMgr->loadPixmap( "SMESH", tr( "ICON_DLG_ELEM0D" ) ) ) );
+ bool has0DElems = myEntityMode & SMESH_Actor::e0DElements;
+ my0DElemsTB->setChecked( has0DElems );
+ if ( has0DElems )
+ myNbCheckedButtons++;
+ connect( my0DElemsTB, SIGNAL(toggled(bool)), this, SLOT(onChangeEntityMode(bool)) );
+ QLabel* nb0DElemsLab = new QLabel( QString("%1").arg(nbElements).toLatin1().data(), anEntitiesGrp );
+ hl->addWidget( my0DElemsTB, 0, 0 );
+ hl->addWidget( nb0DElemsLab, 0, 1 );
+ my0DElemsTB->setEnabled( nbElements );
+ nb0DElemsLab->setEnabled( nbElements );
+
+ // Edges
+ nbElements = myActor ? myActor->GetObject()->GetNbEntities( SMDSAbs_Edge ) : aMesh->NbEdges();
+ myEdgesTB = new QCheckBox( tr("SMESH_EDGES"), anEntitiesGrp );
+ myEdgesTB->setIcon( QIcon( aResMgr->loadPixmap( "SMESH", tr( "ICON_DLG_EDGE" ) ) ) );
+ bool hasEdges = myEntityMode & SMESH_Actor::eEdges;
+ myEdgesTB->setChecked( hasEdges );
+ if ( hasEdges )
+ myNbCheckedButtons++;
+ connect( myEdgesTB, SIGNAL(toggled(bool)), this, SLOT(onChangeEntityMode(bool)) );
+ QLabel* nbEdgesLab = new QLabel( QString("%1").arg(nbElements).toLatin1().data(), anEntitiesGrp );
+ hl->addWidget( myEdgesTB, 1, 0 );
+ hl->addWidget( nbEdgesLab, 1, 1 );
+ myEdgesTB->setEnabled( nbElements );
+ nbEdgesLab->setEnabled( nbElements );
+
+ // Faces
+ nbElements = myActor ? myActor->GetObject()->GetNbEntities( SMDSAbs_Face ) : aMesh->NbFaces();
+ myFacesTB = new QCheckBox( tr("SMESH_FACES"), anEntitiesGrp );
+ myFacesTB->setIcon( QIcon( aResMgr->loadPixmap( "SMESH", tr( "ICON_DLG_TRIANGLE" ) ) ) );
+ bool hasFaces = myEntityMode & SMESH_Actor::eFaces;
+ myFacesTB->setChecked( hasFaces );
+ if ( hasFaces )
+ myNbCheckedButtons++;
+ connect( myFacesTB, SIGNAL(toggled(bool)), this, SLOT(onChangeEntityMode(bool)) );
+ QLabel* nbFacesLab = new QLabel( QString("%1").arg(nbElements).toLatin1().data(), anEntitiesGrp );
+ hl->addWidget( myFacesTB, 2, 0 );
+ hl->addWidget( nbFacesLab, 2, 1 );
+ myFacesTB->setEnabled( nbElements );
+ nbFacesLab->setEnabled( nbElements );
+
+ // Volumes
+ nbElements = myActor ? myActor->GetObject()->GetNbEntities( SMDSAbs_Volume ) : aMesh->NbVolumes();
+ myVolumesTB = new QCheckBox( tr("SMESH_VOLUMES"), anEntitiesGrp );
+ myVolumesTB->setIcon( QIcon( aResMgr->loadPixmap( "SMESH", tr( "ICON_DLG_TETRAS" ) ) ) );
+ bool hasVolumes = myEntityMode & SMESH_Actor::eVolumes;
+ myVolumesTB->setChecked( hasVolumes );
+ if ( hasVolumes )
+ myNbCheckedButtons++;
+ connect( myVolumesTB, SIGNAL(toggled(bool)), this, SLOT(onChangeEntityMode(bool) ) );
+ QLabel* nbVolumesLab = new QLabel( QString("%1").arg(nbElements).toLatin1().data(), anEntitiesGrp );
+ hl->addWidget( myVolumesTB, 3, 0 );
+ hl->addWidget( nbVolumesLab, 3, 1 );
+ myVolumesTB->setEnabled( nbElements );
+ nbVolumesLab->setEnabled( nbElements );
+
+ // Balls
+ nbElements = myActor ? myActor->GetObject()->GetNbEntities( SMDSAbs_Ball ) : aMesh->NbBalls();
+ myBallsTB = new QCheckBox( tr("SMESH_BALLS"), anEntitiesGrp );
+ myBallsTB->setIcon( QIcon( aResMgr->loadPixmap( "SMESH", tr( "ICON_DLG_BALL" ) ) ) );
+ bool hasBalls = myEntityMode & SMESH_Actor::eBallElem;
+ myBallsTB->setChecked( hasBalls );
+ if ( hasBalls )
+ myNbCheckedButtons++;
+ connect( myBallsTB, SIGNAL(toggled(bool)), this, SLOT(onChangeEntityMode(bool)) );
+ QLabel* nbBallsLab = new QLabel( QString("%1").arg(nbElements).toLatin1().data(), anEntitiesGrp );
+ hl->addWidget( myBallsTB, 4, 0 );
+ hl->addWidget( nbBallsLab, 4, 1 );
+ myBallsTB->setEnabled( nbElements );
+ nbBallsLab->setEnabled( nbElements );
+
+ QVBoxLayout* aDlgLay = new QVBoxLayout( mainFrame() );
+ aDlgLay->setMargin( 0 );
+ aDlgLay->setSpacing( SPACING );
+ aDlgLay->addWidget( anEntitiesGrp );
+
+ button( OK )->setText( tr( "SMESH_BUT_OK" ) );
+
+ connect( this, SIGNAL( dlgHelp() ), this, SLOT( onHelp() ) );
+ connect( this, SIGNAL( dlgOk() ), this, SLOT( onOk() ) );
+}
+
+/*
+ \brief Destructor: clean-up resources if necessary
+*/
+SMESHGUI_DisplayEntitiesDlg::~SMESHGUI_DisplayEntitiesDlg()
+{
+}
+
+void SMESHGUI_DisplayEntitiesDlg::InverseEntityMode(unsigned int& theOutputMode,
+ unsigned int theMode)
+{
+ bool anIsNotPresent = ~theOutputMode & theMode;
+ if(anIsNotPresent)
+ theOutputMode |= theMode;
+ else
+ theOutputMode &= ~theMode;
+}
+
+/*!
+ \brief Slot for changing entities state
+*/
+void SMESHGUI_DisplayEntitiesDlg::onChangeEntityMode( bool isChecked )
+{
+ QCheckBox* aSender = (QCheckBox*)sender();
+ if ( myNbCheckedButtons == 1 && !isChecked ) {
+ SUIT_MessageBox::warning(this, tr("SMESH_WRN_WARNING"),
+ tr("WRN_AT_LEAST_ONE"));
+ disconnect( aSender, SIGNAL(toggled(bool)), this, SLOT(onChangeEntityMode(bool)) );
+ aSender->setChecked( true );
+ connect( aSender, SIGNAL(toggled(bool)), this, SLOT(onChangeEntityMode(bool)) );
+ return;
+ }
+ if ( my0DElemsTB == aSender )
+ InverseEntityMode( myEntityMode, SMESH_Actor::e0DElements );
+ else if ( myEdgesTB == aSender )
+ InverseEntityMode( myEntityMode, SMESH_Actor::eEdges );
+ else if ( myFacesTB == aSender )
+ InverseEntityMode( myEntityMode, SMESH_Actor::eFaces );
+ else if ( myVolumesTB == aSender )
+ InverseEntityMode( myEntityMode, SMESH_Actor::eVolumes );
+ else if ( myBallsTB == aSender )
+ InverseEntityMode( myEntityMode, SMESH_Actor::eBallElem );
+
+ isChecked ? myNbCheckedButtons++ : myNbCheckedButtons--;
+
+}
+
+/*!
+ \brief Show online help on dialog box
+*/
+void SMESHGUI_DisplayEntitiesDlg::onHelp()
+{
+ LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
+ app->onHelpContextModule( "SMESH", "display_entity_page.html" );
+}
+
+/*!
+ \brief Display or update the mesh in the 3D view with selected entity mode
+*/
+void SMESHGUI_DisplayEntitiesDlg::onOk()
+{
+ const char* entry = myIObject->getEntry();
+
+ if ( !myActor ) {
+ myActor = SMESH::CreateActor(SMESH::GetActiveStudyDocument(),
+ entry, true);
+ }
+
+ if( myEntityMode != myActor->GetEntityMode() ) {
+ myActor->SetEntityMode(myEntityMode);
+ SUIT_ViewWindow* wnd = SMESH::GetActiveWindow();
+ SMESH::DisplayActor( wnd, myActor );
+ SUIT_DataOwnerPtrList aList;
+ aList.append( new LightApp_DataOwner( entry ) );
+ SMESHGUI::selectionMgr()->setSelected( aList, false );
+ SMESH::UpdateView( wnd, SMESH::eDisplay, entry );
+ }
+}
diff --git a/src/SMESHGUI/SMESHGUI_DisplayEntitiesDlg.h b/src/SMESHGUI/SMESHGUI_DisplayEntitiesDlg.h
new file mode 100644
index 000000000..4b36a6b25
--- /dev/null
+++ b/src/SMESHGUI/SMESHGUI_DisplayEntitiesDlg.h
@@ -0,0 +1,61 @@
+// Copyright (C) 2014 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File : SMESHGUI_DisplayEntitiesDlg.h
+// Author : Alexander KOVALEV, Open CASCADE S.A.S. (alexander.kovalev@opencascade.com)
+
+#ifndef SMESHGUI_DISPLAYENTITIES_H
+#define SMESHGUI_DISPLAYENTITIES_H
+
+#include "SMESHGUI_Dialog.h"
+#include "SMESH_SMESHGUI.hxx"
+
+#include
+
+class QCheckBox;
+
+class SMESHGUI_EXPORT SMESHGUI_DisplayEntitiesDlg : public SMESHGUI_Dialog
+{
+ Q_OBJECT
+
+public:
+ SMESHGUI_DisplayEntitiesDlg( QWidget* parent );
+ ~SMESHGUI_DisplayEntitiesDlg();
+
+private:
+ void InverseEntityMode( unsigned int& theOutputMode,
+ unsigned int theMode );
+
+private slots:
+ void onOk();
+ void onHelp();
+ void onChangeEntityMode( bool isChecked );
+
+private:
+ Handle(SALOME_InteractiveObject) myIObject;
+ unsigned int myEntityMode;
+ SMESH_Actor *myActor;
+ int myNbCheckedButtons;
+ QCheckBox* my0DElemsTB;
+ QCheckBox* myEdgesTB;
+ QCheckBox* myFacesTB;
+ QCheckBox* myVolumesTB;
+ QCheckBox* myBallsTB;
+};
+
+#endif // SMESHGUI_DISPLAYENTITIES_H
diff --git a/src/SMESHGUI/SMESHGUI_DuplicateNodesDlg.cxx b/src/SMESHGUI/SMESHGUI_DuplicateNodesDlg.cxx
index ad4997644..57428add2 100644
--- a/src/SMESHGUI/SMESHGUI_DuplicateNodesDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_DuplicateNodesDlg.cxx
@@ -48,7 +48,6 @@
#include
#include
-#include
// Qt includes
#include
diff --git a/src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx b/src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx
index 5dba32360..798b6b9eb 100644
--- a/src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx
@@ -860,7 +860,7 @@ void SMESHGUI_ExtrusionDlg::SelectionIntoArgument()
else
return;
} else {
- // get indices of selcted elements
+ // get indices of selected elements
TColStd_IndexedMapOfInteger aMapIndex;
mySelector->GetIndex(IO,aMapIndex);
aNbElements = aMapIndex.Extent();
diff --git a/src/SMESHGUI/SMESHGUI_FilterDlg.cxx b/src/SMESHGUI/SMESHGUI_FilterDlg.cxx
index 8409afa4a..8db0a7814 100755
--- a/src/SMESHGUI/SMESHGUI_FilterDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_FilterDlg.cxx
@@ -62,8 +62,6 @@
#include
#include
-#include
-#include
#include
@@ -1956,7 +1954,10 @@ void SMESHGUI_FilterTable::onCriterionChanged (const int row, const int col, con
break;
}
case 3: {
+ int oldValue = aCompareItem->value();
aCompareItem->setItems(getCompare());
+ if ( oldValue >= 0 )
+ aCompareItem->setValue( oldValue );
break;
}
}
diff --git a/src/SMESHGUI/SMESHGUI_GEOMGenUtils.cxx b/src/SMESHGUI/SMESHGUI_GEOMGenUtils.cxx
index 88b181944..5453a6a1b 100644
--- a/src/SMESHGUI/SMESHGUI_GEOMGenUtils.cxx
+++ b/src/SMESHGUI/SMESHGUI_GEOMGenUtils.cxx
@@ -82,20 +82,25 @@ namespace SMESH
return GEOM::GEOM_Object::_nil();
}
- GEOM::GEOM_Object_ptr GetGeom (_PTR(SObject) theSO)
+ GEOM::GEOM_Object_var GetGeom (_PTR(SObject) theSO)
{
+ GEOM::GEOM_Object_var aMeshShape;
if (!theSO)
- return GEOM::GEOM_Object::_nil();
+ return aMeshShape;
+
+ CORBA::Object_var obj = _CAST( SObject,theSO )->GetObject();
+ aMeshShape = GEOM::GEOM_Object::_narrow( obj );
+ if ( !aMeshShape->_is_nil() )
+ return aMeshShape;
_PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
if (!aStudy)
- return GEOM::GEOM_Object::_nil();
+ return aMeshShape;
_PTR(ChildIterator) anIter (aStudy->NewChildIterator(theSO));
for ( ; anIter->More(); anIter->Next()) {
_PTR(SObject) aSObject = anIter->Value();
_PTR(SObject) aRefSOClient;
- GEOM::GEOM_Object_var aMeshShape;
if (aSObject->ReferencedObject(aRefSOClient)) {
SALOMEDS_SObject* aRefSO = _CAST(SObject,aRefSOClient);
@@ -104,11 +109,10 @@ namespace SMESH
SALOMEDS_SObject* aSO = _CAST(SObject,aSObject);
aMeshShape = GEOM::GEOM_Object::_narrow(aSO->GetObject());
}
-
- if (!aMeshShape->_is_nil())
- return aMeshShape._retn();
+ if ( !aMeshShape->_is_nil() )
+ return aMeshShape;
}
- return GEOM::GEOM_Object::_nil();
+ return aMeshShape;
}
SMESHGUI_EXPORT char* GetGeomName( _PTR(SObject) smeshSO )
diff --git a/src/SMESHGUI/SMESHGUI_GEOMGenUtils.h b/src/SMESHGUI/SMESHGUI_GEOMGenUtils.h
index f9cdeafd4..0aa10bd7a 100644
--- a/src/SMESHGUI/SMESHGUI_GEOMGenUtils.h
+++ b/src/SMESHGUI/SMESHGUI_GEOMGenUtils.h
@@ -47,7 +47,7 @@ namespace SMESH
SMESHGUI_EXPORT GEOM::GEOM_Object_var GetShapeOnMeshOrSubMesh( _PTR(SObject), bool* isMesh=0 );
- SMESHGUI_EXPORT GEOM::GEOM_Object_ptr GetGeom( _PTR(SObject) );
+ SMESHGUI_EXPORT GEOM::GEOM_Object_var GetGeom( _PTR(SObject) );
SMESHGUI_EXPORT char* GetGeomName( _PTR(SObject) smeshSO );
diff --git a/src/SMESHGUI/SMESHGUI_GroupDlg.cxx b/src/SMESHGUI/SMESHGUI_GroupDlg.cxx
index 60095ebe2..7cad33071 100644
--- a/src/SMESHGUI/SMESHGUI_GroupDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_GroupDlg.cxx
@@ -61,7 +61,6 @@
#include
#include
-#include
#include
diff --git a/src/SMESHGUI/SMESHGUI_GroupOpDlg.cxx b/src/SMESHGUI/SMESHGUI_GroupOpDlg.cxx
index 33a4720ea..bbebee448 100644
--- a/src/SMESHGUI/SMESHGUI_GroupOpDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_GroupOpDlg.cxx
@@ -59,7 +59,6 @@
#include
#include
#include
-#include
#include
#include
diff --git a/src/SMESHGUI/SMESHGUI_Hypotheses.cxx b/src/SMESHGUI/SMESHGUI_Hypotheses.cxx
index af1377aba..630100e71 100644
--- a/src/SMESHGUI/SMESHGUI_Hypotheses.cxx
+++ b/src/SMESHGUI/SMESHGUI_Hypotheses.cxx
@@ -670,7 +670,7 @@ void SMESHGUI_HypothesisDlg::onHelp()
if (app) {
QString name = "SMESH";
if(myCreator) {
- QVariant pluginName = myCreator->property( PLUGIN_NAME );
+ QVariant pluginName = myCreator->property( SMESH::Plugin_Name() );
if( pluginName.isValid() ) {
QString rootDir = pluginName.toString() + "PLUGIN_ROOT_DIR";
QString varValue = QString( getenv(rootDir.toLatin1().constData()));
diff --git a/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx b/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx
index 379ed1b2b..fa29da180 100644
--- a/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx
+++ b/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx
@@ -128,7 +128,7 @@ namespace SMESH
}
else
{
- QObject::tr(QString("SMESH_HYP_%1").arg(theHypStatus).toLatin1().data());
+ aMsg += QObject::tr(QString("SMESH_HYP_%1").arg(theHypStatus).toLatin1().data());
if ( theHypStatus == SMESH::HYP_HIDDEN_ALGO ) { // PAL18501
CORBA::String_var hypType = theHyp->GetName();
@@ -469,7 +469,7 @@ namespace SMESH
// It is used to obtain plugin root dir environment variable
// in the SMESHGUI_HypothesisDlg class. Plugin root dir environment
// variable is used to display documentation.
- aCreator->setProperty(PLUGIN_NAME,aHypData->PluginName);
+ aCreator->setProperty(SMESH::Plugin_Name(),aHypData->PluginName);
}
}
}
@@ -511,10 +511,14 @@ namespace SMESH
return SMESH::SMESH_Hypothesis::_nil();
}
+
bool IsApplicable(const QString& aHypType,
GEOM::GEOM_Object_ptr theGeomObject,
const bool toCheckAll)
{
+ if ( getenv("NO_LIMIT_ALGO_BY_SHAPE")) // allow a workaround for a case if
+ return true; // IsApplicable() returns false due to a bug
+
HypothesisData* aHypData = GetHypothesisData(aHypType);
QString aServLib = aHypData->ServerLibName;
return SMESHGUI::GetSMESHGen()->IsApplicable( aHypType.toLatin1().data(),
diff --git a/src/SMESHGUI/SMESHGUI_HypothesesUtils.h b/src/SMESHGUI/SMESHGUI_HypothesesUtils.h
index 2841b7a7f..8768e0711 100644
--- a/src/SMESHGUI/SMESHGUI_HypothesesUtils.h
+++ b/src/SMESHGUI/SMESHGUI_HypothesesUtils.h
@@ -58,8 +58,6 @@ class SALOMEDSClient_SObject;
class algo_error_array;
-#define PLUGIN_NAME "PLUGIN_NAME"
-
namespace SMESH
{
SMESHGUI_EXPORT
@@ -119,6 +117,10 @@ namespace SMESH
SMESHGUI_EXPORT
QString GetMessageOnAlgoStateErrors( const algo_error_array& );
+
+ SMESHGUI_EXPORT
+ // name of proprty saving plug-in of a hypothesis
+ inline const char* Plugin_Name() { return "PLUGIN_NAME"; }
}
#endif // SMESHGUI_HYPOTHESESUTILS_H
diff --git a/src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.cxx b/src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.cxx
index 970500e69..2754b34a9 100644
--- a/src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.cxx
@@ -716,17 +716,17 @@ void SMESHGUI_MakeNodeAtPointOp::redisplayPreview()
myDlg->myDestinationZ->SetValue(z);
}
if ( myDestCoordChanged ) {
- dx = myDlg->myDestinationX->GetValue() - myDlg->myCurrentX->GetValue();
- dy = myDlg->myDestinationY->GetValue() - myDlg->myCurrentY->GetValue();
- dz = myDlg->myDestinationZ->GetValue() - myDlg->myCurrentZ->GetValue();
+ dx = myDlg->myDestinationX->GetValue() - x;
+ dy = myDlg->myDestinationY->GetValue() - y;
+ dz = myDlg->myDestinationZ->GetValue() - z;
myDlg->myDestDX->SetValue(dx);
myDlg->myDestDY->SetValue(dy);
myDlg->myDestDZ->SetValue(dz);
}
else {
- dx = myDlg->myDestDX->GetValue() + myDlg->myCurrentX->GetValue();;
- dy = myDlg->myDestDY->GetValue() + myDlg->myCurrentY->GetValue();;
- dz = myDlg->myDestDZ->GetValue() + myDlg->myCurrentZ->GetValue();;
+ dx = myDlg->myDestDX->GetValue() + x;
+ dy = myDlg->myDestDY->GetValue() + y;
+ dz = myDlg->myDestDZ->GetValue() + z;
myDlg->myDestinationX->SetValue(dx);
myDlg->myDestinationY->SetValue(dy);
myDlg->myDestinationZ->SetValue(dz);
diff --git a/src/SMESHGUI/SMESHGUI_Measurements.cxx b/src/SMESHGUI/SMESHGUI_Measurements.cxx
index e00937aff..9f7c9bb26 100644
--- a/src/SMESHGUI/SMESHGUI_Measurements.cxx
+++ b/src/SMESHGUI/SMESHGUI_Measurements.cxx
@@ -36,7 +36,7 @@
#include
#include
#include
-#include
+#include
#include
#include
diff --git a/src/SMESHGUI/SMESHGUI_MeshDlg.cxx b/src/SMESHGUI/SMESHGUI_MeshDlg.cxx
index f3a2719d4..a381acde0 100644
--- a/src/SMESHGUI/SMESHGUI_MeshDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_MeshDlg.cxx
@@ -171,6 +171,7 @@ void SMESHGUI_MeshTab::addItem( const QString& txt, const int type, const int in
if ( type <= AddHyp )
{
myHypCombo[ type ]->addItem( txt, QVariant( index ));
+ myHypCombo[ type ]->setMaxVisibleItems( qMax( 10, myHypCombo[ type ]->count() ) );
}
else
{
diff --git a/src/SMESHGUI/SMESHGUI_MeshEditPreview.cxx b/src/SMESHGUI/SMESHGUI_MeshEditPreview.cxx
index ef9ac22ad..7f8b060c8 100644
--- a/src/SMESHGUI/SMESHGUI_MeshEditPreview.cxx
+++ b/src/SMESHGUI/SMESHGUI_MeshEditPreview.cxx
@@ -126,8 +126,9 @@ vtkIdType getCellType( const SMDSAbs_ElementType theType,
{
switch( theType )
{
+ case SMDSAbs_Ball: return VTK_VERTEX;
case SMDSAbs_Node: return VTK_VERTEX;
- case SMDSAbs_Edge:
+ case SMDSAbs_Edge:
if( theNbNodes == 2 ) return VTK_LINE;
else if ( theNbNodes == 3 ) return VTK_QUADRATIC_EDGE;
else return VTK_EMPTY_CELL;
diff --git a/src/SMESHGUI/SMESHGUI_MeshInfo.cxx b/src/SMESHGUI/SMESHGUI_MeshInfo.cxx
index 2dca23bba..e91afa388 100644
--- a/src/SMESHGUI/SMESHGUI_MeshInfo.cxx
+++ b/src/SMESHGUI/SMESHGUI_MeshInfo.cxx
@@ -506,8 +506,9 @@ void SMESHGUI_MeshInfo::showInfo( SMESH::SMESH_IDSource_ptr obj )
long nb2DLinear = info[SMDSEntity_Triangle] + info[SMDSEntity_Quadrangle] + info[SMDSEntity_Polygon];
long nb2DQuadratic = info[SMDSEntity_Quad_Triangle] + info[SMDSEntity_Quad_Quadrangle];
long nb2DBiQuadratic = info[SMDSEntity_BiQuad_Triangle] + info[SMDSEntity_BiQuad_Quadrangle];
+ long nb2DTotal = nb2DLinear + nb2DQuadratic + nb2DBiQuadratic;
- myWidgets[i2D][iTotal] ->setProperty( "text", QString::number( nb2DLinear + nb2DQuadratic ));
+ myWidgets[i2D][iTotal] ->setProperty( "text", QString::number( nb2DTotal ));
myWidgets[i2D][iLinear] ->setProperty( "text", QString::number( nb2DLinear ) );
myWidgets[i2D][iQuadratic] ->setProperty( "text", QString::number( nb2DQuadratic ) );
myWidgets[i2D][iBiQuadratic] ->setProperty( "text", QString::number( nb2DBiQuadratic ) );
@@ -524,10 +525,11 @@ void SMESHGUI_MeshInfo::showInfo( SMESH::SMESH_IDSource_ptr obj )
long nbHexahedrons = info[SMDSEntity_Hexa] + info[SMDSEntity_Quad_Hexa] + info[SMDSEntity_TriQuad_Hexa];
long nbPyramids = info[SMDSEntity_Pyramid] + info[SMDSEntity_Quad_Pyramid];
long nbPrisms = info[SMDSEntity_Penta] + info[SMDSEntity_Quad_Penta];
- long nb3DLinear = info[SMDSEntity_Tetra] + info[SMDSEntity_Hexa] + info[SMDSEntity_Pyramid] + info[SMDSEntity_Penta] + info[SMDSEntity_Polyhedra] + info[SMDSEntity_Hexagonal_Prism];
+ long nb3DLinear = info[SMDSEntity_Tetra] + info[SMDSEntity_Hexa] + info[SMDSEntity_Pyramid] + info[SMDSEntity_Penta] + info[SMDSEntity_Polyhedra] + info[SMDSEntity_Hexagonal_Prism];
long nb3DQuadratic = info[SMDSEntity_Quad_Tetra] + info[SMDSEntity_Quad_Hexa] + info[SMDSEntity_Quad_Pyramid] + info[SMDSEntity_Quad_Penta];
long nb3DBiQuadratic = info[SMDSEntity_TriQuad_Hexa];
- myWidgets[i3D][iTotal] ->setProperty( "text", QString::number( nb3DLinear + nb3DQuadratic ) );
+ long nb3DTotal = nb3DLinear + nb3DQuadratic + nb3DBiQuadratic;
+ myWidgets[i3D][iTotal] ->setProperty( "text", QString::number( nb3DTotal ) );
myWidgets[i3D][iLinear] ->setProperty( "text", QString::number( nb3DLinear ) );
myWidgets[i3D][iQuadratic] ->setProperty( "text", QString::number( nb3DQuadratic ) );
myWidgets[i3D][iBiQuadratic] ->setProperty( "text", QString::number( nb3DBiQuadratic ) );
@@ -546,7 +548,7 @@ void SMESHGUI_MeshInfo::showInfo( SMESH::SMESH_IDSource_ptr obj )
myWidgets[i3DPrisms][iQuadratic] ->setProperty( "text", QString::number( info[SMDSEntity_Quad_Penta] ) );
myWidgets[i3DHexaPrisms][iTotal] ->setProperty( "text", QString::number( info[SMDSEntity_Hexagonal_Prism] ) );
myWidgets[i3DPolyhedrons][iTotal] ->setProperty( "text", QString::number( info[SMDSEntity_Polyhedra] ) );
- long nbElemTotal = info[SMDSEntity_0D] + info[SMDSEntity_Ball] + nbEdges + nb2DLinear + nb2DQuadratic + nb2DBiQuadratic + nb3DLinear + nb3DQuadratic + nb3DBiQuadratic;
+ long nbElemTotal = info[SMDSEntity_0D] + info[SMDSEntity_Ball] + nbEdges + nb2DTotal + nb3DTotal;
long nbElemLinerial = info[SMDSEntity_Edge] + nb2DLinear + nb3DLinear;
long nbElemQuadratic = info[SMDSEntity_Quad_Edge] + nb2DQuadratic + nb3DQuadratic;
long nbElemBiQuadratic = nb2DBiQuadratic + nb3DBiQuadratic;
diff --git a/src/SMESHGUI/SMESHGUI_MeshOp.cxx b/src/SMESHGUI/SMESHGUI_MeshOp.cxx
index ab8b437a6..cdb3bc919 100644
--- a/src/SMESHGUI/SMESHGUI_MeshOp.cxx
+++ b/src/SMESHGUI/SMESHGUI_MeshOp.cxx
@@ -26,15 +26,15 @@
#include "SMESHGUI_MeshOp.h"
#include "SMESHGUI.h"
-#include "SMESHGUI_MeshDlg.h"
-#include "SMESHGUI_ShapeByMeshDlg.h"
-#include "SMESHGUI_HypothesesUtils.h"
-#include "SMESHGUI_Hypotheses.h"
-#include "SMESHGUI_Utils.h"
#include "SMESHGUI_GEOMGenUtils.h"
-
-#include
-#include
+#include "SMESHGUI_Hypotheses.h"
+#include "SMESHGUI_HypothesesUtils.h"
+#include "SMESHGUI_MeshDlg.h"
+#include "SMESHGUI_Operations.h"
+#include "SMESHGUI_ShapeByMeshDlg.h"
+#include "SMESHGUI_Utils.h"
+#include "SMESH_NumberFilter.hxx"
+#include "SMESH_TypeFilter.hxx"
// SALOME GEOM includes
#include
@@ -247,8 +247,9 @@ void SMESHGUI_MeshOp::startOperation()
myDlg->activateObject( myIsMesh ? SMESHGUI_MeshDlg::Geom : SMESHGUI_MeshDlg::Mesh );
}
else
+ {
myDlg->activateObject( SMESHGUI_MeshDlg::Obj );
-
+ }
myDlg->setCurrentTab( SMESH::DIM_3D );
QStringList TypeMeshList;
@@ -363,15 +364,39 @@ bool SMESHGUI_MeshOp::isSubshapeOk() const
// skl for NPAL14695 - implementation of searching of mainObj
GEOM::GEOM_Object_var mainObj = op->GetMainShape(aSubGeomVar); /* _var not _wrap as
mainObj already exists! */
- while(1) {
- if (mainObj->_is_nil())
- return false;
+ while( !mainObj->_is_nil()) {
CORBA::String_var entry1 = mainObj->GetEntry();
CORBA::String_var entry2 = mainGeom->GetEntry();
if (std::string( entry1.in() ) == entry2.in() )
return true;
mainObj = op->GetMainShape(mainObj);
}
+ if ( aSubGeomVar->GetShapeType() == GEOM::COMPOUND )
+ {
+ // is aSubGeomVar a compound of sub-shapes?
+ GEOM::GEOM_IShapesOperations_wrap sop = geomGen->GetIShapesOperations(aStudy->StudyId());
+ if (sop->_is_nil()) return false;
+ GEOM::ListOfLong_var ids = sop->GetAllSubShapesIDs( aSubGeomVar,
+ GEOM::SHAPE,/*sorted=*/false);
+ if ( ids->length() > 0 )
+ {
+ ids->length( 1 );
+ GEOM::GEOM_Object_var compSub = geomGen->AddSubShape( aSubGeomVar, ids );
+ if ( !compSub->_is_nil() )
+ {
+ GEOM::ListOfGO_var shared = sop->GetSharedShapes( mainGeom,
+ compSub,
+ compSub->GetShapeType() );
+ geomGen->RemoveObject( compSub );
+ compSub->UnRegister();
+ if ( shared->length() > 0 ) {
+ geomGen->RemoveObject( shared[0] );
+ shared[0]->UnRegister();
+ }
+ return ( shared->length() > 0 );
+ }
+ }
+ }
}
}
@@ -380,8 +405,8 @@ bool SMESHGUI_MeshOp::isSubshapeOk() const
//================================================================================
/*!
- * \brief Return name of the algorithm that does not support submeshes and makes
- * submesh creation useless
+ * \brief Return name of the algorithm that does not support sub-meshes and makes
+ * sub-mesh creation useless
* \retval char* - string is to be deleted!!!
*/
//================================================================================
@@ -847,7 +872,7 @@ void SMESHGUI_MeshOp::availableHyps( const int theDim,
theDataList.clear();
theHyps.clear();
bool isAlgo = ( theHypType == Algo );
- bool isAux = ( theHypType == AddHyp );
+ bool isAux = ( theHypType >= AddHyp );
QStringList aHypTypeNameList = SMESH::GetAvailableHypotheses( isAlgo, theDim, isAux, myIsOnGeometry, !myIsMesh );
QStringList::const_iterator anIter;
@@ -906,7 +931,7 @@ void SMESHGUI_MeshOp::existingHyps( const int theDim,
else
aPart = theHypType == Algo ? SMESH::Tag_AlgorithmsRoot : SMESH::Tag_HypothesisRoot;
- const bool isAux = ( theHypType == AddHyp );
+ const bool isAux = ( theHypType >= AddHyp );
const bool allHyps = ( !isMesh && theHypType != Algo && theDim > -1);
if ( theFather->FindSubObject( aPart, aHypRoot ) )
@@ -1489,14 +1514,24 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
{
if ( !isAccessibleDim( dim ))
continue;
- for ( int dlgType = MainHyp; dlgType < nbDlgHypTypes(dim); dlgType++ )
+
+ // get indices of selected hyps
+ const int nbTypes = nbDlgHypTypes(dim);
+ std::vector hypIndexByType( nbTypes, -1 );
+ for ( int dlgType = MainHyp; dlgType < nbTypes; dlgType++ )
+ {
+ hypIndexByType[ dlgType ] = currentHyp( dim, dlgType );
+ }
+
+ // update hyps
+ for ( int dlgType = MainHyp; dlgType < nbTypes; dlgType++ )
{
const int type = Min( dlgType, AddHyp );
myAvailableHypData[ dim ][ type ].clear();
QStringList anAvailable, anExisting;
HypothesisData* curAlgo = algoByDim[ dim ];
- int hypIndex = currentHyp( dim, dlgType );
+ int hypIndex = hypIndexByType[ dlgType ];
SMESH::SMESH_Hypothesis_var curHyp;
if ( hypIndex >= 0 && hypIndex < myExistingHyps[ dim ][ type ].count() )
@@ -1535,24 +1570,26 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
defaulHypAvlbl = (type == MainHyp && !curAlgo->IsAuxOrNeedHyp );
}
// set list of hypotheses
- myDlg->tab( dim )->setAvailableHyps( type, anAvailable );
- myDlg->tab( dim )->setExistingHyps( type, anExisting, defaulHypAvlbl );
-
+ if ( dlgType <= AddHyp )
+ {
+ myDlg->tab( dim )->setAvailableHyps( type, anAvailable );
+ myDlg->tab( dim )->setExistingHyps( type, anExisting, defaulHypAvlbl );
+ }
// set current existing hypothesis
if ( !curHyp->_is_nil() && !anExisting.isEmpty() )
hypIndex = this->find( curHyp, myExistingHyps[ dim ][ type ]);
else
hypIndex = -1;
- if ( !isSubmesh && hypIndex < 0 && anExisting.count() == 1 ) {
+ if ( !isSubmesh && myToCreate && hypIndex < 0 && anExisting.count() == 1 ) {
// none is yet selected => select the sole existing if it is not optional
CORBA::String_var hypTypeName = myExistingHyps[ dim ][ type ].first().first->GetName();
bool isOptional = true;
if ( algoByDim[ dim ] &&
- SMESH::IsAvailableHypothesis( algoByDim[ dim ], hypTypeName.in(), isOptional ) &&
- !isOptional )
+ SMESH::IsAvailableHypothesis( algoByDim[ dim ], hypTypeName.in(), isOptional ) &&
+ !isOptional )
hypIndex = 0;
}
- setCurrentHyp( dim, type, hypIndex );
+ setCurrentHyp( dim, dlgType, hypIndex );
}
}
}
@@ -2371,7 +2408,7 @@ bool SMESHGUI_MeshOp::checkSubMeshConcurrency(SMESH::SMESH_Mesh_ptr mesh,
myDlg->setEnabled( false ); // disactivate selection
selectionMgr()->clearFilters();
selectObject( meshSO );
- SMESHGUI::GetSMESHGUI()->OnGUIEvent( 713 ); // MESH_ORDER
+ SMESHGUI::GetSMESHGUI()->OnGUIEvent( SMESHOp::OpMeshOrder ); // MESH_ORDER
qApp->processEvents();
myDlg->setEnabled( true );
@@ -2578,11 +2615,11 @@ void SMESHGUI_MeshOp::setFilteredAlgoData( const int theTabIndex, const int theI
bool toCheckIsApplicableToAll = !myIsMesh;
GEOM::GEOM_Object_var aGeomVar;
- QString anEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
+ QString anEntry =
+ myDlg->selectedObject( myToCreate ? SMESHGUI_MeshDlg::Geom : SMESHGUI_MeshDlg::Obj );
if ( _PTR(SObject) so = studyDS()->FindObjectID( anEntry.toLatin1().data() ))
{
- CORBA::Object_var obj = _CAST( SObject,so )->GetObject();
- aGeomVar = GEOM::GEOM_Object::_narrow( obj );
+ aGeomVar = SMESH::GetGeom( so );
if ( !aGeomVar->_is_nil() && toCheckIsApplicableToAll )
toCheckIsApplicableToAll = ( aGeomVar->GetType() == GEOM_GROUP );
}
diff --git a/src/SMESHGUI/SMESHGUI_MultiEditDlg.cxx b/src/SMESHGUI/SMESHGUI_MultiEditDlg.cxx
index b2fdc8bdd..e42a8389d 100755
--- a/src/SMESHGUI/SMESHGUI_MultiEditDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_MultiEditDlg.cxx
@@ -53,7 +53,6 @@
#include
#include
#include
-#include
#include
#include
diff --git a/src/SMESHGUI/SMESHGUI_Operations.h b/src/SMESHGUI/SMESHGUI_Operations.h
index 0d1cfe56a..18c28a441 100644
--- a/src/SMESHGUI/SMESHGUI_Operations.h
+++ b/src/SMESHGUI/SMESHGUI_Operations.h
@@ -200,7 +200,8 @@ namespace SMESHOp {
OpDEFaces = 6042, // POPUP MENU - DISPLAY ENTITY - FACES
OpDEVolumes = 6043, // POPUP MENU - DISPLAY ENTITY - VOLUMES
OpDEBalls = 6044, // POPUP MENU - DISPLAY ENTITY - BALLS
- OpDEAllEntity = 6045, // POPUP MENU - DISPLAY ENTITY - ALL ENTITY
+ OpDEAllEntity = 6045, // POPUP MENU - DISPLAY ENTITY - ALL ENTITIES
+ OpDEChoose = 6046, // POPUP MENU - DISPLAY ENTITY - CHOOSE ENTITIES
// Representation -----------------//--------------------------------
OpRepresentationLines = 6050, // POPUP MENU - 2D QUADRATIC - LINES
OpRepresentationArcs = 6051, // POPUP MENU - 2D QUADRATIC - ARCS
diff --git a/src/SMESHGUI/SMESHGUI_ReorientFacesDlg.cxx b/src/SMESHGUI/SMESHGUI_ReorientFacesDlg.cxx
index 41e341cca..064df3909 100644
--- a/src/SMESHGUI/SMESHGUI_ReorientFacesDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_ReorientFacesDlg.cxx
@@ -46,7 +46,6 @@
// SALOME GUI includes
#include
#include
-#include
#include
#include
#include
diff --git a/src/SMESHGUI/SMESHGUI_RotationDlg.cxx b/src/SMESHGUI/SMESHGUI_RotationDlg.cxx
index 936a228c1..1a9724012 100644
--- a/src/SMESHGUI/SMESHGUI_RotationDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_RotationDlg.cxx
@@ -52,7 +52,6 @@
#include
#include
#include
-#include
// SALOME KERNEL includes
#include
diff --git a/src/SMESHGUI/SMESHGUI_ScaleDlg.cxx b/src/SMESHGUI/SMESHGUI_ScaleDlg.cxx
index 9da433c69..e07177bf1 100644
--- a/src/SMESHGUI/SMESHGUI_ScaleDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_ScaleDlg.cxx
@@ -49,7 +49,6 @@
#include
#include
#include
-#include
// SALOME KERNEL includes
#include
diff --git a/src/SMESHGUI/SMESHGUI_Selection.cxx b/src/SMESHGUI/SMESHGUI_Selection.cxx
index 80ca03466..94331c901 100644
--- a/src/SMESHGUI/SMESHGUI_Selection.cxx
+++ b/src/SMESHGUI/SMESHGUI_Selection.cxx
@@ -80,8 +80,10 @@ void SMESHGUI_Selection::init( const QString& client, LightApp_SelectionMgr* mgr
return;
_PTR(Study) aStudy = aSStudy->studyDS();
- for( int i=0, n=count(); i 0 ) {
+ QString mode = myControls[0];
+ for( int ind = 1; ind < myControls.count(); ind++ ) {
+ if( mode != myControls[ind] )
+ return "eNone";
+ }
+ return mode;
+ }
+ return "eNone";
+}
+
bool SMESHGUI_Selection::isNumFunctor( int ind ) const
{
bool result = false;
diff --git a/src/SMESHGUI/SMESHGUI_Selection.h b/src/SMESHGUI/SMESHGUI_Selection.h
index 0a9d46ccc..3ba1bf4cb 100644
--- a/src/SMESHGUI/SMESHGUI_Selection.h
+++ b/src/SMESHGUI/SMESHGUI_Selection.h
@@ -49,6 +49,7 @@ public:
virtual void init( const QString&, LightApp_SelectionMgr* );
virtual QVariant parameter( const int, const QString& ) const;
+ virtual QVariant parameter( const QString& ) const;
virtual bool processOwner( const LightApp_DataOwner* );
// got from object, not from actor
@@ -74,6 +75,7 @@ public:
virtual QString shrinkMode( int ) const;
virtual QList entityMode( int ) const;
virtual QString controlMode( int ) const;
+ virtual QString controlMode() const;
virtual bool isNumFunctor( int ) const;
virtual QString facesOrientationMode( int ) const;
virtual QString groupType( int ) const;
@@ -87,6 +89,7 @@ public:
private:
QStringList myTypes;
+ QStringList myControls;
QList myActors;
};
diff --git a/src/SMESHGUI/SMESHGUI_SelectionOp.cxx b/src/SMESHGUI/SMESHGUI_SelectionOp.cxx
index 0c8486ed2..daf2bf493 100644
--- a/src/SMESHGUI/SMESHGUI_SelectionOp.cxx
+++ b/src/SMESHGUI/SMESHGUI_SelectionOp.cxx
@@ -43,7 +43,6 @@
#include
#include
-#include
// SALOME KERNEL includes
#include
@@ -428,7 +427,7 @@ void SMESHGUI_SelectionOp::selected( QStringList& names,
{
_PTR(SObject) obj = _study->studyDS()->FindObjectID( anIt.Value()->getEntry() );
if( obj )
- names.append( obj->GetName().c_str() );
+ names.append( QString( obj->GetName().c_str() ).trimmed() );
}
}
}
diff --git a/src/SMESHGUI/SMESHGUI_SmoothingDlg.cxx b/src/SMESHGUI/SMESHGUI_SmoothingDlg.cxx
index 7e1d8d051..6fcc47a41 100644
--- a/src/SMESHGUI/SMESHGUI_SmoothingDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_SmoothingDlg.cxx
@@ -596,20 +596,21 @@ void SMESHGUI_SmoothingDlg::SelectionIntoArgument()
if (myNbOkElements < 1)
return;
-
+
QStringList elements;
for ( int i = 0; i < myNbOkElements; ++i )
elements << QString::number( aMapIndex( i+1 ) );
aString = elements.join(" ");
}
- } else if (myEditCurrentArgument == LineEditNodes && !myMesh->_is_nil() && myIO == IO ) {
+ } else if (myEditCurrentArgument == LineEditNodes && !myMesh->_is_nil() && myIO->isSame(IO) )
+ {
myNbOkNodes = SMESH::GetNameOfSelectedNodes(mySelector, IO, aString);
}
myEditCurrentArgument->setText(aString);
myEditCurrentArgument->repaint();
myEditCurrentArgument->setEnabled(false); // to update lineedit IPAL 19809
- myEditCurrentArgument->setEnabled(true);
+ myEditCurrentArgument->setEnabled(true);
if (myNbOkElements && (myNbOkNodes || LineEditNodes->text().trimmed().isEmpty())) {
buttonOk->setEnabled(true);
diff --git a/src/SMESHGUI/SMESHGUI_SymmetryDlg.cxx b/src/SMESHGUI/SMESHGUI_SymmetryDlg.cxx
index c887edf84..2a014f21e 100644
--- a/src/SMESHGUI/SMESHGUI_SymmetryDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_SymmetryDlg.cxx
@@ -52,7 +52,6 @@
#include
#include
#include
-#include
// SALOME KERNEL includes
#include
diff --git a/src/SMESHGUI/SMESHGUI_TranslationDlg.cxx b/src/SMESHGUI/SMESHGUI_TranslationDlg.cxx
index e4bf823f8..ae7adcfa0 100644
--- a/src/SMESHGUI/SMESHGUI_TranslationDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_TranslationDlg.cxx
@@ -52,7 +52,6 @@
#include
#include
#include
-#include
// SALOME KERNEL includes
#include
diff --git a/src/SMESHGUI/SMESHGUI_TransparencyDlg.cxx b/src/SMESHGUI/SMESHGUI_TransparencyDlg.cxx
index 58b52c670..6c1370943 100644
--- a/src/SMESHGUI/SMESHGUI_TransparencyDlg.cxx
+++ b/src/SMESHGUI/SMESHGUI_TransparencyDlg.cxx
@@ -40,7 +40,6 @@
#include
#include
-#include
#include
#include
diff --git a/src/SMESHGUI/SMESHGUI_Utils.h b/src/SMESHGUI/SMESHGUI_Utils.h
index d5ec25ed4..5ac9ee97c 100644
--- a/src/SMESHGUI/SMESHGUI_Utils.h
+++ b/src/SMESHGUI/SMESHGUI_Utils.h
@@ -204,7 +204,7 @@ SMESHGUI_EXPORT
struct toQStr : public toStrT< QString > {
toQStr( char* s ): toStrT< QString >(s) {}
};
- class toStdStr : public toStrT< std::string > {
+ struct toStdStr : public toStrT< std::string > {
toStdStr( char* s ): toStrT< std::string >(s) {}
};
diff --git a/src/SMESHGUI/SMESHGUI_VTKUtils.cxx b/src/SMESHGUI/SMESHGUI_VTKUtils.cxx
index 6b67d5e9c..7ca3e9395 100644
--- a/src/SMESHGUI/SMESHGUI_VTKUtils.cxx
+++ b/src/SMESHGUI/SMESHGUI_VTKUtils.cxx
@@ -47,7 +47,6 @@
#include
#include
-#include
#include
#include
diff --git a/src/SMESHGUI/SMESHGUI_XmlHandler.cxx b/src/SMESHGUI/SMESHGUI_XmlHandler.cxx
index b5c53d4b5..cb27cf9b4 100644
--- a/src/SMESHGUI/SMESHGUI_XmlHandler.cxx
+++ b/src/SMESHGUI/SMESHGUI_XmlHandler.cxx
@@ -161,8 +161,9 @@ bool SMESHGUI_XmlHandler::startElement (const QString&, const QString&,
for ( int i = 0; i < NB_ATTRIBUTES; ++i ) {
QString aStr = atts.value( name[i] );
if ( !aStr.isEmpty() ) {
- aStr.remove( ' ' );
- attr[ i ] = aStr.split( ',', QString::SkipEmptyParts );
+ attr[i] = aStr.split( ',', QString::SkipEmptyParts );
+ for ( int j = 0; j < attr[i].count(); ++j )
+ attr[i][j] = attr[i][j].trimmed();
}
}
diff --git a/src/SMESHGUI/SMESH_images.ts b/src/SMESHGUI/SMESH_images.ts
index 80c04e7d6..7da6cad1a 100644
--- a/src/SMESHGUI/SMESH_images.ts
+++ b/src/SMESHGUI/SMESH_images.ts
@@ -255,6 +255,14 @@
ICON_DLG_TRIANGLE
mesh_triangle.png
+
+ ICON_DLG_CHOOSE
+ mesh_choose.png
+
+
+ ICON_DLG_CHOOSE_ALL
+ mesh_choose_all.png
+
ICON_EDIT_GROUP
mesh_edit_group.png
diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts
index fcb37740a..3f8a01c03 100644
--- a/src/SMESHGUI/SMESH_msg_en.ts
+++ b/src/SMESHGUI/SMESH_msg_en.ts
@@ -396,6 +396,10 @@
MEN_EDGES
Edges
+
+ MEN_CHOOSE
+ Choose...
+
MEN_EDIT
Edit
@@ -7805,4 +7809,11 @@ as they are of improper type:
Shrink coef:
+
+ SMESHGUI_DisplayEntitiesDlg
+
+ WRN_AT_LEAST_ONE
+ At least one entity type should be chosen!
+
+
diff --git a/src/SMESHGUI/SMESH_msg_fr.ts b/src/SMESHGUI/SMESH_msg_fr.ts
index f20d819eb..91596f776 100755
--- a/src/SMESHGUI/SMESH_msg_fr.ts
+++ b/src/SMESHGUI/SMESH_msg_fr.ts
@@ -396,6 +396,10 @@
MEN_EDGES
Arêtes
+
+ MEN_CHOOSE
+ Choose...
+
MEN_EDIT
Edition
@@ -7753,4 +7757,11 @@ en raison de leurs types incompatibles:
Coef de réduction:
+
+ SMESHGUI_DisplayEntitiesDlg
+
+ WRN_AT_LEAST_ONE
+ At least one entity type should be chosen!
+
+
diff --git a/src/SMESHGUI/SMESH_msg_ja.ts b/src/SMESHGUI/SMESH_msg_ja.ts
index 5d6e78d20..0332875cf 100644
--- a/src/SMESHGUI/SMESH_msg_ja.ts
+++ b/src/SMESHGUI/SMESH_msg_ja.ts
@@ -395,6 +395,10 @@
MEN_EDGES
エッジ
+
+ MEN_CHOOSE
+ Choose...
+
MEN_EDIT
編集(&E)
@@ -7687,4 +7691,11 @@
減少係数:
+
+ SMESHGUI_DisplayEntitiesDlg
+
+ WRN_AT_LEAST_ONE
+ At least one entity type should be chosen!
+
+
diff --git a/src/SMESHUtils/SMESH_TypeDefs.hxx b/src/SMESHUtils/SMESH_TypeDefs.hxx
index 9fec2e5bd..f5dedaec0 100644
--- a/src/SMESHUtils/SMESH_TypeDefs.hxx
+++ b/src/SMESHUtils/SMESH_TypeDefs.hxx
@@ -43,7 +43,8 @@ typedef std::map, TIDCompare > TElemOfElemListMap;
typedef std::map, TIDCompare > TElemOfNodeListMap;
-typedef std::map TNodeNodeMap;
+typedef std::map TNodeNodeMap;
//!< Set of elements sorted by ID, to be used to assure predictability of edition
typedef std::set< const SMDS_MeshElement*, TIDCompare > TIDSortedElemSet;
diff --git a/src/SMESH_I/SMESH_2smeshpy.cxx b/src/SMESH_I/SMESH_2smeshpy.cxx
index 564632744..911375f68 100644
--- a/src/SMESH_I/SMESH_2smeshpy.cxx
+++ b/src/SMESH_I/SMESH_2smeshpy.cxx
@@ -1793,10 +1793,29 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand )
list< Handle(_pyHypothesis) >::iterator hyp;
if ( !myLastComputeCmd.IsNull() )
{
- for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
- (*hyp)->ComputeDiscarded( myLastComputeCmd );
+ // check if the previously computed mesh has been edited,
+ // if so then we do not clear the previous Compute()
+ bool toClear = true;
+ if ( myLastComputeCmd->GetMethod() == "Compute" )
+ {
+ list< Handle(_pyMeshEditor)>::iterator e = myEditors.begin();
+ for ( ; e != myEditors.end() && toClear; ++e )
+ {
+ list< Handle(_pyCommand)>& cmds = (*e)->GetProcessedCmds();
+ list< Handle(_pyCommand) >::reverse_iterator cmd = cmds.rbegin();
+ if ( cmd != cmds.rend() &&
+ (*cmd)->GetOrderNb() > myLastComputeCmd->GetOrderNb() )
+ toClear = false;
+ }
+ }
+ if ( toClear )
+ {
+ // clear hyp commands called before myLastComputeCmd
+ for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
+ (*hyp)->ComputeDiscarded( myLastComputeCmd );
- myLastComputeCmd->Clear();
+ myLastComputeCmd->Clear();
+ }
}
myLastComputeCmd = theCommand;
@@ -1961,7 +1980,7 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand )
//
// remove "PartTo" from the method
TCollection_AsciiString newMethod = method;
- newMethod.Remove( 7, 6 );
+ newMethod.Remove( /*where=*/7, /*howmany=*/6 );
theCommand->SetMethod( newMethod );
// make the 1st arg be the last one (or last but three for ExportMED())
_pyID partID = theCommand->GetArg( 1 );
diff --git a/src/SMESH_I/SMESH_2smeshpy.hxx b/src/SMESH_I/SMESH_2smeshpy.hxx
index 4e6531dde..04352f24c 100644
--- a/src/SMESH_I/SMESH_2smeshpy.hxx
+++ b/src/SMESH_I/SMESH_2smeshpy.hxx
@@ -117,17 +117,17 @@ public:
_pyCommand( const _AString& theString, int theNb=-1 )
: myString( theString ), myOrderNb( theNb ) {};
_AString & GetString() { return myString; }
- int GetOrderNb() const { return myOrderNb; }
+ int GetOrderNb() const { return myOrderNb; }
void SetOrderNb( int theNb ) { myOrderNb = theNb; }
typedef void* TAddr;
TAddr GetAddress() const { return (void*) this; }
- int Length() const { return myString.Length(); }
+ int Length() const { return myString.Length(); }
void Clear() { myString.Clear(); myBegPos.Clear(); myArgs.Clear(); }
bool IsEmpty() const { return myString.IsEmpty(); }
_AString GetIndentation();
const _AString & GetResultValue();
int GetNbResultValues();
- const _AString& GetResultValue(int res);
+ const _AString & GetResultValue(int res);
const _AString & GetObject();
const _AString & GetMethod();
const _AString & GetArg( int index );
@@ -183,11 +183,11 @@ public:
const _pyID& GetID() { return myID.IsEmpty() ? myCreationCmd->GetResultValue() : myID; }
static _pyID FatherID(const _pyID & childID);
const Handle(_pyCommand)& GetCreationCmd() { return myCreationCmd; }
- int GetNbCalls() const { return myProcessedCmds.size(); }
+ int GetNbCalls() const { return myProcessedCmds.size(); }
bool IsInStudy() const { return myIsPublished; }
virtual void SetRemovedFromStudy(const bool isRemoved) { myIsPublished = !isRemoved; }
void SetCreationCmd( Handle(_pyCommand) cmd ) { myCreationCmd = cmd; }
- int GetCommandNb() { return myCreationCmd->GetOrderNb(); }
+ int GetCommandNb() { return myCreationCmd->GetOrderNb(); }
void AddProcessedCmd( const Handle(_pyCommand) & cmd )
{ if (myProcessedCmds.empty() || myProcessedCmds.back()!=cmd) myProcessedCmds.push_back( cmd );}
std::list< Handle(_pyCommand) >& GetProcessedCmds() { return myProcessedCmds; }
diff --git a/src/SMESH_I/SMESH_Filter_i.cxx b/src/SMESH_I/SMESH_Filter_i.cxx
index 0293f51a3..3d7977cb6 100644
--- a/src/SMESH_I/SMESH_Filter_i.cxx
+++ b/src/SMESH_I/SMESH_Filter_i.cxx
@@ -1550,8 +1550,8 @@ void ConnectedElements_i::SetThreshold ( const char*
if ( sobj->_is_nil() )
THROW_SALOME_CORBA_EXCEPTION
( "ConnectedElements_i::SetThreshold(): invalid vertex study entry", SALOME::BAD_PARAM );
- CORBA::Object_var obj = sobj->GetObject();
- GEOM::GEOM_Object_wrap vertex = GEOM::GEOM_Object::_narrow( obj );
+ CORBA::Object_var obj = sobj->GetObject();
+ GEOM::GEOM_Object_var vertex = GEOM::GEOM_Object::_narrow( obj );
if ( vertex->_is_nil() )
THROW_SALOME_CORBA_EXCEPTION
( "ConnectedElements_i::SetThreshold(): no GEOM_Object in SObject", SALOME::BAD_PARAM );
@@ -3020,7 +3020,8 @@ CORBA::Boolean Filter_i::SetCriteria( const SMESH::Filter::Criteria& theCriteria
SMESH::Predicate_ptr aPrevPredicate = SMESH::Predicate::_nil();
int aPrevBinary = SMESH::FT_Undefined;
- aBinaries.back() = SMESH::FT_Undefined;
+ if ( !aBinaries.empty() )
+ aBinaries.back() = SMESH::FT_Undefined;
for ( aPredIter = aPredicates.begin(), aBinaryIter = aBinaries.begin();
aPredIter != aPredicates.end() && aBinaryIter != aBinaries.end();
diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx
index b822651b7..cffb3d573 100644
--- a/src/SMESH_I/SMESH_Gen_i.cxx
+++ b/src/SMESH_I/SMESH_Gen_i.cxx
@@ -467,23 +467,22 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::createHypothesis(const char* theHypName
SMESH_Hypothesis_i* myHypothesis_i = 0;
SMESH::SMESH_Hypothesis_var hypothesis_i;
std::string aPlatformLibName;
- typedef GenericHypothesisCreator_i* (*GetHypothesisCreator)(const char* );
- GenericHypothesisCreator_i* aCreator = getHypothesisCreator(theHypName, theLibName, aPlatformLibName);
+ GenericHypothesisCreator_i* aCreator =
+ getHypothesisCreator(theHypName, theLibName, aPlatformLibName);
+
// create a new hypothesis object, store its ref. in studyContext
- if(MYDEBUG) MESSAGE("Create Hypothesis " << theHypName);
- myHypothesis_i =
- myHypCreatorMap[string(theHypName)]->Create(myPoa, GetCurrentStudyID(), &myGen);
- myHypothesis_i->SetLibName(aPlatformLibName.c_str()); // for persistency assurance
-
- if (!myHypothesis_i)
- return hypothesis_i._retn();
-
- // activate the CORBA servant of hypothesis
- hypothesis_i = myHypothesis_i->_this();
- int nextId = RegisterObject( hypothesis_i );
- if(MYDEBUG) { MESSAGE( "Add hypo to map with id = "<< nextId ); }
- else { nextId = 0; } // avoid "unused variable" warning in release mode
+ myHypothesis_i = aCreator->Create(myPoa, GetCurrentStudyID(), &myGen);
+ if (myHypothesis_i)
+ {
+ myHypothesis_i->SetLibName(aPlatformLibName.c_str()); // for persistency assurance
+ myHypCreatorMap[ myHypothesis_i->GetName() ] = aCreator;
+ // activate the CORBA servant of hypothesis
+ hypothesis_i = myHypothesis_i->_this();
+ int nextId = RegisterObject( hypothesis_i );
+ if(MYDEBUG) { MESSAGE( "Add hypo to map with id = "<< nextId ); }
+ else { nextId = 0; } // avoid "unused variable" warning in release mode
+ }
return hypothesis_i._retn();
}
diff --git a/src/SMESH_I/SMESH_Gen_i_1.cxx b/src/SMESH_I/SMESH_Gen_i_1.cxx
index 6890bcf08..b59479fce 100644
--- a/src/SMESH_I/SMESH_Gen_i_1.cxx
+++ b/src/SMESH_I/SMESH_Gen_i_1.cxx
@@ -43,6 +43,8 @@
#include
#include
+#include
+
#ifdef _DEBUG_
static int MYDEBUG = 0;
//static int VARIABLE_DEBUG = 0;
@@ -341,9 +343,15 @@ void SMESH_Gen_i::SetName(SALOMEDS::SObject_ptr theSObject,
SALOMEDS::GenericAttribute_wrap anAttr =
aStudyBuilder->FindOrCreateAttribute( theSObject, "AttributeName" );
SALOMEDS::AttributeName_wrap aNameAttr = anAttr;
- if ( theName && strlen( theName ) != 0 )
- aNameAttr->SetValue( theName );
- else {
+ if ( theName && theName[0] ) {
+ std::string name( theName ); // trim trailing white spaces
+ for ( size_t i = name.size()-1; i > 0; --i )
+ if ( isspace( name[i] )) name[i] = '\0';
+ else break;
+ aNameAttr->SetValue( name.c_str() );
+ }
+ else
+ {
CORBA::String_var curName = aNameAttr->Value();
if ( strlen( curName.in() ) == 0 ) {
SMESH_Comment aName(theDefaultName);
@@ -355,7 +363,7 @@ void SMESH_Gen_i::SetName(SALOMEDS::SObject_ptr theSObject,
//=======================================================================
//function : SetPixMap
-//purpose :
+//purpose :
//=======================================================================
void SMESH_Gen_i::SetPixMap(SALOMEDS::SObject_ptr theSObject,
diff --git a/src/SMESH_I/SMESH_MeshEditor_i.cxx b/src/SMESH_I/SMESH_MeshEditor_i.cxx
index c54b068cf..763f976e4 100644
--- a/src/SMESH_I/SMESH_MeshEditor_i.cxx
+++ b/src/SMESH_I/SMESH_MeshEditor_i.cxx
@@ -64,6 +64,7 @@
#include
#include
#include
+#include
#include
#include
@@ -4746,9 +4747,16 @@ SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
};
double tol = std::numeric_limits::max();
gp_Trsf aTrsf;
+
+#if OCC_VERSION_LARGE > 0x06070100
+ aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
+ 0, S[1], 0, thePoint.y * (1-S[1]),
+ 0, 0, S[2], thePoint.z * (1-S[2]) );
+#else
aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
0, S[1], 0, thePoint.y * (1-S[1]),
0, 0, S[2], thePoint.z * (1-S[2]), tol, tol);
+#endif
TIDSortedElemSet copyElements;
TIDSortedElemSet* workElements = &elements;
diff --git a/src/SMESH_SWIG/StdMeshersBuilder.py b/src/SMESH_SWIG/StdMeshersBuilder.py
index 1e9c73533..1496202ff 100644
--- a/src/SMESH_SWIG/StdMeshersBuilder.py
+++ b/src/SMESH_SWIG/StdMeshersBuilder.py
@@ -385,7 +385,7 @@ class StdMeshersBuilder_Segment(Mesh_Algorithm):
algo = self.mesh.smeshpyD.CreateHypothesis("SegmentAroundVertex_0D", "libStdMeshersEngine.so")
pass
status = self.mesh.mesh.AddHypothesis(self.geom, algo)
- TreatHypoStatus(status, "SegmentAroundVertex_0D", name, True)
+ TreatHypoStatus(status, "SegmentAroundVertex_0D", name, True, self.mesh)
#
from salome.smesh.smeshBuilder import IsEqual
comFun = lambda hyp, args: IsEqual(hyp.GetLength(), args[0])
@@ -830,12 +830,13 @@ class StdMeshersBuilder_Projection2D(Mesh_Algorithm):
from salome.smesh.smeshBuilder import AssureGeomPublished
AssureGeomPublished( self.mesh, geom )
hyp = self.Hypothesis("ProjectionSource2D", [face,mesh,srcV1,tgtV1,srcV2,tgtV2],
- UseExisting=0)
+ UseExisting=0, toAdd=False)
# it does not seem to be useful to reuse the existing "SourceFace" hypothesis
#UseExisting=UseExisting, CompareMethod=self.CompareSourceFace)
hyp.SetSourceFace( face )
hyp.SetSourceMesh( mesh )
hyp.SetVertexAssociation( srcV1, srcV2, tgtV1, tgtV2 )
+ self.mesh.AddHypothesis(hyp, self.geom)
return hyp
pass # end of StdMeshersBuilder_Projection2D class
diff --git a/src/SMESH_SWIG/smeshBuilder.py b/src/SMESH_SWIG/smeshBuilder.py
index dbbbe973b..fe63e726b 100644
--- a/src/SMESH_SWIG/smeshBuilder.py
+++ b/src/SMESH_SWIG/smeshBuilder.py
@@ -627,7 +627,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
# pass result of Mesh.GetIDSource( list_of_ids, type ) as meshPart
# @param meshName a name of the new mesh
# @param toCopyGroups to create in the new mesh groups the copied elements belongs to
- # @param toKeepIDs to preserve IDs of the copied elements or not
+ # @param toKeepIDs to preserve order of the copied elements or not
# @return an instance of Mesh class
def CopyMesh( self, meshPart, meshName, toCopyGroups=False, toKeepIDs=False):
if (isinstance( meshPart, Mesh )):
@@ -1596,7 +1596,7 @@ class Mesh:
AssureGeomPublished( self, geom, "shape for %s" % hyp.GetName())
status = self.mesh.AddHypothesis(geom, hyp)
else:
- status = HYP_BAD_GEOMETRY
+ status = HYP_BAD_GEOMETRY,""
hyp_name = GetName( hyp )
geom_name = ""
if geom:
@@ -1876,7 +1876,12 @@ class Mesh:
# @ingroup l2_grps_create
def MakeGroupByIds(self, groupName, elementType, elemIDs):
group = self.mesh.CreateGroup(elementType, groupName)
- group.Add(elemIDs)
+ if hasattr( elemIDs, "GetIDs" ):
+ if hasattr( elemIDs, "SetMesh" ):
+ elemIDs.SetMesh( self.GetMesh() )
+ group.AddFrom( elemIDs )
+ else:
+ group.Add(elemIDs)
return group
## Creates a mesh group by the given conditions
@@ -3451,7 +3456,7 @@ class Mesh:
##
# @brief Creates missing boundary elements around either the whole mesh or
- # groups of 2D elements
+ # groups of elements
# @param dimension - defines type of boundary elements to create
# @param groupName - a name of group to store all boundary elements in,
# "" means not to create the group
@@ -3459,7 +3464,7 @@ class Mesh:
# mesh + created boundary elements; "" means not to create the new mesh
# @param toCopyAll - if true, the whole initial mesh will be copied into
# the new mesh else only boundary elements will be copied into the new mesh
- # @param groups - groups of 2D elements to make boundary around
+ # @param groups - groups of elements to make boundary around
# @retval tuple( long, mesh, groups )
# long - number of added boundary elements
# mesh - the mesh where elements were added to
@@ -3472,12 +3477,12 @@ class Mesh:
if mesh: mesh = self.smeshpyD.Mesh(mesh)
return nb, mesh, group
- ## Renumber mesh nodes
+ ## Renumber mesh nodes (Obsolete, does nothing)
# @ingroup l2_modif_renumber
def RenumberNodes(self):
self.editor.RenumberNodes()
- ## Renumber mesh elements
+ ## Renumber mesh elements (Obsole, does nothing)
# @ingroup l2_modif_renumber
def RenumberElements(self):
self.editor.RenumberElements()
diff --git a/src/SMESH_SWIG/smesh_algorithm.py b/src/SMESH_SWIG/smesh_algorithm.py
index 3623b5176..8ce382e17 100644
--- a/src/SMESH_SWIG/smesh_algorithm.py
+++ b/src/SMESH_SWIG/smesh_algorithm.py
@@ -40,7 +40,7 @@ import SMESH
# @code
# meshMethod = "MyAlgorithm"
# @endcode
-# then an instance of @c MyPlugin_Algorithm can be created by the direct invokation of the function
+# then an instance of @c MyPlugin_Algorithm can be created by the direct invocation of the function
# of smesh.Mesh class:
# @code
# my_algo = mesh.MyAlgorithm()
@@ -257,7 +257,7 @@ class Mesh_Algorithm:
## Defines "ViscousLayers" hypothesis to give parameters of layers of prisms to build
# near mesh boundary. This hypothesis can be used by several 3D algorithms:
- # NETGEN 3D, GHS3D, Hexahedron(i,j,k)
+ # NETGEN 3D, MG-Tetra, Hexahedron(i,j,k)
# @param thickness total thickness of layers of prisms
# @param numberOfLayers number of layers of prisms
# @param stretchFactor factor (>1.0) of growth of layer thickness towards inside of mesh
@@ -274,7 +274,14 @@ class Mesh_Algorithm:
if not "ViscousLayers" in self.GetCompatibleHypothesis():
raise TypeError, "ViscousLayers are not supported by %s"%self.algo.GetName()
if faces and isinstance( faces[0], geomBuilder.GEOM._objref_GEOM_Object ):
- faces = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in faces ]
+ import GEOM
+ faceIDs = []
+ for f in faces:
+ if self.mesh.geompyD.ShapeIdToType( f.GetType() ) == "GROUP":
+ faceIDs += f.GetSubShapeIndices()
+ else:
+ faceIDs += [self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f)]
+ faces = faceIDs
hyp = self.Hypothesis("ViscousLayers",
[thickness, numberOfLayers, stretchFactor, faces, isFacesToIgnore],
toAdd=False)
@@ -287,7 +294,7 @@ class Mesh_Algorithm:
## Defines "ViscousLayers2D" hypothesis to give parameters of layers of quadrilateral
# elements to build near mesh boundary. This hypothesis can be used by several 2D algorithms:
- # NETGEN 2D, NETGEN 1D-2D, Quadrangle (mapping), MEFISTO, BLSURF
+ # NETGEN 2D, NETGEN 1D-2D, Quadrangle (mapping), MEFISTO, MG-CADSurf
# @param thickness total thickness of layers of quadrilaterals
# @param numberOfLayers number of layers
# @param stretchFactor factor (>1.0) of growth of layer thickness towards inside of mesh
diff --git a/src/StdMeshers/StdMeshers_Adaptive1D.cxx b/src/StdMeshers/StdMeshers_Adaptive1D.cxx
index 62a2cf5a9..7bcfca77d 100644
--- a/src/StdMeshers/StdMeshers_Adaptive1D.cxx
+++ b/src/StdMeshers/StdMeshers_Adaptive1D.cxx
@@ -1179,6 +1179,7 @@ bool AdaptiveAlgo::Compute(SMESH_Mesh & theMesh,
eData.AddPoint( eData.myPoints.end(), eData.myC3d.LastParameter() );
}
}
+ if ( myEdges.empty() ) return true;
if ( _computeCanceled ) return false;
// Take into account size of already existing segments
diff --git a/src/StdMeshers/StdMeshers_CartesianParameters3D.cxx b/src/StdMeshers/StdMeshers_CartesianParameters3D.cxx
index 0b7ac0235..b2e15df8c 100644
--- a/src/StdMeshers/StdMeshers_CartesianParameters3D.cxx
+++ b/src/StdMeshers/StdMeshers_CartesianParameters3D.cxx
@@ -329,7 +329,7 @@ void StdMeshers_CartesianParameters3D::ComputeCoordinates(const double x0,
coords.clear();
for ( size_t i = 0; i < spaceFuns.size(); ++i )
{
- FunctionExpr fun( spaceFuns[i].c_str(), /*convMode=*/-1 );
+ StdMeshers::FunctionExpr fun( spaceFuns[i].c_str(), /*convMode=*/-1 );
const double p0 = x0 * ( 1. - points[i]) + x1 * points[i];
const double p1 = x0 * ( 1. - points[i+1]) + x1 * points[i+1];
diff --git a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx
index 3cd23ff35..bec175bb3 100644
--- a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx
+++ b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx
@@ -100,17 +100,6 @@ using namespace std;
//#define _MY_DEBUG_
#endif
-#if OCC_VERSION_LARGE <= 0x06050300
-// workaround is required only for OCCT6.5.3 and older (see OCC22809)
-#define ELLIPSOLID_WORKAROUND
-#endif
-
-#ifdef ELLIPSOLID_WORKAROUND
-#include
-#include
-#include
-#endif
-
//=============================================================================
/*!
* Constructor
@@ -317,41 +306,6 @@ namespace
void ComputeUVW(const gp_XYZ& p, double uvw[3]);
void ComputeNodes(SMESH_MesherHelper& helper);
};
-#ifdef ELLIPSOLID_WORKAROUND
- // --------------------------------------------------------------------------
- /*!
- * \brief struct temporary replacing IntCurvesFace_Intersector until
- * OCCT bug 0022809 is fixed
- * http://tracker.dev.opencascade.org/view.php?id=22809
- */
- struct TMP_IntCurvesFace_Intersector
- {
- BRepAdaptor_Surface _surf;
- double _tol;
- BRepIntCurveSurface_Inter _intcs;
- vector _points;
- BRepTopAdaptor_TopolTool _clsf;
-
- TMP_IntCurvesFace_Intersector(const TopoDS_Face& face, const double tol)
- :_surf( face ), _tol( tol ), _clsf( new BRepAdaptor_HSurface(_surf) ) {}
- Bnd_Box Bounding() const { Bnd_Box b; BRepBndLib::Add (_surf.Face(), b); return b; }
- void Perform( const gp_Lin& line, const double w0, const double w1 )
- {
- _points.clear();
- for ( _intcs.Init( _surf.Face(), line, _tol ); _intcs.More(); _intcs.Next() )
- if ( w0 <= _intcs.W() && _intcs.W() <= w1 )
- _points.push_back( _intcs.Point() );
- }
- bool IsDone() const { return true; }
- int NbPnt() const { return _points.size(); }
- IntCurveSurface_TransitionOnCurve Transition( const int i ) const { return _points[ i-1 ].Transition(); }
- double WParameter( const int i ) const { return _points[ i-1 ].W(); }
- TopAbs_State ClassifyUVPoint(const gp_Pnt2d& p) { return _clsf.Classify( p, _tol ); }
- };
-#define __IntCurvesFace_Intersector TMP_IntCurvesFace_Intersector
-#else
-#define __IntCurvesFace_Intersector IntCurvesFace_Intersector
-#endif
// --------------------------------------------------------------------------
/*!
* \brief Intersector of TopoDS_Face with all GridLine's
@@ -362,7 +316,7 @@ namespace
TGeomID _faceID;
Grid* _grid;
Bnd_Box _bndBox;
- __IntCurvesFace_Intersector* _surfaceInt;
+ IntCurvesFace_Intersector* _surfaceInt;
vector< std::pair< GridLine*, F_IntersectPoint > > _intersections;
FaceGridIntersector(): _grid(0), _surfaceInt(0) {}
@@ -383,11 +337,11 @@ namespace
GetCurveFaceIntersector();
return _bndBox;
}
- __IntCurvesFace_Intersector* GetCurveFaceIntersector()
+ IntCurvesFace_Intersector* GetCurveFaceIntersector()
{
if ( !_surfaceInt )
{
- _surfaceInt = new __IntCurvesFace_Intersector( _face, Precision::PConfusion() );
+ _surfaceInt = new IntCurvesFace_Intersector( _face, Precision::PConfusion() );
_bndBox = _surfaceInt->Bounding();
if ( _bndBox.IsVoid() )
BRepBndLib::Add (_face, _bndBox);
@@ -412,7 +366,7 @@ namespace
gp_Cone _cone;
gp_Sphere _sphere;
gp_Torus _torus;
- __IntCurvesFace_Intersector* _surfaceInt;
+ IntCurvesFace_Intersector* _surfaceInt;
vector< F_IntersectPoint > _intPoints;
diff --git a/src/StdMeshers/StdMeshers_Distribution.cxx b/src/StdMeshers/StdMeshers_Distribution.cxx
index aa7ebf1f5..3a0a7334b 100644
--- a/src/StdMeshers/StdMeshers_Distribution.cxx
+++ b/src/StdMeshers/StdMeshers_Distribution.cxx
@@ -43,6 +43,8 @@
using namespace std;
+namespace StdMeshers {
+
Function::Function( const int conv )
: myConv( conv )
{
@@ -345,3 +347,4 @@ bool buildDistribution( const Function& func, const double start, const double e
data[nbSeg] = end;
return true;
}
+}
diff --git a/src/StdMeshers/StdMeshers_Distribution.hxx b/src/StdMeshers/StdMeshers_Distribution.hxx
index d5744d2da..e974e95f7 100644
--- a/src/StdMeshers/StdMeshers_Distribution.hxx
+++ b/src/StdMeshers/StdMeshers_Distribution.hxx
@@ -37,7 +37,8 @@
#include
#include
-
+namespace StdMeshers
+{
class STDMESHERS_EXPORT Function
{
public:
@@ -114,5 +115,5 @@ bool buildDistribution( const TCollection_AsciiString& f, const int conv, const
STDMESHERS_EXPORT
bool buildDistribution( const std::vector& f, const int conv, const double start, const double end,
const int nbSeg, std::vector& data, const double eps );
-
+}
#endif
diff --git a/src/StdMeshers/StdMeshers_FaceSide.cxx b/src/StdMeshers/StdMeshers_FaceSide.cxx
index c2596b4b6..84884800b 100644
--- a/src/StdMeshers/StdMeshers_FaceSide.cxx
+++ b/src/StdMeshers/StdMeshers_FaceSide.cxx
@@ -43,6 +43,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -151,21 +152,26 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace,
myMissingVertexNodes = true;
// check if the edge has a non-uniform parametrization (issue 0020705)
- if ( !myC2d[i].IsNull() && myEdgeLength[i] > DBL_MIN)
+ if ( !myC2d[i].IsNull() )
{
- Geom2dAdaptor_Curve A2dC( myC2d[i],
- std::min( myFirst[i], myLast[i] ),
- std::max( myFirst[i], myLast[i] ));
- double p2 = myFirst[i]+(myLast[i]-myFirst[i])/2., p4 = myFirst[i]+(myLast[i]-myFirst[i])/4.;
- double d2 = GCPnts_AbscissaPoint::Length( A2dC, myFirst[i], p2 );
- double d4 = GCPnts_AbscissaPoint::Length( A2dC, myFirst[i], p4 );
- //cout<<"len = "< 0.01 || fabs(2*d4/d2-1.0) > 0.01 );
- //if ( !myIsUniform[i] ) to implement Value3d(u)
+ if ( myEdgeLength[i] > DBL_MIN)
{
- double fp,lp;
- Handle(Geom_Curve) C3d = BRep_Tool::Curve(myEdge[i],fp,lp);
- myC3dAdaptor[i].Load( C3d, fp,lp );
+ Geom2dAdaptor_Curve A2dC( myC2d[i],
+ std::min( myFirst[i], myLast[i] ),
+ std::max( myFirst[i], myLast[i] ));
+ double p2 = myFirst[i]+(myLast[i]-myFirst[i])/2., p4 = myFirst[i]+(myLast[i]-myFirst[i])/4.;
+ double d2 = GCPnts_AbscissaPoint::Length( A2dC, myFirst[i], p2 );
+ double d4 = GCPnts_AbscissaPoint::Length( A2dC, myFirst[i], p4 );
+ //cout<<"len = "< 0.01 || fabs(2*d4/d2-1.0) > 0.01 );
+ Handle(Geom_Curve) C3d = BRep_Tool::Curve(myEdge[i],d2,d4);
+ myC3dAdaptor[i].Load( C3d, d2,d4 );
+ }
+ else
+ {
+ const TopoDS_Vertex& V = TopoDS::Vertex( vExp.Value() );
+ Handle(Geom_Curve) C3d = new Geom_Line( BRep_Tool::Pnt( V ), gp::DX() );
+ myC3dAdaptor[i].Load( C3d, 0, 0.5 * BRep_Tool::Tolerance( V ));
}
}
// reverse a proxy submesh
@@ -988,7 +994,7 @@ gp_Pnt StdMeshers_FaceSide::Value3d(double U) const
double r = ( U - prevU )/ ( myNormPar[ i ] - prevU );
double par = myFirst[i] * ( 1 - r ) + myLast[i] * r;
-
+
// check parametrization of curve
if( !myIsUniform[i] )
{
diff --git a/src/StdMeshers/StdMeshers_NumberOfSegments.cxx b/src/StdMeshers/StdMeshers_NumberOfSegments.cxx
index f09dc7a10..c9e48b7e2 100644
--- a/src/StdMeshers/StdMeshers_NumberOfSegments.cxx
+++ b/src/StdMeshers/StdMeshers_NumberOfSegments.cxx
@@ -53,6 +53,7 @@
#include
+using namespace StdMeshers;
using namespace std;
const double PRECISION = 1e-7;
diff --git a/src/StdMeshers/StdMeshers_Prism_3D.cxx b/src/StdMeshers/StdMeshers_Prism_3D.cxx
index afac9bebe..04cc3aebe 100644
--- a/src/StdMeshers/StdMeshers_Prism_3D.cxx
+++ b/src/StdMeshers/StdMeshers_Prism_3D.cxx
@@ -49,6 +49,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -77,7 +78,7 @@ using namespace std;
#define SHOWYXZ(msg, xyz)
#endif
-namespace TAssocTool = StdMeshers_ProjectionUtils;
+namespace NSProjUtils = StdMeshers_ProjectionUtils;
typedef SMESH_Comment TCom;
@@ -157,6 +158,10 @@ namespace {
fatherAlgo->GetGen() );
return algo;
}
+ const NSProjUtils::TNodeNodeMap& GetNodesMap()
+ {
+ return _src2tgtNodes;
+ }
};
//=======================================================================
/*!
@@ -539,7 +544,7 @@ StdMeshers_Prism_3D::StdMeshers_Prism_3D(int hypId, int studyId, SMESH_Gen* gen)
{
_name = "Prism_3D";
_shapeType = (1 << TopAbs_SOLID); // 1 bit per shape type
- _onlyUnaryInput = false; // accept all SOLIDs at once
+ _onlyUnaryInput = false; // mesh all SOLIDs at once
_requireDiscreteBoundary = false; // mesh FACEs and EDGEs by myself
_supportSubmeshes = true; // "source" FACE must be meshed by other algo
_neededLowerHyps[ 1 ] = true; // suppress warning on hiding a global 1D algo
@@ -578,12 +583,12 @@ bool StdMeshers_Prism_3D::CheckHypothesis(SMESH_Mesh& a
for ( ; exp.More(); exp.Next() ) {
++nbFace;
const TopoDS_Shape& face = exp.Current();
- nbEdge = TAssocTool::Count( face, TopAbs_EDGE, 0 );
- nbWire = TAssocTool::Count( face, TopAbs_WIRE, 0 );
+ nbEdge = NSProjUtils::Count( face, TopAbs_EDGE, 0 );
+ nbWire = NSProjUtils::Count( face, TopAbs_WIRE, 0 );
if ( nbEdge!= 4 || nbWire!= 1 ) {
if ( !notQuadFaces.empty() ) {
- if ( TAssocTool::Count( notQuadFaces.back(), TopAbs_EDGE, 0 ) != nbEdge ||
- TAssocTool::Count( notQuadFaces.back(), TopAbs_WIRE, 0 ) != nbWire )
+ if ( NSProjUtils::Count( notQuadFaces.back(), TopAbs_EDGE, 0 ) != nbEdge ||
+ NSProjUtils::Count( notQuadFaces.back(), TopAbs_WIRE, 0 ) != nbWire )
RETURN_BAD_RESULT("Different not quad faces");
}
notQuadFaces.push_back( face );
@@ -595,7 +600,7 @@ bool StdMeshers_Prism_3D::CheckHypothesis(SMESH_Mesh& a
RETURN_BAD_RESULT("Bad nb not quad faces: " << notQuadFaces.size());
// check total nb faces
- nbEdge = TAssocTool::Count( notQuadFaces.back(), TopAbs_EDGE, 0 );
+ nbEdge = NSProjUtils::Count( notQuadFaces.back(), TopAbs_EDGE, 0 );
if ( nbFace != nbEdge + 2 )
RETURN_BAD_RESULT("Bad nb of faces: " << nbFace << " but must be " << nbEdge + 2);
}
@@ -657,12 +662,14 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
Prism_3D::TPrismTopo prism;
myPropagChains = 0;
+ bool selectBottom = meshedFaces.empty();
if ( nbSolids == 1 )
{
+ TopoDS_Shape solid = TopExp_Explorer( theShape, TopAbs_SOLID ).Current();
if ( !meshedFaces.empty() )
prism.myBottom = meshedFaces.front();
- return ( initPrism( prism, TopExp_Explorer( theShape, TopAbs_SOLID ).Current() ) &&
+ return ( initPrism( prism, solid, selectBottom ) &&
compute( prism ));
}
@@ -683,6 +690,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
TopTools_MapOfShape meshedSolids;
list< Prism_3D::TPrismTopo > meshedPrism;
+ list< TopoDS_Face > suspectSourceFaces;
TopTools_ListIteratorOfListOfShape solidIt;
while ( meshedSolids.Extent() < nbSolids )
@@ -704,7 +712,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
{
prism.Clear();
prism.myBottom = face;
- if ( !initPrism( prism, solid ) ||
+ if ( !initPrism( prism, solid, selectBottom ) ||
!compute( prism ))
return false;
@@ -713,6 +721,10 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
{
meshedFaces.push_front( prism.myTop );
}
+ else
+ {
+ suspectSourceFaces.push_back( prism.myTop );
+ }
meshedPrism.push_back( prism );
}
}
@@ -742,6 +754,10 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
solidList.Remove( solidIt );
continue; // already computed prism
}
+ if ( myHelper->IsBlock( solid )) {
+ solidIt.Next();
+ continue; // too trivial
+ }
// find a source FACE of the SOLID: it's a FACE sharing a bottom EDGE with wFace
const TopoDS_Edge& wEdge = (*wQuad)->side[ QUAD_TOP_SIDE ].grid->Edge(0);
PShapeIteratorPtr faceIt = myHelper->GetAncestors( wEdge, *myHelper->GetMesh(),
@@ -749,14 +765,24 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
while ( const TopoDS_Shape* f = faceIt->next() )
{
const TopoDS_Face& candidateF = TopoDS::Face( *f );
+ if ( candidateF.IsSame( wFace )) continue;
+ // select a source FACE: prismIt->myBottom or prismIt->myTop
+ TopoDS_Face sourceF = prismIt->myBottom;
+ for ( TopExp_Explorer v( prismIt->myTop, TopAbs_VERTEX ); v.More(); v.Next() )
+ if ( myHelper->IsSubShape( v.Current(), candidateF )) {
+ sourceF = prismIt->myTop;
+ break;
+ }
prism.Clear();
- prism.myBottom = candidateF;
+ prism.myBottom = candidateF;
mySetErrorToSM = false;
if ( !myHelper->IsSubShape( candidateF, prismIt->myShape3D ) &&
- myHelper->IsSubShape( candidateF, solid ) &&
+ myHelper ->IsSubShape( candidateF, solid ) &&
!myHelper->GetMesh()->GetSubMesh( candidateF )->IsMeshComputed() &&
- initPrism( prism, solid ) &&
- project2dMesh( prismIt->myBottom, candidateF))
+ initPrism( prism, solid, /*selectBottom=*/false ) &&
+ !myHelper->GetMesh()->GetSubMesh( prism.myTop )->IsMeshComputed() &&
+ !myHelper->GetMesh()->GetSubMesh( prism.myBottom )->IsMeshComputed() &&
+ project2dMesh( sourceF, prism.myBottom ))
{
mySetErrorToSM = true;
if ( !compute( prism ))
@@ -766,6 +792,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
{
meshedFaces.push_front( prism.myTop );
meshedFaces.push_front( prism.myBottom );
+ selectBottom = false;
}
meshedPrism.push_back( prism );
meshedSolids.Add( solid );
@@ -785,31 +812,52 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
break; // to compute prisms with avident sources
}
+ if ( meshedFaces.empty() )
+ {
+ meshedFaces.splice( meshedFaces.end(), suspectSourceFaces );
+ selectBottom = true;
+ }
+
// find FACEs with local 1D hyps, which has to be computed by now,
// or at least any computed FACEs
- for ( int iF = 1; ( meshedFaces.empty() && iF < faceToSolids.Extent() ); ++iF )
+ if ( meshedFaces.empty() )
{
- const TopoDS_Face& face = TopoDS::Face( faceToSolids.FindKey( iF ));
- const TopTools_ListOfShape& solidList = faceToSolids.FindFromKey( face );
- if ( solidList.IsEmpty() ) continue;
- SMESH_subMesh* faceSM = theMesh.GetSubMesh( face );
- if ( !faceSM->IsEmpty() )
+ int prevNbFaces = 0;
+ for ( int iF = 1; iF <= faceToSolids.Extent(); ++iF )
{
- meshedFaces.push_back( face ); // lower priority
- }
- else
- {
- bool allSubMeComputed = true;
- SMESH_subMeshIteratorPtr smIt = faceSM->getDependsOnIterator(false,true);
- while ( smIt->more() && allSubMeComputed )
- allSubMeComputed = smIt->next()->IsMeshComputed();
- if ( allSubMeComputed )
+ const TopoDS_Face& face = TopoDS::Face( faceToSolids.FindKey( iF ));
+ const TopTools_ListOfShape& solidList = faceToSolids.FindFromKey( face );
+ if ( solidList.IsEmpty() ) continue;
+ SMESH_subMesh* faceSM = theMesh.GetSubMesh( face );
+ if ( !faceSM->IsEmpty() )
{
- faceSM->ComputeStateEngine( SMESH_subMesh::COMPUTE );
- if ( !faceSM->IsEmpty() )
- meshedFaces.push_front( face ); // higher priority
- else
- faceSM->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+ int nbFaces = faceSM->GetSubMeshDS()->NbElements();
+ if ( prevNbFaces < nbFaces )
+ {
+ if ( !meshedFaces.empty() ) meshedFaces.pop_back();
+ meshedFaces.push_back( face ); // lower priority
+ selectBottom = true;
+ prevNbFaces = nbFaces;
+ }
+ }
+ else
+ {
+ bool allSubMeComputed = true;
+ SMESH_subMeshIteratorPtr smIt = faceSM->getDependsOnIterator(false,true);
+ while ( smIt->more() && allSubMeComputed )
+ allSubMeComputed = smIt->next()->IsMeshComputed();
+ if ( allSubMeComputed )
+ {
+ faceSM->ComputeStateEngine( SMESH_subMesh::COMPUTE );
+ if ( !faceSM->IsEmpty() ) {
+ meshedFaces.push_front( face ); // higher priority
+ selectBottom = true;
+ break;
+ }
+ else {
+ faceSM->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+ }
+ }
}
}
}
@@ -835,6 +883,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
meshedFaces.push_front( prism.myBottom );
meshedPrism.push_back( prism );
meshedSolids.Add( solid.Current() );
+ selectBottom = true;
}
mySetErrorToSM = true;
}
@@ -983,6 +1032,7 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism,
// find wall FACEs adjacent to each of thePrism.myWallQuads by the top side EDGE
if ( totalNbFaces - faceMap.Extent() > 2 )
{
+ const int nbFoundWalls = faceMap.Extent();
for ( size_t i = 0; i < thePrism.myWallQuads.size(); ++i )
{
StdMeshers_FaceSidePtr topSide = thePrism.myWallQuads[i].back()->side[ QUAD_TOP_SIDE ];
@@ -1009,6 +1059,9 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism,
}
}
}
+ if ( nbFoundWalls == faceMap.Extent() )
+ return toSM( error("Failed to find wall faces"));
+
}
} // while ( totalNbFaces - faceMap.Extent() > 2 )
@@ -1035,7 +1088,7 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism,
StdMeshers_FaceSidePtr topSide = thePrism.myWallQuads[i].back()->side[ QUAD_TOP_SIDE ];
const TopoDS_Edge & topE = topSide->Edge( 0 );
if ( !myHelper->IsSubShape( topE, thePrism.myTop ))
- return toSM( error( TCom("Wrong source face (#") << shapeID( thePrism.myBottom )));
+ return toSM( error( TCom("Wrong source face: #") << shapeID( thePrism.myBottom )));
}
return true;
@@ -1052,11 +1105,23 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism)
if ( _computeCanceled )
return toSM( error( SMESH_ComputeError::New(COMPERR_CANCELED)));
+ // Assure the bottom is meshed
+ SMESH_subMesh * botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
+ if (( botSM->IsEmpty() ) &&
+ ( ! botSM->GetAlgo() ||
+ ! _gen->Compute( *botSM->GetFather(), botSM->GetSubShape(), /*shapeOnly=*/true )))
+ return error( COMPERR_BAD_INPUT_MESH,
+ TCom( "No mesher defined to compute the face #")
+ << shapeID( thePrism.myBottom ));
+
// Make all side FACEs of thePrism meshed with quads
if ( !computeWalls( thePrism ))
return false;
// Analyse mesh and geometry to find all block sub-shapes and submeshes
+ // (after fixing IPAL52499 myBlock is used as a holder of boundary nodes
+ // and for 2D projection in hard cases where StdMeshers_Projection_2D fails;
+ // location of internal nodes is usually computed by StdMeshers_Sweeper)
if ( !myBlock.Init( myHelper, thePrism ))
return toSM( error( myBlock.GetError()));
@@ -1067,10 +1132,10 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism)
// Try to get gp_Trsf to get all nodes from bottom ones
vector trsf;
gp_Trsf bottomToTopTrsf;
- if ( !myBlock.GetLayersTransformation( trsf, thePrism ))
- trsf.clear();
- else if ( !trsf.empty() )
- bottomToTopTrsf = trsf.back();
+ // if ( !myBlock.GetLayersTransformation( trsf, thePrism ))
+ // trsf.clear();
+ // else if ( !trsf.empty() )
+ // bottomToTopTrsf = trsf.back();
// To compute coordinates of a node inside a block, it is necessary to know
// 1. normalized parameters of the node by which
@@ -1085,6 +1150,7 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism)
// Projections on the top and bottom faces are taken from nodes existing
// on these faces; find correspondence between bottom and top nodes
+ myUseBlock = false;
myBotToColumnMap.clear();
if ( !assocOrProjBottom2Top( bottomToTopTrsf, thePrism ) ) // it also fills myBotToColumnMap
return false;
@@ -1092,31 +1158,36 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism)
// Create nodes inside the block
- // try to use transformation (issue 0020680)
- if ( !trsf.empty() )
+ // use transformation (issue 0020680, IPAL0052499)
+ StdMeshers_Sweeper sweeper;
+ double tol;
+ bool allowHighBndError;
+
+ if ( !myUseBlock )
{
- // loop on nodes inside the bottom face
+ // load boundary nodes into sweeper
+ bool dummy;
+ list< TopoDS_Edge >::const_iterator edge = thePrism.myBottomEdges.begin();
+ for ( ; edge != thePrism.myBottomEdges.end(); ++edge )
+ {
+ int edgeID = meshDS->ShapeToIndex( *edge );
+ TParam2ColumnMap* u2col = const_cast
+ ( myBlock.GetParam2ColumnMap( edgeID, dummy ));
+ TParam2ColumnMap::iterator u2colIt = u2col->begin();
+ for ( ; u2colIt != u2col->end(); ++u2colIt )
+ sweeper.myBndColumns.push_back( & u2colIt->second );
+ }
+ // load node columns inside the bottom face
TNode2ColumnMap::iterator bot_column = myBotToColumnMap.begin();
for ( ; bot_column != myBotToColumnMap.end(); ++bot_column )
- {
- const Prism_3D::TNode& tBotNode = bot_column->first; // bottom TNode
- if ( tBotNode.GetPositionType() != SMDS_TOP_FACE )
- continue; // node is not inside face
+ sweeper.myIntColumns.push_back( & bot_column->second );
- // column nodes; middle part of the column are zero pointers
- TNodeColumn& column = bot_column->second;
- TNodeColumn::iterator columnNodes = column.begin();
- for ( int z = 0; columnNodes != column.end(); ++columnNodes, ++z)
- {
- const SMDS_MeshNode* & node = *columnNodes;
- if ( node ) continue; // skip bottom or top node
+ tol = getSweepTolerance( thePrism );
+ allowHighBndError = !isSimpleBottom( thePrism );
+ }
- gp_XYZ coords = tBotNode.GetCoords();
- trsf[z-1].Transforms( coords );
- node = meshDS->AddNode( coords.X(), coords.Y(), coords.Z() );
- meshDS->SetNodeInVolume( node, volumeID );
- }
- } // loop on bottom nodes
+ if ( !myUseBlock && sweeper.ComputeNodes( *myHelper, tol, allowHighBndError ))
+ {
}
else // use block approach
{
@@ -1127,7 +1198,7 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism)
{
const Prism_3D::TNode& tBotNode = bot_column->first; // bottom TNode
if ( tBotNode.GetPositionType() != SMDS_TOP_FACE )
- continue; // node is not inside the FACE
+ continue; // node is not inside the FACE
// column nodes; middle part of the column are zero pointers
TNodeColumn& column = bot_column->second;
@@ -1249,7 +1320,17 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism)
// clear data
myBotToColumnMap.clear();
myBlock.Clear();
-
+
+ // update state of sub-meshes (mostly in order to erase improper errors)
+ SMESH_subMesh* sm = myHelper->GetMesh()->GetSubMesh( thePrism.myShape3D );
+ SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/false);
+ while ( smIt->more() )
+ {
+ sm = smIt->next();
+ sm->GetComputeError().reset();
+ sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+ }
+
return true;
}
@@ -1491,7 +1572,7 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
for ( ; quad != thePrism.myWallQuads[iW].end(); ++quad )
{
const TopoDS_Face& face = (*quad)->face;
- SMESH_subMesh* fSM = mesh->GetSubMesh( face );
+ SMESH_subMesh* fSM = mesh->GetSubMesh( face );
if ( ! fSM->IsMeshComputed() )
{
// Top EDGEs must be projections from the bottom ones
@@ -1503,6 +1584,8 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
SMESH_subMesh* topSM = mesh->GetSubMesh( topE );
SMESH_subMesh* srcSM = botSM;
SMESH_subMesh* tgtSM = topSM;
+ srcSM->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+ tgtSM->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
if ( !srcSM->IsMeshComputed() && tgtSM->IsMeshComputed() )
std::swap( srcSM, tgtSM );
@@ -1512,7 +1595,6 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
srcSM->ComputeSubMeshStateEngine( SMESH_subMesh::COMPUTE ); // nodes on VERTEXes
srcSM->ComputeStateEngine( SMESH_subMesh::COMPUTE ); // segments on the EDGE
}
- srcSM->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
if ( tgtSM->IsMeshComputed() &&
tgtSM->GetSubMeshDS()->NbNodes() != srcSM->GetSubMeshDS()->NbNodes() )
@@ -1853,8 +1935,8 @@ void StdMeshers_Prism_3D::AddPrisms( vector & columns,
bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf,
const Prism_3D::TPrismTopo& thePrism)
{
- SMESH_subMesh * botSM = myBlock.SubMesh( ID_BOT_FACE );
- SMESH_subMesh * topSM = myBlock.SubMesh( ID_TOP_FACE );
+ SMESH_subMesh * botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
+ SMESH_subMesh * topSM = myHelper->GetMesh()->GetSubMesh( thePrism.myTop );
SMESHDS_SubMesh * botSMDS = botSM->GetSubMeshDS();
SMESHDS_SubMesh * topSMDS = topSM->GetSubMeshDS();
@@ -1885,86 +1967,90 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
<<" and #"<< topSM->GetId() << " seems different" ));
///RETURN_BAD_RESULT("Need to project but not allowed");
+ NSProjUtils::TNodeNodeMap n2nMap;
+ const NSProjUtils::TNodeNodeMap* n2nMapPtr = & n2nMap;
if ( needProject )
{
- return projectBottomToTop( bottomToTopTrsf );
+ if ( !projectBottomToTop( bottomToTopTrsf, thePrism ))
+ return false;
+ n2nMapPtr = & TProjction2dAlgo::instance( this )->GetNodesMap();
}
- TopoDS_Face botFace = TopoDS::Face( myBlock.Shape( ID_BOT_FACE ));
- TopoDS_Face topFace = TopoDS::Face( myBlock.Shape( ID_TOP_FACE ));
- // associate top and bottom faces
- TAssocTool::TShapeShapeMap shape2ShapeMap;
- const bool sameTopo =
- TAssocTool::FindSubShapeAssociation( botFace, myBlock.Mesh(),
- topFace, myBlock.Mesh(),
- shape2ShapeMap);
- if ( !sameTopo )
- for ( size_t iQ = 0; iQ < thePrism.myWallQuads.size(); ++iQ )
- {
- const Prism_3D::TQuadList& quadList = thePrism.myWallQuads[iQ];
- StdMeshers_FaceSidePtr botSide = quadList.front()->side[ QUAD_BOTTOM_SIDE ];
- StdMeshers_FaceSidePtr topSide = quadList.back ()->side[ QUAD_TOP_SIDE ];
- if ( botSide->NbEdges() == topSide->NbEdges() )
- {
- for ( int iE = 0; iE < botSide->NbEdges(); ++iE )
- {
- TAssocTool::InsertAssociation( botSide->Edge( iE ),
- topSide->Edge( iE ), shape2ShapeMap );
- TAssocTool::InsertAssociation( myHelper->IthVertex( 0, botSide->Edge( iE )),
- myHelper->IthVertex( 0, topSide->Edge( iE )),
- shape2ShapeMap );
- }
- }
- else
- {
- TopoDS_Vertex vb, vt;
- StdMeshers_FaceSidePtr sideB, sideT;
- vb = myHelper->IthVertex( 0, botSide->Edge( 0 ));
- vt = myHelper->IthVertex( 0, topSide->Edge( 0 ));
- sideB = quadList.front()->side[ QUAD_LEFT_SIDE ];
- sideT = quadList.back ()->side[ QUAD_LEFT_SIDE ];
- if ( vb.IsSame( sideB->FirstVertex() ) &&
- vt.IsSame( sideT->LastVertex() ))
- {
- TAssocTool::InsertAssociation( botSide->Edge( 0 ),
- topSide->Edge( 0 ), shape2ShapeMap );
- TAssocTool::InsertAssociation( vb, vt, shape2ShapeMap );
- }
- vb = myHelper->IthVertex( 1, botSide->Edge( botSide->NbEdges()-1 ));
- vt = myHelper->IthVertex( 1, topSide->Edge( topSide->NbEdges()-1 ));
- sideB = quadList.front()->side[ QUAD_RIGHT_SIDE ];
- sideT = quadList.back ()->side[ QUAD_RIGHT_SIDE ];
- if ( vb.IsSame( sideB->FirstVertex() ) &&
- vt.IsSame( sideT->LastVertex() ))
- {
- TAssocTool::InsertAssociation( botSide->Edge( botSide->NbEdges()-1 ),
- topSide->Edge( topSide->NbEdges()-1 ),
- shape2ShapeMap );
- TAssocTool::InsertAssociation( vb, vt, shape2ShapeMap );
- }
- }
- }
-
- // Find matching nodes of top and bottom faces
- TNodeNodeMap n2nMap;
- if ( ! TAssocTool::FindMatchingNodesOnFaces( botFace, myBlock.Mesh(),
- topFace, myBlock.Mesh(),
- shape2ShapeMap, n2nMap ))
+ if ( !n2nMapPtr || n2nMapPtr->size() < botSMDS->NbNodes() )
{
- if ( sameTopo )
- return toSM( error(TCom("Mesh on faces #") << botSM->GetId()
- <<" and #"<< topSM->GetId() << " seems different" ));
- else
- return toSM( error(TCom("Topology of faces #") << botSM->GetId()
- <<" and #"<< topSM->GetId() << " seems different" ));
+ // associate top and bottom faces
+ NSProjUtils::TShapeShapeMap shape2ShapeMap;
+ const bool sameTopo =
+ NSProjUtils::FindSubShapeAssociation( thePrism.myBottom, myHelper->GetMesh(),
+ thePrism.myTop, myHelper->GetMesh(),
+ shape2ShapeMap);
+ if ( !sameTopo )
+ for ( size_t iQ = 0; iQ < thePrism.myWallQuads.size(); ++iQ )
+ {
+ const Prism_3D::TQuadList& quadList = thePrism.myWallQuads[iQ];
+ StdMeshers_FaceSidePtr botSide = quadList.front()->side[ QUAD_BOTTOM_SIDE ];
+ StdMeshers_FaceSidePtr topSide = quadList.back ()->side[ QUAD_TOP_SIDE ];
+ if ( botSide->NbEdges() == topSide->NbEdges() )
+ {
+ for ( int iE = 0; iE < botSide->NbEdges(); ++iE )
+ {
+ NSProjUtils::InsertAssociation( botSide->Edge( iE ),
+ topSide->Edge( iE ), shape2ShapeMap );
+ NSProjUtils::InsertAssociation( myHelper->IthVertex( 0, botSide->Edge( iE )),
+ myHelper->IthVertex( 0, topSide->Edge( iE )),
+ shape2ShapeMap );
+ }
+ }
+ else
+ {
+ TopoDS_Vertex vb, vt;
+ StdMeshers_FaceSidePtr sideB, sideT;
+ vb = myHelper->IthVertex( 0, botSide->Edge( 0 ));
+ vt = myHelper->IthVertex( 0, topSide->Edge( 0 ));
+ sideB = quadList.front()->side[ QUAD_LEFT_SIDE ];
+ sideT = quadList.back ()->side[ QUAD_LEFT_SIDE ];
+ if ( vb.IsSame( sideB->FirstVertex() ) &&
+ vt.IsSame( sideT->LastVertex() ))
+ {
+ NSProjUtils::InsertAssociation( botSide->Edge( 0 ),
+ topSide->Edge( 0 ), shape2ShapeMap );
+ NSProjUtils::InsertAssociation( vb, vt, shape2ShapeMap );
+ }
+ vb = myHelper->IthVertex( 1, botSide->Edge( botSide->NbEdges()-1 ));
+ vt = myHelper->IthVertex( 1, topSide->Edge( topSide->NbEdges()-1 ));
+ sideB = quadList.front()->side[ QUAD_RIGHT_SIDE ];
+ sideT = quadList.back ()->side[ QUAD_RIGHT_SIDE ];
+ if ( vb.IsSame( sideB->FirstVertex() ) &&
+ vt.IsSame( sideT->LastVertex() ))
+ {
+ NSProjUtils::InsertAssociation( botSide->Edge( botSide->NbEdges()-1 ),
+ topSide->Edge( topSide->NbEdges()-1 ),
+ shape2ShapeMap );
+ NSProjUtils::InsertAssociation( vb, vt, shape2ShapeMap );
+ }
+ }
+ }
+
+ // Find matching nodes of top and bottom faces
+ n2nMapPtr = & n2nMap;
+ if ( ! NSProjUtils::FindMatchingNodesOnFaces( thePrism.myBottom, myHelper->GetMesh(),
+ thePrism.myTop, myHelper->GetMesh(),
+ shape2ShapeMap, n2nMap ))
+ {
+ if ( sameTopo )
+ return toSM( error(TCom("Mesh on faces #") << botSM->GetId()
+ <<" and #"<< topSM->GetId() << " seems different" ));
+ else
+ return toSM( error(TCom("Topology of faces #") << botSM->GetId()
+ <<" and #"<< topSM->GetId() << " seems different" ));
+ }
}
// Fill myBotToColumnMap
int zSize = myBlock.VerticalSize();
- //TNode prevTNode;
- TNodeNodeMap::iterator bN_tN = n2nMap.begin();
- for ( ; bN_tN != n2nMap.end(); ++bN_tN )
+ TNodeNodeMap::const_iterator bN_tN = n2nMapPtr->begin();
+ for ( ; bN_tN != n2nMapPtr->end(); ++bN_tN )
{
const SMDS_MeshNode* botNode = bN_tN->first;
const SMDS_MeshNode* topNode = bN_tN->second;
@@ -1972,7 +2058,7 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
continue; // wall columns are contained in myBlock
// create node column
Prism_3D::TNode bN( botNode );
- TNode2ColumnMap::iterator bN_col =
+ TNode2ColumnMap::iterator bN_col =
myBotToColumnMap.insert( make_pair ( bN, TNodeColumn() )).first;
TNodeColumn & column = bN_col->second;
column.resize( zSize );
@@ -1984,27 +2070,43 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
//================================================================================
/*!
- * \brief Remove quadrangles from the top face and
- * create triangles there by projection from the bottom
+ * \brief Remove faces from the top face and re-create them by projection from the bottom
* \retval bool - a success or not
*/
//================================================================================
-bool StdMeshers_Prism_3D::projectBottomToTop( const gp_Trsf & bottomToTopTrsf )
+bool StdMeshers_Prism_3D::projectBottomToTop( const gp_Trsf & bottomToTopTrsf,
+ const Prism_3D::TPrismTopo& thePrism )
{
- SMESHDS_Mesh* meshDS = myBlock.MeshDS();
- SMESH_subMesh * botSM = myBlock.SubMesh( ID_BOT_FACE );
- SMESH_subMesh * topSM = myBlock.SubMesh( ID_TOP_FACE );
+ if ( project2dMesh( thePrism.myBottom, thePrism.myTop ))
+ {
+ return true;
+ }
+ NSProjUtils::TNodeNodeMap& n2nMap =
+ (NSProjUtils::TNodeNodeMap&) TProjction2dAlgo::instance( this )->GetNodesMap();
+ n2nMap.clear();
+
+ myUseBlock = true;
+
+ SMESHDS_Mesh* meshDS = myHelper->GetMeshDS();
+ SMESH_subMesh * botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
+ SMESH_subMesh * topSM = myHelper->GetMesh()->GetSubMesh( thePrism.myTop );
SMESHDS_SubMesh * botSMDS = botSM->GetSubMeshDS();
SMESHDS_SubMesh * topSMDS = topSM->GetSubMeshDS();
if ( topSMDS && topSMDS->NbElements() > 0 )
- topSM->ComputeStateEngine( SMESH_subMesh::CLEAN );
+ {
+ //topSM->ComputeStateEngine( SMESH_subMesh::CLEAN ); -- avoid propagation of events
+ for ( SMDS_ElemIteratorPtr eIt = topSMDS->GetElements(); eIt->more(); )
+ meshDS->RemoveFreeElement( eIt->next(), topSMDS, /*fromGroups=*/false );
+ for ( SMDS_NodeIteratorPtr nIt = topSMDS->GetNodes(); nIt->more(); )
+ meshDS->RemoveFreeNode( nIt->next(), topSMDS, /*fromGroups=*/false );
+ }
- const TopoDS_Face& botFace = TopoDS::Face( myBlock.Shape( ID_BOT_FACE )); // oriented within
- const TopoDS_Face& topFace = TopoDS::Face( myBlock.Shape( ID_TOP_FACE )); // the 3D SHAPE
- int topFaceID = meshDS->ShapeToIndex( topFace );
+ const TopoDS_Face& botFace = thePrism.myBottom; // oriented within
+ const TopoDS_Face& topFace = thePrism.myTop; // the 3D SHAPE
+ int topFaceID = meshDS->ShapeToIndex( thePrism.myTop );
SMESH_MesherHelper botHelper( *myHelper->GetMesh() );
botHelper.SetSubShape( botFace );
@@ -2071,6 +2173,11 @@ bool StdMeshers_Prism_3D::projectBottomToTop( const gp_Trsf & bottomToTopTrsf )
column.resize( zSize );
column.front() = botNode;
column.back() = topNode;
+
+ n2nMap.insert( n2nMap.end(), make_pair( botNode, topNode ));
+
+ if ( _computeCanceled )
+ return toSM( error( SMESH_ComputeError::New(COMPERR_CANCELED)));
}
// Create top faces
@@ -2118,11 +2225,11 @@ bool StdMeshers_Prism_3D::projectBottomToTop( const gp_Trsf & bottomToTopTrsf )
case 3: {
newFace = myHelper->AddFace(nodes[0], nodes[1], nodes[2]);
break;
- }
+ }
case 4: {
newFace = myHelper->AddFace( nodes[0], nodes[1], nodes[2], nodes[3] );
break;
- }
+ }
default:
newFace = meshDS->AddPolygonalFace( nodes );
}
@@ -2130,8 +2237,152 @@ bool StdMeshers_Prism_3D::projectBottomToTop( const gp_Trsf & bottomToTopTrsf )
meshDS->SetMeshElementOnShape( newFace, topFaceID );
}
- myHelper->SetElementsOnShape( oldSetElemsOnShape );
+ myHelper->SetElementsOnShape( oldSetElemsOnShape );
+ // Check the projected mesh
+
+ if ( thePrism.myNbEdgesInWires.size() > 1 && // there are holes
+ topHelper.IsDistorted2D( topSM, /*checkUV=*/false ))
+ {
+ SMESH_MeshEditor editor( topHelper.GetMesh() );
+
+ // smooth in 2D or 3D?
+ TopLoc_Location loc;
+ Handle(Geom_Surface) surface = BRep_Tool::Surface( topFace, loc );
+ bool isPlanar = GeomLib_IsPlanarSurface( surface ).IsPlanar();
+
+ bool isFixed = false;
+ set fixedNodes;
+ for ( int iAttemp = 0; !isFixed && iAttemp < 10; ++iAttemp )
+ {
+ TIDSortedElemSet faces;
+ for ( faceIt = topSMDS->GetElements(); faceIt->more(); )
+ faces.insert( faces.end(), faceIt->next() );
+
+ SMESH_MeshEditor::SmoothMethod algo =
+ iAttemp ? SMESH_MeshEditor::CENTROIDAL : SMESH_MeshEditor::LAPLACIAN;
+
+ // smoothing
+ editor.Smooth( faces, fixedNodes, algo, /*nbIterations=*/ 10,
+ /*theTgtAspectRatio=*/1.0, /*the2D=*/!isPlanar);
+
+ isFixed = !topHelper.IsDistorted2D( topSM, /*checkUV=*/true );
+ }
+ if ( !isFixed )
+ return toSM( error( TCom("Projection from face #") << botSM->GetId()
+ << " to face #" << topSM->GetId()
+ << " failed: inverted elements created"));
+ }
+
+ return true;
+}
+
+//=======================================================================
+//function : getSweepTolerance
+//purpose : Compute tolerance to pass to StdMeshers_Sweeper
+//=======================================================================
+
+double StdMeshers_Prism_3D::getSweepTolerance( const Prism_3D::TPrismTopo& thePrism )
+{
+ SMESHDS_Mesh* meshDS = myHelper->GetMeshDS();
+ SMESHDS_SubMesh * sm[2] = { meshDS->MeshElements( thePrism.myBottom ),
+ meshDS->MeshElements( thePrism.myTop ) };
+ double minDist = 1e100;
+
+ vector< SMESH_TNodeXYZ > nodes;
+ for ( int iSM = 0; iSM < 2; ++iSM )
+ {
+ if ( !sm[ iSM ]) continue;
+
+ SMDS_ElemIteratorPtr fIt = sm[ iSM ]->GetElements();
+ while ( fIt->more() )
+ {
+ const SMDS_MeshElement* face = fIt->next();
+ const int nbNodes = face->NbCornerNodes();
+ SMDS_ElemIteratorPtr nIt = face->nodesIterator();
+
+ nodes.resize( nbNodes + 1 );
+ for ( int iN = 0; iN < nbNodes; ++iN )
+ nodes[ iN ] = nIt->next();
+ nodes.back() = nodes[0];
+
+ // loop on links
+ double dist2;
+ for ( int iN = 0; iN < nbNodes; ++iN )
+ {
+ if ( nodes[ iN ]._node->GetPosition()->GetDim() < 2 &&
+ nodes[ iN+1 ]._node->GetPosition()->GetDim() < 2 )
+ {
+ // it's a boundary link; measure distance of other
+ // nodes to this link
+ gp_XYZ linkDir = nodes[ iN ] - nodes[ iN+1 ];
+ double linkLen = linkDir.Modulus();
+ bool isDegen = ( linkLen < numeric_limits::min() );
+ if ( !isDegen ) linkDir /= linkLen;
+ for ( int iN2 = 0; iN2 < nbNodes; ++iN2 ) // loop on other nodes
+ {
+ if ( nodes[ iN2 ] == nodes[ iN ] ||
+ nodes[ iN2 ] == nodes[ iN+1 ]) continue;
+ if ( isDegen )
+ {
+ dist2 = ( nodes[ iN ] - nodes[ iN2 ]).SquareModulus();
+ }
+ else
+ {
+ dist2 = linkDir.CrossSquareMagnitude( nodes[ iN ] - nodes[ iN2 ]);
+ }
+ if ( dist2 > numeric_limits::min() )
+ minDist = Min ( minDist, dist2 );
+ }
+ }
+ // measure length link
+ else if ( nodes[ iN ]._node < nodes[ iN+1 ]._node ) // not to measure same link twice
+ {
+ dist2 = ( nodes[ iN ] - nodes[ iN+1 ]).SquareModulus();
+ if ( dist2 > numeric_limits::min() )
+ minDist = Min ( minDist, dist2 );
+ }
+ }
+ }
+ }
+ return 0.1 * Sqrt ( minDist );
+}
+
+//=======================================================================
+//function : isSimpleQuad
+//purpose : check if the bottom FACE is meshable with nice qudrangles,
+// if so the block aproach can work rather fast.
+// This is a temporary mean caused by problems in StdMeshers_Sweeper
+//=======================================================================
+
+bool StdMeshers_Prism_3D::isSimpleBottom( const Prism_3D::TPrismTopo& thePrism )
+{
+ // analyse angles between edges
+ double nbConcaveAng = 0, nbConvexAng = 0;
+ TopoDS_Face reverseBottom = TopoDS::Face( thePrism.myBottom.Reversed() ); // see initPrism()
+ TopoDS_Vertex commonV;
+ const list< TopoDS_Edge >& botEdges = thePrism.myBottomEdges;
+ list< TopoDS_Edge >::const_iterator edge = botEdges.begin();
+ while ( edge != botEdges.end() )
+ {
+ if ( SMESH_Algo::isDegenerated( *edge ))
+ return false;
+ TopoDS_Edge e1 = *edge++;
+ TopoDS_Edge e2 = ( edge == botEdges.end() ? botEdges.front() : *edge );
+ if ( ! TopExp::CommonVertex( e1, e2, commonV ))
+ {
+ e2 = botEdges.front();
+ if ( ! TopExp::CommonVertex( e1, e2, commonV ))
+ break;
+ }
+ double angle = myHelper->GetAngle( e1, e2, reverseBottom, commonV );
+ if ( angle < -5 * M_PI/180 )
+ if ( ++nbConcaveAng > 1 )
+ return false;
+ if ( angle > 85 * M_PI/180 )
+ if ( ++nbConvexAng > 4 )
+ return false;
+ }
return true;
}
@@ -2149,6 +2400,15 @@ bool StdMeshers_Prism_3D::project2dMesh(const TopoDS_Face& theSrcFace,
bool ok = projector2D->Compute( *myHelper->GetMesh(), theTgtFace );
SMESH_subMesh* tgtSM = myHelper->GetMesh()->GetSubMesh( theTgtFace );
+ if ( !ok && tgtSM->GetSubMeshDS() ) {
+ //tgtSM->ComputeStateEngine( SMESH_subMesh::CLEAN ); -- avoid propagation of events
+ SMESHDS_Mesh* meshDS = myHelper->GetMeshDS();
+ SMESHDS_SubMesh* tgtSMDS = tgtSM->GetSubMeshDS();
+ for ( SMDS_ElemIteratorPtr eIt = tgtSMDS->GetElements(); eIt->more(); )
+ meshDS->RemoveFreeElement( eIt->next(), tgtSMDS, /*fromGroups=*/false );
+ for ( SMDS_NodeIteratorPtr nIt = tgtSMDS->GetNodes(); nIt->more(); )
+ meshDS->RemoveFreeNode( nIt->next(), tgtSMDS, /*fromGroups=*/false );
+ }
tgtSM->ComputeStateEngine ( SMESH_subMesh::CHECK_COMPUTE_STATE );
tgtSM->ComputeSubMeshStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
@@ -2261,6 +2521,12 @@ namespace // utils used by StdMeshers_Prism_3D::IsApplicable()
if ( E.IsSame( Edge( i ))) return i;
return -1;
}
+ bool IsSideFace( const TopoDS_Shape& face ) const
+ {
+ if ( _faces->Contains( face )) // avoid returning true for a prism top FACE
+ return ( !_face.IsNull() || !( face.IsSame( _faces->FindKey( _faces->Extent() ))));
+ return false;
+ }
};
//--------------------------------------------------------------------------------
/*!
@@ -2392,12 +2658,11 @@ bool StdMeshers_Prism_3D::IsApplicable(const TopoDS_Shape & shape, bool toCheckA
TEdgeWithNeighborsVec& botEdges = faceEdgesVec[ iF ];
if ( botEdges.empty() )
- {
if ( !getEdges( botF, botEdges, /*noHoles=*/false ))
break;
- if ( allFaces.Extent()-1 <= (int) botEdges.size() )
- continue; // all faces are adjacent to botF - no top FACE
- }
+ if ( allFaces.Extent()-1 <= (int) botEdges.size() )
+ continue; // all faces are adjacent to botF - no top FACE
+
// init data of side FACEs
vector< PrismSide > sides( botEdges.size() );
for ( int iS = 0; iS < botEdges.size(); ++iS )
@@ -2411,8 +2676,8 @@ bool StdMeshers_Prism_3D::IsApplicable(const TopoDS_Shape & shape, bool toCheckA
}
bool isOK = true; // ok for a current botF
- bool isAdvanced = true;
- int nbFoundSideFaces = 0;
+ bool isAdvanced = true; // is new data found in a current loop
+ int nbFoundSideFaces = 0;
for ( int iLoop = 0; isOK && isAdvanced; ++iLoop )
{
isAdvanced = false;
@@ -2420,7 +2685,8 @@ bool StdMeshers_Prism_3D::IsApplicable(const TopoDS_Shape & shape, bool toCheckA
{
PrismSide& side = sides[ iS ];
if ( side._face.IsNull() )
- continue;
+ continue; // probably the prism top face is the last of side._faces
+
if ( side._topEdge.IsNull() )
{
// find vertical EDGEs --- EGDEs shared with neighbor side FACEs
@@ -2434,7 +2700,7 @@ bool StdMeshers_Prism_3D::IsApplicable(const TopoDS_Shape & shape, bool toCheckA
if ( side._isCheckedEdge[ iE ] ) continue;
const TopoDS_Edge& vertE = side.Edge( iE );
const TopoDS_Shape& neighborF = getAnotherFace( side._face, vertE, facesOfEdge );
- bool isEdgeShared = adjSide->_faces->Contains( neighborF );
+ bool isEdgeShared = adjSide->IsSideFace( neighborF );
if ( isEdgeShared )
{
isAdvanced = true;
@@ -2480,13 +2746,13 @@ bool StdMeshers_Prism_3D::IsApplicable(const TopoDS_Shape & shape, bool toCheckA
{
if ( side._leftSide->_faces->Contains( f ))
{
- stop = true;
+ stop = true; // probably f is the prism top face
side._leftSide->_face.Nullify();
side._leftSide->_topEdge.Nullify();
}
if ( side._rightSide->_faces->Contains( f ))
{
- stop = true;
+ stop = true; // probably f is the prism top face
side._rightSide->_face.Nullify();
side._rightSide->_topEdge.Nullify();
}
@@ -2497,8 +2763,8 @@ bool StdMeshers_Prism_3D::IsApplicable(const TopoDS_Shape & shape, bool toCheckA
side._topEdge.Nullify();
continue;
}
- side._face = TopoDS::Face( f );
- int faceID = allFaces.FindIndex( side._face );
+ side._face = TopoDS::Face( f );
+ int faceID = allFaces.FindIndex( side._face );
side._edges = & faceEdgesVec[ faceID ];
if ( side._edges->empty() )
if ( !getEdges( side._face, * side._edges, /*noHoles=*/true ))
@@ -2658,16 +2924,18 @@ void StdMeshers_PrismAsBlock::Clear()
//=======================================================================
bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
- const TopoDS_Shape& shape3D)
+ const TopoDS_Shape& theShape3D,
+ const bool selectBottom)
{
- myHelper->SetSubShape( shape3D );
+ myHelper->SetSubShape( theShape3D );
- SMESH_subMesh* mainSubMesh = myHelper->GetMesh()->GetSubMeshContaining( shape3D );
+ SMESH_subMesh* mainSubMesh = myHelper->GetMesh()->GetSubMeshContaining( theShape3D );
if ( !mainSubMesh ) return toSM( error(COMPERR_BAD_INPUT_MESH,"Null submesh of shape3D"));
// detect not-quad FACE sub-meshes of the 3D SHAPE
list< SMESH_subMesh* > notQuadGeomSubMesh;
list< SMESH_subMesh* > notQuadElemSubMesh;
+ list< SMESH_subMesh* > meshedSubMesh;
int nbFaces = 0;
//
SMESH_subMesh* anyFaceSM = 0;
@@ -2689,10 +2957,14 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
if ( nbWires != 1 || nbEdgesInWires.front() != 4 )
notQuadGeomSubMesh.push_back( sm );
- // look for not quadrangle mesh elements
- if ( SMESHDS_SubMesh* smDS = sm->GetSubMeshDS() )
- if ( !myHelper->IsSameElemGeometry( smDS, SMDSGeom_QUADRANGLE ))
+ // look for a not structured sub-mesh
+ if ( !sm->IsEmpty() )
+ {
+ meshedSubMesh.push_back( sm );
+ if ( !myHelper->IsSameElemGeometry( sm->GetSubMeshDS(), SMDSGeom_QUADRANGLE ) ||
+ !myHelper->IsStructured ( sm ))
notQuadElemSubMesh.push_back( sm );
+ }
}
int nbNotQuadMeshed = notQuadElemSubMesh.size();
@@ -2757,33 +3029,50 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
// use thePrism.myBottom
if ( !thePrism.myBottom.IsNull() )
{
- if ( botSM ) {
+ if ( botSM ) { // <-- not quad geom or mesh on botSM
if ( ! botSM->GetSubShape().IsSame( thePrism.myBottom )) {
std::swap( botSM, topSM );
- if ( !botSM || ! botSM->GetSubShape().IsSame( thePrism.myBottom ))
- return toSM( error( COMPERR_BAD_INPUT_MESH,
- "Incompatible non-structured sub-meshes"));
+ if ( !botSM || ! botSM->GetSubShape().IsSame( thePrism.myBottom )) {
+ if ( !selectBottom )
+ return toSM( error( COMPERR_BAD_INPUT_MESH,
+ "Incompatible non-structured sub-meshes"));
+ std::swap( botSM, topSM );
+ thePrism.myBottom = TopoDS::Face( botSM->GetSubShape() );
+ }
}
}
- else {
+ else if ( !selectBottom ) {
botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
}
}
- else if ( !botSM ) // find a proper bottom
+ if ( !botSM ) // find a proper bottom
{
- // composite walls or not prism shape
- for ( TopExp_Explorer f( shape3D, TopAbs_FACE ); f.More(); f.Next() )
+ bool savedSetErrorToSM = mySetErrorToSM;
+ mySetErrorToSM = false; // ingore errors in initPrism()
+
+ // search among meshed FACEs
+ list< SMESH_subMesh* >::iterator sm = meshedSubMesh.begin();
+ for ( ; !botSM && sm != meshedSubMesh.end(); ++sm )
+ {
+ thePrism.Clear();
+ botSM = *sm;
+ thePrism.myBottom = TopoDS::Face( botSM->GetSubShape() );
+ if ( !initPrism( thePrism, theShape3D, /*selectBottom=*/false ))
+ botSM = NULL;
+ }
+ // search among all FACEs
+ for ( TopExp_Explorer f( theShape3D, TopAbs_FACE ); !botSM && f.More(); f.Next() )
{
int minNbFaces = 2 + myHelper->Count( f.Current(), TopAbs_EDGE, false);
- if ( nbFaces >= minNbFaces)
- {
- thePrism.Clear();
- thePrism.myBottom = TopoDS::Face( f.Current() );
- if ( initPrism( thePrism, shape3D ))
- return true;
- }
- return toSM( error( COMPERR_BAD_SHAPE ));
+ if ( nbFaces < minNbFaces) continue;
+ thePrism.Clear();
+ thePrism.myBottom = TopoDS::Face( f.Current() );
+ botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
+ if ( !initPrism( thePrism, theShape3D, /*selectBottom=*/false ))
+ botSM = NULL;
}
+ mySetErrorToSM = savedSetErrorToSM;
+ return botSM ? true : toSM( error( COMPERR_BAD_SHAPE ));
}
// find vertex 000 - the one with smallest coordinates (for easy DEBUG :-)
@@ -2802,11 +3091,12 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
}
}
- thePrism.myShape3D = shape3D;
+ thePrism.myShape3D = theShape3D;
if ( thePrism.myBottom.IsNull() )
thePrism.myBottom = TopoDS::Face( botSM->GetSubShape() );
- thePrism.myBottom.Orientation( myHelper->GetSubShapeOri( shape3D,
- thePrism.myBottom ));
+ thePrism.myBottom.Orientation( myHelper->GetSubShapeOri( theShape3D, thePrism.myBottom ));
+ thePrism.myTop. Orientation( myHelper->GetSubShapeOri( theShape3D, thePrism.myTop ));
+
// Get ordered bottom edges
TopoDS_Face reverseBottom = // to have order of top EDGEs as in the top FACE
TopoDS::Face( thePrism.myBottom.Reversed() );
@@ -2815,7 +3105,7 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
thePrism.myNbEdgesInWires, V000 );
// Get Wall faces corresponding to the ordered bottom edges and the top FACE
- if ( !getWallFaces( thePrism, nbFaces ))
+ if ( !getWallFaces( thePrism, nbFaces )) // it also sets thePrism.myTop
return false; //toSM( error(COMPERR_BAD_SHAPE, "Can't find side faces"));
if ( topSM )
@@ -3759,7 +4049,7 @@ gp_Pnt StdMeshers_PrismAsBlock::TSideFace::Value(const Standard_Real U,
TopoDS_Shape s = myHelper.GetSubShapeByNode( nn[0], myHelper.GetMeshDS() );
if ( s.ShapeType() != TopAbs_EDGE )
s = myHelper.GetSubShapeByNode( nn[2], myHelper.GetMeshDS() );
- if ( s.ShapeType() == TopAbs_EDGE )
+ if ( !s.IsNull() && s.ShapeType() == TopAbs_EDGE )
edge = TopoDS::Edge( s );
}
if ( !edge.IsNull() )
@@ -4221,3 +4511,359 @@ gp_Pnt2d StdMeshers_PrismAsBlock::TPCurveOnHorFaceAdaptor::Value(const Standard_
double r = ( U - i1->first ) / ( i2->first - i1->first );
return i1->second * ( 1 - r ) + i2->second * r;
}
+
+//================================================================================
+/*!
+ * \brief Projects internal nodes using transformation found by boundary nodes
+ */
+//================================================================================
+
+bool StdMeshers_Sweeper::projectIntPoints(const vector< gp_XYZ >& fromBndPoints,
+ const vector< gp_XYZ >& toBndPoints,
+ const vector< gp_XYZ >& fromIntPoints,
+ vector< gp_XYZ >& toIntPoints,
+ NSProjUtils::TrsfFinder3D& trsf,
+ vector< gp_XYZ > * bndError)
+{
+ // find transformation
+ if ( trsf.IsIdentity() && !trsf.Solve( fromBndPoints, toBndPoints ))
+ return false;
+
+ // compute internal points using the found trsf
+ for ( size_t iP = 0; iP < fromIntPoints.size(); ++iP )
+ {
+ toIntPoints[ iP ] = trsf.Transform( fromIntPoints[ iP ]);
+ }
+
+ // compute boundary error
+ if ( bndError )
+ {
+ bndError->resize( fromBndPoints.size() );
+ gp_XYZ fromTrsf;
+ for ( size_t iP = 0; iP < fromBndPoints.size(); ++iP )
+ {
+ fromTrsf = trsf.Transform( fromBndPoints[ iP ] );
+ (*bndError)[ iP ] = toBndPoints[ iP ] - fromTrsf;
+ }
+ }
+ return true;
+}
+
+//================================================================================
+/*!
+ * \brief Add boundary error to ineternal points
+ */
+//================================================================================
+
+void StdMeshers_Sweeper::applyBoundaryError(const vector< gp_XYZ >& bndPoints,
+ const vector< gp_XYZ >& bndError1,
+ const vector< gp_XYZ >& bndError2,
+ const double r,
+ vector< gp_XYZ >& intPoints,
+ vector< double >& int2BndDist)
+{
+ // fix each internal point
+ const double eps = 1e-100;
+ for ( size_t iP = 0; iP < intPoints.size(); ++iP )
+ {
+ gp_XYZ & intPnt = intPoints[ iP ];
+
+ // compute distance from intPnt to each boundary node
+ double int2BndDistSum = 0;
+ for ( size_t iBnd = 0; iBnd < bndPoints.size(); ++iBnd )
+ {
+ int2BndDist[ iBnd ] = 1 / (( intPnt - bndPoints[ iBnd ]).SquareModulus() + eps );
+ int2BndDistSum += int2BndDist[ iBnd ];
+ }
+
+ // apply bndError
+ for ( size_t iBnd = 0; iBnd < bndPoints.size(); ++iBnd )
+ {
+ intPnt += bndError1[ iBnd ] * ( 1 - r ) * int2BndDist[ iBnd ] / int2BndDistSum;
+ intPnt += bndError2[ iBnd ] * r * int2BndDist[ iBnd ] / int2BndDistSum;
+ }
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Creates internal nodes of the prism
+ */
+//================================================================================
+
+bool StdMeshers_Sweeper::ComputeNodes( SMESH_MesherHelper& helper,
+ const double tol,
+ const bool allowHighBndError)
+{
+ const size_t zSize = myBndColumns[0]->size();
+ const size_t zSrc = 0, zTgt = zSize-1;
+ if ( zSize < 3 ) return true;
+
+ vector< vector< gp_XYZ > > intPntsOfLayer( zSize ); // node coodinates to compute
+ // set coordinates of src and tgt nodes
+ for ( size_t z = 0; z < intPntsOfLayer.size(); ++z )
+ intPntsOfLayer[ z ].resize( myIntColumns.size() );
+ for ( size_t iP = 0; iP < myIntColumns.size(); ++iP )
+ {
+ intPntsOfLayer[ zSrc ][ iP ] = intPoint( iP, zSrc );
+ intPntsOfLayer[ zTgt ][ iP ] = intPoint( iP, zTgt );
+ }
+
+ // compute coordinates of internal nodes by projecting (transfroming) src and tgt
+ // nodes towards the central layer
+
+ vector< NSProjUtils::TrsfFinder3D > trsfOfLayer( zSize );
+ vector< vector< gp_XYZ > > bndError( zSize );
+
+ // boundary points used to compute an affine transformation from a layer to a next one
+ vector< gp_XYZ > fromSrcBndPnts( myBndColumns.size() ), fromTgtBndPnts( myBndColumns.size() );
+ vector< gp_XYZ > toSrcBndPnts ( myBndColumns.size() ), toTgtBndPnts ( myBndColumns.size() );
+ for ( size_t iP = 0; iP < myBndColumns.size(); ++iP )
+ {
+ fromSrcBndPnts[ iP ] = bndPoint( iP, zSrc );
+ fromTgtBndPnts[ iP ] = bndPoint( iP, zTgt );
+ }
+
+ size_t zS = zSrc + 1;
+ size_t zT = zTgt - 1;
+ for ( ; zS < zT; ++zS, --zT ) // vertical loop on layers
+ {
+ for ( size_t iP = 0; iP < myBndColumns.size(); ++iP )
+ {
+ toSrcBndPnts[ iP ] = bndPoint( iP, zS );
+ toTgtBndPnts[ iP ] = bndPoint( iP, zT );
+ }
+ if (! projectIntPoints( fromSrcBndPnts, toSrcBndPnts,
+ intPntsOfLayer[ zS-1 ], intPntsOfLayer[ zS ],
+ trsfOfLayer [ zS-1 ], & bndError[ zS-1 ]))
+ return false;
+ if (! projectIntPoints( fromTgtBndPnts, toTgtBndPnts,
+ intPntsOfLayer[ zT+1 ], intPntsOfLayer[ zT ],
+ trsfOfLayer [ zT+1 ], & bndError[ zT+1 ]))
+ return false;
+
+ // if ( zT == zTgt - 1 )
+ // {
+ // for ( size_t iP = 0; iP < myBndColumns.size(); ++iP )
+ // {
+ // gp_XYZ fromTrsf = trsfOfLayer [ zT+1].Transform( fromTgtBndPnts[ iP ] );
+ // cout << "mesh.AddNode( "
+ // << fromTrsf.X() << ", "
+ // << fromTrsf.Y() << ", "
+ // << fromTrsf.Z() << ") " << endl;
+ // }
+ // for ( size_t iP = 0; iP < myIntColumns.size(); ++iP )
+ // cout << "mesh.AddNode( "
+ // << intPntsOfLayer[ zT ][ iP ].X() << ", "
+ // << intPntsOfLayer[ zT ][ iP ].Y() << ", "
+ // << intPntsOfLayer[ zT ][ iP ].Z() << ") " << endl;
+ // }
+
+ fromTgtBndPnts.swap( toTgtBndPnts );
+ fromSrcBndPnts.swap( toSrcBndPnts );
+ }
+
+ // Compute two projections of internal points to the central layer
+ // in order to evaluate an error of internal points
+
+ bool centerIntErrorIsSmall;
+ vector< gp_XYZ > centerSrcIntPnts( myIntColumns.size() );
+ vector< gp_XYZ > centerTgtIntPnts( myIntColumns.size() );
+
+ for ( size_t iP = 0; iP < myBndColumns.size(); ++iP )
+ {
+ toSrcBndPnts[ iP ] = bndPoint( iP, zS );
+ toTgtBndPnts[ iP ] = bndPoint( iP, zT );
+ }
+ if (! projectIntPoints( fromSrcBndPnts, toSrcBndPnts,
+ intPntsOfLayer[ zS-1 ], centerSrcIntPnts,
+ trsfOfLayer [ zS-1 ], & bndError[ zS-1 ]))
+ return false;
+ if (! projectIntPoints( fromTgtBndPnts, toTgtBndPnts,
+ intPntsOfLayer[ zT+1 ], centerTgtIntPnts,
+ trsfOfLayer [ zT+1 ], & bndError[ zT+1 ]))
+ return false;
+
+ // evaluate an error of internal points on the central layer
+ centerIntErrorIsSmall = true;
+ if ( zS == zT ) // odd zSize
+ {
+ for ( size_t iP = 0; ( iP < myIntColumns.size() && centerIntErrorIsSmall ); ++iP )
+ centerIntErrorIsSmall =
+ (centerSrcIntPnts[ iP ] - centerTgtIntPnts[ iP ]).SquareModulus() < tol*tol;
+ }
+ else // even zSize
+ {
+ for ( size_t iP = 0; ( iP < myIntColumns.size() && centerIntErrorIsSmall ); ++iP )
+ centerIntErrorIsSmall =
+ (intPntsOfLayer[ zS-1 ][ iP ] - centerTgtIntPnts[ iP ]).SquareModulus() < tol*tol;
+ }
+
+ // Evaluate an error of boundary points
+
+ bool bndErrorIsSmall = true;
+ for ( size_t iP = 0; ( iP < myBndColumns.size() && bndErrorIsSmall ); ++iP )
+ {
+ double sumError = 0;
+ for ( size_t z = 1; z < zS; ++z ) // loop on layers
+ sumError += ( bndError[ z-1 ][ iP ].Modulus() +
+ bndError[ zSize-z ][ iP ].Modulus() );
+
+ bndErrorIsSmall = ( sumError < tol );
+ }
+
+ if ( !bndErrorIsSmall && !allowHighBndError )
+ return false;
+
+ // compute final points on the central layer
+ std::vector< double > int2BndDist( myBndColumns.size() ); // work array of applyBoundaryError()
+ double r = zS / ( zSize - 1.);
+ if ( zS == zT )
+ {
+ for ( size_t iP = 0; iP < myIntColumns.size(); ++iP )
+ {
+ intPntsOfLayer[ zS ][ iP ] =
+ ( 1 - r ) * centerSrcIntPnts[ iP ] + r * centerTgtIntPnts[ iP ];
+ }
+ if ( !bndErrorIsSmall )
+ {
+ applyBoundaryError( toSrcBndPnts, bndError[ zS-1 ], bndError[ zS+1 ], r,
+ intPntsOfLayer[ zS ], int2BndDist );
+ }
+ }
+ else
+ {
+ for ( size_t iP = 0; iP < myIntColumns.size(); ++iP )
+ {
+ intPntsOfLayer[ zS ][ iP ] =
+ r * intPntsOfLayer[ zS ][ iP ] + ( 1 - r ) * centerSrcIntPnts[ iP ];
+ intPntsOfLayer[ zT ][ iP ] =
+ r * intPntsOfLayer[ zT ][ iP ] + ( 1 - r ) * centerTgtIntPnts[ iP ];
+ }
+ if ( !bndErrorIsSmall )
+ {
+ applyBoundaryError( toSrcBndPnts, bndError[ zS-1 ], bndError[ zS+1 ], r,
+ intPntsOfLayer[ zS ], int2BndDist );
+ applyBoundaryError( toTgtBndPnts, bndError[ zT+1 ], bndError[ zT-1 ], r,
+ intPntsOfLayer[ zT ], int2BndDist );
+ }
+ }
+
+ //centerIntErrorIsSmall = true;
+ //bndErrorIsSmall = true;
+ if ( !centerIntErrorIsSmall )
+ {
+ // Compensate the central error; continue adding projection
+ // by going from central layer to the source and target ones
+
+ vector< gp_XYZ >& fromSrcIntPnts = centerSrcIntPnts;
+ vector< gp_XYZ >& fromTgtIntPnts = centerTgtIntPnts;
+ vector< gp_XYZ > toSrcIntPnts( myIntColumns.size() );
+ vector< gp_XYZ > toTgtIntPnts( myIntColumns.size() );
+ vector< gp_XYZ > srcBndError( myBndColumns.size() );
+ vector< gp_XYZ > tgtBndError( myBndColumns.size() );
+
+ fromTgtBndPnts.swap( toTgtBndPnts );
+ fromSrcBndPnts.swap( toSrcBndPnts );
+
+ for ( ++zS, --zT; zS < zTgt; ++zS, --zT ) // vertical loop on layers
+ {
+ // invert transformation
+ if ( !trsfOfLayer[ zS+1 ].Invert() )
+ trsfOfLayer[ zS+1 ] = NSProjUtils::TrsfFinder3D(); // to recompute
+ if ( !trsfOfLayer[ zT-1 ].Invert() )
+ trsfOfLayer[ zT-1 ] = NSProjUtils::TrsfFinder3D();
+
+ // project internal nodes and compute bnd error
+ for ( size_t iP = 0; iP < myBndColumns.size(); ++iP )
+ {
+ toSrcBndPnts[ iP ] = bndPoint( iP, zS );
+ toTgtBndPnts[ iP ] = bndPoint( iP, zT );
+ }
+ projectIntPoints( fromSrcBndPnts, toSrcBndPnts,
+ fromSrcIntPnts, toSrcIntPnts,
+ trsfOfLayer[ zS+1 ], & srcBndError );
+ projectIntPoints( fromTgtBndPnts, toTgtBndPnts,
+ fromTgtIntPnts, toTgtIntPnts,
+ trsfOfLayer[ zT-1 ], & tgtBndError );
+
+ // if ( zS == zTgt - 1 )
+ // {
+ // cout << "mesh2 = smesh.Mesh()" << endl;
+ // for ( size_t iP = 0; iP < myBndColumns.size(); ++iP )
+ // {
+ // gp_XYZ fromTrsf = trsfOfLayer [ zS+1].Transform( fromSrcBndPnts[ iP ] );
+ // cout << "mesh2.AddNode( "
+ // << fromTrsf.X() << ", "
+ // << fromTrsf.Y() << ", "
+ // << fromTrsf.Z() << ") " << endl;
+ // }
+ // for ( size_t iP = 0; iP < myIntColumns.size(); ++iP )
+ // cout << "mesh2.AddNode( "
+ // << toSrcIntPnts[ iP ].X() << ", "
+ // << toSrcIntPnts[ iP ].Y() << ", "
+ // << toSrcIntPnts[ iP ].Z() << ") " << endl;
+ // }
+
+ // sum up 2 projections
+ r = zS / ( zSize - 1.);
+ vector< gp_XYZ >& zSIntPnts = intPntsOfLayer[ zS ];
+ vector< gp_XYZ >& zTIntPnts = intPntsOfLayer[ zT ];
+ for ( size_t iP = 0; iP < myIntColumns.size(); ++iP )
+ {
+ zSIntPnts[ iP ] = r * zSIntPnts[ iP ] + ( 1 - r ) * toSrcIntPnts[ iP ];
+ zTIntPnts[ iP ] = r * zTIntPnts[ iP ] + ( 1 - r ) * toTgtIntPnts[ iP ];
+ }
+
+ // compensate bnd error
+ if ( !bndErrorIsSmall )
+ {
+ applyBoundaryError( toSrcBndPnts, srcBndError, bndError[ zS+1 ], r,
+ intPntsOfLayer[ zS ], int2BndDist );
+ applyBoundaryError( toTgtBndPnts, tgtBndError, bndError[ zT-1 ], r,
+ intPntsOfLayer[ zT ], int2BndDist );
+ }
+
+ fromSrcBndPnts.swap( toSrcBndPnts );
+ fromSrcIntPnts.swap( toSrcIntPnts );
+ fromTgtBndPnts.swap( toTgtBndPnts );
+ fromTgtIntPnts.swap( toTgtIntPnts );
+ }
+ } // if ( !centerIntErrorIsSmall )
+
+ else if ( !bndErrorIsSmall )
+ {
+ zS = zSrc + 1;
+ zT = zTgt - 1;
+ for ( ; zS < zT; ++zS, --zT ) // vertical loop on layers
+ {
+ for ( size_t iP = 0; iP < myBndColumns.size(); ++iP )
+ {
+ toSrcBndPnts[ iP ] = bndPoint( iP, zS );
+ toTgtBndPnts[ iP ] = bndPoint( iP, zT );
+ }
+ // compensate bnd error
+ applyBoundaryError( toSrcBndPnts, bndError[ zS-1 ], bndError[ zS-1 ], 0.5,
+ intPntsOfLayer[ zS ], int2BndDist );
+ applyBoundaryError( toTgtBndPnts, bndError[ zT+1 ], bndError[ zT+1 ], 0.5,
+ intPntsOfLayer[ zT ], int2BndDist );
+ }
+ }
+
+ // cout << "centerIntErrorIsSmall = " << centerIntErrorIsSmall<< endl;
+ // cout << "bndErrorIsSmall = " << bndErrorIsSmall<< endl;
+
+ // Create nodes
+ for ( size_t iP = 0; iP < myIntColumns.size(); ++iP )
+ {
+ vector< const SMDS_MeshNode* > & nodeCol = *myIntColumns[ iP ];
+ for ( size_t z = zSrc + 1; z < zTgt; ++z ) // vertical loop on layers
+ {
+ const gp_XYZ & xyz = intPntsOfLayer[ z ][ iP ];
+ if ( !( nodeCol[ z ] = helper.AddNode( xyz.X(), xyz.Y(), xyz.Z() )))
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/src/StdMeshers/StdMeshers_Prism_3D.hxx b/src/StdMeshers/StdMeshers_Prism_3D.hxx
index f2929c31a..546bf4950 100644
--- a/src/StdMeshers/StdMeshers_Prism_3D.hxx
+++ b/src/StdMeshers/StdMeshers_Prism_3D.hxx
@@ -56,6 +56,10 @@ namespace Prism_3D
struct TNode;
struct TPrismTopo;
}
+namespace StdMeshers_ProjectionUtils
+{
+ class TrsfFinder3D;
+}
class SMESHDS_SubMesh;
class TopoDS_Edge;
@@ -398,7 +402,43 @@ private:
}; // class StdMeshers_PrismAsBlock
-// =============================================
+// ===============================================
+/*!
+ * \brief Tool building internal nodes in a prism
+ */
+struct StdMeshers_Sweeper
+{
+ std::vector< TNodeColumn* > myBndColumns; // boundary nodes
+ std::vector< TNodeColumn* > myIntColumns; // internal nodes
+
+ bool ComputeNodes( SMESH_MesherHelper& helper,
+ const double tol,
+ const bool allowHighBndError );
+
+private:
+
+ gp_XYZ bndPoint( int iP, int z ) const
+ { return SMESH_TNodeXYZ( (*myBndColumns[ iP ])[ z ]); }
+
+ gp_XYZ intPoint( int iP, int z ) const
+ { return SMESH_TNodeXYZ( (*myIntColumns[ iP ])[ z ]); }
+
+ static bool projectIntPoints(const std::vector< gp_XYZ >& fromBndPoints,
+ const std::vector< gp_XYZ >& toBndPoints,
+ const std::vector< gp_XYZ >& fromIntPoints,
+ std::vector< gp_XYZ >& toIntPoints,
+ StdMeshers_ProjectionUtils::TrsfFinder3D& trsf,
+ std::vector< gp_XYZ > * bndError);
+
+ static void applyBoundaryError(const std::vector< gp_XYZ >& bndPoints,
+ const std::vector< gp_XYZ >& bndError1,
+ const std::vector< gp_XYZ >& bndError2,
+ const double r,
+ std::vector< gp_XYZ >& toIntPoints,
+ std::vector< double >& int2BndDist);
+};
+
+// ===============================================
/*!
* \brief Algo building prisms on a prism shape
*/
@@ -443,7 +483,9 @@ public:
* \brief Analyse shape geometry and mesh.
* If there are triangles on one of faces, it becomes 'bottom'
*/
- bool initPrism(Prism_3D::TPrismTopo& thePrism, const TopoDS_Shape& theSolid);
+ bool initPrism(Prism_3D::TPrismTopo& thePrism,
+ const TopoDS_Shape& theSolid,
+ const bool selectBottom = true);
/*!
* \brief Fill thePrism.myWallQuads and thePrism.myTopEdges
@@ -480,7 +522,18 @@ public:
* create triangles there by projection from the bottom
* \retval bool - a success or not
*/
- bool projectBottomToTop( const gp_Trsf & bottomToTopTrsf );
+ bool projectBottomToTop( const gp_Trsf & bottomToTopTrsf,
+ const Prism_3D::TPrismTopo& thePrism );
+
+ /*!
+ * \brief Compute tolerance to pass to StdMeshers_Sweeper
+ */
+ double getSweepTolerance( const Prism_3D::TPrismTopo& thePrism );
+
+ /*!
+ * \brief Defines if it's safe to use the block approach
+ */
+ bool isSimpleBottom( const Prism_3D::TPrismTopo& thePrism );
/*!
* \brief Project mesh faces from a source FACE of one prism to
@@ -511,6 +564,7 @@ private:
bool myProjectTriangles;
bool mySetErrorToSM;
+ bool myUseBlock;
StdMeshers_PrismAsBlock myBlock;
SMESH_MesherHelper* myHelper;
diff --git a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx
index 92474f205..e5ab88a1e 100644
--- a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx
+++ b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx
@@ -51,6 +51,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -66,6 +67,7 @@
#include
#include
#include
+#include
#include
#include
@@ -98,7 +100,7 @@ namespace HERE = StdMeshers_ProjectionUtils;
namespace {
- static SMESHDS_Mesh* theMeshDS[2] = { 0, 0 }; // used to debug only
+ static SMESHDS_Mesh* theMeshDS[2] = { 0, 0 }; // used for debug only
long shapeIndex(const TopoDS_Shape& S)
{
if ( theMeshDS[0] && theMeshDS[1] )
@@ -548,7 +550,7 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the
// ----------------------------------------------------------------------
case TopAbs_EDGE: { // TopAbs_EDGE
// ----------------------------------------------------------------------
- if ( theMap.Extent() != 2 )
+ if ( theMap.Extent() != 1 )
RETURN_BAD_RESULT("Wrong map extent " << theMap.Extent() );
TopoDS_Edge edge1 = TopoDS::Edge( theShape1 );
TopoDS_Edge edge2 = TopoDS::Edge( theShape2 );
@@ -656,7 +658,6 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the
TopoDS_Shape F1, F2;
// get a face sharing edge1 (F1)
- TopoDS_Shape FF2[2];
TopTools_ListIteratorOfListOfShape ancestIt1( edgeToFace1.FindFromKey( edge1 ));
for ( ; F1.IsNull() && ancestIt1.More(); ancestIt1.Next() )
if ( ancestIt1.Value().ShapeType() == TopAbs_FACE )
@@ -666,6 +667,7 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the
RETURN_BAD_RESULT(" Face1 not found");
// get 2 faces sharing edge2 (one of them is F2)
+ TopoDS_Shape FF2[2];
TopTools_ListIteratorOfListOfShape ancestIt2( edgeToFace2.FindFromKey( edge2 ));
for ( int i = 0; FF2[1].IsNull() && ancestIt2.More(); ancestIt2.Next() )
if ( ancestIt2.Value().ShapeType() == TopAbs_FACE )
@@ -1244,8 +1246,9 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the
double minDist = std::numeric_limits::max();
for ( int nbChecked=0; edge1 != allBndEdges1.end() && nbChecked++ < 10; ++edge1 )
{
- TopExp::Vertices( TopoDS::Edge( edge1->Oriented(TopAbs_FORWARD)), VV1[0], VV1[1]);
- if ( VV1[0].IsSame( VV1[1] ))
+ TopoDS_Vertex edge1VV[2];
+ TopExp::Vertices( TopoDS::Edge( edge1->Oriented(TopAbs_FORWARD)), edge1VV[0], edge1VV[1]);
+ if ( edge1VV[0].IsSame( edge1VV[1] ))
continue;//RETURN_BAD_RESULT("Only closed edges");
// find vertices closest to 2 linked vertices of shape 1
@@ -1253,7 +1256,7 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the
TopoDS_Vertex edge2VV[2];
for ( int i1 = 0; i1 < 2; ++i1 )
{
- gp_Pnt p1 = BRep_Tool::Pnt( VV1[ i1 ]);
+ gp_Pnt p1 = BRep_Tool::Pnt( edge1VV[ i1 ]);
p1.Scale( gc[0], scale );
p1.Translate( vec01 );
if ( !i1 ) {
@@ -1289,6 +1292,8 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the
}
}
if ( dist2[0] + dist2[1] < minDist ) {
+ VV1[0] = edge1VV[0];
+ VV1[1] = edge1VV[1];
VV2[0] = edge2VV[0];
VV2[1] = edge2VV[1];
minDist = dist2[0] + dist2[1];
@@ -1448,8 +1453,10 @@ int StdMeshers_ProjectionUtils::FindFaceAssociation(const TopoDS_Face& face1,
edge1End = edge1Beg;
std::advance( edge1End, *nbE1 );
// UV on face1 to find on face2
- v0f1UV = BRep_Tool::Parameters( TopExp::FirstVertex(*edge1Beg,true), face1 );
- v1f1UV = BRep_Tool::Parameters( TopExp::LastVertex (*edge1Beg,true), face1 );
+ TopoDS_Vertex v01 = SMESH_MesherHelper::IthVertex(0,*edge1Beg);
+ TopoDS_Vertex v11 = SMESH_MesherHelper::IthVertex(1,*edge1Beg);
+ v0f1UV = BRep_Tool::Parameters( v01, face1 );
+ v1f1UV = BRep_Tool::Parameters( v11, face1 );
v0f1UV.ChangeCoord() += dUV;
v1f1UV.ChangeCoord() += dUV;
//
@@ -1474,9 +1481,30 @@ int StdMeshers_ProjectionUtils::FindFaceAssociation(const TopoDS_Face& face1,
sameVertexUV( *edge2Beg, face2, 0, v0f1UV, vTolUV ))
{
if ( iW1 == 0 ) OK = true; // OK is for the first wire
+
// reverse edges2 if needed
- if ( !sameVertexUV( *edge2Beg, face2, 1, v1f1UV, vTolUV ))
- reverseEdges( edges2 , *nbE2, std::distance( edges2.begin(),edge2Beg ));
+ if ( SMESH_MesherHelper::IsClosedEdge( *edge1Beg ))
+ {
+ double f,l;
+ Handle(Geom2d_Curve) c1 = BRep_Tool::CurveOnSurface( *edge1Beg, face1,f,l );
+ if ( edge1Beg->Orientation() == TopAbs_REVERSED )
+ std::swap( f,l );
+ gp_Pnt2d uv1 = dUV + c1->Value( f * 0.8 + l * 0.2 ).XY();
+
+ Handle(Geom2d_Curve) c2 = BRep_Tool::CurveOnSurface( *edge2Beg, face2,f,l );
+ if ( edge2Beg->Orientation() == TopAbs_REVERSED )
+ std::swap( f,l );
+ gp_Pnt2d uv2 = c2->Value( f * 0.8 + l * 0.2 );
+
+ if ( uv1.Distance( uv2 ) > vTolUV )
+ edge2Beg->Reverse();
+ }
+ else
+ {
+ if ( !sameVertexUV( *edge2Beg, face2, 1, v1f1UV, vTolUV ))
+ reverseEdges( edges2 , *nbE2, std::distance( edges2.begin(),edge2Beg ));
+ }
+
// put wire2 at a right place within edges2
if ( iW1 != iW2 ) {
list< TopoDS_Edge >::iterator place2 = edges2.begin();
@@ -1914,97 +1942,109 @@ FindMatchingNodesOnFaces( const TopoDS_Face& face1,
// 2. face sets
- set Elems1, Elems2;
- for ( int is2 = 0; is2 < 2; ++is2 )
+ int assocRes;
+ for ( int iAttempt = 0; iAttempt < 2; ++iAttempt )
{
- set & elems = is2 ? Elems2 : Elems1;
- SMESHDS_SubMesh* sm = is2 ? SM2 : SM1;
- SMESH_MesherHelper* helper = is2 ? &helper2 : &helper1;
- const TopoDS_Face & face = is2 ? face2 : face1;
- SMDS_ElemIteratorPtr eIt = sm->GetElements();
-
- if ( !helper->IsRealSeam( is2 ? edge2 : edge1 ))
+ set Elems1, Elems2;
+ for ( int is2 = 0; is2 < 2; ++is2 )
{
- while ( eIt->more() ) elems.insert( eIt->next() );
- }
- else
- {
- // the only suitable edge is seam, i.e. it is a sphere.
- // FindMatchingNodes() will not know which way to go from any edge.
- // So we ignore all faces having nodes on edges or vertices except
- // one of faces sharing current start nodes
+ set & elems = is2 ? Elems2 : Elems1;
+ SMESHDS_SubMesh* sm = is2 ? SM2 : SM1;
+ SMESH_MesherHelper* helper = is2 ? &helper2 : &helper1;
+ const TopoDS_Face & face = is2 ? face2 : face1;
+ SMDS_ElemIteratorPtr eIt = sm->GetElements();
- // find a face to keep
- const SMDS_MeshElement* faceToKeep = 0;
- const SMDS_MeshNode* vNode = is2 ? vNode2 : vNode1;
- const SMDS_MeshNode* eNode = is2 ? eNode2[0] : eNode1[0];
- TIDSortedElemSet inSet, notInSet;
-
- const SMDS_MeshElement* f1 =
- SMESH_MeshAlgos::FindFaceInSet( vNode, eNode, inSet, notInSet );
- if ( !f1 ) RETURN_BAD_RESULT("The first face on seam not found");
- notInSet.insert( f1 );
-
- const SMDS_MeshElement* f2 =
- SMESH_MeshAlgos::FindFaceInSet( vNode, eNode, inSet, notInSet );
- if ( !f2 ) RETURN_BAD_RESULT("The second face on seam not found");
-
- // select a face with less UV of vNode
- const SMDS_MeshNode* notSeamNode[2] = {0, 0};
- for ( int iF = 0; iF < 2; ++iF ) {
- const SMDS_MeshElement* f = ( iF ? f2 : f1 );
- for ( int i = 0; !notSeamNode[ iF ] && i < f->NbNodes(); ++i ) {
- const SMDS_MeshNode* node = f->GetNode( i );
- if ( !helper->IsSeamShape( node->getshapeId() ))
- notSeamNode[ iF ] = node;
- }
+ if ( !helper->IsRealSeam( is2 ? edge2 : edge1 ))
+ {
+ while ( eIt->more() ) elems.insert( elems.end(), eIt->next() );
}
- gp_Pnt2d uv1 = helper->GetNodeUV( face, vNode, notSeamNode[0] );
- gp_Pnt2d uv2 = helper->GetNodeUV( face, vNode, notSeamNode[1] );
- if ( uv1.X() + uv1.Y() > uv2.X() + uv2.Y() )
- faceToKeep = f2;
else
- faceToKeep = f1;
+ {
+ // the only suitable edge is seam, i.e. it is a sphere.
+ // FindMatchingNodes() will not know which way to go from any edge.
+ // So we ignore all faces having nodes on edges or vertices except
+ // one of faces sharing current start nodes
- // fill elem set
- elems.insert( faceToKeep );
- while ( eIt->more() ) {
- const SMDS_MeshElement* f = eIt->next();
- int nbNodes = f->NbNodes();
- if ( f->IsQuadratic() )
- nbNodes /= 2;
- bool onBnd = false;
- for ( int i = 0; !onBnd && i < nbNodes; ++i ) {
- const SMDS_MeshNode* node = f->GetNode( i );
- onBnd = ( node->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE);
+ // find a face to keep
+ const SMDS_MeshElement* faceToKeep = 0;
+ const SMDS_MeshNode* vNode = is2 ? vNode2 : vNode1;
+ const SMDS_MeshNode* eNode = is2 ? eNode2[0] : eNode1[0];
+ TIDSortedElemSet inSet, notInSet;
+
+ const SMDS_MeshElement* f1 =
+ SMESH_MeshAlgos::FindFaceInSet( vNode, eNode, inSet, notInSet );
+ if ( !f1 ) RETURN_BAD_RESULT("The first face on seam not found");
+ notInSet.insert( f1 );
+
+ const SMDS_MeshElement* f2 =
+ SMESH_MeshAlgos::FindFaceInSet( vNode, eNode, inSet, notInSet );
+ if ( !f2 ) RETURN_BAD_RESULT("The second face on seam not found");
+
+ // select a face with less UV of vNode
+ const SMDS_MeshNode* notSeamNode[2] = {0, 0};
+ for ( int iF = 0; iF < 2; ++iF ) {
+ const SMDS_MeshElement* f = ( iF ? f2 : f1 );
+ for ( int i = 0; !notSeamNode[ iF ] && i < f->NbNodes(); ++i ) {
+ const SMDS_MeshNode* node = f->GetNode( i );
+ if ( !helper->IsSeamShape( node->getshapeId() ))
+ notSeamNode[ iF ] = node;
+ }
}
- if ( !onBnd )
- elems.insert( f );
- }
- // add also faces adjacent to faceToKeep
- int nbNodes = faceToKeep->NbNodes();
- if ( faceToKeep->IsQuadratic() ) nbNodes /= 2;
- notInSet.insert( f1 );
- notInSet.insert( f2 );
- for ( int i = 0; i < nbNodes; ++i ) {
- const SMDS_MeshNode* n1 = faceToKeep->GetNode( i );
- const SMDS_MeshNode* n2 = faceToKeep->GetNode(( i+1 ) % nbNodes );
- f1 = SMESH_MeshAlgos::FindFaceInSet( n1, n2, inSet, notInSet );
- if ( f1 )
- elems.insert( f1 );
- }
- } // case on a sphere
- } // loop on 2 faces
+ gp_Pnt2d uv1 = helper->GetNodeUV( face, vNode, notSeamNode[0] );
+ gp_Pnt2d uv2 = helper->GetNodeUV( face, vNode, notSeamNode[1] );
+ if ( uv1.X() + uv1.Y() > uv2.X() + uv2.Y() )
+ faceToKeep = f2;
+ else
+ faceToKeep = f1;
- // int quadFactor = (*Elems1.begin())->IsQuadratic() ? 2 : 1;
+ // fill elem set
+ elems.insert( faceToKeep );
+ while ( eIt->more() ) {
+ const SMDS_MeshElement* f = eIt->next();
+ int nbNodes = f->NbNodes();
+ if ( f->IsQuadratic() )
+ nbNodes /= 2;
+ bool onBnd = false;
+ for ( int i = 0; !onBnd && i < nbNodes; ++i ) {
+ const SMDS_MeshNode* node = f->GetNode( i );
+ onBnd = ( node->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE);
+ }
+ if ( !onBnd )
+ elems.insert( f );
+ }
+ // add also faces adjacent to faceToKeep
+ int nbNodes = faceToKeep->NbNodes();
+ if ( faceToKeep->IsQuadratic() ) nbNodes /= 2;
+ notInSet.insert( f1 );
+ notInSet.insert( f2 );
+ for ( int i = 0; i < nbNodes; ++i ) {
+ const SMDS_MeshNode* n1 = faceToKeep->GetNode( i );
+ const SMDS_MeshNode* n2 = faceToKeep->GetNode(( i+1 ) % nbNodes );
+ f1 = SMESH_MeshAlgos::FindFaceInSet( n1, n2, inSet, notInSet );
+ if ( f1 )
+ elems.insert( f1 );
+ }
+ } // case on a sphere
+ } // loop on 2 faces
- node1To2Map.clear();
- int res = SMESH_MeshEditor::FindMatchingNodes( Elems1, Elems2,
- vNode1, vNode2,
- eNode1[0], eNode2[0],
- node1To2Map);
- if ( res != SMESH_MeshEditor::SEW_OK )
- RETURN_BAD_RESULT("FindMatchingNodes() result " << res );
+ node1To2Map.clear();
+ assocRes = SMESH_MeshEditor::FindMatchingNodes( Elems1, Elems2,
+ vNode1, vNode2,
+ eNode1[0], eNode2[0],
+ node1To2Map);
+ if (( assocRes != SMESH_MeshEditor::SEW_OK ) &&
+ ( eNode1[1] || eNode2[1] )) // there is another node to try (on a closed EDGE)
+ {
+ node1To2Map.clear();
+ if ( eNode1[1] ) std::swap( eNode1[0], eNode1[1] );
+ else std::swap( eNode2[0], eNode2[1] );
+ continue; // one more attempt
+ }
+
+ break;
+ }
+ if ( assocRes != SMESH_MeshEditor::SEW_OK )
+ RETURN_BAD_RESULT("FindMatchingNodes() result " << assocRes );
// On a sphere, add matching nodes on the edge
@@ -2402,3 +2442,229 @@ void StdMeshers_ProjectionUtils::SetEventListener(SMESH_subMesh* subMesh,
}
}
}
+
+namespace StdMeshers_ProjectionUtils
+{
+
+ //================================================================================
+ /*!
+ * \brief Computes transformation beween two sets of 2D points using
+ * a least square approximation
+ *
+ * See "Surface Mesh Projection For Hexahedral Mesh Generation By Sweeping"
+ * by X.Roca, J.Sarrate, A.Huerta. (2.2)
+ */
+ //================================================================================
+
+ bool TrsfFinder2D::Solve( const vector< gp_XY >& srcPnts,
+ const vector< gp_XY >& tgtPnts )
+ {
+ // find gravity centers
+ gp_XY srcGC( 0,0 ), tgtGC( 0,0 );
+ for ( size_t i = 0; i < srcPnts.size(); ++i )
+ {
+ srcGC += srcPnts[i];
+ tgtGC += tgtPnts[i];
+ }
+ srcGC /= srcPnts.size();
+ tgtGC /= tgtPnts.size();
+
+ // find trsf
+
+ math_Matrix mat (1,4,1,4, 0.);
+ math_Vector vec (1,4, 0.);
+
+ // cout << "m1 = smesh.Mesh('src')" << endl
+ // << "m2 = smesh.Mesh('tgt')" << endl;
+ double xx = 0, xy = 0, yy = 0;
+ for ( size_t i = 0; i < srcPnts.size(); ++i )
+ {
+ gp_XY srcUV = srcPnts[i] - srcGC;
+ gp_XY tgtUV = tgtPnts[i] - tgtGC;
+ xx += srcUV.X() * srcUV.X();
+ yy += srcUV.Y() * srcUV.Y();
+ xy += srcUV.X() * srcUV.Y();
+ vec( 1 ) += srcUV.X() * tgtUV.X();
+ vec( 2 ) += srcUV.Y() * tgtUV.X();
+ vec( 3 ) += srcUV.X() * tgtUV.Y();
+ vec( 4 ) += srcUV.Y() * tgtUV.Y();
+ // cout << "m1.AddNode( " << srcUV.X() << ", " << srcUV.Y() << ", 0 )" << endl
+ // << "m2.AddNode( " << tgtUV.X() << ", " << tgtUV.Y() << ", 0 )" << endl;
+ }
+ mat( 1,1 ) = mat( 3,3 ) = xx;
+ mat( 2,2 ) = mat( 4,4 ) = yy;
+ mat( 1,2 ) = mat( 2,1 ) = mat( 3,4 ) = mat( 4,3 ) = xy;
+
+ math_Gauss solver( mat );
+ if ( !solver.IsDone() )
+ return false;
+ solver.Solve( vec );
+ if ( vec.Norm2() < gp::Resolution() )
+ return false;
+ // cout << vec( 1 ) << "\t " << vec( 2 ) << endl
+ // << vec( 3 ) << "\t " << vec( 4 ) << endl;
+
+ _trsf.SetTranslation( tgtGC );
+ _srcOrig = srcGC;
+
+ gp_Mat2d& M = const_cast< gp_Mat2d& >( _trsf.HVectorialPart());
+ M( 1,1 ) = vec( 1 );
+ M( 2,1 ) = vec( 2 );
+ M( 1,2 ) = vec( 3 );
+ M( 2,2 ) = vec( 4 );
+
+ return true;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Transforms a 2D points using a found transformation
+ */
+ //================================================================================
+
+ gp_XY TrsfFinder2D::Transform( const gp_Pnt2d& srcUV ) const
+ {
+ gp_XY uv = srcUV.XY() - _srcOrig ;
+ _trsf.Transforms( uv );
+ return uv;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Computes transformation beween two sets of 3D points using
+ * a least square approximation
+ *
+ * See "Surface Mesh Projection For Hexahedral Mesh Generation By Sweeping"
+ * by X.Roca, J.Sarrate, A.Huerta. (2.4)
+ */
+ //================================================================================
+
+ bool TrsfFinder3D::Solve( const vector< gp_XYZ > & srcPnts,
+ const vector< gp_XYZ > & tgtPnts )
+ {
+ // find gravity center
+ gp_XYZ srcGC( 0,0,0 ), tgtGC( 0,0,0 );
+ for ( size_t i = 0; i < srcPnts.size(); ++i )
+ {
+ srcGC += srcPnts[i];
+ tgtGC += tgtPnts[i];
+ }
+ srcGC /= srcPnts.size();
+ tgtGC /= tgtPnts.size();
+
+ gp_XYZ srcOrig = 2 * srcGC - tgtGC;
+ gp_XYZ tgtOrig = srcGC;
+
+ // find trsf
+
+ math_Matrix mat (1,9,1,9, 0.);
+ math_Vector vec (1,9, 0.);
+
+ double xx = 0, yy = 0, zz = 0;
+ double xy = 0, xz = 0, yz = 0;
+ for ( size_t i = 0; i < srcPnts.size(); ++i )
+ {
+ gp_XYZ src = srcPnts[i] - srcOrig;
+ gp_XYZ tgt = tgtPnts[i] - tgtOrig;
+ xx += src.X() * src.X();
+ yy += src.Y() * src.Y();
+ zz += src.Z() * src.Z();
+ xy += src.X() * src.Y();
+ xz += src.X() * src.Z();
+ yz += src.Y() * src.Z();
+ vec( 1 ) += src.X() * tgt.X();
+ vec( 2 ) += src.Y() * tgt.X();
+ vec( 3 ) += src.Z() * tgt.X();
+ vec( 4 ) += src.X() * tgt.Y();
+ vec( 5 ) += src.Y() * tgt.Y();
+ vec( 6 ) += src.Z() * tgt.Y();
+ vec( 7 ) += src.X() * tgt.Z();
+ vec( 8 ) += src.Y() * tgt.Z();
+ vec( 9 ) += src.Z() * tgt.Z();
+ }
+ mat( 1,1 ) = mat( 4,4 ) = mat( 7,7 ) = xx;
+ mat( 2,2 ) = mat( 5,5 ) = mat( 8,8 ) = yy;
+ mat( 3,3 ) = mat( 6,6 ) = mat( 9,9 ) = zz;
+ mat( 1,2 ) = mat( 2,1 ) = mat( 4,5 ) = mat( 5,4 ) = mat( 7,8 ) = mat( 8,7 ) = xy;
+ mat( 1,3 ) = mat( 3,1 ) = mat( 4,6 ) = mat( 6,4 ) = mat( 7,9 ) = mat( 9,7 ) = xz;
+ mat( 2,3 ) = mat( 3,2 ) = mat( 5,6 ) = mat( 6,5 ) = mat( 8,9 ) = mat( 9,8 ) = yz;
+
+ math_Gauss solver( mat );
+ if ( !solver.IsDone() )
+ return false;
+ solver.Solve( vec );
+ if ( vec.Norm2() < gp::Resolution() )
+ return false;
+ // cout << endl
+ // << vec( 1 ) << "\t " << vec( 2 ) << "\t " << vec( 3 ) << endl
+ // << vec( 4 ) << "\t " << vec( 5 ) << "\t " << vec( 6 ) << endl
+ // << vec( 7 ) << "\t " << vec( 8 ) << "\t " << vec( 9 ) << endl;
+
+ _srcOrig = srcOrig;
+ _trsf.SetTranslation( tgtOrig );
+
+ gp_Mat& M = const_cast< gp_Mat& >( _trsf.HVectorialPart() );
+ M.SetRows( gp_XYZ( vec( 1 ), vec( 2 ), vec( 3 )),
+ gp_XYZ( vec( 4 ), vec( 5 ), vec( 6 )),
+ gp_XYZ( vec( 7 ), vec( 8 ), vec( 9 )));
+ return true;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Transforms a 3D point using a found transformation
+ */
+ //================================================================================
+
+ gp_XYZ TrsfFinder3D::Transform( const gp_Pnt& srcP ) const
+ {
+ gp_XYZ p = srcP.XYZ() - _srcOrig;
+ _trsf.Transforms( p );
+ return p;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Transforms a 3D vector using a found transformation
+ */
+ //================================================================================
+
+ gp_XYZ TrsfFinder3D::TransformVec( const gp_Vec& v ) const
+ {
+ return v.XYZ().Multiplied( _trsf.HVectorialPart() );
+ }
+ //================================================================================
+ /*!
+ * \brief Inversion
+ */
+ //================================================================================
+
+ bool TrsfFinder3D::Invert()
+ {
+ if (( _trsf.Form() == gp_Translation ) &&
+ ( _srcOrig.X() != 0 || _srcOrig.Y() != 0 || _srcOrig.Z() != 0 ))
+ {
+ // seems to be defined via Solve()
+ gp_XYZ newSrcOrig = _trsf.TranslationPart();
+ gp_Mat& M = const_cast< gp_Mat& >( _trsf.HVectorialPart() );
+ const double D = M.Determinant();
+ if ( D < 1e-3 * ( newSrcOrig - _srcOrig ).Modulus() )
+ {
+#ifdef _DEBUG_
+ cerr << "TrsfFinder3D::Invert()"
+ << "D " << M.Determinant() << " IsSingular " << M.IsSingular() << endl;
+#endif
+ return false;
+ }
+ gp_Mat Minv = M.Inverted();
+ _trsf.SetTranslation( _srcOrig );
+ _srcOrig = newSrcOrig;
+ M = Minv;
+ }
+ else
+ {
+ _trsf.Invert();
+ }
+ return true;
+ }
+}
diff --git a/src/StdMeshers/StdMeshers_ProjectionUtils.hxx b/src/StdMeshers/StdMeshers_ProjectionUtils.hxx
index 31afb072f..e7ea4423d 100644
--- a/src/StdMeshers/StdMeshers_ProjectionUtils.hxx
+++ b/src/StdMeshers/StdMeshers_ProjectionUtils.hxx
@@ -30,10 +30,14 @@
#include "SMESH_StdMeshers.hxx"
+#include "SMDS_MeshElement.hxx"
+
#include
#include
-#include
#include
+#include
+#include
+#include
#include
#include
@@ -77,7 +81,54 @@ namespace StdMeshers_ProjectionUtils
{
typedef StdMeshers_ShapeShapeBiDirectionMap TShapeShapeMap;
typedef TopTools_IndexedDataMapOfShapeListOfShape TAncestorMap;
- typedef std::map TNodeNodeMap;
+ typedef std::map TNodeNodeMap;
+
+
+ /*!
+ * \brief Finds transformation beween two sets of 2D points using
+ * a least square approximation
+ */
+ class TrsfFinder2D
+ {
+ gp_Trsf2d _trsf;
+ gp_XY _srcOrig;
+ public:
+ TrsfFinder2D(): _srcOrig(0,0) {}
+
+ void Set( const gp_Trsf2d& t ) { _trsf = t; } // it's an alternative to Solve()
+
+ bool Solve( const std::vector< gp_XY >& srcPnts,
+ const std::vector< gp_XY >& tgtPnts );
+
+ gp_XY Transform( const gp_Pnt2d& srcUV ) const;
+
+ bool IsIdentity() const { return ( _trsf.Form() == gp_Identity ); }
+ };
+ /*!
+ * \brief Finds transformation beween two sets of 3D points using
+ * a least square approximation
+ */
+ class TrsfFinder3D
+ {
+ gp_Trsf _trsf;
+ gp_XYZ _srcOrig;
+ public:
+ TrsfFinder3D(): _srcOrig(0,0,0) {}
+
+ void Set( const gp_Trsf& t ) { _trsf = t; } // it's an alternative to Solve()
+
+ bool Solve( const std::vector< gp_XYZ > & srcPnts,
+ const std::vector< gp_XYZ > & tgtPnts );
+
+ gp_XYZ Transform( const gp_Pnt& srcP ) const;
+
+ gp_XYZ TransformVec( const gp_Vec& v ) const;
+
+ bool IsIdentity() const { return ( _trsf.Form() == gp_Identity ); }
+
+ bool Invert();
+ };
/*!
* \brief Looks for association of all sub-shapes of two shapes
diff --git a/src/StdMeshers/StdMeshers_Projection_2D.cxx b/src/StdMeshers/StdMeshers_Projection_2D.cxx
index a0eb3248f..7b3d1e1e1 100644
--- a/src/StdMeshers/StdMeshers_Projection_2D.cxx
+++ b/src/StdMeshers/StdMeshers_Projection_2D.cxx
@@ -47,8 +47,11 @@
#include "utilities.h"
+#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -139,6 +142,7 @@ bool StdMeshers_Projection_2D::CheckHypothesis(SMESH_Mesh&
!SMESH_MesherHelper::IsSubShape( edge, _sourceHypo->GetSourceFace() ))
{
theStatus = HYP_BAD_PARAMETER;
+ error("Invalid source vertices");
SCRUTE((edge.IsNull()));
SCRUTE((SMESH_MesherHelper::IsSubShape( edge, srcMesh )));
SCRUTE((SMESH_MesherHelper::IsSubShape( edge, _sourceHypo->GetSourceFace() )));
@@ -151,6 +155,7 @@ bool StdMeshers_Projection_2D::CheckHypothesis(SMESH_Mesh&
if ( edge.IsNull() || !SMESH_MesherHelper::IsSubShape( edge, tgtMesh ))
{
theStatus = HYP_BAD_PARAMETER;
+ error("Invalid target vertices");
SCRUTE((edge.IsNull()));
SCRUTE((SMESH_MesherHelper::IsSubShape( edge, tgtMesh )));
}
@@ -159,6 +164,7 @@ bool StdMeshers_Projection_2D::CheckHypothesis(SMESH_Mesh&
!SMESH_MesherHelper::IsSubShape( edge, theShape ))
{
theStatus = HYP_BAD_PARAMETER;
+ error("Invalid target vertices");
SCRUTE((SMESH_MesherHelper::IsSubShape( edge, theShape )));
}
}
@@ -168,6 +174,7 @@ bool StdMeshers_Projection_2D::CheckHypothesis(SMESH_Mesh&
( srcMesh == tgtMesh && theShape == _sourceHypo->GetSourceFace() ))
{
theStatus = HYP_BAD_PARAMETER;
+ error("Invalid source face");
SCRUTE((SMESH_MesherHelper::IsSubShape( _sourceHypo->GetSourceFace(), srcMesh )));
SCRUTE((srcMesh == tgtMesh));
SCRUTE(( theShape == _sourceHypo->GetSourceFace() ));
@@ -190,7 +197,7 @@ namespace {
*/
//================================================================================
- bool isOldNode( const SMDS_MeshNode* node/*, const bool is1DComputed*/ )
+ bool isOldNode( const SMDS_MeshNode* node )
{
// old nodes are shared by edges and new ones are shared
// only by faces created by mapper
@@ -370,227 +377,274 @@ namespace {
//================================================================================
/*!
- * \brief Preform projection in case if tgtFace.IsPartner( srcFace ) and in case
- * if projection by transformation is possible
+ * \brief Check if two consecutive EDGEs are connected in 2D
+ * \param [in] E1 - a well oriented non-seam EDGE
+ * \param [in] E2 - a possibly well oriented seam EDGE
+ * \param [in] F - a FACE
+ * \return bool - result
*/
//================================================================================
- bool projectPartner(const TopoDS_Face& tgtFace,
- const TopoDS_Face& srcFace,
- SMESH_Mesh * tgtMesh,
- SMESH_Mesh * srcMesh,
- const TAssocTool::TShapeShapeMap& shape2ShapeMap)
+ bool are2dConnected( const TopoDS_Edge & E1,
+ const TopoDS_Edge & E2,
+ const TopoDS_Face & F )
+ {
+ double f,l;
+ Handle(Geom2d_Curve) c1 = BRep_Tool::CurveOnSurface( E1, F, f, l );
+ gp_Pnt2d uvLast1 = c1->Value( E1.Orientation() == TopAbs_REVERSED ? f : l );
+
+ Handle(Geom2d_Curve) c2 = BRep_Tool::CurveOnSurface( E2, F, f, l );
+ gp_Pnt2d uvFirst2 = c2->Value( f );
+ gp_Pnt2d uvLast2 = c2->Value( l );
+ double tol2 = 1e-5 * uvLast2.SquareDistance( uvFirst2 );
+
+ return (( uvLast1.SquareDistance( uvFirst2 ) < tol2 ) ||
+ ( uvLast1.SquareDistance( uvLast2 ) < tol2 ));
+ }
+
+ //================================================================================
+ /*!
+ * \brief Compose TSideVector for both FACEs keeping matching order of EDGEs
+ * and fill src2tgtNodes map
+ */
+ //================================================================================
+
+ TError getWires(const TopoDS_Face& tgtFace,
+ const TopoDS_Face& srcFace,
+ SMESH_Mesh * tgtMesh,
+ SMESH_Mesh * srcMesh,
+ const TAssocTool::TShapeShapeMap& shape2ShapeMap,
+ TSideVector& srcWires,
+ TSideVector& tgtWires,
+ TAssocTool::TNodeNodeMap& src2tgtNodes,
+ bool& is1DComputed)
{
SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
+ src2tgtNodes.clear();
+
+ // get ordered src EDGEs
+ TError err;
+ srcWires = StdMeshers_FaceSide::GetFaceWires( srcFace, *srcMesh,/*skipMediumNodes=*/0, err);
+ if ( err && !err->IsOK() )
+ return err;
+
+ // make corresponding sequence of tgt EDGEs
+ tgtWires.resize( srcWires.size() );
+ for ( size_t iW = 0; iW < srcWires.size(); ++iW )
+ {
+ list< TopoDS_Edge > tgtEdges;
+ StdMeshers_FaceSidePtr srcWire = srcWires[iW];
+ TopTools_IndexedMapOfShape edgeMap; // to detect seam edges
+ for ( int iE = 0; iE < srcWire->NbEdges(); ++iE )
+ {
+ TopoDS_Edge srcE = srcWire->Edge( iE );
+ TopoDS_Edge tgtE = TopoDS::Edge( shape2ShapeMap( srcE, /*isSrc=*/true));
+ TopoDS_Shape srcEbis = shape2ShapeMap( tgtE, /*isSrc=*/false );
+ if ( srcE.Orientation() != srcEbis.Orientation() )
+ tgtE.Reverse();
+ // reverse a seam edge encountered for the second time
+ const int index = edgeMap.Add( tgtE );
+ if ( index < edgeMap.Extent() ) // E is a seam
+ {
+ // check which of edges to reverse, E or one already being in tgtEdges
+ if ( are2dConnected( tgtEdges.back(), tgtE, tgtFace ))
+ {
+ list< TopoDS_Edge >::iterator eIt = tgtEdges.begin();
+ std::advance( eIt, index-1 );
+ eIt->Reverse();
+ }
+ else
+ {
+ tgtE.Reverse();
+ }
+ }
+ if ( srcWire->NbEdges() == 1 && tgtMesh == srcMesh ) // circle
+ {
+ // try to verify ori by propagation
+ pair nE =
+ StdMeshers_ProjectionUtils::GetPropagationEdge( srcMesh, tgtE, srcE );
+ if ( !nE.second.IsNull() )
+ tgtE = nE.second;
+ }
+ tgtEdges.push_back( tgtE );
+
+
+ // Fill map of src to tgt nodes with nodes on edges
+
+ if ( srcMesh->GetSubMesh( srcE )->IsEmpty() ||
+ tgtMesh->GetSubMesh( tgtE )->IsEmpty() )
+ {
+ // add nodes on VERTEXes for a case of not meshes EDGEs
+ const TopoDS_Shape& srcV = SMESH_MesherHelper::IthVertex( 0, srcE );
+ const TopoDS_Shape& tgtV = shape2ShapeMap( srcV, /*isSrc=*/true );
+ const SMDS_MeshNode* srcN = SMESH_Algo::VertexNode( TopoDS::Vertex( srcV ), srcMeshDS );
+ const SMDS_MeshNode* tgtN = SMESH_Algo::VertexNode( TopoDS::Vertex( tgtV ), tgtMeshDS );
+ if ( srcN && tgtN )
+ src2tgtNodes.insert( make_pair( srcN, tgtN ));
+ }
+ else
+ {
+ const bool skipMediumNodes = true;
+ map< double, const SMDS_MeshNode* > srcNodes, tgtNodes;
+ if ( !SMESH_Algo::GetSortedNodesOnEdge( srcMeshDS, srcE, skipMediumNodes, srcNodes) ||
+ !SMESH_Algo::GetSortedNodesOnEdge( tgtMeshDS, tgtE, skipMediumNodes, tgtNodes ))
+ return SMESH_ComputeError::New( COMPERR_BAD_INPUT_MESH,
+ "Invalid node parameters on edges");
+
+ if (( srcNodes.size() != tgtNodes.size() ) && tgtNodes.size() > 0 )
+ return SMESH_ComputeError::New( COMPERR_BAD_INPUT_MESH,
+ "Different number of nodes on edges");
+ if ( !tgtNodes.empty() )
+ {
+ map< double, const SMDS_MeshNode* >::iterator u_tn = tgtNodes.begin();
+ if ( srcE.Orientation() == tgtE.Orientation() )
+ {
+ map< double, const SMDS_MeshNode* >::iterator u_sn = srcNodes.begin();
+ for ( ; u_tn != tgtNodes.end(); ++u_tn, ++u_sn)
+ src2tgtNodes.insert( make_pair( u_sn->second, u_tn->second ));
+ }
+ else
+ {
+ map< double, const SMDS_MeshNode* >::reverse_iterator u_sn = srcNodes.rbegin();
+ for ( ; u_tn != tgtNodes.end(); ++u_tn, ++u_sn)
+ src2tgtNodes.insert( make_pair( u_sn->second, u_tn->second ));
+ }
+ is1DComputed = true;
+ }
+ }
+ } // loop on EDGEs of a WIRE
+
+ tgtWires[ iW ].reset( new StdMeshers_FaceSide( tgtFace, tgtEdges, tgtMesh,
+ /*theIsForward = */ true,
+ /*theIgnoreMediumNodes = */false));
+ } // loop on WIREs
+
+ return TError();
+ }
+
+ //================================================================================
+ /*!
+ * \brief Preform projection in case if tgtFace.IsPartner( srcFace ) and in case
+ * if projection by 3D transformation is possible
+ */
+ //================================================================================
+
+ bool projectPartner(const TopoDS_Face& tgtFace,
+ const TopoDS_Face& srcFace,
+ const TSideVector& tgtWires,
+ const TSideVector& srcWires,
+ const TAssocTool::TShapeShapeMap& shape2ShapeMap,
+ TAssocTool::TNodeNodeMap& src2tgtNodes,
+ const bool is1DComputed)
+ {
+ SMESH_Mesh * tgtMesh = tgtWires[0]->GetMesh();
+ SMESH_Mesh * srcMesh = srcWires[0]->GetMesh();
+ SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
+ SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
+ SMESH_MesherHelper helper( *tgtMesh );
+
const double tol = 1.e-7 * srcMeshDS->getMaxDim();
- gp_Trsf trsf; // transformation to get location of target nodes from source ones
+ // transformation to get location of target nodes from source ones
+ StdMeshers_ProjectionUtils::TrsfFinder3D trsf;
if ( tgtFace.IsPartner( srcFace ))
{
gp_Trsf srcTrsf = srcFace.Location();
gp_Trsf tgtTrsf = tgtFace.Location();
- trsf = srcTrsf.Inverted() * tgtTrsf;
+ trsf.Set( srcTrsf.Inverted() * tgtTrsf );
+ // check
+ gp_Pnt srcP = BRep_Tool::Pnt( srcWires[0]->FirstVertex() );
+ gp_Pnt tgtP = BRep_Tool::Pnt( tgtWires[0]->FirstVertex() );
+ if ( tgtP.Distance( trsf.Transform( srcP )) > tol )
+ trsf.Set( tgtTrsf.Inverted() * srcTrsf );
}
else
{
- // Try to find the transformation
+ // Try to find the 3D transformation
- // make any local coord systems of src and tgt faces
- vector srcPP, tgtPP; // 3 points on face boundaries to make axes of CS
- int tgtNbVert = SMESH_MesherHelper::Count( tgtFace, TopAbs_VERTEX, /*ignoreSame=*/true );
- int srcNbVert = SMESH_MesherHelper::Count( srcFace, TopAbs_VERTEX, /*ignoreSame=*/true );
- SMESH_subMesh * srcSM = srcMesh->GetSubMesh( srcFace );
- SMESH_subMeshIteratorPtr smIt = srcSM->getDependsOnIterator(/*includeSelf=*/false,false);
- srcSM = smIt->next(); // sm of a vertex
- while ( smIt->more() && srcPP.size() < 3 )
+ const int totNbSeg = 50;
+ vector< gp_XYZ > srcPnts, tgtPnts;
+ srcPnts.reserve( totNbSeg );
+ tgtPnts.reserve( totNbSeg );
+ gp_XYZ srcBC( 0,0,0 ), tgtBC( 0,0,0 );
+ for ( size_t iW = 0; iW < srcWires.size(); ++iW )
{
- srcSM = smIt->next();
- SMESHDS_SubMesh* srcSmds = srcSM->GetSubMeshDS();
- if ( !srcSmds ) continue;
- SMDS_NodeIteratorPtr nIt = srcSmds->GetNodes();
- while ( nIt->more() )
+ const double minSegLen = srcWires[iW]->Length() / totNbSeg;
+ for ( int iE = 0; iE < srcWires[iW]->NbEdges(); ++iE )
{
- SMESH_TNodeXYZ p ( nIt->next());
- bool pOK = false;
- switch ( srcPP.size() )
+ int nbSeg = Max( 1, int( srcWires[iW]->EdgeLength( iE ) / minSegLen ));
+ double srcU = srcWires[iW]->FirstParameter( iE );
+ double tgtU = tgtWires[iW]->FirstParameter( iE );
+ double srcDu = ( srcWires[iW]->LastParameter( iE )- srcU ) / nbSeg;
+ double tgtDu = ( tgtWires[iW]->LastParameter( iE )- tgtU ) / nbSeg;
+ for ( size_t i = 0; i < nbSeg; ++i )
{
- case 0: pOK = true; break;
-
- case 1: pOK = ( srcPP[0].SquareDistance( p ) > 10*tol ); break;
-
- case 2:
- {
- gp_Vec p0p1( srcPP[0], srcPP[1] ), p0p( srcPP[0], p );
- // pOK = !p0p1.IsParallel( p0p, tol );
- pOK = !p0p1.IsParallel( p0p, 3.14/20 ); // angle min 18 degrees
- break;
- }
+ srcPnts.push_back( srcWires[iW]->Value3d( srcU ).XYZ() );
+ tgtPnts.push_back( tgtWires[iW]->Value3d( tgtU ).XYZ() );
+ srcU += srcDu;
+ tgtU += tgtDu;
+ srcBC += srcPnts.back();
+ tgtBC += tgtPnts.back();
}
- if ( !pOK )
- continue;
-
- // find corresponding point on target shape
- pOK = false;
- gp_Pnt tgtP;
- const TopoDS_Shape& tgtShape = shape2ShapeMap( srcSM->GetSubShape(), /*isSrc=*/true );
- if ( tgtShape.ShapeType() == TopAbs_VERTEX )
- {
- tgtP = BRep_Tool::Pnt( TopoDS::Vertex( tgtShape ));
- if ( srcNbVert == tgtNbVert || tgtPP.empty() )
- pOK = true;
- else
- pOK = (( tgtP.Distance( tgtPP[0] ) > tol*tol ) &&
- ( tgtPP.size() == 1 || tgtP.Distance( tgtPP[1] ) > tol*tol ));
- //cout << "V - nS " << p._node->GetID() << " - nT " << SMESH_Algo::VertexNode(TopoDS::Vertex( tgtShape),tgtMeshDS)->GetID() << endl;
- }
- else if ( tgtPP.size() > 0 )
- {
- if ( SMESHDS_SubMesh* tgtSmds = tgtMeshDS->MeshElements( tgtShape ))
- {
- double srcDist = srcPP[0].Distance( p );
- double eTol = BRep_Tool::Tolerance( TopoDS::Edge( tgtShape ));
- if (eTol < tol) eTol = tol;
- SMDS_NodeIteratorPtr nItT = tgtSmds->GetNodes();
- while ( nItT->more() && !pOK )
- {
- const SMDS_MeshNode* n = nItT->next();
- tgtP = SMESH_TNodeXYZ( n );
- pOK = ( fabs( srcDist - tgtPP[0].Distance( tgtP )) < 2*eTol );
- //cout << "E - nS " << p._node->GetID() << " - nT " << n->GetID()<< " OK - " << pOK<< " " << fabs( srcDist - tgtPP[0].Distance( tgtP ))<< " tol " << eTol<< endl;
- }
- }
- }
- if ( !pOK )
- continue;
-
- srcPP.push_back( p );
- tgtPP.push_back( tgtP );
}
}
- if ( srcPP.size() != 3 )
+ if ( !trsf.Solve( srcPnts, tgtPnts ))
return false;
- // make transformation
- gp_Trsf fromTgtCS, toSrcCS; // from/to global CS
- gp_Ax2 srcCS( srcPP[0], gp_Vec( srcPP[0], srcPP[1] ), gp_Vec( srcPP[0], srcPP[2]));
- gp_Ax2 tgtCS( tgtPP[0], gp_Vec( tgtPP[0], tgtPP[1] ), gp_Vec( tgtPP[0], tgtPP[2]));
- toSrcCS .SetTransformation( gp_Ax3( srcCS ));
- fromTgtCS.SetTransformation( gp_Ax3( tgtCS ));
- fromTgtCS.Invert();
+ // check trsf
- trsf = fromTgtCS * toSrcCS;
- }
-
- // Fill map of src to tgt nodes with nodes on edges
-
- map src2tgtNodes;
- map::iterator srcN_tgtN;
-
- bool tgtEdgesMeshed = false;
- for ( TopExp_Explorer srcExp( srcFace, TopAbs_EDGE); srcExp.More(); srcExp.Next() )
- {
- const TopoDS_Shape& srcEdge = srcExp.Current();
- const TopoDS_Shape& tgtEdge = shape2ShapeMap( srcEdge, /*isSrc=*/true );
- tgtEdgesMeshed != tgtMesh->GetSubMesh( tgtEdge )->IsEmpty();
-
- if ( srcMesh->GetSubMesh( srcEdge )->IsEmpty() ||
- tgtMesh->GetSubMesh( tgtEdge )->IsEmpty() )
- continue;
-
- map< double, const SMDS_MeshNode* > srcNodes, tgtNodes;
- if (( ! SMESH_Algo::GetSortedNodesOnEdge( srcMeshDS,
- TopoDS::Edge( srcEdge ),
- /*ignoreMediumNodes = */true,
- srcNodes ))
- ||
- ( ! SMESH_Algo::GetSortedNodesOnEdge( tgtMeshDS,
- TopoDS::Edge( tgtEdge ),
- /*ignoreMediumNodes = */true,
- tgtNodes ))
- ||
- (( srcNodes.size() != tgtNodes.size() ) && tgtNodes.size() > 0 )
- )
+ bool trsfIsOK = true;
+ const int nbTestPnt = 20;
+ const size_t iStep = Max( 1, int( srcPnts.size() / nbTestPnt ));
+ // check boundary
+ gp_Pnt trsfTgt = trsf.Transform( srcBC / srcPnts.size() );
+ trsfIsOK = ( trsfTgt.SquareDistance( tgtBC / tgtPnts.size() ) < tol*tol );
+ for ( size_t i = 0; ( i < srcPnts.size() && trsfIsOK ); i += iStep )
+ {
+ gp_Pnt trsfTgt = trsf.Transform( srcPnts[i] );
+ trsfIsOK = ( trsfTgt.SquareDistance( tgtPnts[i] ) < tol*tol );
+ }
+ // check an in-FACE point
+ if ( trsfIsOK )
+ {
+ BRepAdaptor_Surface srcSurf( srcFace );
+ gp_Pnt srcP =
+ srcSurf.Value( 0.321 * ( srcSurf.FirstUParameter() + srcSurf.LastUParameter() ),
+ 0.123 * ( srcSurf.FirstVParameter() + srcSurf.LastVParameter() ));
+ gp_Pnt tgtTrsfP = trsf.Transform( srcP );
+ TopLoc_Location loc;
+ GeomAPI_ProjectPointOnSurf& proj = helper.GetProjector( tgtFace, loc, 0.1*tol );
+ if ( !loc.IsIdentity() )
+ tgtTrsfP.Transform( loc.Transformation().Inverted() );
+ proj.Perform( tgtTrsfP );
+ trsfIsOK = ( proj.IsDone() &&
+ proj.NbPoints() > 0 &&
+ proj.LowerDistance() < tol );
+ }
+ if ( !trsfIsOK )
return false;
-
- if ( !tgtEdge.IsPartner( srcEdge ))
- {
- if ( tgtNodes.empty() )
- return false;
- // check that transformation is OK by three nodes
- gp_Pnt p0S = SMESH_TNodeXYZ( (srcNodes.begin()) ->second);
- gp_Pnt p1S = SMESH_TNodeXYZ( (srcNodes.rbegin()) ->second);
- gp_Pnt p2S = SMESH_TNodeXYZ( (++srcNodes.begin())->second);
-
- gp_Pnt p0T = SMESH_TNodeXYZ( (tgtNodes.begin()) ->second);
- gp_Pnt p1T = SMESH_TNodeXYZ( (tgtNodes.rbegin()) ->second);
- gp_Pnt p2T = SMESH_TNodeXYZ( (++tgtNodes.begin())->second);
-
- // transform source points, they must coincide with target ones
- if ( p0T.SquareDistance( p0S.Transformed( trsf )) > tol ||
- p1T.SquareDistance( p1S.Transformed( trsf )) > tol ||
- p2T.SquareDistance( p2S.Transformed( trsf )) > tol )
- {
- //cout << "KO trsf, 3 dist: "
- //<< p0T.SquareDistance( p0S.Transformed( trsf ))<< ", "
- //<< p1T.SquareDistance( p1S.Transformed( trsf ))<< ", "
- //<< p2T.SquareDistance( p2S.Transformed( trsf ))<< ", "<::iterator u_tn = tgtNodes.begin();
- map< double, const SMDS_MeshNode* >::iterator u_sn = srcNodes.begin();
- for ( ; u_tn != tgtNodes.end(); ++u_tn, ++u_sn)
- src2tgtNodes.insert( make_pair( u_sn->second, u_tn->second ));
- }
}
- // check nodes on VERTEXes for a case of not meshes EDGEs
- for ( TopExp_Explorer srcExp( srcFace, TopAbs_VERTEX); srcExp.More(); srcExp.Next() )
- {
- const TopoDS_Shape& srcV = srcExp.Current();
- const TopoDS_Shape& tgtV = shape2ShapeMap( srcV, /*isSrc=*/true );
- const SMDS_MeshNode* srcN = SMESH_Algo::VertexNode( TopoDS::Vertex( srcV ), srcMeshDS );
- const SMDS_MeshNode* tgtN = SMESH_Algo::VertexNode( TopoDS::Vertex( tgtV ), srcMeshDS );
- if ( !srcN )
- continue;
- if ( !tgtN || tgtV.ShapeType() != TopAbs_VERTEX )
- return false;
-
- if ( !tgtV.IsPartner( srcV ))
- {
- // check that transformation is OK by three nodes
- gp_Pnt p0S = SMESH_TNodeXYZ( srcN );
- gp_Pnt p0T = SMESH_TNodeXYZ( tgtN );
- if ( p0T.SquareDistance( p0S.Transformed( trsf )) > tol )
- {
- return false;
- }
- }
- src2tgtNodes.insert( make_pair( srcN, tgtN ));
- }
-
// Make new faces
// prepare the helper to adding quadratic elements if necessary
- SMESH_MesherHelper helper( *tgtMesh );
helper.SetSubShape( tgtFace );
helper.IsQuadraticSubMesh( tgtFace );
SMESHDS_SubMesh* srcSubDS = srcMeshDS->MeshElements( srcFace );
- if ( !tgtEdgesMeshed && srcSubDS->NbElements() )
+ if ( !is1DComputed && srcSubDS->NbElements() )
helper.SetIsQuadratic( srcSubDS->GetElements()->next()->IsQuadratic() );
SMESH_MesherHelper srcHelper( *srcMesh );
srcHelper.SetSubShape( srcFace );
const SMDS_MeshNode* nullNode = 0;
+ TAssocTool::TNodeNodeMap::iterator srcN_tgtN;
// indices of nodes to create properly oriented faces
- bool isReverse = ( trsf.Form() != gp_Identity );
+ bool isReverse = ( !trsf.IsIdentity() );
int tri1 = 1, tri2 = 2, quad1 = 1, quad3 = 3;
if ( isReverse )
std::swap( tri1, tri2 ), std::swap( quad1, quad3 );
@@ -610,7 +664,7 @@ namespace {
if ( srcN_tgtN->second == nullNode )
{
// create a new node
- gp_Pnt tgtP = gp_Pnt( SMESH_TNodeXYZ( srcNode )).Transformed( trsf );
+ gp_Pnt tgtP = trsf.Transform( SMESH_TNodeXYZ( srcNode ));
SMDS_MeshNode* n = helper.AddNode( tgtP.X(), tgtP.Y(), tgtP.Z() );
srcN_tgtN->second = n;
switch ( srcNode->GetPosition()->GetTypeOfPosition() )
@@ -657,7 +711,12 @@ namespace {
if ( !tgtFace.IsPartner( srcFace ) )
{
+ SMESH_MesherHelper edgeHelper( *tgtMesh );
+ edgeHelper.ToFixNodeParameters( true );
+ helper.ToFixNodeParameters( true );
+
int nbOkPos = 0;
+ bool toCheck = true;
const double tol2d = 1e-12;
srcN_tgtN = src2tgtNodes.begin();
for ( ; srcN_tgtN != src2tgtNodes.end(); ++srcN_tgtN )
@@ -667,22 +726,20 @@ namespace {
{
case SMDS_TOP_FACE:
{
+ if ( nbOkPos > 10 ) break;
gp_XY uv = helper.GetNodeUV( tgtFace, n ), uvBis = uv;
if (( helper.CheckNodeUV( tgtFace, n, uv, tol )) &&
- (( uv - uvBis ).SquareModulus() < tol2d ) &&
- ( ++nbOkPos > 10 ))
- return true;
+ (( uv - uvBis ).SquareModulus() < tol2d ))
+ ++nbOkPos;
else
- nbOkPos = 0;
+ nbOkPos = -((int) src2tgtNodes.size() );
break;
}
case SMDS_TOP_EDGE:
{
const TopoDS_Edge & tgtE = TopoDS::Edge( tgtMeshDS->IndexToShape( n->getshapeId() ));
- double u = helper.GetNodeU( tgtE, n ), uBis = u;
- if (( !helper.CheckNodeU( tgtE, n, u, tol )) ||
- (( u - uBis ) < tol2d ))
- nbOkPos = 0;
+ edgeHelper.SetSubShape( tgtE );
+ edgeHelper.GetNodeU( tgtE, n, 0, &toCheck );
break;
}
default:;
@@ -694,95 +751,29 @@ namespace {
} // bool projectPartner()
- //================================================================================
- /*!
- * \brief Check if two consecutive EDGEs are connected in 2D
- * \param [in] E1 - a well oriented non-seam EDGE
- * \param [in] E2 - a possibly well oriented seam EDGE
- * \param [in] F - a FACE
- * \return bool - result
- */
- //================================================================================
-
- bool are2dConnected( const TopoDS_Edge & E1,
- const TopoDS_Edge & E2,
- const TopoDS_Face & F )
- {
- double f,l;
- Handle(Geom2d_Curve) c1 = BRep_Tool::CurveOnSurface( E1, F, f, l );
- gp_Pnt2d uvLast1 = c1->Value( E1.Orientation() == TopAbs_REVERSED ? f : l );
-
- Handle(Geom2d_Curve) c2 = BRep_Tool::CurveOnSurface( E2, F, f, l );
- gp_Pnt2d uvFirst2 = c2->Value( f );
- gp_Pnt2d uvLast2 = c2->Value( l );
- double tol2 = 1e-5 * uvLast2.SquareDistance( uvFirst2 );
-
- return (( uvLast1.SquareDistance( uvFirst2 ) < tol2 ) ||
- ( uvLast1.SquareDistance( uvLast2 ) < tol2 ));
- }
-
//================================================================================
/*!
* \brief Preform projection in case if the faces are similar in 2D space
*/
//================================================================================
- bool projectBy2DSimilarity(const TopoDS_Face& tgtFace,
- const TopoDS_Face& srcFace,
- SMESH_Mesh * tgtMesh,
- SMESH_Mesh * srcMesh,
- const TAssocTool::TShapeShapeMap& shape2ShapeMap,
- const bool is1DComputed)
+ bool projectBy2DSimilarity(const TopoDS_Face& tgtFace,
+ const TopoDS_Face& srcFace,
+ const TSideVector& tgtWires,
+ const TSideVector& srcWires,
+ const TAssocTool::TShapeShapeMap& shape2ShapeMap,
+ TAssocTool::TNodeNodeMap& src2tgtNodes,
+ const bool is1DComputed)
{
- // 1) Preparation
+ SMESH_Mesh * tgtMesh = tgtWires[0]->GetMesh();
+ SMESH_Mesh * srcMesh = srcWires[0]->GetMesh();
- // get ordered src EDGEs
- TError err;
- TSideVector srcWires =
- StdMeshers_FaceSide::GetFaceWires( srcFace, *srcMesh,/*ignoreMediumNodes = */false, err);
- if ( err && !err->IsOK() )
- return false;
+ // WARNING: we can have problems if the FACE is symmetrical in 2D,
+ // then the projection can be mirrored relating to what is expected
- // make corresponding sequence of tgt EDGEs
- TSideVector tgtWires( srcWires.size() );
- for ( size_t iW = 0; iW < srcWires.size(); ++iW )
- {
- list< TopoDS_Edge > tgtEdges;
- StdMeshers_FaceSidePtr srcWire = srcWires[iW];
- TopTools_IndexedMapOfShape edgeMap; // to detect seam edges
- for ( int iE = 0; iE < srcWire->NbEdges(); ++iE )
- {
- TopoDS_Edge E = TopoDS::Edge( shape2ShapeMap( srcWire->Edge( iE ), /*isSrc=*/true));
- // reverse a seam edge encountered for the second time
- const int index = edgeMap.Add( E );
- if ( index < edgeMap.Extent() ) // E is a seam
- {
- // check which of edges to reverse, E or one already being in tgtEdges
- if ( are2dConnected( tgtEdges.back(), E, tgtFace ))
- {
- list< TopoDS_Edge >::iterator eIt = tgtEdges.begin();
- std::advance( eIt, index-1 );
- eIt->Reverse();
- }
- else
- {
- E.Reverse();
- }
- }
- tgtEdges.push_back( E );
- }
- tgtWires[ iW ].reset( new StdMeshers_FaceSide( tgtFace, tgtEdges, tgtMesh,
- /*theIsForward = */ true,
- /*theIgnoreMediumNodes = */false));
- if ( is1DComputed &&
- srcWires[iW]->GetUVPtStruct().size() !=
- tgtWires[iW]->GetUVPtStruct().size())
- return false;
- }
+ // 1) Find 2D transformation
- // 2) Find transformation
-
- gp_Trsf2d trsf;
+ StdMeshers_ProjectionUtils::TrsfFinder2D trsf;
{
// get 2 pairs of corresponding UVs
gp_Pnt2d srcP0 = srcWires[0]->Value2d(0.0);
@@ -797,50 +788,63 @@ namespace {
toSrcCS .SetTransformation( srcCS );
fromTgtCS.SetTransformation( tgtCS );
fromTgtCS.Invert();
-
- trsf = fromTgtCS * toSrcCS;
+ trsf.Set( fromTgtCS * toSrcCS );
// check transformation
+ bool trsfIsOK = true;
const double tol = 1e-5 * gp_Vec2d( srcP0, srcP1 ).Magnitude();
- for ( double u = 0.12; u < 1.; u += 0.1 )
+ for ( double u = 0.12; ( u < 1. && trsfIsOK ); u += 0.1 )
{
- gp_Pnt2d srcUV = srcWires[0]->Value2d( u );
- gp_Pnt2d tgtUV = tgtWires[0]->Value2d( u );
- gp_Pnt2d tgtUV2 = srcUV.Transformed( trsf );
- if ( tgtUV.Distance( tgtUV2 ) > tol )
+ gp_Pnt2d srcUV = srcWires[0]->Value2d( u );
+ gp_Pnt2d tgtUV = tgtWires[0]->Value2d( u );
+ gp_Pnt2d tgtUV2 = trsf.Transform( srcUV );
+ trsfIsOK = ( tgtUV.Distance( tgtUV2 ) < tol );
+ }
+
+ // Find trsf using a least-square approximation
+ if ( !trsfIsOK )
+ {
+ // find trsf
+ const int totNbSeg = 50;
+ vector< gp_XY > srcPnts, tgtPnts;
+ srcPnts.resize( totNbSeg );
+ tgtPnts.resize( totNbSeg );
+ for ( size_t iW = 0; iW < srcWires.size(); ++iW )
+ {
+ const double minSegLen = srcWires[iW]->Length() / totNbSeg;
+ for ( int iE = 0; iE < srcWires[iW]->NbEdges(); ++iE )
+ {
+ int nbSeg = Max( 1, int( srcWires[iW]->EdgeLength( iE ) / minSegLen ));
+ double srcU = srcWires[iW]->FirstParameter( iE );
+ double tgtU = tgtWires[iW]->FirstParameter( iE );
+ double srcDu = ( srcWires[iW]->LastParameter( iE )- srcU ) / nbSeg;
+ double tgtDu = ( tgtWires[iW]->LastParameter( iE )- tgtU ) / nbSeg;
+ for ( size_t i = 0; i < nbSeg; ++i, srcU += srcDu, tgtU += tgtDu )
+ {
+ srcPnts.push_back( srcWires[iW]->Value2d( srcU ).XY() );
+ tgtPnts.push_back( tgtWires[iW]->Value2d( tgtU ).XY() );
+ }
+ }
+ }
+ if ( !trsf.Solve( srcPnts, tgtPnts ))
+ return false;
+
+ // check trsf
+
+ trsfIsOK = true;
+ const int nbTestPnt = 10;
+ const size_t iStep = Max( 1, int( srcPnts.size() / nbTestPnt ));
+ for ( size_t i = 0; ( i < srcPnts.size() && trsfIsOK ); i += iStep )
+ {
+ gp_Pnt2d trsfTgt = trsf.Transform( srcPnts[i] );
+ trsfIsOK = ( trsfTgt.Distance( tgtPnts[i] ) < tol );
+ }
+ if ( !trsfIsOK )
return false;
}
- }
+ } // "Find transformation" block
- // 3) Projection
-
- typedef map TN2NMap;
- TN2NMap src2tgtNodes;
- TN2NMap::iterator srcN_tgtN;
-
- // fill src2tgtNodes in with nodes on EDGEs
- for ( unsigned iW = 0; iW < srcWires.size(); ++iW )
- if ( is1DComputed )
- {
- const vector& srcUVs = srcWires[iW]->GetUVPtStruct();
- const vector& tgtUVs = tgtWires[iW]->GetUVPtStruct();
- for ( unsigned i = 0; i < srcUVs.size(); ++i )
- src2tgtNodes.insert( make_pair( srcUVs[i].node, tgtUVs[i].node ));
- }
- else
- {
- for ( int iE = 0; iE < srcWires[iW]->NbEdges(); ++iE )
- {
- TopoDS_Vertex srcV = srcWires[iW]->FirstVertex(iE);
- TopoDS_Vertex tgtV = tgtWires[iW]->FirstVertex(iE);
- const SMDS_MeshNode* srcNode = SMESH_Algo::VertexNode( srcV, srcMesh->GetMeshDS() );
- const SMDS_MeshNode* tgtNode = SMESH_Algo::VertexNode( tgtV, tgtMesh->GetMeshDS() );
- if ( tgtNode && srcNode )
- src2tgtNodes.insert( make_pair( srcNode, tgtNode ));
- }
- }
-
- // make elements
+ // 2) Projection
SMESHDS_SubMesh* srcSubDS = srcMesh->GetMeshDS()->MeshElements( srcFace );
@@ -858,6 +862,7 @@ namespace {
srcHelper.SetSubShape( srcFace );
const SMDS_MeshNode* nullNode = 0;
+ TAssocTool::TNodeNodeMap::iterator srcN_tgtN;
SMDS_ElemIteratorPtr elemIt = srcSubDS->GetElements();
vector< const SMDS_MeshNode* > tgtNodes;
@@ -876,8 +881,8 @@ namespace {
// create a new node
gp_Pnt2d srcUV = srcHelper.GetNodeUV( srcFace, srcNode,
elem->GetNode( helper.WrapIndex(i+1,nbN)), &uvOK);
- gp_Pnt2d tgtUV = srcUV.Transformed( trsf );
- gp_Pnt tgtP = tgtSurface->Value( tgtUV.X(), tgtUV.Y() );
+ gp_Pnt2d tgtUV = trsf.Transform( srcUV );
+ gp_Pnt tgtP = tgtSurface->Value( tgtUV.X(), tgtUV.Y() );
SMDS_MeshNode* n = tgtMeshDS->AddNode( tgtP.X(), tgtP.Y(), tgtP.Z() );
switch ( srcNode->GetPosition()->GetTypeOfPosition() )
{
@@ -888,10 +893,9 @@ namespace {
case SMDS_TOP_EDGE: {
TopoDS_Shape srcEdge = srcHelper.GetSubShapeByNode( srcNode, srcHelper.GetMeshDS() );
TopoDS_Edge tgtEdge = TopoDS::Edge( shape2ShapeMap( srcEdge, /*isSrc=*/true ));
- tgtMeshDS->SetNodeOnEdge( n, TopoDS::Edge( tgtEdge ));
- double U = srcHelper.GetNodeU( TopoDS::Edge( srcEdge ), srcNode );
+ double U = Precision::Infinite();
helper.CheckNodeU( tgtEdge, n, U, Precision::PConfusion());
- n->SetPosition(SMDS_PositionPtr(new SMDS_EdgePosition( U )));
+ tgtMeshDS->SetNodeOnEdge( n, TopoDS::Edge( tgtEdge ), U );
break;
}
case SMDS_TOP_VERTEX: {
@@ -916,16 +920,75 @@ namespace {
} // bool projectBy2DSimilarity(...)
+ //================================================================================
+ /*!
+ * \brief Fix bad faces by smoothing
+ */
+ //================================================================================
+
+ bool fixDistortedFaces( SMESH_MesherHelper& helper,
+ TSideVector& tgtWires )
+ {
+ SMESH_subMesh* faceSM = helper.GetMesh()->GetSubMesh( helper.GetSubShape() );
+
+ if ( helper.IsDistorted2D( faceSM, /*checkUV=*/false ))
+ {
+ SMESH_MeshEditor editor( helper.GetMesh() );
+ SMESHDS_SubMesh* smDS = faceSM->GetSubMeshDS();
+ const TopoDS_Face& F = TopoDS::Face( faceSM->GetSubShape() );
+
+ TIDSortedElemSet faces;
+ SMDS_ElemIteratorPtr faceIt = smDS->GetElements();
+ for ( faceIt = smDS->GetElements(); faceIt->more(); )
+ faces.insert( faces.end(), faceIt->next() );
+
+ // choose smoothing algo
+ //SMESH_MeshEditor:: SmoothMethod algo = SMESH_MeshEditor::CENTROIDAL;
+ bool isConcaveBoundary = false;
+ for ( size_t iW = 0; iW < tgtWires.size() && !isConcaveBoundary; ++iW )
+ {
+ TopoDS_Edge prevEdge = tgtWires[iW]->Edge( tgtWires[iW]->NbEdges() - 1 );
+ for ( int iE = 0; iE < tgtWires[iW]->NbEdges() && !isConcaveBoundary; ++iE )
+ {
+ double angle = helper.GetAngle( prevEdge, tgtWires[iW]->Edge( iE ),
+ F, tgtWires[iW]->FirstVertex( iE ));
+ isConcaveBoundary = ( angle < -5. * M_PI / 180. );
+
+ prevEdge = tgtWires[iW]->Edge( iE );
+ }
+ }
+ SMESH_MeshEditor:: SmoothMethod algo =
+ isConcaveBoundary ? SMESH_MeshEditor::CENTROIDAL : SMESH_MeshEditor::LAPLACIAN;
+
+ // smooth in 2D or 3D?
+ TopLoc_Location loc;
+ Handle(Geom_Surface) surface = BRep_Tool::Surface( F, loc );
+ bool isPlanar = GeomLib_IsPlanarSurface( surface ).IsPlanar();
+
+ // smoothing
+ set fixedNodes;
+ editor.Smooth( faces, fixedNodes, algo, /*nbIterations=*/ 10,
+ /*theTgtAspectRatio=*/1.0, /*the2D=*/!isPlanar);
+
+ helper.ToFixNodeParameters( true );
+
+ return !helper.IsDistorted2D( faceSM, /*checkUV=*/true );
+ }
+ return true;
+ }
+
} // namespace
//=======================================================================
//function : Compute
-//purpose :
+//purpose :
//=======================================================================
bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theShape)
{
+ _src2tgtNodes.clear();
+
MESSAGE("Projection_2D Compute");
if ( !_sourceHypo )
return false;
@@ -986,35 +1049,38 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
// Projection
// ===========
- // find out if EDGEs are meshed or not
- bool is1DComputed = false;
- SMESH_subMeshIteratorPtr smIt = tgtSubMesh->getDependsOnIterator(/*includeSelf=*/false,
- /*complexShapeFirst=*/true);
- while ( smIt->more() && !is1DComputed )
- {
- SMESH_subMesh* sm = smIt->next();
- if ( sm->GetSubShape().ShapeType() == TopAbs_EDGE )
- is1DComputed = sm->IsMeshComputed();
- }
+ // get ordered src and tgt EDGEs
+ TSideVector srcWires, tgtWires;
+ bool is1DComputed = false; // if any tgt EDGE is meshed
+ TError err = getWires( tgtFace, srcFace, tgtMesh, srcMesh,
+ shape2ShapeMap, srcWires, tgtWires, _src2tgtNodes, is1DComputed );
+ if ( err && !err->IsOK() )
+ return error( err );
- bool done = false;
+ bool projDone = false;
- if ( !done )
+ if ( !projDone )
{
// try to project from the same face with different location
- done = projectPartner( tgtFace, srcFace, tgtMesh, srcMesh, shape2ShapeMap );
+ projDone = projectPartner( tgtFace, srcFace, tgtWires, srcWires,
+ shape2ShapeMap, _src2tgtNodes, is1DComputed );
}
- if ( !done )
+ if ( !projDone )
{
// projection in case if the faces are similar in 2D space
- done = projectBy2DSimilarity( tgtFace, srcFace, tgtMesh, srcMesh, shape2ShapeMap, is1DComputed);
+ projDone = projectBy2DSimilarity( tgtFace, srcFace, tgtWires, srcWires,
+ shape2ShapeMap, _src2tgtNodes, is1DComputed);
}
SMESH_MesherHelper helper( theMesh );
helper.SetSubShape( tgtFace );
- if ( !done )
+ // it will remove mesh built on edges and vertices in failure case
+ MeshCleaner cleaner( tgtSubMesh );
+
+ if ( !projDone )
{
+ _src2tgtNodes.clear();
// --------------------
// Prepare to mapping
// --------------------
@@ -1096,7 +1162,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
return error(COMPERR_BAD_INPUT_MESH,"Can't load mesh pattern from the source face");
// --------------------
- // Perform 2D mapping
+ // Perform 2D mapping
// --------------------
// Compute mesh on a target face
@@ -1112,13 +1178,9 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
return error("Can't make mesh by source mesh pattern");
- // it will remove mesh built by pattern mapper on edges and vertices
- // in failure case
- MeshCleaner cleaner( tgtSubMesh );
-
// -------------------------------------------------------------------------
// mapper doesn't take care of nodes already existing on edges and vertices,
- // so we must merge nodes created by it with existing ones
+ // so we must merge nodes created by it with existing ones
// -------------------------------------------------------------------------
SMESH_MeshEditor::TListOfListOfNodes groupsOfNodes;
@@ -1126,7 +1188,8 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
// Make groups of nodes to merge
// loop on EDGE and VERTEX sub-meshes of a target FACE
- smIt = tgtSubMesh->getDependsOnIterator(/*includeSelf=*/false,/*complexShapeFirst=*/false);
+ SMESH_subMeshIteratorPtr smIt = tgtSubMesh->getDependsOnIterator(/*includeSelf=*/false,
+ /*complexShapeFirst=*/false);
while ( smIt->more() )
{
SMESH_subMesh* sm = smIt->next();
@@ -1134,7 +1197,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
if ( !smDS || smDS->NbNodes() == 0 )
continue;
//if ( !is1DComputed && sm->GetSubShape().ShapeType() == TopAbs_EDGE )
- //break;
+ // break;
if ( helper.IsDegenShape( sm->GetId() ) ) // to merge all nodes on degenerated
{
@@ -1292,11 +1355,18 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
editor.ConvertToQuadratic(/*theForce3d=*/false, tgtFaces, false);
}
- cleaner.Release(); // not to remove mesh
-
} // end of projection using Pattern mapping
+ if ( !projDone || is1DComputed )
+ // ----------------------------------------------------------------
+ // The mapper can create distorted faces by placing nodes out of the FACE
+ // boundary, also bad face can be created if EDGEs already discretized
+ // --> fix bad faces by smoothing
+ // ----------------------------------------------------------------
+ if ( !fixDistortedFaces( helper, tgtWires ))
+ return error("Invalid mesh generated");
+
// ---------------------------
// Check elements orientation
// ---------------------------
@@ -1342,6 +1412,8 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
}
}
+ cleaner.Release(); // not to remove mesh
+
return true;
}
diff --git a/src/StdMeshers/StdMeshers_Projection_2D.hxx b/src/StdMeshers/StdMeshers_Projection_2D.hxx
index 57e34dbc4..878d21849 100644
--- a/src/StdMeshers/StdMeshers_Projection_2D.hxx
+++ b/src/StdMeshers/StdMeshers_Projection_2D.hxx
@@ -30,6 +30,7 @@
#include "SMESH_StdMeshers.hxx"
#include "SMESH_Algo.hxx"
+#include "StdMeshers_ProjectionUtils.hxx"
class StdMeshers_ProjectionSource2D;
@@ -59,9 +60,12 @@ public:
*/
virtual void SetEventListener(SMESH_subMesh* whenSetToSubMesh);
-protected:
- const StdMeshers_ProjectionSource2D* _sourceHypo;
+ protected:
+
+ const StdMeshers_ProjectionSource2D* _sourceHypo;
+
+ StdMeshers_ProjectionUtils::TNodeNodeMap _src2tgtNodes;
};
diff --git a/src/StdMeshers/StdMeshers_Projection_3D.cxx b/src/StdMeshers/StdMeshers_Projection_3D.cxx
index 3079c7bd8..93969dfeb 100644
--- a/src/StdMeshers/StdMeshers_Projection_3D.cxx
+++ b/src/StdMeshers/StdMeshers_Projection_3D.cxx
@@ -307,7 +307,7 @@ bool StdMeshers_Projection_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aS
}
}
// Find matching nodes of tgt and src faces
- TNodeNodeMap faceMatchingNodes;
+ TAssocTool::TNodeNodeMap faceMatchingNodes;
if ( ! TAssocTool::FindMatchingNodesOnFaces( srcFace, srcMesh, tgtFace, tgtMesh,
shape2ShapeMap, faceMatchingNodes ))
return error(COMPERR_BAD_INPUT_MESH,SMESH_Comment("Mesh on faces #")
diff --git a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx
index a9990e5e7..4d1321497 100644
--- a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx
+++ b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx
@@ -4280,16 +4280,17 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face& theFace,
vMap.Add( (*a2v).second );
// check if there are possible variations in choosing corners
- bool isThereVariants = false;
+ bool haveVariants = false;
if ( vertexByAngle.size() > nbCorners )
{
double lostAngle = a2v->first;
double lastAngle = ( --a2v, a2v->first );
- isThereVariants = ( lostAngle * 1.1 >= lastAngle );
+ haveVariants = ( lostAngle * 1.1 >= lastAngle );
}
+ const double angleTol = 5.* M_PI/180;
myCheckOri = ( vertexByAngle.size() > nbCorners ||
- vertexByAngle.begin()->first < 5.* M_PI/180 );
+ vertexByAngle.begin()->first < angleTol );
// make theWire begin from a corner vertex or triaVertex
if ( nbCorners == 3 )
@@ -4306,9 +4307,10 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face& theFace,
vector< double > angles;
vector< TopoDS_Edge > edgeVec;
vector< int > cornerInd, nbSeg;
- angles.reserve( vertexByAngle.size() );
+ int nbSegTot = 0;
+ angles .reserve( vertexByAngle.size() );
edgeVec.reserve( vertexByAngle.size() );
- nbSeg.reserve( vertexByAngle.size() );
+ nbSeg .reserve( vertexByAngle.size() );
cornerInd.reserve( nbCorners );
for ( edge = theWire.begin(); edge != theWire.end(); ++edge )
{
@@ -4321,105 +4323,219 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face& theFace,
theVertices.push_back( v );
cornerInd.push_back( angles.size() );
}
- angles.push_back( angleByVertex.IsBound( v ) ? angleByVertex( v ) : -M_PI );
+ angles .push_back( angleByVertex.IsBound( v ) ? angleByVertex( v ) : -M_PI );
edgeVec.push_back( *edge );
- if ( theConsiderMesh && isThereVariants )
+ if ( theConsiderMesh && haveVariants )
{
if ( SMESHDS_SubMesh* sm = helper.GetMeshDS()->MeshElements( *edge ))
nbSeg.push_back( sm->NbNodes() + 1 );
else
nbSeg.push_back( 0 );
+ nbSegTot += nbSeg.back();
}
}
- // refine the result vector - make sides elual by length if
+ // refine the result vector - make sides equal by length if
// there are several equal angles
- if ( isThereVariants )
+ if ( haveVariants )
{
if ( nbCorners == 3 )
angles[0] = 2 * M_PI; // not to move the base triangle VERTEX
- set< int > refinedCorners;
+ // here we refer to VERTEX'es and EDGEs by indices in angles and edgeVec vectors
+ typedef int TGeoIndex;
+
+ // for each vertex find a vertex till which there are nbSegHalf segments
+ const int nbSegHalf = ( nbSegTot % 2 || nbCorners == 3 ) ? 0 : nbSegTot / 2;
+ vector< TGeoIndex > halfDivider( angles.size(), -1 );
+ int nbHalfDividers = 0;
+ if ( nbSegHalf )
+ {
+ // get min angle of corners
+ double minAngle = 10.;
+ for ( size_t iC = 0; iC < cornerInd.size(); ++iC )
+ minAngle = Min( minAngle, angles[ cornerInd[ iC ]]);
+
+ // find halfDivider's
+ for ( TGeoIndex iV1 = 0; iV1 < TGeoIndex( angles.size() ); ++iV1 )
+ {
+ int nbSegs = 0;
+ TGeoIndex iV2 = iV1;
+ do {
+ nbSegs += nbSeg[ iV2 ];
+ iV2 = helper.WrapIndex( iV2 + 1, nbSeg.size() );
+ } while ( nbSegs < nbSegHalf );
+
+ if ( nbSegs == nbSegHalf &&
+ angles[ iV1 ] + angleTol >= minAngle &&
+ angles[ iV2 ] + angleTol >= minAngle )
+ {
+ halfDivider[ iV1 ] = iV2;
+ ++nbHalfDividers;
+ }
+ }
+ }
+
+ set< TGeoIndex > refinedCorners, treatedCorners;
for ( size_t iC = 0; iC < cornerInd.size(); ++iC )
{
- int iV = cornerInd[iC];
- if ( !refinedCorners.insert( iV ).second )
+ TGeoIndex iV = cornerInd[iC];
+ if ( !treatedCorners.insert( iV ).second )
continue;
- list< int > equalVertices;
- equalVertices.push_back( iV );
+ list< TGeoIndex > equVerts; // inds of vertices that can become corners
+ equVerts.push_back( iV );
int nbC[2] = { 0, 0 };
// find equal angles backward and forward from the iV-th corner vertex
for ( int isFwd = 0; isFwd < 2; ++isFwd )
{
- int dV = isFwd ? +1 : -1;
- int iCNext = helper.WrapIndex( iC + dV, cornerInd.size() );
- int iVNext = helper.WrapIndex( iV + dV, angles.size() );
+ int dV = isFwd ? +1 : -1;
+ int iCNext = helper.WrapIndex( iC + dV, cornerInd.size() );
+ TGeoIndex iVNext = helper.WrapIndex( iV + dV, angles.size() );
while ( iVNext != iV )
{
- bool equal = Abs( angles[iV] - angles[iVNext] ) < 0.1 * angles[iV];
+ bool equal = Abs( angles[iV] - angles[iVNext] ) < angleTol;
if ( equal )
- equalVertices.insert( isFwd ? equalVertices.end() : equalVertices.begin(), iVNext );
+ equVerts.insert( isFwd ? equVerts.end() : equVerts.begin(), iVNext );
if ( iVNext == cornerInd[ iCNext ])
{
if ( !equal )
+ {
+ if ( angles[iV] < angles[iVNext] )
+ refinedCorners.insert( iVNext );
break;
+ }
nbC[ isFwd ]++;
- refinedCorners.insert( cornerInd[ iCNext ] );
+ treatedCorners.insert( cornerInd[ iCNext ] );
iCNext = helper.WrapIndex( iCNext + dV, cornerInd.size() );
}
iVNext = helper.WrapIndex( iVNext + dV, angles.size() );
}
+ if ( iVNext == iV )
+ break; // all angles equal
}
- // move corners to make sides equal by length
- int nbEqualV = equalVertices.size();
- int nbExcessV = nbEqualV - ( 1 + nbC[0] + nbC[1] );
- if ( nbExcessV > 0 )
+
+ const bool allCornersSame = ( nbC[0] == 3 );
+ if ( allCornersSame && nbHalfDividers > 0 )
{
- // calculate normalized length of each side enclosed between neighbor equalVertices
- vector< double > curLengths;
- double totalLen = 0;
- vector< int > evVec( equalVertices.begin(), equalVertices.end() );
- int iEV = 0;
- int iE = cornerInd[ helper.WrapIndex( iC - nbC[0] - 1, cornerInd.size() )];
- int iEEnd = cornerInd[ helper.WrapIndex( iC + nbC[1] + 1, cornerInd.size() )];
- while ( curLengths.size() < nbEqualV + 1 )
+ // select two halfDivider's as corners
+ TGeoIndex hd1, hd2 = -1;
+ int iC2;
+ for ( iC2 = 0; iC2 < cornerInd.size() && hd2 < 0; ++iC2 )
{
- curLengths.push_back( totalLen );
+ hd1 = cornerInd[ iC2 ];
+ hd2 = halfDivider[ hd1 ];
+ if ( std::find( equVerts.begin(), equVerts.end(), hd2 ) == equVerts.end() )
+ hd2 = -1; // hd2-th vertex can't become a corner
+ else
+ break;
+ }
+ if ( hd2 >= 0 )
+ {
+ angles[ hd1 ] = 2 * M_PI; // make hd1-th vertex no more "equal"
+ angles[ hd2 ] = 2 * M_PI;
+ refinedCorners.insert( hd1 );
+ refinedCorners.insert( hd2 );
+ treatedCorners = refinedCorners;
+ // update cornerInd
+ equVerts.push_front( equVerts.back() );
+ equVerts.push_back( equVerts.front() );
+ list< TGeoIndex >::iterator hdPos =
+ std::find( equVerts.begin(), equVerts.end(), hd2 );
+ if ( hdPos == equVerts.end() ) break;
+ cornerInd[ helper.WrapIndex( iC2 + 0, cornerInd.size()) ] = hd1;
+ cornerInd[ helper.WrapIndex( iC2 + 1, cornerInd.size()) ] = *( --hdPos );
+ cornerInd[ helper.WrapIndex( iC2 + 2, cornerInd.size()) ] = hd2;
+ cornerInd[ helper.WrapIndex( iC2 + 3, cornerInd.size()) ] = *( ++hdPos, ++hdPos );
+
+ theVertices[ 0 ] = helper.IthVertex( 0, edgeVec[ cornerInd[0] ]);
+ theVertices[ 1 ] = helper.IthVertex( 0, edgeVec[ cornerInd[1] ]);
+ theVertices[ 2 ] = helper.IthVertex( 0, edgeVec[ cornerInd[2] ]);
+ theVertices[ 3 ] = helper.IthVertex( 0, edgeVec[ cornerInd[3] ]);
+ iC = -1;
+ continue;
+ }
+ }
+
+ // move corners to make sides equal by length
+ int nbEqualV = equVerts.size();
+ int nbExcessV = nbEqualV - ( 1 + nbC[0] + nbC[1] );
+ if ( nbExcessV > 0 ) // there is nbExcessV vertices that can become corners
+ {
+ // calculate normalized length of each "side" enclosed between neighbor equVerts
+ vector< double > accuLength;
+ double totalLen = 0;
+ vector< TGeoIndex > evVec( equVerts.begin(), equVerts.end() );
+ int iEV = 0;
+ TGeoIndex iE = cornerInd[ helper.WrapIndex( iC - nbC[0] - 1, cornerInd.size() )];
+ TGeoIndex iEEnd = cornerInd[ helper.WrapIndex( iC + nbC[1] + 1, cornerInd.size() )];
+ while ( accuLength.size() < nbEqualV + int( !allCornersSame ) )
+ {
+ // accumulate length of edges before iEV-th equal vertex
+ accuLength.push_back( totalLen );
do {
- curLengths.back() += SMESH_Algo::EdgeLength( edgeVec[ iE ]);
+ accuLength.back() += SMESH_Algo::EdgeLength( edgeVec[ iE ]);
iE = helper.WrapIndex( iE + 1, edgeVec.size());
- if ( iEV < evVec.size() && iE == evVec[ iEV++ ] )
- break;
+ if ( iEV < evVec.size() && iE == evVec[ iEV ] ) {
+ iEV++;
+ break; // equal vertex reached
+ }
}
while( iE != iEEnd );
- totalLen = curLengths.back();
+ totalLen = accuLength.back();
}
- curLengths.resize( equalVertices.size() );
- for ( size_t iS = 0; iS < curLengths.size(); ++iS )
- curLengths[ iS ] /= totalLen;
+ accuLength.resize( equVerts.size() );
+ for ( size_t iS = 0; iS < accuLength.size(); ++iS )
+ accuLength[ iS ] /= totalLen;
- // find equalVertices most close to the ideal sub-division of all sides
+ // find equVerts most close to the ideal sub-division of all sides
int iBestEV = 0;
int iCorner = helper.WrapIndex( iC - nbC[0], cornerInd.size() );
- int nbSides = 2 + nbC[0] + nbC[1];
+ int nbSides = Min( nbCorners, 2 + nbC[0] + nbC[1] );
for ( int iS = 1; iS < nbSides; ++iS, ++iBestEV )
{
double idealLen = iS / double( nbSides );
- double d, bestDist = 1.;
- for ( iEV = iBestEV; iEV < curLengths.size(); ++iEV )
- if (( d = Abs( idealLen - curLengths[ iEV ])) < bestDist )
+ double d, bestDist = 2.;
+ for ( iEV = iBestEV; iEV < accuLength.size(); ++iEV )
+ {
+ d = Abs( idealLen - accuLength[ iEV ]);
+
+ // take into account presence of a coresponding halfDivider
+ const double cornerWgt = 0.5 / nbSides;
+ const double vertexWgt = 0.25 / nbSides;
+ TGeoIndex hd = halfDivider[ evVec[ iEV ]];
+ if ( hd < 0 )
+ d += vertexWgt;
+ else if( refinedCorners.count( hd ))
+ d -= cornerWgt;
+ else
+ d -= vertexWgt;
+
+ // choose vertex with the best d
+ if ( d < bestDist )
{
bestDist = d;
iBestEV = iEV;
}
+ }
if ( iBestEV > iS-1 + nbExcessV )
iBestEV = iS-1 + nbExcessV;
theVertices[ iCorner ] = helper.IthVertex( 0, edgeVec[ evVec[ iBestEV ]]);
+ refinedCorners.insert( evVec[ iBestEV ]);
iCorner = helper.WrapIndex( iCorner + 1, cornerInd.size() );
}
+
+ } // if ( nbExcessV > 0 )
+ else
+ {
+ refinedCorners.insert( cornerInd[ iC ]);
}
- }
- }
+ } // loop on cornerInd
+
+ // make theWire begin from the cornerInd[0]-th EDGE
+ while ( !theWire.front().IsSame( edgeVec[ cornerInd[0] ]))
+ theWire.splice( theWire.begin(), theWire, --theWire.end() );
+
+ } // if ( haveVariants )
return nbCorners;
}
diff --git a/src/StdMeshers/StdMeshers_RadialPrism_3D.cxx b/src/StdMeshers/StdMeshers_RadialPrism_3D.cxx
index 17411417e..5ef61aab9 100644
--- a/src/StdMeshers/StdMeshers_RadialPrism_3D.cxx
+++ b/src/StdMeshers/StdMeshers_RadialPrism_3D.cxx
@@ -57,11 +57,7 @@
#include
#include
#include
-#if OCC_VERSION_LARGE > 0x06050400
#include
-#else
-#include
-#endif
using namespace std;
@@ -169,11 +165,7 @@ bool StdMeshers_RadialPrism_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& a
// get 2 shells
TopoDS_Solid solid = TopoDS::Solid( aShape );
-#if OCC_VERSION_LARGE > 0x06050400
TopoDS_Shell outerShell = BRepClass3d::OuterShell( solid );
-#else
- TopoDS_Shell outerShell = BRepTools::OuterShell( solid );
-#endif
TopoDS_Shape innerShell;
int nbShells = 0;
for ( TopoDS_Iterator It (solid); It.More(); It.Next(), ++nbShells )
@@ -187,13 +179,13 @@ bool StdMeshers_RadialPrism_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& a
// ----------------------------------
ProjectionUtils::TShapeShapeMap shape2ShapeMaps[2];
- if ( !ProjectionUtils::FindSubShapeAssociation( innerShell, &aMesh,
- outerShell, &aMesh,
- shape2ShapeMaps[0])
- &&
- !ProjectionUtils::FindSubShapeAssociation( innerShell.Reversed(), &aMesh,
- outerShell, &aMesh,
- shape2ShapeMaps[1]))
+ bool mapOk1 = ProjectionUtils::FindSubShapeAssociation( innerShell, &aMesh,
+ outerShell, &aMesh,
+ shape2ShapeMaps[0]);
+ bool mapOk2 = ProjectionUtils::FindSubShapeAssociation( innerShell.Reversed(), &aMesh,
+ outerShell, &aMesh,
+ shape2ShapeMaps[1]);
+ if ( !mapOk1 && !mapOk2 )
return error(COMPERR_BAD_SHAPE,"Topology of inner and outer shells seems different" );
int iMap;
@@ -239,7 +231,7 @@ bool StdMeshers_RadialPrism_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& a
}
// Find matching nodes of in and out faces
- TNodeNodeMap nodeIn2OutMap;
+ ProjectionUtils::TNodeNodeMap nodeIn2OutMap;
if ( ! ProjectionUtils::FindMatchingNodesOnFaces( inFace, &aMesh, outFace, &aMesh,
shape2ShapeMap, nodeIn2OutMap ))
return error(COMPERR_BAD_INPUT_MESH,SMESH_Comment("Mesh on faces #")
@@ -439,11 +431,7 @@ bool StdMeshers_RadialPrism_3D::Evaluate(SMESH_Mesh& aMesh,
{
// get 2 shells
TopoDS_Solid solid = TopoDS::Solid( aShape );
-#if OCC_VERSION_LARGE > 0x06050400
TopoDS_Shell outerShell = BRepClass3d::OuterShell( solid );
-#else
- TopoDS_Shell outerShell = BRepTools::OuterShell( solid );
-#endif
TopoDS_Shape innerShell;
int nbShells = 0;
for ( TopoDS_Iterator It (solid); It.More(); It.Next(), ++nbShells )
diff --git a/src/StdMeshers/StdMeshers_Regular_1D.cxx b/src/StdMeshers/StdMeshers_Regular_1D.cxx
index cc964cfac..a7e67cfeb 100644
--- a/src/StdMeshers/StdMeshers_Regular_1D.cxx
+++ b/src/StdMeshers/StdMeshers_Regular_1D.cxx
@@ -68,6 +68,7 @@
#include
using namespace std;
+using namespace StdMeshers;
//=============================================================================
/*!
diff --git a/src/StdMeshers/StdMeshers_ViscousLayers.cxx b/src/StdMeshers/StdMeshers_ViscousLayers.cxx
index db5469ea2..704144d7a 100644
--- a/src/StdMeshers/StdMeshers_ViscousLayers.cxx
+++ b/src/StdMeshers/StdMeshers_ViscousLayers.cxx
@@ -44,6 +44,7 @@
#include "SMESH_subMeshEventListener.hxx"
#include "StdMeshers_FaceSide.hxx"
+#include
#include
#include
#include
@@ -75,6 +76,8 @@
#include
#include
#include
+#include
+#include
#include
#include
@@ -83,7 +86,10 @@
#include
#include
-#define __myDEBUG
+#ifdef _DEBUG_
+//#define __myDEBUG
+//#define __NOT_INVALIDATE_BAD_SMOOTH
+#endif
using namespace std;
@@ -97,6 +103,10 @@ namespace VISCOUS_3D
const double theMinSmoothCosin = 0.1;
const double theSmoothThickToElemSizeRatio = 0.3;
+ // what part of thickness is allowed till intersection
+ // (defined by SALOME_TESTS/Grids/smesh/viscous_layers_00/A5)
+ const double theThickToIntersection = 1.5;
+
bool needSmoothing( double cosin, double tgtThick, double elemSize )
{
return cosin * tgtThick > theSmoothThickToElemSizeRatio * elemSize;
@@ -109,7 +119,8 @@ namespace VISCOUS_3D
struct _MeshOfSolid : public SMESH_ProxyMesh,
public SMESH_subMeshEventListenerData
{
- bool _n2nMapComputed;
+ bool _n2nMapComputed;
+ SMESH_ComputeErrorPtr _warning;
_MeshOfSolid( SMESH_Mesh* mesh)
:SMESH_subMeshEventListenerData( /*isDeletable=*/true),_n2nMapComputed(false)
@@ -173,7 +184,8 @@ namespace VISCOUS_3D
SMESH_subMeshEventListenerData* data,
const SMESH_Hypothesis* hyp)
{
- if ( SMESH_subMesh::COMPUTE_EVENT == eventType )
+ if ( SMESH_subMesh::COMPUTE_EVENT == eventType &&
+ SMESH_subMesh::CHECK_COMPUTE_STATE != event)
{
// delete SMESH_ProxyMesh containing temporary faces
subMesh->DeleteEventListener( this );
@@ -228,6 +240,7 @@ namespace VISCOUS_3D
sub->SetEventListener( _ShrinkShapeListener::Get(), data, /*whereToListenTo=*/mainSM );
}
}
+ struct _SolidData;
//--------------------------------------------------------------------------------
/*!
* \brief Simplex (triangle or tetrahedron) based on 1 (tria) or 2 (tet) nodes of
@@ -243,19 +256,19 @@ namespace VISCOUS_3D
const SMDS_MeshNode* nNext=0,
const SMDS_MeshNode* nOpp=0)
: _nPrev(nPrev), _nNext(nNext), _nOpp(nOpp) {}
- bool IsForward(const SMDS_MeshNode* nSrc, const gp_XYZ* pntTgt) const
+ bool IsForward(const SMDS_MeshNode* nSrc, const gp_XYZ* pntTgt, double& vol) const
{
const double M[3][3] =
{{ _nNext->X() - nSrc->X(), _nNext->Y() - nSrc->Y(), _nNext->Z() - nSrc->Z() },
{ pntTgt->X() - nSrc->X(), pntTgt->Y() - nSrc->Y(), pntTgt->Z() - nSrc->Z() },
{ _nPrev->X() - nSrc->X(), _nPrev->Y() - nSrc->Y(), _nPrev->Z() - nSrc->Z() }};
- double determinant = ( + M[0][0]*M[1][1]*M[2][2]
- + M[0][1]*M[1][2]*M[2][0]
- + M[0][2]*M[1][0]*M[2][1]
- - M[0][0]*M[1][2]*M[2][1]
- - M[0][1]*M[1][0]*M[2][2]
- - M[0][2]*M[1][1]*M[2][0]);
- return determinant > 1e-100;
+ vol = ( + M[0][0]*M[1][1]*M[2][2]
+ + M[0][1]*M[1][2]*M[2][0]
+ + M[0][2]*M[1][0]*M[2][1]
+ - M[0][0]*M[1][2]*M[2][1]
+ - M[0][1]*M[1][0]*M[2][2]
+ - M[0][2]*M[1][1]*M[2][0]);
+ return vol > 1e-100;
}
bool IsForward(const gp_XY& tgtUV,
const SMDS_MeshNode* smoothedNode,
@@ -273,6 +286,12 @@ namespace VISCOUS_3D
{
return _nPrev == other._nNext || _nNext == other._nPrev;
}
+ static void GetSimplices( const SMDS_MeshNode* node,
+ vector<_Simplex>& simplices,
+ const set& ingnoreShapes,
+ const _SolidData* dataToCheckOri = 0,
+ const bool toSort = false);
+ static void SortSimplices(vector<_Simplex>& simplices);
};
//--------------------------------------------------------------------------------
/*!
@@ -301,7 +320,12 @@ namespace VISCOUS_3D
double lenDelta(double len) const { return _k * ( _r + len ); }
double lenDeltaByDist(double dist) const { return dist * _h2lenRatio; }
};
+ //--------------------------------------------------------------------------------
+
struct _2NearEdges;
+ struct _LayerEdge;
+ typedef map< const SMDS_MeshNode*, _LayerEdge*, TIDCompare > TNode2Edge;
+
//--------------------------------------------------------------------------------
/*!
* \brief Edge normal to surface, connecting a node on solid surface (_nodes[0])
@@ -309,6 +333,8 @@ namespace VISCOUS_3D
*/
struct _LayerEdge
{
+ typedef gp_XYZ (_LayerEdge::*PSmooFun)();
+
vector< const SMDS_MeshNode*> _nodes;
gp_XYZ _normal; // to solid surface
@@ -322,6 +348,7 @@ namespace VISCOUS_3D
// simplices connected to the source node (_nodes[0]);
// used for smoothing and quality check of _LayerEdge's based on the FACE
vector<_Simplex> _simplices;
+ PSmooFun _smooFunction; // smoothing function
// data for smoothing of _LayerEdge's based on the EDGE
_2NearEdges* _2neibors;
@@ -336,7 +363,9 @@ namespace VISCOUS_3D
const SMDS_MeshNode* n2,
SMESH_MesherHelper& helper);
void InvalidateStep( int curStep, bool restoreLength=false );
- bool Smooth(int& badNb);
+ void ChooseSmooFunction(const set< TGeomID >& concaveVertices,
+ const TNode2Edge& n2eMap);
+ int Smooth(const int step, const bool isConcaveFace, const bool findBest);
bool SmoothOnEdge(Handle(Geom_Surface)& surface,
const TopoDS_Face& F,
SMESH_MesherHelper& helper);
@@ -356,7 +385,30 @@ namespace VISCOUS_3D
gp_XYZ Copy( _LayerEdge& other, SMESH_MesherHelper& helper );
void SetCosin( double cosin );
int NbSteps() const { return _pos.size() - 1; } // nb inlation steps
+
+ gp_XYZ smoothLaplacian();
+ gp_XYZ smoothAngular();
+ gp_XYZ smoothLengthWeighted();
+ gp_XYZ smoothCentroidal();
+ gp_XYZ smoothNefPolygon();
+
+ enum { FUN_LAPLACIAN, FUN_LENWEIGHTED, FUN_CENTROIDAL, FUN_NEFPOLY, FUN_ANGULAR, FUN_NB };
+ static const int theNbSmooFuns = FUN_NB;
+ static PSmooFun _funs[theNbSmooFuns];
+ static const char* _funNames[theNbSmooFuns+1];
+ int smooFunID( PSmooFun fun=0) const;
};
+ _LayerEdge::PSmooFun _LayerEdge::_funs[theNbSmooFuns] = { &_LayerEdge::smoothLaplacian,
+ &_LayerEdge::smoothLengthWeighted,
+ &_LayerEdge::smoothCentroidal,
+ &_LayerEdge::smoothNefPolygon,
+ &_LayerEdge::smoothAngular };
+ const char* _LayerEdge::_funNames[theNbSmooFuns+1] = { "Laplacian",
+ "LengthWeighted",
+ "Centroidal",
+ "NefPolygon",
+ "Angular",
+ "None"};
struct _LayerEdgeCmp
{
bool operator () (const _LayerEdge* e1, const _LayerEdge* e2) const
@@ -365,7 +417,29 @@ namespace VISCOUS_3D
return cmpNodes ? ( e1->_nodes[0]->GetID() < e2->_nodes[0]->GetID()) : ( e1 < e2 );
}
};
- struct _LayerEdge;
+ //--------------------------------------------------------------------------------
+ /*!
+ * A 2D half plane used by _LayerEdge::smoothNefPolygon()
+ */
+ struct _halfPlane
+ {
+ gp_XY _pos, _dir, _inNorm;
+ bool IsOut( const gp_XY p, const double tol ) const
+ {
+ return _inNorm * ( p - _pos ) < -tol;
+ }
+ bool FindInterestion( const _halfPlane& hp, gp_XY & intPnt )
+ {
+ const double eps = 1e-10;
+ double D = _dir.Crossed( hp._dir );
+ if ( fabs(D) < std::numeric_limits::min())
+ return false;
+ gp_XY vec21 = _pos - hp._pos;
+ double u = hp._dir.Crossed( vec21 ) / D;
+ intPnt = _pos + _dir * u;
+ return true;
+ }
+ };
//--------------------------------------------------------------------------------
/*!
* Structure used to smooth a _LayerEdge based on an EDGE.
@@ -433,7 +507,7 @@ namespace VISCOUS_3D
_nbHyps++;
_nbLayers = hyp->GetNumberLayers();
//_thickness += hyp->GetTotalThickness();
- _thickness = Max( _thickness, hyp->GetTotalThickness() );
+ _thickness = Max( _thickness, hyp->GetTotalThickness() );
_stretchFactor += hyp->GetStretchFactor();
}
}
@@ -445,10 +519,6 @@ namespace VISCOUS_3D
double _thickness, _stretchFactor;
};
- //--------------------------------------------------------------------------------
-
- typedef map< const SMDS_MeshNode*, _LayerEdge*, TIDCompare > TNode2Edge;
-
//--------------------------------------------------------------------------------
/*!
* \brief Data of a SOLID
@@ -485,7 +555,7 @@ namespace VISCOUS_3D
// Convex FACEs whose radius of curvature is less than the thickness of layers
map< TGeomID, _ConvexFace > _convexFaces;
- // shapes (EDGEs and VERTEXes) srink from which is forbiden due to collisions with
+ // shapes (EDGEs and VERTEXes) srink from which is forbidden due to collisions with
// the adjacent SOLID
set< TGeomID > _noShrinkShapes;
@@ -495,6 +565,7 @@ namespace VISCOUS_3D
// end indices in _edges of _LayerEdge on each shape, first go shapes to smooth
vector< int > _endEdgeOnShape;
int _nbShapesToSmooth;
+ set< TGeomID > _concaveFaces;
// data of averaged StdMeshers_ViscousLayers parameters for each shape with _LayerEdge's
vector< AverageHyp > _hypOnShape;
@@ -511,15 +582,17 @@ namespace VISCOUS_3D
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);
+ SMESH_MesherHelper& helper,
+ vector<_LayerEdge* >* edges=0);
void SortOnEdge( const TopoDS_Edge& E,
const int iFrom,
const int iTo,
SMESH_MesherHelper& helper);
+ void Sort2NeiborsOnEdge( const int iFrom, const int iTo);
+
_ConvexFace* GetConvexFace( const TGeomID faceID )
{
map< TGeomID, _ConvexFace >::iterator id2face = _convexFaces.find( faceID );
@@ -534,6 +607,11 @@ namespace VISCOUS_3D
bool GetShapeEdges(const TGeomID shapeID, size_t& iEdgeEnd, int* iBeg=0, int* iEnd=0 ) const;
void AddShapesToSmooth( const set< TGeomID >& shapeIDs );
+
+ void PrepareEdgesToSmoothOnFace( _LayerEdge** edgeBeg,
+ _LayerEdge** edgeEnd,
+ const TopoDS_Face& face,
+ bool substituteSrcNodes );
};
//--------------------------------------------------------------------------------
/*!
@@ -624,17 +702,17 @@ namespace VISCOUS_3D
SMESH_MesherHelper& helper,
bool& isOK,
bool shiftInside=false);
- gp_XYZ getWeigthedNormal( const SMDS_MeshNode* n,
- std::pair< TGeomID, gp_XYZ > fId2Normal[],
- const int nbFaces );
+ bool getFaceNormalAtSingularity(const gp_XY& uv,
+ const TopoDS_Face& face,
+ SMESH_MesherHelper& helper,
+ gp_Dir& normal );
+ gp_XYZ getWeigthedNormal( const SMDS_MeshNode* n,
+ std::pair< TopoDS_Face, gp_XYZ > fId2Normal[],
+ int nbFaces );
bool findNeiborsOnEdge(const _LayerEdge* edge,
const SMDS_MeshNode*& n1,
const SMDS_MeshNode*& n2,
_SolidData& data);
- void getSimplices( const SMDS_MeshNode* node, vector<_Simplex>& simplices,
- const set& ingnoreShapes,
- const _SolidData* dataToCheckOri = 0,
- const bool toSort = false);
void findSimplexTestEdges( _SolidData& data,
vector< vector<_LayerEdge*> >& edgesByGeom);
void computeGeomSize( _SolidData& data );
@@ -833,6 +911,14 @@ StdMeshers_ViscousLayers::Compute(SMESH_Mesh& theMesh,
return SMESH_ProxyMesh::Ptr();
components.push_back( SMESH_ProxyMesh::Ptr( pm ));
pm->myIsDeletable = false; // it will de deleted by boost::shared_ptr
+
+ if ( pm->_warning && !pm->_warning->IsOK() )
+ {
+ SMESH_subMesh* sm = theMesh.GetSubMesh( exp.Current() );
+ SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
+ if ( !smError || smError->IsOK() )
+ smError = pm->_warning;
+ }
}
_ViscousListener::RemoveSolidMesh ( &theMesh, exp.Current() );
}
@@ -899,7 +985,7 @@ bool StdMeshers_ViscousLayers::IsShapeWithLayers(int shapeIndex) const
// END StdMeshers_ViscousLayers hypothesis
//================================================================================
-namespace
+namespace VISCOUS_3D
{
gp_XYZ getEdgeDir( const TopoDS_Edge& E, const TopoDS_Vertex& fromV )
{
@@ -1038,14 +1124,56 @@ namespace
return dir;
}
+
+ //================================================================================
+ /*!
+ * \brief Finds concave VERTEXes of a FACE
+ */
+ //================================================================================
+
+ bool getConcaveVertices( const TopoDS_Face& F,
+ SMESH_MesherHelper& helper,
+ set< TGeomID >* vertices = 0)
+ {
+ // check angles at VERTEXes
+ TError error;
+ TSideVector wires = StdMeshers_FaceSide::GetFaceWires( F, *helper.GetMesh(), 0, error );
+ for ( size_t iW = 0; iW < wires.size(); ++iW )
+ {
+ const int nbEdges = wires[iW]->NbEdges();
+ if ( nbEdges < 2 && SMESH_Algo::isDegenerated( wires[iW]->Edge(0)))
+ continue;
+ for ( int iE1 = 0; iE1 < nbEdges; ++iE1 )
+ {
+ if ( SMESH_Algo::isDegenerated( wires[iW]->Edge( iE1 ))) continue;
+ int iE2 = ( iE1 + 1 ) % nbEdges;
+ while ( SMESH_Algo::isDegenerated( wires[iW]->Edge( iE2 )))
+ iE2 = ( iE2 + 1 ) % nbEdges;
+ TopoDS_Vertex V = wires[iW]->FirstVertex( iE2 );
+ double angle = helper.GetAngle( wires[iW]->Edge( iE1 ),
+ wires[iW]->Edge( iE2 ), F, V );
+ if ( angle < -5. * M_PI / 180. )
+ {
+ if ( !vertices )
+ return true;
+ vertices->insert( helper.GetMeshDS()->ShapeToIndex( V ));
+ }
+ }
+ }
+ return vertices ? !vertices->empty() : false;
+ }
+
//================================================================================
/*!
* \brief Returns true if a FACE is bound by a concave EDGE
*/
//================================================================================
- bool isConcave( const TopoDS_Face& F, SMESH_MesherHelper& helper )
+ bool isConcave( const TopoDS_Face& F,
+ SMESH_MesherHelper& helper,
+ set< TGeomID >* vertices = 0 )
{
+ bool isConcv = false;
// if ( helper.Count( F, TopAbs_WIRE, /*useMap=*/false) > 1 )
// return true;
gp_Vec2d drv1, drv2;
@@ -1074,32 +1202,21 @@ namespace
if ( !isConvex )
{
//cout << "Concave FACE " << helper.GetMeshDS()->ShapeToIndex( F ) << endl;
- return true;
- }
- }
- // check angles at VERTEXes
- TError error;
- TSideVector wires = StdMeshers_FaceSide::GetFaceWires( F, *helper.GetMesh(), 0, error );
- for ( size_t iW = 0; iW < wires.size(); ++iW )
- {
- const int nbEdges = wires[iW]->NbEdges();
- if ( nbEdges < 2 && SMESH_Algo::isDegenerated( wires[iW]->Edge(0)))
- continue;
- for ( int iE1 = 0; iE1 < nbEdges; ++iE1 )
- {
- if ( SMESH_Algo::isDegenerated( wires[iW]->Edge( iE1 ))) continue;
- int iE2 = ( iE1 + 1 ) % nbEdges;
- while ( SMESH_Algo::isDegenerated( wires[iW]->Edge( iE2 )))
- iE2 = ( iE2 + 1 ) % nbEdges;
- double angle = helper.GetAngle( wires[iW]->Edge( iE1 ),
- wires[iW]->Edge( iE2 ), F,
- wires[iW]->FirstVertex( iE2 ));
- if ( angle < -5. * M_PI / 180. )
+ isConcv = true;
+ if ( vertices )
+ break;
+ else
return true;
}
}
- return false;
+
+ // check angles at VERTEXes
+ if ( getConcaveVertices( F, helper, vertices ))
+ isConcv = true;
+
+ return isConcv;
}
+
//================================================================================
/*!
* \brief Computes mimimal distance of face in-FACE nodes from an EDGE
@@ -1152,6 +1269,43 @@ namespace
}
return done;
}
+ //================================================================================
+ /*!
+ * \brief Return direction of axis or revolution of a surface
+ */
+ //================================================================================
+
+ bool getRovolutionAxis( const Adaptor3d_Surface& surface,
+ gp_Dir & axis )
+ {
+ switch ( surface.GetType() ) {
+ case GeomAbs_Cone:
+ {
+ gp_Cone cone = surface.Cone();
+ axis = cone.Axis().Direction();
+ break;
+ }
+ case GeomAbs_Sphere:
+ {
+ gp_Sphere sphere = surface.Sphere();
+ axis = sphere.Position().Direction();
+ break;
+ }
+ case GeomAbs_SurfaceOfRevolution:
+ {
+ axis = surface.AxeOfRevolution().Direction();
+ break;
+ }
+ //case GeomAbs_SurfaceOfExtrusion:
+ case GeomAbs_OffsetSurface:
+ {
+ Handle(Adaptor3d_HSurface) base = surface.BasisSurface();
+ return getRovolutionAxis( base->Surface(), axis );
+ }
+ default: return false;
+ }
+ return true;
+ }
//--------------------------------------------------------------------------------
// DEBUG. Dump intermediate node positions into a python script
@@ -1159,18 +1313,19 @@ namespace
// construction steps of viscous layers
#ifdef __myDEBUG
ofstream* py;
- int theNbFunc;
+ int theNbPyFunc;
struct PyDump {
- PyDump() {
+ PyDump(SMESH_Mesh& m) {
+ int tag = 3 + m.GetId();
const char* fname = "/tmp/viscous.py";
cout << "execfile('"<GetID()<< ", "<< n->X()
- << ", "<Y()<<", "<< n->Z()<< ")\t\t # "<< ln <Y()<<", "<< n->Z()<< ")\t\t # "<< ln <<" "<< txt << endl; }
void _dumpCmd(const string& txt, int ln)
{ if (py) *py<< " "<GetNode( f->NbNodes()-1 )->GetID() << " ])"<< endl; }}
#define debugMsg( txt ) { cout << txt << " (line: " << __LINE__ << ")" << endl; }
#else
- struct PyDump { void Finish() {} };
+ struct PyDump { PyDump(SMESH_Mesh&) {} void Finish() {} };
#define dumpFunction(f) f
#define dumpMove(n)
+#define dumpMoveComm(n,txt)
#define dumpCmd(txt)
#define dumpFunctionEnd()
#define dumpChangeNodes(f)
@@ -1342,7 +1499,7 @@ SMESH_ComputeErrorPtr _ViscousBuilder::Compute(SMESH_Mesh& theMesh,
if ( _ViscousListener::GetSolidMesh( _mesh, exp.Current(), /*toCreate=*/false))
return SMESH_ComputeErrorPtr(); // everything already computed
- PyDump debugDump;
+ PyDump debugDump( theMesh );
// TODO: ignore already computed SOLIDs
if ( !findSolidsWithLayers())
@@ -1547,27 +1704,28 @@ bool _ViscousBuilder::findFacesWithLayers(const bool onlyWith)
{
_sdVec[i]._ignoreFaceIds.swap( ignoreFacesOfHyps.back().first );
}
-
- // fill _SolidData::_reversedFaceIds
- {
- exp.Init( _sdVec[i]._solid.Oriented( TopAbs_FORWARD ), TopAbs_FACE );
- for ( ; exp.More(); exp.Next() )
- {
- const TopoDS_Face& face = TopoDS::Face( exp.Current() );
- const TGeomID faceID = getMeshDS()->ShapeToIndex( face );
- if ( //!sdVec[i]._ignoreFaceIds.count( faceID ) && ???????
- helper.NbAncestors( face, *_mesh, TopAbs_SOLID ) > 1 &&
- helper.IsReversedSubMesh( face ))
- {
- _sdVec[i]._reversedFaceIds.insert( faceID );
- }
- }
- }
} // loop on _sdVec
if ( onlyWith ) // is called to check hypotheses compatibility only
return true;
+ // fill _SolidData::_reversedFaceIds
+ for ( size_t i = 0; i < _sdVec.size(); ++i )
+ {
+ exp.Init( _sdVec[i]._solid.Oriented( TopAbs_FORWARD ), TopAbs_FACE );
+ for ( ; exp.More(); exp.Next() )
+ {
+ const TopoDS_Face& face = TopoDS::Face( exp.Current() );
+ const TGeomID faceID = getMeshDS()->ShapeToIndex( face );
+ if ( //!sdVec[i]._ignoreFaceIds.count( faceID ) &&
+ helper.NbAncestors( face, *_mesh, TopAbs_SOLID ) > 1 &&
+ helper.IsReversedSubMesh( face ))
+ {
+ _sdVec[i]._reversedFaceIds.insert( faceID );
+ }
+ }
+ }
+
// Find faces to shrink mesh on (solution 2 in issue 0020832);
TopTools_IndexedMapOfShape shapes;
for ( size_t i = 0; i < _sdVec.size(); ++i )
@@ -1849,14 +2007,16 @@ bool _ViscousBuilder::makeLayer(_SolidData& data)
subIds = data._noShrinkShapes;
TopExp_Explorer exp( data._solid, TopAbs_FACE );
for ( ; exp.More(); exp.Next() )
+ {
+ SMESH_subMesh* fSubM = _mesh->GetSubMesh( exp.Current() );
+ if ( ! data._ignoreFaceIds.count( fSubM->GetId() ))
{
- SMESH_subMesh* fSubM = _mesh->GetSubMesh( exp.Current() );
- if ( ! data._ignoreFaceIds.count( fSubM->GetId() ))
- faceIds.insert( fSubM->GetId() );
+ faceIds.insert( fSubM->GetId() );
SMESH_subMeshIteratorPtr subIt = fSubM->getDependsOnIterator(/*includeSelf=*/true);
while ( subIt->more() )
subIds.insert( subIt->next()->GetId() );
}
+ }
// make a map to find new nodes on sub-shapes shared with other SOLID
map< TGeomID, TNode2Edge* >::iterator s2ne;
@@ -1879,7 +2039,7 @@ bool _ViscousBuilder::makeLayer(_SolidData& data)
// Create temporary faces and _LayerEdge's
- dumpFunction(SMESH_Comment("makeLayers_")<::iterator e2c = data._edge2curve.begin();
+ for ( ; e2c != data._edge2curve.end(); ++e2c )
+ if ( !e2c->second.IsNull() )
+ {
+ size_t iEdgeEnd; int iBeg, iEnd;
+ if ( data.GetShapeEdges( e2c->first, iEdgeEnd, &iBeg, &iEnd ))
+ data.Sort2NeiborsOnEdge( iBeg, iEnd );
+ }
+
dumpFunctionEnd();
return true;
}
@@ -2168,7 +2338,8 @@ void _ViscousBuilder::limitStepSizeByCurvature( _SolidData& data )
else
continue;
// check concavity and curvature and limit data._stepSize
- const double minCurvature = 0.9 / data._hypOnShape[ edgesEnd ].GetTotalThickness();
+ const double minCurvature =
+ 1. / ( data._hypOnShape[ edgesEnd ].GetTotalThickness() * ( 1+theThickToIntersection ));
int nbLEdges = iEnd - iBeg;
int iStep = Max( 1, nbLEdges / nbTestPnt );
for ( ; iBeg < iEnd; iBeg += iStep )
@@ -2239,7 +2410,7 @@ void _ViscousBuilder::limitStepSizeByCurvature( _SolidData& data )
const SMDS_MeshNode* srcNode = ledge->_nodes[0];
if ( !usedNodes.insert( srcNode ).second ) continue;
- getSimplices( srcNode, ledge->_simplices, data._ignoreFaceIds, &data );
+ _Simplex::GetSimplices( srcNode, ledge->_simplices, data._ignoreFaceIds, &data );
for ( size_t i = 0; i < ledge->_simplices.size(); ++i )
{
usedNodes.insert( ledge->_simplices[i]._nPrev );
@@ -2278,104 +2449,133 @@ bool _ViscousBuilder::sortEdges( _SolidData& data,
// boundry inclined to the shape at a sharp angle
list< TGeomID > shapesToSmooth;
-
+ TopTools_MapOfShape edgesOfSmooFaces;
+
SMESH_MesherHelper helper( *_mesh );
bool ok = true;
- for ( size_t iS = 0; iS < edgesByGeom.size(); ++iS )
+ for ( int isEdge = 0; isEdge < 2; ++isEdge ) // loop on [ FACEs, EDGEs ]
{
- vector<_LayerEdge*>& eS = edgesByGeom[iS];
- if ( eS.empty() ) continue;
- const TopoDS_Shape& S = getMeshDS()->IndexToShape( iS );
- bool needSmooth = false;
- switch ( S.ShapeType() )
- {
- case TopAbs_EDGE: {
+ const int dim = isEdge ? 1 : 2;
- if ( SMESH_Algo::isDegenerated( TopoDS::Edge( S )))
- break;
- //bool isShrinkEdge = !eS[0]->_sWOL.IsNull();
- for ( TopoDS_Iterator vIt( S ); vIt.More() && !needSmooth; vIt.Next() )
+ for ( size_t iS = 0; iS < edgesByGeom.size(); ++iS )
+ {
+ vector<_LayerEdge*>& eS = edgesByGeom[iS];
+ if ( eS.empty() ) continue;
+ if ( eS[0]->_nodes[0]->GetPosition()->GetDim() != dim ) continue;
+
+ const TopoDS_Shape& S = getMeshDS()->IndexToShape( iS );
+ bool needSmooth = false;
+ switch ( S.ShapeType() )
{
- TGeomID iV = getMeshDS()->ShapeToIndex( vIt.Value() );
- vector<_LayerEdge*>& eV = edgesByGeom[ iV ];
- if ( eV.empty() ) continue;
- gp_Vec eDir = getEdgeDir( TopoDS::Edge( S ), TopoDS::Vertex( vIt.Value() ));
- double angle = eDir.Angle( eV[0]->_normal );
- double cosin = Cos( angle );
- if ( cosin > theMinSmoothCosin )
+ case TopAbs_EDGE: {
+
+ const TopoDS_Edge& E = TopoDS::Edge( S );
+ if ( SMESH_Algo::isDegenerated( E ) || !edgesOfSmooFaces.Contains( E ))
+ break;
+
+ TopoDS_Face F;
+ if ( !eS[0]->_sWOL.IsNull() && eS[0]->_sWOL.ShapeType() == TopAbs_FACE )
+ F = TopoDS::Face( eS[0]->_sWOL );
+
+ for ( TopoDS_Iterator vIt( S ); vIt.More() && !needSmooth; vIt.Next() )
{
- // compare tgtThick with the length of an end segment
- SMDS_ElemIteratorPtr eIt = eV[0]->_nodes[0]->GetInverseElementIterator(SMDSAbs_Edge);
- while ( eIt->more() )
+ TGeomID iV = getMeshDS()->ShapeToIndex( vIt.Value() );
+ vector<_LayerEdge*>& eV = edgesByGeom[ iV ];
+ if ( eV.empty() ) continue;
+ gp_Vec eDir = getEdgeDir( TopoDS::Edge( S ), TopoDS::Vertex( vIt.Value() ));
+ double angle = eDir.Angle( eV[0]->_normal );
+ double cosin = Cos( angle );
+ double cosinAbs = Abs( cosin );
+ if ( cosinAbs > theMinSmoothCosin )
{
- const SMDS_MeshElement* endSeg = eIt->next();
- if ( endSeg->getshapeId() == iS )
+ // always smooth analytic EDGEs
+ needSmooth = ! data.CurveForSmooth( E, 0, eS.size(), F, helper, &eS ).IsNull();
+
+ // compare tgtThick with the length of an end segment
+ SMDS_ElemIteratorPtr eIt = eV[0]->_nodes[0]->GetInverseElementIterator(SMDSAbs_Edge);
+ while ( eIt->more() && !needSmooth )
{
- double segLen =
- SMESH_TNodeXYZ( endSeg->GetNode(0) ).Distance( endSeg->GetNode(1 ));
- needSmooth = needSmoothing( cosin, tgtThick, segLen );
- break;
+ const SMDS_MeshElement* endSeg = eIt->next();
+ if ( endSeg->getshapeId() == iS )
+ {
+ double segLen =
+ SMESH_TNodeXYZ( endSeg->GetNode(0) ).Distance( endSeg->GetNode(1 ));
+ needSmooth = needSmoothing( cosinAbs, tgtThick, segLen );
+ }
}
}
}
+ break;
}
- break;
- }
- case TopAbs_FACE: {
+ case TopAbs_FACE: {
- for ( TopExp_Explorer eExp( S, TopAbs_EDGE ); eExp.More() && !needSmooth; eExp.Next() )
- {
- TGeomID iE = getMeshDS()->ShapeToIndex( eExp.Current() );
- vector<_LayerEdge*>& eE = edgesByGeom[ iE ];
- if ( eE.empty() ) continue;
- // TopLoc_Location loc;
- // Handle(Geom_Surface) surface = BRep_Tool::Surface( TopoDS::Face( S ), loc );
- // bool isPlane = GeomLib_IsPlanarSurface( surface ).IsPlanar();
- //if ( eE[0]->_sWOL.IsNull() )
+ for ( TopExp_Explorer eExp( S, TopAbs_EDGE ); eExp.More() && !needSmooth; eExp.Next() )
{
- double faceSize;
- for ( size_t i = 0; i < eE.size() && !needSmooth; ++i )
- if ( eE[i]->_cosin > theMinSmoothCosin )
- {
- SMDS_ElemIteratorPtr fIt = eE[i]->_nodes[0]->GetInverseElementIterator(SMDSAbs_Face);
- while ( fIt->more() && !needSmooth )
+ TGeomID iE = getMeshDS()->ShapeToIndex( eExp.Current() );
+ vector<_LayerEdge*>& eE = edgesByGeom[ iE ];
+ if ( eE.empty() ) continue;
+ // TopLoc_Location loc;
+ // Handle(Geom_Surface) surface = BRep_Tool::Surface( TopoDS::Face( S ), loc );
+ // bool isPlane = GeomLib_IsPlanarSurface( surface ).IsPlanar();
+ //if ( eE[0]->_sWOL.IsNull() )
+ {
+ double faceSize;
+ for ( size_t i = 0; i < eE.size() && !needSmooth; ++i )
+ if ( eE[i]->_cosin > theMinSmoothCosin )
{
- const SMDS_MeshElement* face = fIt->next();
- if ( getDistFromEdge( face, eE[i]->_nodes[0], faceSize ))
- needSmooth = needSmoothing( eE[i]->_cosin, tgtThick, faceSize );
+ SMDS_ElemIteratorPtr fIt = eE[i]->_nodes[0]->GetInverseElementIterator(SMDSAbs_Face);
+ while ( fIt->more() && !needSmooth )
+ {
+ const SMDS_MeshElement* face = fIt->next();
+ if ( getDistFromEdge( face, eE[i]->_nodes[0], faceSize ))
+ needSmooth = needSmoothing( eE[i]->_cosin, tgtThick, faceSize );
+ }
}
- }
+ }
+ // else
+ // {
+ // const TopoDS_Face& F1 = TopoDS::Face( S );
+ // const TopoDS_Face& F2 = TopoDS::Face( eE[0]->_sWOL );
+ // const TopoDS_Edge& E = TopoDS::Edge( eExp.Current() );
+ // for ( size_t i = 0; i < eE.size() && !needSmooth; ++i )
+ // {
+ // gp_Vec dir1 = getFaceDir( F1, E, eE[i]->_nodes[0], helper, ok );
+ // gp_Vec dir2 = getFaceDir( F2, E, eE[i]->_nodes[0], helper, ok );
+ // double angle = dir1.Angle( );
+ // double cosin = cos( angle );
+ // needSmooth = ( cosin > theMinSmoothCosin );
+ // }
+ // }
}
- // else
- // {
- // const TopoDS_Face& F1 = TopoDS::Face( S );
- // const TopoDS_Face& F2 = TopoDS::Face( eE[0]->_sWOL );
- // const TopoDS_Edge& E = TopoDS::Edge( eExp.Current() );
- // for ( size_t i = 0; i < eE.size() && !needSmooth; ++i )
- // {
- // gp_Vec dir1 = getFaceDir( F1, E, eE[i]->_nodes[0], helper, ok );
- // gp_Vec dir2 = getFaceDir( F2, E, eE[i]->_nodes[0], helper, ok );
- // double angle = dir1.Angle( );
- // double cosin = cos( angle );
- // needSmooth = ( cosin > theMinSmoothCosin );
- // }
- // }
+ if ( needSmooth )
+ for ( TopExp_Explorer eExp( S, TopAbs_EDGE ); eExp.More(); eExp.Next() )
+ edgesOfSmooFaces.Add( eExp.Current() );
+
+ break;
+ }
+ case TopAbs_VERTEX:
+ continue;
+ default:;
}
- break;
- }
- case TopAbs_VERTEX:
- continue;
- default:;
- }
- if ( needSmooth )
- {
- if ( S.ShapeType() == TopAbs_EDGE ) shapesToSmooth.push_front( iS );
- else shapesToSmooth.push_back ( iS );
- }
+ if ( needSmooth )
+ {
+ if ( S.ShapeType() == TopAbs_EDGE ) shapesToSmooth.push_front( iS );
+ else shapesToSmooth.push_back ( iS );
- } // loop on edgesByGeom
+ // preparation for smoothing
+ if ( S.ShapeType() == TopAbs_FACE )
+ {
+ data.PrepareEdgesToSmoothOnFace( & eS[0],
+ & eS[0] + eS.size(),
+ TopoDS::Face( S ),
+ /*substituteSrcNodes=*/false);
+ }
+ }
+
+ } // loop on edgesByGeom
+ } // // loop on [ FACEs, EDGEs ]
data._edges.reserve( data._n2eMap.size() );
data._endEdgeOnShape.clear();
@@ -2460,7 +2660,7 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge& edge,
SMESH_MeshEditor editor(_mesh);
const SMDS_MeshNode* node = edge._nodes[0]; // source node
- SMDS_TypeOfPosition posType = node->GetPosition()->GetTypeOfPosition();
+ const SMDS_TypeOfPosition posType = node->GetPosition()->GetTypeOfPosition();
edge._len = 0;
edge._2neibors = 0;
@@ -2474,13 +2674,41 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge& edge,
edge._normal.SetCoord(0,0,0);
int totalNbFaces = 0;
+ TopoDS_Face F;
+ std::pair< TopoDS_Face, gp_XYZ > face2Norm[20];
gp_Vec geomNorm;
bool normOK = true;
+ // get geom FACEs the node lies on
+ {
+ set faceIds;
+ if ( posType == SMDS_TOP_FACE )
+ {
+ faceIds.insert( node->getshapeId() );
+ }
+ else
+ {
+ SMDS_ElemIteratorPtr fIt = node->GetInverseElementIterator(SMDSAbs_Face);
+ while ( fIt->more() )
+ faceIds.insert( editor.FindShape(fIt->next()));
+ }
+ set::iterator id = faceIds.begin();
+ for ( ; id != faceIds.end(); ++id )
+ {
+ const TopoDS_Shape& s = getMeshDS()->IndexToShape( *id );
+ if ( s.IsNull() || s.ShapeType() != TopAbs_FACE || !subIds.count( *id ))
+ continue;
+ F = TopoDS::Face( s );
+ face2Norm[ totalNbFaces ].first = F;
+ totalNbFaces++;
+ }
+ }
+
const TGeomID shapeInd = node->getshapeId();
map< TGeomID, TopoDS_Shape >::const_iterator s2s = data._shrinkShape2Shape.find( shapeInd );
const bool onShrinkShape ( s2s != data._shrinkShape2Shape.end() );
+ // find _normal
if ( onShrinkShape ) // one of faces the node is on has no layers
{
TopoDS_Shape vertEdge = getMeshDS()->IndexToShape( s2s->first ); // vertex or edge
@@ -2504,54 +2732,35 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge& edge,
}
else // layers are on all faces of SOLID the node is on
{
- // find indices of geom faces the node lies on
- set faceIds;
- if ( posType == SMDS_TOP_FACE )
+ int nbOkNorms = 0;
+ for ( int iF = 0; iF < totalNbFaces; ++iF )
{
- faceIds.insert( node->getshapeId() );
- }
- else
- {
- SMDS_ElemIteratorPtr fIt = node->GetInverseElementIterator(SMDSAbs_Face);
- while ( fIt->more() )
- faceIds.insert( editor.FindShape(fIt->next()));
- }
-
- set::iterator id = faceIds.begin();
- TopoDS_Face F;
- std::pair< TGeomID, gp_XYZ > id2Norm[20];
- for ( ; id != faceIds.end(); ++id )
- {
- const TopoDS_Shape& s = getMeshDS()->IndexToShape( *id );
- if ( s.IsNull() || s.ShapeType() != TopAbs_FACE || !subIds.count( *id ))
- continue;
- F = TopoDS::Face( s );
+ F = TopoDS::Face( face2Norm[ iF ].first );
geomNorm = getFaceNormal( node, F, helper, normOK );
if ( !normOK ) continue;
+ nbOkNorms++;
if ( helper.GetSubShapeOri( data._solid, F ) != TopAbs_REVERSED )
geomNorm.Reverse();
- id2Norm[ totalNbFaces ].first = *id;
- id2Norm[ totalNbFaces ].second = geomNorm.XYZ();
- totalNbFaces++;
+ face2Norm[ iF ].second = geomNorm.XYZ();
edge._normal += geomNorm.XYZ();
}
- if ( totalNbFaces == 0 )
+ if ( nbOkNorms == 0 )
return error(SMESH_Comment("Can't get normal to node ") << node->GetID(), data._index);
- if ( normOK && edge._normal.Modulus() < 1e-3 && totalNbFaces > 1 )
+ if ( edge._normal.Modulus() < 1e-3 && nbOkNorms > 1 )
{
// opposite normals, re-get normals at shifted positions (IPAL 52426)
edge._normal.SetCoord( 0,0,0 );
- for ( int i = 0; i < totalNbFaces; ++i )
+ for ( int iF = 0; iF < totalNbFaces; ++iF )
{
- const TopoDS_Face& F = TopoDS::Face( getMeshDS()->IndexToShape( id2Norm[i].first ));
+ const TopoDS_Face& F = face2Norm[iF].first;
geomNorm = getFaceNormal( node, F, helper, normOK, /*shiftInside=*/true );
if ( helper.GetSubShapeOri( data._solid, F ) != TopAbs_REVERSED )
geomNorm.Reverse();
if ( normOK )
- id2Norm[ i ].second = geomNorm.XYZ();
- edge._normal += id2Norm[ i ].second;
+ face2Norm[ iF ].second = geomNorm.XYZ();
+ edge._normal += face2Norm[ iF ].second;
}
}
@@ -2561,34 +2770,46 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge& edge,
}
else
{
- edge._normal = getWeigthedNormal( node, id2Norm, totalNbFaces );
+ edge._normal = getWeigthedNormal( node, face2Norm, totalNbFaces );
}
+ }
- switch ( posType )
- {
- case SMDS_TOP_FACE:
- edge._cosin = 0; break;
-
- case SMDS_TOP_EDGE: {
- TopoDS_Edge E = TopoDS::Edge( helper.GetSubShapeByNode( node, getMeshDS()));
- gp_Vec inFaceDir = getFaceDir( F, E, node, helper, normOK );
- double angle = inFaceDir.Angle( edge._normal ); // [0,PI]
- edge._cosin = cos( angle );
- //cout << "Cosin on EDGE " << edge._cosin << " node " << node->GetID() << endl;
- break;
- }
- case SMDS_TOP_VERTEX: {
- TopoDS_Vertex V = TopoDS::Vertex( helper.GetSubShapeByNode( node, getMeshDS()));
- gp_Vec inFaceDir = getFaceDir( F, V, node, helper, normOK );
- double angle = inFaceDir.Angle( edge._normal ); // [0,PI]
- edge._cosin = cos( angle );
- //cout << "Cosin on VERTEX " << edge._cosin << " node " << node->GetID() << endl;
- break;
- }
- default:
- return error(SMESH_Comment("Invalid shape position of node ")<GetID() << endl;
+ break;
+ }
+ case SMDS_TOP_VERTEX: {
+ TopoDS_Vertex V = TopoDS::Vertex( helper.GetSubShapeByNode( node, getMeshDS()));
+ gp_Vec inFaceDir = getFaceDir( F, V, node, helper, normOK );
+ double angle = inFaceDir.Angle( edge._normal ); // [0,PI]
+ edge._cosin = Cos( angle );
+ if ( totalNbFaces > 2 || helper.IsSeamShape( node->getshapeId() ))
+ for ( int iF = totalNbFaces-2; iF >=0; --iF )
+ {
+ F = face2Norm[ iF ].first;
+ inFaceDir = getFaceDir( F, V, node, helper, normOK );
+ if ( normOK ) {
+ double angle = inFaceDir.Angle( edge._normal );
+ edge._cosin = Max( edge._cosin, Cos( angle ));
+ }
+ }
+ //cout << "Cosin on VERTEX " << edge._cosin << " node " << node->GetID() << endl;
+ break;
+ }
+ default:
+ return error(SMESH_Comment("Invalid shape position of node ")<::min() )
@@ -2630,17 +2851,7 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge& edge,
if ( posType == SMDS_TOP_FACE )
{
- getSimplices( node, edge._simplices, data._ignoreFaceIds, &data );
- double avgNormProj = 0, avgLen = 0;
- for ( size_t i = 0; i < edge._simplices.size(); ++i )
- {
- gp_XYZ vec = edge._pos.back() - SMESH_TNodeXYZ( edge._simplices[i]._nPrev );
- avgNormProj += edge._normal * vec;
- avgLen += vec.Modulus();
- }
- avgNormProj /= edge._simplices.size();
- avgLen /= edge._simplices.size();
- edge._curvature = _Curvature::New( avgNormProj, avgLen );
+ _Simplex::GetSimplices( node, edge._simplices, data._ignoreFaceIds, &data );
}
}
@@ -2733,6 +2944,15 @@ gp_XYZ _ViscousBuilder::getFaceNormal(const SMDS_MeshNode* node,
isOK = false;
Handle(Geom_Surface) surface = BRep_Tool::Surface( face );
+
+ if ( !shiftInside &&
+ helper.IsDegenShape( node->getshapeId() ) &&
+ getFaceNormalAtSingularity( uv, face, helper, normal ))
+ {
+ isOK = true;
+ return normal.XYZ();
+ }
+
int pointKind = GeomLib::NormEstim( surface, uv, 1e-5, normal );
enum { REGULAR = 0, QUASYSINGULAR, CONICAL, IMPOSSIBLE };
@@ -2781,6 +3001,55 @@ gp_XYZ _ViscousBuilder::getFaceNormal(const SMDS_MeshNode* node,
return normal.XYZ();
}
+//================================================================================
+/*!
+ * \brief Try to get normal at a singularity of a surface basing on it's nature
+ */
+//================================================================================
+
+bool _ViscousBuilder::getFaceNormalAtSingularity( const gp_XY& uv,
+ const TopoDS_Face& face,
+ SMESH_MesherHelper& helper,
+ gp_Dir& normal )
+{
+ BRepAdaptor_Surface surface( face );
+ gp_Dir axis;
+ if ( !getRovolutionAxis( surface, axis ))
+ return false;
+
+ double f,l, d, du, dv;
+ f = surface.FirstUParameter();
+ l = surface.LastUParameter();
+ d = ( uv.X() - f ) / ( l - f );
+ du = ( d < 0.5 ? +1. : -1 ) * 1e-5 * ( l - f );
+ f = surface.FirstVParameter();
+ l = surface.LastVParameter();
+ d = ( uv.Y() - f ) / ( l - f );
+ dv = ( d < 0.5 ? +1. : -1 ) * 1e-5 * ( l - f );
+
+ gp_Dir refDir;
+ gp_Pnt2d testUV = uv;
+ enum { REGULAR = 0, QUASYSINGULAR, CONICAL, IMPOSSIBLE };
+ double tol = 1e-5;
+ Handle(Geom_Surface) geomsurf = surface.Surface().Surface();
+ for ( int iLoop = 0; true ; ++iLoop )
+ {
+ testUV.SetCoord( testUV.X() + du, testUV.Y() + dv );
+ if ( GeomLib::NormEstim( geomsurf, testUV, tol, refDir ) == REGULAR )
+ break;
+ if ( iLoop > 20 )
+ return false;
+ tol /= 10.;
+ }
+
+ if ( axis * refDir < 0. )
+ axis.Reverse();
+
+ normal = axis;
+
+ return true;
+}
+
//================================================================================
/*!
* \brief Return a normal at a node weighted with angles taken by FACEs
@@ -2791,23 +3060,40 @@ gp_XYZ _ViscousBuilder::getFaceNormal(const SMDS_MeshNode* node,
*/
//================================================================================
-gp_XYZ _ViscousBuilder::getWeigthedNormal( const SMDS_MeshNode* n,
- std::pair< TGeomID, gp_XYZ > fId2Normal[],
- const int nbFaces )
+gp_XYZ _ViscousBuilder::getWeigthedNormal( const SMDS_MeshNode* n,
+ std::pair< TopoDS_Face, gp_XYZ > fId2Normal[],
+ int nbFaces )
{
gp_XYZ resNorm(0,0,0);
TopoDS_Shape V = SMESH_MesherHelper::GetSubShapeByNode( n, getMeshDS() );
if ( V.ShapeType() != TopAbs_VERTEX )
{
for ( int i = 0; i < nbFaces; ++i )
- resNorm += fId2Normal[i].second / nbFaces ;
+ resNorm += fId2Normal[i].second;
+ return resNorm;
+ }
+
+ // exclude equal normals
+ //int nbUniqNorms = nbFaces;
+ for ( int i = 0; i < nbFaces; ++i )
+ for ( int j = i+1; j < nbFaces; ++j )
+ if ( fId2Normal[i].second.IsEqual( fId2Normal[j].second, 0.1 ))
+ {
+ fId2Normal[i].second.SetCoord( 0,0,0 );
+ //--nbUniqNorms;
+ break;
+ }
+ //if ( nbUniqNorms < 3 )
+ {
+ for ( int i = 0; i < nbFaces; ++i )
+ resNorm += fId2Normal[i].second;
return resNorm;
}
double angles[30];
for ( int i = 0; i < nbFaces; ++i )
{
- const TopoDS_Face& F = TopoDS::Face( getMeshDS()->IndexToShape( fId2Normal[i].first ));
+ const TopoDS_Face& F = fId2Normal[i].first;
// look for two EDGEs shared by F and other FACEs within fId2Normal
TopoDS_Edge ee[2];
@@ -2821,7 +3107,7 @@ gp_XYZ _ViscousBuilder::getWeigthedNormal( const SMDS_MeshNode* n,
for ( int j = 0; j < nbFaces && !isSharedEdge; ++j )
{
if ( i == j ) continue;
- const TopoDS_Shape& otherF = getMeshDS()->IndexToShape( fId2Normal[j].first );
+ const TopoDS_Shape& otherF = fId2Normal[j].first;
isSharedEdge = SMESH_MesherHelper::IsSubShape( *E, otherF );
}
if ( !isSharedEdge )
@@ -3015,11 +3301,11 @@ void _LayerEdge::SetCosin( double cosin )
*/
//================================================================================
-void _ViscousBuilder::getSimplices( const SMDS_MeshNode* node,
- vector<_Simplex>& simplices,
- const set& ingnoreShapes,
- const _SolidData* dataToCheckOri,
- const bool toSort)
+void _Simplex::GetSimplices( const SMDS_MeshNode* node,
+ vector<_Simplex>& simplices,
+ const set& ingnoreShapes,
+ const _SolidData* dataToCheckOri,
+ const bool toSort)
{
simplices.clear();
SMDS_ElemIteratorPtr fIt = node->GetInverseElementIterator(SMDSAbs_Face);
@@ -3039,23 +3325,32 @@ void _ViscousBuilder::getSimplices( const SMDS_MeshNode* node,
}
if ( toSort )
+ SortSimplices( simplices );
+}
+
+//================================================================================
+/*!
+ * \brief Set neighbor simplices side by side
+ */
+//================================================================================
+
+void _Simplex::SortSimplices(vector<_Simplex>& simplices)
+{
+ vector<_Simplex> sortedSimplices( simplices.size() );
+ sortedSimplices[0] = simplices[0];
+ int nbFound = 0;
+ for ( size_t i = 1; i < simplices.size(); ++i )
{
- vector<_Simplex> sortedSimplices( simplices.size() );
- sortedSimplices[0] = simplices[0];
- int nbFound = 0;
- for ( size_t i = 1; i < simplices.size(); ++i )
- {
- for ( size_t j = 1; j < simplices.size(); ++j )
- if ( sortedSimplices[i-1]._nNext == simplices[j]._nPrev )
- {
- sortedSimplices[i] = simplices[j];
- nbFound++;
- break;
- }
- }
- if ( nbFound == simplices.size() - 1 )
- simplices.swap( sortedSimplices );
+ for ( size_t j = 1; j < simplices.size(); ++j )
+ if ( sortedSimplices[i-1]._nNext == simplices[j]._nPrev )
+ {
+ sortedSimplices[i] = simplices[j];
+ nbFound++;
+ break;
+ }
}
+ if ( nbFound == simplices.size() - 1 )
+ simplices.swap( sortedSimplices );
}
//================================================================================
@@ -3093,11 +3388,13 @@ void _ViscousBuilder::makeGroupOfLE()
dumpFunctionEnd();
dumpFunction( SMESH_Comment("makeTmpFaces_") << i );
+ dumpCmd( "faceId1 = mesh.NbElements()" );
TopExp_Explorer fExp( _sdVec[i]._solid, TopAbs_FACE );
for ( ; fExp.More(); fExp.Next() )
{
if (const SMESHDS_SubMesh* sm = _sdVec[i]._proxyMesh->GetProxySubMesh( fExp.Current()))
{
+ if ( sm->NbElements() == 0 ) continue;
SMDS_ElemIteratorPtr fIt = sm->GetElements();
while ( fIt->more())
{
@@ -3109,6 +3406,10 @@ void _ViscousBuilder::makeGroupOfLE()
}
}
}
+ dumpCmd( "faceId2 = mesh.NbElements()" );
+ dumpCmd( SMESH_Comment( "mesh.MakeGroup( 'tmpFaces_" ) << i << "',"
+ << "SMESH.FACE, SMESH.FT_RangeOfIds,'=',"
+ << "'%s-%s' % (faceId1+1, faceId2))");
dumpFunctionEnd();
}
#endif
@@ -3163,6 +3464,8 @@ bool _ViscousBuilder::inflate(_SolidData& data)
debugMsg( "-- geomSize = " << data._geomSize << ", stepSize = " << data._stepSize );
+ const double safeFactor = ( 2*data._maxThickness < data._geomSize ) ? 1 : theThickToIntersection;
+
double avgThick = 0, curThick = 0, distToIntersection = Precision::Infinite();
int nbSteps = 0, nbRepeats = 0;
int iBeg, iEnd, iS;
@@ -3196,6 +3499,10 @@ bool _ViscousBuilder::inflate(_SolidData& data)
{
if ( nbSteps > 0 )
{
+#ifdef __NOT_INVALIDATE_BAD_SMOOTH
+ debugMsg("NOT INVALIDATED STEP!");
+ return error("Smoothing failed", data._index);
+#endif
dumpFunction(SMESH_Comment("invalidate")<GetSubMeshContaining( data._index ))
+ {
+ if ( !data._proxyMesh->_warning || data._proxyMesh->_warning->IsOK() )
{
- SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
- if ( !smError || smError->IsOK() )
- smError.reset
- ( new SMESH_ComputeError (COMPERR_WARNING,
- SMESH_Comment("Thickness ") << tgtThick <<
- " of viscous layers not reached,"
- " average reached thickness is " << avgThick*tgtThick));
+ data._proxyMesh->_warning.reset
+ ( new SMESH_ComputeError (COMPERR_WARNING,
+ SMESH_Comment("Thickness ") << tgtThick <<
+ " of viscous layers not reached,"
+ " average reached thickness is " << avgThick*tgtThick));
}
-
+ }
// Restore position of src nodes moved by infaltion on _noShrinkShapes
dumpFunction(SMESH_Comment("restoNoShrink_So")< badSmooEdges;
SMESH_MesherHelper helper(*_mesh);
Handle(Geom_Surface) surface;
@@ -3293,16 +3600,18 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
iBeg = iEnd;
iEnd = data._endEdgeOnShape[ iS ];
- // bool toSmooth = false;
- // for ( int i = iBeg; i < iEnd; ++i )
- // toSmooth = data._edges[ iBeg ]->NbSteps() >= nbSteps+1;
- // if ( !toSmooth )
- // {
- // if ( iS+1 == data._nbShapesToSmooth )
- // data._nbShapesToSmooth--;
- // continue; // target length reached some steps before
- // }
+ // need to smooth this shape?
+ bool toSmooth = ( data._hyps.front() == data._hyps.back() );
+ for ( int i = iBeg; i < iEnd && !toSmooth; ++i )
+ toSmooth = ( data._edges[ iBeg ]->NbSteps() >= nbSteps+1 );
+ if ( !toSmooth )
+ {
+ if ( iS+1 == data._nbShapesToSmooth )
+ data._nbShapesToSmooth--;
+ continue; // target length reached some steps before
+ }
+ // prepare data
if ( !data._edges[ iBeg ]->_sWOL.IsNull() &&
data._edges[ iBeg ]->_sWOL.ShapeType() == TopAbs_FACE )
{
@@ -3316,7 +3625,9 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
{
F.Nullify(); surface.Nullify();
}
- TGeomID sInd = data._edges[ iBeg ]->_nodes[0]->getshapeId();
+ const TGeomID sInd = data._edges[ iBeg ]->_nodes[0]->getshapeId();
+
+ // perform smoothing
if ( data._edges[ iBeg ]->IsOnEdge() )
{
@@ -3342,37 +3653,65 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
else
{
// smooth on FACE's
- int step = 0, stepLimit = 5, badNb = 0; moved = true;
- while (( ++step <= stepLimit && moved ) || improved )
+
+ const bool isConcaveFace = data._concaveFaces.count( sInd );
+
+ int step = 0, stepLimit = 5, badNb = 0;
+ while (( ++step <= stepLimit ) || improved )
{
dumpFunction(SMESH_Comment("smooth")<